Decompiled source of Bookmark Organizer v1.1.0
plugins/PotionCraftBookmarkOrganizer.dll
Decompiled 11 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading.Tasks; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using PotionCraft.Assemblies.GamepadNavigation; using PotionCraft.Core.Extensions; using PotionCraft.Core.ValueContainers; using PotionCraft.InputSystem; using PotionCraft.ManagersSystem; using PotionCraft.ManagersSystem.Cursor; using PotionCraft.ManagersSystem.SaveLoad; using PotionCraft.ObjectBased.InteractiveItem; using PotionCraft.ObjectBased.UIElements; using PotionCraft.ObjectBased.UIElements.Bookmarks; using PotionCraft.ObjectBased.UIElements.Books; using PotionCraft.ObjectBased.UIElements.Books.RecipeBook; using PotionCraft.ObjectBased.UIElements.PotionCustomizationPanel; using PotionCraft.ObjectBased.UIElements.Tooltip; using PotionCraft.SaveFileSystem; using PotionCraft.SaveLoadSystem; using PotionCraft.ScriptableObjects; using PotionCraft.ScriptableObjects.Potion; using PotionCraft.Settings; using PotionCraftBookmarkOrganizer.Scripts.ClassOverrides; using PotionCraftBookmarkOrganizer.Scripts.Services; using PotionCraftBookmarkOrganizer.Scripts.Storage; using UnityEngine; using UnityEngine.Events; using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PotionCraftBookmarkOrganizer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Recipe Waypoint Mod for Potion Craft")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("PotionCraftBookmarkOrganizer")] [assembly: AssemblyTitle("PotionCraftBookmarkOrganizer")] [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 PotionCraftBookmarkOrganizer { [BepInPlugin("com.fahlgorithm.potioncraftbookmarkorganizer", "PotionCraftBookmarkOrganizer", "1.1.0.0")] [BepInProcess("Potion Craft.exe")] public class Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "com.fahlgorithm.potioncraftbookmarkorganizer"; public const string PLUGIN_VERSION = "1.1.0.0"; public static ManualLogSource PluginLogger { get; private set; } private void Awake() { PluginLogger = ((BaseUnityPlugin)this).Logger; PluginLogger.LogInfo((object)"Plugin com.fahlgorithm.potioncraftbookmarkorganizer is loaded!"); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.fahlgorithm.potioncraftbookmarkorganizer"); PluginLogger.LogInfo((object)"Plugin com.fahlgorithm.potioncraftbookmarkorganizer: Patch Succeeded!"); } } public static class PluginInfo { public const string PLUGIN_GUID = "PotionCraftBookmarkOrganizer"; public const string PLUGIN_NAME = "PotionCraftBookmarkOrganizer"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace PotionCraftBookmarkOrganizer.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}"); } } } namespace PotionCraftBookmarkOrganizer.Scripts.Storage { public class BookmarkOrganizerManager : MonoBehaviour { public Dictionary<int, List<BookmarkStorage>> BookmarkGroups => StaticStorage.BookmarkGroups; public List<int> SavedRecipePositions => StaticStorage.SavedRecipePositions; public List<Transform> SubRailLayers => StaticStorage.SubRailLayers; public Transform InvisiRailLayer => StaticStorage.InvisiRailLayer; public BookmarkRail SubRail => StaticStorage.SubRail; public GameObject SubRailActiveBookmarkLayer => StaticStorage.SubRailActiveBookmarkLayer; public BookmarkRail InvisiRail => StaticStorage.InvisiRail; public bool AddedListeners => StaticStorage.AddedListeners; private void Update() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Invalid comparison between Unknown and I4 if (StaticStorage.HotkeyDown == null || StaticStorage.HotkeyUp == null) { return; } if ((int)Commands.roomDown.State == 2) { RecipeBookService.FlipPageToNextGroup(flipForward: false); StaticStorage.HotkeyDown.SetAction((Action<CommandInvokeRepeater>)delegate { RecipeBookService.FlipPageToNextGroup(flipForward: false); }).StopWhen((Func<bool>)(() => !CanHotkeysBeUsed()), (Action<CommandInvokeRepeater>)null); } else if ((int)Commands.roomUp.State == 2) { RecipeBookService.FlipPageToNextGroup(flipForward: true); StaticStorage.HotkeyUp.SetAction((Action<CommandInvokeRepeater>)delegate { RecipeBookService.FlipPageToNextGroup(flipForward: true); }).StopWhen((Func<bool>)(() => !CanHotkeysBeUsed()), (Action<CommandInvokeRepeater>)null); } } private bool CanHotkeysBeUsed() { return !Managers.Input.HasInputGotToBeDisabled(); } } public class BookmarkStorage { public int recipeIndex; public SerializedBookmark SerializedBookmark; } public static class StaticStorage { public class SavedStaticStorage { public Dictionary<int, List<BookmarkStorage>> BookmarkGroups { get; set; } public List<int> SavedRecipePositions { get; set; } public List<string> ErrorLog { get; set; } public string BookmarkManagerVersion { get; set; } } public const string BookmarkGroupsJsonSaveName = "FahlgorithmBookmarkOrganizer"; public const string SubRailName = "BottomToTopSubRail"; public const string InvisiRailName = "BottomToTopInvisiRail"; public const string CornerIconGameObjectName = "GroupCornerIcon"; public static Dictionary<int, List<BookmarkStorage>> BookmarkGroups = new Dictionary<int, List<BookmarkStorage>>(); public static List<int> SavedRecipePositions; public static List<string> ErrorLog = new List<string>(); public static BookmarkRail SubRail; public static GameObject SubRailPages; public static BookmarkRail InvisiRail; public static Bookmark StaticBookmark; public static Dictionary<RecipeBookLeftPageContent, (GameObject, GameObject)> StaticRails = new Dictionary<RecipeBookLeftPageContent, (GameObject, GameObject)>(); public static List<Transform> SubRailLayers = new List<Transform>(); public static Transform InvisiRailLayer; public static GameObject SubRailActiveBookmarkLayer; public static bool AddedListeners; public static bool IsLoaded; public static CommandInvokeRepeater HotkeyUp; public static CommandInvokeRepeater HotkeyDown; public static string StateJsonString; } } namespace PotionCraftBookmarkOrganizer.Scripts.Services { public static class RecipeBookService { private static bool ignoreBookmarkRearrangeForSubBookmarkPromotion; private static bool currentlyRearranging; private static ConcurrentQueue<List<int>> rearrangeQueue = new ConcurrentQueue<List<int>>(); private static int recipeIndexForCurrentGroupUpdate = -1; public static void SetupListeners() { if (!StaticStorage.AddedListeners) { StaticStorage.AddedListeners = true; ((UnityEvent<BookmarkController, List<int>>)(object)((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.onBookmarksRearranged).AddListener((UnityAction<BookmarkController, List<int>>)BookmarksRearranged); ((Component)Managers.Potion).gameObject.AddComponent<BookmarkOrganizerManager>(); CursorManagerSettings asset = Settings<CursorManagerSettings>.Asset; StaticStorage.HotkeyUp = CommandInvokeRepeater.GetNewCommandInvokeRepeater(asset.invokeRepeaterSettings, new List<Command> { Commands.roomUp }, false); StaticStorage.HotkeyDown = CommandInvokeRepeater.GetNewCommandInvokeRepeater(asset.invokeRepeaterSettings, new List<Command> { Commands.roomDown }, false); } } public static void FlipPageToNextGroup(bool flipForward) { if (((Behaviour)Managers.Potion.recipeBook).isActiveAndEnabled) { int nextNonSubRecipeIndex = GetNextNonSubRecipeIndex(flipForward); if (nextNonSubRecipeIndex != ((Book)Managers.Potion.recipeBook).currentPageIndex) { FlipPageToIndex(nextNonSubRecipeIndex); } } } private static int GetNextNonSubRecipeIndex(bool moveForward) { RecipeBook recipeBook = Managers.Potion.recipeBook; int currentPageIndex = ((Book)recipeBook).currentPageIndex; int pagesCount = ((Book)recipeBook).GetPagesCount(); int result = currentPageIndex; for (int i = 1; i <= pagesCount; i++) { int num = i * (moveForward ? 1 : (-1)); int num2 = (currentPageIndex + num + pagesCount) % pagesCount; GetBookmarkStorageRecipeIndex(num2, out var indexIsParent); if (!indexIsParent) { result = num2; break; } } return result; } public static void PromoteIndexToParent(int subBookmarkIndex) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) bool indexIsParent; int groupIndex = GetBookmarkStorageRecipeIndex(subBookmarkIndex, out indexIsParent); if (!indexIsParent) { return; } List<Bookmark> allBookmarksList = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList(); Bookmark subBookmark = allBookmarksList[subBookmarkIndex]; Bookmark groupBookmark = allBookmarksList[groupIndex]; Vector2 groupBookmarkPosition = groupBookmark.GetNormalizedPosition(); Vector2 subBookmarkPosition = subBookmark.GetNormalizedPosition(); BookmarkController bookmarkController = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers[0].bookmarkController; int i = 0; (from rail in bookmarkController.rails.ToList() select (rail, rail.railBookmarks.ToList())).ToList().ForEach(delegate((BookmarkRail rail, List<Bookmark> bookmarks) rail) { rail.bookmarks.ForEach(delegate { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (i == groupIndex) { rail.rail.Connect(subBookmark, groupBookmarkPosition); } else if (i == subBookmarkIndex) { rail.rail.Connect(groupBookmark, subBookmarkPosition); } int num = i; i = num + 1; }); }); ignoreBookmarkRearrangeForSubBookmarkPromotion = true; bookmarkController.CallOnBookmarksRearrangeIfNecessary(allBookmarksList); ignoreBookmarkRearrangeForSubBookmarkPromotion = false; Managers.Potion.recipeBook.UpdateBookmarkIcon(groupIndex); Managers.Potion.recipeBook.UpdateBookmarkIcon(subBookmarkIndex); SubRailService.UpdateStaticBookmark(); UpdateBookmarkGroupsForCurrentRecipe(); ShowHideGroupBookmarkIcon(groupBookmark, show: false); SubRailService.UpdateSubBookmarksActiveState(); } private static async void BookmarksRearranged(BookmarkController bookmarkController, List<int> intList) { if (ignoreBookmarkRearrangeForSubBookmarkPromotion) { return; } rearrangeQueue.Enqueue(intList); if (currentlyRearranging) { while (currentlyRearranging) { await Task.Delay(100); } } BookmarksRearranged(); } private static async void BookmarksRearranged() { currentlyRearranging = true; try { while (rearrangeQueue.Count > 0) { List<int> intList; bool flag = rearrangeQueue.TryDequeue(out intList); while (!flag) { await Task.Delay(10); flag = rearrangeQueue.TryDequeue(out var result); if (flag) { intList = result; } } Dictionary<int, List<BookmarkStorage>> bookmarkGroups = StaticStorage.BookmarkGroups; Dictionary<int, List<BookmarkStorage>> dictionary = new Dictionary<int, List<BookmarkStorage>>(); List<BookmarkStorage> oldStoredBookmarksList = bookmarkGroups.SelectMany((KeyValuePair<int, List<BookmarkStorage>> b) => b.Value).ToList(); List<IGrouping<int, BookmarkStorage>> list = (from b in oldStoredBookmarksList group b by b.recipeIndex into bg where bg.Count() > 1 select bg).ToList(); if (list.Any()) { Plugin.PluginLogger.LogError((object)"ERROR: somehow the same bookmark is in two different groups!"); list.ForEach(delegate(IGrouping<int, BookmarkStorage> dbg) { oldStoredBookmarksList.Remove(dbg.Last()); }); } Dictionary<int, BookmarkStorage> dictionary2 = oldStoredBookmarksList.ToDictionary((BookmarkStorage b) => b.recipeIndex); for (int i = 0; i < intList.Count; i++) { int num = intList[i]; if (recipeIndexForCurrentGroupUpdate == num) { recipeIndexForCurrentGroupUpdate = i; } if (bookmarkGroups.ContainsKey(num)) { dictionary[i] = bookmarkGroups[num]; } if (num != i && dictionary2.TryGetValue(num, out var value)) { value.recipeIndex = i; } } StaticStorage.BookmarkGroups = dictionary; intList = null; } DoOrphanedBookmarkFailsafe(); } catch (Exception ex) { Ex.LogException(ex); } currentlyRearranging = false; } private static void DoOrphanedBookmarkFailsafe() { ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList().ForEach(delegate(Bookmark bookmark) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bookmark.rail == (Object)null || !bookmark.rail.railBookmarks.Contains(bookmark)) { Plugin.PluginLogger.LogError((object)"ERROR: An orphaned bookmark has been found! This is the result of another error!"); BookmarkController bookmarkController = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController; Tuple<BookmarkRail, Vector2> tuple = SubRailService.GetSpawnPosition(bookmarkController, (SpaceType)3) ?? SubRailService.GetSpawnPosition(bookmarkController, (SpaceType)2) ?? SubRailService.GetSpawnPosition(bookmarkController, (SpaceType)1) ?? SubRailService.GetSpawnPosition(bookmarkController, (SpaceType)0); if (tuple == null) { Plugin.PluginLogger.LogError((object)"DoOrphanedBookmarkFailsafe - There is no empty space for bookmark! Change settings!"); } else { SubRailService.ConnectBookmarkToRail(tuple.Item1, bookmark, tuple.Item2); } } }); } public static async void UpdateBookmarkGroupsForCurrentRecipe() { recipeIndexForCurrentGroupUpdate = GetBookmarkStorageRecipeIndexForSelectedRecipe(); var subRailBookmarks = StaticStorage.SubRail.railBookmarks.Select((Bookmark b) => new { bookmark = b, serialized = b.GetSerialized() }).ToList(); if (currentlyRearranging || rearrangeQueue.Count > 0) { while (currentlyRearranging || rearrangeQueue.Count > 0) { await Task.Delay(100); } } currentlyRearranging = true; List<Bookmark> allBookmarks = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList(); IEnumerable<BookmarkStorage> source = subRailBookmarks.Select(bookmark => new BookmarkStorage { recipeIndex = allBookmarks.IndexOf(bookmark.bookmark), SerializedBookmark = bookmark.serialized }); StaticStorage.BookmarkGroups[recipeIndexForCurrentGroupUpdate] = source.ToList(); currentlyRearranging = false; ShowHideGroupBookmarkIcon(((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetBookmarkByIndex(recipeIndexForCurrentGroupUpdate), source.Any()); } public static int GetBookmarkStorageRecipeIndexForSelectedRecipe() { bool indexIsParent; return GetBookmarkStorageRecipeIndex(((Book)Managers.Potion.recipeBook).currentPageIndex, out indexIsParent); } public static int GetBookmarkStorageRecipeIndexForSelectedRecipe(out bool indexIsParent) { return GetBookmarkStorageRecipeIndex(((Book)Managers.Potion.recipeBook).currentPageIndex, out indexIsParent); } public static int GetBookmarkStorageRecipeIndex(int recipeIndex) { bool indexIsParent; return GetBookmarkStorageRecipeIndex(recipeIndex, out indexIsParent); } public static int GetBookmarkStorageRecipeIndex(int recipeIndex, out bool indexIsParent) { indexIsParent = false; List<int> source = StaticStorage.BookmarkGroups.Keys.Where((int k) => StaticStorage.BookmarkGroups[k].Any((BookmarkStorage b) => b.recipeIndex == recipeIndex)).ToList(); if (source.Any()) { recipeIndex = source.First(); indexIsParent = true; } return recipeIndex; } public static bool IsBookmarkGroupParent(int index) { if (!StaticStorage.BookmarkGroups.TryGetValue(index, out var value)) { return false; } return value.Count > 0; } public static void FlipPageToIndex(int nextIndex) { if (!(Managers.Cursor.grabbedInteractiveItem is BookmarkButtonInactive)) { RecipeBook recipeBook = Managers.Potion.recipeBook; int pagesCount = ((Book)recipeBook).GetPagesCount(); ((Book)recipeBook).curlPageController.HotkeyClicked((nextIndex > ((Book)recipeBook).currentPageIndex) ? (IntExtension.Distance(((Book)recipeBook).currentPageIndex, nextIndex) <= IntExtension.Distance(nextIndex, ((Book)recipeBook).currentPageIndex + pagesCount)) : (IntExtension.Distance(((Book)recipeBook).currentPageIndex, nextIndex) >= IntExtension.Distance(((Book)recipeBook).currentPageIndex, nextIndex + pagesCount)), true, nextIndex); } } public static void ShowHideGroupBookmarkIcon(Bookmark bookmark, bool show) { Transform obj = ((Component)bookmark).transform.Find("GroupCornerIcon"); GameObject val = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)val == (Object)null) { Plugin.PluginLogger.LogError((object)"ERROR: Bookmark does not have a group corner icon setup!"); } else { val.gameObject.SetActive(show); } } } public static class SaveLoadService { private class BookmarkGroupsDeserialized { [JsonProperty("FahlgorithmBookmarkOrganizer")] public StaticStorage.SavedStaticStorage SavedStaticStorage { get; set; } } public static void StoreBookmarkGroups(ref string result) { string modifiedResult = null; string savedStateJson = result; Ex.RunSafe(delegate { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (StaticStorage.BookmarkGroups.Any()) { string text = JsonConvert.SerializeObject((object)new StaticStorage.SavedStaticStorage { BookmarkGroups = StaticStorage.BookmarkGroups, SavedRecipePositions = StaticStorage.SavedRecipePositions, ErrorLog = StaticStorage.ErrorLog, BookmarkManagerVersion = "1.1.0.0" }, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 }); string value = ",\"FahlgorithmBookmarkOrganizer\":" + text; int startIndex = savedStateJson.LastIndexOf('}'); modifiedResult = savedStateJson.Insert(startIndex, value); } }); if (!string.IsNullOrEmpty(modifiedResult)) { result = modifiedResult; } } public static bool RetreiveStoredBookmarkGroups(Type type) { //IL_0059: 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_006a: Expected O, but got Unknown if (type != typeof(ProgressState)) { return true; } string stateJsonString = StaticStorage.StateJsonString; StaticStorage.StateJsonString = null; if (string.IsNullOrEmpty(stateJsonString)) { Plugin.PluginLogger.LogInfo((object)"Error: stateJsonString is empty. Cannot load bookmark groups."); return true; } if (stateJsonString.IndexOf("FahlgorithmBookmarkOrganizer") == -1) { Plugin.PluginLogger.LogInfo((object)"No existing bookmark groups found during load"); return true; } BookmarkGroupsDeserialized bookmarkGroupsDeserialized = JsonConvert.DeserializeObject<BookmarkGroupsDeserialized>(stateJsonString, new JsonSerializerSettings { ReferenceLoopHandling = (ReferenceLoopHandling)1 }); if (bookmarkGroupsDeserialized.SavedStaticStorage?.BookmarkGroups == null) { Plugin.PluginLogger.LogError((object)"Error: An error occured during bookmark group deserialization"); return true; } StaticStorage.BookmarkGroups = bookmarkGroupsDeserialized.SavedStaticStorage.BookmarkGroups; StaticStorage.SavedRecipePositions = bookmarkGroupsDeserialized.SavedStaticStorage.SavedRecipePositions; return true; } public static bool RetrieveStateJsonString(File instance) { StaticStorage.StateJsonString = instance.StateJsonString; return true; } public static bool ClearFileSpecificDataOnFileLoad() { StaticStorage.BookmarkGroups.Clear(); StaticStorage.SavedRecipePositions = null; return true; } public static Sprite GenerateSpriteFromImage(string path, Vector2? pivot = null, bool createComplexMesh = false) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path); byte[] array; using (MemoryStream memoryStream = new MemoryStream()) { manifestResourceStream.CopyTo(memoryStream); array = memoryStream.ToArray(); } Texture2D val = ((!createComplexMesh) ? new Texture2D(0, 0, (GraphicsFormat)8, (TextureCreationFlags)0) { filterMode = (FilterMode)1 } : new Texture2D(0, 0, (TextureFormat)5, false, false) { filterMode = (FilterMode)1 }); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).wrapModeU = (TextureWrapMode)1; ((Texture)val).wrapModeV = (TextureWrapMode)1; ((Texture)val).wrapModeW = (TextureWrapMode)1; if (!ImageConversion.LoadImage(val, array)) { Plugin.PluginLogger.LogError((object)"ERROR: Failed to load Bookmark_organizer_recipe_slot.png."); return null; } Vector2 val2 = (Vector2)(pivot.HasValue ? pivot.Value : new Vector2(0.5f, 0.5f)); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), val2, 100f, 1u, (SpriteMeshType)(createComplexMesh ? 1 : 0)); } } public static class SubRailService { public static bool IsSubRail(BookmarkRail rail) { if ((Object)(object)rail == (Object)null) { return false; } return ((Object)((Component)rail).gameObject).name == "BottomToTopSubRail"; } public static bool IsActiveBookmark(Bookmark bookmark) { if (bookmark.IsActiveBookmark()) { return true; } return false; } public static bool IsInvisiRail(BookmarkRail rail) { if ((Object)(object)rail == (Object)null) { return false; } return ((Object)((Component)rail).gameObject).name == "BottomToTopInvisiRail"; } public static void UpdateSubRailForSelectedIndex(int pageIndex) { UpdateStaticBookmark(pageIndex); int bookmarkStorageRecipeIndex = RecipeBookService.GetBookmarkStorageRecipeIndex(pageIndex); List<Bookmark> allBookmarks = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList(); var list = (from s in GetSubRailRecipesForIndex(bookmarkStorageRecipeIndex) select new { savedBookmark = s, bookmark = allBookmarks[s.recipeIndex], isActive = (pageIndex == s.recipeIndex) }).ToList(); if (list.Any(sb => StaticStorage.SubRail.railBookmarks.Any((Bookmark rb) => (Object)(object)sb.bookmark == (Object)(object)rb))) { list.ForEach(savedBookmark => { savedBookmark.bookmark.CurrentVisualState = (VisualState)(savedBookmark.isActive ? 1 : 0); }); return; } StaticStorage.SubRail.railBookmarks.ToList().ForEach(delegate(Bookmark b) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) Vector2? nextEmptySpaceOnRail = GetNextEmptySpaceOnRail(StaticStorage.InvisiRail); if (!nextEmptySpaceOnRail.HasValue) { throw new Exception("PotionCraftBookmarkOrganizer - Somehow the InvisiRail ran out of space. All hope is lost!"); } ConnectBookmarkToRail(StaticStorage.InvisiRail, b, nextEmptySpaceOnRail.Value); }); list.ForEach(savedBookmark => { //IL_0016: Unknown result type (might be due to invalid IL or missing references) ConnectBookmarkToRail(StaticStorage.SubRail, savedBookmark.bookmark, savedBookmark.savedBookmark.SerializedBookmark.position); savedBookmark.bookmark.CurrentVisualState = (VisualState)(savedBookmark.isActive ? 1 : 0); }); } public static List<BookmarkStorage> GetSubRailRecipesForIndex(int nextPageIndex) { int bookmarkStorageRecipeIndex = RecipeBookService.GetBookmarkStorageRecipeIndex(nextPageIndex); if (!StaticStorage.BookmarkGroups.TryGetValue(bookmarkStorageRecipeIndex, out var value)) { return new List<BookmarkStorage>(); } return value; } public static Vector2? GetNextEmptySpaceOnRail(BookmarkRail rail, bool getMax = false) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) List<MinMaxFloat> emptySegments = rail.GetEmptySegments((SpaceType)0, (Bookmark)null); object? value = typeof(BookmarkController).GetField("spawnHeight", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(rail.bookmarkController); MinMaxFloat val = (MinMaxFloat)((value is MinMaxFloat) ? value : null); if (emptySegments.Any()) { return new Vector2((rail.inverseSpawnOrder || getMax) ? ((MinMax<float, float>)(object)emptySegments.Last()).max : ((MinMax<float, float>)(object)emptySegments.First()).min, ((MinMax<float, float>)(object)val).min); } return null; } public static void UpdateStaticBookmark(int nextPageIndex = -1) { RecipeBook recipeBook = Managers.Potion.recipeBook; if (nextPageIndex == -1) { nextPageIndex = ((Book)recipeBook).currentPageIndex; } bool indexIsParent; int bookmarkStorageRecipeIndex = RecipeBookService.GetBookmarkStorageRecipeIndex(nextPageIndex, out indexIsParent); if ((Object)(object)recipeBook.savedRecipes[bookmarkStorageRecipeIndex] == (Object)null) { ((Component)StaticStorage.StaticBookmark).gameObject.SetActive(false); return; } ((Component)StaticStorage.StaticBookmark).gameObject.SetActive(true); Bookmark bookmarkByIndex = ((Book)recipeBook).bookmarkControllersGroupController.GetBookmarkByIndex(bookmarkStorageRecipeIndex); StaticStorage.StaticBookmark.SetBookmarkContent(((SpriteChangingButton)bookmarkByIndex.activeBookmarkButton).normalSpriteIcon, ((SpriteChangingButton)bookmarkByIndex.inactiveBookmarkButton).normalSpriteIcon, (Sprite)null, ""); StaticStorage.StaticBookmark.CurrentVisualState = (VisualState)((!indexIsParent) ? 1 : 0); } public static int GetPagesCountWithoutSpecialRails() { return ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[2] { StaticStorage.SubRail, StaticStorage.InvisiRail }).Sum((BookmarkRail r) => r.railBookmarks.Count); } public static void ConnectBookmarkToRail(BookmarkRail rail, Bookmark bookmark, Vector2 position) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) List<Bookmark> allBookmarksList = StaticStorage.SubRail.bookmarkController.GetAllBookmarksList(); rail.Connect(bookmark, position); rail.SortBookmarksInClockwiseOrder(); rail.bookmarkController.CallOnBookmarksRearrangeIfNecessary(allBookmarksList); } public static void ShowSubRailAfterFlip() { ((Component)StaticStorage.SubRail).gameObject.SetActive(true); StaticStorage.SubRailPages.gameObject.SetActive(true); StaticStorage.StaticRails.Values.ToList().ForEach(delegate((GameObject, GameObject) r) { r.Item1.SetActive(false); r.Item2.SetActive(false); }); } public static void UpdateNonSubBookmarksActiveState() { int bookmarkStorageRecipeIndexForSelectedRecipe = RecipeBookService.GetBookmarkStorageRecipeIndexForSelectedRecipe(); List<Bookmark> list = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[2] { StaticStorage.SubRail, StaticStorage.InvisiRail }).SelectMany((BookmarkRail r) => r.railBookmarks).ToList(); for (int i = 0; i < list.Count; i++) { list[i].CurrentVisualState = (VisualState)((i == bookmarkStorageRecipeIndexForSelectedRecipe) ? 1 : 0); } } public static void UpdateSubBookmarksActiveState() { List<Bookmark> railBookmarks = StaticStorage.SubRail.railBookmarks; Bookmark val = railBookmarks.FirstOrDefault(); if (!((Object)(object)val == (Object)null)) { int num = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList().IndexOf(val); for (int i = 0; i < railBookmarks.Count; i++) { int num2 = i + num; railBookmarks[i].CurrentVisualState = (VisualState)((num2 == ((Book)Managers.Potion.recipeBook).currentPageIndex) ? 1 : 0); } } } public static Tuple<BookmarkRail, Vector2> GetSpawnPosition(BookmarkController bookmarkController, SpaceType spaceType) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) foreach (BookmarkRail item in bookmarkController.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[2] { StaticStorage.SubRail, StaticStorage.InvisiRail }).ToList()) { List<MinMaxFloat> emptySegments = item.GetEmptySegments(spaceType, (Bookmark)null); if (emptySegments.Any()) { float num = (item.inverseSpawnOrder ? ((MinMax<float, float>)(object)emptySegments.Last()).max : ((MinMax<float, float>)(object)emptySegments.First()).min); object? value = typeof(BookmarkController).GetField("spawnHeight", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(bookmarkController); float random = ((MinMax<float, float>)((value is MinMaxFloat) ? value : null)).GetRandom(); return new Tuple<BookmarkRail, Vector2>(item, new Vector2(num, random)); } } return null; } } } namespace PotionCraftBookmarkOrganizer.Scripts.Patches { public class AddGroupCornerIconToBookmarkPatch { [HarmonyPatch(typeof(Bookmark), "UpdateVisualState")] public class Bookmark_UpdateVisualState { private static void Postfix(Bookmark __instance) { Ex.RunSafe(delegate { UpdateCornerIconScaleToMatchActiveState(__instance); }); } } [HarmonyPatch(typeof(BookmarkButtonInactive), "OnGrabPrimary")] public class InactiveBookmarkButton_OnGrabPrimary { private static void Postfix(BookmarkButtonInactive __instance) { Ex.RunSafe(delegate { UpdateCornerIconScaleToMatchActiveState(__instance, isGrabbed: true); }); } } [HarmonyPatch(typeof(BookmarkButtonInactive), "OnReleasePrimary")] public class InactiveBookmarkButton_OnReleasePrimary { private static void Postfix(BookmarkButtonInactive __instance) { Ex.RunSafe(delegate { UpdateCornerIconScaleToMatchActiveState(__instance, isGrabbed: false); }); } } [HarmonyPatch(typeof(RecipeBook), "UpdateBookmarkIcon")] public class RecipeBook_UpdateBookmarkIcon { private static void Postfix(RecipeBook __instance, int index) { Ex.RunSafe(delegate { AddGroupBookmarkIconToBookmarkOnFirstContentUpdate(__instance, index); }); } } private static Vector2 CornerIconLocation = new Vector2(0.245f, 0.675f); private static Sprite LoadedCornerSprite; private static Sprite LoadedCornerMaskSprite; private static void AddGroupBookmarkIconToBookmarkOnFirstContentUpdate(RecipeBook instance, int index) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) Bookmark bookmarkByIndex = ((Book)instance).bookmarkControllersGroupController.GetBookmarkByIndex(index); if (!((Object)(object)((Component)bookmarkByIndex).gameObject.transform.Find("GroupCornerIcon") != (Object)null)) { if ((Object)(object)LoadedCornerSprite == (Object)null) { LoadedCornerSprite = SaveLoadService.GenerateSpriteFromImage("PotionCraftBookmarkOrganizer.InGameImages.Group_bookmark_icon.png", null, createComplexMesh: true); } if ((Object)(object)LoadedCornerMaskSprite == (Object)null) { LoadedCornerMaskSprite = SaveLoadService.GenerateSpriteFromImage("PotionCraftBookmarkOrganizer.InGameImages.Group_bookmark_icon_mask.png", null, createComplexMesh: true); } GameObject val = new GameObject("GroupCornerIcon"); val.transform.parent = ((Component)bookmarkByIndex).transform; SpriteRenderer obj = val.AddComponent<SpriteRenderer>(); obj.sprite = LoadedCornerSprite; SpriteRenderer spriteRendererIcon = ((SpriteChangingButton)bookmarkByIndex.activeBookmarkButton).spriteRendererIcon; ((Renderer)obj).sortingLayerID = ((Renderer)spriteRendererIcon).sortingLayerID; ((Renderer)obj).sortingLayerName = ((Renderer)spriteRendererIcon).sortingLayerName; ((Renderer)obj).sortingOrder = ((Renderer)spriteRendererIcon).sortingOrder; SpriteMask obj2 = val.AddComponent<SpriteMask>(); obj2.sprite = LoadedCornerMaskSprite; ((Renderer)obj2).sortingLayerID = ((Renderer)spriteRendererIcon).sortingLayerID; ((Renderer)obj2).sortingLayerName = ((Renderer)spriteRendererIcon).sortingLayerName; ((Renderer)obj2).sortingOrder = ((Renderer)spriteRendererIcon).sortingOrder; val.transform.localPosition = Vector2.op_Implicit(CornerIconLocation); val.transform.rotation = Quaternion.identity; val.transform.localEulerAngles = Vector3.zero; bool active = RecipeBookService.IsBookmarkGroupParent(index); val.SetActive(active); } } private static void UpdateCornerIconScaleToMatchActiveState(Bookmark instance) { UpdateCornerIconScaleToMatchActiveState(instance.inactiveBookmarkButton, isGrabbed: false, instance); } private static void UpdateCornerIconScaleToMatchActiveState(BookmarkButtonInactive instance, bool isGrabbed, Bookmark bookmark = null) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Invalid comparison between Unknown and I4 //IL_0082: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bookmark == (Object)null) { bookmark = ((Component)instance).GetComponentInParent<Bookmark>(); } if (!((Object)(object)bookmark == (Object)null) && !((Object)(object)bookmark == (Object)(object)StaticStorage.StaticBookmark)) { Transform obj = ((Component)bookmark).transform.Find("GroupCornerIcon"); GameObject val = ((obj != null) ? ((Component)obj).gameObject : null); if (!((Object)(object)val == (Object)null)) { float num = 1.03f; float num2 = 0.97f; val.transform.localScale = (Vector3)(((int)bookmark.CurrentVisualState == 1) ? new Vector3(num, num, num) : (isGrabbed ? new Vector3(num2, num2, num2) : Vector3.one)); val.transform.localPosition = Vector2.op_Implicit(CornerIconLocation + (Vector2)(((int)bookmark.CurrentVisualState == 1) ? new Vector2(0.01f, 0.01f) : (isGrabbed ? new Vector2(-0.006f, -0.006f) : Vector2.zero))); } } } } public class MoveSubRailBookmarkOnRecipeErasePatch { [HarmonyPatch(typeof(RecipeBook), "EraseRecipe")] public class RecipeBook_EraseRecipe { private static bool Prefix(RecipeBook __instance, ref Potion potion) { return MoveSubRailBookmarkOnRecipeErase(__instance, ref potion); } private static void Postfix() { Ex.RunSafe(delegate { SubRailService.UpdateStaticBookmark(); }); } } [HarmonyPatch(typeof(Book), "GoToTheFirstNotEmptyPage")] public class Book_GoToTheFirstNotEmptyPage { private static bool Prefix(Book __instance) { return Ex.RunSafe(() => ShowPageAfterRecipeDelete(__instance)); } } private static int? ShowPageAfterRecipeDeleteIndex; private static bool MoveSubRailBookmarkOnRecipeErase(RecipeBook instance, ref Potion potion) { Potion localPotion = potion; Ex.RunSafe(delegate { int num = instance.savedRecipes.IndexOf(localPotion); bool indexIsParent; int bookmarkStorageRecipeIndex = RecipeBookService.GetBookmarkStorageRecipeIndex(num, out indexIsParent); bool flag = RecipeBookService.IsBookmarkGroupParent(num); if (indexIsParent || flag) { ShowPageAfterRecipeDeleteIndex = bookmarkStorageRecipeIndex; if (flag) { _ = ((Book)instance).bookmarkControllersGroupController.controllers.First().bookmarkController; BookmarkStorage bookmarkStorage = (from b in StaticStorage.BookmarkGroups[num] orderby (Object)(object)instance.savedRecipes[b.recipeIndex] != (Object)null descending, b.SerializedBookmark.position.x descending select b).FirstOrDefault(); num = bookmarkStorage.recipeIndex; RecipeBookService.PromoteIndexToParent(bookmarkStorage.recipeIndex); localPotion = Managers.Potion.recipeBook.savedRecipes[bookmarkStorage.recipeIndex]; } } }); if ((Object)(object)localPotion != (Object)(object)potion) { potion = localPotion; } return true; } private static bool ShowPageAfterRecipeDelete(Book instance) { RecipeBook val = (RecipeBook)(object)((instance is RecipeBook) ? instance : null); if (val == null) { return true; } if (!ShowPageAfterRecipeDeleteIndex.HasValue) { return true; } int num = ShowPageAfterRecipeDeleteIndex.Value; ShowPageAfterRecipeDeleteIndex = null; if ((Object)(object)val.savedRecipes[num] == (Object)null) { int count = val.savedRecipes.Count; for (int i = 0; i < count; i++) { int num2 = (num + i * -1 + count) % count; RecipeBookService.GetBookmarkStorageRecipeIndex(num2, out var indexIsParent); if ((Object)(object)val.savedRecipes[num2] != (Object)null && !indexIsParent) { num = num2; break; } } } instance.UpdateCurrentPageIndex(num); return false; } } public class RemoveBottomLeftPageTurnButtonPatch { [HarmonyPatch(typeof(Book), "Awake")] public class Book_Awake { private static void Postfix(Book __instance) { Ex.RunSafe(delegate { RemoveBottomLeftPageTurnButton(__instance); }); } } private static void RemoveBottomLeftPageTurnButton(Book instance) { RecipeBook val = (RecipeBook)(object)((instance is RecipeBook) ? instance : null); if (val != null) { ((Component)((Book)val).curlPageController.bottomLeftCorner).gameObject.SetActive(false); } } } public class ClearFileSpecificDataOnFileLoadPatch { [HarmonyPatch(typeof(SaveLoadManager), "LoadFile")] public class SaveLoadManager_LoadFile { private static bool Prefix() { return Ex.RunSafe(() => SaveLoadService.ClearFileSpecificDataOnFileLoad()); } } } public class InjectBookmarkGroupingDataIntoSaveFilePatch { [HarmonyPatch(typeof(SavedState), "ToJson")] public class SavedState_ToJson { private static void Postfix(ref string __result) { SaveLoadService.StoreBookmarkGroups(ref __result); } } } public class LoadBookmarkGroupingDataFromSaveFilePatch { [HarmonyPatch(typeof(SaveLoadManager), "LoadSelectedState")] public class SaveLoadManager_LoadSelectedState { private static bool Prefix(Type type) { return Ex.RunSafe(() => SaveLoadService.RetreiveStoredBookmarkGroups(type)); } } } public class RemoveSubBookmarksFromMainRailsOnLoadPatch { [HarmonyPatch(typeof(BookmarkController), "LoadFrom")] public class BookmarkController_LoadFrom { private static void Postfix(BookmarkController __instance) { Ex.RunSafe(delegate { RemoveSubBookmarksFromMainRailsOnLoad(__instance); }, null, logErrorToStorage: true); } } private static void RemoveSubBookmarksFromMainRailsOnLoad(BookmarkController instance) { if (!((Object)(object)instance != (Object)(object)((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController)) { if (StaticStorage.SavedRecipePositions == null || !StaticStorage.SavedRecipePositions.Any()) { DoHardResetIfNeeded(instance); return; } RemoveSubBookmarksFromMainRails(instance); ReorganizeSavedRecipes(); DoIncorrectCountFailsafe(); StaticStorage.SavedRecipePositions = null; ReparentOrphanedBookmarksFailsafe(instance); } } private static void RemoveSubBookmarksFromMainRails(BookmarkController instance) { List<BookmarkRail> list = instance.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[2] { StaticStorage.SubRail, StaticStorage.InvisiRail }).ToList(); int num = list.Sum((BookmarkRail r) => r.railBookmarks.Count); int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; while (num2 < num) { BookmarkRail val = list[0]; while (num4 >= val.railBookmarks.Count) { num4 = 0; list.RemoveAt(0); val = list[0]; } bool num6 = StaticStorage.SavedRecipePositions[num5] != num3; RecipeBookService.GetBookmarkStorageRecipeIndex(num2, out var indexIsParent); if (!num6 && !indexIsParent) { num4++; num2++; num5++; num3++; } else { Bookmark obj = val.railBookmarks[num4]; val.railBookmarks.RemoveAt(num4); Object.Destroy((Object)(object)((Component)obj).gameObject); num3++; num--; } } } private static void ReorganizeSavedRecipes() { ProgressState selectedProgressState = Managers.SaveLoad.SelectedProgressState; List<SerializedPotionRecipe> list = new List<SerializedPotionRecipe>(); for (int i = 0; i < selectedProgressState.savedRecipes.Count; i++) { list.Add(selectedProgressState.savedRecipes[StaticStorage.SavedRecipePositions[i]]); } selectedProgressState.savedRecipes = list; } private static void DoIncorrectCountFailsafe() { int num = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList().Count; int num2 = StaticStorage.SavedRecipePositions?.Count ?? Managers.Potion.recipeBook.savedRecipes.Count; if (num == num2) { return; } string text = "ERROR: There is an incorrect ammount of bookmarks saved. Running failsafe to fix file! - 2"; Plugin.PluginLogger.LogError((object)text); Ex.SaveErrorMessage(text); while (num > num2) { int count = StaticStorage.InvisiRail.railBookmarks.Count; if (count == 0) { Plugin.PluginLogger.LogError((object)"ERROR: Incorrect count failsafe failed to find enough bookmarks on the invisirail to fix count. To recover save file post it in the Potion Craft discord modding channel!"); break; } Bookmark obj = StaticStorage.InvisiRail.railBookmarks[count - 1]; StaticStorage.InvisiRail.railBookmarks.RemoveAt(count - 1); Object.Destroy((Object)(object)((Component)obj).gameObject); num--; } } private static void DoHardResetIfNeeded(BookmarkController instance) { //IL_01ed: Unknown result type (might be due to invalid IL or missing references) int i = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList().Count; int count = Managers.SaveLoad.SelectedProgressState.savedRecipes.Count; if (i == count) { return; } string text = "ERROR: There is an incorrect ammount of bookmarks saved. Running failsafe to fix file! - 1"; Plugin.PluginLogger.LogError((object)text); Ex.SaveErrorMessage(text); StaticStorage.BookmarkGroups.SelectMany((KeyValuePair<int, List<BookmarkStorage>> b) => b.Value).Count(); List<BookmarkRail> source = instance.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[2] { StaticStorage.SubRail, StaticStorage.InvisiRail }).ToList(); while (StaticStorage.InvisiRail.railBookmarks.Count > 0 || StaticStorage.SubRail.railBookmarks.Count > 0 || i > count) { BookmarkRail val = null; val = (BookmarkRail)((StaticStorage.InvisiRail.railBookmarks.Count > 0) ? StaticStorage.InvisiRail : ((StaticStorage.SubRail.railBookmarks.Count <= 0) ? ((object)((IEnumerable<BookmarkRail>)source).LastOrDefault((Func<BookmarkRail, bool>)((BookmarkRail r) => r.railBookmarks.Count > 0))) : ((object)StaticStorage.SubRail))); if ((Object)(object)val == (Object)null) { Plugin.PluginLogger.LogError((object)"ERROR: Incorrect count failsafe failed to find enough bookmarks on any rails to fix count. To recover save file post it in the Potion Craft discord modding channel!"); return; } Bookmark obj = val.railBookmarks[val.railBookmarks.Count - 1]; val.railBookmarks.RemoveAt(val.railBookmarks.Count - 1); Object.Destroy((Object)(object)((Component)obj).gameObject); i--; } StaticStorage.BookmarkGroups.Clear(); StaticStorage.SavedRecipePositions = null; for (; i < count; i++) { Tuple<BookmarkRail, Vector2> tuple = SubRailService.GetSpawnPosition(instance, (SpaceType)3) ?? SubRailService.GetSpawnPosition(instance, (SpaceType)2) ?? SubRailService.GetSpawnPosition(instance, (SpaceType)1) ?? SubRailService.GetSpawnPosition(instance, (SpaceType)0); if (tuple == null) { Plugin.PluginLogger.LogError((object)"There is no empty space for bookmark! Change settings!"); break; } tuple.Item1.SpawnBookmarkAt(0, tuple.Item2, false); } } private static void ReparentOrphanedBookmarksFailsafe(BookmarkController instance) { List<Bookmark> allBookmarkList = instance.GetAllBookmarksList(); StaticStorage.InvisiRail.railBookmarks.ToList().ForEach(delegate(Bookmark invisiBookmark) { //IL_00b4: 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) int index = allBookmarkList.IndexOf(invisiBookmark); if (!StaticStorage.BookmarkGroups.Any((KeyValuePair<int, List<BookmarkStorage>> bg) => bg.Value.Any((BookmarkStorage b) => b.recipeIndex == index))) { Plugin.PluginLogger.LogError((object)$"ERROR: Orphaned bookmark found at index: {index}. Moving orphaned bookmark to main rails!"); Tuple<BookmarkRail, Vector2> tuple = SubRailService.GetSpawnPosition(instance, (SpaceType)3) ?? SubRailService.GetSpawnPosition(instance, (SpaceType)2) ?? SubRailService.GetSpawnPosition(instance, (SpaceType)1) ?? SubRailService.GetSpawnPosition(instance, (SpaceType)0) ?? new Tuple<BookmarkRail, Vector2>(instance.rails[0], Vector2.zero); SubRailService.ConnectBookmarkToRail(tuple.Item1, invisiBookmark, tuple.Item2); allBookmarkList = instance.GetAllBookmarksList(); } }); } } public class RetrieveStateJsonStringPatch { [HarmonyPatch(typeof(File), "Load")] public class File_Load { private static bool Prefix(File __instance) { return Ex.RunSafe(() => SaveLoadService.RetrieveStateJsonString(__instance)); } } } public class StoreSubRecipesOntoAvailableRailsOnSavePatch { [HarmonyPatch(typeof(BookmarkController), "GetSerialized")] public class BookmarkController_GetSerialized { private static bool Prefix(ref SerializedBookmarkController __result, BookmarkController __instance) { return AssignSubBookmarksToRailsBeforeSerialization(ref __result, __instance); } } private static bool AssignSubBookmarksToRailsBeforeSerialization(ref SerializedBookmarkController result, BookmarkController instance) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown if ((Object)(object)instance != (Object)(object)((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController) { return true; } SerializedBookmarkController serialized = new SerializedBookmarkController(); Ex.RunSafe(delegate { Dictionary<BookmarkRail, List<(SerializedBookmark, int)>> subBookmarkPositions = new Dictionary<BookmarkRail, List<(SerializedBookmark, int)>>(); List<BookmarkStorage> list = StaticStorage.BookmarkGroups.SelectMany((KeyValuePair<int, List<BookmarkStorage>> bg) => bg.Value).ToList(); Tuple<BookmarkRail, Vector2> defaultSpawnPosition = null; list.ForEach(delegate(BookmarkStorage bookmark) { //IL_00ea: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) Tuple<BookmarkRail, Vector2> tuple = GetSpawnPosition(instance, (SpaceType)3, subBookmarkPositions) ?? GetSpawnPosition(instance, (SpaceType)2, subBookmarkPositions) ?? GetSpawnPosition(instance, (SpaceType)1, subBookmarkPositions) ?? GetSpawnPosition(instance, (SpaceType)0, subBookmarkPositions); if (defaultSpawnPosition == null) { defaultSpawnPosition = tuple; } if (tuple == null) { if (defaultSpawnPosition == null) { defaultSpawnPosition = new Tuple<BookmarkRail, Vector2>(instance.rails[0], Vector2.zero); } tuple = defaultSpawnPosition; } defaultSpawnPosition = MoveDefaultSpawnPosition(defaultSpawnPosition); if (!subBookmarkPositions.ContainsKey(tuple.Item1)) { subBookmarkPositions[tuple.Item1] = new List<(SerializedBookmark, int)>(); } SerializedBookmark item = new SerializedBookmark { position = tuple.Item2, prefabIndex = bookmark.SerializedBookmark.prefabIndex, isMirrored = bookmark.SerializedBookmark.isMirrored }; subBookmarkPositions[tuple.Item1].Add((item, bookmark.recipeIndex)); }); serialized.serializedRails = instance.rails.Select((BookmarkRail rail) => GetSerialized(rail, subBookmarkPositions)).ToList(); DoFailsafeIfNeeded(instance, serialized, subBookmarkPositions, defaultSpawnPosition); RearrangeSavedBookmarksToWorkForBookmarkOrder(serialized, subBookmarkPositions); }, null, logErrorToStorage: true); result = serialized; return false; } private static Tuple<BookmarkRail, Vector2> MoveDefaultSpawnPosition(Tuple<BookmarkRail, Vector2> defaultSpawnPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) defaultSpawnPosition = new Tuple<BookmarkRail, Vector2>(defaultSpawnPosition.Item1, new Vector2(defaultSpawnPosition.Item2.x + 0.09952f, defaultSpawnPosition.Item2.y)); return defaultSpawnPosition; } private static void DoFailsafeIfNeeded(BookmarkController instance, SerializedBookmarkController serialized, Dictionary<BookmarkRail, List<(SerializedBookmark, int)>> subBookmarkPositions, Tuple<BookmarkRail, Vector2> defaultSpawnPosition) { //IL_0118: 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) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) int num = Managers.SaveLoad.SelectedProgressState.savedRecipes.Count - serialized.serializedRails.Take(serialized.serializedRails.Count - 2).Sum((SerializedBookmarkRail r) => r.serializedBookmarks.Count); if (num <= 0) { return; } string text = "ERROR: There are not enough saved bookmarks when saving. Running failsafe to fix file!"; Plugin.PluginLogger.LogError((object)text); Ex.SaveErrorMessage(text); for (int i = 0; i < num; i++) { defaultSpawnPosition = MoveDefaultSpawnPosition(defaultSpawnPosition); Tuple<BookmarkRail, Vector2> tuple = GetSpawnPosition(instance, (SpaceType)3, subBookmarkPositions) ?? GetSpawnPosition(instance, (SpaceType)2, subBookmarkPositions) ?? GetSpawnPosition(instance, (SpaceType)1, subBookmarkPositions) ?? GetSpawnPosition(instance, (SpaceType)0, subBookmarkPositions) ?? defaultSpawnPosition ?? new Tuple<BookmarkRail, Vector2>(instance.rails[0], Vector2.zero); if (!subBookmarkPositions.ContainsKey(tuple.Item1)) { subBookmarkPositions[tuple.Item1] = new List<(SerializedBookmark, int)>(); } SerializedBookmark item = new SerializedBookmark { position = tuple.Item2, prefabIndex = 0, isMirrored = false }; subBookmarkPositions[tuple.Item1].Add((item, -1)); } serialized.serializedRails = instance.rails.Select((BookmarkRail rail) => GetSerialized(rail, subBookmarkPositions)).ToList(); } private static void RearrangeSavedBookmarksToWorkForBookmarkOrder(SerializedBookmarkController serialized, Dictionary<BookmarkRail, List<(SerializedBookmark, int)>> subBookmarkPositions) { List<(SerializedBookmark, int)> subBookmarkList = subBookmarkPositions.Values.SelectMany((List<(SerializedBookmark, int)> v) => v).ToList(); List<(int, int)> intList = new List<(int, int)>(); int addedSubBookmarks = 0; int num = serialized.serializedRails.Count - 2; for (int j = 0; j < num; j++) { serialized.serializedRails[j].serializedBookmarks.ForEach(delegate(SerializedBookmark sb) { int count = intList.Count; if (!TryFirst(subBookmarkList, ((SerializedBookmark, int) b) => b.Item1 == sb, out var first)) { intList.Add((intList.Count - addedSubBookmarks, count)); } else { intList.Add((first.Item2, count)); addedSubBookmarks++; } }); } List<SerializedPotionRecipe> list = new List<SerializedPotionRecipe>(); for (int k = 0; k < Managers.SaveLoad.SelectedProgressState.savedRecipes.Count; k++) { int item = intList[k].Item1; item = GetRecipeIndexForFailsafeIfNeeded(intList, k, item); list.Add(Managers.SaveLoad.SelectedProgressState.savedRecipes[item]); } Managers.SaveLoad.SelectedProgressState.savedRecipes = list; StaticStorage.SavedRecipePositions = (from i in intList orderby i.Item1 select i.Item2).ToList(); } private static int GetRecipeIndexForFailsafeIfNeeded(List<(int, int)> intList, int newIndex, int oldIndex) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown if (oldIndex == -1) { int i2; for (i2 = 0; i2 < Managers.SaveLoad.SelectedProgressState.savedRecipes.Count; i2++) { if (!intList.Any(((int, int) item) => item.Item1 == i2)) { oldIndex = i2; intList[newIndex] = (i2, intList[newIndex].Item2); List<BookmarkStorage> list = StaticStorage.BookmarkGroups.Values.FirstOrDefault(); if (list == null) { list = new List<BookmarkStorage>(); StaticStorage.BookmarkGroups[0] = list; } Vector2 val = (Vector2)(((??)list.FirstOrDefault()?.SerializedBookmark?.position) ?? new Vector2(0.5f, 0f)); ((Vector2)(ref val))..ctor(val.x + 0.09953334f, val.y); list.Add(new BookmarkStorage { recipeIndex = i2, SerializedBookmark = new SerializedBookmark { position = val, prefabIndex = 0, isMirrored = false } }); break; } } } return oldIndex; } private static SerializedBookmarkRail GetSerialized(BookmarkRail rail, Dictionary<BookmarkRail, List<(SerializedBookmark, int)>> subBookmarks) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown List<SerializedBookmark> list = rail.railBookmarks.Select((Bookmark bookmark) => bookmark.GetSerialized()).ToList(); if (subBookmarks.TryGetValue(rail, out var value)) { list = list.Concat(value.Select(((SerializedBookmark, int) b) => b.Item1)).ToList(); list.Sort((SerializedBookmark b1, SerializedBookmark b2) => b1.position.x.CompareTo(b2.position.x)); } return new SerializedBookmarkRail { serializedBookmarks = list }; } private static bool TryFirst<T>(List<T> values, Func<T, bool> compareFunc, out T first) { first = default(T); foreach (T value in values) { if (compareFunc(value)) { first = value; return true; } } return false; } public static Tuple<BookmarkRail, Vector2> GetSpawnPosition(BookmarkController bookmarkController, SpaceType spaceType, Dictionary<BookmarkRail, List<(SerializedBookmark, int)>> subBookmarks) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) foreach (BookmarkRail item in bookmarkController.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[2] { StaticStorage.SubRail, StaticStorage.InvisiRail }).ToList()) { List<MinMaxFloat> emptySegments = GetEmptySegments(item, spaceType, subBookmarks); if (emptySegments.Any()) { float num = (item.inverseSpawnOrder ? ((MinMax<float, float>)(object)emptySegments.Last()).max : ((MinMax<float, float>)(object)emptySegments.First()).min); object? value = typeof(BookmarkController).GetField("spawnHeight", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(bookmarkController); float random = ((MinMax<float, float>)((value is MinMaxFloat) ? value : null)).GetRandom(); return new Tuple<BookmarkRail, Vector2>(item, new Vector2(num, random)); } } return null; } private static List<MinMaxFloat> GetEmptySegments(BookmarkRail rail, SpaceType spaceType, Dictionary<BookmarkRail, List<(SerializedBookmark, int)>> subBookmarks) { //IL_0001: 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_0099: Expected O, but got Unknown List<MinMaxFloat> emptySegments = rail.GetEmptySegments(spaceType, (Bookmark)null); if (!subBookmarks.ContainsKey(rail)) { return emptySegments; } List<(SerializedBookmark, int)> list = subBookmarks[rail].OrderBy(((SerializedBookmark, int) b) => b.Item1.position.x).ToList(); for (int i = 0; i < emptySegments.Count; i++) { if (!list.Any()) { break; } MinMaxFloat val = emptySegments[i]; (SerializedBookmark, int) tuple = list[0]; if (!(tuple.Item1.position.x < ((MinMax<float, float>)(object)val).min)) { MinMaxFloat item = new MinMaxFloat(((MinMax<float, float>)(object)val).min, tuple.Item1.position.x); int index = i + 1; emptySegments.Insert(index, item); list.RemoveAt(0); } } return emptySegments; } } public class UpdateUIOnRecipeBookLoadPatch { [HarmonyPatch(typeof(RecipeBook), "OnLoad")] public class RecipeBook_OnLoad { private static void Postfix() { Ex.RunSafe(delegate { UpdateUIOnRecipeBookLoad(); }); } } private static void UpdateUIOnRecipeBookLoad() { StaticStorage.IsLoaded = true; SubRailService.UpdateStaticBookmark(); EnsureSubBookmarksAreShowingFailsafe(); } private static void EnsureSubBookmarksAreShowingFailsafe() { int pageIndex = ((Book)Managers.Potion.recipeBook).currentPageIndex; int bookmarkStorageRecipeIndex = RecipeBookService.GetBookmarkStorageRecipeIndex(pageIndex); List<Bookmark> allBookmarks = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.GetAllBookmarksList(); var list = (from sb in (from s in SubRailService.GetSubRailRecipesForIndex(bookmarkStorageRecipeIndex) select new { savedBookmark = s, bookmark = allBookmarks[s.recipeIndex], isActive = (pageIndex == s.recipeIndex) }).ToList() where StaticStorage.SubRail.railBookmarks.All((Bookmark rb) => (Object)(object)sb.bookmark != (Object)(object)rb) select sb).ToList(); if (list.Any()) { Plugin.PluginLogger.LogError((object)"ERROR: Not all bookmarks are showing on subrail on load! Adding missing bookmarks to subrail."); list.ForEach(savedBookmark => { //IL_0025: Unknown result type (might be due to invalid IL or missing references) Plugin.PluginLogger.LogMessage((object)"Adding bookmark"); SubRailService.ConnectBookmarkToRail(StaticStorage.SubRail, savedBookmark.bookmark, savedBookmark.savedBookmark.SerializedBookmark.position); savedBookmark.bookmark.CurrentVisualState = (VisualState)(savedBookmark.isActive ? 1 : 0); }); } } } public class CreateSubRailForRecipePagePatch { [HarmonyPatch(typeof(PotionCustomizationPanel), "OnPanelContainerStart")] public class PotionCustomizationPanel_OnPanelContainerStart { private static void Postfix(PotionCustomizationPanel __instance) { Ex.RunSafe(delegate { CreateSubRailForRecipePage(__instance); }); } } private static void CreateSubRailForRecipePage(PotionCustomizationPanel instance) { RecipeBookLeftPageContent componentInParent = ((Component)instance).gameObject.GetComponentInParent<RecipeBookLeftPageContent>(); if (!((Object)(object)componentInParent == (Object)null)) { if ((Object)(object)StaticStorage.SubRail != (Object)null) { CreateStaticRailCopyForPage(componentInParent); ShrinkDescriptionBox(componentInParent); return; } RecipeBookService.SetupListeners(); SetupInvisiRail(); (GameObject, GameObject) tuple = SetupBookmarkContainer(componentInParent); SetupRail(tuple.Item1, tuple.Item2); CreateStaticRailCopyForPage(componentInParent); ShrinkDescriptionBox(componentInParent); } } private static void SetupRail(GameObject subRailPages, GameObject subRailBookmarkContainer) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_012d: Unknown result type (might be due to invalid IL or missing references) BookmarkController bookmarkController = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController; GameObject val = new GameObject("BottomToTopSubRail"); val.transform.parent = ((Component)bookmarkController).gameObject.transform; val.transform.localPosition = subRailBookmarkContainer.transform.localPosition; BookmarkRail val2 = (StaticStorage.SubRail = val.AddComponent<BookmarkRail>()); BookmarkController bookmarkController2 = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController; val.transform.parent = ((Component)bookmarkController2).transform; subRailBookmarkContainer.transform.parent = ((Component)val2).transform; subRailBookmarkContainer.transform.localPosition = Vector2.op_Implicit(Vector2.zero); val2.bookmarksContainer = subRailBookmarkContainer.transform; Transform val3 = StaticStorage.SubRailLayers.First(); typeof(BookmarkRail).GetField("activeLayer", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(val2, val3); val3.localPosition = Vector3.zero; val3.localEulerAngles = Vector3.zero; SpriteRenderer componentInChildren = subRailPages.GetComponentInChildren<SpriteRenderer>(); val2.size = new Vector2(componentInChildren.size.y - 0.5f, 0.7f); val2.direction = (Direction)3; val2.bottomLine = typeof(BookmarkRail).GetMethod("GetBottomLine", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(val2, null) as Tuple<Vector2, Vector2>; typeof(BookmarkRail).GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(val2, null); val2.bookmarkController.rails.Add(val2); SetupStaticBookmark(val2); } private static void SetupStaticBookmark(BookmarkRail subRail) { //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_0024: 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) Vector2 value = SubRailService.GetNextEmptySpaceOnRail(subRail, getMax: true).Value; float num = subRail.bookmarkController.minBookmarksSpace * 0.75f; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(value.x + num, -0.04f); StaticStorage.StaticBookmark = subRail.SpawnBookmarkAt(0, val, false); ((Component)StaticStorage.StaticBookmark).transform.parent = StaticStorage.SubRailActiveBookmarkLayer.transform; subRail.railBookmarks.Clear(); } private static void SetupInvisiRail() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) //IL_0069: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) BookmarkController bookmarkController = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController; GameObject val = new GameObject("BottomToTopInvisiRail"); val.transform.localPosition = Vector2.op_Implicit(new Vector2(0f, 300f)); val.transform.parent = ((Component)bookmarkController).gameObject.transform; GameObject val2 = new GameObject("InvisiRailBookmarkContainer"); GameObject val3 = new GameObject("Layer 0"); val3.transform.parent = val2.transform; StaticStorage.InvisiRailLayer = val3.transform; BookmarkRail val4 = (StaticStorage.InvisiRail = val.AddComponent<BookmarkRail>()); BookmarkController bookmarkController2 = ((Book)Managers.Potion.recipeBook).bookmarkControllersGroupController.controllers.First().bookmarkController; val.transform.parent = ((Component)bookmarkController2).transform; val2.transform.parent = ((Component)val4).transform; val2.transform.localPosition = Vector2.op_Implicit(Vector2.zero); val4.bookmarksContainer = val2.transform; Transform transform = val3.transform; typeof(BookmarkRail).GetField("activeLayer", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(val4, transform); transform.localPosition = Vector3.zero; transform.localEulerAngles = Vector3.zero; val4.size = new Vector2(100f, 0.7f); val4.direction = (Direction)3; val4.bottomLine = typeof(BookmarkRail).GetMethod("GetBottomLine", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(val4, null) as Tuple<Vector2, Vector2>; typeof(BookmarkRail).GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(val4, null); val4.bookmarkController.rails.Add(val4); } private static (GameObject, GameObject) SetupBookmarkContainer(RecipeBookLeftPageContent page) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: 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) GameObject val = new GameObject("SubRailBookmarkContainer"); GameObject val2 = (StaticStorage.SubRailPages = new GameObject("SubRailPages")); Transform parent = ((Component)Managers.Potion.recipeBook).transform.Find("ContentContainer").Find("BackgroundPages"); val2.transform.parent = parent; Sprite val3 = SaveLoadService.GenerateSpriteFromImage("PotionCraftBookmarkOrganizer.InGameImages.Bookmark_organizer_recipe_slot_bottom_left_mask.png", null, createComplexMesh: true); if ((Object)(object)val3 == (Object)null) { return (null, null); } object? value = typeof(RecipeBookLeftPageContent).GetField("titleDecorLeftRenderer", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(page); object? obj = ((value is SpriteRenderer) ? value : null); int sortingLayerID = ((Renderer)obj).sortingLayerID; string sortingLayerName = ((Renderer)obj).sortingLayerName; int num = 511; for (int num2 = 4 - 1; num2 >= 0; num2--) { GameObject val4 = new GameObject($"Layer{num2}"); val4.transform.parent = val2.transform; val4.AddComponent<PageLayer>(); SpriteRenderer val5 = val4.AddComponent<SpriteRenderer>(); Sprite val6 = SaveLoadService.GenerateSpriteFromImage($"PotionCraftBookmarkOrganizer.InGameImages.Bookmark_organizer_recipe_slot_{num2}.png"); if ((Object)(object)val6 == (Object)null) { return (null, null); } val5.sprite = val6; ((Renderer)val5).sortingLayerID = sortingLayerID; ((Renderer)val5).sortingLayerName = sortingLayerName; ((Renderer)val5).sortingOrder = num; BoxCollider2D val7 = val4.AddComponent<BoxCollider2D>(); if (num2 == 0) { ((Collider2D)val7).isTrigger = true; } val7.size = val5.size; (GameObject, GameObject) tuple = CreateBookmarkLayer(val, val3, sortingLayerID, sortingLayerName, num, $"Layer {num2}"); StaticStorage.SubRailLayers.Add(tuple.Item1.transform); StaticStorage.SubRailLayers.Add(tuple.Item1.transform); StaticStorage.SubRailLayers.Add(tuple.Item1.transform); if (num2 == 0) { GameObject item = tuple.Item2; SpriteRenderer val8 = item.AddComponent<SpriteRenderer>(); val8.sprite = val3; DummyInteractiveItem dummyInteractiveItem = item.AddComponent<DummyInteractiveItem>(); ((InteractiveItem)dummyInteractiveItem).raycastPriorityLevel = -11000f; ((InteractiveItem)dummyInteractiveItem).cursorRadiusCollision = false; ((InteractiveItem)dummyInteractiveItem).showOnlyFingerWhenInteracting = true; item.AddComponent<PolygonCollider2D>(); item.layer = 5; ((Renderer)val8).enabled = false; } num += 20; } StaticStorage.SubRailActiveBookmarkLayer = CreateBookmarkLayer(val, val3, sortingLayerID, sortingLayerName, num - 11, "ActiveBookmarkLayer").Item1; StaticStorage.SubRailLayers.Reverse(); val.transform.localPosition = Vector2.op_Implicit(new Vector2(-7.594f, -4.13f)); val2.transform.localPosition = Vector2.op_Implicit(new Vector2(-7.165f, -4.07f)); return (val2, val); } private static void CreateStaticRailCopyForPage(RecipeBookLeftPageContent parentPage) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002c: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("StaticSubRail"); val.transform.parent = ((Component)parentPage).transform; val.transform.localPosition = Vector2.op_Implicit(new Vector2(-3.443f, -4.07f)); SpriteRenderer component = ((Component)((Component)parentPage).transform.parent.Find("Scratches")).GetComponent<SpriteRenderer>(); SortingGroup obj = val.AddComponent<SortingGroup>(); obj.sortingLayerID = ((Renderer)component).sortingLayerID; obj.sortingLayerName = ((Renderer)component).sortingLayerName; obj.sortingOrder = ((Renderer)component).sortingOrder + 1; GameObject val2 = Object.Instantiate<GameObject>(StaticStorage.SubRailPages, val.transform); val2.transform.localPosition = Vector2.op_Implicit(new Vector2(0.2933f, 0f)); val2.SetActive(false); GameObject val3 = new GameObject("StaticBookmarkContainer"); val3.transform.parent = val.transform; val3.transform.localPosition = Vector2.op_Implicit(new Vector2(-0.1365f, -0.06f)); val3.SetActive(false); StaticStorage.StaticRails[parentPage] = (val3, val2); } private static (GameObject, GameObject) CreateBookmarkLayer(GameObject subRailBookmarkContainer, Sprite maskSprite, int sortingLayerId, string sortingLayerName, int currentSortOrder, string layerName) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0074: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(layerName); val.transform.parent = subRailBookmarkContainer.transform; SortingGroup obj = val.AddComponent<SortingGroup>(); obj.sortingLayerID = sortingLayerId; obj.sortingLayerName = sortingLayerName; obj.sortingOrder = currentSortOrder - 10; GameObject val2 = new GameObject("BookmarkMask"); val2.transform.parent = val.transform; val2.AddComponent<SpriteMask>().sprite = maskSprite; val2.transform.rotation = Quaternion.Euler(0f, 0f, 270f); Transform transform = val2.transform; transform.localPosition += new Vector3(0.06f, -1.61f, 0.96f); return (val, val2); } private static void ShrinkDescriptionBox(RecipeBookLeftPageContent parentPage) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)((Component)parentPage.potionCustomizationPanel).transform.Find("InputFieldCanvas")).transform; Transform val = transform.Find("DescriptionTop"); Transform val2 = transform.Find("DescriptionBottom"); Transform val3 = transform.Find("DescriptionBackground Top"); Transform val4 = transform.Find("DescriptionBackground Bottom"); Transform val5 = transform.Find("DescriptionBackground Left"); Transform val6 = transform.Find("DescriptionBackground Right"); Transform obj = transform.Find("Maskable"); Vector3 val7 = default(Vector3); ((Vector3)(ref val7))..ctor(0.3309f, 0f); Transform transform2 = ((Component)val3).transform; transform2.localPosition += val7; Transform transform3 = ((Component)val4).transform; transform3.localPosition += val7; Transform transform4 = ((Component)val).transform; transform4.localPosition += val7; Transform transform5 = ((Component)val2).transform; transform5.localPosition += val7; Transform transform6 = ((Component)obj).transform; transform6.localPosition += val7; ((Vector3)(ref val7))..ctor(0.02f, 0f); Transform transform7 = ((Component)val6).transform; transform7.localPosition += val7; ((Vector3)(ref val7))..ctor(0.64f, 0f); Transform transform8 = ((Component)val5).transform; transform8.localPosition += val7; Vector3 localScale = ((Component)val3).transform.localScale; Vector3 localScale2 = default(Vector3); ((Vector3)(ref localScale2))..ctor(localScale.x * 0.9018f, localScale.y, localScale.z); ((Component)val3).transform.localScale = localScale2; ((Component)val4).transform.localScale = localScale2; ((Component)val).transform.localScale = localScale2; ((Component)val2).transform.localScale = localScale2; Vector3 localScale3 = default(Vector3); ((Vector3)(ref localScale3))..ctor(0.9018f, 1f, 1f); ((Component)obj).transform.localScale = localScale3; } } public class DisableGrabbingForInactiveStaticBookmarkPatch { [HarmonyPatch(typeof(BookmarkButtonInactive), "OnGrabPrimary")] public class InactiveBookmarkButton_OnGrabPrimary { private static bool Prefix(BookmarkButtonInactive __instance) { return Ex.RunSafe(() => DisableGrabbingForInactiveStaticBookmark(__instance)); } } private static bool DisableGrabbingForInactiveStaticBookmark(BookmarkButtonInactive instance) { return (Object)(object)((BookmarkButton)instance).bookmark != (Object)(object)StaticStorage.StaticBookmark; } } public class DisableGrabbingForStaticBookmarkPatch { [HarmonyPatch(typeof(Bookmark), "UpdateMovingState")] public class Bookmark_UpdateMovingState { private static bool Prefix(Bookmark __instance, MovingState value) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) return Ex.RunSafe(() => DisableGrabbingForStaticBookmark(__instance, value)); } } private static bool DisableGrabbingForStaticBookmark(Bookmark instance, MovingState value) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if ((Object)(object)instance != (Object)(object)StaticStorage.StaticBookmark) { return true; } if ((int)value == 1) { return false; } return true; } } public class DisableMovingBookmarkToOwnSubRailPatch { [HarmonyPatch(typeof(BookmarkRail), "Connect")] public class BookmarkRail_Connect { private static bool Prefix(BookmarkRail __instance, Bookmark bookmark) { return Ex.RunSafe(() => DisableMovingBookmarkToOwnSubRail(__instance, bookmark)); } } private static bool DisableMovingBookmarkToOwnSubRail(BookmarkRail instance, Bookmark bookmark) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (!StaticStorage.IsLoaded) { return true; } if ((Object)(object)instance != (Object)(object)StaticStorage.SubRail) { return true; } if ((int)bookmark.CurrentMovingState == 0) { return true; } int num = (typeof(Bookmark).GetField("bookmarksListBeforeMoving", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(bookmark) as List<Bookmark>).IndexOf(bookmark); bool flag = RecipeBookService.IsBookmarkGroupParent(num); if (num != ((Book)Managers.Potion.recipeBook).currentPageIndex && !flag) { return true; } Vector2 mouseWorldPosition = Managers.Input.controlsProvider.CurrentMouseWorldPosition; BookmarkRail val = (from bRail in instance.bookmarkController.rails.Except((IEnumerable<BookmarkRail>)(object)new BookmarkRail[1] { instance }) orderby VectorExtension.GetDistanceToLineSegment(mouseWorldPosition - Vector2.op_Implicit(((Component)bRail).transform.position), bRail.bottomLine.Item1, bRail.bottomLine.Item2) select bRail).First(); Dictionary<BookmarkRail, List<MinMaxFloat>> dictionary = typeof(Bookmark).GetField("emptySegmentsForMoving", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(bookmark) as Dictionary<BookmarkRail, List<MinMaxFloat>>; if ((Object)(object)val == (Object)(object)bookmark.rail || dictionary[val].Count == 0) { return false; } val.Connect(bookmark, val.GetMovingToNormalizedPosition(dictionary[val], bookmark)); return false; } } public class DisableRecipeBookHotkeysWhileDraggingBookmarkPatch { [HarmonyPatch(typeof(CurlPageCornerController), "FlipPage")] public class CurlPageCornerController_FlipPage { private static bool Prefix() { return Ex.RunSafe(() => DisableRecipeBookHotkeysWhileDraggingBookmark()); } } private static bool DisableRecipeBookHotkeysWhileDraggingBookmark() { return !(Managers.Cursor.grabbedInteractiveItem is BookmarkButtonInactive); } } public class DisallowSpawningOfNewBookmarksOnSpecialRailsPatch { [HarmonyPatch(typeof(BookmarkController), "AddNewBookmark")] public class Bookmark_AddNewBookmark { private static bool Prefix() { return Ex.RunSafe(() => SetAddingBookmarkFlag(adding: true)); } private static void Postfix() { Ex.RunSafe(() => SetAddingBookmarkFlag(adding: false)); } } [HarmonyPatch(typeof(BookmarkRail), "GetEmptySegments")] public class BookmarkRail_GetEmptySegments { private static bool Prefix(ref List<MinMaxFloat> __result, BookmarkRail __instance) { return DisallowSpawningOfNewBookmarksOnSpecialRails(ref __result, __instance); } } private static bool addingNewBookmark; private static bool SetAddingBookmarkFlag(bool adding) { addingNewBookmark = adding; return true; } private static bool DisallowSpawningOfNewBookmarksOnSpecialRails(ref List<MinMaxFloat> result, BookmarkRail instance) { if (!addingNewBookmark) { return true; } if ((Object)(object)instance != (Object)(object)StaticStorage.SubRail && (Object)(object)instance != (Object)(object)StaticStorage.InvisiRail) { return true; } result = new List<MinMaxFloat>(); return false; } } public class HideStaticRailsAndShowRealRailAfterFlipAnimationPatch { [HarmonyPatch(typeof(CurlPageController), "OnPageFlippingEnd")] public class CurlPageController_OnPageFlippingEnd { private static void Postfix(CurlPageController __instance) { Ex.RunSafe(delegate { HideStaticRailsAndShowRealRailAfterFlipAnimation(__instance); }); } } private static void HideStaticRailsAndShowRealRailAfterFlipAnimation(CurlPageController instance) { SubRailService.ShowSubRailAfterFlip(); SubRailService.UpdateNonSubBookmarksActiveState(); } } public class OpenParentRecipeOnInactiveStaticBookmarkClickPatch { [HarmonyPatch(typeof(BookmarkButtonInactive), "OnReleasePrimary")] public class InactiveBookmarkButton_OnReleasePrimary { private static bool Prefix(BookmarkButtonInactive __instance) { return Ex.RunSafe(() => DisableGrabbingForInactiveStaticBookmark(__instance)); } } private static bool DisableGrabbingForInactiveStaticBookmark(BookmarkButtonInactive instance) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Bookmark bookmark = ((BookmarkButton)instance).bookmark; if ((Object)(object)bookmark != (Object)(object)StaticStorage.StaticBookmark) { return true; } int bookmarkStorageRecipeIndexForSelectedRecipe = RecipeBookService.GetBookmarkStorageRecipeIndexForSelectedRecipe(); Bookmark bookmarkByIndex = bookmark.rail.bookmarkController.GetBookmarkByIndex(bookmarkStorageRecipeIndexForSelectedRecipe); bookmark.rail.bookmarkController.bookmarkControllersGroupController.SetActiveBookmark(bookmarkByIndex, true); bookmark.CurrentVisualState = (VisualState)1; ((BookmarkButton)bookmark.activeBookmarkButton).slot.Selected = true; Bounds bounds = ((Button)bookmark.activeBookmarkButton).thisCollider.bounds; if (((Bounds)(ref bounds)).Contains(Vector2.op_Implicit(Managers.Input.controlsProvider.CurrentMouseWorldPosition))) { ((Button)bookmark.activeBookmarkButton).SetHovered(true); } typeof(BookmarkButtonInactive).GetField("grabConditionChecked", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, true); return false; } } public class OverrideGetTooltipContentForStaticBookmarkPatch { [HarmonyPatch(typeof(RecipeBookBookmarkTooltipContentContainer), "GetTooltipContent")] public class RecipeBookBookmarkTooltipContentContainer_GetTooltipContent { private static bool Prefix(ref TooltipContent __result, Bookmark ___bookmark) { return OverrideGetTooltipContentForStaticBookmark(ref __result, ___bookmark); } } private static bool OverrideGetTooltipContentForStaticBookmark(ref TooltipContent __result, Bookmark bookmark) { if ((Object)(object)bookmark != (Object)(object)StaticStorage.StaticBookmark) { return true; } int bookmarkStorageRecipeIndexForSelectedRecipe = RecipeBookService.GetBookmarkStorageRecipeIndexForSelectedRecipe(); Potion obj = Managers.Potion.recipeBook.savedRecipes[bookmarkStorageRecipeIndexForSelectedRecipe]; __result = ((obj != null) ? ((InventoryItem)obj).GetTooltipContent(1, (ItemsPanel)null, false) : null); return false; } } public class OverrideNextIndexWhenSwitchingPagesPatch { [HarmonyPatch(typeof(Book), "OnBookmarksRearranged")] public class Book_OnBookmarksRearranged { private static void Postfix(Book __instance, List<int> newIndexes) { Ex.RunSafe(delegate { UpdatePageIndexesOnRearrange(__instance, newIndexes); }); } } [HarmonyPatch(typeof(Book), "GetNextPageIndex")] public class Book_GetNextPageIndex { private static bool Prefix(ref int __result, Book __instance) { return OverrideNextIndexWhenSwitchingPages(ref __result, __instance, next: true); } } [HarmonyPatch(typeof(Book), "GetPreviousPageIndex")] public class Book_GetPreviousPageIndex { private static bool Prefix(ref int __result, Book __instance) { return OverrideNextIndexWhenSwitchingPages(ref __result, __instance, next: false); } } private static bool OverrideNextIndexWhenSwitchingPages(ref int result, Book instance, bool next) { if (!(instance is RecipeBook)) { return true; } int newResult = -1; Ex.RunSafe(delegate { int currentPageIndex = instance.currentPageIndex; bool indexIsParent; int bookmarkStorageRecipeIndex = RecipeBookService.GetBookmarkStorageRecipeIndex(currentPageIndex, out indexIsParent); bool flag = RecipeBookService.IsBookmarkGroupParent(currentPageIndex); if (!indexIsParent && !flag) { if (next) { int pagesCountWithoutSpecialRails = SubRailService.GetPagesCountWithoutSpecialRails(); newResult = (currentPageIndex + 1 + pagesCountWithoutSpecialRails) % pagesCountWithoutSpecialRails; } else { newResult = GetPreviousIndexForPreviousGroup(bookmarkStorageRecipeIndex); } } else { List<BookmarkStorage> currentBookmarkGroup = StaticStorage.BookmarkGroups[bookmarkStorageRecipeIndex]; BookmarkStorage bookmarkStorage = null; if (indexIsParent) { bookmarkStorage = GetNextBookmarkFromGroup(currentBookmarkGroup, currentPageIndex, next, isParent: false); if (bookmarkStorage != null) { newResult = bookmarkStorage.recipeIndex; } else if (next) { int pagesCountWithoutSpecialRails2 = SubRailService.GetPagesCountWithoutSpecialRails(); newResult = (bookmarkStorageRecipeIndex + 1 + pagesCountWithoutSpecialRails2) % pagesCountWithoutSpecialRails2; } else { newResult = bookmarkStorageRecipeIndex; } } else if (next) { newResult = GetNextBookmarkFromGroup(currentBookmarkGroup, currentPageIndex, next, isParent: true).recipeIndex; } else { newResult = GetPreviousIndexForPreviousGroup(bookmarkStorageRecipeIndex); } } }); if (newResult >= 0) { result = newResult; return false; } return true; } private static int GetPreviousIndexForPreviousGroup(int groupIndex) { int pagesCountWithoutSpecialRails = SubRailService.GetPagesCountWithoutSpecialRails(); int num = (groupIndex - 1 + pagesCountWithoutSpecialRails) % pagesCountWithoutSpecialRails; return (RecipeBookService.IsBookmarkGroupParent(num) ? StaticStorage.BookmarkGroups[num] : new List<BookmarkStorage>()).OrderBy((BookmarkStorage b) => b.recipeIndex).FirstOrDefault()?.recipeIndex ?? num; } private static BookmarkStorage GetNextBookmarkFromGroup(List<BookmarkStorage> currentBookmarkGroup, int currentBookIndex, bool next, bool isParent) { if (!isParent) { currentBookmarkGroup = currentBookmarkGroup.Where((BookmarkStorage b) => (!next) ? (b.recipeIndex > currentBookIndex) : (b.recipeIndex < currentBookIndex)).ToList(); } if (next) { return currentBookmarkGroup.OrderByDescending((BookmarkStorage b) => b.recipeIndex).FirstOrDefault(); } return currentBookmarkGroup.OrderBy((BookmarkStorage b) => b.recipeIndex).FirstOrDefault(); } private static void UpdatePageIndexesOnRearrange(Book instance, List<int> newIndexes) { UpdatePageIndexesOnRearrange(instance.curlPageController.frontLeftPage, newIndexes); UpdatePageIndexesOnRearrange(instance.curlPageController.frontRightPage, newIndexes); UpdatePageIndexesOnRearrange(instance.curlPageController.backLeftPage, newIndexes); UpdatePageIndexesOnRearrange(instance.curlPageController.backRightPage, newIndexes); } private static void UpdatePageIndexesOnRearrange(Page page, List<int> newIndexes) { page.pageIndex = newIndexes.IndexOf(page.pageIndex); } } public class OverrideSubRailLayersPatch { [HarmonyPatch(typeof(BookmarkRail), "SpawnLayers")] public class BookmarkRail_SpawnLayers { private static bool Prefix(BookmarkRail __instance) { return Ex.RunSafe(() => OverrideSubRailLayers(__instance)); } } private static bool OverrideSubRailLayers(BookmarkRail instance) { if (SubRailService.IsInvisiRail(instance)) { Transform[] value = (Transform[])(object)new Transform[1] { StaticStorage.InvisiRailLayer }; typeof(BookmarkRail).GetField("layers", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, value); return false; } if (!SubRailService.IsSubRail(instance)) { return true; } Transform[] value2 = StaticStorage.SubRailLayers.ToArray(); typeof(BookmarkRail).GetField("layers", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, value2); return false; } } public class ReturnCustomLayersToSubRailPatch { [HarmonyPatch(typeof(BookmarkController), "GetLayer")] public class BookmarkController_GetLayer { private static bool Prefix(ref BookmarkLayer __result, BookmarkController __instance, int index) { return ReturnCustomLayersToSubRail(ref __result, __instance, index); } } private static bool ReturnCustomLayersToSubRail(ref BookmarkLayer __result, BookmarkController instance, int index) { return true; } } public class SetupBookmarkMaskingPatch { [HarmonyPatch(typeof(Bookmark