public override void Unload()
        {
            if (!Main.dedServ)
            {
                concurrentTaskHandlerToken?.Cancel();
                concurrentTaskHandler?.Wait();
            }
            instance                   = null;
            translations               = null;
            itemChecklistInstance      = null;
            LootCache.instance         = null;
            ToggleRecipeBrowserHotKey  = null;
            QueryHoveredItemHotKey     = null;
            RecipeBrowserUI.instance   = null;
            RecipeCatalogueUI.instance = null;
            ItemCatalogueUI.instance   = null;
            BestiaryUI.instance        = null;
            CraftUI.instance           = null;
            SharedUI.instance          = null;
            RecipePath.Refresh(true);
            RecipeBrowserPlayer.seenTiles = null;

            UIElements.UIRecipeSlot.favoritedBackgroundTexture           = null;
            UIElements.UIRecipeSlot.selectedBackgroundTexture            = null;
            UIElements.UIRecipeSlot.ableToCraftBackgroundTexture         = null;
            UIElements.UIRecipeSlot.ableToCraftExtendedBackgroundTexture = null;
            UIElements.UIMockRecipeSlot.ableToCraftBackgroundTexture     = null;
            UIElements.UICheckbox.checkboxTexture  = null;
            UIElements.UICheckbox.checkmarkTexture = null;
            UIHorizontalGrid.moreLeftTexture       = null;
            UIHorizontalGrid.moreRightTexture      = null;
            Utilities.tileTextures = null;
            ArmorSetFeatureHelper.Unload();
            UIItemSlot.hoveredItem = null;
        }
        internal void Update()
        {
            // TODO: investigate why this Update is slower than RecipeCatalogueUI

            if (!RecipeBrowserUI.instance.ShowRecipeBrowser || RecipeBrowserUI.instance.CurrentPanel != RecipeBrowserUI.ItemCatalogue)
            {
                return;
            }

            if (slowUpdateNeeded > 0)
            {
                slowUpdateNeeded--;
                if (slowUpdateNeeded == 0)
                {
                    updateNeeded = true;
                }
            }

            if (!updateNeeded)
            {
                return;
            }
            updateNeeded     = false;
            slowUpdateNeeded = 0;

            if (itemSlots.Count == 0)
            {
                // should only happen once
                craftResults = new bool[ItemLoader.ItemCount];
                isLoot       = new bool[ItemLoader.ItemCount];
                itemSlots.Clear();
                for (int type = 1; type < ItemLoader.ItemCount; type++)
                {
                    Item item = new Item();
                    item.SetDefaults(type, false);                     // 300 ms vs 30 ms
                    if (item.type == 0)
                    {
                        continue;
                    }
                    var slot = new UIItemCatalogueItemSlot(item);
                    itemSlots.Add(slot);
                }

                for (int i = 0; i < Recipe.numRecipes; i++)
                {
                    Recipe recipe = Main.recipe[i];
                    craftResults[recipe.createItem.type] = true;
                }

                foreach (var kvp in LootCache.instance.lootInfos)
                {
                    //if (kvp.Key.id == 0 && kvp.Key.mod == "Terraria")
                    //	Console.WriteLine();
                    int id = kvp.Key.GetID();
                    if (id > 0)
                    {
                        isLoot[id] = true;
                    }
                }
            }

            itemGrid.Clear();
            List <UIItemCatalogueItemSlot> slotsToUse = itemSlots;

            if (SharedUI.instance.SelectedCategory.name == ArmorSetFeatureHelper.ArmorSetsHoverTest)
            {
                if (ArmorSetFeatureHelper.armorSetSlots == null)
                {
                    ArmorSetFeatureHelper.CalculateArmorSets();
                }
                slotsToUse = ArmorSetFeatureHelper.armorSetSlots.Cast <UIItemCatalogueItemSlot>().ToList();
                ArmorSetFeatureHelper.AppendSpecialUI(itemGrid);
            }

            foreach (var slot in slotsToUse)
            {
                if (PassItemFilters(slot))
                {
                    itemGrid._items.Add(slot);
                    itemGrid._innerList.Append(slot);
                }
            }
            itemGrid.UpdateOrder();
            itemGrid._innerList.Recalculate();
        }