Decompiled source of DvergerAutomation v0.5.0

plugins/DvergerAutomation.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DvergerAutomation.Common;
using EpicLootAPI;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using SimpleJson;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("DvergerAutomation")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DvergerAutomation")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.5.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.5.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace DvergerAutomation
{
	internal class Logger
	{
		public static LogLevel Level = (LogLevel)16;

		public static void EnableDebugLogging(object sender, EventArgs e)
		{
			CheckEnableDebugLogging();
		}

		public static void CheckEnableDebugLogging()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (ValConfig.EnableDebugMode.Value)
			{
				Level = (LogLevel)32;
			}
			else
			{
				Level = (LogLevel)16;
			}
		}

		public static void SetDebugLogging(bool state)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (state)
			{
				Level = (LogLevel)32;
			}
			else
			{
				Level = (LogLevel)16;
			}
		}

		public static void LogDebug(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)Level >= 32)
			{
				DvergerAutomation.Log.LogInfo((object)("[DEBUG]" + message));
			}
		}

		public static void LogInfo(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)Level >= 16)
			{
				DvergerAutomation.Log.LogInfo((object)message);
			}
		}

		public static void LogWarning(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)Level >= 4)
			{
				DvergerAutomation.Log.LogWarning((object)message);
			}
		}

		public static void LogError(string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)Level >= 2)
			{
				DvergerAutomation.Log.LogError((object)message);
			}
		}
	}
	internal class ValConfig
	{
		public static ConfigFile cfg;

		public static ConfigEntry<bool> EnableDebugMode;

		public static ConfigEntry<bool> AutomationEnabled;

		public static ConfigEntry<float> ScanInterval;

		public static ConfigEntry<float> ScanRadius;

		public static ConfigEntry<float> RangePerCore;

		public static ConfigEntry<bool> RequireCores;

		public const string cfgFolder = "DvergerAutomation";

		public ValConfig(ConfigFile cf)
		{
			cfg = cf;
			cfg.SaveOnConfigSet = true;
			CreateConfigValues(cf);
			Logger.SetDebugLogging(EnableDebugMode.Value);
		}

		private void CreateConfigValues(ConfigFile Config)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdvanced = true
			} }));
			EnableDebugMode.SettingChanged += Logger.EnableDebugLogging;
			Logger.CheckEnableDebugLogging();
			AutomationEnabled = BindServerConfig("Dverger AutoSorter", "Enabled", value: true, "Enables the Dverger AutoSorter: nearby accessible chests act as a shared material pool when crafting at linked stations or building with the Hammer near the sorter.");
			ScanInterval = BindServerConfig("Dverger AutoSorter", "Scan Interval", 30f, "Seconds between scans for nearby crafting stations and storage chests.", advanced: false, 5f, 300f);
			ScanRadius = BindServerConfig("Dverger AutoSorter", "Scan Radius", 20f, "Radius (meters) around the AutoSorter in which crafting stations and chests are linked.", advanced: false, 1f, 64f);
			RangePerCore = BindServerConfig("Dverger AutoSorter", "Range Per Core", 25f, "Extra link radius (meters) added per inserted Surtling Core.", advanced: false, 0f, 100f);
			RequireCores = BindServerConfig("Dverger AutoSorter", "Require Cores", value: true, "When enabled, the AutoSorter only links stations/chests after at least one Surtling Core is inserted.");
		}

		public static ConfigEntry<List<string>> BindServerConfig(string category, string key, List<string> value, string description, bool advanced = false)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			return cfg.Bind<List<string>>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public static ConfigEntry<float[]> BindServerConfig(string category, string key, float[] value, string description, bool advanced = false, float valMin = 0f, float valMax = 150f)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			return cfg.Bind<float[]>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public static ConfigEntry<bool> BindServerConfig(string category, string key, bool value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			return cfg.Bind<bool>(category, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public static ConfigEntry<int> BindServerConfig(string category, string key, int value, string description, bool advanced = false, int valMin = 0, int valMax = 150)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			return cfg.Bind<int>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public static ConfigEntry<float> BindServerConfig(string category, string key, float value, string description, bool advanced = false, float valMin = 0f, float valMax = 150f)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			return cfg.Bind<float>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valMin, valMax), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}

		public static ConfigEntry<string> BindServerConfig(string category, string key, string value, string description, AcceptableValueList<string> acceptableValues = null, bool advanced = false)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			return cfg.Bind<string>(category, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				IsAdvanced = advanced
			} }));
		}
	}
	[BepInPlugin("MidngightsFX.DvergerAutomation", "DvergerAutomation", "0.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class DvergerAutomation : BaseUnityPlugin
	{
		public const string PluginGUID = "MidngightsFX.DvergerAutomation";

		public const string PluginName = "DvergerAutomation";

		public const string PluginVersion = "0.5.0";

		internal static ManualLogSource Log;

		internal ValConfig cfg;

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		public static AssetBundle EmbeddedResourceBundle;

		public static Harmony HarmonyInstance { get; private set; }

		public void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			cfg = new ValConfig(((BaseUnityPlugin)this).Config);
			EmbeddedResourceBundle = AssetUtils.LoadAssetBundleFromResources("DvergerAutomation.embedded.automation", typeof(DvergerAutomation).Assembly);
			HarmonyInstance = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "MidngightsFX.DvergerAutomation");
			LocalizationLoader.AddLocalizations();
			AddPieces();
			EpicLootIntegration.Register();
		}

		public void OnDestroy()
		{
			EpicLootIntegration.Unregister();
		}

		public void AddPieces()
		{
			JotunnPiece.RegisterJotunnPiece(new JotunnPiece.JotunnBuildPiece
			{
				Name = "Dverger AutoSorter",
				Prefab = "DA_Autosorter",
				Sprite = "DA_Autosorter",
				Workbench = "forge",
				Category = "Crafting",
				PieceCost = new List<JotunnPiece.PieceCost>
				{
					new JotunnPiece.PieceCost
					{
						prefab = "Stone",
						amount = 20,
						refundable = true
					},
					new JotunnPiece.PieceCost
					{
						prefab = "Bronze",
						amount = 8,
						refundable = true
					},
					new JotunnPiece.PieceCost
					{
						prefab = "GreyDwarfEyes",
						amount = 20,
						refundable = true
					},
					new JotunnPiece.PieceCost
					{
						prefab = "Ectoplasm",
						amount = 4,
						refundable = true
					}
				}
			});
		}
	}
	public class AutomationHub : MonoBehaviour
	{
		public Switch CoreSwitch1;

		public Switch CoreSwitch2;

		public Switch CoreSwitch3;

		public Switch CoreSwitch4;

		public GameObject Core1Visual;

		public GameObject Core2Visual;

		public GameObject Core3Visual;

		public GameObject Core4Visual;

		public GameObject EnabledVisuals;

		private const string CoreMaskKey = "DA_cores";

		private const string SurtlingCorePrefab = "SurtlingCore";

		private ZNetView nview;

		internal readonly HashSet<CraftingStation> LinkedStations = new HashSet<CraftingStation>();

		internal readonly List<Container> LinkedContainers = new List<Container>();

		private Coroutine scanLoop;

		private static int pieceMask;

		internal int CoreCount
		{
			get
			{
				int coreMask = GetCoreMask();
				int num = 0;
				for (int i = 0; i < 4; i++)
				{
					if ((coreMask & (1 << i)) != 0)
					{
						num++;
					}
				}
				return num;
			}
		}

		internal bool IsActive => GetCoreMask() != 0;

		internal float EffectiveRadius => ValConfig.ScanRadius.Value + (float)CoreCount * ValConfig.RangePerCore.Value;

		private void Awake()
		{
			nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)nview != (Object)null && nview.GetZDO() != null)
			{
				nview.Register("DA_RefreshCores", (Action<long>)RPC_RefreshCores);
				WearNTear component = ((Component)this).GetComponent<WearNTear>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyedDropCores));
				}
			}
			WireSwitch(CoreSwitch1, 0);
			WireSwitch(CoreSwitch2, 1);
			WireSwitch(CoreSwitch3, 2);
			WireSwitch(CoreSwitch4, 3);
			((MonoBehaviour)this).InvokeRepeating("UpdateVisuals", 1f, 4f);
		}

		private void OnEnable()
		{
			ContainerNetwork.Register(this);
			scanLoop = ((MonoBehaviour)this).StartCoroutine(ScanLoopRoutine());
		}

		private void OnDisable()
		{
			if (scanLoop != null)
			{
				((MonoBehaviour)this).StopCoroutine(scanLoop);
				scanLoop = null;
			}
			LinkedStations.Clear();
			LinkedContainers.Clear();
			ContainerNetwork.Unregister(this);
		}

		private IEnumerator ScanLoopRoutine()
		{
			yield return (object)new WaitForSeconds(2f);
			while (true)
			{
				if (ValConfig.AutomationEnabled.Value && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					Scan();
				}
				yield return (object)new WaitForSeconds(Mathf.Max(1f, ValConfig.ScanInterval.Value));
			}
		}

		private void Scan()
		{
			//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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			LinkedStations.Clear();
			LinkedContainers.Clear();
			if (ValConfig.RequireCores.Value && CoreCount == 0)
			{
				ContainerNetwork.RebuildStationCache();
				return;
			}
			float effectiveRadius = EffectiveRadius;
			Vector3 position = ((Component)this).transform.position;
			long playerId = (((Object)(object)Game.instance != (Object)null && Game.instance.GetPlayerProfile() != null) ? Game.instance.GetPlayerProfile().GetPlayerID() : 0);
			foreach (CraftingStation allStation in CraftingStation.m_allStations)
			{
				if (!((Object)(object)allStation == (Object)null) && Vector3.Distance(position, ((Component)allStation).transform.position) <= effectiveRadius)
				{
					LinkedStations.Add(allStation);
				}
			}
			if (pieceMask == 0)
			{
				pieceMask = LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" });
			}
			Collider[] array = Physics.OverlapSphere(position, effectiveRadius, pieceMask);
			HashSet<Container> hashSet = new HashSet<Container>();
			Collider[] array2 = array;
			foreach (Collider val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Container componentInParent = ((Component)val).GetComponentInParent<Container>();
					if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent) && IsAccessible(componentInParent, playerId))
					{
						LinkedContainers.Add(componentInParent);
					}
				}
			}
			if (ValConfig.EnableDebugMode.Value)
			{
				Logger.LogInfo($"[Autosorter] scan linked {LinkedStations.Count} stations, {LinkedContainers.Count} chests within {effectiveRadius}m.");
			}
			ContainerNetwork.RebuildStationCache();
		}

		private static bool IsAccessible(Container container, long playerId)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (container.m_inventory == null)
			{
				return false;
			}
			if (!container.CheckAccess(playerId))
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
			{
				return false;
			}
			return true;
		}

		private int GetCoreMask()
		{
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return 0;
			}
			return nview.GetZDO().GetInt("DA_cores", 0);
		}

		private void SetCoreMask(int mask)
		{
			if (!((Object)(object)nview == (Object)null) && nview.IsValid())
			{
				if (!nview.IsOwner())
				{
					nview.ClaimOwnership();
				}
				nview.GetZDO().Set("DA_cores", mask);
				nview.InvokeRPC(ZNetView.Everybody, "DA_RefreshCores", Array.Empty<object>());
				UpdateVisuals();
				if (ValConfig.AutomationEnabled.Value && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					Scan();
				}
			}
		}

		private void RPC_RefreshCores(long sender)
		{
			UpdateVisuals();
		}

		private void WireSwitch(Switch sw, int slot)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			if (!((Object)(object)sw == (Object)null))
			{
				sw.m_onUse = new Callback(OnCoreSwitchUsed);
				sw.m_onHover = (TooltipCallback)(() => GetSwitchHover(slot));
				sw.m_name = "$DA_autosorter_name";
			}
		}

		private int SlotForSwitch(Switch caller)
		{
			if ((Object)(object)caller == (Object)(object)CoreSwitch1)
			{
				return 0;
			}
			if ((Object)(object)caller == (Object)(object)CoreSwitch2)
			{
				return 1;
			}
			if ((Object)(object)caller == (Object)(object)CoreSwitch3)
			{
				return 2;
			}
			if ((Object)(object)caller == (Object)(object)CoreSwitch4)
			{
				return 3;
			}
			return -1;
		}

		private bool OnCoreSwitchUsed(Switch caller, Humanoid user, ItemData item)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			int num = SlotForSwitch(caller);
			if (num < 0)
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val == null)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return false;
			}
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			GameObject val2 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("SurtlingCore") : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			string name = val2.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
			int coreMask = GetCoreMask();
			if ((coreMask & (1 << num)) != 0)
			{
				if (!((Humanoid)val).GetInventory().AddItem(val2, 1))
				{
					((Character)user).Message((MessageType)2, "$inventory_full", 0, (Sprite)null, false);
					return false;
				}
				SetCoreMask(coreMask & ~(1 << num));
				((Character)user).Message((MessageType)2, "$DA_Remove_Core", 0, (Sprite)null, false);
			}
			else
			{
				if (((Humanoid)val).GetInventory().CountItems(name, -1, true) <= 0)
				{
					((Character)user).Message((MessageType)2, "$DA_Need_Core", 0, (Sprite)null, false);
					return false;
				}
				((Humanoid)val).GetInventory().RemoveItem(name, 1, -1, true);
				SetCoreMask(coreMask | (1 << num));
				((Character)user).Message((MessageType)2, "$DA_Add_Core", 0, (Sprite)null, false);
			}
			return true;
		}

		private string GetSwitchHover(int slot)
		{
			string text = (((GetCoreMask() & (1 << slot)) != 0) ? "$DA_Remove_Core" : "$DA_Add_Core");
			return Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] " + text);
		}

		private void UpdateVisuals()
		{
			if (!((Object)(object)nview == (Object)null) && nview.IsValid())
			{
				int coreMask = GetCoreMask();
				SetActiveSafe(Core1Visual, (coreMask & 1) != 0);
				SetActiveSafe(Core2Visual, (coreMask & 2) != 0);
				SetActiveSafe(Core3Visual, (coreMask & 4) != 0);
				SetActiveSafe(Core4Visual, (coreMask & 8) != 0);
				SetActiveSafe(EnabledVisuals, coreMask != 0);
			}
		}

		private static void SetActiveSafe(GameObject go, bool active)
		{
			if ((Object)(object)go != (Object)null && go.activeSelf != active)
			{
				go.SetActive(active);
			}
		}

		private void OnDestroyedDropCores()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
			{
				return;
			}
			int coreCount = CoreCount;
			if (coreCount <= 0)
			{
				return;
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("SurtlingCore") : null);
			if (!((Object)(object)val == (Object)null))
			{
				for (int i = 0; i < coreCount; i++)
				{
					Vector3 val2 = ((Component)this).transform.position + Vector3.up * 0.5f + Random.insideUnitSphere * 0.3f;
					Object.Instantiate<GameObject>(val, val2, Random.rotation);
				}
			}
		}
	}
	internal static class ContainerNetwork
	{
		internal static readonly List<AutomationHub> Hubs = new List<AutomationHub>();

		private static readonly Dictionary<CraftingStation, List<Container>> StationToContainers = new Dictionary<CraftingStation, List<Container>>();

		private static readonly HashSet<Container> RebuildSeen = new HashSet<Container>();

		private static readonly List<Container> Empty = new List<Container>();

		private static readonly Dictionary<string, int> AggCounts = new Dictionary<string, int>();

		private static int aggFrame = -1;

		private static List<Container> aggPool;

		private static readonly List<Container> NearPointResult = new List<Container>();

		private static readonly HashSet<Container> NearPointSeen = new HashSet<Container>();

		private static int nearPointFrame = -1;

		private static Vector3 nearPointPos;

		internal static void Register(AutomationHub hub)
		{
			if (!Hubs.Contains(hub))
			{
				Hubs.Add(hub);
			}
			RebuildStationCache();
		}

		internal static void Unregister(AutomationHub hub)
		{
			Hubs.Remove(hub);
			RebuildStationCache();
		}

		internal static void RebuildStationCache()
		{
			StationToContainers.Clear();
			foreach (AutomationHub hub in Hubs)
			{
				if ((Object)(object)hub == (Object)null)
				{
					continue;
				}
				foreach (CraftingStation linkedStation in hub.LinkedStations)
				{
					if ((Object)(object)linkedStation == (Object)null)
					{
						continue;
					}
					if (!StationToContainers.TryGetValue(linkedStation, out List<Container> value))
					{
						value = new List<Container>();
						StationToContainers[linkedStation] = value;
					}
					RebuildSeen.Clear();
					RebuildSeen.UnionWith(value);
					foreach (Container linkedContainer in hub.LinkedContainers)
					{
						if ((Object)(object)linkedContainer != (Object)null && RebuildSeen.Add(linkedContainer))
						{
							value.Add(linkedContainer);
						}
					}
				}
			}
			aggFrame = -1;
			aggPool = null;
			nearPointFrame = -1;
		}

		internal static List<Container> GetContainersForStation(CraftingStation station)
		{
			if ((Object)(object)station != (Object)null && StationToContainers.TryGetValue(station, out List<Container> value))
			{
				return value;
			}
			return Empty;
		}

		internal static List<Container> GetContainersNearPoint(Vector3 point)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (nearPointFrame == Time.frameCount && nearPointPos == point)
			{
				return NearPointResult;
			}
			NearPointResult.Clear();
			NearPointSeen.Clear();
			foreach (AutomationHub hub in Hubs)
			{
				if ((Object)(object)hub == (Object)null || (ValConfig.RequireCores.Value && hub.CoreCount == 0) || Vector3.Distance(((Component)hub).transform.position, point) > hub.EffectiveRadius)
				{
					continue;
				}
				foreach (Container linkedContainer in hub.LinkedContainers)
				{
					if ((Object)(object)linkedContainer != (Object)null && NearPointSeen.Add(linkedContainer))
					{
						NearPointResult.Add(linkedContainer);
					}
				}
			}
			nearPointFrame = Time.frameCount;
			nearPointPos = point;
			return NearPointResult;
		}

		internal static int CountInPool(List<Container> pool, string name)
		{
			if (pool == null || pool.Count == 0)
			{
				return 0;
			}
			if (aggFrame != Time.frameCount || aggPool != pool)
			{
				BuildAggregate(pool);
			}
			if (!AggCounts.TryGetValue(name, out var value))
			{
				return 0;
			}
			return value;
		}

		private static void BuildAggregate(List<Container> pool)
		{
			bool value = ValConfig.EnableDebugMode.Value;
			double num = (value ? Time.realtimeSinceStartupAsDouble : 0.0);
			AggCounts.Clear();
			int worldLevel = Game.m_worldLevel;
			foreach (Container item in pool)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Inventory inventory = item.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem.m_worldLevel >= worldLevel && !EpicLootIntegration.IsProtectedItem(allItem))
					{
						string name = allItem.m_shared.m_name;
						AggCounts.TryGetValue(name, out var value2);
						AggCounts[name] = value2 + allItem.m_stack;
					}
				}
			}
			aggFrame = Time.frameCount;
			aggPool = pool;
			if (value)
			{
				double num2 = (Time.realtimeSinceStartupAsDouble - num) * 1000.0;
				Logger.LogInfo($"[Autosorter] aggregated {pool.Count} chests, {AggCounts.Count} item types in {num2:F2}ms.");
			}
		}
	}
	internal static class CraftFromStoragePatches
	{
		internal static int InCraftRequirements;

		internal static int InBuildRequirements;

		internal static int SumContainers(List<Container> pool, string name, int quality)
		{
			int num = 0;
			foreach (Container item in pool)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Inventory inventory = item.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (Matches(allItem, name, quality))
					{
						num += allItem.m_stack;
					}
				}
			}
			return num;
		}

		private static bool Matches(ItemData item, string name, int quality)
		{
			if (item == null || item.m_shared == null)
			{
				return false;
			}
			if (item.m_shared.m_name != name)
			{
				return false;
			}
			if (quality >= 0 && item.m_quality != quality)
			{
				return false;
			}
			if (item.m_worldLevel < Game.m_worldLevel)
			{
				return false;
			}
			return !EpicLootIntegration.IsProtectedItem(item);
		}

		internal static void ClaimOwnership(Container container)
		{
			if (!((Object)(object)container == (Object)null) && (Object)(object)container.m_nview != (Object)null && container.m_nview.IsValid() && !container.m_nview.IsOwner())
			{
				container.m_nview.ClaimOwnership();
			}
		}

		internal static int RemoveFromContainers(List<Container> pool, string name, int amount, int itemQuality)
		{
			int num = 0;
			foreach (Container item in pool)
			{
				if (amount <= 0)
				{
					break;
				}
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Inventory inventory = item.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				bool flag = false;
				List<ItemData> allItems = inventory.GetAllItems();
				int num2 = allItems.Count - 1;
				while (num2 >= 0 && amount > 0)
				{
					ItemData val = allItems[num2];
					if (Matches(val, name, itemQuality))
					{
						if (!flag)
						{
							ClaimOwnership(item);
							flag = true;
						}
						int num3 = Mathf.Min(val.m_stack, amount);
						inventory.RemoveItem(val, num3);
						amount -= num3;
						num += num3;
					}
					num2--;
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(Player), "HaveRequirementItems", new Type[]
	{
		typeof(Recipe),
		typeof(bool),
		typeof(int),
		typeof(int)
	})]
	internal static class Player_HaveRequirementItems_Patch
	{
		private static void Postfix(Player __instance, ref bool __result, Recipe piece, bool discover, int qualityLevel, int amount)
		{
			if (__result || discover || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation == (Object)null)
			{
				return;
			}
			List<Container> containersForStation = ContainerNetwork.GetContainersForStation(currentCraftingStation);
			if (containersForStation.Count == 0)
			{
				return;
			}
			bool requireOnlyOneIngredient = piece.m_requireOnlyOneIngredient;
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if ((Object)(object)val.m_resItem == (Object)null)
				{
					continue;
				}
				string name = val.m_resItem.m_itemData.m_shared.m_name;
				int num = val.GetAmount(qualityLevel) * amount;
				int num2 = 0;
				for (int j = 1; j < val.m_resItem.m_itemData.m_shared.m_maxQuality + 1; j++)
				{
					int num3 = ((Humanoid)__instance).m_inventory.CountItems(name, j, true);
					if (num3 > num2)
					{
						num2 = num3;
					}
				}
				int num4 = num2 + ContainerNetwork.CountInPool(containersForStation, name);
				if (requireOnlyOneIngredient)
				{
					if (num4 >= num)
					{
						__result = true;
						return;
					}
				}
				else if (num4 < num)
				{
					return;
				}
			}
			__result = !requireOnlyOneIngredient;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")]
	internal static class InventoryGui_SetupRequirementList_Patch
	{
		private static void Prefix()
		{
			CraftFromStoragePatches.InCraftRequirements++;
		}

		[HarmonyPriority(0)]
		private static void Postfix()
		{
			CraftFromStoragePatches.InCraftRequirements--;
		}
	}
	[HarmonyPatch(typeof(Hud), "SetupPieceInfo")]
	internal static class Hud_SetupPieceInfo_Patch
	{
		private static void Prefix()
		{
			CraftFromStoragePatches.InBuildRequirements++;
		}

		[HarmonyPriority(0)]
		private static void Postfix()
		{
			CraftFromStoragePatches.InBuildRequirements--;
		}
	}
	[HarmonyPatch(typeof(Inventory), "CountItems")]
	internal static class Inventory_CountItems_Patch
	{
		private static void Postfix(Inventory __instance, ref int __result, string name, int quality)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name))
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).m_inventory)
			{
				return;
			}
			List<Container> list;
			if (CraftFromStoragePatches.InCraftRequirements > 0)
			{
				CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
				if ((Object)(object)currentCraftingStation == (Object)null)
				{
					return;
				}
				list = ContainerNetwork.GetContainersForStation(currentCraftingStation);
			}
			else
			{
				if (CraftFromStoragePatches.InBuildRequirements <= 0)
				{
					return;
				}
				list = ContainerNetwork.GetContainersNearPoint(((Component)localPlayer).transform.position);
			}
			if (list.Count != 0)
			{
				__result += ((quality < 0) ? ContainerNetwork.CountInPool(list, name) : CraftFromStoragePatches.SumContainers(list, name, quality));
			}
		}
	}
	[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
	{
		typeof(Piece),
		typeof(RequirementMode)
	})]
	internal static class Player_HaveRequirements_Piece_Patch
	{
		private static void Postfix(Player __instance, ref bool __result, Piece piece, RequirementMode mode)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if (__result || (int)mode != 0 || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Object)(object)piece.m_craftingStation != (Object)null && (Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position) == (Object)null && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)27)) || (piece.m_dlc != null && piece.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(piece.m_dlc)))
			{
				return;
			}
			List<Container> containersNearPoint = ContainerNetwork.GetContainersNearPoint(((Component)__instance).transform.position);
			if (containersNearPoint.Count == 0)
			{
				return;
			}
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val.m_resItem == (Object)null) && val.m_amount > 0)
				{
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					if (((Humanoid)__instance).m_inventory.CountItems(name, -1, true) + ContainerNetwork.CountInPool(containersNearPoint, name) < val.m_amount)
					{
						return;
					}
				}
			}
			__result = true;
		}
	}
	[HarmonyPatch(typeof(Player), "ConsumeResources")]
	internal static class Player_ConsumeResources_Patch
	{
		private static void Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
			List<Container> list = (((Object)(object)currentCraftingStation != (Object)null) ? ContainerNetwork.GetContainersForStation(currentCraftingStation) : ContainerNetwork.GetContainersNearPoint(((Component)__instance).transform.position));
			if (list.Count == 0)
			{
				return;
			}
			foreach (Requirement val in requirements)
			{
				if ((Object)(object)val.m_resItem == (Object)null)
				{
					continue;
				}
				int num = val.GetAmount(qualityLevel) * multiplier;
				if (num > 0)
				{
					string name = val.m_resItem.m_itemData.m_shared.m_name;
					int num2 = ((Humanoid)__instance).m_inventory.CountItems(name, itemQuality, true);
					int num3 = num - num2;
					if (num3 > 0)
					{
						CraftFromStoragePatches.RemoveFromContainers(list, name, num3, itemQuality);
					}
				}
			}
		}
	}
	internal static class EpicLootIntegration
	{
		internal const string EpicLootGUID = "randyknapp.mods.epicloot";

		private static readonly List<Container> Empty = new List<Container>();

		private static readonly List<ItemData> ItemsResult = new List<ItemData>();

		private static int itemsFrame = -1;

		internal static bool Active { get; private set; }

		internal static void Register()
		{
			if (Active)
			{
				return;
			}
			if (!EpicLoot.IsLoaded())
			{
				Logger.LogDebug("[Autosorter] Epic Loot not present; skipping integration.");
				return;
			}
			Active = EpicLoot.RegisterInventoryProvider("MidngightsFX.DvergerAutomation", GetItems, CountItem, RemoveItem, RemoveExactItem);
			if (Active)
			{
				Logger.LogInfo("[Autosorter] Registered inventory provider with Epic Loot " + EpicLoot.GetPluginVersion() + ".");
			}
			else
			{
				Logger.LogWarning("[Autosorter] Epic Loot is present but refused the inventory provider registration.");
			}
		}

		internal static void Unregister()
		{
			if (Active)
			{
				EpicLoot.UnregisterInventoryProvider("MidngightsFX.DvergerAutomation");
				Active = false;
			}
		}

		internal static bool IsProtectedItem(ItemData item)
		{
			if (!Active || item == null || item.m_shared == null)
			{
				return false;
			}
			if (item.m_shared.m_maxStackSize > 1)
			{
				return false;
			}
			return item.IsMagicItem();
		}

		private static List<Container> Pool()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return Empty;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if (!((Object)(object)currentCraftingStation != (Object)null))
			{
				return ContainerNetwork.GetContainersNearPoint(((Component)localPlayer).transform.position);
			}
			return ContainerNetwork.GetContainersForStation(currentCraftingStation);
		}

		private static List<ItemData> GetItems()
		{
			if (itemsFrame == Time.frameCount)
			{
				return ItemsResult;
			}
			ItemsResult.Clear();
			foreach (Container item in Pool())
			{
				if (!((Object)(object)item == (Object)null))
				{
					Inventory inventory = item.GetInventory();
					if (inventory != null)
					{
						ItemsResult.AddRange(inventory.GetAllItems());
					}
				}
			}
			itemsFrame = Time.frameCount;
			return ItemsResult;
		}

		private static int CountItem(string name)
		{
			if (!string.IsNullOrEmpty(name))
			{
				return ContainerNetwork.CountInPool(Pool(), name);
			}
			return 0;
		}

		private static int RemoveItem(string name, int amount)
		{
			if (string.IsNullOrEmpty(name) || amount <= 0)
			{
				return 0;
			}
			return CraftFromStoragePatches.RemoveFromContainers(Pool(), name, amount, -1);
		}

		private static int RemoveExactItem(ItemData item, int amount)
		{
			if (item == null || amount <= 0)
			{
				return 0;
			}
			foreach (Container item2 in Pool())
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					Inventory inventory = item2.GetInventory();
					if (inventory != null && inventory.ContainsItem(item))
					{
						CraftFromStoragePatches.ClaimOwnership(item2);
						int num = Mathf.Min(item.m_stack, amount);
						inventory.RemoveItem(item, num);
						return num;
					}
				}
			}
			return 0;
		}
	}
}
namespace DvergerAutomation.Common
{
	public static class JotunnPiece
	{
		public class LoadedGameObjects
		{
			public GameObject Prefab { get; set; }

			public Sprite Sprite { get; set; }

			public GameObject ScenePrefab { get; set; }
		}

		public class PieceCost
		{
			public string prefab { get; set; }

			public int amount { get; set; }

			public bool refundable { get; set; } = true;
		}

		public class PieceConfigs
		{
			public ConfigEntry<bool> Enabled { get; set; }

			public ConfigEntry<bool> RequiresWorkbench { get; set; }

			public ConfigEntry<string> Workbench { get; set; }

			public ConfigEntry<string> PieceCategory { get; set; }

			public ConfigEntry<string> PieceCost { get; set; }

			public List<PieceCost> UpdatedCost { get; set; } = new List<PieceCost>();
		}

		public class JotunnBuildPiece
		{
			public string Name { get; set; }

			public bool Enabled { get; set; } = true;

			public string Prefab { get; set; }

			public string Sprite { get; set; }

			public string Category { get; set; } = "Misc";

			public string Workbench { get; set; } = "piece_workbench";

			public List<PieceCost> PieceCost { get; set; } = new List<PieceCost>();

			public LoadedGameObjects Objs { get; set; }

			public PieceConfigs Cfgs { get; set; }
		}

		private static List<JotunnBuildPiece> BuildPieces = new List<JotunnBuildPiece>();

		private static bool PiecesReady = false;

		public static void RegisterJotunnPiece(JotunnBuildPiece jbuildpiece)
		{
			LoadedGameObjects loadedGameObjects = new LoadedGameObjects();
			loadedGameObjects.Prefab = DvergerAutomation.EmbeddedResourceBundle.LoadAsset<GameObject>(jbuildpiece.Prefab + ".prefab");
			loadedGameObjects.Sprite = DvergerAutomation.EmbeddedResourceBundle.LoadAsset<Sprite>(jbuildpiece.Sprite + ".png");
			jbuildpiece.Objs = loadedGameObjects;
			jbuildpiece.Cfgs = new PieceConfigs();
			InitialPieceSetup(jbuildpiece);
			BuildPieces.Add(jbuildpiece);
			PrefabManager.OnPrefabsRegistered += ResolveAndApplyScenePrefab;
			void ResolveAndApplyScenePrefab()
			{
				IEnumerable<GameObject> source = from obj in Resources.FindObjectsOfTypeAll<GameObject>()
					where ((Object)obj).name == jbuildpiece.Prefab
					select obj;
				if (ValConfig.EnableDebugMode.Value)
				{
					Logger.LogInfo($"Found {jbuildpiece.Prefab} scene parent objects: {source.Count()}");
				}
				GameObject val = source.FirstOrDefault();
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning("Could not find scene prefab '" + jbuildpiece.Prefab + "' after prefab registration; skipping in-place setup for " + jbuildpiece.Name + ".");
				}
				else
				{
					jbuildpiece.Objs.ScenePrefab = val;
					PiecesReady = true;
					ApplyWorkbench(jbuildpiece);
					ApplyCategory(jbuildpiece);
					ApplyRecipe(jbuildpiece);
				}
			}
		}

		private static void InitialPieceSetup(JotunnBuildPiece jbuildpiece)
		{
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Expected O, but got Unknown
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Expected O, but got Unknown
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Expected O, but got Unknown
			jbuildpiece.Cfgs.Workbench = ValConfig.BindServerConfig(jbuildpiece.Name ?? "", "Workbench", jbuildpiece.Workbench, "The table required to allow building this piece, eg: 'forge', 'piece_workbench', 'blackforge', 'piece_artisanstation'.");
			jbuildpiece.Cfgs.Workbench.SettingChanged += RequiredBench_SettingChanged;
			jbuildpiece.Cfgs.Enabled = ValConfig.BindServerConfig(jbuildpiece.Name ?? "", "Enabled", jbuildpiece.Enabled, "Enable/Disable the " + jbuildpiece.Name + ".");
			jbuildpiece.Cfgs.Enabled.SettingChanged += BuildRecipeChanged_SettingChanged;
			jbuildpiece.Cfgs.PieceCategory = ValConfig.BindServerConfig(jbuildpiece.Name ?? "", "Piece Category", jbuildpiece.Category, "Piece category for building.", PieceCategories.GetAcceptableValueList());
			jbuildpiece.Cfgs.PieceCategory.SettingChanged += CraftingCategory_SettingChanged;
			List<string> list = new List<string>();
			foreach (PieceCost item in jbuildpiece.PieceCost)
			{
				list.Add($"{item.prefab},{item.amount},{item.refundable}");
			}
			string text = string.Join("|", list);
			jbuildpiece.Cfgs.PieceCost = ValConfig.BindServerConfig(jbuildpiece.Name ?? "", "Building Cost", text, "Cost to build. Find item ids: https://valheim.fandom.com/wiki/Item_IDs Format: resouce_id,amount,refund eg: Wood,8,true|LeatherScraps,4,false", null, advanced: true);
			if (!PieceRecipeConfigUpdater(jbuildpiece, jbuildpiece.Cfgs.PieceCost.Value, during_runtime: false))
			{
				Logger.LogWarning(jbuildpiece.Name + " has an invalid piece cost. The default will be used instead.");
				PieceRecipeConfigUpdater(jbuildpiece, text, during_runtime: false);
			}
			jbuildpiece.Cfgs.PieceCost.SettingChanged += BuildRecipeChanged_SettingChanged;
			List<RequirementConfig> list2 = new List<RequirementConfig>();
			foreach (PieceCost item2 in jbuildpiece.Cfgs.UpdatedCost)
			{
				list2.Add(new RequirementConfig
				{
					Item = item2.prefab,
					Amount = item2.amount,
					Recover = item2.refundable
				});
			}
			PieceConfig val = new PieceConfig
			{
				CraftingStation = jbuildpiece.Cfgs.Workbench.Value,
				PieceTable = PieceTables.Hammer,
				Category = jbuildpiece.Cfgs.PieceCategory.Value,
				Icon = jbuildpiece.Objs.Sprite,
				Requirements = list2.ToArray()
			};
			PieceManager.Instance.AddPiece(new CustomPiece(jbuildpiece.Objs.Prefab, true, val));
			void BuildRecipeChanged_SettingChanged(object sender, EventArgs e)
			{
				if (PiecesReady && !((Object)(object)jbuildpiece.Objs.ScenePrefab == (Object)null))
				{
					if (sender.GetType() == typeof(ConfigEntry<string>))
					{
						ConfigEntry<string> val2 = (ConfigEntry<string>)sender;
						if (ValConfig.EnableDebugMode.Value)
						{
							Logger.LogInfo("Recieved new piece config " + val2.Value);
						}
						if (!PieceRecipeConfigUpdater(jbuildpiece, val2.Value))
						{
							return;
						}
					}
					ApplyRecipe(jbuildpiece);
				}
			}
			void CraftingCategory_SettingChanged(object sender, EventArgs e)
			{
				if (PiecesReady && !((Object)(object)jbuildpiece.Objs.ScenePrefab == (Object)null))
				{
					ApplyCategory(jbuildpiece);
				}
			}
			void RequiredBench_SettingChanged(object sender, EventArgs e)
			{
				if (PiecesReady && !((Object)(object)jbuildpiece.Objs.ScenePrefab == (Object)null))
				{
					ApplyWorkbench(jbuildpiece);
				}
			}
		}

		private static void ApplyWorkbench(JotunnBuildPiece jbuildpiece)
		{
			ConfigEntry<bool> requiresWorkbench = jbuildpiece.Cfgs.RequiresWorkbench;
			if ((requiresWorkbench != null && !requiresWorkbench.Value) || string.IsNullOrEmpty(jbuildpiece.Cfgs.Workbench.Value) || jbuildpiece.Cfgs.Workbench.Value.ToLower() == "none")
			{
				Logger.LogInfo("Setting required crafting station to none.");
				jbuildpiece.Objs.ScenePrefab.GetComponent<Piece>().m_craftingStation = null;
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(jbuildpiece.Cfgs.Workbench.Value);
			CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning("Required crafting station does not exist or does not have a crafting station componet, check your prefab name (" + jbuildpiece.Cfgs.Workbench.Value + ").");
				return;
			}
			if (ValConfig.EnableDebugMode.Value)
			{
				Logger.LogInfo("Setting crafting station to " + jbuildpiece.Cfgs.Workbench.Value + ".");
			}
			jbuildpiece.Objs.ScenePrefab.GetComponent<Piece>().m_craftingStation = val;
		}

		private static void ApplyCategory(JotunnBuildPiece jbuildpiece)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			PieceCategory? val = PieceManager.Instance.GetPieceCategory(jbuildpiece.Cfgs.PieceCategory.Value);
			if (!val.HasValue)
			{
				val = PieceManager.Instance.AddPieceCategory(jbuildpiece.Cfgs.PieceCategory.Value);
			}
			jbuildpiece.Objs.ScenePrefab.GetComponent<Piece>().m_category = val.Value;
		}

		private static void ApplyRecipe(JotunnBuildPiece jbuildpiece)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			List<RequirementConfig> list = new List<RequirementConfig>();
			if (ValConfig.EnableDebugMode.Value)
			{
				Logger.LogInfo("Validating and building requirementsConfig");
			}
			foreach (PieceCost item in jbuildpiece.Cfgs.UpdatedCost)
			{
				if ((Object)(object)PrefabManager.Instance.GetPrefab(item.prefab) == (Object)null)
				{
					if (ValConfig.EnableDebugMode.Value)
					{
						Logger.LogInfo(item.prefab + " is not a valid prefab, skipping recipe update.");
					}
					return;
				}
				if (ValConfig.EnableDebugMode.Value)
				{
					Logger.LogInfo($"Checking entry {item.prefab} amount:{item.amount} refund?:{item.refundable}");
				}
				list.Add(new RequirementConfig
				{
					Item = item.prefab,
					Amount = item.amount,
					Recover = item.refundable
				});
			}
			if (jbuildpiece.Cfgs.Enabled.Value)
			{
				if (ValConfig.EnableDebugMode.Value)
				{
					Logger.LogInfo("Updating Piece.");
				}
				List<Requirement> list2 = new List<Requirement>();
				foreach (RequirementConfig item2 in list)
				{
					Requirement val = new Requirement();
					GameObject prefab = PrefabManager.Instance.GetPrefab(item2.Item.Replace("JVLmock_", ""));
					val.m_resItem = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
					val.m_amount = item2.Amount;
					val.m_recover = item2.Recover;
					list2.Add(val);
				}
				if (ValConfig.EnableDebugMode.Value)
				{
					Logger.LogInfo($"Fixed mock requirements {list2.Count}.");
				}
				jbuildpiece.Objs.ScenePrefab.GetComponent<Piece>().m_resources = list2.ToArray();
				if (ValConfig.EnableDebugMode.Value)
				{
					Logger.LogInfo($"New requirements set {jbuildpiece.Objs.ScenePrefab.GetComponent<Piece>().m_resources}.");
				}
			}
			else
			{
				jbuildpiece.Objs.ScenePrefab.GetComponent<Piece>().m_enabled = false;
			}
		}

		private static bool PieceRecipeConfigUpdater(JotunnBuildPiece jbuildpiece, string rawrecipe, bool during_runtime = true)
		{
			string[] array = rawrecipe.Split(new char[1] { '|' });
			List<PieceCost> list = new List<PieceCost>();
			if (array.Length >= 1)
			{
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Split(new char[1] { ',' });
					if (array3.Length != 3)
					{
						Logger.LogWarning(text + " is invalid, it does not have enough segments. Proper format is: PREFABNAME,COST,REFUND_BOOL eg: Wood,8,false");
						return false;
					}
					if (ValConfig.EnableDebugMode.Value)
					{
						string text2 = "";
						string[] array4 = array3;
						foreach (string text3 in array4)
						{
							text2 = text2 + " " + text3;
						}
					}
					if (during_runtime && (Object)(object)PrefabManager.Instance.GetPrefab(array3[0]) == (Object)null)
					{
						Logger.LogWarning(array3[0] + " is an invalid prefab and does not exist.");
						return false;
					}
					if (array3[0].Length == 0 || array3[1].Length == 0 || array3[2].Length == 0)
					{
						Logger.LogWarning(text + " is invalid, one segment does not have enough data. Proper format is: PREFABNAME,CRAFT_COST,REFUND_BOOL eg: Wood,8,false");
						return false;
					}
					if (!bool.TryParse(array3[2], out var result))
					{
						Logger.LogWarning(text + " is invalid, the REFUND_BOOL could not be parsed to (true/false). Proper format is: PREFABNAME,CRAFT_COST,REFUND_BOOL eg: Wood,8,false");
						return false;
					}
					if (ValConfig.EnableDebugMode.Value)
					{
						Logger.LogInfo("prefab: " + array3[0] + " c:" + array3[1] + " u:" + array3[2]);
					}
					list.Add(new PieceCost
					{
						prefab = array3[0],
						amount = int.Parse(array3[1]),
						refundable = result
					});
				}
				jbuildpiece.Cfgs.UpdatedCost.Clear();
				foreach (PieceCost item in list)
				{
					jbuildpiece.Cfgs.UpdatedCost.Add(item);
				}
				if (ValConfig.EnableDebugMode.Value)
				{
					string text4 = "";
					foreach (PieceCost item2 in list)
					{
						text4 += $" {item2.prefab} c:{item2.amount} r:{item2.refundable}";
					}
					Logger.LogInfo("Updated recipe:" + text4);
				}
				return true;
			}
			Logger.LogWarning("Invalid recipe: " + rawrecipe + ". defaults will be used. Check your prefab names.");
			jbuildpiece.Cfgs.UpdatedCost = jbuildpiece.PieceCost;
			return false;
		}
	}
	internal static class LocalizationLoader
	{
		internal static string LocalizationFolder = "Localizations";

		internal static void AddLocalizations()
		{
			CustomLocalization localization = DvergerAutomation.Localization;
			string text = Path.Combine(Paths.ConfigPath, "DvergerAutomation", LocalizationFolder);
			Directory.CreateDirectory(text);
			string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
			foreach (string text2 in manifestResourceNames)
			{
				if (!text2.Contains(LocalizationFolder))
				{
					continue;
				}
				string text3 = Regex.Replace(ReadEmbeddedResourceFile(text2), "\\/\\/.*", "");
				Dictionary<string, string> internal_localization = SimpleJson.DeserializeObject<Dictionary<string, string>>(text3);
				string[] array = text2.Split(new char[1] { '.' });
				if (File.Exists(text + "/" + array[2] + ".json"))
				{
					string text4 = File.ReadAllText(text + "/" + array[2] + ".json");
					try
					{
						Dictionary<string, string> dictionary = SimpleJson.DeserializeObject<Dictionary<string, string>>(text4);
						UpdateLocalizationWithMissingKeys(internal_localization, dictionary);
						Logger.LogDebug("Reading " + text + "/" + array[2] + ".json");
						File.WriteAllText(text + "/" + array[2] + ".json", SimpleJson.SerializeObject((object)dictionary));
						string text5 = File.ReadAllText(text + "/" + array[2] + ".json");
						localization.AddJsonFile(array[2], text5);
					}
					catch
					{
						File.WriteAllText(text + "/" + array[2] + ".json", text3);
						Logger.LogDebug("Reading " + text2);
						localization.AddJsonFile(array[2], text3);
					}
				}
				else
				{
					File.WriteAllText(text + "/" + array[2] + ".json", text3);
					Logger.LogDebug("Reading " + text2);
					localization.AddJsonFile(array[2], text3);
				}
				Logger.LogDebug("Added localization: '" + array[2] + "'");
			}
		}

		private static Dictionary<string, string> UpdateLocalizationWithMissingKeys(Dictionary<string, string> internal_localization, Dictionary<string, string> cached_localization)
		{
			if (internal_localization.Keys != cached_localization.Keys)
			{
				List<string> list = cached_localization.Keys.ToList();
				foreach (KeyValuePair<string, string> item in internal_localization)
				{
					list.Remove(item.Key);
					if (!cached_localization.ContainsKey(item.Key))
					{
						Logger.LogDebug("Adding missing localization key " + item.Key);
						cached_localization.Add(item.Key, item.Value);
					}
				}
				if (list.Count > 0)
				{
					Logger.LogDebug("Removing extra keys " + string.Join(",", list) + ".");
					foreach (string item2 in list)
					{
						cached_localization.Remove(item2);
					}
				}
			}
			return cached_localization;
		}

		private static string ReadEmbeddedResourceFile(string filename)
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(filename);
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}
	}
}
namespace EpicLootAPI
{
	[Serializable]
	[PublicAPI]
	public enum AbilityActivationMode
	{
		Passive,
		Triggerable,
		Activated
	}
	[Serializable]
	[PublicAPI]
	public enum AbilityAction
	{
		Custom,
		StatusEffect
	}
	[Serializable]
	[PublicAPI]
	public class AbilityDefinition
	{
		public string ID = "";

		public string IconAsset = "";

		public AbilityActivationMode ActivationMode;

		public float Cooldown;

		public AbilityAction Action;

		public List<string> ActionParams = new List<string>();

		internal static readonly Method API_AddAbility = new Method("AddAbility");

		internal static readonly Method API_UpdateAbility = new Method("UpdateAbility");

		internal static List<AbilityDefinition> Abilities = new List<AbilityDefinition>();

		[Description("Register a status effect ability which activates on player input")]
		public AbilityDefinition(string ID, string iconAsset, float cooldown, string statusEffectName)
		{
			this.ID = ID;
			ActivationMode = AbilityActivationMode.Activated;
			Cooldown = cooldown;
			Action = AbilityAction.StatusEffect;
			ActionParams.Add(statusEffectName);
			IconAsset = iconAsset;
			Abilities.Add(this);
		}

		internal AbilityDefinition(string ID, AbilityActivationMode mode)
		{
			this.ID = ID;
			ActivationMode = mode;
		}

		public AbilityDefinition()
		{
		}

		public static void RegisterAll()
		{
			foreach (AbilityDefinition item in new List<AbilityDefinition>(Abilities))
			{
				item.Register();
			}
		}

		public bool Register()
		{
			string text = JsonConvert.SerializeObject((object)this);
			if (!(API_AddAbility.Invoke(text)[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(this, value);
			Abilities.Remove(this);
			EpicLoot.logger.LogDebug("Registered ability: " + ID);
			return true;
		}

		public bool Update()
		{
			if (!RunTimeRegistry.TryGetValue(this, out string value))
			{
				return false;
			}
			string text = JsonConvert.SerializeObject((object)this);
			bool flag = (bool)(API_UpdateAbility.Invoke(value, text)[0] ?? ((object)false));
			EpicLoot.logger.LogDebug($"Updated ability {ID}: {flag}");
			return flag;
		}
	}
	[PublicAPI]
	public class AbilityProxyDefinition
	{
		public readonly AbilityDefinition Ability;

		public readonly Dictionary<string, Delegate> Callbacks = new Dictionary<string, Delegate>();

		internal static readonly List<AbilityProxyDefinition> ProxyAbilities = new List<AbilityProxyDefinition>();

		internal static readonly Method API_RegisterProxyAbility = new Method("RegisterProxyAbility");

		internal static readonly Method API_UpdateProxyAbility = new Method("UpdateProxyAbility");

		[Description("Register a complex ability behavior using Proxy class")]
		public AbilityProxyDefinition(string ID, AbilityActivationMode mode, Proxy definition)
		{
			Ability = new AbilityDefinition(ID, mode);
			RegisterCallbacks(definition);
			ProxyAbilities.Add(this);
		}

		[Description("Register a complex ability behavior using Proxy class")]
		public AbilityProxyDefinition(string ID, AbilityActivationMode mode, Type type)
		{
			Ability = new AbilityDefinition(ID, mode);
			if (!typeof(Proxy).IsAssignableFrom(type))
			{
				EpicLoot.logger.LogError("Ability Proxy " + ID + " Type " + type.Name + " does not implement Proxy class");
				return;
			}
			try
			{
				object obj = Activator.CreateInstance(type);
				RegisterCallbacks((Proxy)obj);
				ProxyAbilities.Add(this);
			}
			catch (Exception ex)
			{
				EpicLoot.logger.LogError("Failed to create instance of " + type.Name + ": " + ex.Message);
			}
		}

		private void RegisterCallbacks(Proxy implementation)
		{
			Type type = implementation.GetType();
			MethodInfo[] methods = typeof(Proxy).GetMethods();
			foreach (MethodInfo methodInfo in methods)
			{
				try
				{
					Type[] array = (from p in methodInfo.GetParameters()
						select p.ParameterType).ToArray();
					MethodInfo method = type.GetMethod(methodInfo.Name, array);
					if (method == null)
					{
						EpicLoot.logger.LogWarning("Method " + methodInfo.Name + " not found in implementation");
						continue;
					}
					Type type2 = ((!(methodInfo.ReturnType == typeof(void))) ? Expression.GetFuncType(array.Concat(new Type[1] { methodInfo.ReturnType }).ToArray()) : ((array.Length != 0) ? Expression.GetActionType(array) : typeof(Action)));
					Delegate value = Delegate.CreateDelegate(type2, implementation, method);
					Callbacks[methodInfo.Name] = value;
				}
				catch (Exception ex)
				{
					EpicLoot.logger.LogError("Failed to register callback for method " + methodInfo.Name + ": " + ex.Message);
				}
			}
		}

		public static void RegisterAll()
		{
			foreach (AbilityProxyDefinition item in new List<AbilityProxyDefinition>(ProxyAbilities))
			{
				item.Register();
			}
		}

		public bool Register()
		{
			string text = JsonConvert.SerializeObject((object)Ability);
			if (!(API_RegisterProxyAbility.Invoke(text, Callbacks)[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(this, value);
			ProxyAbilities.Remove(this);
			EpicLoot.logger.LogDebug("Registered proxy ability: " + Ability.ID);
			return true;
		}

		public bool Update()
		{
			if (!RunTimeRegistry.TryGetValue(this, out string value))
			{
				return false;
			}
			string text = JsonConvert.SerializeObject((object)Ability);
			bool flag = (bool)(API_UpdateProxyAbility.Invoke(value, text, Callbacks)[0] ?? ((object)false));
			EpicLoot.logger.LogDebug($"Updated proxy ability: {Ability.ID}, {flag}");
			return flag;
		}
	}
	[Description("Functions are converted into delegates when registered to epic loot")]
	[PublicAPI]
	public class Proxy
	{
		protected Player Player;

		public string AbilityID = "";

		public float Cooldown;

		public virtual string CooldownEndKey => "EpicLoot." + AbilityID + ".CooldownEnd";

		public virtual void Initialize(Player player, string id, float cooldown)
		{
			Player = player;
			AbilityID = id;
			Cooldown = cooldown;
		}

		public virtual void OnUpdate()
		{
		}

		public virtual bool ShouldTrigger()
		{
			return false;
		}

		public virtual bool IsOnCooldown()
		{
			if (HasCooldown())
			{
				return GetTime() < GetCooldownEndTime();
			}
			return false;
		}

		public virtual float TimeUntilCooldownEnds()
		{
			return Mathf.Max(0f, GetCooldownEndTime() - GetTime());
		}

		public virtual float PercentCooldownComplete()
		{
			if (HasCooldown() && IsOnCooldown())
			{
				return 1f - TimeUntilCooldownEnds() / Cooldown;
			}
			return 1f;
		}

		public virtual bool CanActivate()
		{
			return !IsOnCooldown();
		}

		public virtual void TryActivate()
		{
			if (CanActivate())
			{
				Activate();
			}
		}

		public virtual void Activate()
		{
			if (HasCooldown())
			{
				float cooldownEndTime = GetTime() + Cooldown;
				SetCooldownEndTime(cooldownEndTime);
			}
		}

		public virtual void ActivateCustomAction()
		{
		}

		public virtual void ActivateStatusEffectAction()
		{
		}

		public virtual bool HasCooldown()
		{
			return Cooldown > 0f;
		}

		public virtual void SetCooldownEndTime(float cooldownEndTime)
		{
			if (!((Object)(object)Player == (Object)null))
			{
				((Character)Player).m_nview.GetZDO().Set(CooldownEndKey, cooldownEndTime);
			}
		}

		public virtual float GetCooldownEndTime()
		{
			if ((Object)(object)Player == (Object)null)
			{
				return 0f;
			}
			return ((Character)Player).m_nview.GetZDO().GetFloat(CooldownEndKey, 0f);
		}

		public virtual void OnRemoved()
		{
		}

		protected static float GetTime()
		{
			return (float)ZNet.instance.GetTimeSeconds();
		}
	}
	public static class EpicLoot
	{
		[PublicAPI]
		public static class ChangeReason
		{
			public const string Enchant = "Enchant";

			public const string Augment = "Augment";

			public const string Disenchant = "Disenchant";

			public const string Rune = "Rune";

			public const string Temper = "Temper";

			public const string Socket = "Socket";

			public const string Unsocket = "Unsocket";

			public const string LootRoll = "LootRoll";

			public const string Transfer = "Transfer";

			public const string AddSocket = "AddSocket";

			public const string Unspecified = "Unspecified";
		}

		public static readonly Logger logger = new Logger();

		private static readonly Method API_GetTotalActiveMagicEffectValue = new Method("GetTotalActiveMagicEffectValue");

		private static readonly Method API_GetTotalActiveMagicEffectValueForWeapon = new Method("GetTotalActiveMagicEffectValueForWeapon");

		private static readonly Method API_HasActiveMagicEffect = new Method("HasActiveMagicEffect");

		private static readonly Method API_HasActiveMagicEffectOnWeapon = new Method("HasActiveMagicEffectOnWeapon");

		private static readonly Method API_GetTotalActiveSetEffectValue = new Method("GetTotalActiveSetEffectValue");

		private static readonly Method API_GetAllActiveMagicEffects = new Method("GetAllActiveMagicEffects");

		private static readonly Method API_GetAllSetMagicEffects = new Method("GetAllActiveSetMagicEffects");

		private static readonly Method API_GetPlayerTotalActiveMagicEffectValue = new Method("GetTotalPlayerActiveMagicEffectValue");

		private static readonly Method API_PlayerHasActiveMagicEffect = new Method("PlayerHasActiveMagicEffect");

		private static readonly Method API_HasLegendaryItem = new Method("HasLegendaryItem");

		private static readonly Method API_HasLegendarySet = new Method("HasLegendarySet");

		private static readonly Method API_RegisterAsset = new Method("RegisterAsset");

		private static readonly Method API_GetMagicItemJson = new Method("GetMagicItemJson");

		private static readonly Method API_RegisterMagicEffectRequirement = new Method("RegisterMagicEffectRequirement", typeof(string), typeof(Func<ItemData, object, string, bool, bool, bool, bool>));

		private static readonly Method API_AddMagicItemChangedListener = new Method("AddMagicItemChangedListener", typeof(Action<ItemData, string>));

		private static readonly Method API_RemoveMagicItemChangedListener = new Method("RemoveMagicItemChangedListener", typeof(Action<ItemData, string>));

		private static readonly Method API_AddLootGeneratedListener = new Method("AddLootGeneratedListener", typeof(Action<ItemData>));

		private static readonly Method API_RemoveLootGeneratedListener = new Method("RemoveLootGeneratedListener", typeof(Action<ItemData>));

		private static readonly Method API_AddBountyCompletedListener = new Method("AddBountyCompletedListener", typeof(Action<Player, string>));

		private static readonly Method API_RemoveBountyCompletedListener = new Method("RemoveBountyCompletedListener", typeof(Action<Player, string>));

		private static readonly Method API_TryMakeMagicItem = new Method("TryMakeMagicItem");

		private static readonly Method API_RollMagicItemJson = new Method("RollMagicItemJson");

		private static readonly Method API_ApplyMagicItemJson = new Method("ApplyMagicItemJson");

		private static readonly Method API_GetLuckFactor = new Method("GetLuckFactor");

		private static readonly Method API_RollEffectCountForRarity = new Method("RollEffectCountForRarity");

		private static readonly Method API_GetLegendaryIDs = new Method("GetLegendaryIDs");

		private static readonly Method API_GetLegendaryInfoJson = new Method("GetLegendaryInfoJson");

		private static readonly Method API_GetAvailableEffectTypes = new Method("GetAvailableEffectTypes");

		private static readonly Method API_AddLootTables = new Method("AddLootTables");

		private static readonly Method API_UpdateLootTables = new Method("UpdateLootTables");

		private static readonly Method API_RegisterInventoryProvider = new Method("RegisterInventoryProvider", typeof(string), typeof(Func<List<ItemData>>), typeof(Func<string, int>), typeof(Func<string, int, int>), typeof(Func<ItemData, int, int>));

		private static readonly Method API_UnregisterInventoryProvider = new Method("UnregisterInventoryProvider");

		private static readonly Method API_RegisterEquipmentProvider = new Method("RegisterEquipmentProvider", typeof(string), typeof(Func<Player, List<ItemData>>));

		private static readonly Method API_UnregisterEquipmentProvider = new Method("UnregisterEquipmentProvider");

		private static readonly Method API_RegisterSacrificeFilter = new Method("RegisterSacrificeFilter", typeof(string), typeof(Func<ItemData, bool>));

		private static readonly Method API_UnregisterSacrificeFilter = new Method("UnregisterSacrificeFilter");

		private static readonly Method API_InvalidatePlayerEffectCache = new Method("InvalidatePlayerEffectCache");

		private static readonly Method API_GetRegisteredProviders = new Method("GetRegisteredProviders");

		private static readonly Method API_GetApiVersion = new Method("GetApiVersion");

		private static readonly Method API_GetPluginVersion = new Method("GetPluginVersion");

		private static readonly Method API_HasEndpoint = new Method("HasEndpoint");

		private static readonly Method API_IsMagicItem = new Method("IsMagicItem");

		private static readonly Method API_TryGetRarity = new Method("TryGetRarity");

		private static readonly Method API_GetRarityCount = new Method("GetRarityCount");

		private static readonly Method API_GetRarityColorByIndex = new Method("GetRarityColorByIndex");

		private static readonly Method API_GetRarityDisplayNameByIndex = new Method("GetRarityDisplayNameByIndex");

		private static readonly Method API_GetItemRarityColor = new Method("GetItemRarityColor");

		private static readonly Method API_IsEpicLootItem = new Method("IsEpicLootItem");

		private static readonly Method API_IsShardStone = new Method("IsShardStone");

		private static readonly Method API_IsRunestone = new Method("IsRunestone");

		private static readonly Method API_IsMagicCraftingMaterial = new Method("IsMagicCraftingMaterial");

		private static readonly Method API_IsUnidentified = new Method("IsUnidentified");

		private static readonly Method API_CanBeMagicItem = new Method("CanBeMagicItem");

		private static readonly Method API_ItemHasMagicEffect = new Method("ItemHasMagicEffect");

		private static readonly Method API_GetAllMagicEffectTypes = new Method("GetAllMagicEffectTypes");

		private static readonly Method API_GetEnchantCostsJson = new Method("GetEnchantCostsJson");

		private static readonly Method API_GetSacrificeProductsJson = new Method("GetSacrificeProductsJson");

		private static readonly Method API_GetItemDisplayName = new Method("GetItemDisplayName");

		private static readonly Method API_GetItemDecoratedName = new Method("GetItemDecoratedName", typeof(ItemData), typeof(string));

		private static readonly Method API_ApplyMagicItemBackground = new Method("ApplyMagicItemBackground", typeof(GameObject), typeof(GameObject), typeof(ItemData), typeof(bool));

		private static readonly Method API_ApplyMagicItemBackgroundToIcon = new Method("ApplyMagicItemBackgroundToIcon", typeof(GameObject), typeof(ItemData));

		[PublicAPI]
		[Description("Send all your custom conversions, effects, item definitions, etc... to Epic Loot")]
		public static void RegisterAll()
		{
			MaterialConversion.RegisterAll();
			MagicItemEffectDefinition.RegisterAll();
			AbilityDefinition.RegisterAll();
			CustomRecipe.RegisterAll();
			Sacrifice.RegisterAll();
			TreasureMap.RegisterAll();
			SecretStashItem.RegisterAll();
			LegendaryInfo.RegisterAll();
			LegendarySetInfo.RegisterAll();
			BountyTarget.RegisterAll();
			AbilityProxyDefinition.RegisterAll();
		}

		[PublicAPI]
		[Description("Register asset into EpicLoot in order to target them in your definitions")]
		public static bool RegisterAsset(string name, object asset)
		{
			bool flag = (bool)(API_RegisterAsset.Invoke(name, asset)[0] ?? ((object)false));
			logger.LogDebug($"Registered asset: {name}, {flag}");
			return flag;
		}

		[PublicAPI]
		public static bool RegisterMagicEffectRequirement(string externalRequirement, Func<ItemData, object, string, bool, bool, bool, bool> requirement)
		{
			bool flag = (bool)(API_RegisterMagicEffectRequirement.Invoke(externalRequirement, requirement)[0] ?? ((object)false));
			logger.LogDebug($"Registered magic effect requirement: {externalRequirement}, {flag}");
			return flag;
		}

		[PublicAPI]
		public static bool HasLegendaryItem(this Player player, string legendaryItemID)
		{
			bool flag = (bool)(API_HasLegendaryItem.Invoke(player, legendaryItemID)[0] ?? ((object)false));
			logger.LogDebug($"Has legendary item: {legendaryItemID}, {flag} ");
			return flag;
		}

		[PublicAPI]
		public static bool HasLegendarySet(this Player player, string legendarySetID, out int count)
		{
			count = 0;
			object[] array = API_HasLegendarySet.Invoke(player, legendarySetID, count);
			count = (int)(array[3] ?? ((object)0));
			bool flag = (bool)(array[0] ?? ((object)false));
			logger.LogDebug($"Has legendary set: {legendarySetID}, {flag}, count: {count}");
			return flag;
		}

		[PublicAPI]
		public static bool HasActiveMagicEffectOnWeapon(Player player, ItemData item, string effectType, out float effectValue)
		{
			effectValue = 0f;
			object[] array = API_HasActiveMagicEffectOnWeapon.Invoke(player, item, effectType, effectValue);
			effectValue = (float)(array[4] ?? ((object)0f));
			bool flag = (bool)(array[0] ?? ((object)false));
			logger.LogDebug($"Has magic effect on weapon: {effectType}, {flag}, value: {effectValue}");
			return flag;
		}

		[PublicAPI]
		public static float GetTotalActiveMagicEffectValue(Player player, ItemData item, string effectType, float scale = 1f)
		{
			float num = (float)(API_GetTotalActiveMagicEffectValue.Invoke(player, item, effectType, scale)[0] ?? ((object)0f));
			logger.LogDebug($"Total magic effect value: {effectType}, amount: {num}");
			return num;
		}

		[PublicAPI]
		public static float GetTotalActiveMagicEffectValueForWeapon(Player player, ItemData item, string effectType, float scale = 1f)
		{
			float num = (float)(API_GetTotalActiveMagicEffectValueForWeapon.Invoke(player, item, effectType, scale)[0] ?? ((object)0f));
			logger.LogDebug($"Total effect on weapon: {effectType}, amount: {num}");
			return num;
		}

		[PublicAPI]
		public static bool HasActiveMagicEffect(Player player, string effectType, ItemData item, out float effectValue)
		{
			effectValue = 0f;
			object[] array = API_HasActiveMagicEffect.Invoke(player, effectType, item, effectValue);
			effectValue = (float)(array[4] ?? ((object)0f));
			bool flag = (bool)(array[0] ?? ((object)false));
			logger.LogDebug($"Has active effect: {effectType}, {flag}, value: {effectValue}");
			return flag;
		}

		[PublicAPI]
		public static float GetTotalActiveSetEffectValue(Player player, string effectType, float scale = 1f)
		{
			float num = (float)(API_GetTotalActiveSetEffectValue.Invoke(player, effectType, scale)[0] ?? ((object)0f));
			logger.LogDebug($"Total effect value: {effectType}, amount: {num}");
			return num;
		}

		[PublicAPI]
		public static List<MagicItemEffect> GetAllActiveMagicEffects(this Player player, string effectType = null)
		{
			List<string> list = (List<string>)(API_GetAllActiveMagicEffects.Invoke(player, effectType)[0] ?? new List<string>());
			if (list.Count <= 0)
			{
				return new List<MagicItemEffect>();
			}
			List<MagicItemEffect> list2 = new List<MagicItemEffect>();
			list2.DeserializeList(list);
			return list2;
		}

		[PublicAPI]
		public static List<MagicItemEffect> GetAllActiveSetMagicEffects(this Player player, string effectType = null)
		{
			List<string> list = (List<string>)(API_GetAllSetMagicEffects.Invoke(player, effectType)[0] ?? new List<string>());
			if (list.Count <= 0)
			{
				return new List<MagicItemEffect>();
			}
			List<MagicItemEffect> list2 = new List<MagicItemEffect>();
			list2.DeserializeList(list);
			return list2;
		}

		private static void DeserializeList<T>(this List<T> output, List<string> input)
		{
			foreach (string item in input)
			{
				try
				{
					T val = JsonConvert.DeserializeObject<T>(item);
					if (val != null)
					{
						output.Add(val);
					}
				}
				catch
				{
					logger.LogWarning("Failed to parse " + typeof(T).Name);
				}
			}
		}

		[PublicAPI]
		public static float GetTotalActiveMagicEffectValue(this Player player, string effectType, float scale = 1f, ItemData ignoreThisItem = null)
		{
			float num = (float)(API_GetPlayerTotalActiveMagicEffectValue.Invoke(player, effectType, scale, ignoreThisItem)[0] ?? ((object)0f));
			logger.LogDebug($"Total magic effect: {effectType}, value: {num}");
			return num;
		}

		[PublicAPI]
		public static bool HasActiveMagicEffect(this Player player, string effectType, out float effectValue, float scale = 1f, ItemData ignoreThisItem = null)
		{
			effectValue = 0f;
			object[] array = API_PlayerHasActiveMagicEffect.Invoke(player, effectType, effectValue, scale, ignoreThisItem);
			effectValue = (float)(array[3] ?? ((object)0f));
			bool flag = (bool)(array[0] ?? ((object)false));
			logger.LogDebug($"Has active magic effect: {effectType}, value: {flag}");
			return flag;
		}

		[PublicAPI]
		public static MagicItem GetMagicItem(this ItemData itemData)
		{
			string text = (string)(API_GetMagicItemJson.Invoke(itemData)[0] ?? "");
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			return JsonConvert.DeserializeObject<MagicItem>(text);
		}

		[PublicAPI]
		public static bool AddMagicItemChangedListener(Action<ItemData, string> listener)
		{
			return (bool)(API_AddMagicItemChangedListener.Invoke(listener)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool RemoveMagicItemChangedListener(Action<ItemData, string> listener)
		{
			return (bool)(API_RemoveMagicItemChangedListener.Invoke(listener)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool AddLootGeneratedListener(Action<ItemData> listener)
		{
			return (bool)(API_AddLootGeneratedListener.Invoke(listener)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool RemoveLootGeneratedListener(Action<ItemData> listener)
		{
			return (bool)(API_RemoveLootGeneratedListener.Invoke(listener)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool AddBountyCompletedListener(Action<Player, string> listener)
		{
			return (bool)(API_AddBountyCompletedListener.Invoke(listener)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool RemoveBountyCompletedListener(Action<Player, string> listener)
		{
			return (bool)(API_RemoveBountyCompletedListener.Invoke(listener)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool TryMakeMagicItem(this ItemData item, ItemRarity rarity, float luck = 0f, string? legendaryID = null)
		{
			bool flag = (bool)(API_TryMakeMagicItem.Invoke(item, (int)rarity, luck, legendaryID ?? "")[0] ?? ((object)false));
			logger.LogDebug($"Made magic item: {item?.m_shared?.m_name}, {rarity}, {flag}");
			return flag;
		}

		[PublicAPI]
		public static MagicItem? RollMagicItem(ItemRarity rarity, ItemData item, float luck = 0f)
		{
			string text = (string)(API_RollMagicItemJson.Invoke((int)rarity, item, luck)[0] ?? "");
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			try
			{
				return JsonConvert.DeserializeObject<MagicItem>(text);
			}
			catch
			{
				logger.LogWarning("Failed to parse rolled magic item");
				return null;
			}
		}

		[PublicAPI]
		public static bool ApplyMagicItem(this ItemData item, MagicItem magicItem)
		{
			if (magicItem == null)
			{
				return false;
			}
			string text = JsonConvert.SerializeObject((object)magicItem);
			return (bool)(API_ApplyMagicItemJson.Invoke(item, text)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static float GetLuckFactor(Vector3 position)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return (float)(API_GetLuckFactor.Invoke(position)[0] ?? ((object)0f));
		}

		[PublicAPI]
		public static int RollEffectCountForRarity(ItemRarity rarity)
		{
			return (int)(API_RollEffectCountForRarity.Invoke((int)rarity)[0] ?? ((object)0));
		}

		[PublicAPI]
		public static List<string> GetLegendaryIDs(ItemRarity rarity)
		{
			return (List<string>)(API_GetLegendaryIDs.Invoke((int)rarity)[0] ?? new List<string>());
		}

		[PublicAPI]
		public static LegendaryInfo? GetLegendaryInfo(string legendaryID)
		{
			string text = (string)(API_GetLegendaryInfoJson.Invoke(legendaryID)[0] ?? "");
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			try
			{
				return JsonConvert.DeserializeObject<LegendaryInfo>(text);
			}
			catch
			{
				logger.LogWarning("Failed to parse legendary info for " + legendaryID);
				return null;
			}
		}

		[PublicAPI]
		public static List<string> GetAvailableEffectTypes(this ItemData item, ItemRarity rarity, MagicItem? magicItem = null)
		{
			string text = ((magicItem == null) ? "" : JsonConvert.SerializeObject((object)magicItem));
			return (List<string>)(API_GetAvailableEffectTypes.Invoke(item, text, (int)rarity)[0] ?? new List<string>());
		}

		[PublicAPI]
		public static bool AddLootTables(string json)
		{
			if (!(API_AddLootTables.Invoke(json)[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(json, value);
			logger.LogDebug("Registered external loot tables");
			return true;
		}

		[PublicAPI]
		public static bool UpdateLootTables(string originalJson, string json)
		{
			if (!RunTimeRegistry.TryGetValue(originalJson, out string value))
			{
				return false;
			}
			return (bool)(API_UpdateLootTables.Invoke(value, json)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool RegisterInventoryProvider(string id, Func<List<ItemData>> getItems, Func<string, int> countItem, Func<string, int, int> removeItem, Func<ItemData, int, int> removeExactItem)
		{
			bool flag = (bool)(API_RegisterInventoryProvider.Invoke(id, getItems, countItem, removeItem, removeExactItem)[0] ?? ((object)false));
			logger.LogDebug($"Registered inventory provider: {id}, {flag}");
			return flag;
		}

		[PublicAPI]
		public static bool UnregisterInventoryProvider(string id)
		{
			return (bool)(API_UnregisterInventoryProvider.Invoke(id)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool RegisterEquipmentProvider(string id, Func<Player, List<ItemData>> getExtraEquipped)
		{
			bool flag = (bool)(API_RegisterEquipmentProvider.Invoke(id, getExtraEquipped)[0] ?? ((object)false));
			logger.LogDebug($"Registered equipment provider: {id}, {flag}");
			return flag;
		}

		[PublicAPI]
		public static bool UnregisterEquipmentProvider(string id)
		{
			return (bool)(API_UnregisterEquipmentProvider.Invoke(id)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static void InvalidatePlayerEffectCache(this Player player)
		{
			API_InvalidatePlayerEffectCache.Invoke(player);
		}

		[PublicAPI]
		public static bool RegisterSacrificeFilter(string id, Func<ItemData, bool> canSacrifice)
		{
			bool flag = (bool)(API_RegisterSacrificeFilter.Invoke(id, canSacrifice)[0] ?? ((object)false));
			logger.LogDebug($"Registered sacrifice filter: {id}, {flag}");
			return flag;
		}

		[PublicAPI]
		public static bool UnregisterSacrificeFilter(string id)
		{
			return (bool)(API_UnregisterSacrificeFilter.Invoke(id)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static Dictionary<string, List<string>> GetRegisteredProviders()
		{
			return (Dictionary<string, List<string>>)(API_GetRegisteredProviders.Invoke()[0] ?? new Dictionary<string, List<string>>());
		}

		[PublicAPI]
		public static int GetApiVersion()
		{
			return (int)(API_GetApiVersion.Invoke()[0] ?? ((object)0));
		}

		[PublicAPI]
		public static bool IsLoaded()
		{
			return GetApiVersion() > 0;
		}

		[PublicAPI]
		public static string GetPluginVersion()
		{
			return (string)(API_GetPluginVersion.Invoke()[0] ?? "");
		}

		[PublicAPI]
		public static bool HasEndpoint(string name)
		{
			return (bool)(API_HasEndpoint.Invoke(name)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool IsMagicItem(this ItemData item)
		{
			return (bool)(API_IsMagicItem.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool TryGetRarity(this ItemData item, out ItemRarity rarity)
		{
			rarity = ItemRarity.Magic;
			int num = 0;
			object[] array = API_TryGetRarity.Invoke(item, num);
			if ((bool)(array[0] ?? ((object)false)))
			{
				rarity = (ItemRarity)(int)(array[2] ?? ((object)0));
				return true;
			}
			return false;
		}

		[PublicAPI]
		public static string GetDisplayName(this ItemData item)
		{
			return (string)(API_GetItemDisplayName.Invoke(item)[0] ?? "");
		}

		[PublicAPI]
		public static string GetDecoratedName(this ItemData item, string colorOverride = null)
		{
			return (string)(API_GetItemDecoratedName.Invoke(item, colorOverride)[0] ?? "");
		}

		[PublicAPI]
		public static int GetRarityCount()
		{
			return (int)(API_GetRarityCount.Invoke()[0] ?? ((object)0));
		}

		[PublicAPI]
		public static string GetRarityColor(ItemRarity rarity)
		{
			return (string)(API_GetRarityColorByIndex.Invoke((int)rarity)[0] ?? "#FFFFFF");
		}

		[PublicAPI]
		public static string GetRarityDisplayName(ItemRarity rarity)
		{
			return (string)(API_GetRarityDisplayNameByIndex.Invoke((int)rarity)[0] ?? "");
		}

		[PublicAPI]
		public static string GetItemRarityColor(this ItemData item)
		{
			return (string)(API_GetItemRarityColor.Invoke(item)[0] ?? "#FFFFFF");
		}

		[PublicAPI]
		public static bool IsEpicLootItem(this ItemData item)
		{
			return (bool)(API_IsEpicLootItem.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool IsShardStone(this ItemData item)
		{
			return (bool)(API_IsShardStone.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool IsRunestone(this ItemData item)
		{
			return (bool)(API_IsRunestone.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool IsMagicCraftingMaterial(this ItemData item)
		{
			return (bool)(API_IsMagicCraftingMaterial.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool IsUnidentified(this ItemData item)
		{
			return (bool)(API_IsUnidentified.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool CanBeMagicItem(this ItemData item)
		{
			return (bool)(API_CanBeMagicItem.Invoke(item)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool HasMagicEffect(this ItemData item, string effectType, bool includeSocketed = true)
		{
			return (bool)(API_ItemHasMagicEffect.Invoke(item, effectType, includeSocketed)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static List<string> GetAllMagicEffectTypes()
		{
			return (List<string>)(API_GetAllMagicEffectTypes.Invoke()[0] ?? new List<string>());
		}

		[PublicAPI]
		public static List<ItemAmount> GetEnchantCosts(this ItemData item, ItemRarity rarity)
		{
			return DeserializeAmounts((string)(API_GetEnchantCostsJson.Invoke(item, (int)rarity)[0] ?? "[]"));
		}

		[PublicAPI]
		public static List<ItemAmount> GetSacrificeProducts(this ItemData item)
		{
			return DeserializeAmounts((string)(API_GetSacrificeProductsJson.Invoke(item)[0] ?? "[]"));
		}

		private static List<ItemAmount> DeserializeAmounts(string json)
		{
			try
			{
				return JsonConvert.DeserializeObject<List<ItemAmount>>(json) ?? new List<ItemAmount>();
			}
			catch
			{
				logger.LogWarning("Failed to parse item amount list");
				return new List<ItemAmount>();
			}
		}

		[PublicAPI]
		public static bool ApplyMagicItemBackground(GameObject slotRoot, GameObject equippedOverlay, ItemData item, bool inventoryGrid)
		{
			return (bool)(API_ApplyMagicItemBackground.Invoke(slotRoot, equippedOverlay, item, inventoryGrid)[0] ?? ((object)false));
		}

		[PublicAPI]
		public static bool ApplyMagicItemBackgroundToIcon(GameObject iconObject, ItemData item)
		{
			return (bool)(API_ApplyMagicItemBackgroundToIcon.Invoke(iconObject, item)[0] ?? ((object)false));
		}
	}
	[Serializable]
	[PublicAPI]
	public class BountyMinion
	{
		public string ID = "";

		public int Count;

		public BountyMinion(string ID, int count)
		{
			this.ID = ID;
			Count = count;
		}

		public BountyMinion()
		{
		}
	}
	[Serializable]
	[PublicAPI]
	public class BountyTarget
	{
		public Biome Biome;

		public string TargetID = "";

		public int RewardGold;

		public int RewardIron;

		public int RewardCoins;

		public List<BountyMinion> Adds = new List<BountyMinion>();

		internal static readonly List<BountyTarget> BountyTargets = new List<BountyTarget>();

		internal static readonly Method API_AddBountyTarget = new Method("AddBountyTarget");

		internal static readonly Method API_UpdateBountyTarget = new Method("UpdateBountyTarget");

		public BountyTarget(Biome biome, string targetID)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Biome = biome;
			TargetID = targetID;
			BountyTargets.Add(this);
		}

		public BountyTarget()
		{
		}

		public static void RegisterAll()
		{
			foreach (BountyTarget item in new List<BountyTarget>(BountyTargets))
			{
				item.Register();
			}
		}

		public bool Register()
		{
			string text = JsonConvert.SerializeObject((object)this);
			if (!(API_AddBountyTarget.Invoke(text)[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(this, value);
			BountyTargets.Remove(this);
			EpicLoot.logger.LogDebug("Registered bounty: " + TargetID);
			return true;
		}

		public bool Update()
		{
			if (!RunTimeRegistry.TryGetValue(this, out string value))
			{
				return false;
			}
			string text = JsonConvert.SerializeObject((object)this);
			bool flag = (bool)(API_UpdateBountyTarget.Invoke(value, text)[0] ?? ((object)false));
			EpicLoot.logger.LogDebug($"Updated bounty target: {TargetID}, {flag}");
			return flag;
		}
	}
	[Serializable]
	[PublicAPI]
	public class RecipeRequirement
	{
		public string item;

		public int amount;

		public RecipeRequirement(string item, int amount = 1)
		{
			this.item = item;
			this.amount = amount;
		}
	}
	internal static class RecipeApi
	{
		internal const string Obsolete = "Epic Loot removed recipes.json in 0.13.0 and no longer ships a recipe config, so this no longer has anywhere to register into. Add recipes with Jotunn's ItemManager instead.";
	}
	[Serializable]
	[PublicAPI]
	[Obsolete("Epic Loot removed recipes.json in 0.13.0 and no longer ships a recipe config, so this no longer has anywhere to register into. Add recipes with Jotunn's ItemManager instead.")]
	public class CustomRecipe
	{
		public string name = "";

		public string item = "";

		public int amount;

		public string craftingStation = "";

		public int minStationLevel = 1;

		public bool enabled = true;

		public string repairStation = "";

		public List<RecipeRequirement> resources = new List<RecipeRequirement>();

		internal static readonly List<CustomRecipe> Recipes = new List<CustomRecipe>();

		internal static readonly Method API_AddRecipe = new Method("AddRecipe");

		public CustomRecipe(string name, string item, CraftingTable craftingTable, int amount = 1)
		{
			this.name = name;
			this.item = item;
			this.amount = amount;
			craftingStation = craftingTable.GetInternalName();
			Recipes.Add(this);
		}

		public CustomRecipe()
		{
		}

		[PublicAPI]
		[Obsolete("Epic Loot removed recipes.json in 0.13.0 and no longer ships a recipe config, so this no longer has anywhere to register into. Add recipes with Jotunn's ItemManager instead.")]
		public static void RegisterAll()
		{
			foreach (CustomRecipe item in new List<CustomRecipe>(Recipes))
			{
				item.Register();
			}
		}

		[Obsolete("Epic Loot removed recipes.json in 0.13.0 and no longer ships a recipe config, so this no longer has anywhere to register into. Add recipes with Jotunn's ItemManager instead.")]
		public bool Register()
		{
			string text = JsonConvert.SerializeObject((object)this);
			if (!(API_AddRecipe.Invoke(text)[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(this, value);
			Recipes.Remove(this);
			EpicLoot.logger.LogDebug("Registered recipe: " + name);
			return true;
		}
	}
	[PublicAPI]
	public enum CraftingTable
	{
		[InternalName("piece_workbench")]
		Workbench,
		[InternalName("piece_cauldron")]
		Cauldron,
		[InternalName("forge")]
		Forge,
		[InternalName("piece_artisanstation")]
		ArtisanTable,
		[InternalName("piece_stonecutter")]
		StoneCutter,
		[InternalName("piece_magetable")]
		MageTable,
		[InternalName("blackforge")]
		BlackForge,
		[InternalName("piece_preptable")]
		FoodPreparationTable,
		[InternalName("piece_MeadCauldron")]
		MeadKetill
	}
	internal class InternalName : Attribute
	{
		public readonly string internalName;

		public InternalName(string internalName)
		{
			this.internalName = internalName;
		}
	}
	[PublicAPI]
	public static class EffectType
	{
		public static string DvergerCirclet = "DvergerCirclet";

		public static string InstantMead = "InstantMead";

		public static string AutoMead = "AutoMead";

		public static string DecreaseMeadCooldown = "DecreaseMeadCooldown";

		public static string Megingjord = "Megingjord";

		public static string Wishbone = "Wishbone";

		public static string Andvaranaut = "Andvaranaut";

		public static string ModifyDamage = "ModifyDamage";

		public static string ModifyPhysicalDamage = "ModifyPhysicalDamage";

		public static string ModifyElementalDamage = "ModifyElementalDamage";

		public static string ModifyDurability = "ModifyDurability";

		public static string ModifyDrawStaminaUse = "ModifyDrawStaminaUse";

		public static string ReduceWeight = "ReduceWeight";

		public static string RemoveSpeedPenalty = "RemoveSpeedPenalty";

		public static string ModifyBlockPower = "ModifyBlockPower";

		public static string ModifyBlockForce = "ModifyBlockForce";

		public static string ModifyParry = "ModifyParry";

		public static string ModifyArmor = "ModifyArmor";

		public static string ModifyBackstab = "ModifyBackstab";

		public static string IncreaseMiningDrop = "IncreaseMiningDrop";

		public static string IncreaseTreeDrop = "IncreaseTreeDrop";

		public static string IncreaseHealth = "IncreaseHealth";

		public static string IncreaseHeatResistance = "IncreaseHeatResistance";

		public static string IncreaseStamina = "IncreaseStamina";

		public static string IncreaseEitr = "IncreaseEitr";

		public static string DecreaseForsakenCooldown = "DecreaseForsakenCooldown";

		public static string ModifyHealthRegen = "ModifyHealthRegen";

		public static string AddHealthRegen = "AddHealthRegen";

		public static string ModifyStaminaRegen = "ModifyStaminaRegen";

		public static string ModifyEitrRegen = "ModifyEitrRegen";

		public static string AddBluntDamage = "AddBluntDamage";

		public static string AddSlashingDamage = "AddSlashingDamage";

		public static string AddPiercingDamage = "AddPiercingDamage";

		public static string AddFireDamage = "AddFireDamage";

		public static string AddFrostDamage = "AddFrostDamage";

		public static string AddLightningDamage = "AddLightningDamage";

		public static string AddPoisonDamage = "AddPoisonDamage";

		public static string AddSpiritDamage = "AddSpiritDamage";

		public static string AddFireResistancePercentage = "AddFireResistancePercentage";

		public static string AddFrostResistancePercentage = "AddFrostResistancePercentage";

		public static string AddLightningResistancePercentage = "AddLightningResistancePercentage";

		public static string AddPoisonResistancePercentage = "AddPoisonResistancePercentage";

		public static string AddSpiritResistancePercentage = "AddSpiritResistancePercentage";

		public static string AddElementalResistancePercentage = "AddElementalResistancePercentage";

		public static string AddBluntResistancePercentage = "AddBluntResistancePercentage";

		public static string AddSlashingResistancePercentage = "AddSlashingResistancePercentage";

		public static string AddPiercingResistancePercentage = "AddPiercingResistancePercentage";

		public static string AddChoppingResistancePercentage = "AddChoppingResistancePercentage";

		public static string AddPhysicalResistancePercentage = "AddPhysicalResistancePercentage";

		public static string ModifyMovementSpeed = "ModifyMovementSpeed";

		public static string ModifySprintStaminaUse = "ModifySprintStaminaUse";

		public static string ModifyNoise = "ModifyNoise";

		public static string ModifyBuildDistance = "ModifyBuildDistance";

		public static string ModifyPickupRange = "ModifyPickupRange";

		public static string ModifyMagicFireRate = "ModifyMagicFireRate";

		public static string AmmoConservation = "AmmoConservation";

		public static string ModifyProjectileSpeed = "ModifyProjectileSpeed";

		public static string ModifyDodgeStaminaUse = "ModifyDodgeStaminaUse";

		public static string ModifyJumpStaminaUse = "ModifyJumpStaminaUse";

		public static string ModifyAttackStaminaUse = "ModifyAttackStaminaUse";

		public static string ModifyAttackEitrUse = "ModifyAttackEitrUse";

		public static string ModifyAttackHealthUse = "ModifyAttackHealthUse";

		public static string ModifyBlockStaminaUse = "ModifyBlockStaminaUse";

		public static string ModifySummonHealth = "ModifySummonHealth";

		public static string ModifySummonDamage = "ModifySummonDamage";

		public static string ModifyWispRange = "ModifyWispRange";

		public static string Indestructible = "Indestructible";

		public static string CoinHoarder = "CoinHoarder";

		public static string Weightless = "Weightless";

		public static string LifeSteal = "LifeSteal";

		public static string EitrLeech = "EitrLeech";

		public static string Bloodlust = "Bloodlust";

		public static string AddCarryWeight = "AddCarryWeight";

		public static string ModifyAttackSpeed = "ModifyAttackSpeed";

		public static string Throwable = "Throwable";

		public static string Waterproof = "Waterproof";

		public static string Warmth = "Warmth";

		public static string Paralyze = "Paralyze";

		public static string DoubleJump = "DoubleJump";

		public static string ExplosiveArrows = "ExplosiveArrows";

		public static string QuickDraw = "QuickDraw";

		public static string AddSwordsSkill = "AddSwordsSkill";

		public static string AddKnivesSkill = "AddKnivesSkill";

		public static string AddClubsSkill = "AddClubsSkill";

		public static string AddPolearmsSkill = "AddPolearmsSkill";

		public static string AddSpearsSkill = "AddSpearsSkill";

		public static string AddBlockingSkill = "AddBlockingSkill";

		public static string AddAxesSkill = "AddAxesSkill";

		public static string AddBowsSkill = "AddBowsSkill";

		public static string AddCrossbowsSkill = "AddCrossbowsSkill";

		public static string AddUnarmedSkill = "AddUnarmedSkill";

		public static string AddPickaxesSkill = "AddPickaxesSkill";

		public static string AddFishingSkill = "AddFishingSkill";

		public static string AddElementalMagicSkill = "AddElementalMagicSkill";

		public static string AddBloodMagicSkill = "AddBloodMagicSkill";

		public static string AddMovementSkills = "AddMovementSkills";

		public static string AddCrafterSkills = "AddCrafterSkills";

		public static string ModifyStaggerDuration = "ModifyStaggerDuration