Decompiled source of Pour Back In v2.0.1

plugins/PotionCraftPourBackIn.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using IngredientVisualEffectSystem;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PotionCraft;
using PotionCraft.Assemblies.GamepadNavigation;
using PotionCraft.Assemblies.GamepadNavigation.Conditions;
using PotionCraft.Core;
using PotionCraft.Core.SerializableDictionary;
using PotionCraft.InventorySystem;
using PotionCraft.LocalizationSystem;
using PotionCraft.ManagersSystem;
using PotionCraft.ManagersSystem.Input.ControlProviders;
using PotionCraft.ManagersSystem.Player;
using PotionCraft.ManagersSystem.Potion;
using PotionCraft.ManagersSystem.Potion.Entities;
using PotionCraft.ManagersSystem.Room;
using PotionCraft.NotificationSystem;
using PotionCraft.ObjectBased;
using PotionCraft.ObjectBased.AlchemyMachine;
using PotionCraft.ObjectBased.Cauldron;
using PotionCraft.ObjectBased.InteractiveItem;
using PotionCraft.ObjectBased.InteractiveItem.InventoryObject;
using PotionCraft.ObjectBased.InteractiveItem.SoundControllers;
using PotionCraft.ObjectBased.InteractiveItem.SoundControllers.Presets;
using PotionCraft.ObjectBased.InteractiveItem.Vacuuming;
using PotionCraft.ObjectBased.Mortar;
using PotionCraft.ObjectBased.Potion;
using PotionCraft.ObjectBased.RecipeMap.RecipeMapItem.PathMapItem;
using PotionCraft.ObjectBased.RecipeMap.RecipeMapItem.PotionEffectMapItem;
using PotionCraft.ObjectBased.ScalesSystem;
using PotionCraft.ObjectBased.Stack;
using PotionCraft.ObjectBased.Stack.StackItem;
using PotionCraft.ObjectBased.UIElements;
using PotionCraft.ObjectBased.UIElements.Books;
using PotionCraft.ObjectBased.UIElements.Books.RecipeBook;
using PotionCraft.ObjectBased.UIElements.PotionCraftPanel;
using PotionCraft.ScriptableObjects;
using PotionCraft.ScriptableObjects.Ingredient;
using PotionCraft.ScriptableObjects.Potion;
using PotionCraft.Settings;
using PotionCraft.SoundSystem;
using PotionCraft.SoundSystem.SoundPresets;
using PotionCraftPourBackIn.Scripts.Extensions;
using PotionCraftPourBackIn.Scripts.Services;
using PotionCraftPourBackIn.Scripts.Storage;
using PotionCraftPourBackIn.Scripts.UIElements;
using TMPro;
using TooltipSystem;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PotionCraftPourBackIn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Recipe Waypoint Mod for Potion Craft")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1eb1fc372d31ff82812bc2e8ea2afdb2dba5f778")]
[assembly: AssemblyProduct("PotionCraftPourBackIn")]
[assembly: AssemblyTitle("PotionCraftPourBackIn")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PotionCraftPourBackIn
{
	[BepInPlugin("com.fahlgorithm.potioncraftpourbackin", "PotionCraftPourBackIn", "2.0.0.0")]
	[BepInProcess("Potion Craft.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "com.fahlgorithm.potioncraftpourbackin";

		public static ManualLogSource PluginLogger { get; private set; }

		private void Awake()
		{
			PluginLogger = ((BaseUnityPlugin)this).Logger;
			PluginLogger.LogInfo((object)"Plugin com.fahlgorithm.potioncraftpourbackin is loaded!");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.fahlgorithm.potioncraftpourbackin");
			PluginLogger.LogInfo((object)"Plugin com.fahlgorithm.potioncraftpourbackin: Patch Succeeded!");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "PotionCraftPourBackIn";

		public const string PLUGIN_NAME = "PotionCraftPourBackIn";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace PotionCraftPourBackIn.Scripts
{
	public static class Ex
	{
		public static bool RunSafe(Func<bool> action, Func<bool> errorAction = null)
		{
			try
			{
				return action();
			}
			catch (Exception ex)
			{
				LogException(ex);
			}
			return errorAction?.Invoke() ?? true;
		}

		public static void RunSafe(Action action, Action errorAction = null)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				LogException(ex);
				errorAction?.Invoke();
			}
		}

		public static void LogException(Exception ex)
		{
			string text = $"{ex.GetType()}: {ex.Message}\r\n{ex.StackTrace}\r\n{ex.InnerException?.Message}";
			Plugin.PluginLogger.LogError((object)text);
		}
	}
}
namespace PotionCraftPourBackIn.Scripts.UIElements
{
	public class PotionStackItem : StackItem
	{
		public PotionItem potionItem;

		public override Bounds? GetHoveringColliderBounds()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return ((MovableItem)potionItem).mainCollider.bounds;
		}

		public override void SetPhysicsToDefault()
		{
			((Component)potionItem).gameObject.layer = 0;
		}

		public override void SetThisItemLayersToNormal()
		{
			((Component)potionItem).gameObject.layer = 14;
		}

		public override void IgnoreCollision(Collider2D target, bool ignore = true)
		{
			if (!((Object)(object)((Component)target).GetComponentInParent<ThrowVacuuming>() != (Object)(object)Managers.Ingredient.cauldron.throwVacuuming) && (ignore || !Managers.Potion.potionCraftPanel.IsPotionBrewingStarted()))
			{
				((InteractiveItem)potionItem).IgnoreCollision(target, ignore);
			}
		}
	}
}
namespace PotionCraftPourBackIn.Scripts.Storage
{
	public static class StaticStorage
	{
		public static bool CurrentlyMakingPotion;

		public static bool CurrentlyGeneratingRecipe;

		public static List<AlchemySubstanceComponent> PouredInUsedComponents;

		public static List<PotionEffect> PouredInEffects;

		public static List<Potion> PotionItemsNotifiedFor = new List<Potion>();

		public static float LastNotifiedTime;

		public static Potion CurrentPotionCraftPanelPotion;

		public static bool DummyEffectAddedToEnableFinishPotionGrab;
	}
}
namespace PotionCraftPourBackIn.Scripts.Services
{
	public static class EquipmentInteractionService
	{
		public static bool DisallowMortarPotionCollisions(Collider2D other, ThrowVacuuming throwVacuuming)
		{
			PotionStackItem componentInChildren = ((Component)other).GetComponentInChildren<PotionStackItem>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return true;
			}
			if (((StackItem)componentInChildren).IsVacuumingNow)
			{
				return false;
			}
			if ((Object)(object)throwVacuuming == (Object)(object)Managers.Ingredient.cauldron.throwVacuuming)
			{
				return true;
			}
			return false;
		}

		public static bool DisallowMortarGraphicStateSwitch(GraphicStateMachine instance, Collider2D other)
		{
			if (!(instance.stackItem is PotionStackItem))
			{
				return true;
			}
			if (Managers.Potion.potionCraftPanel.IsPotionBrewingStarted())
			{
				return false;
			}
			return !(((Component)other).GetComponentInParent<InteractiveItem>() is Mortar);
		}

		public static bool SetupSlotCauldronSlotConditionToAllowPotion(Slot instance)
		{
			if ((Object)(object)((Component)instance).GetComponentInParent<Cauldron>() == (Object)null)
			{
				return true;
			}
			if (((Object)((Component)((Component)instance).transform.parent).gameObject).name != "Cauldron")
			{
				return true;
			}
			if (instance.conditions.Contains((Condition)30))
			{
				return true;
			}
			if (!instance.conditions.Contains((Condition)10))
			{
				return true;
			}
			instance.conditions = instance.conditions.Concat((IEnumerable<Condition>)(object)new Condition[1] { (Condition)30 }).ToArray();
			return true;
		}
	}
	public static class PotionDataService
	{
		public static bool PotionHasSerializedData(Potion potion)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			SerializedPath serializedPath = ((SerializedPotionRecipeData)potion.GetSerializedRecipeData()).serializedPath;
			if (!(serializedPath.indicatorTargetPosition != Vector2.zero))
			{
				return (serializedPath?.fixedPathPoints?.Any()).GetValueOrDefault();
			}
			return true;
		}

		public static bool IsPotionStackItemEffect(StackVisualEffects instance)
		{
			if ((Object)(object)instance?.stackScript == (Object)null)
			{
				return false;
			}
			return Traverse.Create((object)instance.stackScript).Property<InventoryItem>("InventoryItem", (object[])null).Value is Potion;
		}

		public static void CopyImportantInfoToPotionInstance(IRecipeBookPageContent copyToPg, Potion copyFromPotion, SerializedPotionRecipeData copyFrom)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			Potion copyTo = (Potion)(object)((copyToPg is Potion) ? copyToPg : null);
			if (copyTo == null)
			{
				return;
			}
			SerializedPotionRecipeData val = (SerializedPotionRecipeData)copyTo.GetSerializedRecipeData();
			List<SerializedRecipeMark> recipeMarks = val.recipeMarks;
			recipeMarks.Clear();
			copyFrom.recipeMarks.ForEach(delegate(SerializedRecipeMark m)
			{
				recipeMarks.Add(m.Clone());
			});
			val.collectedPotionEffects.Clear();
			PotionEffect[] array = ((copyFromPotion != null) ? copyFromPotion.Effects : null) ?? Managers.Potion.collectedPotionEffects;
			foreach (PotionEffect val2 in array)
			{
				if ((ComparableScriptableObject<PotionEffect>)(object)val2 == (ComparableScriptableObject<PotionEffect>)null)
				{
					break;
				}
				val.collectedPotionEffects.Add(((Object)val2).name);
			}
			val.serializedPath = copyFrom.serializedPath;
			SimpleAlchemySubstanceComponents usedComponents = copyTo.usedComponents;
			bool? obj;
			if (usedComponents == null)
			{
				obj = null;
			}
			else
			{
				List<AlchemySubstanceComponent> summaryComponents = usedComponents.GetSummaryComponents();
				obj = ((summaryComponents != null) ? new bool?(!summaryComponents.Any()) : null);
			}
			bool? flag = obj;
			if (flag.GetValueOrDefault())
			{
				copyTo.usedComponents.Clear();
				(from component in Managers.Potion.PotionUsedComponents.GetSummaryComponents()
					select component.Clone()).ToList().ForEach(delegate(AlchemySubstanceComponent c)
				{
					copyTo.usedComponents.Add(c, -1);
				});
			}
			if (!copyFrom.usedComponents.components.Any())
			{
				copyTo.usedComponents.GetSummaryComponents().ForEach(delegate(AlchemySubstanceComponent component)
				{
					//IL_0010: Unknown result type (might be due to invalid IL or missing references)
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					//IL_0026: Unknown result type (might be due to invalid IL or missing references)
					//IL_0032: Unknown result type (might be due to invalid IL or missing references)
					//IL_0034: Unknown result type (might be due to invalid IL or missing references)
					//IL_0039: Unknown result type (might be due to invalid IL or missing references)
					//IL_0051: Expected O, but got Unknown
					List<SerializedAlchemySubstanceComponent> components = copyFrom.usedComponents.components;
					SerializedAlchemySubstanceComponent val3 = new SerializedAlchemySubstanceComponent
					{
						name = ((Object)component.Component).name,
						amount = component.Amount
					};
					AlchemySubstanceComponentType type = component.Type;
					val3.type = ((object)(AlchemySubstanceComponentType)(ref type)).ToString();
					components.Add(val3);
				});
			}
			val.usedComponents = copyFrom.usedComponents;
			val.skinSettings = copyFrom.skinSettings;
		}
	}
	public static class PotionItemStackService
	{
		public static void SetupPotionItemForPouringIn(PotionItem potionItem)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			InventoryItem inventoryItem = ((ItemFromInventory)(object)potionItem).GetInventoryItem();
			Potion potion = (Potion)(object)((inventoryItem is Potion) ? inventoryItem : null);
			if (PotionDataService.PotionHasSerializedData(potion) || RecipeService.GetRecipeForPotion(potion) != null)
			{
				StackVisualEffects obj = ((Component)potionItem).gameObject.AddComponent<StackVisualEffects>();
				Stack val = ((Component)potionItem).gameObject.AddComponent<Stack>();
				typeof(MovableItem).GetField("thisRigidbody", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(val, ((ItemFromInventory)potionItem).GetRigidbody());
				PotionStackItem potionStackItem = ((Component)potionItem).gameObject.AddComponent<PotionStackItem>();
				potionStackItem.potionItem = potionItem;
				typeof(StackItem).GetField("thisRigidbody", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(potionStackItem, ((ItemFromInventory)potionItem).GetRigidbody());
				((Component)potionStackItem).transform.parent = ((Component)potionItem).transform;
				val.itemsFromThisStack = new List<StackItem> { (StackItem)(object)potionStackItem };
				SoundController val2 = (SoundController)FormatterServices.GetUninitializedObject(typeof(SoundController));
				InitPotionStackSoundController(val2, (ItemFromInventory)(object)val, (ItemFromInventoryPreset)(object)((Potion)((ItemFromInventory)(object)potionItem).GetInventoryItem()).soundPreset);
				typeof(ItemFromInventory).GetField("_soundController", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(val, val2);
				((StackItem)potionStackItem).Initialize(val);
				obj.stackScript = val;
				((ItemFromInventory)(object)val).SetInventoryItem(((ItemFromInventory)(object)potionItem).GetInventoryItem());
				((StackItem)potionStackItem).spriteRenderers = (SpriteRenderer[])(object)new SpriteRenderer[1] { potionItem.visualObject.bottleLiquidMainSpriteRenderer };
				((StackItem)potionStackItem).graphicStateMachine = ((Component)potionItem).gameObject.AddComponent<GraphicStateMachine>();
				((StackItem)potionStackItem).graphicStateMachine.Init((StackItem)(object)potionStackItem);
			}
		}

		private static void InitPotionStackSoundController(SoundController instance, ItemFromInventory itemFromInventory, ItemFromInventoryPreset preset)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			Ingredient val = ((SerializableDictionaryBase<InventoryItem, int, int>)(object)Managers.Player.Inventory.items).Keys.ToList().OfType<Ingredient>().FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				val = Ingredient.allIngredients.FirstOrDefault();
				if ((Object)(object)val?.soundPreset == (Object)null)
				{
					Plugin.PluginLogger.LogError((object)"Failed to setup sound controller for potion because there were no ingredients in the player inventory.");
					return;
				}
			}
			SoundPresetIngredient val2 = Object.Instantiate<SoundPresetIngredient>(val.soundPreset);
			((HitRubPreset)val2).hit = ((HitRubPreset)preset).hit;
			typeof(SoundController).GetField("stack", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, itemFromInventory);
			typeof(SoundController).GetField("soundPresetIngredient", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, val2);
			typeof(SoundController).GetField("rubGrindLoopEmitter", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, (object?)new LoopEmitter(val2.rubGrindLoop, (AudioMixerGroup)null, (Transform)null));
			typeof(ItemFromInventoryController).GetField("itemFromInventory", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, itemFromInventory);
			typeof(ItemFromInventoryController).GetField("preset", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, preset);
			typeof(ItemFromInventoryController).GetField("rubLoopEmitter", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, (object?)new LoopEmitter(((HitRubPreset)preset).rubLoop, (AudioMixerGroup)null, (Transform)null));
			typeof(ItemFromInventoryController).GetField("newCollisions", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, new List<Vector2>());
			typeof(ItemFromInventoryController).GetField("collidedWith", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, new Dictionary<int, GameObject>());
			typeof(ItemFromInventoryController).GetField("collidedWithToRemove", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, new Dictionary<int, Tuple<float, GameObject>>());
		}

		public static void NotifyForPreModPotion(PotionItem instance)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			if ((int)Managers.Room.CurrentRoomIndex == 1 || (int)Traverse.Create((object)Managers.Room).Field<RoomIndex>("targetRoom").Value == 1)
			{
				Potion val = (Potion)((ItemFromInventory)(object)instance).GetInventoryItem();
				if (!PotionDataService.PotionHasSerializedData(val) && RecipeService.GetRecipeForPotion(val) == null && (Object)(object)val != (Object)(object)StaticStorage.CurrentPotionCraftPanelPotion && !StaticStorage.PotionItemsNotifiedFor.Contains(val) && !(Time.unscaledTime - StaticStorage.LastNotifiedTime < 5f))
				{
					StaticStorage.LastNotifiedTime = Time.unscaledTime;
					StaticStorage.PotionItemsNotifiedFor.Add(val);
					Plugin.PluginLogger.LogInfo((object)"Grabbed potion does not have recipe data. This is likely a pre-mod potion with no corresponding recipe.");
					Notification.ShowText("This potion is missing critical markings", "You wouldn't know where to start if you poured it back in the cauldron", (TextType)0);
				}
			}
		}
	}
	public static class RecipeService
	{
		public static SerializedPotionRecipeData GetRecipeForPotion(Potion potion)
		{
			IRecipeBookPageContent? obj = ((IEnumerable<IRecipeBookPageContent>)RecipeBook.Instance.savedRecipes).FirstOrDefault((Func<IRecipeBookPageContent, bool>)((IRecipeBookPageContent recipe) => RecipeMatchesPotion(potion, (Potion)(object)((recipe is Potion) ? recipe : null))));
			ISerializedRecipeData obj2 = ((obj != null) ? obj.GetSerializedRecipeData() : null);
			return (SerializedPotionRecipeData)(object)((obj2 is SerializedPotionRecipeData) ? obj2 : null);
		}

		private static bool RecipeMatchesPotion(Potion potion, Potion recipe)
		{
			if ((Object)(object)recipe == (Object)null)
			{
				return false;
			}
			if (!((InventoryItem)recipe).GetLocalizedTitleText().Equals(((InventoryItem)potion).GetLocalizedTitleText()))
			{
				return false;
			}
			if (recipe.Effects.Count() != potion.Effects.Count())
			{
				return false;
			}
			if (!SequencesMatch(recipe.Effects.Select((PotionEffect e) => ((Object)e).name).ToList(), potion.Effects.Select((PotionEffect e) => ((Object)e).name).ToList()))
			{
				return false;
			}
			if (recipe.usedComponents.GetSummaryComponentsCount() != potion.usedComponents.GetSummaryComponentsCount())
			{
				return false;
			}
			var seq = (from e in recipe.usedComponents.GetSummaryComponents()
				select new
				{
					((Object)e.Component).name,
					e.Amount
				}).ToList();
			var seq2 = (from e in potion.usedComponents.GetSummaryComponents()
				select new
				{
					((Object)e.Component).name,
					e.Amount
				}).ToList();
			if (!SequencesMatch(seq, seq2))
			{
				return false;
			}
			return true;
		}

		private static bool SequencesMatch<T>(IList<T> seq1, IList<T> seq2)
		{
			if (seq1.Count != seq2.Count)
			{
				return false;
			}
			for (int i = 0; i < seq1.Count; i++)
			{
				if (!seq1[i].Equals(seq2[i]))
				{
					return false;
				}
			}
			return true;
		}
	}
}
namespace PotionCraftPourBackIn.Scripts.Patches
{
	[HarmonyPatch(typeof(EnterZone), "OnTriggerStay2D")]
	public class AcceptPotionCollisionEnterZonePatch
	{
		private static bool Prefix(Collider2D other, ThrowVacuuming ___throwVacuuming)
		{
			return Ex.RunSafe(() => EquipmentInteractionService.DisallowMortarPotionCollisions(other, ___throwVacuuming));
		}
	}
	[HarmonyPatch(typeof(GraphicStateMachine), "OnTriggerExit2D")]
	public class DisallowMortarGraphicStateSwitchExitPatch
	{
		private static bool Prefix(GraphicStateMachine __instance, Collider2D other)
		{
			return Ex.RunSafe(() => EquipmentInteractionService.DisallowMortarGraphicStateSwitch(__instance, other));
		}
	}
	[HarmonyPatch(typeof(GraphicStateMachine), "OnTriggerEnter2D")]
	public class DisallowMortarGraphicStateSwitchPatch
	{
		private static bool Prefix(GraphicStateMachine __instance, Collider2D other)
		{
			return Ex.RunSafe(() => EquipmentInteractionService.DisallowMortarGraphicStateSwitch(__instance, other));
		}
	}
	[HarmonyPatch(typeof(AlchemyMachineSlotObject), "CanBeInteractedNow")]
	public class OverrideAlchemyMachineSlotCanBeInteractedPatch
	{
		private static void Postfix(ref bool __result)
		{
			OverrideAlchemyMachineSlotCanBeInteracted(ref __result);
		}

		private static void OverrideAlchemyMachineSlotCanBeInteracted(ref bool result)
		{
			if (!result)
			{
				return;
			}
			bool newResult = true;
			Ex.RunSafe(delegate
			{
				InteractiveItem grabbedInteractiveItem = Managers.Cursor.grabbedInteractiveItem;
				PotionItem val = (PotionItem)(object)((grabbedInteractiveItem is PotionItem) ? grabbedInteractiveItem : null);
				if (val != null)
				{
					InventoryItem value = Traverse.Create((object)val).Property<InventoryItem>("InventoryItem", (object[])null).Value;
					Potion val2 = (Potion)(object)((value is Potion) ? value : null);
					if (val2.Effects.Length == 0 || (ComparableScriptableObject<PotionEffect>)(object)val2.Effects[0] == (ComparableScriptableObject<PotionEffect>)null)
					{
						newResult = false;
					}
				}
			});
			if (!newResult)
			{
				result = false;
			}
		}
	}
	public class OverrideCauldronCanBeInteractedPatch
	{
		[HarmonyPatch(typeof(Cauldron), "CanBeInteractedNow")]
		public class Cauldron_CanBeInteractedNow
		{
			private static void Postfix(ref bool __result, Cauldron __instance)
			{
				OverrideCauldronCanBeInteracted(ref __result, __instance);
			}
		}

		[HarmonyPatch(typeof(SlotSelector), "SelectNextSlotByStick")]
		public class SlotSelector_SelectNextSlotByStick
		{
			private static bool Prefix()
			{
				SetIsSelectingSlotByStick(isSelectingSlotByStick: true);
				return true;
			}

			private static void Postfix()
			{
				SetIsSelectingSlotByStick(isSelectingSlotByStick: false);
			}
		}

		private static bool IsSelectingSlotByStick;

		private static void OverrideCauldronCanBeInteracted(ref bool result, Cauldron instance)
		{
			if (result)
			{
				return;
			}
			bool newResult = false;
			Ex.RunSafe(delegate
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Expected O, but got Unknown
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				InteractiveItem grabbedInteractiveItem = Managers.Cursor.grabbedInteractiveItem;
				PotionItem val = (PotionItem)(object)((grabbedInteractiveItem is PotionItem) ? grabbedInteractiveItem : null);
				if (val != null && !Managers.Potion.potionCraftPanel.IsPotionBrewingStarted())
				{
					Potion potion = (Potion)Traverse.Create((object)val).Property<InventoryItem>("InventoryItem", (object[])null).Value;
					if ((PotionDataService.PotionHasSerializedData(potion) || RecipeService.GetRecipeForPotion(potion) != null) && (IsSelectingSlotByStick || IsPotionItemWithinCauldronBounds(instance, val)))
					{
						ControlsProvider controlsProvider = Managers.Input.controlsProvider;
						newResult = instance.СanTakeIngredients && ((Object)(object)((ItemFromInventory)val).GetRigidbody() == (Object)null || InteractiveItem.CanBeInteractedByVelocity(((ItemFromInventory)val).GetRigidbody().velocity) || (controlsProvider is Gamepad && !Gamepad.MustFreeModeBeEnabled()));
					}
				}
			});
			if (newResult)
			{
				result = true;
			}
		}

		private static bool IsPotionItemWithinCauldronBounds(Cauldron instance, PotionItem potionItem)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = instance.waterZoneCollider.bounds;
			if (((Component)potionItem).transform.position.x <= ((Bounds)(ref bounds)).min.x || ((Component)potionItem).transform.position.x >= ((Bounds)(ref bounds)).max.x)
			{
				return false;
			}
			CauldronPhysicsCollider componentInChildren = ((Component)instance).GetComponentInChildren<CauldronPhysicsCollider>();
			PolygonCollider2D val = ((componentInChildren != null) ? ((Component)componentInChildren).GetComponent<PolygonCollider2D>() : null);
			if ((Object)(object)val != (Object)null)
			{
				float y = ((Component)potionItem).transform.position.y;
				Bounds bounds2 = ((Collider2D)val).bounds;
				float num = y - ((Bounds)(ref bounds2)).min.y;
				bounds2 = ((Collider2D)val).bounds;
				float num2 = num / ((Bounds)(ref bounds2)).size.y;
				if (num2 < 0.5f)
				{
					return false;
				}
				if (num2 >= 0.7f)
				{
					num2 = 1f;
				}
				else if (num2 > 0.5f)
				{
					num2 += 0.2f;
				}
				float num3 = 0.7f * (1f - num2) * ((Bounds)(ref bounds)).size.x;
				if (((Component)potionItem).transform.position.x <= ((Bounds)(ref bounds)).min.x + num3 || ((Component)potionItem).transform.position.x >= ((Bounds)(ref bounds)).max.x - num3)
				{
					return false;
				}
			}
			return true;
		}

		private static void SetIsSelectingSlotByStick(bool isSelectingSlotByStick)
		{
			IsSelectingSlotByStick = isSelectingSlotByStick;
		}
	}
	[HarmonyPatch(typeof(EnterZone), "OnTriggerExit2D")]
	public class OverrideEnterZoneOnTriggerExit2DPatch
	{
		private static bool Prefix(Collider2D other, ThrowVacuuming ___throwVacuuming)
		{
			return Ex.RunSafe(() => EquipmentInteractionService.DisallowMortarPotionCollisions(other, ___throwVacuuming));
		}
	}
	[HarmonyPatch(typeof(PotionItem), "VacuumItem")]
	public class OverridePotionItemVaccumItemPatch
	{
		private static bool Prefix(PotionItem __instance, bool isPrimaryGrab, bool forceMassModifier, bool forceAltModifier)
		{
			return Ex.RunSafe(() => OverridePotionItemVaccumItem(__instance, isPrimaryGrab, forceMassModifier, forceAltModifier));
		}

		private static bool OverridePotionItemVaccumItem(PotionItem instance, bool isPrimaryGrab, bool forceMassModifier, bool forceAltModifier)
		{
			if (!isPrimaryGrab)
			{
				return true;
			}
			((ItemFromInventory)((Component)instance).gameObject.GetComponent<Stack>()).VacuumItem(isPrimaryGrab, forceMassModifier, forceAltModifier);
			return false;
		}
	}
	[HarmonyPatch(typeof(Stack), "OnCollisionEnter2D")]
	public class OverrideStackOnCollisionEnter2DPatch
	{
		private static bool Prefix(Stack __instance)
		{
			return Ex.RunSafe(() => OverrideStackOnCollisionEnter2D(__instance));
		}

		private static bool OverrideStackOnCollisionEnter2D(Stack instance)
		{
			if (instance.itemsFromThisStack.FirstOrDefault() is PotionStackItem)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PotionItem), "CanBeInteractedNow")]
	public class PreventPotionInteractionWhileVacuumPatch
	{
		private static void Postfix(ref bool __result, PotionItem __instance)
		{
			PreventPotionInteractionWhileVacuum(ref __result, __instance);
		}

		private static void PreventPotionInteractionWhileVacuum(ref bool result, PotionItem instance)
		{
			if (!result)
			{
				return;
			}
			bool newResult = true;
			Ex.RunSafe(delegate
			{
				Stack component = ((Component)instance).GetComponent<Stack>();
				if (!((Object)(object)component == (Object)null))
				{
					newResult = (Object)(object)component.vacuumingTo == (Object)null && ((Component)instance).GetComponent<SortingGroup>().sortingLayerID != 16;
				}
			});
			if (!newResult)
			{
				result = false;
			}
		}
	}
	[HarmonyPatch(typeof(WaterZone), "OnTriggerStay2D")]
	public class RejectPotionCollisionWhenBrewingPatch
	{
		private static bool Prefix(Collider2D other)
		{
			return Ex.RunSafe(() => RejectPotionCollisionWhenBrewing(other));
		}

		private static bool RejectPotionCollisionWhenBrewing(Collider2D other)
		{
			if ((Object)(object)((Component)other).GetComponentInParent<PotionItem>() == (Object)null)
			{
				return true;
			}
			if (Managers.Potion.potionCraftPanel.IsPotionBrewingStarted())
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GraphicStateMachine), "SetCurrentGraphicState")]
	public class RemovePotionHighlightWhenEnteringCauldronPatch
	{
		private static void Postfix(GraphicStateMachine __instance)
		{
			Ex.RunSafe(delegate
			{
				RemovePotionHighlightWhenEnteringCauldron(__instance);
			});
		}

		private static void RemovePotionHighlightWhenEnteringCauldron(GraphicStateMachine instance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			StackItem stackItem = instance.stackItem;
			string sortingLayerName = ((InteractiveItem)stackItem).sortingGroup.sortingLayerName;
			SpriteSortingLayers val = (SpriteSortingLayers)16;
			if (sortingLayerName == ((object)(SpriteSortingLayers)(ref val)).ToString())
			{
				IHoverable iHoverableScript = ((InteractiveItem)stackItem.stackScript).iHoverableScript;
				PotionItem val2 = (PotionItem)(object)((iHoverableScript is PotionItem) ? iHoverableScript : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetHovered(false);
				}
			}
		}
	}
	public class SetupSlotCauldronSlotConditionToAllowPotion
	{
		[HarmonyPatch(typeof(Slot), "SetupConditions")]
		public class Slot_SetupConditions
		{
			private static bool Prefix(Slot __instance)
			{
				return Ex.RunSafe(() => EquipmentInteractionService.SetupSlotCauldronSlotConditionToAllowPotion(__instance));
			}
		}
	}
	[HarmonyPatch(typeof(ExperienceSubManager))]
	public class AddModifiedExperienceForPouredBackInPotionsPatch
	{
		private static MethodInfo TargetMethod()
		{
			return typeof(Potion).GetMethod("AddBrewingExperience", new Type[2]
			{
				typeof(int),
				typeof(bool)
			});
		}

		private static bool Prefix(Potion __instance, int count, bool isBrewingFromRecipeBook)
		{
			return Ex.RunSafe(() => AddModifiedExperienceForPouredBackInPotions(__instance, count, isBrewingFromRecipeBook));
		}

		private static bool AddModifiedExperienceForPouredBackInPotions(Potion potion, int count, bool isBrewingFromRecipeBook)
		{
			if (isBrewingFromRecipeBook)
			{
				return true;
			}
			if (StaticStorage.PouredInUsedComponents == null)
			{
				return true;
			}
			PlayerManagerSettings asset = Settings<PlayerManagerSettings>.Asset;
			float ingredientsExperience = 0f;
			(potion.usedComponents.GetSummaryComponents().Any() ? potion.usedComponents : Managers.Potion.PotionUsedComponents).GetSummaryComponents().Skip(StaticStorage.PouredInUsedComponents.Count).ToList()
				.ForEach(delegate(AlchemySubstanceComponent component)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0016: Unknown result type (might be due to invalid IL or missing references)
					if ((int)component.Type == 0)
					{
						ingredientsExperience += ((InventoryItem)component.Component).GetPrice() * (float)component.Amount;
					}
				});
			ingredientsExperience *= asset.experiencePotionIngredientsMultiplier;
			new List<PotionEffect>();
			int num = 0;
			for (int i = 0; i < (StaticStorage.PouredInEffects?.Count ?? 0); i++)
			{
				if ((ComparableScriptableObject<PotionEffect>)(object)potion.Effects[num] == (ComparableScriptableObject<PotionEffect>)(object)StaticStorage.PouredInEffects[i])
				{
					num++;
				}
				else if (num > 0)
				{
					break;
				}
			}
			List<PotionEffect> list = potion.Effects.Skip(num).ToList();
			float num2 = (list.Any() ? ((float)Potion.GetPotionReview(Array.Empty<PotionEffect>(), list.ToArray()).cost * asset.experiencePotionEffectsMultiplier) : 0f);
			Managers.Player.experience.AddExperience((ingredientsExperience + num2) * (float)count, (ExperienceCategory)1);
			StaticStorage.PouredInUsedComponents = null;
			StaticStorage.PouredInEffects = null;
			return false;
		}
	}
	[HarmonyPatch(typeof(PotionManager), "GeneratePotionFromCurrentPotion")]
	public class CopyImportantInfoToPotionInstancePotionManagerPatch
	{
		[HarmonyAfter(new string[] { "com.fahlgorithm.potioncraftalchemymachinerecipies" })]
		private static void Postfix(Potion __result)
		{
			Ex.RunSafe(delegate
			{
				CopyImportantInfoToPotionInstance(__result);
			});
		}

		private static void CopyImportantInfoToPotionInstance(Potion copyTo)
		{
			if (!StaticStorage.CurrentlyMakingPotion || StaticStorage.CurrentlyGeneratingRecipe)
			{
				return;
			}
			SerializedPotionRecipeData serializedPotionRecipeDataFromCurrentPotion = Managers.Potion.GetSerializedPotionRecipeDataFromCurrentPotion();
			IRecipeBookPageContent recipeBookPageContent = Managers.Potion.potionCraftPanel.GetRecipeBookPageContent();
			Potion val = (Potion)(object)((recipeBookPageContent is Potion) ? recipeBookPageContent : null);
			PotionItem val2 = null;
			if ((Object)(object)val == (Object)null)
			{
				InteractiveItem grabbedInteractiveItem = Managers.Cursor.grabbedInteractiveItem;
				PotionItem val3 = (PotionItem)(object)((grabbedInteractiveItem is PotionItem) ? grabbedInteractiveItem : null);
				if (val3 != null)
				{
					Traverse.Create((object)val3).Property("InventoryItem", (object[])null).SetValue((object)copyTo);
					val2 = val3;
				}
			}
			PotionDataService.CopyImportantInfoToPotionInstance((IRecipeBookPageContent)(object)copyTo, val, serializedPotionRecipeDataFromCurrentPotion);
			if ((Object)(object)val2 != (Object)null)
			{
				PotionItemStackService.SetupPotionItemForPouringIn(val2);
				((ItemFromInventory)val2).OnGrabPrimary();
			}
		}
	}
	[HarmonyPatch(typeof(Potion), "Clone")]
	public class CopyImportantInfoToPotionInstancePotionPatch
	{
		private static void Postfix(IRecipeBookPageContent __result, Potion __instance)
		{
			Ex.RunSafe(delegate
			{
				CopyImportantInfoToPotionInstance(__result, __instance);
			});
		}

		private static void CopyImportantInfoToPotionInstance(IRecipeBookPageContent copyTo, Potion copyFrom)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			PotionDataService.CopyImportantInfoToPotionInstance(copyTo, copyFrom, (SerializedPotionRecipeData)copyFrom.GetSerializedRecipeData());
		}
	}
	[HarmonyPatch(typeof(StackVisualEffects))]
	public class HidePotionStackExplosionEffectsPatch
	{
		private static MethodInfo TargetMethod()
		{
			return typeof(StackVisualEffects).GetMethod("SpawnEffectsExplosion", new Type[3]
			{
				typeof(IngredientVisualEffect),
				typeof(Vector3),
				typeof(SpriteSortingLayers)
			});
		}

		private static bool Prefix(StackVisualEffects __instance)
		{
			return Ex.RunSafe(() => !PotionDataService.IsPotionStackItemEffect(__instance));
		}
	}
	[HarmonyPatch(typeof(StackVisualEffects), "SpawnEffectsUpdate")]
	public class HidePotionStackVisualEffectsPatch
	{
		private static bool Prefix(StackVisualEffects __instance)
		{
			return Ex.RunSafe(() => !PotionDataService.IsPotionStackItemEffect(__instance));
		}
	}
	[HarmonyPatch(typeof(PotionCraftPanel), "UpdatePotionInCraftPanel")]
	public class KeepTrackOfCurrentPotionCraftPanelPotionPatch
	{
		private static void Postfix()
		{
			Ex.RunSafe(delegate
			{
				KeepTrackOfCurrentPotionCraftPanelPotion();
			});
		}

		private static void KeepTrackOfCurrentPotionCraftPanelPotion()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			StaticStorage.CurrentPotionCraftPanelPotion = (Potion)Managers.Potion.potionCraftPanel.GetRecipeBookPageContent();
		}
	}
	[HarmonyPatch(typeof(Potion))]
	public class LoadPotionSerializedDataPatch
	{
		private static MethodInfo TargetMethod()
		{
			return typeof(Potion).GetMethod("GetFromSerializedObject", new Type[1] { typeof(SerializedInventorySlot) });
		}

		private static void Postfix(Potion __result, SerializedInventorySlot serializedObject)
		{
			Ex.RunSafe(delegate
			{
				LoadPotionSerializedData(__result, serializedObject);
			});
		}

		private static void LoadPotionSerializedData(Potion result, SerializedInventorySlot serializedRecipe)
		{
			int num = serializedRecipe.data.IndexOf("recipeData");
			if (num == -1)
			{
				return;
			}
			int num2 = serializedRecipe.data.IndexOf('{', num);
			if (num2 == -1)
			{
				Plugin.PluginLogger.LogInfo((object)"Error: recipeData data in serialized potion is malformed.");
				return;
			}
			int endJsonIndex = GetEndJsonIndex(serializedRecipe.data, num2, useBrackets: false);
			if (endJsonIndex >= serializedRecipe.data.Length)
			{
				Plugin.PluginLogger.LogInfo((object)"Error: recipeData data in serialized potion is malformed (bad end index).");
				return;
			}
			string text = serializedRecipe.data.Substring(num2, endJsonIndex - num2);
			if (text.Length <= 2)
			{
				Plugin.PluginLogger.LogInfo((object)"Error: recipeData data in serialized potion is malformed (empty object).");
			}
			else
			{
				result.SetSerializedPotionFromPanel(JsonUtility.FromJson<SerializedPotionRecipeData>(text));
			}
		}

		private static int GetEndJsonIndex(string input, int startIndex, bool useBrackets)
		{
			int num = startIndex + 1;
			int num2 = 1;
			char value = (useBrackets ? '[' : '{');
			char value2 = (useBrackets ? ']' : '}');
			while (num2 > 0 && num < input.Length - 1)
			{
				int num3 = input.IndexOf(value, num);
				int num4 = input.IndexOf(value2, num);
				if (num3 == -1 && num4 == -1)
				{
					break;
				}
				if (num3 == -1)
				{
					num3 = int.MaxValue;
				}
				if (num4 == -1)
				{
					num4 = int.MaxValue;
				}
				if (num3 < num4)
				{
					num = num3 + 1;
					num2++;
				}
				else if (num4 < num3)
				{
					num = num4 + 1;
					num2--;
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(Stack), "AddIngredientPathToMapPath")]
	public class OverrideAddIngredientPathToMapPathPatch
	{
		private static bool Prefix(Stack __instance)
		{
			return Ex.RunSafe(() => OverrideAddIngredientPathToMapPath(__instance), () => OnError(__instance));
		}

		private static bool OnError(Stack stack)
		{
			try
			{
				if (stack.itemsFromThisStack.FirstOrDefault() is PotionStackItem)
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				Ex.LogException(ex);
			}
			return true;
		}

		private static bool OverrideAddIngredientPathToMapPath(Stack instance)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			PotionStackItem potionStackItem = (instance.itemsFromThisStack.FirstOrDefault() as PotionStackItem) ?? (instance.vacuumedItemsFromThisStack.FirstOrDefault() as PotionStackItem);
			if ((Object)(object)potionStackItem == (Object)null)
			{
				return true;
			}
			ContinueBrewingFromPotion((Potion)Traverse.Create((object)potionStackItem.potionItem).Property<InventoryItem>("InventoryItem", (object[])null).Value);
			return false;
		}

		private static void ContinueBrewingFromPotion(Potion potion)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			SerializedPotionRecipeData recipeForPotion = RecipeService.GetRecipeForPotion(potion);
			SerializedPotionRecipeData val = (SerializedPotionRecipeData)((!PotionDataService.PotionHasSerializedData(potion)) ? ((object)recipeForPotion) : ((object)(SerializedPotionRecipeData)potion.GetSerializedRecipeData()));
			if (val == null)
			{
				Plugin.PluginLogger.LogInfo((object)"ERROR: Failed to find recipe for poured-in, pre-mod potion!");
				return;
			}
			PotionBase potionBase = val.usedComponents.GetPotionBase();
			Managers.Potion.ApplySerializedPotionRecipeDataToCurrentPotion(val, potionBase, true);
			StaticStorage.PouredInUsedComponents = potion.usedComponents.GetSummaryComponents().ToList();
			StaticStorage.PouredInEffects = potion.Effects.ToList();
			if (recipeForPotion != null)
			{
				Managers.Potion.potionCraftPanel.potionChangedAfterSavingRecipe = false;
				((Button)Managers.Potion.potionCraftPanel.saveRecipeButton).Locked = true;
			}
			PotionEffect[] collectedPotionEffects = Managers.Potion.collectedPotionEffects;
			foreach (PotionEffect val2 in collectedPotionEffects)
			{
				if ((ComparableScriptableObject<PotionEffect>)(object)val2 == (ComparableScriptableObject<PotionEffect>)null)
				{
					continue;
				}
				foreach (PotionEffectMapItem item in Managers.RecipeMap.currentMap.referencesContainer.potionEffectsOnMap)
				{
					if ((ComparableScriptableObject<PotionEffect>)(object)item.Effect == (ComparableScriptableObject<PotionEffect>)(object)val2)
					{
						item.Status = (PotionEffectStatus)3;
						break;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Potion), "GetSerializedInventorySlot")]
	public class SavePotionSerializedDataPatch
	{
		private static void Postfix(SerializedInventorySlot __result, Potion __instance)
		{
			Ex.RunSafe(delegate
			{
				SavePotionSerializedData(__result, __instance);
			});
		}

		private static void SavePotionSerializedData(SerializedInventorySlot result, Potion instance)
		{
			if (!result.data.Contains("recipeData"))
			{
				string value = ",\"recipeData\":" + JsonUtility.ToJson((object)instance.GetSerializedRecipeData());
				int startIndex = result.data.LastIndexOf('}');
				result.data = result.data.Insert(startIndex, value);
			}
		}
	}
	[HarmonyPatch(typeof(SavePotionRecipeButton), "GenerateRecipe")]
	public class SetCurrentlyGeneratingRecipePatch
	{
		private static bool Prefix()
		{
			return Ex.RunSafe(() => SetCurrentlyGeneratingRecipe(currentlyGeneratingRecipe: true));
		}

		private static void Postfix()
		{
			Ex.RunSafe(() => SetCurrentlyGeneratingRecipe(currentlyGeneratingRecipe: false));
		}

		private static bool SetCurrentlyGeneratingRecipe(bool currentlyGeneratingRecipe)
		{
			StaticStorage.CurrentlyGeneratingRecipe = currentlyGeneratingRecipe;
			return true;
		}
	}
	[HarmonyPatch(typeof(PotionCraftPanel), "MakePotion")]
	public class SetCurrentlyMakingPotionPatch
	{
		private static bool Prefix()
		{
			return Ex.RunSafe(() => SetCurrentlyMakingPotion(currentlyMakingPotion: true));
		}

		private static void Postfix()
		{
			Ex.RunSafe(() => SetCurrentlyMakingPotion(currentlyMakingPotion: false));
		}

		private static bool SetCurrentlyMakingPotion(bool currentlyMakingPotion)
		{
			StaticStorage.CurrentlyMakingPotion = currentlyMakingPotion;
			return true;
		}
	}
	[HarmonyPatch(typeof(PotionItem), "OnGrabPrimary")]
	public class ForwardGrabPrimaryPatch
	{
		private static void Postfix(PotionItem __instance)
		{
			Ex.RunSafe(delegate
			{
				ForwardGrabPrimary(__instance);
			});
		}

		private static void ForwardGrabPrimary(PotionItem instance)
		{
			Stack component = ((Component)instance).GetComponent<Stack>();
			if ((Object)(object)component == (Object)null)
			{
				PotionItemStackService.NotifyForPreModPotion(instance);
				return;
			}
			((ItemFromInventory)component).OnGrabPrimary();
			MethodInfo method = typeof(ConditionValue).GetMethod("SetConditionValue", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(Condition),
				typeof(bool)
			}, new ParameterModifier[0]);
			if (!(method == null))
			{
				method.Invoke(null, new object[2]
				{
					(object)(Condition)30,
					true
				});
			}
		}
	}
	[HarmonyPatch(typeof(ItemFromInventory), "CustomOnReleasePrimaryCondition")]
	public class ForwardPotionItemOnReleasePrimaryPatch
	{
		private static void Postfix(ItemFromInventory __instance)
		{
			Ex.RunSafe(delegate
			{
				ForwardPotionItemOnReleasePrimary(__instance);
			});
		}

		private static void ForwardPotionItemOnReleasePrimary(ItemFromInventory instance)
		{
			if (instance is PotionItem)
			{
				Stack component = ((Component)instance).gameObject.GetComponent<Stack>();
				if (!((Object)(object)component == (Object)null) && !(Managers.Cursor.hoveredInteractiveItem is ScalesCupDisplay))
				{
					_ = Managers.Cursor.hoveredInteractiveItem;
					typeof(Stack).GetMethod("CustomOnReleasePrimaryCondition", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(component, null);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemFromInventory), "OnReleasePrimary")]
	public class ForwardReleasePrimaryPatch
	{
		private static void Postfix(ItemFromInventory __instance)
		{
			Ex.RunSafe(delegate
			{
				ForwardReleasePrimary(__instance);
			});
		}

		private static void ForwardReleasePrimary(ItemFromInventory instance)
		{
			if ((Object)(object)instance == (Object)null || ((MovableItem)instance).markedAsDestroyed)
			{
				return;
			}
			PotionItem val = (PotionItem)(object)((instance is PotionItem) ? instance : null);
			if (val != null)
			{
				Stack component = ((Component)val).GetComponent<Stack>();
				if (!((Object)(object)component == (Object)null) && !(Managers.Cursor.hoveredInteractiveItem is ScalesCupDisplay))
				{
					_ = Managers.Cursor.hoveredInteractiveItem;
					((ItemFromInventory)component).OnReleasePrimary(false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(LedgeController), "DetachItem")]
	public class ForwardLedgeControllerDetachItemToPotionStackItemPatch
	{
		private static void Postfix(LedgeController __instance, ILedgeTarget ledgeTarget, bool removeFromColliders)
		{
			Ex.RunSafe(delegate
			{
				ForwardLedgeControllerDetachItemToPotionStackItem(__instance, ledgeTarget, removeFromColliders);
			});
		}

		private static void ForwardLedgeControllerDetachItemToPotionStackItem(LedgeController __instance, ILedgeTarget ledgeTarget, bool removeFromColliders)
		{
			PotionItem val = (PotionItem)(object)((ledgeTarget is PotionItem) ? ledgeTarget : null);
			if (val != null)
			{
				PotionStackItem component = ((Component)val).GetComponent<PotionStackItem>();
				__instance.DetachItem((ILedgeTarget)(object)component, removeFromColliders);
			}
		}
	}
	[HarmonyPatch(typeof(LedgeController), "AttachItem")]
	public class ForwardLedgeControllerAttachItemToPotionStackItemPatch
	{
		private static void Postfix(LedgeController __instance, ILedgeTarget ledgeTarget)
		{
			Ex.RunSafe(delegate
			{
				ForwardLedgeControllerAttachItemToPotionStackItem(__instance, ledgeTarget);
			});
		}

		private static void ForwardLedgeControllerAttachItemToPotionStackItem(LedgeController __instance, ILedgeTarget ledgeTarget)
		{
			PotionItem val = (PotionItem)(object)((ledgeTarget is PotionItem) ? ledgeTarget : null);
			if (val != null)
			{
				PotionStackItem component = ((Component)val).GetComponent<PotionStackItem>();
				__instance.AttachItem((ILedgeTarget)(object)component);
			}
		}
	}
	[HarmonyPatch(typeof(RoomManager), "GoTo")]
	public class NotifyForPreModPotionOnRoomChangePatch
	{
		private static void Postfix()
		{
			Ex.RunSafe(delegate
			{
				NotifyForPreModPotionOnRoomChange();
			});
		}

		private static void NotifyForPreModPotionOnRoomChange()
		{
			InteractiveItem grabbedInteractiveItem = Managers.Cursor.grabbedInteractiveItem;
			PotionItem val = (PotionItem)(object)((grabbedInteractiveItem is PotionItem) ? grabbedInteractiveItem : null);
			if (val != null)
			{
				PotionItemStackService.NotifyForPreModPotion(val);
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	public class OverridePotionStackItemSoundControllerPatch
	{
		private static bool Prefix(SoundController __instance, StackItem stackItem)
		{
			return Ex.RunSafe(() => OverridePotionStackItemSoundController(__instance, stackItem), () => OnError(stackItem));
		}

		private static bool OnError(StackItem stackItem)
		{
			try
			{
				if (stackItem is PotionStackItem)
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				Ex.LogException(ex);
			}
			return true;
		}

		private static bool OverridePotionStackItemSoundController(SoundController instance, StackItem stackItem)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			if (!(stackItem is PotionStackItem))
			{
				return true;
			}
			PotionItem potionItem = ((PotionStackItem)(object)stackItem).potionItem;
			typeof(SoundController).GetField("stackItem", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, stackItem);
			typeof(SoundController).GetField("newCollisions", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, new List<Vector2>());
			typeof(SoundController).GetField("collidedWith", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, new List<GameObject>());
			Ingredient val = ((SerializableDictionaryBase<InventoryItem, int, int>)(object)Managers.Player.Inventory.items).Keys.ToList().OfType<Ingredient>().FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				val = Ingredient.allIngredients.FirstOrDefault();
				if ((Object)(object)val == (Object)null)
				{
					Plugin.PluginLogger.LogError((object)"Failed to setup sound controller for potion because there were no ingredients in the player inventory.");
					return false;
				}
			}
			SoundPresetIngredient val2 = Object.Instantiate<SoundPresetIngredient>(val.soundPreset);
			SoundPresetPotion soundPreset = ((Potion)Traverse.Create((object)potionItem).Property<InventoryItem>("InventoryItem", (object[])null).Value).soundPreset;
			((HitRubPreset)val2).hit = ((HitRubPreset)soundPreset).hit;
			typeof(SoundController).GetField("preset", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, val2);
			typeof(SoundController).GetField("rubLoopEmitter", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, (object?)new LoopEmitter(((HitRubPreset)val2).rubLoop, (AudioMixerGroup)null, (Transform)null));
			return false;
		}
	}
	[HarmonyPatch(typeof(SoundController), "OnGrind")]
	public class OverrideSoundControllerOnGrindPatch
	{
		private static bool Prefix(SoundController __instance)
		{
			return Ex.RunSafe(() => OverrideSoundControllerOnGrind(__instance));
		}

		private static bool OverrideSoundControllerOnGrind(SoundController instance)
		{
			return !(typeof(SoundController).GetField("stackItem", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance) is PotionStackItem);
		}
	}
	public class PreventCrashOnStackItemDestroy
	{
		[HarmonyPatch(typeof(StackItem), "RemoveItemFromStackAndReset")]
		public class StackItem_RemoveItemFromStackAndReset
		{
			private static bool Prefix(StackItem __instance)
			{
				return Ex.RunSafe(() => DoPreventCrashOnStackItemDestroy(__instance));
			}
		}

		private static bool DoPreventCrashOnStackItemDestroy(StackItem instance)
		{
			if (!(instance is PotionStackItem))
			{
				return true;
			}
			Stack stackScript = instance.stackScript;
			if (stackScript != null)
			{
				stackScript.RemoveItemFromStack(instance);
			}
			instance.soundController.ResetController();
			return false;
		}
	}
	[HarmonyPatch(typeof(Stack), "DisassembleStack")]
	public class PreventPotionStackDissassemblyPatch
	{
		private static bool Prefix(Stack __instance)
		{
			return Ex.RunSafe(() => PreventPotionStackDissassembly(__instance));
		}

		private static bool PreventPotionStackDissassembly(Stack instance)
		{
			return (Object)(object)((Component)instance).GetComponent<PotionItem>() == (Object)null;
		}
	}
	[HarmonyPatch(typeof(StackItem), "OnDestroy")]
	public class PreventStackItemOnDestroyExceptionPatch
	{
		private static bool Prefix(StackItem __instance)
		{
			return Ex.RunSafe(() => PreventStackItemOnDestroyException(__instance));
		}

		private static bool PreventStackItemOnDestroyException(StackItem instance)
		{
			if (!(instance is PotionStackItem))
			{
				return true;
			}
			Stack stackScript = instance.stackScript;
			if (stackScript != null)
			{
				stackScript.RemoveItemFromStack(instance);
			}
			SoundController soundController = instance.soundController;
			if (soundController != null)
			{
				soundController.ResetController();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PotionItem), "SpawnNewPotion")]
	public class SetupPotionItemForPouringInPatch
	{
		private static void Postfix(PotionItem __result)
		{
			Ex.RunSafe(delegate
			{
				PotionItemStackService.SetupPotionItemForPouringIn(__result);
			});
		}
	}
	[HarmonyPatch(typeof(RecipeBook), "OnLoad")]
	public class SetupPotionItemsForPouringInOnRecipeLoadPatch
	{
		private static void Postfix()
		{
			Ex.RunSafe(delegate
			{
				SetupPotionItemsForPouringInOnRecipeLoad();
			});
		}

		private static void SetupPotionItemsForPouringInOnRecipeLoad()
		{
			(from p in ((Component)Managers.Game.ItemContainer).GetComponentsInChildren<PotionItem>()
				where (Object)(object)((Component)p).GetComponent<Stack>() == (Object)null
				select p).ToList().ForEach(PotionItemStackService.SetupPotionItemForPouringIn);
		}
	}
	public static class UnfinishedPotionPatcher
	{
		[HarmonyPatch(typeof(PotionCraftPanel), "UpdatePotionInCraftPanel")]
		public class EnableFinishPotionButtonForUnfinishedPotionsPatch
		{
			private static void Postfix(PotionCraftPanel __instance)
			{
				Ex.RunSafe(delegate
				{
					EnableFinishPotionButtonForUnfinishedPotions(__instance);
				});
			}

			private static void EnableFinishPotionButtonForUnfinishedPotions(PotionCraftPanel instance)
			{
				if (instance.IsPotionBrewingStarted())
				{
					((Button)((ItemsPanel)instance.limitedInventoryPanel).buttons.First()).Locked = false;
					((Button)instance.potionFinishingButton).Locked = false;
				}
			}
		}

		[HarmonyPatch(typeof(PotionInventoryObject), "CanBeInteractedNow")]
		public class EnableGrabUnfinishedPotionToFinishPatch
		{
			private static bool Prefix(PotionInventoryObject __instance)
			{
				return Ex.RunSafe(() => EnableGrabUnfinishedPotionToFinishPrefix(((InventoryObject)(object)__instance).GetInventoryItem()));
			}

			private static void Postfix(PotionInventoryObject __instance)
			{
				Ex.RunSafe(delegate
				{
					EnableGrabUnfinishedPotionToFinishPostfix(((InventoryObject)(object)__instance).GetInventoryItem());
				});
			}
		}

		[HarmonyPatch(typeof(RecipeBookInventoryObjectPotion), "CanBeInteractedNow")]
		public class RecipeBookPotionInventoryObject_CanBeInteractedNow
		{
			private static bool Prefix(RecipeBookInventoryObjectPotion __instance)
			{
				return Ex.RunSafe(() => EnableGrabUnfinishedPotionToFinishPrefix(((InventoryObject)(object)__instance).GetInventoryItem(), requireBrewStart: false));
			}

			private static void Postfix(RecipeBookInventoryObjectPotion __instance)
			{
				Ex.RunSafe(delegate
				{
					EnableGrabUnfinishedPotionToFinishPostfix(((InventoryObject)(object)__instance).GetInventoryItem(), requireBrewStart: false);
				});
			}
		}

		private static bool EnableGrabUnfinishedPotionToFinishPrefix(InventoryItem inventoryItem, bool requireBrewStart = true)
		{
			Potion val = (Potion)(object)((inventoryItem is Potion) ? inventoryItem : null);
			if (val == null)
			{
				return true;
			}
			if (requireBrewStart && !Managers.Potion.potionCraftPanel.IsPotionBrewingStarted())
			{
				return true;
			}
			if (val.Effects.Any())
			{
				return true;
			}
			val.Effects = (PotionEffect[])(object)new PotionEffect[1] { PotionEffect.allPotionEffects.First() };
			StaticStorage.DummyEffectAddedToEnableFinishPotionGrab = true;
			return true;
		}

		private static void EnableGrabUnfinishedPotionToFinishPostfix(InventoryItem inventoryItem, bool requireBrewStart = true)
		{
			Potion val = (Potion)(object)((inventoryItem is Potion) ? inventoryItem : null);
			if (val != null && (!requireBrewStart || Managers.Potion.potionCraftPanel.IsPotionBrewingStarted()) && StaticStorage.DummyEffectAddedToEnableFinishPotionGrab)
			{
				val.Effects = Array.Empty<PotionEffect>();
				StaticStorage.DummyEffectAddedToEnableFinishPotionGrab = false;
			}
		}
	}
	public class ConvertPotionInventoryItemV1toV2Pacth
	{
		[HarmonyPatch("PotionCraft.Assemblies.ConverterFrom110To200.SerializedInventorySlot, PotionCraft.ConverterFrom110To200, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "ConvertPotionAndLegendarySubstancesToNew")]
		public class SerializedInventorySlot_ConvertPotionAndLegendarySubstancesToNew
		{
			private static void Postfix(ref object __result, string ___data, string ___classFullName)
			{
				object myResult = __result;
				Ex.RunSafe(delegate
				{
					ConvertPotionInventoryItem(myResult, ___data, ___classFullName);
				});
			}

			private static void ConvertPotionInventoryItem(object result, string unconvertedJson, string classFullName)
			{
				if (classFullName.ToLower().Equals("PotionCraft.ScriptableObjects.Potion.Potion".ToLower()))
				{
					Traverse val = Traverse.Create(result);
					JObject val2 = JObject.Parse(val.Field<string>("data").Value);
					JToken val3 = JObject.Parse(unconvertedJson)["potionFromPanel"];
					if (val3 != null)
					{
						JObject val4 = JObject.Parse(JsonUtility.ToJson(Traverse.Create(JsonConvert.DeserializeObject(val3.ToString((Formatting)0, Array.Empty<JsonConverter>()), AccessTools.TypeByName("PotionCraft.Assemblies.ConverterFrom110To200.SerializedPotionRecipeDataOld"))).Method("ConvertPotionToNew", Array.Empty<object>()).GetValue()));
						val2["recipeData"] = (JToken)(object)val4;
						string value = ((JToken)val2).ToString((Formatting)0, Array.Empty<JsonConverter>());
						val.Field("data").SetValue((object)value);
					}
				}
			}
		}
	}
}
namespace PotionCraftPourBackIn.Scripts.Patches.UnfinishedPotion
{
	public class AllowBrewingNoEffectPotionsFromRecipeBookPatch
	{
		[HarmonyPatch(typeof(RecipeBookInventoryPanelTooltip), "GetTooltipContent")]
		public class RecipeBookPotionPlaceholderForTooltip_GetTooltipContent
		{
			private static void Postfix(ref TooltipContent __result, RecipeBookLeftPageContent ___leftPageContent)
			{
				OverrideRecipeBookPotionIconTooltip(ref __result, ___leftPageContent);
			}
		}

		[HarmonyPatch(typeof(RecipeBookInventoryObjectPotion), "UpdateVisual")]
		public class RecipeBookPotionInventoryObject_UpdateVisual
		{
			private static void Postfix(RecipeBookInventoryObjectPotion __instance)
			{
				Ex.RunSafe(delegate
				{
					AllowBrewingNoEffectPotionsFromRecipeBook(__instance);
				});
			}
		}

		private static void OverrideRecipeBookPotionIconTooltip(ref TooltipContent result, RecipeBookLeftPageContent leftPageContent)
		{
			if (result == (TooltipContent)null)
			{
				return;
			}
			TooltipContent newResult = result;
			string header = result.header;
			Ex.RunSafe(delegate
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Expected O, but got Unknown
				string text = new Key("#recipebook_brew_potion_no_effects", (List<string>)null, (KeyParametersStyle)0, (TMP_FontAsset)null, Array.Empty<KeyTagParameter>()).GetText();
				if (!(header != text))
				{
					if (RecipeBookRecipeBrewController.GetMaxRecipesCountForBrew(leftPageContent.GetRecipeBookPageContent(), false, false) != 0)
					{
						newResult = null;
					}
					else
					{
						string text2 = new Key("#recipebook_brew_potion_not_enough_ingredients", (List<string>)null, (KeyParametersStyle)0, (TMP_FontAsset)null, Array.Empty<KeyTagParameter>()).GetText();
						newResult = new TooltipContent
						{
							header = text2
						};
					}
				}
			});
			result = newResult;
		}

		private static void AllowBrewingNoEffectPotionsFromRecipeBook(RecipeBookInventoryObjectPotion instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (((Button)instance).Locked)
			{
				ItemsPanel value = Traverse.Create((object)instance).Property<ItemsPanel>("ItemsPanel", (object[])null).Value;
				ItemsPanel obj = ((value is RecipeBookPanelInventoryPanel) ? value : null);
				PageContentState currentState = ((PageContent)((RecipeBookPanelInventoryPanel)obj).leftPageContent).currentState;
				IRecipeBookPageContent recipeBookPageContent = ((RecipeBookPanelInventoryPanel)obj).leftPageContent.GetRecipeBookPageContent();
				Potion val = (Potion)(object)((recipeBookPageContent is Potion) ? recipeBookPageContent : null);
				if ((int)currentState != 0 && (val.Effects.Length == 0 || (ComparableScriptableObject<PotionEffect>)(object)val.Effects[0] == (ComparableScriptableObject<PotionEffect>)null) && RecipeBookRecipeBrewController.GetMaxRecipesCountForBrew((IRecipeBookPageContent)(object)val, false, false) != 0)
				{
					((Button)instance).Locked = false;
				}
			}
		}
	}
}
namespace PotionCraftPourBackIn.Scripts.Extensions
{
	public static class PotionExtensions
	{
		public static InventoryItem GetInventoryItem(this ItemFromInventory item)
		{
			return Traverse.Create((object)item).Property<InventoryItem>("InventoryItem", (object[])null).Value;
		}

		public static void SetInventoryItem(this ItemFromInventory item, InventoryItem value)
		{
			Traverse.Create((object)item).Property("InventoryItem", (object[])null).SetValue((object)value);
		}

		public static InventoryItem GetInventoryItem(this InventoryObject item)
		{
			return Traverse.Create((object)item).Property<InventoryItem>("InventoryItem", (object[])null).Value;
		}

		public static void SetInventoryItem(this InventoryObject item, InventoryItem value)
		{
			Traverse.Create((object)item).Property("InventoryItem", (object[])null).SetValue((object)value);
		}
	}
}