Decompiled source of Brew From Here v2.0.0
plugins/PotionCraftBrewFromHere.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using DarkScreenSystem; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using PotionCraft.Core; using PotionCraft.ManagersSystem; using PotionCraft.ManagersSystem.Potion; using PotionCraft.ManagersSystem.Potion.Entities; using PotionCraft.ManagersSystem.SaveLoad; using PotionCraft.NotificationSystem; using PotionCraft.ObjectBased.InteractiveItem; using PotionCraft.ObjectBased.RecipeMap.Path; using PotionCraft.ObjectBased.RecipeMap.RecipeMapItem; using PotionCraft.ObjectBased.RecipeMap.RecipeMapItem.PathMapItem; using PotionCraft.ObjectBased.UIElements; using PotionCraft.ObjectBased.UIElements.Bookmarks; using PotionCraft.ObjectBased.UIElements.Books; using PotionCraft.ObjectBased.UIElements.Books.RecipeBook; using PotionCraft.ObjectBased.UIElements.PotionCraftPanel; using PotionCraft.SaveFileSystem; using PotionCraft.SaveLoadSystem; using PotionCraft.ScriptableObjects; using PotionCraft.ScriptableObjects.Ingredient; using PotionCraft.ScriptableObjects.Potion; using PotionCraft.ScriptableObjects.Salts; using PotionCraftUsefulRecipeMarks.Scripts; using PotionCraftUsefulRecipeMarks.Scripts.Json; using PotionCraftUsefulRecipeMarks.Scripts.Services; using PotionCraftUsefulRecipeMarks.Scripts.Storage; using PotionCraftUsefulRecipeMarks.Scripts.Storage.Delta; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [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("PotionCraftBrewFromHere")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Recipe Waypoint Mod for Potion Craft")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+e859b5ed3bf7d2ed7f325b5227e700e362cb6fe5")] [assembly: AssemblyProduct("PotionCraftBrewFromHere")] [assembly: AssemblyTitle("PotionCraftBrewFromHere")] [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 PotionCraftUsefulRecipeMarks { [BepInPlugin("com.fahlgorithm.potioncraftbrewfromhere", "PotionCraftBrewFromHere", "2.0.0.0")] [BepInProcess("Potion Craft.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.fahlgorithm.potioncraftbrewfromhere"; public const string PLUGIN_VERSION = "2.0.0.0"; public static ManualLogSource PluginLogger { get; private set; } public static void LogInfo(string message) { PluginLogger.LogInfo((object)message); } public static void LogError(string message) { PluginLogger.LogError((object)message); Ex.SaveErrorMessage(message); } private void Awake() { PluginLogger = ((BaseUnityPlugin)this).Logger; PluginLogger.LogInfo((object)"Plugin com.fahlgorithm.potioncraftbrewfromhere is loaded!"); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.fahlgorithm.potioncraftbrewfromhere"); PluginLogger.LogInfo((object)"Plugin com.fahlgorithm.potioncraftbrewfromhere: Patch Succeeded!"); StaticStorage.BookmarkOrganizerOldVersionInstalled = Chainloader.PluginInfos.Any((KeyValuePair<string, PluginInfo> p) => p.Value.Metadata.GUID.Equals("com.fahlgorithm.potioncraftbookmarkorganizer") && p.Value.Metadata.Version < new Version(1, 0, 5, 3)); if (StaticStorage.BookmarkOrganizerOldVersionInstalled) { PluginLogger.LogError((object)"An old version of Bookmark Organizer is installed! This version causes some issues for this mod and should be updated as soon as possible!"); } } } public static class PluginInfo { public const string PLUGIN_GUID = "PotionCraftBrewFromHere"; public const string PLUGIN_NAME = "PotionCraftBrewFromHere"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace PotionCraftUsefulRecipeMarks.Scripts { public static class Ex { public static bool RunSafe(Func<bool> action, Func<bool> errorAction = null, bool logErrorToStorage = false) { try { return action(); } catch (Exception ex) { LogException(ex, logErrorToStorage); } return errorAction?.Invoke() ?? true; } public static void RunSafe(Action action, Action errorAction = null, bool logErrorToStorage = false) { try { action(); } catch (Exception ex) { LogException(ex, logErrorToStorage); errorAction?.Invoke(); } } public static void LogException(Exception ex, bool logErrorToStorage = false) { string exceptionText = GetExceptionText(ex); Plugin.PluginLogger.LogError((object)exceptionText); if (logErrorToStorage) { StaticStorage.ErrorLog.Add(exceptionText); } } public static string GetExceptionText(Exception ex) { return $"{DateTime.UtcNow}: {ex.GetType()}: {ex.Message}\r\n{ex.StackTrace}\r\n{ex.InnerException?.Message}"; } public static void SaveErrorMessage(string errorMessage) { StaticStorage.ErrorLog.Add($"{DateTime.UtcNow}: {errorMessage}"); } } public static class Extensions { public static (float x, float y) ToTuple(this Vector3 vector) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Vector2.op_Implicit(vector).ToTuple(); } public static (float x, float y) ToTuple(this Vector2 vector) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) return (vector.x, vector.y); } public static Vector2 ToVector(this (float x, float y) tuple) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2(tuple.x, tuple.y); } public static SerializedPotionRecipeData GetRecipeData(this Potion potion) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown return (SerializedPotionRecipeData)potion.GetSerializedRecipeData(); } } public static class Saver { public class SaveState { public Dictionary<int, RecipeMarkInfo> CurrentPotionRecipeMarkInfos { get; set; } public Dictionary<DeltaProperty, BaseDelta> CurrentPotionState { get; set; } public RecipeMarkInfo CurrentRecipeMarkInfo { get; set; } public Dictionary<int, RecipeMarkInfo> PreviousPotionRecipeMarkInfo { get; set; } public Dictionary<DeltaProperty, BaseDelta> SelectedRecipePotionState { get; set; } public int SelectedRecipeMarkIndex { get; set; } public int SelectedRecipeIndex { get; set; } public Dictionary<int, Dictionary<int, RecipeMarkInfo>> RecipeMarkInfos { get; set; } public List<string> ErrorLog { get; set; } public string Version { get; set; } } [HarmonyPatch(typeof(SavedState), "ToJson")] public class SavedState_ToJson { private static void Postfix(ref string __result) { StoreData(ref __result); } } [HarmonyPatch(typeof(SaveLoadManager), "LoadProgressState")] public class SaveLoadManager_LoadProgressState { private static bool Prefix() { return RetreiveStoredData(); } } [HarmonyPatch(typeof(File), "Load")] public class File_Load { private static bool Prefix(File __instance) { return RetrieveStateJsonString(__instance); } } private class Deserialized<T> { [JsonProperty("FahlgorithmUsefulRecipeMarks")] public T DeserializedObject { get; set; } } public const string JsonSaveName = "FahlgorithmUsefulRecipeMarks"; public static string StateJsonString; private static SaveState GetSaveState() { return new SaveState { CurrentPotionRecipeMarkInfos = StaticStorage.CurrentPotionRecipeMarkInfos, CurrentPotionState = StaticStorage.CurrentPotionState, CurrentRecipeMarkInfo = StaticStorage.CurrentRecipeMarkInfo, PreviousPotionRecipeMarkInfo = StaticStorage.PreviousPotionRecipeMarkInfo, SelectedRecipePotionState = StaticStorage.SelectedRecipePotionState, SelectedRecipeMarkIndex = StaticStorage.SelectedRecipeMarkIndex, SelectedRecipeIndex = StaticStorage.SelectedRecipeIndex, RecipeMarkInfos = StaticStorage.RecipeMarkInfos, ErrorLog = StaticStorage.ErrorLog, Version = "2.0.0.0" }; } private static void LoadSaveState(SaveState loadedSaveState) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown if (loadedSaveState == null) { LogError("Error: An error occured during deserialization. Could not find load save state!"); return; } if (loadedSaveState.CurrentPotionRecipeMarkInfos == null || loadedSaveState.CurrentPotionState == null || loadedSaveState.RecipeMarkInfos == null || loadedSaveState.ErrorLog == null) { LogError("Error: An error occured during deserialization. A property was null!"); return; } StaticStorage.CurrentPotionRecipeMarkInfos = loadedSaveState.CurrentPotionRecipeMarkInfos; StaticStorage.CurrentPotionState = loadedSaveState.CurrentPotionState; StaticStorage.CurrentRecipeMarkInfo = loadedSaveState.CurrentRecipeMarkInfo; StaticStorage.PreviousPotionRecipeMarkInfo = loadedSaveState.PreviousPotionRecipeMarkInfo; StaticStorage.SelectedRecipePotionState = loadedSaveState.SelectedRecipePotionState; StaticStorage.SelectedRecipeMarkIndex = loadedSaveState.SelectedRecipeMarkIndex; StaticStorage.SelectedRecipeIndex = loadedSaveState.SelectedRecipeIndex; StaticStorage.RecipeMarkInfos = loadedSaveState.RecipeMarkInfos; StaticStorage.ErrorLog = loadedSaveState.ErrorLog; StaticStorage.ShouldLoadLastBrewState = StaticStorage.CurrentRecipeMarkInfo != null; int currentPageIndex = ((Book)RecipeBook.Instance).currentPageIndex; if (!RecipeReconstructionService.MarkHasSavedData(currentPageIndex, StaticStorage.SelectedRecipeMarkIndex)) { RecipeBookUIService.DisableOldRecipeMarks((RecipeBookRightPageContent)((Book)RecipeBook.Instance).curlPageController.frontRightPage.pageContent); } else { RecipeBookUIService.UpdateRecipeBookPageForSelectedRecipeMark(currentPageIndex, StaticStorage.SelectedRecipeMarkIndex); } } private static void LogError(string errorMessage) { Plugin.PluginLogger.LogInfo((object)errorMessage); } public static void StoreData(ref string result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown string text = null; try { string obj = result; SaveState saveState = GetSaveState(); if (saveState == null) { LogError("Error: no data found to save!"); } string text2 = JsonConvert.SerializeObject((object)saveState, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1, TypeNameHandling = (TypeNameHandling)4 }); string value = ",\"FahlgorithmUsefulRecipeMarks\":" + text2; int startIndex = obj.LastIndexOf('}'); text = obj.Insert(startIndex, value); } catch (Exception ex) { LogError($"{ex.GetType()}: {ex.Message}\r\n{ex.StackTrace}\r\n{ex.InnerException?.Message}"); } if (!string.IsNullOrEmpty(text)) { result = text; } } public static bool RetreiveStoredData() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown try { SaveLoadService.ClearFileSpecificDataOnFileLoad(); string stateJsonString = StateJsonString; StateJsonString = null; if (string.IsNullOrEmpty(stateJsonString)) { LogError("Error: stateJsonString is empty. Cannot load data."); return true; } if (stateJsonString.IndexOf("FahlgorithmUsefulRecipeMarks") == -1) { LogError("No existing data found during load"); return true; } NamespaceMigrationSerializationBinder serializationBinder = new NamespaceMigrationSerializationBinder(new BasicNamespaceMigration { FromAssembly = "PotionCraftBrewFromHere", FromType = "PotionCraftUsefulRecipeMarks.Scripts.Storage.Delta.ModifyDelta`1[[PotionCraft.SaveLoadSystem.ProgressState+SerializedPath, PotionCraft.Scripts]]", ToType = typeof(ModifyDelta<SerializedPath>) }); LoadSaveState(JsonConvert.DeserializeObject<Deserialized<SaveState>>(stateJsonString, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1, TypeNameHandling = (TypeNameHandling)4, SerializationBinder = (ISerializationBinder)(object)serializationBinder }).DeserializedObject); } catch (Exception ex) { LogError($"{ex.GetType()}: {ex.Message}\r\n{ex.StackTrace}\r\n{ex.InnerException?.Message}"); } return true; } public static bool RetrieveStateJsonString(File instance) { try { StateJsonString = instance.StateJsonString; } catch (Exception ex) { LogError($"{ex.GetType()}: {ex.Message}\r\n{ex.StackTrace}\r\n{ex.InnerException?.Message}"); } return true; } } } namespace PotionCraftUsefulRecipeMarks.Scripts.Storage { public class FixedHintTimeline { public int FixedHintIndex { get; set; } public string IngredientName { get; set; } public float GrindPercent { get; set; } public int AddedRecipeIndex { get; set; } = int.MaxValue; public SortedDictionary<int, List<ModifyDelta>> Timeline { get; set; } = new SortedDictionary<int, List<ModifyDelta>>(); public void AddInformationFromDeltas(List<SerializedRecipeMark> recipeMarks, int recipeMarkIndex, List<ModifyDelta> deltas) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 SerializedRecipeMark val = recipeMarks[recipeMarkIndex]; if ((int)val.type == 1) { IngredientName = val.stringValue; GrindPercent = val.floatValue; } Timeline[recipeMarkIndex] = deltas.Where((ModifyDelta d) => d.Property == DeltaProperty.FixedHint_Length).ToList(); if (recipeMarkIndex < AddedRecipeIndex) { AddedRecipeIndex = recipeMarkIndex; } } } public class RecipeMarkInfo { public int Index { get; set; } public List<BaseDelta> Deltas { get; set; } = new List<BaseDelta>(); } public class ReconstructionTimeline { public Dictionary<int, FixedHintTimeline> FixedHintTimelines = new Dictionary<int, FixedHintTimeline>(); public SortedDictionary<int, List<BaseDelta>> PathRotationTimeline = new SortedDictionary<int, List<BaseDelta>>(); public void AddBasePropertyInformationFromDeltas(List<SerializedRecipeMark> recipeMarks, int recipeMarkIndex, List<BaseDelta> deltas) { List<BaseDelta> list = deltas.Where((BaseDelta d) => d.Property == DeltaProperty.Rotation).ToList(); if (list.Any()) { PathRotationTimeline[recipeMarkIndex] = list; } } public List<(int index, bool fromEnd, float length)> GetPathDeletionEvents(List<SerializedRecipeMark> allRecipeMarks, int fixedHintIndex) { List<(int, bool, float)> deletionEvents = new List<(int, bool, float)>(); if (!FixedHintTimelines.TryGetValue(fixedHintIndex, out var value)) { return deletionEvents; } int addedIndex = value.AddedRecipeIndex; int nextAddedIndex = (from p in FixedHintTimelines where p.Key > fixedHintIndex orderby p.Key select p.Value).FirstOrDefault()?.AddedRecipeIndex ?? int.MaxValue; FixedHintTimelines.Values.ToList().ForEach(delegate(FixedHintTimeline FixedHintTimeline) { float currentLength = -1f; FixedHintTimeline.Timeline.Where((KeyValuePair<int, List<ModifyDelta>> prt) => prt.Key < nextAddedIndex).ToList().ForEach(delegate(KeyValuePair<int, List<ModifyDelta>> prt) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 ModifyDelta<float> modifyDelta = prt.Value.FirstOrDefault((ModifyDelta d) => d.Property == DeltaProperty.FixedHint_Length) as ModifyDelta<float>; if (!(modifyDelta == null)) { if (currentLength < 0f) { currentLength = modifyDelta.NewValue; } else { SerializedRecipeMark val = allRecipeMarks[prt.Key]; bool item = (int)val.type == 5 && val.stringValue == "Void Salt"; float num = currentLength - modifyDelta.NewValue; if (num < 0f) { throw new Exception("Looks like someone added a new salt. This mod simply cannot handle paths which increase in length."); } if (!(num < 0.0001f)) { if (prt.Key >= addedIndex) { deletionEvents.Add((prt.Key, item, num)); } currentLength = modifyDelta.NewValue; } } } }); }); return deletionEvents; } public List<(int index, Quaternion rotation)> GetRotationEventsForFixedHint(int fixedHintIndex) { List<(int, Quaternion)> rotationEvents = new List<(int, Quaternion)>(); if (!FixedHintTimelines.TryGetValue(fixedHintIndex, out var value)) { return rotationEvents; } int addedIndex = value.AddedRecipeIndex; int nextAddedIndex = (from p in FixedHintTimelines where p.Key > fixedHintIndex orderby p.Key select p.Value).FirstOrDefault()?.AddedRecipeIndex ?? int.MaxValue; PathRotationTimeline.Where((KeyValuePair<int, List<BaseDelta>> prt) => prt.Key >= addedIndex && prt.Key < nextAddedIndex).ToList().ForEach(delegate(KeyValuePair<int, List<BaseDelta>> prt) { AddRotationEvent(prt.Key, prt.Value, rotationEvents); }); return rotationEvents; } private void AddRotationEvent(int index, List<BaseDelta> deltas, List<(int, Quaternion)> rotationEvents) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) ModifyDelta<float> modifyDelta = deltas.FirstOrDefault((BaseDelta d) => d.Property == DeltaProperty.Rotation) as ModifyDelta<float>; if (modifyDelta == null) { return; } float num = (from p in PathRotationTimeline where p.Key < index orderby p.Key descending select p.Value.FirstOrDefault((BaseDelta d) => d.Property == DeltaProperty.Rotation) as ModifyDelta<float> into p where p != null select p).FirstOrDefault()?.NewValue ?? 0f; float newValue = modifyDelta.NewValue; if (newValue != num) { rotationEvents.Add((index, Quaternion.Euler(0f, 0f, newValue - num))); } } } public static class StaticStorage { public static List<string> ErrorLog = new List<string>(); public static bool AddedListeners; public static Dictionary<int, RecipeMarkInfo> CurrentPotionRecipeMarkInfos = new Dictionary<int, RecipeMarkInfo>(); public static Dictionary<DeltaProperty, BaseDelta> CurrentPotionState = new Dictionary<DeltaProperty, BaseDelta>(); public static RecipeMarkInfo CurrentRecipeMarkInfo; public static Dictionary<int, RecipeMarkInfo> PreviousPotionRecipeMarkInfo; public static Dictionary<DeltaProperty, BaseDelta> SelectedRecipePotionState; public static int SelectedRecipeMarkIndex; public static int SelectedRecipeIndex; public static Dictionary<int, Dictionary<int, RecipeMarkInfo>> RecipeMarkInfos = new Dictionary<int, Dictionary<int, RecipeMarkInfo>>(); public static bool ShouldLoadLastBrewState; public static bool BookmarkOrganizerOldVersionInstalled; public static List<IRecipeBookPageContent> RecipeIndexes; } public class UsefulRecipeMarksManager : MonoBehaviour { public Dictionary<int, RecipeMarkInfo> CurrentPotionRecipeMarkInfos => StaticStorage.CurrentPotionRecipeMarkInfos; public Dictionary<DeltaProperty, BaseDelta> CurrentPotionState => StaticStorage.CurrentPotionState; public RecipeMarkInfo CurrentRecipeMarkInfo => StaticStorage.CurrentRecipeMarkInfo; public Dictionary<int, Dictionary<int, RecipeMarkInfo>> RecipeMarkInfos => StaticStorage.RecipeMarkInfos; public Dictionary<int, RecipeMarkInfo> PreviousPotionRecipeMarkInfo => StaticStorage.PreviousPotionRecipeMarkInfo; public Dictionary<DeltaProperty, BaseDelta> SelectedRecipePotionState => StaticStorage.SelectedRecipePotionState; public int SelectedRecipeMarkIndex => StaticStorage.SelectedRecipeMarkIndex; public int SelectedRecipeIndex => StaticStorage.SelectedRecipeIndex; public List<IRecipeBookPageContent> RecipeIndexes => StaticStorage.RecipeIndexes; } } namespace PotionCraftUsefulRecipeMarks.Scripts.Storage.Delta { public abstract class BaseDelta { public DeltaProperty Property { get; set; } public static bool operator ==(BaseDelta obj1, BaseDelta obj2) { if ((object)obj1 == null || (object)obj2 == null) { if ((object)obj1 == null) { return (object)obj2 == null; } return false; } return obj1.Equals(obj2); } public static bool operator !=(BaseDelta obj1, BaseDelta obj2) { if ((object)obj1 == null || (object)obj2 == null) { if ((object)obj1 == null) { return (object)obj2 != null; } return true; } return !obj1.Equals(obj2); } public override bool Equals(object obj) { if (obj is BaseDelta baseDelta) { return baseDelta.Property == Property; } return false; } public override int GetHashCode() { return HashCode.Combine(Property); } } public enum DeltaProperty { IndicatorPosition = 0, PathPosition = 1, IndicatorTargetPosition = 2, FollowButtonTargetPosition = 3, Rotation = 10, PathHints = 20, PathDeletedSegments = 30, PathAddedFixedHints = 35, PathFixedHintsCount = 36, FixedHints = 50, FixedHint_Length = 53, FixedHint_ConnectionPoint = 54, UsedComponents = 60, UsedComponent_Ammount = 61, Effects = 70, Health = 80, OldSerializedPath = 1000, IsOldFixedHint = 1010 } public class ListAddDelta : BaseDelta { public int Index { get; set; } public List<ModifyDelta> Deltas { get; set; } = new List<ModifyDelta>(); public override bool Equals(object obj) { if (!base.Equals(obj)) { return false; } if (!(obj is ListAddDelta listAddDelta)) { return false; } if (Index == listAddDelta.Index) { return Deltas.SequenceEqual(listAddDelta.Deltas); } return false; } public override int GetHashCode() { int hashCode = base.GetHashCode(); Deltas.ForEach(delegate(ModifyDelta delta) { hashCode = HashCode.Combine(hashCode, delta.GetHashCode()); }); return hashCode; } } public class ListDelta : BaseDelta { public List<ListAddDelta> AddDeltas { get; set; } = new List<ListAddDelta>(); public override bool Equals(object obj) { if (!base.Equals(obj)) { return false; } if (!(obj is ListDelta listDelta)) { return false; } return AddDeltas.SequenceEqual(listDelta.AddDeltas); } public override int GetHashCode() { int hashCode = HashCode.Combine(base.GetHashCode(), AddDeltas.Count); AddDeltas.ForEach(delegate(ListAddDelta delta) { hashCode = HashCode.Combine(hashCode, delta.GetHashCode()); }); return hashCode; } } public class ListModifyDelta<T> : ModifyDelta<T> { public int Index { get; set; } } public abstract class ModifyDelta : BaseDelta { } public class ModifyDelta<T> : ModifyDelta { public T NewValue { get; set; } public override bool Equals(object obj) { if (!base.Equals(obj)) { return false; } if (!(obj is ModifyDelta<T> modifyDelta)) { return false; } if (NewValue == null || modifyDelta.NewValue == null) { if (NewValue == null) { return modifyDelta.NewValue == null; } return false; } T newValue = modifyDelta.NewValue; if (!((object)newValue is string b)) { if (newValue is float) { object obj2 = newValue; float num = (float)((obj2 is float) ? obj2 : null); return (double)Mathf.Abs((NewValue as float?).Value - num) < 1E-05; } if ((object)newValue is List<string> list) { return (NewValue as List<string>)?.SequenceEqual(list) ?? (list == null); } return EqualityComparer<T>.Default.Equals(NewValue, modifyDelta.NewValue); } return string.Equals(NewValue as string, b); } public override int GetHashCode() { int hashCode = base.GetHashCode(); T newValue = NewValue; return HashCode.Combine(hashCode, (newValue != null) ? newValue.GetHashCode() : 0); } } } namespace PotionCraftUsefulRecipeMarks.Scripts.Services { public static class DeltaRecordingService { public const string VoidSaltName = "Void Salt"; private static RecipeBookRecipeMarkType? LastRecipeMarkType; private static string LastRecipeMarkStringValue; private static Dictionary<DeltaProperty, BaseDelta> TemporaryCurrentPotionState; private static Vector2 indicatorPosition; private static Vector2 pathPosition; private static Vector2 indicatorTargetPosition; private static Vector2 followButtonTargetPosition; private static float rotation; private static float health; private static bool didDeleteFixedHintViaVoidSalt; public static void RecordRecipeMarkInfo() { PotionManager potion = Managers.Potion; bool? obj; if (potion == null) { obj = null; } else { PotionCraftPanel potionCraftPanel = potion.potionCraftPanel; obj = ((potionCraftPanel != null) ? new bool?(!potionCraftPanel.IsPotionBrewingStarted()) : null); } bool? flag = obj; if (!flag.GetValueOrDefault()) { RecordRecipeMarkInfo(Managers.Potion.recipeMarks.GetMarksList().LastOrDefault()); } } public static void SetupInitialInfoForRecipe(RecipeBookRightPageContent rightPageContent) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown int currentPageIndex = ((Book)RecipeBook.Instance).currentPageIndex; SetupInitialInfoForRecipe(Extensions.GetRecipeData((Potion)rightPageContent.GetRecipeBookPageContent()), currentPageIndex); } public static void SetupInitialInfoForRecipe(SerializedPotionRecipeData potionFromPanel, int recipeIndex) { if (!StaticStorage.RecipeMarkInfos.TryGetValue(recipeIndex, out var value)) { RecipeBook.Instance.currentRecipeIndexes[(RecipeBookPageContentType)1] = recipeIndex; SetupInitialInfo(); StaticStorage.CurrentPotionRecipeMarkInfos[0].Deltas.Add(new ModifyDelta<SerializedPath> { Property = DeltaProperty.OldSerializedPath, NewValue = potionFromPanel.serializedPath }); List<ListAddDelta> addDeltas = ((ListDelta)StaticStorage.CurrentPotionState[DeltaProperty.FixedHints]).AddDeltas; List<ListAddDelta> addDeltas2 = ((ListDelta)StaticStorage.CurrentPotionRecipeMarkInfos[0].Deltas.First((BaseDelta d) => d.Property == DeltaProperty.FixedHints)).AddDeltas; addDeltas.Concat(addDeltas2).ToList().ForEach(delegate(ListAddDelta fixedHintDelta) { fixedHintDelta.Deltas.Add(new ModifyDelta<bool> { Property = DeltaProperty.IsOldFixedHint, NewValue = true }); }); } else { int selectedRecipeMarkIndex = StaticStorage.SelectedRecipeMarkIndex; StaticStorage.CurrentPotionRecipeMarkInfos = ((value.Count > selectedRecipeMarkIndex) ? value.Take(selectedRecipeMarkIndex + 1).ToDictionary((KeyValuePair<int, RecipeMarkInfo> kvp) => kvp.Key, (KeyValuePair<int, RecipeMarkInfo> kvp) => kvp.Value) : value); List<SerializedRecipeMark> marksList = Managers.Potion.recipeMarks.GetMarksList(); while (marksList.Count > selectedRecipeMarkIndex + 1) { marksList.RemoveAt(marksList.Count - 1); } if (StaticStorage.SelectedRecipePotionState != null) { StaticStorage.CurrentPotionState = StaticStorage.SelectedRecipePotionState; } } } public static void CommitRecipeMarkInfoForSavedRecipe() { int num = RecipeBook.Instance.savedRecipes.IndexOf(null); if (num != -1) { if (Managers.Potion.potionCraftPanel.previousPotionRecipe != null) { StaticStorage.RecipeMarkInfos[num] = StaticStorage.PreviousPotionRecipeMarkInfo; StaticStorage.PreviousPotionRecipeMarkInfo = null; } else { RecordRecipeMarkInfo(null); StaticStorage.RecipeMarkInfos[num] = StaticStorage.CurrentPotionRecipeMarkInfos; } } } public static void ResetPotion() { Plugin.PluginLogger.LogMessage((object)$"ResetPotion - {StaticStorage.ShouldLoadLastBrewState} - {StaticStorage.CurrentPotionRecipeMarkInfos != null} - {StaticStorage.CurrentPotionState != null}"); if (StaticStorage.ShouldLoadLastBrewState) { StaticStorage.ShouldLoadLastBrewState = false; if (StaticStorage.CurrentPotionRecipeMarkInfos != null && StaticStorage.CurrentPotionState != null) { return; } } Plugin.PluginLogger.LogMessage((object)"ResetPotion - 1"); if (Managers.Potion.potionCraftPanel.potionChangedAfterSavingRecipe) { RecordRecipeMarkInfo(null); StaticStorage.PreviousPotionRecipeMarkInfo = StaticStorage.CurrentPotionRecipeMarkInfos; } SetupInitialInfo(); } public static void ClearPreviousSavedPotionRecipeMarkInfo(bool potionUpdated) { Ex.RunSafe(delegate { if (potionUpdated) { StaticStorage.PreviousPotionRecipeMarkInfo = null; } }); } public static void SetupInitialInfo() { Plugin.PluginLogger.LogMessage((object)"SetupInitialInfo"); StaticStorage.CurrentPotionState = new Dictionary<DeltaProperty, BaseDelta>(); RecordPositionInfo(); SetupCurrentPotionState(useTemporaryStateDict: false); StaticStorage.CurrentPotionRecipeMarkInfos = new Dictionary<int, RecipeMarkInfo> { [0] = new RecipeMarkInfo { Index = 0, Deltas = StaticStorage.CurrentPotionState.Values.ToList() } }; StaticStorage.CurrentRecipeMarkInfo = null; } public static void RecordRecipeMarkInfo(SerializedRecipeMark recipeMark) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected I4, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 if (recipeMark != null && (int)recipeMark.type == 0) { return; } if (StaticStorage.CurrentRecipeMarkInfo != null && (LastRecipeMarkType != recipeMark?.type || (recipeMark != null && (int)recipeMark.type == 1) || (recipeMark != null && (int)recipeMark.type == 5 && recipeMark?.stringValue != LastRecipeMarkStringValue))) { CommitPositionInfo(); if (didDeleteFixedHintViaVoidSalt) { didDeleteFixedHintViaVoidSalt = false; StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(GetBaseProperty(DeltaProperty.PathAddedFixedHints)); } StaticStorage.CurrentPotionRecipeMarkInfos[StaticStorage.CurrentRecipeMarkInfo.Index] = StaticStorage.CurrentRecipeMarkInfo; if (TemporaryCurrentPotionState != null) { StaticStorage.CurrentPotionState = TemporaryCurrentPotionState; } } if (recipeMark == null) { return; } LastRecipeMarkType = recipeMark.type; LastRecipeMarkStringValue = recipeMark.stringValue; int index = Managers.Potion.recipeMarks.GetMarksList().IndexOf(recipeMark); StaticStorage.CurrentRecipeMarkInfo = new RecipeMarkInfo { Index = index }; RecipeBookRecipeMarkType type = recipeMark.type; switch (type - 1) { case 1: RecordPositionInfo(); RecordMoveAlongPathInfo(); break; case 2: RecordPositionInfo(); break; case 3: RecordEffectInfo(); break; case 4: RecordPositionInfo(); RecordUsedComponentInfo(recipeMark.stringValue); if (recipeMark.stringValue == "Void Salt") { HandleDeletedFixedHintFromVoidSalt(); RecordEndPathHintInfo(); } else { RecordConnectionPointInfo(); } break; case 0: RecordNewIngredientInfo(recipeMark.stringValue); break; } SetupCurrentPotionState(useTemporaryStateDict: true); } private static void SetupCurrentPotionState(bool useTemporaryStateDict) { StaticStorage.CurrentPotionState.TryGetValue(DeltaProperty.PathAddedFixedHints, out var value); if (useTemporaryStateDict) { TemporaryCurrentPotionState = new Dictionary<DeltaProperty, BaseDelta>(); } else { StaticStorage.CurrentPotionState = new Dictionary<DeltaProperty, BaseDelta>(); } Dictionary<DeltaProperty, BaseDelta> currentPotionState = (useTemporaryStateDict ? TemporaryCurrentPotionState : StaticStorage.CurrentPotionState); if (value != null) { currentPotionState[DeltaProperty.PathAddedFixedHints] = value; } else { currentPotionState[DeltaProperty.PathAddedFixedHints] = GetBaseProperty(DeltaProperty.PathAddedFixedHints); } currentPotionState[DeltaProperty.UsedComponents] = GetUsedComponentsProperty(); currentPotionState[DeltaProperty.FixedHints] = GetFixedHintsProperty(); List<DeltaProperty> list = new List<DeltaProperty>(); list.Add(DeltaProperty.IndicatorPosition); list.Add(DeltaProperty.PathPosition); list.Add(DeltaProperty.IndicatorTargetPosition); list.Add(DeltaProperty.FollowButtonTargetPosition); list.Add(DeltaProperty.Rotation); list.Add(DeltaProperty.Health); list.Add(DeltaProperty.Effects); list.Add(DeltaProperty.PathDeletedSegments); list.Add(DeltaProperty.PathFixedHintsCount); list.ForEach(delegate(DeltaProperty p) { currentPotionState[p] = GetBaseProperty(p); }); } private static void RecordPositionInfo() { //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_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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) indicatorPosition = ((ModifyDelta<(float, float)>)GetBaseProperty(DeltaProperty.IndicatorPosition)).NewValue.ToVector(); pathPosition = ((ModifyDelta<(float, float)>)GetBaseProperty(DeltaProperty.PathPosition)).NewValue.ToVector(); indicatorTargetPosition = ((ModifyDelta<(float, float)>)GetBaseProperty(DeltaProperty.IndicatorTargetPosition)).NewValue.ToVector(); followButtonTargetPosition = ((ModifyDelta<(float, float)>)GetBaseProperty(DeltaProperty.FollowButtonTargetPosition)).NewValue.ToVector(); rotation = ((ModifyDelta<float>)GetBaseProperty(DeltaProperty.Rotation)).NewValue; health = ((ModifyDelta<float>)GetBaseProperty(DeltaProperty.Health)).NewValue; } private static void CommitPositionInfo() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) CommitProperty(DeltaProperty.IndicatorPosition, indicatorPosition.ToTuple()); CommitProperty(DeltaProperty.PathPosition, pathPosition.ToTuple()); CommitProperty(DeltaProperty.IndicatorTargetPosition, indicatorTargetPosition.ToTuple()); CommitProperty(DeltaProperty.FollowButtonTargetPosition, followButtonTargetPosition.ToTuple()); CommitProperty(DeltaProperty.Rotation, rotation); CommitProperty(DeltaProperty.Health, health); } private static void CommitProperty<T>(DeltaProperty property, T value) { ModifyDelta<T> modifyDelta = new ModifyDelta<T> { Property = property, NewValue = value }; if (StaticStorage.CurrentPotionState[property] != modifyDelta) { StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(modifyDelta); } } private static void RecordMoveAlongPathInfo() { RecordProperty(DeltaProperty.PathDeletedSegments); ListDelta listDelta = (ListDelta)StaticStorage.CurrentPotionState[DeltaProperty.FixedHints]; int fixedPathHintsCount = GetFixedPathHintsCount(); if (fixedPathHintsCount < listDelta.AddDeltas.Count) { StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(GetBaseProperty(DeltaProperty.PathFixedHintsCount)); } int num = listDelta.AddDeltas.Count - fixedPathHintsCount; FixedHint val = ((IEnumerable<FixedHint>)Managers.RecipeMap.path.fixedPathHints).FirstOrDefault((Func<FixedHint, bool>)((FixedHint fph) => fph.GetPathLength() > 0.001f)); if (!((Object)(object)val == (Object)null)) { int index = Managers.RecipeMap.path.fixedPathHints.IndexOf(val); RecordListObjectInfo<FixedHint>(DeltaProperty.FixedHints, val, index, num); RecordConnectionPointInfo(num); } } private static void RecordConnectionPointInfo(int indexOffset = 0) { for (int i = 1; i < Managers.RecipeMap.path.fixedPathHints.Count; i++) { FixedHint sourceAdded = Managers.RecipeMap.path.fixedPathHints[i]; RecordListObjectInfo<FixedHint>(DeltaProperty.FixedHints, sourceAdded, i, i + indexOffset, new List<DeltaProperty> { DeltaProperty.FixedHint_ConnectionPoint }); } } private static void RecordEffectInfo() { RecordProperty(DeltaProperty.Effects); } private static void RecordNewIngredientInfo(string ingredientName) { ((ModifyDelta<int>)StaticStorage.CurrentPotionState[DeltaProperty.PathAddedFixedHints]).NewValue++; RecordNewListAddInfo(DeltaProperty.FixedHints, Managers.RecipeMap.path.fixedPathHints); StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(GetBaseProperty(DeltaProperty.PathAddedFixedHints)); StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(GetBaseProperty(DeltaProperty.PathFixedHintsCount)); RecordUsedComponentInfo(ingredientName); } private static void RecordEndPathHintInfo() { RecordNewListAddInfo(DeltaProperty.FixedHints, Managers.RecipeMap.path.fixedPathHints, Managers.RecipeMap.path.fixedPathHints.Count - 1); } private static void HandleDeletedFixedHintFromVoidSalt() { ListDelta listDelta = (ListDelta)StaticStorage.CurrentPotionState[DeltaProperty.FixedHints]; int fixedPathHintsCount = GetFixedPathHintsCount(); if (fixedPathHintsCount == listDelta.AddDeltas.Count - 1) { didDeleteFixedHintViaVoidSalt = true; listDelta.AddDeltas = listDelta.AddDeltas.Take(fixedPathHintsCount).ToList(); ((ModifyDelta<int>)StaticStorage.CurrentPotionState[DeltaProperty.PathAddedFixedHints]).NewValue--; } } private static void RecordUsedComponentInfo(string usedComponentName) { List<AlchemySubstanceComponent> summaryComponents = Managers.Potion.PotionUsedComponents.GetSummaryComponents(); AlchemySubstanceComponent val = ((IEnumerable<AlchemySubstanceComponent>)summaryComponents).FirstOrDefault((Func<AlchemySubstanceComponent, bool>)((AlchemySubstanceComponent c) => ((Object)c.Component).name == usedComponentName)); if (val == null) { throw new ArgumentException("Cannot record new used component info for " + usedComponentName + ". Used component not found in usedComponents list"); } RecordListObjectInfo<AlchemySubstanceComponent>(DeltaProperty.UsedComponents, val, summaryComponents.IndexOf(val)); } private static void RecordNewListAddInfo<T>(DeltaProperty property, List<T> sourceList, int indexOverride = -1) { T val = sourceList.LastOrDefault(); if (val == null) { throw new InvalidOperationException($"RecordNewListAddInfo should only be called when a new item is added. No {property} found!"); } RecordListObjectInfo(property, val, (indexOverride == -1) ? (sourceList.Count - 1) : indexOverride); } private static void RecordListObjectInfo<T>(DeltaProperty property, T sourceAdded, int index, int addDeltaIndex = -1, List<DeltaProperty> propertiesToRecord = null) { ListDelta listDelta = StaticStorage.CurrentPotionState[property] as ListDelta; ListAddDelta baseAddDelta = GetBaseAddDelta(sourceAdded, index, propertiesToRecord); if (addDeltaIndex == -1) { addDeltaIndex = index; } ListAddDelta lastAddedDelta = ((listDelta.AddDeltas.Count > addDeltaIndex) ? listDelta.AddDeltas[addDeltaIndex] : null); if (lastAddedDelta != null && lastAddedDelta == baseAddDelta) { return; } if (lastAddedDelta == null) { StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(baseAddDelta); return; } IEnumerable<ModifyDelta> source = baseAddDelta.Deltas.Where(delegate(ModifyDelta newProperty) { ModifyDelta modifyDelta = lastAddedDelta.Deltas.FirstOrDefault((ModifyDelta d) => d.Property == newProperty.Property); return modifyDelta == null || newProperty != modifyDelta; }); ListAddDelta item = new ListAddDelta { Property = baseAddDelta.Property, Index = baseAddDelta.Index, Deltas = source.ToList() }; StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(item); } private static void RecordProperty(DeltaProperty property) { ModifyDelta baseProperty = GetBaseProperty(property); if (StaticStorage.CurrentPotionState[property] != baseProperty) { StaticStorage.CurrentRecipeMarkInfo.Deltas.Add(baseProperty); } } private static ListDelta GetUsedComponentsProperty() { return new ListDelta { Property = DeltaProperty.UsedComponents, AddDeltas = (from d in Managers.Potion.PotionUsedComponents.GetSummaryComponents().Select((AlchemySubstanceComponent u, int i) => GetBaseAddDelta(u, i)) where d != null select d).ToList() }; } private static ListDelta GetFixedHintsProperty() { return new ListDelta { Property = DeltaProperty.FixedHints, AddDeltas = (from d in Managers.RecipeMap.path.fixedPathHints.Select((FixedHint h, int i) => GetBaseAddDelta(h, i)) where d != null select d).ToList() }; } private static ListAddDelta GetBaseAddDelta(object obj, int index, List<DeltaProperty> propertiesToRecord = null) { if (obj == null) { return null; } DeltaProperty deltaProperty; if (!(obj is AlchemySubstanceComponent)) { if (!(obj is FixedHint)) { throw new ArgumentException($"Object of type: {obj.GetType()} is not a valid list add object!"); } deltaProperty = DeltaProperty.FixedHints; } else { deltaProperty = DeltaProperty.UsedComponents; } DeltaProperty deltaProperty2 = deltaProperty; if (deltaProperty2 == DeltaProperty.FixedHints) { int num = ((ModifyDelta<int>)StaticStorage.CurrentPotionState[DeltaProperty.PathAddedFixedHints]).NewValue - Managers.RecipeMap.path.fixedPathHints.Count; index += num; } return new ListAddDelta { Index = index, Property = deltaProperty2, Deltas = ((propertiesToRecord == null) ? GetAllBaseProperties(obj) : propertiesToRecord.Select((DeltaProperty p) => GetListObjectProperty(p, obj)).ToList()) }; } private static List<ModifyDelta> GetAllBaseProperties(object obj) { if (obj == null) { return new List<ModifyDelta>(); } List<DeltaProperty> source; if (!(obj is AlchemySubstanceComponent)) { if (!(obj is FixedHint)) { throw new ArgumentException($"Object of type: {obj.GetType()} is not a valid list add object!"); } source = new List<DeltaProperty> { DeltaProperty.FixedHint_Length, DeltaProperty.FixedHint_ConnectionPoint }; } else { source = new List<DeltaProperty> { DeltaProperty.UsedComponent_Ammount }; } return source.Select((DeltaProperty p) => GetListObjectProperty(p, obj)).ToList(); } private static ModifyDelta GetListObjectProperty(DeltaProperty property, object obj) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0044: 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) return property switch { DeltaProperty.UsedComponent_Ammount => new ModifyDelta<int> { Property = DeltaProperty.UsedComponent_Ammount, NewValue = ((AlchemySubstanceComponent)obj).Amount }, DeltaProperty.FixedHint_ConnectionPoint => new ModifyDelta<(float, float)> { Property = DeltaProperty.FixedHint_ConnectionPoint, NewValue = GetConnectionPointForFixedHint((FixedHint)obj).ToTuple() }, DeltaProperty.FixedHint_Length => new ModifyDelta<float> { Property = DeltaProperty.FixedHint_Length, NewValue = GetFixedHintPathLength((FixedHint)obj) }, _ => throw new ArgumentException($"Property: {property} is not a list object property!"), }; } private static Vector2 GetConnectionPointForFixedHint(FixedHint obj) { //IL_001a: 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_0100: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) int num = Managers.RecipeMap.path.fixedPathHints.IndexOf(obj); switch (num) { case -1: return Vector2.zero; case 0: { ModifyDelta<(float, float)> modifyDelta = GetFixedHintDeltaForFixedHint(obj)?.Deltas?.FirstOrDefault((ModifyDelta d) => d.Property == DeltaProperty.FixedHint_ConnectionPoint) as ModifyDelta<(float, float)>; if (modifyDelta != null) { return modifyDelta.NewValue.ToVector(); } return Vector2.op_Implicit(Managers.RecipeMap.path.fixedPathHints.First().evenlySpacedPointsFixedGraphics.points.First()); } default: { Vector3[] points = Managers.RecipeMap.path.fixedPathHints[num - 1].evenlySpacedPointsFixedGraphics.points; if (!points.Any()) { return Vector2.op_Implicit(Managers.RecipeMap.path.fixedPathHints.First().evenlySpacedPointsFixedGraphics.points.First()); } return Vector2.op_Implicit(points.Last()); } } } private static float GetPreviouslyRecordedLengthForFixedHint(FixedHint obj) { if (StaticStorage.CurrentPotionState.ContainsKey(DeltaProperty.PathAddedFixedHints) && StaticStorage.CurrentPotionState.ContainsKey(DeltaProperty.FixedHints)) { ModifyDelta<float> modifyDelta = GetFixedHintDeltaForFixedHint(obj)?.Deltas?.FirstOrDefault((ModifyDelta d) => d.Property == DeltaProperty.FixedHint_Length) as ModifyDelta<float>; if (modifyDelta != null) { return modifyDelta.NewValue; } } return GetFixedHintPathLength(obj); } private static ListAddDelta GetFixedHintDeltaForFixedHint(FixedHint obj) { if (!StaticStorage.CurrentPotionState.ContainsKey(DeltaProperty.PathAddedFixedHints) || !StaticStorage.CurrentPotionState.ContainsKey(DeltaProperty.FixedHints)) { return null; } int index = Managers.RecipeMap.path.fixedPathHints.IndexOf(obj); int num = ((ModifyDelta<int>)StaticStorage.CurrentPotionState[DeltaProperty.PathAddedFixedHints]).NewValue - GetFixedPathHintsCount(); index += num; return ((ListDelta)StaticStorage.CurrentPotionState[DeltaProperty.FixedHints]).AddDeltas.FirstOrDefault((ListAddDelta d) => d.Index == index); } private static float GetFixedHintPathLength(FixedHint hint) { PathMapItem path = Managers.RecipeMap.path; return hint.GetPathLength() - path.segmentLengthToDeleteFromEndGraphics; } private static ModifyDelta GetBaseProperty(DeltaProperty property) { //IL_007b: 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) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) BaseDelta value; return property switch { DeltaProperty.IndicatorPosition => new ModifyDelta<(float, float)> { Property = DeltaProperty.IndicatorPosition, NewValue = ((RecipeMapItem)Managers.RecipeMap.indicator).thisTransform.localPosition.ToTuple() }, DeltaProperty.PathPosition => new ModifyDelta<(float, float)> { Property = DeltaProperty.PathPosition, NewValue = ((Component)Managers.RecipeMap.path).transform.localPosition.ToTuple() }, DeltaProperty.IndicatorTargetPosition => new ModifyDelta<(float, float)> { Property = DeltaProperty.IndicatorTargetPosition, NewValue = Extensions.ToTuple((Vector2)Traverse.Create((object)Managers.RecipeMap.indicator).Field("targetPosition").GetValue()) }, DeltaProperty.FollowButtonTargetPosition => new ModifyDelta<(float, float)> { Property = DeltaProperty.FollowButtonTargetPosition, NewValue = Managers.RecipeMap.recipeMapObject.followButtonTargetObject.localPosition.ToTuple() }, DeltaProperty.Rotation => new ModifyDelta<float> { Property = DeltaProperty.Rotation, NewValue = Managers.RecipeMap.indicatorRotation.Value }, DeltaProperty.Health => new ModifyDelta<float> { Property = DeltaProperty.Health, NewValue = (float)Traverse.Create((object)Managers.RecipeMap.indicator).Field("visualHealth").GetValue() }, DeltaProperty.Effects => new ModifyDelta<List<string>> { Property = DeltaProperty.Effects, NewValue = (from e in Managers.Potion.collectedPotionEffects where (ComparableScriptableObject<PotionEffect>)(object)e != (ComparableScriptableObject<PotionEffect>)null select ((Object)e).name).ToList() }, DeltaProperty.PathDeletedSegments => new ModifyDelta<float> { Property = DeltaProperty.PathDeletedSegments, NewValue = Managers.RecipeMap.path.deletedGraphicsSegments }, DeltaProperty.PathAddedFixedHints => new ModifyDelta<int> { Property = DeltaProperty.PathAddedFixedHints, NewValue = (StaticStorage.CurrentPotionState.TryGetValue(DeltaProperty.PathAddedFixedHints, out value) ? ((ModifyDelta<int>)value).NewValue : GetFixedPathHintsCount()) }, DeltaProperty.PathFixedHintsCount => new ModifyDelta<int> { Property = DeltaProperty.PathFixedHintsCount, NewValue = GetFixedPathHintsCount() }, _ => throw new ArgumentException($"Property: {property} is not a base property!"), }; } private static int GetFixedPathHintsCount() { return Managers.RecipeMap.path.fixedPathHints.Where((FixedHint fph) => fph.GetPathLength() > 0.001f).Count(); } public static void DeleteMarkInfoForRecipe(Potion recipe) { int key = RecipeBook.Instance.savedRecipes.IndexOf((IRecipeBookPageContent)(object)recipe); if (StaticStorage.RecipeMarkInfos.ContainsKey(key)) { StaticStorage.RecipeMarkInfos.Remove(key); } } private static void DebugPrintDeltas(Dictionary<int, RecipeMarkInfo> recipeMarkInfo) { //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_0017: Expected O, but got Unknown Plugin.PluginLogger.LogMessage((object)JsonConvert.SerializeObject((object)recipeMarkInfo, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 })); } private static void DebugPrintDeltas() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Plugin.PluginLogger.LogMessage((object)JsonConvert.SerializeObject((object)StaticStorage.CurrentRecipeMarkInfo, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 })); } } public class RecipeBookUIService { private static Color? MarkDefaultColor; private static Color? TextDefaultColor; public static void UpdateRecipeBookPageForSelectedRecipeMark(Button __instance) { RecipeBookRecipeMark val = (RecipeBookRecipeMark)(object)((__instance is RecipeBookRecipeMark) ? __instance : null); if (val == null) { return; } int currentPageIndex = ((Book)RecipeBook.Instance).currentPageIndex; int currentMarkIndex = val.currentMarkIndex; if (IsAlchemyMachineRecipe(RecipeBook.Instance.savedRecipes[currentPageIndex]) || currentMarkIndex == 0) { return; } int markIndexOverride = -1; if (!RecipeReconstructionService.MarkHasSavedData(currentPageIndex, currentMarkIndex)) { if (!RecipeReconstructionService.MarkHasSavedData(currentPageIndex, currentMarkIndex + 1)) { Notification.ShowText("This recipe mark is missing critical information", "You can only continue brewing from new recipe marks", (TextType)0); return; } markIndexOverride = 0; } UpdateRecipeBookPageForSelectedRecipeMark(currentPageIndex, currentMarkIndex, markIndexOverride); } public static void UpdateRecipeBookPageForSelectedRecipeMark(int recipeIndex, int markIndex, int markIndexOverride = -1) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown Potion potionForRecipeMark = RecipeReconstructionService.GetPotionForRecipeMark(recipeIndex, (markIndexOverride == -1) ? markIndex : markIndexOverride); if (!((Object)(object)potionForRecipeMark == (Object)null)) { StaticStorage.SelectedRecipeMarkIndex = markIndex; StaticStorage.SelectedRecipeIndex = recipeIndex; Page frontLeftPage = ((Book)RecipeBook.Instance).curlPageController.frontLeftPage; Page frontRightPage = ((Book)RecipeBook.Instance).curlPageController.frontRightPage; frontLeftPage.UpdatePageContent((PageContentState)1, (IBookPageContent)(object)potionForRecipeMark, frontRightPage); frontRightPage.UpdatePageContent((PageContentState)1, (IBookPageContent)(object)potionForRecipeMark, frontLeftPage); bool num = potionForRecipeMark.GetRecipeData().recipeMarks.Count - 1 != markIndex; RecipeBookRightPageContent val = (RecipeBookRightPageContent)frontRightPage.pageContent; RecipeBookBrewRecipeButton val2 = (RecipeBookBrewRecipeButton)Traverse.Create((object)Traverse.Create((object)val).Field<RecipeBookRightPageBottomButtonsController>("bottomButtonsController").Value).Field("brewRecipeSoloButton").GetValue(); val2.UpdateVisual(); if (num) { DisableRecipeWaypointsUIElements(val); } if (num) { ((Button)val2).Locked = true; } } } public static void EnableDisableMark(RecipeBookRecipeMark mark) { int currentPageIndex = ((Book)RecipeBook.Instance).currentPageIndex; if (StaticStorage.SelectedRecipeMarkIndex > 0 && StaticStorage.SelectedRecipeIndex == currentPageIndex && StaticStorage.RecipeMarkInfos.ContainsKey(currentPageIndex)) { EnableDisableMark(mark, mark.currentMarkIndex <= StaticStorage.SelectedRecipeMarkIndex); return; } bool num = StaticStorage.RecipeMarkInfos.ContainsKey(currentPageIndex); int currentMarkIndex = mark.currentMarkIndex; bool enabled = !num || (currentMarkIndex != 0 && (RecipeReconstructionService.MarkHasSavedData(currentPageIndex, currentMarkIndex) || RecipeReconstructionService.MarkHasSavedData(currentPageIndex, currentMarkIndex + 1))); EnableDisableMark(mark, enabled); } private static void EnableDisableMark(RecipeBookRecipeMark mark, bool enabled) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) ((Component)mark).GetComponentsInChildren<SpriteRenderer>().ToList().ForEach(delegate(SpriteRenderer r) { //IL_0021: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0031: Unknown result type (might be due to invalid IL or missing references) if (!MarkDefaultColor.HasValue) { MarkDefaultColor = r.color; } Color value2 = MarkDefaultColor.Value; r.color = (enabled ? value2 : GetDisabledColor(value2)); }); TextMeshPro componentInChildren = ((Component)mark).GetComponentInChildren<TextMeshPro>(); if (!((Object)(object)componentInChildren == (Object)null)) { if (!TextDefaultColor.HasValue) { TextDefaultColor = ((Graphic)componentInChildren).color; } Color value = TextDefaultColor.Value; ((Graphic)componentInChildren).color = (enabled ? value : GetDisabledColor(value)); } } private static Color GetDisabledColor(Color baseColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) return new Color(baseColor.r, baseColor.g, baseColor.b, 0.5f); } public static void UpdateRecipeMarksForStateChanged(bool shown) { Ex.RunSafe(delegate { if (shown) { int currentPageIndex = ((Book)RecipeBook.Instance).currentPageIndex; if (StaticStorage.SelectedRecipeMarkIndex > 0 && StaticStorage.SelectedRecipeIndex == currentPageIndex && StaticStorage.RecipeMarkInfos.ContainsKey(currentPageIndex)) { UpdateRecipeBookPageForSelectedRecipeMark(currentPageIndex, StaticStorage.SelectedRecipeMarkIndex); } else { DisableOldRecipeMarks((Book)(object)RecipeBook.Instance); } } }); } public static void UpdateRecipeMarksForPageChange(int _, int _0) { Ex.RunSafe(delegate { DisableOldRecipeMarks((Book)(object)RecipeBook.Instance); }); } public static void DisableOldRecipeMarks(Book book) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown RecipeBook val = (RecipeBook)(object)((book is RecipeBook) ? book : null); if (val != null) { RecipeBookUIService.DisableOldRecipeMarks((RecipeBookRightPageContent)((Book)val).curlPageController.frontRightPage.pageContent); } } public static void DisableOldRecipeMarks(RecipeBookRightPageContent rightPageContent) { IRecipeBookPageContent obj = ((rightPageContent != null) ? rightPageContent.GetRecipeBookPageContent() : null); SerializedPotionRecipeData val = ((Potion)(object)((obj is Potion) ? obj : null))?.GetRecipeData(); if (!((Object)(object)RecipeBook.Instance == (Object)null) && val != null) { int currentPageIndex = ((Book)RecipeBook.Instance).currentPageIndex; StaticStorage.SelectedRecipeMarkIndex = val.recipeMarks.Count - 1; StaticStorage.SelectedRecipeIndex = currentPageIndex; RecipeBookRightPageRecipePanelController value = Traverse.Create((object)rightPageContent).Field<RecipeBookRightPageRecipePanelController>("recipePanelController").Value; Traverse.Create((object)value).Method("ClearRecipe", Array.Empty<object>()).GetValue(); Traverse.Create((object)value).Method("UpdatePotionRecipe", Array.Empty<object>()).GetValue(); } } private static void DisableRecipeWaypointsUIElements(RecipeBookRightPageContent rightPageContent) { Transform obj = ((Component)rightPageContent).transform.Find("WaypointToggleButton"); if (obj != null) { GameObject gameObject = ((Component)obj).gameObject; if (gameObject != null) { gameObject.SetActive(false); } } } public static bool IsAlchemyMachineRecipe(IRecipeBookPageContent recipe) { return !(recipe is Potion); } public static void BookmarksRearranged(BookmarkController _, List<int> intList) { Ex.RunSafe(delegate { List<KeyValuePair<int, Dictionary<int, RecipeMarkInfo>>> source = StaticStorage.RecipeMarkInfos.ToList(); List<KeyValuePair<int, Dictionary<int, RecipeMarkInfo>>> list = new List<KeyValuePair<int, Dictionary<int, RecipeMarkInfo>>>(); List<IRecipeBookPageContent> list2 = new List<IRecipeBookPageContent>(); for (int i = 0; i < intList.Count; i++) { int oldIndex = intList[i]; KeyValuePair<int, Dictionary<int, RecipeMarkInfo>> keyValuePair = source.FirstOrDefault((KeyValuePair<int, Dictionary<int, RecipeMarkInfo>> rmi) => rmi.Key == oldIndex); if (!keyValuePair.Equals(default(KeyValuePair<int, Dictionary<int, RecipeMarkInfo>>))) { list.Add(new KeyValuePair<int, Dictionary<int, RecipeMarkInfo>>(i, keyValuePair.Value)); } if (StaticStorage.BookmarkOrganizerOldVersionInstalled) { list2.Add(StaticStorage.RecipeIndexes[oldIndex]); } } StaticStorage.RecipeMarkInfos = list.ToDictionary((KeyValuePair<int, Dictionary<int, RecipeMarkInfo>> kvp) => kvp.Key, (KeyValuePair<int, Dictionary<int, RecipeMarkInfo>> kvp) => kvp.Value); StaticStorage.RecipeIndexes = list2; }); } public static void RemoveRecipeMarkForDeletedRecipe(IRecipeBookPageContent recipe) { if (recipe is Potion) { int key = RecipeBook.Instance.savedRecipes.IndexOf(recipe); if (StaticStorage.RecipeMarkInfos.ContainsKey(key)) { StaticStorage.RecipeMarkInfos.Remove(key); } } } public static void DoOldBookmarkOrganizerFailsfe() { if (!StaticStorage.BookmarkOrganizerOldVersionInstalled) { return; } List<IRecipeBookPageContent> savedRecipes = RecipeBook.Instance.savedRecipes; List<int> list = new List<int>(); bool flag = false; for (int i = 0; i < savedRecipes.Count; i++) { if (StaticStorage.RecipeIndexes[i] == savedRecipes[i]) { list.Add(i); continue; } flag = true; list.Add(StaticStorage.RecipeIndexes.IndexOf(savedRecipes[i])); } if (flag) { BookmarksRearranged(null, list); } } } public static class RecipeReconstructionService { public static bool MarkHasSavedData(int recipeIndex, int recipeMarkIndex) { if (!StaticStorage.RecipeMarkInfos.TryGetValue(recipeIndex, out var value)) { return false; } return value.ContainsKey(recipeMarkIndex); } public static Potion GetPotionForRecipeMark(int recipeIndex, int recipeMarkIndex) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Expected O, but got Unknown //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Unknown result type (might be due to invalid IL or missing references) //IL_0528: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_097f: Unknown result type (might be due to invalid IL or missing references) //IL_0981: Unknown result type (might be due to invalid IL or missing references) //IL_0983: Unknown result type (might be due to invalid IL or missing references) //IL_0988: Unknown result type (might be due to invalid IL or missing references) //IL_09fa: Unknown result type (might be due to invalid IL or missing references) //IL_09fc: Unknown result type (might be due to invalid IL or missing references) //IL_0731: Unknown result type (might be due to invalid IL or missing references) //IL_0736: Unknown result type (might be due to invalid IL or missing references) //IL_073b: Unknown result type (might be due to invalid IL or missing references) //IL_075b: Unknown result type (might be due to invalid IL or missing references) //IL_0760: Unknown result type (might be due to invalid IL or missing references) //IL_0925: Unknown result type (might be due to invalid IL or missing references) //IL_092a: Unknown result type (might be due to invalid IL or missing references) //IL_092c: Unknown result type (might be due to invalid IL or missing references) //IL_0931: Unknown result type (might be due to invalid IL or missing references) //IL_0933: Unknown result type (might be due to invalid IL or missing references) if (!StaticStorage.RecipeMarkInfos.ContainsKey(recipeIndex)) { return null; } Potion recipeToClone = (Potion)RecipeBook.Instance.savedRecipes[recipeIndex]; if (recipeToClone.GetRecipeData().recipeMarks.Count - 1 == recipeMarkIndex) { return recipeToClone; } Dictionary<int, RecipeMarkInfo> dictionary = StaticStorage.RecipeMarkInfos[recipeIndex]; Dictionary<DeltaProperty, BaseDelta> potionState = new Dictionary<DeltaProperty, BaseDelta>(); ReconstructionTimeline reconstructionTimeline = new ReconstructionTimeline(); int lowestIngredientIndex = -1; List<int> ignoreFixedHintIndexes = new List<int>(); int? previousAddedIngredients = null; int oldRecipeIndex = 0; int k; for (k = recipeMarkIndex; k >= 0; k--) { if (!dictionary.TryGetValue(k, out var curRecipeMarkDeltas)) { if (oldRecipeIndex == 0) { oldRecipeIndex = k; } continue; } if (k == 0) { k = oldRecipeIndex; } curRecipeMarkDeltas.Deltas.ForEach(delegate(BaseDelta delta) { if (!potionState.ContainsKey(delta.Property)) { Dictionary<DeltaProperty, BaseDelta> dictionary2 = potionState; DeltaProperty property = delta.Property; BaseDelta value6 = ((delta is ListDelta) ? delta : ((!(delta is ListAddDelta)) ? delta : new ListDelta { Property = delta.Property })); dictionary2[property] = value6; if (delta is ListAddDelta addDelta2) { processListAddDelta(addDelta2, (ListDelta)potionState[delta.Property]); } } else if (!(delta is ListDelta listDelta2)) { if (delta is ListAddDelta addDelta3) { processListAddDelta(addDelta3, (ListDelta)potionState[delta.Property]); } } else { ListDelta existingListDelta2 = (ListDelta)potionState[delta.Property]; listDelta2.AddDeltas.ForEach(delegate(ListAddDelta addDelta) { processListAddDelta(addDelta, existingListDelta2); }); } }); reconstructionTimeline.AddBasePropertyInformationFromDeltas(recipeToClone.GetRecipeData().recipeMarks, k, curRecipeMarkDeltas.Deltas); if (k == oldRecipeIndex) { k = 0; } void processListAddDelta(ListAddDelta addDelta, ListDelta existingListDelta) { int curIndex = addDelta.Index; if (addDelta.Property == DeltaProperty.FixedHints) { if (ignoreFixedHintIndexes.Contains(curIndex)) { return; } if (!potionState.TryGetValue(DeltaProperty.PathAddedFixedHints, out var value3)) { value3 = curRecipeMarkDeltas.Deltas.FirstOrDefault((BaseDelta d) => d.Property == DeltaProperty.PathAddedFixedHints) as ModifyDelta<int>; } if (value3 != null) { int newValue2 = ((ModifyDelta<int>)value3).NewValue; ModifyDelta<int> modifyDelta4 = curRecipeMarkDeltas.Deltas.FirstOrDefault((BaseDelta d) => d.Property == DeltaProperty.PathAddedFixedHints) as ModifyDelta<int>; if (modifyDelta4 != null) { if (k == oldRecipeIndex) { modifyDelta4.NewValue = ((ListDelta)curRecipeMarkDeltas.Deltas.FirstOrDefault((BaseDelta d) => d.Property == DeltaProperty.FixedHints))?.AddDeltas?.Count ?? modifyDelta4.NewValue; } if (previousAddedIngredients.HasValue && modifyDelta4.NewValue > previousAddedIngredients) { ignoreFixedHintIndexes.Add(curIndex); return; } previousAddedIngredients = modifyDelta4.NewValue; } int num6 = newValue2 - 1; if (curIndex > num6) { return; } if (potionState.TryGetValue(DeltaProperty.PathFixedHintsCount, out var value4)) { lowestIngredientIndex = num6 - ((ModifyDelta<int>)value4).NewValue + 1; if (curIndex < lowestIngredientIndex) { return; } } } addFixedHintDeltaToTimeline(addDelta); } ListAddDelta existingIndexDelta = existingListDelta.AddDeltas.FirstOrDefault((ListAddDelta d) => d.Index == curIndex); if (existingIndexDelta == null) { existingListDelta.AddDeltas.Add(addDelta); } else { addDelta.Deltas.ForEach(delegate(ModifyDelta modifyDelta) { if (!(existingIndexDelta.Deltas.FirstOrDefault((ModifyDelta d) => d.Property == modifyDelta.Property) != null)) { existingIndexDelta.Deltas.Add(modifyDelta); } }); } } } ListDelta obj = (ListDelta)potionState[DeltaProperty.FixedHints]; int newValue = ((ModifyDelta<int>)potionState[DeltaProperty.PathFixedHintsCount]).NewValue; obj.AddDeltas = obj.AddDeltas.OrderBy((ListAddDelta d) => d.Index).Take(newValue).ToList(); obj.AddDeltas.RemoveAll((ListAddDelta d) => d.Index < lowestIngredientIndex); reconstructionTimeline.FixedHintTimelines.Where((KeyValuePair<int, FixedHintTimeline> fht) => fht.Key < lowestIngredientIndex).ToList().ForEach(delegate(KeyValuePair<int, FixedHintTimeline> fht) { reconstructionTimeline.FixedHintTimelines.Remove(fht.Key); }); StaticStorage.SelectedRecipePotionState = potionState; Potion newRecipe = (Potion)recipeToClone.Clone(); SerializedPotionRecipeData newRecipeRecipeData = newRecipe.GetRecipeData(); ListDelta listDelta = (ListDelta)potionState[DeltaProperty.UsedComponents]; listDelta.AddDeltas.Sort(SortAddDeltasByIndexDesc); int j; for (j = newRecipe.usedComponents.GetSummaryComponentsCount() - 1; j > 0; j--) { ListAddDelta listAddDelta = listDelta.AddDeltas.FirstOrDefault((ListAddDelta d) => d.Index == j); if (listAddDelta == null) { newRecipe.usedComponents.GetSummaryComponents().RemoveAt(j); continue; } ModifyDelta<int> modifyDelta2 = (ModifyDelta<int>)listAddDelta.Deltas.First((ModifyDelta d) => d.Property == DeltaProperty.UsedComponent_Ammount); Traverse.Create((object)newRecipe.usedComponents.GetSummaryComponents()[j]).Property("Amount", (object[])null).SetValue((object)modifyDelta2.NewValue); } newRecipeRecipeData.usedComponents.components.Clear(); newRecipe.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 = newRecipeRecipeData.usedComponents.components; SerializedAlchemySubstanceComponent val4 = new SerializedAlchemySubstanceComponent { name = ((Object)component.Component).name, amount = component.Amount }; AlchemySubstanceComponentType type = component.Type; val4.type = ((object)(AlchemySubstanceComponentType)(ref type)).ToString(); components.Add(val4); }); ListDelta deltaFixedHints = (ListDelta)potionState[DeltaProperty.FixedHints]; deltaFixedHints.AddDeltas.Sort(SortAddDeltasByIndex); List<FixedHint> fixedPathHints = Managers.RecipeMap.path.fixedPathHints; float deletedGraphicsSegments = Managers.RecipeMap.path.deletedGraphicsSegments; Vector3 localPosition = ((Component)Managers.RecipeMap.path).transform.localPosition; List<int> list = new List<int>(); List<FixedHint> list2 = new List<FixedHint>(); GameObject val = new GameObject("dummyObject"); Vector3 val2 = Vector3.zero; Vector3 val3 = Vector3.zero; Managers.RecipeMap.path.fixedPathHints = list2; Managers.RecipeMap.path.deletedGraphicsSegments = 0f; ((RecipeMapItem)Managers.RecipeMap.path).SetPositionOnMap(Vector2.op_Implicit(((Component)Managers.RecipeMap.currentMap.referencesContainer.potionBaseMapItem).transform.localPosition)); if (potionState.ContainsKey(DeltaProperty.OldSerializedPath)) { ModifyDelta<SerializedPath> modifyDelta3 = (ModifyDelta<SerializedPath>)potionState[DeltaProperty.OldSerializedPath]; list.AddRange((from fh in deltaFixedHints.AddDeltas where fh.Deltas.Any((ModifyDelta d) => d.Property == DeltaProperty.IsOldFixedHint) select fh.Index).ToList()); List<SerializedPathPoints> list3 = modifyDelta3.NewValue.fixedPathPoints.ToList(); for (int num = list3.Count - 1; num >= 0; num--) { if (!list.Contains(num)) { modifyDelta3.NewValue.fixedPathPoints.RemoveAt(num); } } Managers.RecipeMap.path.ShowLoadedFixedPathHints(modifyDelta3.NewValue); modifyDelta3.NewValue.fixedPathPoints = list3; } bool flag = true; foreach (ListAddDelta addDelta4 in deltaFixedHints.AddDeltas) { int index = addDelta4.Index; reconstructionTimeline.FixedHintTimelines.TryGetValue(index, out var value); if (!list.Contains(addDelta4.Index)) { string ingredientName = value.IngredientName; float grindPercent = value.GrindPercent; Ingredient byName = Ingredient.GetByName(ingredientName, false, true); if ((Object)(object)byName == (Object)null) { Plugin.LogError($"Error reconstructing path at index {index}. Ingredient ({ingredientName}) is null!"); return null; } Managers.RecipeMap.path.potionComponentHintPainter.ShowIngredientHint(false, 0f, (Object)(object)val, (InventoryItem)(object)byName, grindPercent); Managers.RecipeMap.path.AddCurrentPathToFixedPath(byName); } if (flag) { val2 = Vector2.op_Implicit(((ModifyDelta<(float, float)>)addDelta4.Deltas.First((ModifyDelta d) => d.Property == DeltaProperty.FixedHint_ConnectionPoint)).NewValue.ToVector()); val3 = Managers.RecipeMap.path.fixedPathHints.First().evenlySpacedPointsFixedGraphics.points.First(); } if (value == null) { continue; } List<(int, bool, float)> pathDeletionEvents = reconstructionTimeline.GetPathDeletionEvents(recipeToClone.GetRecipeData().recipeMarks, index); int num2 = (pathDeletionEvents.Any() ? pathDeletionEvents.Max<(int, bool, float)>(((int index, bool fromEnd, float length) d) => d.index) : (-1)); List<(int, Quaternion)> rotationEventsForFixedHint = reconstructionTimeline.GetRotationEventsForFixedHint(index); int num3 = (rotationEventsForFixedHint.Any() ? rotationEventsForFixedHint.Max<(int, Quaternion)>(((int index, Quaternion rotation) d) => d.index) : (-1)); int num4 = Mathf.Max(num2, num3); int i; for (i = 0; i <= num4; i++) { bool num5 = pathDeletionEvents.Any<(int, bool, float)>(((int index, bool fromEnd, float length) e) => e.index == i); bool flag2 = rotationEventsForFixedHint.Any<(int, Quaternion)>(((int index, Quaternion rotation) e) => e.index == i); if (num5) { (int, bool, float) tuple = pathDeletionEvents.First<(int, bool, float)>(((int index, bool fromEnd, float length) e) => e.index == i); float item = tuple.Item3; bool item2 = tuple.Item2; if (item > 0.0001f) { if (item2) { item = MathF.Round(item - 0.099f, 1, MidpointRounding.AwayFromZero); if (item > 0f) { Managers.RecipeMap.path.DeleteSegmentFromEnd(item); } } else { Traverse.Create((object)Managers.RecipeMap.path).Method("DeleteFromFixedPath", new object[2] { item, Managers.RecipeMap.path.fixedPathHints.First() }).GetValue(); } } } if (flag2) { (int, Quaternion) tuple2 = rotationEventsForFixedHint.First<(int, Quaternion)>(((int index, Quaternion rotation) e) => e.index == i); RotatePath(localPosition: -Managers.RecipeMap.path.fixedPathHints[0].evenlySpacedPointsFixedGraphics.points[0], rotation: tuple2.Item2); } } flag = false; } Vector3 offset = val2 - val3; SerializedPath pathFromCurrentPotion = SerializedPath.GetPathFromCurrentPotion(); newRecipeRecipeData.serializedPath = pathFromCurrentPotion; Object.Destroy((Object)(object)val); list2.ForEach(delegate(FixedHint fh) { fh.DestroyPath(); }); Managers.RecipeMap.path.fixedPathHints = fixedPathHints; Managers.RecipeMap.path.deletedGraphicsSegments = deletedGraphicsSegments; ((RecipeMapItem)Managers.RecipeMap.path).SetPositionOnMap(Vector2.op_Implicit(localPosition)); potionState.ToList().ForEach(delegate(KeyValuePair<DeltaProperty, BaseDelta> propertyDelta) { //IL_006a: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown //IL_0189: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) BaseDelta value5 = propertyDelta.Value; switch (propertyDelta.Key) { case DeltaProperty.IndicatorPosition: newRecipeRecipeData.serializedPath.indicatorPosition = ((ModifyDelta<(float, float)>)value5).NewValue.ToVector(); break; case DeltaProperty.PathPosition: { Vector2 pathPosition = ((ModifyDelta<(float, float)>)value5).NewValue.ToVector(); newRecipeRecipeData.serializedPath.pathPosition = pathPosition; if (deltaFixedHints.AddDeltas.Any()) { if (offset != Vector3.zero) { newRecipeRecipeData.serializedPath.fixedPathPoints.ForEach(delegate(SerializedPathPoints point) { point.graphicsPoints = point.graphicsPoints.Select((Vector3 p) => p + offset).ToList(); point.physicsPoints = point.physicsPoints.Select((Vector3 p) => p + offset).ToList(); point.dotsPoints = point.dotsPoints.Select((Vector3 p) => p + offset).ToList(); }); } } else { newRecipeRecipeData.serializedPath.fixedPathPoints.Add(new SerializedPathPoints { graphicsPoints = new List<Vector3> { Vector2.op_Implicit(-newRecipeRecipeData.serializedPath.pathPosition) }, physicsPoints = new List<Vector3> { Vector2.op_Implicit(-newRecipeRecipeData.serializedPath.pathPosition) }, pathEndParameters = new PathEndParameters { spriteIndex = 2 }, pathStartParameters = new PathEndParameters { spriteIndex = 2 } }); } break; } case DeltaProperty.IndicatorTargetPosition: newRecipeRecipeData.serializedPath.indicatorTargetPosition = ((ModifyDelta<(float, float)>)value5).NewValue.ToVector(); break; case DeltaProperty.FollowButtonTargetPosition: newRecipeRecipeData.serializedPath.followButtonTargetObjectPosition = ((ModifyDelta<(float, float)>)value5).NewValue.ToVector(); break; case DeltaProperty.Rotation: newRecipeRecipeData.serializedPath.indicatorRotationValue = ((ModifyDelta<float>)value5).NewValue; break; case DeltaProperty.Health: { float newValue4 = ((ModifyDelta<float>)value5).NewValue; if (newValue4 > 0.01f) { newRecipeRecipeData.serializedPath.health = newValue4; } break; } case DeltaProperty.Effects: { List<string> newValue3 = ((ModifyDelta<List<string>>)value5).NewValue; newRecipe.Effects = newValue3.Select((string e) => PotionEffect.GetByName(e, false, true, (List<PotionEffect>)null)).ToArray(); newRecipeRecipeData.collectedPotionEffects = newValue3.ToList(); break; } case DeltaProperty.PathDeletedSegments: newRecipeRecipeData.serializedPath.deletedGraphicsSegments = ((ModifyDelta<float>)value5).NewValue; break; } }); return newRecipe; void addFixedHintDeltaToTimeline(ListAddDelta addDelta) { if (!reconstructionTimeline.FixedHintTimelines.TryGetValue(addDelta.Index, out var value2)) { value2 = new FixedHintTimeline { FixedHintIndex = addDelta.Index }; reconstructionTimeline.FixedHintTimelines[addDelta.Index] = value2; } value2.AddInformationFromDeltas(recipeToClone.GetRecipeData().recipeMarks, k, addDelta.Deltas); } } private static void RotatePath(Quaternion rotation, Vector3 localPosition) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) if (rotation != Quaternion.identity) { Matrix4x4 rotationMatrix = Matrix4x4.Translate(-localPosition) * Matrix4x4.Rotate(rotation) * Matrix4x4.Translate(localPosition); MethodInfo rotateByMethod = typeof(FixedHint).GetMethod("RotateBy", BindingFlags.Instance | BindingFlags.NonPublic); Managers.RecipeMap.path.fixedPathHints.ForEach(delegate(FixedHint f) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) rotateByMethod.Invoke(f, new object[1] { rotationMatrix }); }); } } private static void DebugLogObject(object obj) { //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_0017: Expected O, but got Unknown Plugin.PluginLogger.LogMessage((object)JsonConvert.SerializeObject(obj, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 })); } public static int SortAddDeltasByIndex(ListAddDelta ad1, ListAddDelta ad2) { if (ad1.Index <= ad2.Index) { if (ad1.Index != ad2.Index) { return -1; } return 0; } return 1; } public static int SortAddDeltasByIndexDesc(ListAddDelta ad1, ListAddDelta ad2) { return -SortAddDeltasByIndex(ad1, ad2); } } public static class SaveLoadService { public static void SetupListeners() { if (!StaticStorage.AddedListeners) { StaticStorage.AddedListeners = true; ((Component)Managers.Potion).gameObject.AddComponent<UsefulRecipeMarksManager>(); ((UnityEvent<BookmarkController, List<int>>)(object)((Book)RecipeBook.Instance).bookmarkControllersGroupController.onBookmarksRearranged).AddListener((UnityAction<BookmarkController, List<int>>)RecipeBookUIService.BookmarksRearranged); ((UnityEvent<int, int>)(object)((Book)RecipeBook.Instance).onPageChanged).AddListener((UnityAction<int, int>)RecipeBookUIService.UpdateRecipeMarksForPageChange); ((UnityEvent<bool>)(object)((DarkScreenContent)RecipeBook.Instance).onActiveStateChanged).AddListener((UnityAction<bool>)RecipeBookUIService.UpdateRecipeMarksForStateChanged); ((UnityEvent<bool>)(object)Managers.Potion.potionCraftPanel.onPotionUpdated).AddListener((UnityAction<bool>)DeltaRecordingService.ClearPreviousSavedPotionRecipeMarkInfo); } } public static void ClearFileSpecificDataOnFileLoad() { SetupListeners(); StaticStorage.CurrentPotionRecipeMarkInfos.Clear(); StaticStorage.CurrentPotionState.Clear(); StaticStorage.CurrentRecipeMarkInfo = null; StaticStorage.PreviousPotionRecipeMarkInfo = null; StaticStorage.SelectedRecipePotionState?.Clear(); StaticStorage.SelectedRecipeMarkIndex = 0; StaticStorage.SelectedRecipeIndex = 0; StaticStorage.RecipeMarkInfos.Clear(); } public static void UpdateFailsafeListOnLoad() { if (StaticStorage.BookmarkOrganizerOldVersionInstalled) { List<IRecipeBookPageContent> savedRecipes = RecipeBook.Instance.savedRecipes; List<IRecipeBookPageContent> list = new List<IRecipeBookPageContent>(savedRecipes.Count); list.AddRange(savedRecipes); StaticStorage.RecipeIndexes = list; } } } } namespace PotionCraftUsefulRecipeMarks.Scripts.Patches { public class OldBookmarkOrganizerFailsafePatch { [HarmonyPatch(typeof(Bookmark), "UpdateMovingState")] public class Bookmark_UpdateMovingState { [HarmonyAfter(new string[] { "com.fahlgorithm.potioncraftbookmarkorganizer" })] private static void Postfix(MovingState value) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) Ex.RunSafe(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) BookmarkMovingStateChanged(value); }); } } [HarmonyPatch(typeof(Bookmark), "UpdateMoving")] public class Bookmark_UpdateMoving { private static void Postfix(Bookmark __instance) { Ex.RunSafe(delegate { DetermineIfShouldSwapOnRelease(__instance); }); } } [HarmonyPatch(typeof(RecipeBook), "OnLoad")] public class RecipeBook_OnLoad { private static void Postfix() { Ex.RunSafe(delegate { SaveLoadService.UpdateFailsafeListOnLoad(); }); } } private const float SwapAboveY = 1.2f; private const float DontSwapBelowX = -0.6f; private static bool ShouldSwapOnRelease; private static void BookmarkMovingStateChanged(MovingState value) { //IL_0008: 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) if (StaticStorage.BookmarkOrganizerOldVersionInstalled) { if ((int)value != 0) { _ = 1; } else if (ShouldSwapOnRelease) { ShouldSwapOnRelease = false; RecipeBookUIService.DoOldBookmarkOrganizerFailsfe(); } } } private static void DetermineIfShouldSwapOnRelease(Bookmark instance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (!StaticStorage.BookmarkOrganizerOldVersionInstalled || (int)instance.CurrentMovingState == 0) { return; } BookmarkController bookmarkController = ((Book)RecipeBook.Instance).bookmarkControllersGroupController.controllers[0].bookmarkController; if (bookmarkController.rails.Count < 8) { return; } BookmarkRail val = bookmarkController.rails[7]; if ((Object)(object)instance.rail != (Object)(object)val) { if (ShouldSwapOnRelease) { ShouldSwapOnRelease = false; } } else if (!ShouldSwapOnRelease) { Vector2 currentMouseWorldPosition = Managers.Input.controlsProvider.CurrentMouseWorldPosition; float num = ((Component)val).transform.position.y + 1.2f; float num2 = ((Component)val).transform.position.x - -0.6f; ShouldSwapOnRelease = currentMouseWorldPosition.y > num && currentMouseWorldPosition.x > num2; } } } } namespace PotionCraftUsefulRecipeMarks.Scripts.Patches.RecipeBookUI { [HarmonyPatch(typeof(Potion), "Clone")] public class CopyImportantInfoToPotionInstancePotionPatch { private static void Postfix(IRecipeBookPageContent __result, Potion __instance) { Ex.RunSafe(delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown CopyImportantInfoToPotionInstance((Potion)__result, __instance); }); } private static void CopyImportantInfoToPotionInstance(Potion copyTo, Potion copyFrom) { CopyImportantInfoToPotionInstance(copyTo, copyFrom, copyFrom.GetRecipeData()); } private static void CopyImportantInfoToPotionInstance(Potion copyTo, Potion copyFromPotion, SerializedPotionRecipeData copyFrom) { SerializedPotionRecipeData recipeData = copyTo.GetRecipeData(); List<SerializedRecipeMark> recipeMarks = recipeData.recipeMarks; recipeMarks.Clear(); copyFrom.recipeMarks.ForEach(delegate(SerializedRecipeMark m) { recipeMarks.Add(m.Clone()); }); recipeData.collectedPotionEffects.Clear(); PotionEffect[] array = ((copyFromPotion != null) ? copyFromPotion.Effects : null) ?? Managers.Potion.collectedPotionEffects; foreach (PotionEffect val in array) { if ((ComparableScriptableObject<PotionEffect>)(object)val == (ComparableScriptableObject<PotionEffect>)null) { break; } recipeData.collectedPotionEffects.Add(((Object)val).name); } recipeData.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 uc) { copyTo.usedComponents.Add(uc, -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 val2 = new SerializedAlchemySubstanceComponent { name = ((Object)component.Component).name, amount = component.Amount }; AlchemySubstanceComponentType type = component.Type; val2.type = ((object)(AlchemySubstanceComponentType)(ref type)).ToString(); components.Add(val2); }); } recipeData.usedComponents = copyFrom.usedComponents; recipeData.skinSettings = copyFrom.skinSettings; } } public class DeleteMarkInfoOnRecipeDeletePatch { [HarmonyPatch(typeof(RecipeBook), "EraseRecipe")] public class RecipeBook_EraseRecipe { private static bool Prefix(IRecipeBookPageContent recipe) { return Ex.RunSafe(() => DeleteMarkInfoOnRecipeDelete(recipe)); } } private static bool DeleteMarkInfoOnRecipeDelete(IRecipeBookPageContent recipe) { Potion val = (Potion)(object)((recipe is Potion) ? recipe : null); if (val == null) { return true; } DeltaRecordingService.DeleteMarkInfoForRecipe(val); return true; } } public class FixIconExceptionPatch { [HarmonyPatch(typeof(Icon), "GetByName")] public class Icon_GetByName { private static bool Prefix(ref Icon __result, string iconName) { return FixPotionIconException(ref __result, iconName); } } private static bool FixPotionIconException(ref Icon result, string iconName) { Icon tempResult = null; bool result2 = Ex.RunSafe(delegate { if (string.IsNullOrEmpty(iconName)) { tempResult = Icon.allIcons.FirstOrDefault(); return false; } return true; }); result = tempResult; return result2; } } public class RemoveRecipeMarkForDeletedRecipePatch { [HarmonyPatch(typeof(RecipeBook), "EraseRecipe")] public class RemoveRecipeMarkForDeletedRecipe { private static void Prefix(IRecipeBookPageContent recipe) { Ex.RunSafe(delegate { RecipeBookUIService.RemoveRecipeMarkForDeletedRecipe(recipe); }); } } } public class UpdateRecipeBookPageForSelectedRecipeMarkPatch { [HarmonyPatch(typeof(Button), "OnClick")] public class Button_OnClick { private static void Postfix(Button __instance) { Ex.RunSafe(delegate { RecipeBookUIService.UpdateRecipeBookPageForSelectedRecipeMark(__instance); }); } } [HarmonyPatch(typeof(RecipeBookRecipeMark), "AssignMark")] public class RecipeBookRecipeMark_AssignMark { private static void Postfix(RecipeBookRecipeMark __instance) { Ex.RunSafe(delegate { RecipeBookUIService.EnableDisableMark(__instance); }); } } } } namespace PotionCraftUsefulRecipeMarks.Scripts.Patches.BrewTracking { public class CommitRecipeMarkInfoForSavedRecipePatch { [HarmonyPatch(typeof(SavePotionRecipeButton), "OnButtonReleasedPointerInside")] public class SaveRecipeButton_OnButtonReleasedPointerInside { private static void Prefix() { Ex.RunSafe((Action)DeltaRecordingService.CommitRecipeMarkInfoForSavedRecipe, (Action)null, logErrorToStorage: false); } } } public class RecordRecipeMarksPatch { [HarmonyPatch(typeof(RecipeMarksSubManager), "AddLadleMark")] public class RecipeMarksSubManager_AddLadleMark { private static void Postfix() { Ex.RunSafe(delegate { DeltaRecordingService.RecordRecipeMarkInfo(); }); } } [HarmonyPatch(typeof(NonTeleportationFixedHint), "RunAlongPath")] public class FixedHint_RunAlongPath { private static void Postfix() { Ex.RunSafe(delegate { DeltaRecordingService.RecordRecipeMarkInfo(); }); } } [HarmonyPatch(typeof(TeleportationFixedHint), "SetIndicatorPosition")] public class TeleportationFixedHint_SetIndicatorPosition { private static void Postfix() { Ex.RunSafe(delegate { DeltaRecordingService.RecordRecipeMarkInfo(); }); } } [HarmonyPatch(typeof(PotionManager), "ApplyEffectToPotion")] public class PotionManager_ApplyEffectToPotion { private static void Postfix() { Ex.RunSafe(delegate { DeltaRecordingService.RecordRecipeMarkInfo(); }); } } [HarmonyPatch(typeof(PotionManager), "AddPotionUsedComponent")] public class RecipeMarksSubManager_AddIngredientMark { private static void Postfix(ScriptableObject componentObject) { Ex.RunSafe(delegate { RecordIngredientMark(componentObject); }); } } [HarmonyPatch(typeof(RecipeMarksSubManager), "AddSaltMark")] public class RecipeMarksSubManager_AddSaltMark { private static void Postfix() { Ex.RunSafe(delegate { DeltaRecordingService.RecordRecipeMarkInfo(); }); } } private static void RecordIngredientMark(ScriptableObject componentObject) { if (!(componentObject is PotionBase) && !(componentObject is Salt)) { DeltaRecordingService.RecordRecipeMarkInfo(); } } } public class ResetTrackingForPotionResetPatch { [HarmonyPatch(typeof(PotionManager