private Dictionary <string, int> categoryCount = new Dictionary <string, int>(); // used to hide dropdown entries
        private void LoadEntries()
        {
            allStacklistItems.Clear();

            foreach (Item item in capi.World.Items)
            {
                if (item.Code != null)
                {
                    if (item.Code.ToShortString().StartsWith("clothes-"))
                    {
                        // capi.Logger.Debug($"=== {item.Code.ToString()} - {item.Code.ToShortString()} ===");
                        // capi.Logger.Debug(item.Variant.ToString());

                        float  warmth          = item.Attributes?["warmth"].AsFloat(0) ?? 0;
                        string clothescategory = item.Attributes?["clothescategory"].AsString() ?? "";
                        // capi.Logger.Debug($"  {clothescategory} - {warmth}");

                        if (!tailorMod.IsItemAllowed(clothescategory, item.Code.ToShortString().ToLowerInvariant()))
                        {
                            continue;
                        }

                        categoryCount[clothescategory] = categoryCount.ContainsKey(clothescategory) ? categoryCount[clothescategory] + 1 : 1;

                        var itemStack = new ItemStack(item);
                        itemStack.Attributes.SetFloat("condition", 1); // 100% condition
                        GuiHandbookItemStackPage stacklistPage = new GuiHandbookItemStackPage(capi, itemStack);
                        // stacklistPage.TextCache = stacklistPage.Stack.GetName() + " " + stacklistPage.Stack.GetDescription(capi.World, stacklistPage.dummySlot, false) + $" ({clothescategory})";
                        allStacklistItems.Add(stacklistPage);
                    }
                }
            }
        }
        private bool OnHelpHotkey(KeyCombination key)
        {
            if (dialog.IsOpened())
            {
                dialog.TryClose();
            }
            else
            {
                dialog.TryOpen();
                // dunno why
                dialog.ignoreNextKeyPress = true;

                if (capi.World.Player.InventoryManager.CurrentHoveredSlot?.Itemstack != null)
                {
                    ItemStack stack    = capi.World.Player.InventoryManager.CurrentHoveredSlot.Itemstack;
                    string    pageCode = GuiHandbookItemStackPage.PageCodeForStack(stack);

                    if (!dialog.OpenDetailPageFor(pageCode))
                    {
                        dialog.OpenDetailPageFor(GuiHandbookItemStackPage.PageCodeForStack(new ItemStack(stack.Collectible)));
                    }
                }

                if (capi.World.Player.Entity.Controls.Sneak && capi.World.Player.CurrentBlockSelection != null)
                {
                    BlockPos  pos   = capi.World.Player.CurrentBlockSelection.Position;
                    ItemStack stack = capi.World.BlockAccessor.GetBlock(pos).OnPickBlock(capi.World, pos);

                    string pageCode = GuiHandbookItemStackPage.PageCodeForStack(stack);

                    if (!dialog.OpenDetailPageFor(pageCode))
                    {
                        dialog.OpenDetailPageFor(GuiHandbookItemStackPage.PageCodeForStack(new ItemStack(stack.Collectible)));
                    }
                }
            }

            return(true);
        }
        public void InitStackCacheAndStacks()
        {
            List <ItemStack>  allstacks        = new List <ItemStack>();
            List <JsonObject> allpotionessence = new List <JsonObject>();
            List <string>     essenceItemName  = new List <string>();

            //HashSet<AssetLocation> groupedBlocks = new HashSet<AssetLocation>();
            //HashSet<AssetLocation> groupedItems = new HashSet<AssetLocation>();
            //essencestionary<string, GuiHandbookGroupedItemstackPage> groupedPages = new essencestionary<string, GuiHandbookGroupedItemstackPage>();


            foreach (CollectibleObject obj in capi.World.Collectibles)
            {
                List <ItemStack> stacks = obj.GetHandBookStacks(capi);
                if (stacks == null)
                {
                    continue;
                }


                //string[] groups = obj.Attributes?["handbook"]?["groupBy"]?.AsStringArray(null);
                //string[] groupednames = obj.Attributes?["handbook"]?["groupedName"]?.AsStringArray(null);

                foreach (ItemStack stack in stacks)
                {
                    bool?potionItem = stack?.ItemAttributes?.KeyExists("potionessences");
                    if (potionItem != null && potionItem != false)
                    {
                        allstacks.Add(stack);
                        bool?specStack = stack?.ItemAttributes?["potionessences"].KeyExists(stack?.Collectible.Code.ToShortString());
                        if (specStack != null && specStack != false)
                        {
                            allpotionessence.Add(stack?.ItemAttributes?["potionessences"][stack?.Collectible.Code.ToShortString()]);
                        }
                        else
                        {
                            allpotionessence.Add(stack?.ItemAttributes?["potionessences"]);
                        }
                        essenceItemName.Add(stack.GetName());

                        /*if (groups != null && groupednames != null) - don't know how to do this right. The detail page also kind of needs to be a slideshow or multi-page thing? meh. :/
                         * {
                         *  bool alreadyAdded = stack.Class == EnumItemClass.Block ? groupedBlocks.Contains(stack.Collectible.Code) : groupedItems.Contains(stack.Collectible.Code);
                         *
                         *  if (!alreadyAdded)
                         *  {
                         *      GroupedHandbookStacklistElement elem;
                         *      if (groupedPages.TryGetValue(stack.Class + "-" + groups[0], out elem))
                         *      {
                         *          elem.Stacks.Add(stack);
                         *          pageNumberByPageCode[HandbookStacklistElement.PageCodeForCollectible(stack.Collectible)] = elem.PageNumber;
                         *      } else
                         *      {
                         *
                         *          elem = new GroupedHandbookStacklistElement()
                         *          {
                         *              TextCache = groupednames == null || groupednames.Length == 0 ? stack.GetName() : Lang.Get(groupednames[0]),
                         *              Name = groupednames == null || groupednames.Length == 0 ? stack.GetName() : Lang.Get(groupednames[0]),
                         *              Visible = true
                         *          };
                         *
                         *          elem.Stacks.Add(stack);
                         *
                         *          listElements.Add(elem);
                         *          pageNumberByPageCode[HandbookStacklistElement.PageCodeForCollectible(stack.Collectible)] = elem.PageNumber = listElements.Count - 1;
                         *          listedListElements.Add(elem);
                         *
                         *          groupedPages[stack.Class +"-"+ groups[0]] = elem;
                         *      }
                         *
                         *      if (stack.Class == EnumItemClass.Block)
                         *      {
                         *          groupedBlocks.Add(stack.Collectible.Code);
                         *      } else
                         *      {
                         *          groupedItems.Add(stack.Collectible.Code);
                         *      }
                         *  }
                         * }
                         * else*/
                        {
                            GuiHandbookItemStackPage elem = new GuiHandbookItemStackPage(capi, stack)
                            {
                                Visible = true
                            };

                            allEssencePages.Add(elem);
                            pageNumberByPageCode[elem.PageCode] = elem.PageNumber = allEssencePages.Count - 1;
                        }
                    }
                }
            }

            this.potionEssences  = allpotionessence.ToArray();
            this.allstacks       = allstacks.ToArray();
            this.essenceItemName = essenceItemName.ToArray();
        }