Decompiled source of ForesightForge v1.0.0

ForesightForge.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using ValheimShared.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ForesightForge
{
	[BepInPlugin("com.drakosdj.foresightforge", "ForesightForge", "1.0.0")]
	public class ForesightForgePlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.drakosdj.foresightforge";

		public const string PluginName = "ForesightForge";

		public const string PluginVersion = "1.0.0";

		public static ConfigEntry<bool> ConfigModEnabled;

		public static ConfigEntry<UpgradeSimulator.OutcomeMode> ConfigOutcomeMode;

		public static ConfigEntry<bool> ConfigEnableAltarEffects;

		public static ConfigEntry<bool> ConfigEnableIdolTransmutation;

		public static ConfigEntry<int> ConfigIdolUpgradeRatio;

		private static bool s_serverHasMod = false;

		private static UpgradeSimulator.OutcomeMode s_serverOutcomeMode = UpgradeSimulator.OutcomeMode.Vanilla;

		private static bool s_serverEnableTransmutation = false;

		private static int s_serverRatio = 3;

		private Harmony m_harmony;

		private static MethodInfo s_updateKnownRecipesMethod = typeof(Player).GetMethod("UpdateKnownRecipesList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static FieldInfo s_knownRecipesField = AccessTools.Field(typeof(Player), "m_knownRecipes");

		public static UpgradeSimulator.OutcomeMode EffectiveOutcomeMode
		{
			get
			{
				if (ConfigModEnabled != null && !ConfigModEnabled.Value)
				{
					return UpgradeSimulator.OutcomeMode.Vanilla;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
				{
					return (ConfigOutcomeMode == null) ? UpgradeSimulator.OutcomeMode.TierScaled : ConfigOutcomeMode.Value;
				}
				if (s_serverHasMod)
				{
					return s_serverOutcomeMode;
				}
				return UpgradeSimulator.OutcomeMode.Vanilla;
			}
		}

		public static bool EffectiveEnableIdolTransmutation
		{
			get
			{
				if (ConfigModEnabled != null && !ConfigModEnabled.Value)
				{
					return false;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
				{
					return ConfigEnableIdolTransmutation != null && ConfigEnableIdolTransmutation.Value;
				}
				if (s_serverHasMod)
				{
					return s_serverEnableTransmutation;
				}
				return false;
			}
		}

		public static void CleanInvalidIdolRecipes(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)ObjectDB.instance == (Object)null || s_knownRecipesField == null)
			{
				return;
			}
			try
			{
				if (!(s_knownRecipesField.GetValue(player) is HashSet<string> hashSet) || ObjectDB.instance.m_recipes == null)
				{
					return;
				}
				for (int i = 0; i < ObjectDB.instance.m_recipes.Count; i++)
				{
					Recipe val = ObjectDB.instance.m_recipes[i];
					if (!((Object)(object)val != (Object)null) || ((Object)val).name == null || !((Object)val).name.StartsWith("Recipe_Transmute_Upgrader") || !((Object)(object)val.m_item != (Object)null) || val.m_item.m_itemData == null || val.m_item.m_itemData.m_shared == null)
					{
						continue;
					}
					string name = val.m_item.m_itemData.m_shared.m_name;
					if (val.m_resources != null && val.m_resources.Length > 0 && (Object)(object)val.m_resources[0].m_resItem != (Object)null && val.m_resources[0].m_resItem.m_itemData != null && val.m_resources[0].m_resItem.m_itemData.m_shared != null)
					{
						string name2 = val.m_resources[0].m_resItem.m_itemData.m_shared.m_name;
						if (!player.IsKnownMaterial(name2))
						{
							hashSet.Remove(name);
						}
					}
				}
			}
			catch
			{
			}
		}

		public static void SafeUpdateKnownRecipes(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			CleanInvalidIdolRecipes(player);
			if (!(s_updateKnownRecipesMethod != null))
			{
				return;
			}
			try
			{
				s_updateKnownRecipesMethod.Invoke(player, null);
			}
			catch
			{
			}
		}

		private void Awake()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			ConfigModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ModEnabled", true, "Master toggle for ForesightForge. When disabled, all features and prediction banners are turned off.");
			ConfigOutcomeMode = ((BaseUnityPlugin)this).Config.Bind<UpgradeSimulator.OutcomeMode>("Mechanics", "OutcomeMode", UpgradeSimulator.OutcomeMode.TierScaled, "Refinement failure outcome behavior. Vanilla = 100% item break on failure. TierScaled = 4-way dynamic risk vs. reward (Break/Downgrade/No Change) based on biome tier.");
			ConfigEnableAltarEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnableAltarEffects", true, "Replicates the authentic thunder, lightning, and sound effects from the world altar on /openforge.");
			ConfigEnableIdolTransmutation = ((BaseUnityPlugin)this).Config.Bind<bool>("Transmutation", "EnableIdolTransmutation", true, "Enables the Craft tab on the Altar of Potential and registers recipes allowing lower-tier Idols to be transmuted into higher-tier Idols.");
			ConfigIdolUpgradeRatio = ((BaseUnityPlugin)this).Config.Bind<int>("Transmutation", "IdolUpgradeRatio", 3, new ConfigDescription("Number of lower-tier Idols required to transmute into 1 higher-tier Idol at the Altar of Potential.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), new object[0]));
			ConfigEnableIdolTransmutation.SettingChanged += delegate
			{
				IdolRecipes.SetRecipesEnabled(EffectiveEnableIdolTransmutation);
			};
			ConfigIdolUpgradeRatio.SettingChanged += delegate
			{
				IdolRecipes.UpdateRecipeRatios(ConfigIdolUpgradeRatio.Value);
			};
			m_harmony = new Harmony("com.drakosdj.foresightforge");
			m_harmony.PatchAll();
			TerminalPatches.RegisterCommands();
			ZLog.Log((object)string.Format("[{0}] Loaded v{1} — Völva's Eye initialized. Mode: {2}, Transmutation: {3}, Ratio: {4}:1", "ForesightForge", "1.0.0", ConfigOutcomeMode.Value, ConfigEnableIdolTransmutation.Value, ConfigIdolUpgradeRatio.Value));
		}

		private void OnDestroy()
		{
			if (m_harmony != null)
			{
				m_harmony.UnpatchSelf();
			}
		}

		public static void SetServerConfig(bool serverHasMod, UpgradeSimulator.OutcomeMode mode, bool enableTransmute, int ratio)
		{
			s_serverHasMod = serverHasMod;
			s_serverOutcomeMode = mode;
			s_serverEnableTransmutation = enableTransmute;
			s_serverRatio = ratio;
			ZLog.Log((object)$"[ForesightForge] Server handshake updated: ServerHasMod={s_serverHasMod}, Mode={s_serverOutcomeMode}, Transmute={s_serverEnableTransmutation}, Ratio={s_serverRatio}:1");
			IdolRecipes.SetRecipesEnabled(EffectiveEnableIdolTransmutation);
			IdolRecipes.UpdateRecipeRatios(s_serverRatio);
		}
	}
	[HarmonyPatch(typeof(Game))]
	public static class GameNetworkingPatches
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void Game_Start()
		{
			try
			{
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.Register<int, bool, int>("ForesightForge_SyncConfig", (Action<long, int, bool, int>)RPC_SyncConfig);
				}
			}
			catch (Exception arg)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Failed to register ZRoutedRpc: {arg}");
			}
		}

		public static void RPC_SyncConfig(long sender, int mode, bool enableTransmute, int ratio)
		{
			ForesightForgePlugin.SetServerConfig(serverHasMod: true, (UpgradeSimulator.OutcomeMode)mode, enableTransmute, ratio);
		}
	}
	[HarmonyPatch(typeof(ZNet))]
	public static class ZNetNetworkingPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnNewConnection")]
		public static void OnNewConnection_Postfix(ZNet __instance, ZNetPeer peer)
		{
			try
			{
				if ((Object)(object)__instance != (Object)null && __instance.IsServer() && peer != null && ZRoutedRpc.instance != null)
				{
					int num = (int)((ForesightForgePlugin.ConfigOutcomeMode == null) ? UpgradeSimulator.OutcomeMode.TierScaled : ForesightForgePlugin.ConfigOutcomeMode.Value);
					bool flag = ForesightForgePlugin.ConfigEnableIdolTransmutation != null && ForesightForgePlugin.ConfigEnableIdolTransmutation.Value;
					int num2 = ((ForesightForgePlugin.ConfigIdolUpgradeRatio != null) ? ForesightForgePlugin.ConfigIdolUpgradeRatio.Value : 3);
					ZRoutedRpc.instance.InvokeRoutedRPC(peer.m_uid, "ForesightForge_SyncConfig", new object[3] { num, flag, num2 });
				}
			}
			catch (Exception arg)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Failed to send server config: {arg}");
			}
		}

		[HarmonyPatch("Shutdown")]
		[HarmonyPostfix]
		public static void Shutdown_Postfix()
		{
			ForesightForgePlugin.SetServerConfig(serverHasMod: false, UpgradeSimulator.OutcomeMode.Vanilla, enableTransmute: false, 3);
		}
	}
	[HarmonyPatch(typeof(InventoryGui))]
	public static class InventoryGuiPatches
	{
		private static FieldInfo s_selectedRecipeField = typeof(InventoryGui).GetField("m_selectedRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static MethodInfo s_updateCraftingPanelMethod = typeof(InventoryGui).GetMethod("UpdateCraftingPanel", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static MethodInfo s_cheatUtilsMethod = null;

		public static void GetSelectedRecipeAndItem(InventoryGui gui, out Recipe recipe, out ItemData upgradeItem)
		{
			recipe = null;
			upgradeItem = null;
			if ((Object)(object)gui == (Object)null || s_selectedRecipeField == null)
			{
				return;
			}
			object value = s_selectedRecipeField.GetValue(gui);
			if (value != null)
			{
				Type type = value.GetType();
				PropertyInfo property = type.GetProperty("Recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				PropertyInfo property2 = type.GetProperty("ItemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null)
				{
					object? value2 = property.GetValue(value, null);
					recipe = (Recipe)((value2 is Recipe) ? value2 : null);
				}
				if (property2 != null)
				{
					object? value3 = property2.GetValue(value, null);
					upgradeItem = (ItemData)((value3 is ItemData) ? value3 : null);
				}
			}
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(InventoryGui __instance)
		{
			try
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					VolvaEyeBanner.Initialize(__instance);
				}
			}
			catch (Exception arg)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Failed to initialize VolvaEyeBanner: {arg}");
			}
		}

		[HarmonyPatch("CanRepair")]
		[HarmonyPrefix]
		public static bool CanRepair_Prefix(ref bool __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
				if ((Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader)
				{
					__result = false;
					return false;
				}
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("AddRecipeToList")]
		public static bool AddRecipeToList_Prefix(Player player, Recipe recipe, ItemData item, bool canCraft)
		{
			if ((Object)(object)player != (Object)null)
			{
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				bool flag = ((Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item != (Object)null && (((Object)recipe.m_item).name.StartsWith("Upgrader") || ((Object)(object)((Component)recipe.m_item).gameObject != (Object)null && ((Object)((Component)recipe.m_item).gameObject).name.StartsWith("Upgrader")))) || ((Object)(object)recipe != (Object)null && ((Object)recipe).name != null && ((Object)recipe).name.StartsWith("Recipe_Transmute_Upgrader"));
				if ((Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader)
				{
					if (item == null)
					{
						if (!flag)
						{
							return false;
						}
						if ((Object)(object)recipe != (Object)null && recipe.m_resources != null && recipe.m_resources.Length > 0 && (Object)(object)recipe.m_resources[0].m_resItem != (Object)null && recipe.m_resources[0].m_resItem.m_itemData != null && recipe.m_resources[0].m_resItem.m_itemData.m_shared != null)
						{
							string name = recipe.m_resources[0].m_resItem.m_itemData.m_shared.m_name;
							if (!player.IsKnownMaterial(name))
							{
								return false;
							}
						}
					}
				}
				else if (flag)
				{
					return false;
				}
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateRecipe")]
		public static void UpdateRecipe_Postfix(InventoryGui __instance, Player player, float dt)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null)
				{
					return;
				}
				if (ForesightForgePlugin.ConfigModEnabled != null && !ForesightForgePlugin.ConfigModEnabled.Value)
				{
					if ((Object)(object)VolvaEyeBanner.Instance != (Object)null)
					{
						VolvaEyeBanner.Instance.SetVisible(visible: false);
					}
					return;
				}
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				bool flag = (Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader;
				GetSelectedRecipeAndItem(__instance, out var recipe, out var upgradeItem);
				if (!flag || upgradeItem == null || (Object)(object)recipe == (Object)null)
				{
					if ((Object)(object)VolvaEyeBanner.Instance != (Object)null)
					{
						VolvaEyeBanner.Instance.SetVisible(visible: false);
					}
					return;
				}
				UpgradeSimulator.OutcomeMode effectiveOutcomeMode = ForesightForgePlugin.EffectiveOutcomeMode;
				UpgradeSimulator.Prediction prediction = UpgradeSimulator.Predict(player, recipe, upgradeItem, 25, effectiveOutcomeMode);
				if ((Object)(object)VolvaEyeBanner.Instance != (Object)null)
				{
					VolvaEyeBanner.Instance.UpdateDisplay(prediction, upgradeItem.m_shared.m_name);
				}
				if (!((Object)(object)__instance.m_itemCraftType != (Object)null))
				{
					return;
				}
				((Component)__instance.m_itemCraftType).gameObject.SetActive(true);
				if (prediction.SuccessCount > 0)
				{
					string arg = ((prediction.SuccessCount > 1) ? "s" : "");
					if (effectiveOutcomeMode == UpgradeSimulator.OutcomeMode.TierScaled)
					{
						if (prediction.NextFailure == UpgradeSimulator.NextFailureType.NoChange)
						{
							__instance.m_itemCraftType.text = $"<color=#55FF55><b>Völva's Eye:</b> Sees <b>{prediction.SuccessCount}</b> upgrade{arg}! <color=#70C0FF>(Next failure will RESIST safely)</color></color>";
						}
						else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.Downgrade)
						{
							__instance.m_itemCraftType.text = $"<color=#55FF55><b>Völva's Eye:</b> Sees <b>{prediction.SuccessCount}</b> upgrade{arg}! <color=#FFAA00>(Caution: Will DOWNGRADE on failure)</color></color>";
						}
						else
						{
							__instance.m_itemCraftType.text = $"<color=#55FF55><b>Völva's Eye:</b> Sees <b>{prediction.SuccessCount}</b> upgrade{arg}! <color=#FF4444>(Warning: Will SHATTER on failure)</color></color>";
						}
					}
					else
					{
						__instance.m_itemCraftType.text = $"<color=#55FF55><b>Völva's Eye:</b> Sees <b>{prediction.SuccessCount}</b> upgrade{arg} in this item's future!</color>";
					}
				}
				else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.NoChange)
				{
					__instance.m_itemCraftType.text = "<color=#70C0FF><b>Völva's Eye:</b> The thread holds firm! 0 upgrades (Will <b>RESIST / NO CHANGE</b>)</color>";
				}
				else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.Downgrade)
				{
					__instance.m_itemCraftType.text = "<color=#FFAA00><b>Völva's Eye:</b> The thread frays! 0 upgrades remaining (Will <b>DOWNGRADE</b>)</color>";
				}
				else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.Break)
				{
					__instance.m_itemCraftType.text = "<color=#FF3333><b>Völva's Eye:</b> Doom awaits! Item will <b>SHATTER</b> on next attempt!</color>";
				}
			}
			catch (Exception arg2)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Error in UpdateRecipe_Postfix: {arg2}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Hide")]
		public static void Hide_Postfix()
		{
			try
			{
				if ((Object)(object)VolvaEyeBanner.Instance != (Object)null)
				{
					VolvaEyeBanner.Instance.SetVisible(visible: false);
				}
			}
			catch
			{
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("DoCrafting")]
		public static bool DoCrafting_Prefix(InventoryGui __instance, Player player)
		{
			if (ForesightForgePlugin.ConfigModEnabled != null && !ForesightForgePlugin.ConfigModEnabled.Value)
			{
				return true;
			}
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation == (Object)null || !currentCraftingStation.m_upgrader)
			{
				return true;
			}
			GetSelectedRecipeAndItem(__instance, out var recipe, out var upgradeItem);
			if (upgradeItem == null)
			{
				if ((Object)(object)recipe != (Object)null && ((Object)recipe).name != null && ((Object)recipe).name.StartsWith("Recipe_Transmute_Upgrader"))
				{
					ExecuteIdolTransmutation(__instance, player, currentCraftingStation, recipe);
					return false;
				}
				return true;
			}
			UpgradeSimulator.OutcomeMode effectiveOutcomeMode = ForesightForgePlugin.EffectiveOutcomeMode;
			if (effectiveOutcomeMode != UpgradeSimulator.OutcomeMode.TierScaled)
			{
				return true;
			}
			if ((Object)(object)recipe == (Object)null)
			{
				return true;
			}
			int num = upgradeItem.m_quality + 1;
			if (!player.HaveRequirements(recipe, false, num, 1) && !player.NoCostCheat() && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25))
			{
				return true;
			}
			ItemDrop val = null;
			if (recipe.m_resources != null)
			{
				for (int i = 0; i < recipe.m_resources.Length; i++)
				{
					Requirement val2 = recipe.m_resources[i];
					if (val2 != null && val2.m_upgraderResource && (Object)(object)val2.m_resItem != (Object)null)
					{
						val = val2.m_resItem;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null || val.m_itemData == null || val.m_itemData.m_shared == null)
			{
				return true;
			}
			ItemData itemData = val.m_itemData;
			int idolTier = UpgradeSimulator.GetIdolTier(val);
			ExecuteTierScaledRefinement(__instance, player, currentCraftingStation, recipe, upgradeItem, itemData, idolTier, num);
			return false;
		}

		private static void ExecuteIdolTransmutation(InventoryGui gui, Player player, CraftingStation station, Recipe recipe)
		{
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || recipe.m_resources == null || recipe.m_resources.Length == 0)
			{
				return;
			}
			Requirement val = recipe.m_resources[0];
			if (val == null || (Object)(object)val.m_resItem == (Object)null)
			{
				return;
			}
			int amount = val.m_amount;
			string text = ((val.m_resItem.m_itemData != null && val.m_resItem.m_itemData.m_shared != null) ? val.m_resItem.m_itemData.m_shared.m_name : ((Object)val.m_resItem).name);
			string text2 = (((Object)(object)((Component)val.m_resItem).gameObject != (Object)null) ? ((Object)((Component)val.m_resItem).gameObject).name : ((Object)val.m_resItem).name);
			if (!player.NoCostCheat() && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25))
			{
				int num = ((Humanoid)player).GetInventory().CountItems(text, -1, false);
				if (num < amount)
				{
					num = Math.Max(num, ((Humanoid)player).GetInventory().CountItems(text2, -1, false));
				}
				if (num < amount)
				{
					((Character)player).Message((MessageType)2, "$msg_missingrequirement", 0, (Sprite)null, false);
					return;
				}
				((Humanoid)player).GetInventory().RemoveItem(text, amount, -1, false);
			}
			string text3 = (((Object)(object)((Component)recipe.m_item).gameObject != (Object)null) ? ((Object)((Component)recipe.m_item).gameObject).name : ((Object)recipe.m_item).name);
			((Humanoid)player).GetInventory().AddItem(text3, recipe.m_amount, 1, 0, player.GetPlayerID(), player.GetPlayerName(), new Vector2i(-1, -1), false, false, false);
			if ((Object)(object)station != (Object)null && station.m_craftItemDoneEffects != null)
			{
				station.m_craftItemDoneEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			else if ((Object)(object)station != (Object)null && station.m_craftItemEffects != null)
			{
				station.m_craftItemEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			string text4 = ((recipe.m_item.m_itemData != null && recipe.m_item.m_itemData.m_shared != null) ? recipe.m_item.m_itemData.m_shared.m_name : ((Object)recipe.m_item).name);
			string arg = ((Localization.instance != null) ? Localization.instance.Localize(text4) : text4);
			((Character)player).Message((MessageType)2, $"Transmuted {arg}", 0, (Sprite)null, true);
			if (s_updateCraftingPanelMethod != null)
			{
				s_updateCraftingPanelMethod.Invoke(gui, new object[1] { false });
			}
		}

		private static void ExecuteTierScaledRefinement(InventoryGui gui, Player player, CraftingStation station, Recipe recipe, ItemData upgradeItem, ItemData idolData, int idolTier, int targetQuality)
		{
			//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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_0566: Unknown result type (might be due to invalid IL or missing references)
			string text = (((Object)(object)recipe.m_item != (Object)null) ? ((Object)((Component)recipe.m_item).gameObject).name : "");
			int num = StringExtensionMethods.GetStableHashCode(text) + targetQuality;
			string text2 = (((Object)(object)upgradeItem.m_dropPrefab != (Object)null) ? ((Object)upgradeItem.m_dropPrefab).name : ((Object)recipe.m_item).name);
			int quality = upgradeItem.m_quality;
			int variant = upgradeItem.m_variant;
			float durability = upgradeItem.m_durability;
			Vector2i gridPos = upgradeItem.m_gridPos;
			bool equipped = upgradeItem.m_equipped;
			Dictionary<string, string> dictionary = ((upgradeItem.m_customData != null) ? new Dictionary<string, string>(upgradeItem.m_customData) : null);
			long crafterID = upgradeItem.m_crafterID;
			string crafterName = upgradeItem.m_crafterName;
			player.ConsumeResources(recipe.m_resources, targetQuality, 1, 1);
			((Humanoid)player).GetInventory().RemoveItem(upgradeItem);
			float itemUpgradeChance = player.GetItemUpgradeChance(num);
			float upgradeChance = idolData.m_shared.m_upgradeChance;
			float breakChance = idolData.m_shared.m_breakChance;
			if (itemUpgradeChance <= upgradeChance)
			{
				ItemData val = ((Humanoid)player).GetInventory().AddItem(text2, 1, targetQuality, variant, crafterID, crafterName, gridPos, equipped, false, false);
				if (val != null)
				{
					val.m_durability = val.GetMaxDurability();
					if (dictionary != null)
					{
						val.m_customData = dictionary;
					}
				}
				if (station.m_craftItemDoneEffects != null)
				{
					station.m_craftItemDoneEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				}
				string name = recipe.m_item.m_itemData.m_shared.m_name;
				string text3 = ((Localization.instance != null) ? Localization.instance.Localize(name) : name);
				((Character)player).Message((MessageType)2, (Localization.instance != null) ? Localization.instance.Localize("$msg_upgrader_success", new string[2]
				{
					text3,
					targetQuality.ToString()
				}) : $"{text3} refined successfully to level {targetQuality}", 0, (Sprite)null, true);
				ZLog.Log((object)$"Upgrader <color=yellow>succeeded</color> on {text3} level {targetQuality}!");
			}
			else
			{
				UpgradeSimulator.NextFailureType nextFailureType = UpgradeSimulator.EvaluateFailure(itemUpgradeChance, upgradeChance, breakChance, idolTier, UpgradeSimulator.OutcomeMode.TierScaled);
				if (station.m_craftItemDoneFailEffects != null)
				{
					station.m_craftItemDoneFailEffects.Create(((Component)station).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				}
				string name = recipe.m_item.m_itemData.m_shared.m_name;
				string text3 = ((Localization.instance != null) ? Localization.instance.Localize(name) : name);
				switch (nextFailureType)
				{
				case UpgradeSimulator.NextFailureType.NoChange:
				{
					ItemData val3 = ((Humanoid)player).GetInventory().AddItem(text2, 1, quality, variant, crafterID, crafterName, gridPos, equipped, false, false);
					if (val3 != null)
					{
						val3.m_durability = durability;
						if (dictionary != null)
						{
							val3.m_customData = dictionary;
						}
					}
					((Character)player).Message((MessageType)2, $"Refining of {text3} was unstable, but the item held firm (level unchanged)", 0, (Sprite)null, true);
					string text4 = $"<color=#70C0FF>Upgrader UNSTABLE on {text3} level {quality}, no change in quality!</color>";
					ZLog.Log((object)text4);
					if ((Object)(object)Chat.instance != (Object)null)
					{
						((Terminal)Chat.instance).AddString(text4);
					}
					break;
				}
				case UpgradeSimulator.NextFailureType.Downgrade:
				{
					int num3 = Mathf.Max(1, targetQuality - 2);
					ItemData val4 = ((Humanoid)player).GetInventory().AddItem(text2, 1, num3, variant, crafterID, crafterName, gridPos, equipped, false, false);
					if (val4 != null)
					{
						val4.m_durability = val4.GetMaxDurability();
						if (dictionary != null)
						{
							val4.m_customData = dictionary;
						}
					}
					((Character)player).Message((MessageType)2, (Localization.instance != null) ? Localization.instance.Localize("$msg_upgrader_failed", new string[2]
					{
						text3,
						num3.ToString()
					}) : $"Refining of {text3} failed, downgraded to level {num3}", 0, (Sprite)null, true);
					ZLog.Log((object)$"Upgrader <color=orange>FAILED</color> {text3} level {quality}, level was reduced!");
					break;
				}
				default:
				{
					((Character)player).Message((MessageType)2, (Localization.instance != null) ? Localization.instance.Localize("$msg_upgrader_broke", new string[2]
					{
						text3,
						quality.ToString()
					}) : $"{text3} refinement failed and broke on level {quality}", 0, (Sprite)null, true);
					ZLog.Log((object)$"Upgrader <color=red>BROKE</color> {text3} level {quality} and was destroyed!");
					float breakReturnIngreientsAmount = idolData.m_shared.m_breakReturnIngreientsAmount;
					if (!(breakReturnIngreientsAmount > 0f) || recipe.m_resources == null)
					{
						break;
					}
					for (int i = 0; i < recipe.m_resources.Length; i++)
					{
						Requirement val2 = recipe.m_resources[i];
						if (val2 != null && val2.m_recover && (Object)(object)val2.m_resItem != (Object)null)
						{
							int num2 = Mathf.CeilToInt((float)(val2.GetAmount(1) + val2.GetAmount(quality)) * breakReturnIngreientsAmount);
							if (num2 > 0)
							{
								((Humanoid)player).GetInventory().AddItem(((Object)val2.m_resItem).name, num2, 1, 0, player.GetPlayerID(), player.GetPlayerName(), new Vector2i(-1, -1), false, false, false);
							}
						}
					}
					break;
				}
				}
			}
			if (s_updateCraftingPanelMethod != null)
			{
				s_updateCraftingPanelMethod.Invoke(gui, new object[1] { false });
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch("DoCrafting")]
		public static IEnumerable<CodeInstruction> DoCrafting_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGuiPatches), "SafeStationIsCheated", (Type[])null, (Type[])null);
			for (int i = 0; i < list.Count - 3; i++)
			{
				if (list[i].opcode == OpCodes.Callvirt && list[i].operand != null && list[i].operand.ToString().Contains("GetComponent") && list[i + 1].opcode == OpCodes.Callvirt && list[i + 1].operand != null && list[i + 1].operand.ToString().Contains("GetZDO"))
				{
					list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo);
					list[i + 1] = new CodeInstruction(OpCodes.Nop, (object)null);
					list[i + 2] = new CodeInstruction(OpCodes.Nop, (object)null);
					break;
				}
			}
			return list;
		}

		public static bool SafeStationIsCheated(CraftingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return false;
			}
			ZNetView component = ((Component)station).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			ZDO zDO = component.GetZDO();
			if (zDO == null)
			{
				return false;
			}
			if (s_cheatUtilsMethod == null)
			{
				Type type = typeof(CraftingStation).Assembly.GetType("CheatUtils");
				if (type != null)
				{
					s_cheatUtilsMethod = AccessTools.Method(type, "IsCheated", new Type[1] { typeof(ZDO) }, (Type[])null);
				}
			}
			if (s_cheatUtilsMethod != null)
			{
				try
				{
					return (bool)s_cheatUtilsMethod.Invoke(null, new object[1] { zDO });
				}
				catch
				{
				}
			}
			return false;
		}

		[HarmonyPatch("DoCrafting")]
		[HarmonyPostfix]
		public static void DoCrafting_Postfix(InventoryGui __instance, Player player)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null)
				{
					return;
				}
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				GetSelectedRecipeAndItem(__instance, out var recipe, out var upgradeItem);
				if ((Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader && upgradeItem != null && (Object)(object)recipe != (Object)null)
				{
					UpgradeSimulator.OutcomeMode effectiveOutcomeMode = ForesightForgePlugin.EffectiveOutcomeMode;
					UpgradeSimulator.Prediction prediction = UpgradeSimulator.Predict(player, recipe, upgradeItem, 25, effectiveOutcomeMode);
					if ((Object)(object)VolvaEyeBanner.Instance != (Object)null)
					{
						VolvaEyeBanner.Instance.UpdateDisplay(prediction, upgradeItem.m_shared.m_name);
					}
				}
			}
			catch (Exception arg)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Error in DoCrafting_Postfix: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	public static class TerminalPatches
	{
		private static bool s_commandsInitialized = false;

		private static FieldInfo s_commandsField = typeof(Terminal).GetField("commands", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

		private static CraftingStation s_dummyUpgraderStation = null;

		public static void OpenForgeInterface()
		{
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, "Must be in-game to open Forge of Potential.", 0, (Sprite)null, false, true);
				}
				return;
			}
			if ((Object)(object)s_dummyUpgraderStation == (Object)null)
			{
				GameObject val = new GameObject("_ForesightVirtualForge");
				Object.DontDestroyOnLoad((Object)(object)val);
				val.transform.position = ((Component)localPlayer).transform.position;
				s_dummyUpgraderStation = val.AddComponent<CraftingStation>();
				s_dummyUpgraderStation.m_name = "$piece_upgradestation";
				s_dummyUpgraderStation.m_upgrader = true;
				s_dummyUpgraderStation.m_hasCraftTab = ForesightForgePlugin.EffectiveEnableIdolTransmutation;
				s_dummyUpgraderStation.m_showBasicRecipies = false;
				s_dummyUpgraderStation.m_canRepair = false;
				s_dummyUpgraderStation.m_useDistance = 999f;
				s_dummyUpgraderStation.m_rangeBuild = 0f;
				s_dummyUpgraderStation.m_discoverRange = 0f;
				s_dummyUpgraderStation.m_craftRequireRoof = false;
				s_dummyUpgraderStation.m_craftRequireFire = false;
				bool flag = false;
				if (ForesightForgePlugin.ConfigEnableAltarEffects != null && ForesightForgePlugin.ConfigEnableAltarEffects.Value && (Object)(object)ZNetScene.instance != (Object)null)
				{
					GameObject prefab = ZNetScene.instance.GetPrefab("piece_upgradestation");
					if ((Object)(object)prefab != (Object)null)
					{
						CraftingStation component = prefab.GetComponent<CraftingStation>();
						if ((Object)(object)component != (Object)null)
						{
							s_dummyUpgraderStation.m_craftItemEffects = component.m_craftItemEffects;
							s_dummyUpgraderStation.m_craftItemDoneEffects = component.m_craftItemDoneEffects;
							s_dummyUpgraderStation.m_craftItemDoneFailEffects = component.m_craftItemDoneFailEffects;
							flag = true;
						}
					}
				}
				if (!flag)
				{
					s_dummyUpgraderStation.m_craftItemEffects = new EffectList();
					s_dummyUpgraderStation.m_craftItemDoneEffects = new EffectList();
					s_dummyUpgraderStation.m_craftItemDoneFailEffects = new EffectList();
				}
			}
			else
			{
				((Component)s_dummyUpgraderStation).transform.position = ((Component)localPlayer).transform.position;
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				IdolRecipes.RegisterAllRecipes(ObjectDB.instance);
			}
			localPlayer.SetCraftingStation(s_dummyUpgraderStation);
			ForesightForgePlugin.SafeUpdateKnownRecipes(localPlayer);
			if ((Object)(object)InventoryGui.instance != (Object)null)
			{
				InventoryGui.instance.Show((Container)null, 3);
			}
		}

		public static int ExecuteSpawnIdols(Player player, int count)
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			string[] array = new string[16]
			{
				"Upgrader0Weapon", "Upgrader1Weapon", "Upgrader2Weapon", "Upgrader3Weapon", "Upgrader4Weapon", "Upgrader5Weapon", "Upgrader6Weapon", "Upgrader7Weapon", "Upgrader0Armor", "Upgrader1Armor",
				"Upgrader2Armor", "Upgrader3Armor", "Upgrader4Armor", "Upgrader5Armor", "Upgrader6Armor", "Upgrader7Armor"
			};
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(array[i]) : null);
				if ((Object)(object)val != (Object)null)
				{
					ItemDrop component = val.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null && component.m_itemData != null)
					{
						player.AddKnownItem(component.m_itemData);
					}
					((Humanoid)player).GetInventory().AddItem(array[i], count, 1, 0, player.GetPlayerID(), player.GetPlayerName(), new Vector2i(-1, -1), false, false, false);
					num += count;
				}
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				IdolRecipes.RegisterAllRecipes(ObjectDB.instance);
			}
			ForesightForgePlugin.SafeUpdateKnownRecipes(player);
			return num;
		}

		public static void RegisterCommands()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Expected O, but got Unknown
			if (s_commandsInitialized)
			{
				return;
			}
			try
			{
				Dictionary<string, ConsoleCommand> dictionary = null;
				if (s_commandsField != null)
				{
					dictionary = s_commandsField.GetValue(null) as Dictionary<string, ConsoleCommand>;
				}
				if (dictionary != null && !dictionary.ContainsKey("openforge"))
				{
					new ConsoleCommand("openforge", "Opens the Forge of Potential upgrade interface directly (requires debugmode).", (ConsoleEvent)delegate(ConsoleEventArgs args)
					{
						if (!Player.m_debugMode)
						{
							args.Context.AddString("<color=red>The openforge command requires debugmode to be active.</color>");
						}
						else
						{
							OpenForgeInterface();
							args.Context.AddString("Opened Forge of Potential interface.");
						}
					}, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				if (dictionary != null && !dictionary.ContainsKey("openupgrader"))
				{
					new ConsoleCommand("openupgrader", "Opens the Forge of Potential upgrade interface directly (requires debugmode).", (ConsoleEvent)delegate(ConsoleEventArgs args)
					{
						if (!Player.m_debugMode)
						{
							args.Context.AddString("<color=red>The openupgrader command requires debugmode to be active.</color>");
						}
						else
						{
							OpenForgeInterface();
							args.Context.AddString("Opened Forge of Potential interface.");
						}
					}, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				if (dictionary != null && !dictionary.ContainsKey("resetseeds"))
				{
					new ConsoleCommand("resetseeds", "Clears all stored Forge of Potential upgrade seeds on the character (Dev Cheat, requires debugmode).", (ConsoleEvent)delegate(ConsoleEventArgs args)
					{
						if (!Player.m_debugMode)
						{
							args.Context.AddString("<color=red>The resetseeds command requires debugmode to be active.</color>");
						}
						else
						{
							Player localPlayer = Player.m_localPlayer;
							if ((Object)(object)localPlayer == (Object)null)
							{
								args.Context.AddString("No local player active.");
							}
							else
							{
								int num = UpgradeSimulator.ResetPlayerSeeds(localPlayer);
								args.Context.AddString($"ForesightForge: Cleared {num} stored upgrade seed(s).");
							}
						}
					}, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				if (dictionary != null && !dictionary.ContainsKey("resetupgradeseeds"))
				{
					new ConsoleCommand("resetupgradeseeds", "Clears all stored Forge of Potential upgrade seeds on the character (Dev Cheat, requires debugmode).", (ConsoleEvent)delegate(ConsoleEventArgs args)
					{
						if (!Player.m_debugMode)
						{
							args.Context.AddString("<color=red>The resetupgradeseeds command requires debugmode to be active.</color>");
						}
						else
						{
							Player localPlayer = Player.m_localPlayer;
							if ((Object)(object)localPlayer == (Object)null)
							{
								args.Context.AddString("No local player active.");
							}
							else
							{
								int num = UpgradeSimulator.ResetPlayerSeeds(localPlayer);
								args.Context.AddString($"ForesightForge: Cleared {num} stored upgrade seed(s).");
							}
						}
					}, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				if (dictionary != null && !dictionary.ContainsKey("listseeds"))
				{
					new ConsoleCommand("listseeds", "Lists stored Forge of Potential upgrade seeds on the character.", (ConsoleEvent)delegate(ConsoleEventArgs args)
					{
						Player localPlayer = Player.m_localPlayer;
						if ((Object)(object)localPlayer == (Object)null)
						{
							args.Context.AddString("No local player active.");
						}
						else
						{
							Dictionary<int, int> playerUpgradeSeeds = UpgradeSimulator.GetPlayerUpgradeSeeds(localPlayer);
							if (playerUpgradeSeeds != null && playerUpgradeSeeds.Count != 0)
							{
								args.Context.AddString($"Stored seeds count: {playerUpgradeSeeds.Count} (Mode: {ForesightForgePlugin.EffectiveOutcomeMode})");
								{
									foreach (KeyValuePair<int, int> item in playerUpgradeSeeds)
									{
										UpgradeSimulator.SeedInfo info = UpgradeSimulator.AnalyzeSeed(item.Key, item.Value, ForesightForgePlugin.EffectiveOutcomeMode);
										args.Context.AddString("  " + UpgradeSimulator.FormatSeedInfo(info));
									}
									return;
								}
							}
							args.Context.AddString("No stored upgrade seeds found on character.");
						}
					}, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				if (dictionary != null && !dictionary.ContainsKey("spawnidols"))
				{
					new ConsoleCommand("spawnidols", "Spawns 10 of each Battle and Protection Idol into player inventory (Dev Cheat, requires debugmode).", (ConsoleEvent)delegate(ConsoleEventArgs args)
					{
						if (!Player.m_debugMode)
						{
							args.Context.AddString("<color=red>The spawnidols command requires debugmode to be active.</color>");
						}
						else
						{
							Player localPlayer = Player.m_localPlayer;
							if ((Object)(object)localPlayer == (Object)null)
							{
								args.Context.AddString("No local player active.");
							}
							else
							{
								int result = 10;
								if (args.Length > 1)
								{
									int.TryParse(args[1], out result);
									if (result <= 0)
									{
										result = 10;
									}
								}
								int num = ExecuteSpawnIdols(localPlayer, result);
								args.Context.AddString($"<color=yellow>ForesightForge: Spawned {num} idols ({result} of each tier) into inventory.</color>");
							}
						}
					}, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				s_commandsInitialized = true;
			}
			catch (Exception arg)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Failed to register console commands: {arg}");
			}
		}

		[HarmonyPatch("InitTerminal")]
		[HarmonyPostfix]
		public static void InitTerminal_Postfix()
		{
			RegisterCommands();
		}
	}
	[HarmonyPatch(typeof(Chat))]
	public static class ChatCommandPatches
	{
		[HarmonyPatch("SendInput")]
		[HarmonyPrefix]
		public static bool SendInput_Prefix(Chat __instance)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)((Terminal)__instance).m_input == (Object)null)
			{
				return true;
			}
			string text = ((TMP_InputField)((Terminal)__instance).m_input).text;
			if (string.IsNullOrEmpty(text))
			{
				return true;
			}
			string text2 = text.Trim();
			if (text2.Equals("/openforge", StringComparison.OrdinalIgnoreCase) || text2.Equals("/openupgrader", StringComparison.OrdinalIgnoreCase) || text2.Equals("/forge", StringComparison.OrdinalIgnoreCase))
			{
				((TMP_InputField)((Terminal)__instance).m_input).text = "";
				if (!Terminal.m_cheat || !Player.m_debugMode)
				{
					if ((Object)(object)Chat.instance != (Object)null)
					{
						((Terminal)Chat.instance).AddString("<color=red>The /openforge command requires devcommands and debugmode to be enabled.</color>");
					}
					return false;
				}
				TerminalPatches.OpenForgeInterface();
				return false;
			}
			if (text2.Equals("/resetseeds", StringComparison.OrdinalIgnoreCase) || text2.Equals("/resetupgradeseeds", StringComparison.OrdinalIgnoreCase))
			{
				((TMP_InputField)((Terminal)__instance).m_input).text = "";
				if (!Terminal.m_cheat || !Player.m_debugMode)
				{
					if ((Object)(object)Chat.instance != (Object)null)
					{
						((Terminal)Chat.instance).AddString("<color=red>The /resetseeds command requires devcommands and debugmode to be enabled.</color>");
					}
					return false;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					int num = UpgradeSimulator.ResetPlayerSeeds(localPlayer);
					if ((Object)(object)Chat.instance != (Object)null)
					{
						((Terminal)Chat.instance).AddString($"<color=yellow>ForesightForge: Cleared {num} stored upgrade seed(s).</color>");
					}
				}
				return false;
			}
			if (text2.StartsWith("/spawnidols", StringComparison.OrdinalIgnoreCase))
			{
				((TMP_InputField)((Terminal)__instance).m_input).text = "";
				if (!Terminal.m_cheat || !Player.m_debugMode)
				{
					if ((Object)(object)Chat.instance != (Object)null)
					{
						((Terminal)Chat.instance).AddString("<color=red>The /spawnidols command requires devcommands and debugmode to be enabled.</color>");
					}
					return false;
				}
				string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
				int result = 10;
				if (array.Length > 1)
				{
					int.TryParse(array[1], out result);
					if (result <= 0)
					{
						result = 10;
					}
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					int num2 = TerminalPatches.ExecuteSpawnIdols(localPlayer, result);
					if ((Object)(object)Chat.instance != (Object)null)
					{
						((Terminal)Chat.instance).AddString($"<color=yellow>ForesightForge: Spawned {num2} idols ({result} of each tier) into inventory.</color>");
					}
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CraftingStation))]
	public static class CraftingStationSafetyPatches
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void Start_Postfix(CraftingStation __instance)
		{
			if ((Object)(object)__instance != (Object)null && __instance.m_upgrader)
			{
				__instance.m_hasCraftTab = ForesightForgePlugin.EffectiveEnableIdolTransmutation;
				__instance.m_showBasicRecipies = false;
				__instance.m_canRepair = false;
			}
		}

		[HarmonyPatch("Interact")]
		[HarmonyPrefix]
		public static void Interact_Prefix(CraftingStation __instance, Humanoid user)
		{
			if ((Object)(object)__instance != (Object)null && __instance.m_upgrader)
			{
				__instance.m_hasCraftTab = ForesightForgePlugin.EffectiveEnableIdolTransmutation;
				__instance.m_showBasicRecipies = false;
				__instance.m_canRepair = false;
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					IdolRecipes.RegisterAllRecipes(ObjectDB.instance);
				}
				Player val = (Player)(object)((user is Player) ? user : null);
				if ((Object)(object)val != (Object)null)
				{
					ForesightForgePlugin.SafeUpdateKnownRecipes(val);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("CheckUsable")]
		public static bool CheckUsable_Prefix(CraftingStation __instance, ref bool __result)
		{
			if ((Object)(object)__instance != (Object)null && __instance.m_upgrader)
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetExtentionCount")]
		public static bool GetExtentionCount_Prefix(CraftingStation __instance, ref int __result)
		{
			if ((Object)(object)__instance != (Object)null && __instance.m_upgrader)
			{
				__result = 0;
				return false;
			}
			return true;
		}

		[HarmonyPatch("InUseDistance")]
		[HarmonyPrefix]
		public static bool InUseDistance_Prefix(CraftingStation __instance, ref bool __result)
		{
			if ((Object)(object)__instance != (Object)null && __instance.m_upgrader)
			{
				__result = true;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player))]
	public static class PlayerStationPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("KnowStationLevel")]
		public static bool KnowStationLevel_Prefix(string name, int level, ref bool __result)
		{
			if (name == "$piece_upgradestation" || name == "_ForesightVirtualForge" || name == "piece_upgradestation")
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnSpawned")]
		public static void OnSpawned_Postfix(Player __instance)
		{
			ForesightForgePlugin.SafeUpdateKnownRecipes(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch("HaveRequirements", new Type[]
		{
			typeof(Recipe),
			typeof(bool),
			typeof(int),
			typeof(int)
		})]
		public static bool HaveRequirements_Prefix(Player __instance, Recipe recipe, bool discover, int qualityLevel, int amount, ref bool __result)
		{
			if ((Object)(object)recipe != (Object)null && ((Object)recipe).name != null && ((Object)recipe).name.StartsWith("Recipe_Transmute_Upgrader"))
			{
				if (recipe.m_resources != null && recipe.m_resources.Length > 0 && (Object)(object)recipe.m_resources[0].m_resItem != (Object)null && recipe.m_resources[0].m_resItem.m_itemData != null && recipe.m_resources[0].m_resItem.m_itemData.m_shared != null)
				{
					string name = recipe.m_resources[0].m_resItem.m_itemData.m_shared.m_name;
					if (discover)
					{
						__result = __instance.IsKnownMaterial(name);
						return false;
					}
					if (__instance.NoCostCheat() || ZoneSystem.instance.GetGlobalKey((GlobalKeys)25))
					{
						__result = true;
						return false;
					}
					int num = recipe.m_resources[0].m_amount * amount;
					int num2 = ((Humanoid)__instance).GetInventory().CountItems(name, -1, false);
					string text = (((Object)(object)((Component)recipe.m_resources[0].m_resItem).gameObject != (Object)null) ? ((Object)((Component)recipe.m_resources[0].m_resItem).gameObject).name : ((Object)recipe.m_resources[0].m_resItem).name);
					if (num2 < num)
					{
						num2 = Math.Max(num2, ((Humanoid)__instance).GetInventory().CountItems(text, -1, false));
					}
					__result = num2 >= num;
					return false;
				}
				__result = false;
				return false;
			}
			return true;
		}
	}
	public static class IdolRecipes
	{
		[HarmonyPatch(typeof(ObjectDB))]
		public static class ObjectDBPatches
		{
			[HarmonyPatch("Awake")]
			[HarmonyPostfix]
			public static void Awake_Postfix(ObjectDB __instance)
			{
				RegisterAllRecipes(__instance);
			}

			[HarmonyPatch("CopyOtherDB")]
			[HarmonyPostfix]
			public static void CopyOtherDB_Postfix(ObjectDB __instance)
			{
				RegisterAllRecipes(__instance);
			}
		}

		[HarmonyPatch(typeof(ZNetScene))]
		public static class ZNetScenePatches
		{
			[HarmonyPatch("Awake")]
			[HarmonyPostfix]
			public static void Awake_Postfix()
			{
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					RegisterAllRecipes(ObjectDB.instance);
				}
			}
		}

		private static readonly List<Recipe> s_customRecipes = new List<Recipe>();

		private static readonly string[][] WeaponProgression = new string[7][]
		{
			new string[2] { "Upgrader0Weapon", "Upgrader1Weapon" },
			new string[2] { "Upgrader1Weapon", "Upgrader2Weapon" },
			new string[2] { "Upgrader2Weapon", "Upgrader3Weapon" },
			new string[2] { "Upgrader3Weapon", "Upgrader4Weapon" },
			new string[2] { "Upgrader4Weapon", "Upgrader5Weapon" },
			new string[2] { "Upgrader5Weapon", "Upgrader6Weapon" },
			new string[2] { "Upgrader6Weapon", "Upgrader7Weapon" }
		};

		private static readonly string[][] ArmorProgression = new string[7][]
		{
			new string[2] { "Upgrader0Armor", "Upgrader1Armor" },
			new string[2] { "Upgrader1Armor", "Upgrader2Armor" },
			new string[2] { "Upgrader2Armor", "Upgrader3Armor" },
			new string[2] { "Upgrader3Armor", "Upgrader4Armor" },
			new string[2] { "Upgrader4Armor", "Upgrader5Armor" },
			new string[2] { "Upgrader5Armor", "Upgrader6Armor" },
			new string[2] { "Upgrader6Armor", "Upgrader7Armor" }
		};

		public static CraftingStation GetAltarStation()
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("piece_upgradestation");
				if ((Object)(object)prefab != (Object)null)
				{
					return prefab.GetComponent<CraftingStation>();
				}
			}
			return null;
		}

		public static void RegisterAllRecipes(ObjectDB odb)
		{
			if ((Object)(object)odb == (Object)null || odb.m_items == null || odb.m_items.Count == 0)
			{
				return;
			}
			int num = ((ForesightForgePlugin.ConfigIdolUpgradeRatio != null) ? ForesightForgePlugin.ConfigIdolUpgradeRatio.Value : 3);
			num = Mathf.Clamp(num, 1, 10);
			CraftingStation altarStation = GetAltarStation();
			if (s_customRecipes.Count == 0)
			{
				CreateAllCustomRecipes(odb, num, altarStation);
			}
			else
			{
				UpdateRecipeRatios(num);
				if ((Object)(object)altarStation != (Object)null)
				{
					for (int i = 0; i < s_customRecipes.Count; i++)
					{
						if ((Object)(object)s_customRecipes[i] != (Object)null && (Object)(object)s_customRecipes[i].m_craftingStation == (Object)null)
						{
							s_customRecipes[i].m_craftingStation = altarStation;
						}
					}
				}
			}
			int num2 = 0;
			for (int i = 0; i < s_customRecipes.Count; i++)
			{
				Recipe val = s_customRecipes[i];
				if ((Object)(object)val != (Object)null && !odb.m_recipes.Contains(val))
				{
					odb.m_recipes.Add(val);
					num2++;
				}
			}
			if (num2 > 0)
			{
				ZLog.Log((object)$"[ForesightForge] Injected {num2} Idol recipes into ObjectDB (Total in DB: {odb.m_recipes.Count}).");
			}
		}

		private static void CreateAllCustomRecipes(ObjectDB odb, int ratio, CraftingStation altarStation)
		{
			s_customRecipes.Clear();
			for (int i = 0; i < WeaponProgression.Length; i++)
			{
				string sourcePrefabName = WeaponProgression[i][0];
				string targetPrefabName = WeaponProgression[i][1];
				Recipe val = CreateIdolRecipe(odb, sourcePrefabName, targetPrefabName, ratio, altarStation);
				if ((Object)(object)val != (Object)null)
				{
					s_customRecipes.Add(val);
				}
			}
			for (int i = 0; i < ArmorProgression.Length; i++)
			{
				string sourcePrefabName = ArmorProgression[i][0];
				string targetPrefabName = ArmorProgression[i][1];
				Recipe val = CreateIdolRecipe(odb, sourcePrefabName, targetPrefabName, ratio, altarStation);
				if ((Object)(object)val != (Object)null)
				{
					s_customRecipes.Add(val);
				}
			}
			ZLog.Log((object)$"[ForesightForge] Initialized {s_customRecipes.Count} Idol transmutation recipes (Ratio: {ratio}:1).");
		}

		public static void SetRecipesEnabled(bool enabled)
		{
			for (int i = 0; i < s_customRecipes.Count; i++)
			{
				if ((Object)(object)s_customRecipes[i] != (Object)null)
				{
					s_customRecipes[i].m_enabled = enabled;
				}
			}
		}

		public static void UpdateRecipeRatios(int newRatio)
		{
			newRatio = Mathf.Clamp(newRatio, 1, 10);
			bool effectiveEnableIdolTransmutation = ForesightForgePlugin.EffectiveEnableIdolTransmutation;
			CraftingStation altarStation = GetAltarStation();
			for (int i = 0; i < s_customRecipes.Count; i++)
			{
				Recipe val = s_customRecipes[i];
				if ((Object)(object)val != (Object)null)
				{
					val.m_enabled = effectiveEnableIdolTransmutation;
					if ((Object)(object)altarStation != (Object)null && (Object)(object)val.m_craftingStation == (Object)null)
					{
						val.m_craftingStation = altarStation;
					}
					if (val.m_resources != null && val.m_resources.Length > 0)
					{
						val.m_resources[0].m_amount = newRatio;
						val.m_resources[0].m_upgraderResource = true;
					}
				}
			}
		}

		private static Recipe CreateIdolRecipe(ObjectDB odb, string sourcePrefabName, string targetPrefabName, int ratio, CraftingStation station)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			GameObject itemPrefab = odb.GetItemPrefab(sourcePrefabName);
			GameObject itemPrefab2 = odb.GetItemPrefab(targetPrefabName);
			ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			ItemDrop val2 = (((Object)(object)itemPrefab2 != (Object)null) ? itemPrefab2.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Recipe val3 = ScriptableObject.CreateInstance<Recipe>();
			((Object)val3).name = $"Recipe_Transmute_{sourcePrefabName}_to_{targetPrefabName}";
			val3.m_item = val2;
			val3.m_amount = 1;
			val3.m_enabled = ForesightForgePlugin.EffectiveEnableIdolTransmutation;
			val3.m_minStationLevel = 1;
			val3.m_craftingStation = station;
			Requirement val4 = new Requirement();
			val4.m_resItem = val;
			val4.m_amount = ratio;
			val4.m_recover = false;
			val4.m_amountPerLevel = 0;
			val4.m_upgraderResource = true;
			val3.m_resources = (Requirement[])(object)new Requirement[1] { val4 };
			return val3;
		}
	}
	public static class UpgradeSimulator
	{
		public enum OutcomeMode
		{
			Vanilla,
			TierScaled
		}

		public enum NextFailureType
		{
			None,
			NoChange,
			Downgrade,
			Break
		}

		public struct Prediction
		{
			public int SuccessCount;

			public NextFailureType NextFailure;

			public float NextRoll;

			public float UpgradeChance;

			public float BreakChance;

			public bool HasIdol;

			public int IdolTier;

			public OutcomeMode Mode;
		}

		public struct SeedInfo
		{
			public int Hash;

			public int Seed;

			public string ItemName;

			public string PrefabName;

			public int TargetQuality;

			public int GuaranteedUpgrades;

			public NextFailureType NextFailure;
		}

		private static FieldInfo s_itemUpgradeSeedsField = typeof(Player).GetField("m_itemUpgradeSeeds", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		public static Dictionary<int, int> GetPlayerUpgradeSeeds(Player player)
		{
			if ((Object)(object)player == (Object)null || s_itemUpgradeSeedsField == null)
			{
				return null;
			}
			return s_itemUpgradeSeedsField.GetValue(player) as Dictionary<int, int>;
		}

		public static int ResetPlayerSeeds(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			Dictionary<int, int> playerUpgradeSeeds = GetPlayerUpgradeSeeds(player);
			if (playerUpgradeSeeds == null)
			{
				return 0;
			}
			int count = playerUpgradeSeeds.Count;
			playerUpgradeSeeds.Clear();
			string arg = $"ForesightForge: Cleared {count} stored upgrade seed(s) for character '{player.GetPlayerName()}'.";
			ZLog.Log((object)$"[ForesightForge] {arg}");
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, $"ForesightForge: Reset {count} upgrade seed(s)!", 0, (Sprite)null, false, true);
			}
			if (InventoryGui.IsVisible() && (Object)(object)InventoryGui.instance != (Object)null)
			{
				try
				{
					MethodInfo method = typeof(InventoryGui).GetMethod("UpdateRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method != null)
					{
						method.Invoke(InventoryGui.instance, new object[2] { player, 0f });
					}
				}
				catch
				{
				}
			}
			return count;
		}

		public static int GetIdolTier(ItemDrop idol)
		{
			if ((Object)(object)idol == (Object)null)
			{
				return 0;
			}
			string text = (((Object)(object)((Component)idol).gameObject != (Object)null) ? ((Object)((Component)idol).gameObject).name : "");
			if (string.IsNullOrEmpty(text) && idol.m_itemData != null && (Object)(object)idol.m_itemData.m_dropPrefab != (Object)null)
			{
				text = ((Object)idol.m_itemData.m_dropPrefab).name;
			}
			if (text.IndexOf("Upgrader0", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 0;
			}
			if (text.IndexOf("Upgrader1", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 1;
			}
			if (text.IndexOf("Upgrader2", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 2;
			}
			if (text.IndexOf("Upgrader3", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 3;
			}
			if (text.IndexOf("Upgrader4", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 4;
			}
			if (text.IndexOf("Upgrader5", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 5;
			}
			if (text.IndexOf("Upgrader6", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 6;
			}
			if (text.IndexOf("Upgrader7", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return 7;
			}
			if (idol.m_itemData != null && idol.m_itemData.m_shared != null)
			{
				string text2 = idol.m_itemData.m_shared.m_name ?? "";
				if (text2.IndexOf("bronze", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 1;
				}
				if (text2.IndexOf("iron", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 2;
				}
				if (text2.IndexOf("silver", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 3;
				}
				if (text2.IndexOf("blackmetal", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("black metal", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 4;
				}
				if (text2.IndexOf("marble", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 5;
				}
				if (text2.IndexOf("flametal", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 6;
				}
				if (text2.IndexOf("bloodgold", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 7;
				}
			}
			return 0;
		}

		public static NextFailureType EvaluateFailure(float roll, float upgradeChance, float vanillaBreakChance, int tier, OutcomeMode mode)
		{
			if (mode == OutcomeMode.Vanilla)
			{
				if (1f - roll < vanillaBreakChance)
				{
					return NextFailureType.Break;
				}
				return NextFailureType.Downgrade;
			}
			tier = Mathf.Clamp(tier, 0, 7);
			float num = 0.05f + 0.05f * (float)tier;
			float num2 = 0.05f + 0.05f * (float)tier;
			float num3 = 0.9f - 0.1f * (float)tier;
			float num4 = Mathf.Max(0.0001f, 1f - upgradeChance);
			float num5 = Mathf.Clamp01((roll - upgradeChance) / num4);
			if (num5 < num3)
			{
				return NextFailureType.NoChange;
			}
			if (num5 < num3 + num2)
			{
				return NextFailureType.Downgrade;
			}
			return NextFailureType.Break;
		}

		public static Prediction Predict(Player player, Recipe recipe, ItemData upgradeItem, int maxLookahead)
		{
			return Predict(player, recipe, upgradeItem, maxLookahead, ForesightForgePlugin.EffectiveOutcomeMode);
		}

		public static Prediction Predict(Player player, Recipe recipe, ItemData upgradeItem, int maxLookahead, OutcomeMode mode)
		{
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			Prediction result = new Prediction
			{
				SuccessCount = 0,
				NextFailure = NextFailureType.None,
				NextRoll = 0f,
				UpgradeChance = 0.65f,
				BreakChance = 1f,
				HasIdol = false,
				IdolTier = 0,
				Mode = mode
			};
			if ((Object)(object)player == (Object)null || (Object)(object)recipe == (Object)null || upgradeItem == null)
			{
				return result;
			}
			ItemDrop val = null;
			if (recipe.m_resources != null)
			{
				for (int i = 0; i < recipe.m_resources.Length; i++)
				{
					Requirement val2 = recipe.m_resources[i];
					if (val2 != null && val2.m_upgraderResource && (Object)(object)val2.m_resItem != (Object)null)
					{
						val = val2.m_resItem;
						break;
					}
				}
			}
			if ((Object)(object)val != (Object)null && val.m_itemData != null && val.m_itemData.m_shared != null)
			{
				result.HasIdol = true;
				result.UpgradeChance = val.m_itemData.m_shared.m_upgradeChance;
				result.BreakChance = val.m_itemData.m_shared.m_breakChance;
				result.IdolTier = GetIdolTier(val);
			}
			int num = upgradeItem.m_quality + 1;
			string text = (((Object)(object)recipe.m_item != (Object)null) ? ((Object)((Component)recipe.m_item).gameObject).name : "");
			int stableHashCode = StringExtensionMethods.GetStableHashCode(text);
			Dictionary<int, int> playerUpgradeSeeds = GetPlayerUpgradeSeeds(player);
			string playerName = player.GetPlayerName();
			int stableHashCode2 = StringExtensionMethods.GetStableHashCode(playerName);
			State state = Random.state;
			try
			{
				int num2 = 0;
				bool flag = true;
				for (int j = 0; j < maxLookahead; j++)
				{
					int num3 = num + j;
					int num4 = stableHashCode + num3;
					if (playerUpgradeSeeds == null || !playerUpgradeSeeds.TryGetValue(num4, out var value))
					{
						value = stableHashCode2 + num4;
					}
					Random.InitState(value);
					float value2 = Random.value;
					if (flag)
					{
						result.NextRoll = value2;
						flag = false;
					}
					if (value2 <= result.UpgradeChance)
					{
						num2++;
						continue;
					}
					result.NextFailure = EvaluateFailure(value2, result.UpgradeChance, result.BreakChance, result.IdolTier, mode);
					break;
				}
				result.SuccessCount = num2;
				return result;
			}
			catch (Exception arg)
			{
				ZLog.LogWarning((object)$"[ForesightForge] Error during upgrade simulation: {arg}");
				return result;
			}
			finally
			{
				Random.state = state;
			}
		}

		public static SeedInfo AnalyzeSeed(int itemHash, int seed)
		{
			return AnalyzeSeed(itemHash, seed, ForesightForgePlugin.EffectiveOutcomeMode);
		}

		public static SeedInfo AnalyzeSeed(int itemHash, int seed, OutcomeMode mode)
		{
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			SeedInfo result = new SeedInfo
			{
				Hash = itemHash,
				Seed = seed,
				ItemName = "Unknown Item",
				PrefabName = "",
				TargetQuality = 0,
				GuaranteedUpgrades = 0,
				NextFailure = NextFailureType.None
			};
			int tier = 0;
			if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null)
			{
				for (int i = 0; i < ObjectDB.instance.m_items.Count; i++)
				{
					GameObject val = ObjectDB.instance.m_items[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					ItemDrop component = val.GetComponent<ItemDrop>();
					if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
					{
						continue;
					}
					int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val).name);
					int num = component.m_itemData.m_shared.m_maxQuality;
					if (num < 2)
					{
						num = 4;
					}
					for (int j = 2; j <= num + 5; j++)
					{
						if (stableHashCode + j == itemHash)
						{
							result.PrefabName = ((Object)val).name;
							result.TargetQuality = j;
							string name = component.m_itemData.m_shared.m_name;
							result.ItemName = ((Localization.instance != null) ? Localization.instance.Localize(name) : name);
							break;
						}
					}
					if (!string.IsNullOrEmpty(result.PrefabName))
					{
						break;
					}
				}
			}
			State state = Random.state;
			try
			{
				int num2 = 0;
				Player localPlayer = Player.m_localPlayer;
				string text = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : "");
				int stableHashCode2 = StringExtensionMethods.GetStableHashCode(text);
				Dictionary<int, int> dictionary = (((Object)(object)localPlayer != (Object)null) ? GetPlayerUpgradeSeeds(localPlayer) : null);
				int stableHashCode = ((!string.IsNullOrEmpty(result.PrefabName)) ? StringExtensionMethods.GetStableHashCode(result.PrefabName) : 0);
				for (int k = 0; k < 25; k++)
				{
					int value;
					if (k == 0)
					{
						value = seed;
					}
					else
					{
						if (string.IsNullOrEmpty(result.PrefabName))
						{
							break;
						}
						int num3 = result.TargetQuality + k;
						int num4 = stableHashCode + num3;
						if (dictionary == null || !dictionary.TryGetValue(num4, out value))
						{
							value = stableHashCode2 + num4;
						}
					}
					Random.InitState(value);
					float value2 = Random.value;
					if (value2 <= 0.65f)
					{
						num2++;
						continue;
					}
					result.NextFailure = EvaluateFailure(value2, 0.65f, 1f, tier, mode);
					break;
				}
				result.GuaranteedUpgrades = num2;
			}
			finally
			{
				Random.state = state;
			}
			return result;
		}

		public static string FormatSeedInfo(SeedInfo info)
		{
			string arg;
			if (info.TargetQuality <= 1)
			{
				arg = ((info.TargetQuality != 1) ? info.ItemName : $"{info.ItemName} (Lvl 1)");
			}
			else
			{
				int num = info.TargetQuality - 1;
				arg = $"{info.ItemName} (Lvl {num} -> {info.TargetQuality})";
			}
			string arg2;
			if (info.GuaranteedUpgrades <= 0)
			{
				arg2 = ((info.NextFailure == NextFailureType.NoChange) ? "0 Upgrades (Will Resist/No Change)" : ((info.NextFailure != NextFailureType.Downgrade) ? "0 Upgrades (Will Break)" : "0 Upgrades (Will Downgrade)"));
			}
			else
			{
				string arg3 = ((info.GuaranteedUpgrades > 1) ? "s" : "");
				arg2 = $"{info.GuaranteedUpgrades} Upgrade{arg3}";
			}
			return $"{info.Seed} [{arg}, {arg2}]";
		}
	}
	public class VolvaEyeBanner : MonoBehaviour
	{
		private ValheimUiBanner m_banner;

		public static VolvaEyeBanner Instance { get; private set; }

		public static void Initialize(InventoryGui gui)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null) && !((Object)(object)gui == (Object)null))
			{
				Transform val = (((Object)(object)gui.m_inventoryRoot != (Object)null) ? ((Component)gui.m_inventoryRoot).transform : ((Component)gui).transform);
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = new GameObject("VolvaEyeBanner_Holder");
					val2.transform.SetParent(val, false);
					Instance = val2.AddComponent<VolvaEyeBanner>();
					Instance.BuildUI(val);
				}
			}
		}

		private void BuildUI(Transform parent)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			m_banner = ValheimUiBuilder.CreateBanner("ForesightForge_ProphecyBanner", "-- VOLVA'S PROPHECY --", "Peering into the weave of fate...", new Vector2(520f, 88f), parent);
			RectTransform component = ((Component)m_banner).GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.anchoredPosition = new Vector2(0f, 210f);
			}
			m_banner.Hide();
		}

		public void UpdateDisplay(UpgradeSimulator.Prediction prediction, string itemName)
		{
			if ((Object)(object)m_banner == (Object)null)
			{
				return;
			}
			if (prediction.SuccessCount > 0)
			{
				string arg = ((prediction.SuccessCount > 1) ? "s" : "");
				m_banner.SetTitle("<color=#FFBA40>-- VOLVA'S PROPHECY --</color>");
				if (prediction.Mode == UpgradeSimulator.OutcomeMode.TierScaled)
				{
					if (prediction.NextFailure == UpgradeSimulator.NextFailureType.NoChange)
					{
						m_banner.SetStatus($"<color=#FFF5EA>Sees </color><color=#55FF55><b>{prediction.SuccessCount}</b></color><color=#FFF5EA> upgrade{arg}! <color=#70C0FF>(Next failure will RESIST safely)</color></color>");
					}
					else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.Downgrade)
					{
						m_banner.SetStatus($"<color=#FFF5EA>Sees </color><color=#55FF55><b>{prediction.SuccessCount}</b></color><color=#FFF5EA> upgrade{arg}! <color=#FFAA00>(Caution: Will DOWNGRADE on failure)</color></color>");
					}
					else
					{
						m_banner.SetStatus($"<color=#FFF5EA>Sees </color><color=#55FF55><b>{prediction.SuccessCount}</b></color><color=#FFF5EA> upgrade{arg}! <color=#FF4444>(Warning: Will SHATTER on failure)</color></color>");
					}
				}
				else
				{
					m_banner.SetStatus($"<color=#FFF5EA>Sees </color><color=#55FF55><b>{prediction.SuccessCount}</b></color><color=#FFF5EA> successful upgrade{arg} in this item's future!</color>");
				}
			}
			else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.NoChange)
			{
				m_banner.SetTitle("<color=#FFBA40>-- VOLVA'S EYE : </color><color=#70C0FF>RESISTANCE</color><color=#FFBA40> --</color>");
				m_banner.SetStatus("<color=#FFF5EA>The thread holds firm! 0 upgrades (Will </color><color=#70C0FF><b>RESIST / NO CHANGE</b></color><color=#FFF5EA>)</color>");
			}
			else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.Downgrade)
			{
				m_banner.SetTitle("<color=#FFBA40>-- VOLVA'S EYE : </color><color=#FFAA00>WARNING</color><color=#FFBA40> --</color>");
				m_banner.SetStatus("<color=#FFF5EA>The thread frays! 0 upgrades remaining (Will </color><color=#FFAA00><b>DOWNGRADE</b></color><color=#FFF5EA>)</color>");
			}
			else if (prediction.NextFailure == UpgradeSimulator.NextFailureType.Break)
			{
				m_banner.SetTitle("<color=#FFBA40>-- VOLVA'S EYE : </color><color=#FF4444>DOOM</color><color=#FFBA40> --</color>");
				m_banner.SetStatus("<color=#FFF5EA>The item will </color><color=#FF4444><b>SHATTER</b></color><color=#FFF5EA> and be </color><color=#FF4444><b>DESTROYED</b></color><color=#FFF5EA> on the next strike!</color>");
			}
			else
			{
				m_banner.SetTitle("<color=#FFBA40>-- VOLVA'S EYE --</color>");
				m_banner.SetStatus("<color=#FFF5EA>The weave is clouded for this offering.</color>");
			}
			m_banner.Show();
		}

		public void SetVisible(bool visible)
		{
			if ((Object)(object)m_banner != (Object)null)
			{
				m_banner.SetVisible(visible);
			}
		}
	}
}
namespace ValheimShared.UI
{
	public static class ValheimUiBuilder
	{
		public static readonly Color ColorNorseGold = new Color(1f, 0.73f, 0.25f, 1f);

		public static readonly Color ColorParchment = new Color(0.88f, 0.82f, 0.72f, 1f);

		public static readonly Color ColorMutedText = new Color(0.7f, 0.65f, 0.55f, 1f);

		public static readonly Color ColorSunkenDark = new Color(0.08f, 0.07f, 0.06f, 0.9f);

		public static readonly Color ColorSunkenBg = new Color(0.06f, 0.05f, 0.04f, 0.65f);

		public static readonly Color ColorDividerGold = new Color(0.75f, 0.58f, 0.22f, 0.4f);

		private static TMP_FontAsset s_valheimFont;

		private static Material s_valheimFontMaterial;

		private static Dictionary<string, Sprite> s_spriteCache = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

		private static GameObject s_woodPanelTemplate;

		private static TMP_Text s_cleanTextTemplate;

		private static Button s_buttonTemplate;

		public static TMP_Text GetOrCreateTextTemplate()
		{
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_cleanTextTemplate != (Object)null)
			{
				return s_cleanTextTemplate;
			}
			TMP_Text val = null;
			if ((Object)(object)PlayerCustomizaton.m_barberInstance != (Object)null && (Object)(object)PlayerCustomizaton.m_barberInstance.m_selectedHair != (Object)null)
			{
				val = PlayerCustomizaton.m_barberInstance.m_selectedHair;
			}
			else if ((Object)(object)PlayerCustomizaton.m_barberInstance != (Object)null && (Object)(object)PlayerCustomizaton.m_barberInstance.m_rootPanel != (Object)null)
			{
				TMP_Text[] componentsInChildren = PlayerCustomizaton.m_barberInstance.m_rootPanel.GetComponentsInChildren<TMP_Text>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null && (Object)(object)componentsInChildren[i].font != (Object)null)
					{
						val = componentsInChildren[i];
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
				if (array != null)
				{
					for (int i = 0; i < array.Length; i++)
					{
						if ((Object)(object)array[i] != (Object)null && (Object)(object)array[i].font != (Object)null)
						{
							val = array[i];
							break;
						}
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				s_valheimFont = val.font;
				s_valheimFontMaterial = val.fontSharedMaterial;
				try
				{
					GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject);
					((Object)val2).name = "ValheimUi_CleanTextTemplate";
					val2.SetActive(false);
					Object.DontDestroyOnLoad((Object)(object)val2);
					StripLocalize(val2);
					for (int i = val2.transform.childCount - 1; i >= 0; i--)
					{
						Object.DestroyImmediate((Object)(object)((Component)val2.transform.GetChild(i)).gameObject);
					}
					Component[] components = val2.GetComponents<Component>();
					foreach (Component val3 in components)
					{
						if (!((Object)(object)val3 == (Object)null) && !(val3 is Transform) && !(val3 is RectTransform) && !(val3 is TMP_Text) && !(val3 is CanvasRenderer))
						{
							Object.DestroyImmediate((Object)(object)val3);
						}
					}
					s_cleanTextTemplate = val2.GetComponent<TMP_Text>();
					if ((Object)(object)s_cleanTextTemplate != (Object)null)
					{
						s_cleanTextTemplate.enableAutoSizing = false;
						s_cleanTextTemplate.margin = Vector4.zero;
						s_cleanTextTemplate.textWrappingMode = (TextWrappingModes)0;
						s_cleanTextTemplate.overflowMode = (TextOverflowModes)1;
						s_cleanTextTemplate.rectTransform.anchoredPosition = Vector2.zero;
						s_cleanTextTemplate.rectTransform.offsetMin = Vector2.zero;
						s_cleanTextTemplate.rectTransform.offsetMax = Vector2.zero;
					}
					return s_cleanTextTemplate;
				}
				catch
				{
					return val;
				}
			}
			return null;
		}

		public static TMP_FontAsset GetValheimFont()
		{
			if ((Object)(object)s_valheimFont != (Object)null)
			{
				return s_valheimFont;
			}
			GetOrCreateTextTemplate();
			return s_valheimFont;
		}

		public static Material GetValheimFontMaterial()
		{
			if ((Object)(object)s_valheimFontMaterial != (Object)null)
			{
				return s_valheimFontMaterial;
			}
			GetOrCreateTextTemplate();
			return s_valheimFontMaterial;
		}

		public static Sprite GetValheimSprite(string spriteName)
		{
			if (string.IsNullOrEmpty(spriteName))
			{
				return null;
			}
			if (s_spriteCache.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
			if (array != null)
			{
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null && string.Equals(((Object)array[i]).name, spriteName, StringComparison.OrdinalIgnoreCase))
					{
						s_spriteCache[spriteName] = array[i];
						return array[i];
					}
				}
			}
			return null;
		}

		public static GameObject GetOrCreateWoodPanelTemplate()
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_woodPanelTemplate != (Object)null)
			{
				return s_woodPanelTemplate;
			}
			if ((Object)(object)PlayerCustomizaton.m_barberInstance != (Object)null && (Object)(object)PlayerCustomizaton.m_barberInstance.m_rootPanel != (Object)null)
			{
				s_woodPanelTemplate = PlayerCustomizaton.m_barberInstance.m_rootPanel;
				return s_woodPanelTemplate;
			}
			if ((Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_trophiesPanel != (Object)null)
			{
				s_woodPanelTemplate = InventoryGui.instance.m_trophiesPanel;
				return s_woodPanelTemplate;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			if (rootGameObjects != null)
			{
				for (int i = 0; i < rootGameObjects.Length; i++)
				{
					PlayerCustomizaton componentInChildren = rootGameObjects[i].GetComponentInChildren<PlayerCustomizaton>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.m_rootPanel != (Object)null)
					{
						s_woodPanelTemplate = componentInChildren.m_rootPanel;
						return s_woodPanelTemplate;
					}
				}
			}
			return null;
		}

		public static void PlayButtonClickAudio()
		{
			try
			{
			}
			catch
			{
			}
		}

		public static bool IsAnyInputFocused()
		{
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
				if ((Object)(object)currentSelectedGameObject != (Object)null && ((Object)(object)currentSelectedGameObject.GetComponentInParent<TMP_InputField>() != (Object)null || (Object)(object)currentSelectedGameObject.GetComponentInParent<InputField>() != (Object)null))
				{
					return true;
				}
			}
			return false;
		}

		public static ValheimUiPanel CreatePanel(string name, string title, Vector2 size, Transform parent = null, Action onClose = null, bool draggable = true)
		{
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Expected O, but got Unknown
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null)
			{
				if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_rootObject != (Object)null)
				{
					parent = Hud.instance.m_rootObject.transform;
				}
				else
				{
					Canvas val = Object.FindAnyObjectByType<Canvas>();
					if ((Object)(object)val != (Object)null)
					{
						parent = ((Component)val).transform;
					}
				}
			}
			GameObject orCreateWoodPanelTemplate = GetOrCreateWoodPanelTemplate();
			GameObject val2;
			if ((Object)(object)orCreateWoodPanelTemplate != (Object)null)
			{
				val2 = Object.Instantiate<GameObject>(orCreateWoodPanelTemplate, parent, false);
				((Object)val2).name = name;
				MonoBehaviour[] components = val2.GetComponents<MonoBehaviour>();
				for (int i = 0; i < components.Length; i++)
				{
					if ((Object)(object)components[i] != (Object)null && ((object)components[i]).GetType().Name != "RectTransform" && ((object)components[i]).GetType().Name != "Image" && ((object)components[i]).GetType().Name != "CanvasRenderer")
					{
						Object.DestroyImmediate((Object)(object)components[i]);
					}
				}
				VerticalLayoutGroup component = val2.GetComponent<VerticalLayoutGroup>();
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component);
				}
				HorizontalLayoutGroup component2 = val2.GetComponent<HorizontalLayoutGroup>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component2);
				}
				ContentSizeFitter component3 = val2.GetComponent<ContentSizeFitter>();
				if ((Object)(object)component3 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component3);
				}
				CanvasGroup component4 = val2.GetComponent<CanvasGroup>();
				if ((Object)(object)component4 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component4);
				}
				Component component5 = val2.GetComponent("Animator");
				if ((Object)(object)component5 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component5);
				}
				Image val3 = val2.GetComponent<Image>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = val2.GetComponentInChildren<Image>(true);
				}
				for (int i = val2.transform.childCount - 1; i >= 0; i--)
				{
					Transform child = val2.transform.GetChild(i);
					if (!((Object)(object)val3 != (Object)null) || !((Object)(object)((Component)child).gameObject == (Object)(object)((Component)val3).gameObject))
					{
						Object.DestroyImmediate((Object)(object)((Component)child).gameObject);
					}
				}
				if ((Object)(object)val3 != (Object)null)
				{
					if (((Graphic)val3).color == Color.white)
					{
						((Graphic)val3).color = new Color(0.24f, 0.17f, 0.12f, 0.98f);
					}
					if ((Object)(object)((Component)val3).gameObject != (Object)(object)val2)
					{
						RectTransform rectTransform = ((Graphic)val3).rectTransform;
						rectTransform.anchorMin = Vector2.zero;
						rectTransform.anchorMax = Vector2.one;
						rectTransform.offsetMin = Vector2.zero;
						rectTransform.offsetMax = Vector2.zero;
						((Transform)rectTransform).localScale = Vector3.one;
					}
				}
				else
				{
					val3 = val2.AddComponent<Image>();
					Sprite val4 = GetValheimSprite("woodpanel_settings") ?? GetValheimSprite("box_sunken");
					if ((Object)(object)val4 != (Object)null)
					{
						val3.sprite = val4;
						val3.type = (Type)1;
					}
					((Graphic)val3).color = new Color(0.24f, 0.17f, 0.12f, 0.98f);
				}
			}
			else
			{
				val2 = new GameObject(name, new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val2.transform.SetParent(parent, false);
				Image component6 = val2.GetComponent<Image>();
				Sprite val4 = GetValheimSprite("woodpanel_settings") ?? GetValheimSprite("box_sunken");
				if ((Object)(object)val4 != (Object)null)
				{
					component6.sprite = val4;
					component6.type = (Type)1;
				}
				((Graphic)component6).color = new Color(0.24f, 0.17f, 0.12f, 0.98f);
			}
			RectTransform component7 = val2.GetComponent<RectTransform>();
			component7.anchorMin = new Vector2(0.5f, 0.5f);
			component7.anchorMax = new Vector2(0.5f, 0.5f);
			component7.pivot = new Vector2(0.5f, 0.5f);
			component7.anchoredPosition = Vector2.zero;
			component7.sizeDelta = size;
			((Transform)component7).localScale = Vector3.one;
			val2.transform.localScale = Vector3.one;
			ValheimUiPanel valheimUiPanel = val2.AddComponent<ValheimUiPanel>();
			valheimUiPanel.Initialize(name, title, size, onClose, draggable);
			return valheimUiPanel;
		}

		public static ValheimUiBanner CreateBanner(string name, string title, string status, Vector2 size, Transform parent = null, bool draggable = true)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null)
			{
				if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_rootObject != (Object)null)
				{
					parent = Hud.instance.m_rootObject.transform;
				}
				else
				{
					Canvas val = Object.FindAnyObjectByType<Canvas>();
					if ((Object)(object)val != (Object)null)
					{
						parent = ((Component)val).transform;
					}
				}
			}
			GameObject val2 = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(parent, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = Vector2.zero;
			component.sizeDelta = size;
			((Transform)component).localScale = Vector3.one;
			GameObject val3 = new GameObject("BannerBackground", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val3.transform.SetParent(val2.transform, false);
			RectTransform component2 = val3.GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			Image component3 = val3.GetComponent<Image>();
			((Graphic)component3).color = new Color(0.18f, 0.13f, 0.09f, 0.98f);
			((Graphic)component3).raycastTarget = true;
			GameObject val4 = new GameObject("BannerFrame", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val4.transform.SetParent(val2.transform, false);
			RectTransform component4 = val4.GetComponent<RectTransform>();
			component4.anchorMin = Vector2.zero;
			component4.anchorMax = Vector2.one;
			component4.offsetMin = Vector2.zero;
			component4.offsetMax = Vector2.zero;
			Image component5 = val4.GetComponent<Image>();
			((Graphic)component5).raycastTarget = false;
			Sprite valheimSprite = GetValheimSprite("woodpanel_settings");
			if ((Object)(object)valheimSprite == (Object)null)
			{
				valheimSprite = GetValheimSprite("woodpanel_popup");
			}
			if ((Object)(object)valheimSprite == (Object)null)
			{
				valheimSprite = GetValheimSprite("woodpanel_modal");
			}
			if ((Object)(object)valheimSprite == (Object)null)
			{
				valheimSprite = GetValheimSprite("crafting_panel");
			}
			if ((Object)(object)valheimSprite == (Object)null)
			{
				valheimSprite = GetValheimSprite("box_sunken");
			}
			if ((Object)(object)valheimSprite != (Object)null)
			{
				component5.sprite = valheimSprite;
				component5.type = (Type)1;
				((Graphic)component5).color = new Color(0.9f, 0.75f, 0.6f, 0.95f);
			}
			else
			{
				((Graphic)component5).color = Color.clear;
			}
			ValheimUiBanner valheimUiBanner = val2.AddComponent<ValheimUiBanner>();
			valheimUiBanner.Initialize(name, title, status, size, draggable);
			return valheimUiBanner;
		}

		public static TMP_Text CreateLabel(Transform parent, string text, float fontSize = 14f, Color? color = null, TextAlignmentOptions align = (TextAlignmentOptions)513, float width = 0f, float height = 0f, FontStyles fontStyle = (FontStyles)0)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text orCreateTextTemplate = GetOrCreateTextTemplate();
			GameObject val;
			TMP_Text component;
			if ((Object)(object)orCreateTextTemplate != (Object)null)
			{
				val = Object.Instantiate<GameObject>(((Component)orCreateTextTemplate).gameObject, parent, false);
				((Object)val).name = "Label_" + text;
				val.transform.localScale = Vector3.one;
				val.SetActive(true);
				component = val.GetComponent<TMP_Text>();
			}
			else
			{
				val = new GameObject("Label_" + text, new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				if ((Object)(object)parent != (Object)null)
				{
					val.transform.SetParent(parent, false);
				}
				val.transform.localScale = Vector3.one;
				component = (TMP_Text)(object)val.GetComponent<TextMeshProUGUI>();
				TMP_FontAsset valheimFont = GetValheimFont();
				if ((Object)(object)valheimFont != (Object)null)
				{
					component.font = valheimFont;
					Material valheimFontMaterial = GetValheimFontMaterial();
					if ((Object)(object)valheimFontMaterial != (Object)null)
					{
						component.fontSharedMaterial = valheimFontMaterial;
					}
				}
			}
			component.text = text;
			component.enableAutoSizing = false;
			component.fontSize = fontSize;
			component.fontStyle = fontStyle;
			component.margin = Vector4.zero;
			((Graphic)component).color = (color.HasValue ? color.Value : ColorParchment);
			component.alignment = align;
			component.textWrappingMode = (TextWrappingModes)0;
			((Graphic)component).raycastTarget = false;
			RectTransform rectTransform = component.rectTransform;
			float num = ((width > 0f) ? width : ((rectTransform.sizeDelta.x > 0f) ? rectTransform.sizeDelta.x : 160f));
			float num2 = ((height > 0f) ? height : ((rectTransform.sizeDelta.y > 0f) ? rectTransform.sizeDelta.y : 24f));
			rectTransform.sizeDelta = new Vector2(num, num2);
			rectTransform.anchoredPosition = Vector2.zero;
			if (width > 0f || height > 0f)
			{
				LayoutElement val2 = val.GetComponent<LayoutElement>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = val.AddComponent<LayoutElement>();
				}
				if (width > 0f)
				{
					val2.minWidth = width;
					val2.preferredWidth = width;
				}
				if (height > 0f)
				{
					val2.minHeight = height;
					val2.preferredHeight = height;
				}
			}
			return component;
		}

		public static Button GetOrCreateButtonTemplate()
		{
			if ((Object)(object)s_buttonTemplate != (Object)null)
			{
				return s_buttonTemplate;
			}
			if ((Object)(object)PlayerCustomizaton.m_barberInstance != (Object)null && (Object)(object)PlayerCustomizaton.m_barberInstance.m_apply != (Object)null)
			{
				s_buttonTemplate = PlayerCustomizaton.m_barberInstance.m_apply;
				return s_buttonTemplate;
			}
			Button[] array = Resources.FindObjectsOfTypeAll<Button>();
			if (array != null)
			{
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null && (Object)(object)((Component)array[i]).GetComponentInChildren<TMP_Text>() != (Object)null)
					{
						s_buttonTemplate = array[i];
						return s_buttonTemplate;
					}
				}
			}
			return null;
		}

		public static void StripLocalize(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			Component[] componentsInChildren = go.GetComponentsInChildren(typeof(Component), true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((object)componentsInChildren[i]).GetType().Name == "Localize")
				{
					Component obj = componentsInChildren[i];
					Behaviour val = (Behaviour)(object)((obj is Behaviour) ? obj : null);
					if ((Object)(object)val != (Object)null)
					{
						val.enabled = false;
					}
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
			}
		}

		public static void SetButtonTextColor(Button btn, Color col)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)btn == (Object)null))
			{
				TMP_Text componentInChildren = ((Component)btn).GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Graphic)componentInChildren).color = col;
				}
			}
		}

		public static void SetButtonFontSize(Button btn, float fontSize)
		{
			if (!((Object)(object)btn == (Object)null))
			{
				TMP_Text componentInChildren = ((Component)btn).GetComponentInChildren<TMP_Text>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.fontSize = fontSize;
				}
			}
		}

		public static Button CreateButton(Transform parent, string label, Action onClick, Vector2? size = null, float fontSize = 14.5f)
		{
			//IL_002f: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expecte