// Assign our componenet based on the slot type.
    private void LateUpdate()
    {
        player = Player.localPlayer;

        if (player != null)
        {
            switch (slotType)
            {
            case SlotType.Equipment:
                // refresh all
                int lastECount = 0;
                if (lastECount != player.equipment.Count)
                {
                    for (int i = 0; i < player.equipment.Count; ++i)
                    {
                        lastECount = player.equipment.Count;
                        if (player.equipment[i].amount > 0)
                        {
                            UIEquipment equipmentContents = gameObject.GetComponent <UIEquipment>();
                            UIUtils.BalancePrefabs(equipmentContents.slotPrefab.gameObject, player.equipment.Count, equipmentContents.content);
                            if (equipmentContents.panel.activeSelf)
                            {
                                UIEquipmentSlot slot = equipmentContents.content.transform.GetChild(i).GetComponent <UIEquipmentSlot>();
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                tooltip    = slot.tooltip;
                                slot.dragAndDropable.name = i.ToString();     // drag and drop slot
                                itemSlot = player.equipment[i];
                                SetRarityColor(itemSlot.item.data);
                            }
                        }
                        else
                        {
                            UIEquipment equipmentContents = gameObject.GetComponent <UIEquipment>();
                            if (equipmentContents.panel.activeSelf)
                            {
                                UIEquipmentSlot slot = equipmentContents.content.transform.GetChild(i).GetComponent <UIEquipmentSlot>();
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                raritySlot.rarityOutline.color = Color.clear;
                            }
                        }
                    }
                }
                break;

            case SlotType.Inventory:
                // refresh all
                int lastICount = 0;
                if (lastICount != player.inventory.Count)
                {
                    for (int i = 0; i < player.inventory.Count; ++i)
                    {
                        lastICount = player.inventory.Count;
                        if (player.inventory[i].amount > 0)
                        {
                            UIInventory inventoryContents = GetComponent <UIInventory>();
                            UIUtils.BalancePrefabs(inventoryContents.slotPrefab.gameObject, player.inventory.Count, inventoryContents.content);
                            if (inventoryContents.panel.activeSelf)
                            {
                                UIInventorySlot slot = inventoryContents.content.transform.GetChild(i).GetComponent <UIInventorySlot>();
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                tooltip    = slot.tooltip;
                                slot.dragAndDropable.name = i.ToString();     // drag and drop slot
                                itemSlot = player.inventory[i];
                                SetRarityColor(itemSlot.item.data);
                            }
                        }
                        else
                        {
                            UIInventory inventoryContents = gameObject.GetComponent <UIInventory>();
                            if (inventoryContents.panel.activeSelf)
                            {
                                UIInventorySlot slot = inventoryContents.content.transform.GetChild(i).GetComponent <UIInventorySlot>();
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                raritySlot.rarityOutline.color = Color.clear;
                            }
                        }
                    }
                }
                break;

            case SlotType.Loot:
                if (player.target != null && player.target.health <= 0)
                {
                    UILoot          lootContent = GetComponent <UILoot>();
                    List <ItemSlot> items       = player.target.inventory.Where(slot => slot.amount > 0).ToList();
                    UIUtils.BalancePrefabs(lootContent.itemSlotPrefab.gameObject, items.Count, lootContent.content);

                    // refresh all valid items
                    for (int i = 0; i < items.Count; ++i)
                    {
                        UILootSlot slot = lootContent.content.GetChild(i).GetComponent <UILootSlot>();
                        slot.dragAndDropable.name = i.ToString();     // drag and drop index
                        int itemIndex = player.target.inventory.FindIndex(
                            // note: .Equals because name AND dynamic variables matter (petLevel etc.)
                            itemSlot => itemSlot.amount > 0 && itemSlot.item.Equals(items[i].item)
                            );

                        // refresh
                        raritySlot = slot.GetComponent <UCE_RaritySlot>();
                        tooltip    = slot.tooltip;
                        slot.dragAndDropable.name = i.ToString();     // drag and drop slot
                        itemSlot = items[i];
                        SetRarityColor(itemSlot.item.data);
                    }
                }
                break;

            case SlotType.PlayerTrade:
                if (player.state == "TRADING")
                {
                    Player other        = (Player)player.target;
                    int    lastPTYCount = 0;
                    if (lastPTYCount != player.tradeOfferItems.Count)
                    {
                        for (int i = 0; i < player.tradeOfferItems.Count; ++i)
                        {
                            lastPTYCount = player.tradeOfferItems.Count;
                            UIPlayerTrading tradeContents = GetComponent <UIPlayerTrading>();
                            UIUtils.BalancePrefabs(tradeContents.slotPrefab.gameObject, player.tradeOfferItems.Count, tradeContents.myContent);
                            if (tradeContents.panel.activeSelf)
                            {
                                UIPlayerTradingSlot slot = tradeContents.myContent.transform.GetChild(i).GetComponent <UIPlayerTradingSlot>();
                                if (slot.amountText.text != "0")
                                {
                                    raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                    tooltip    = slot.tooltip;
                                    slot.dragAndDropable.name = i.ToString();     // drag and drop slot
                                    int inventoryIndex = player.tradeOfferItems[i];
                                    itemSlot = player.inventory[inventoryIndex];
                                    SetRarityColor(itemSlot.item.data);
                                }
                                else
                                {
                                    raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                    raritySlot.rarityOutline.color = Color.clear;
                                }
                            }
                        }
                    }

                    int lastPTOCount = 0;
                    if (lastPTOCount != other.tradeOfferItems.Count)
                    {
                        for (int i = 0; i < other.tradeOfferItems.Count; ++i)
                        {
                            lastPTOCount = other.tradeOfferItems.Count;
                            UIPlayerTrading tradeContents = GetComponent <UIPlayerTrading>();
                            UIUtils.BalancePrefabs(tradeContents.slotPrefab.gameObject, other.tradeOfferItems.Count, tradeContents.otherContent);
                            if (tradeContents.panel.activeSelf)
                            {
                                UIPlayerTradingSlot slot = tradeContents.otherContent.transform.GetChild(i).GetComponent <UIPlayerTradingSlot>();
                                if (slot.amountText.text != "0")
                                {
                                    raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                    tooltip    = slot.tooltip;
                                    slot.dragAndDropable.name = i.ToString();     // drag and drop slot
                                    int inventoryIndex = other.tradeOfferItems[i];
                                    itemSlot = other.inventory[inventoryIndex];
                                    SetRarityColor(itemSlot.item.data);
                                }
                                else
                                {
                                    raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                    raritySlot.rarityOutline.color = Color.clear;
                                }
                            }
                        }
                    }
                }
                break;

            case SlotType.NpcTrade:
                if (player.target is Npc)
                {
                    Npc npc = (Npc)player.target;
#if _iMMONPCSHOP
                    UCE_UI_NpcShop shopContents = GetComponent <UCE_UI_NpcShop>();
                    if (shopContents.panel.activeSelf)
                    {
                        ScriptableItem[] items = npc.saleItems.Where(x => x.itemCategory == shopContents.currentCategory || shopContents.currentCategory == "").ToArray();
                        UIUtils.BalancePrefabs(shopContents.itemSlotPrefab.gameObject, items.Length, shopContents.itemContent);

                        int    lastIMCount = 0;
                        string currentPage = "";
                        if (lastIMCount != items.Length || currentPage != shopContents.currentCategory)
                        {
                            for (int i = 0; i < items.Length; ++i)
                            {
                                lastIMCount = items.Length;
                                currentPage = shopContents.currentCategory;

                                UCE_UI_NpcShopSlot slot = shopContents.itemContent.GetChild(i).GetComponent <UCE_UI_NpcShopSlot>();
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                tooltip    = slot.tooltip;
                                scriptItem = items[i];
                                SetRarityColor(scriptItem);
                            }
                        }
                    }
#else
                    int lastNTCount = 0;
                    if (lastNTCount != npc.saleItems.Length)
                    {
                        for (int i = 0; i < npc.saleItems.Length; ++i)
                        {
                            lastNTCount = npc.saleItems.Length;
                            UINpcTrading npcContents = GetComponent <UINpcTrading>();
                            UIUtils.BalancePrefabs(npcContents.slotPrefab.gameObject, npc.saleItems.Length, npcContents.content);
                            if (npcContents.panel.activeSelf)
                            {
                                UINpcTradingSlot slot = npcContents.content.transform.GetChild(i).GetComponent <UINpcTradingSlot>();
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                tooltip    = slot.tooltip;
                                scriptItem = npc.saleItems[i];
                                SetRarityColor(scriptItem);
                            }
                        }
                    }
#endif
                }
                break;

            case SlotType.ItemMall:
                UIItemMall mallContents = GetComponent <UIItemMall>();
                if (mallContents.panel.activeSelf)
                {
                    ScriptableItem[] items = player.itemMallCategories[mallContents.currentCategory].items;
                    UIUtils.BalancePrefabs(mallContents.itemSlotPrefab.gameObject, items.Length, mallContents.itemContent);

                    int lastIMCount = 0;
                    int currentPage = 0;
                    if (lastIMCount != items.Length || currentPage != mallContents.currentCategory)
                    {
                        for (int i = 0; i < items.Length; ++i)
                        {
                            lastIMCount = items.Length;
                            currentPage = mallContents.currentCategory;
                            UIItemMallSlot slot = mallContents.itemContent.GetChild(i).GetComponent <UIItemMallSlot>();
                            raritySlot = slot.GetComponent <UCE_RaritySlot>();
                            tooltip    = slot.tooltip;
                            scriptItem = items[i];
                            SetRarityColor(scriptItem);
                        }
                    }
                }
                break;

            case SlotType.Crafting:
                UICrafting craftContents = GetComponent <UICrafting>();
                UIUtils.BalancePrefabs(craftContents.ingredientSlotPrefab.gameObject, player.craftingIndices.Count, craftContents.ingredientContent);
                if (craftContents.panel.activeSelf)
                {
                    int lastCCount = 0;
                    if (lastCCount != player.craftingIndices.Count)
                    {
                        for (int i = 0; i < player.craftingIndices.Count; ++i)
                        {
                            lastCCount = player.craftingIndices.Count;
                            UICraftingIngredientSlot slot = craftContents.ingredientContent.GetChild(i).GetComponent <UICraftingIngredientSlot>();
                            if (player.craftingIndices[i] != -1)
                            {
                                int itemIndex = player.craftingIndices[i];
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                tooltip    = slot.tooltip;
                                itemSlot   = player.inventory[itemIndex];
                                SetRarityColor(itemSlot.item.data);
                            }
                            else
                            {
                                raritySlot = slot.GetComponent <UCE_RaritySlot>();
                                raritySlot.rarityOutline.color = Color.clear;
                            }
                        }
                    }
                }
                break;
            }
        }
    }
Exemplo n.º 2
0
    void Update()
    {
        Player player = Player.localPlayer;

        if (player)
        {
            // hotkey (not while typing in chat, etc.)
            if (Input.GetKeyDown(hotKey) && !UIUtils.AnyInputActive())
            {
                panel.SetActive(!panel.activeSelf);
            }

            // only update the panel if it's active
            if (panel.activeSelf)
            {
                // instantiate/destroy enough slots
                UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, player.crafting.indices.Count, ingredientContent);

                // refresh all
                for (int i = 0; i < player.crafting.indices.Count; ++i)
                {
                    UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent <UICraftingIngredientSlot>();
                    slot.dragAndDropable.name = i.ToString(); // drag and drop index
                    int itemIndex = player.crafting.indices[i];

                    if (0 <= itemIndex && itemIndex < player.inventory.slots.Count &&
                        player.inventory.slots[itemIndex].amount > 0)
                    {
                        ItemSlot itemSlot = player.inventory.slots[itemIndex];

                        // refresh valid item

                        // only build tooltip while it's actually shown. this
                        // avoids MASSIVE amounts of StringBuilder allocations.
                        slot.tooltip.enabled = true;
                        if (slot.tooltip.IsVisible())
                        {
                            slot.tooltip.text = itemSlot.ToolTip();
                        }
                        slot.dragAndDropable.dragable = true;

                        // use durability colors?
                        if (itemSlot.item.maxDurability > 0)
                        {
                            if (itemSlot.item.durability == 0)
                            {
                                slot.image.color = brokenDurabilityColor;
                            }
                            else if (itemSlot.item.DurabilityPercent() < lowDurabilityThreshold)
                            {
                                slot.image.color = lowDurabilityColor;
                            }
                            else
                            {
                                slot.image.color = Color.white;
                            }
                        }
                        else
                        {
                            slot.image.color = Color.white;  // reset for no-durability items
                        }
                        slot.image.sprite = itemSlot.item.image;

                        slot.amountOverlay.SetActive(itemSlot.amount > 1);
                        slot.amountText.text = itemSlot.amount.ToString();
                    }
                    else
                    {
                        // reset the index because it's invalid
                        player.crafting.indices[i] = -1;

                        // refresh invalid item
                        slot.tooltip.enabled          = false;
                        slot.dragAndDropable.dragable = false;
                        slot.image.color  = Color.clear;
                        slot.image.sprite = null;
                        slot.amountOverlay.SetActive(false);
                    }
                }

                // find valid indices => item templates => matching recipe
                List <int> validIndices = player.crafting.indices.Where(
                    index => 0 <= index && index < player.inventory.slots.Count &&
                    player.inventory.slots[index].amount > 0
                    ).ToList();
                List <ItemSlot>  items  = validIndices.Select(index => player.inventory.slots[index]).ToList();
                ScriptableRecipe recipe = ScriptableRecipe.Find(items);
                if (recipe != null)
                {
                    // refresh valid recipe
                    Item item = new Item(recipe.result);
                    // only build tooltip while it's actually shown. this
                    // avoids MASSIVE amounts of StringBuilder allocations.
                    resultSlotToolTip.enabled = true;
                    if (resultSlotToolTip.IsVisible())
                    {
                        resultSlotToolTip.text = new ItemSlot(item).ToolTip(); // ItemSlot so that {AMOUNT} is replaced too
                    }
                    resultSlotImage.color  = Color.white;
                    resultSlotImage.sprite = recipe.result.image;

                    // show progress bar while crafting
                    // (show 100% if craft time = 0 because it's just better feedback)
                    progressSlider.gameObject.SetActive(player.state == "CRAFTING");
                    double startTime   = player.crafting.endTime - recipe.craftingTime;
                    double elapsedTime = NetworkTime.time - startTime;
                    progressSlider.value = recipe.craftingTime > 0 ? (float)elapsedTime / recipe.craftingTime : 1;
                }
                else
                {
                    // refresh invalid recipe
                    resultSlotToolTip.enabled = false;
                    resultSlotImage.color     = Color.clear;
                    resultSlotImage.sprite    = null;
                    progressSlider.gameObject.SetActive(false);
                }

                // craft result
                // (no recipe != null check because it will be null if those were
                //  the last two ingredients in our inventory)
                if (player.crafting.state == CraftingState.Success)
                {
                    resultText.color = successColor;
                    resultText.text  = "Success!";
                }
                else if (player.crafting.state == CraftingState.Failed)
                {
                    resultText.color = failedColor;
                    resultText.text  = "Failed :(";
                }
                else
                {
                    resultText.text = "";
                }

                // craft button with 'Try' prefix to let people know that it might fail
                // (disabled while in progress)
                craftButton.GetComponentInChildren <Text>().text = recipe != null &&
                                                                   recipe.probability < 1 ? "Try Craft" : "Craft";
                craftButton.interactable = recipe != null &&
                                           player.state != "CRAFTING" &&
                                           player.crafting.state != CraftingState.InProgress &&
                                           player.inventory.CanAdd(new Item(recipe.result), 1);
                craftButton.onClick.SetListener(() => {
                    player.crafting.state = CraftingState.InProgress; // wait for result

                    // pass original array so server can copy it to it's own
                    // craftingIndices. we pass original one and not only the valid
                    // indicies because then in host mode we would make the crafting
                    // indices array smaller by only copying the valid indices,
                    // hence losing crafting slots
                    player.crafting.CmdCraft(recipe.name, player.crafting.indices.ToArray());
                });
            }
        }
        else
        {
            panel.SetActive(false);
        }
    }
Exemplo n.º 3
0
    void Update()
    {
        GameObject player = Player.player;

        if (!player)
        {
            return;
        }

        PlayerCrafting crafting  = player.GetComponent <PlayerCrafting>();
        Inventory      inventory = player.GetComponent <Inventory>();

        // instantiate/destroy enough slots
        UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, crafting.indices.Count, ingredientContent);

        // refresh all
        for (int i = 0; i < crafting.indices.Count; ++i)
        {
            UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent <UICraftingIngredientSlot>();
            slot.dragAndDropable.name = i.ToString(); // drag and drop index
            int itemIndex = crafting.indices[i];

            if (0 <= itemIndex && itemIndex < inventory.slots.Count &&
                inventory.slots[itemIndex].amount > 0)
            {
                ItemSlot itemSlot = inventory.slots[itemIndex];

                // refresh valid item
                slot.tooltip.enabled          = true;
                slot.tooltip.text             = itemSlot.ToolTip();
                slot.dragAndDropable.dragable = true;
                slot.image.color  = Color.white;
                slot.image.sprite = itemSlot.item.image;
                slot.amountOverlay.SetActive(itemSlot.amount > 1);
                slot.amountText.text = itemSlot.amount.ToString();
            }
            else
            {
                // reset the index because it's invalid
                crafting.indices[i] = -1;

                // refresh invalid item
                slot.tooltip.enabled          = false;
                slot.dragAndDropable.dragable = false;
                slot.image.color  = Color.clear;
                slot.image.sprite = null;
                slot.amountOverlay.SetActive(false);
            }
        }

        // find valid indices => item templates => matching recipe
        List <int> validIndices = crafting.indices.Where(
            index => 0 <= index && index < inventory.slots.Count &&
            inventory.slots[index].amount > 0
            ).ToList();
        List <ItemSlot>  items  = validIndices.Select(index => inventory.slots[index]).ToList();
        ScriptableRecipe recipe = ScriptableRecipe.dict.Values.ToList().Find(r => r.CanCraftWith(items)); // good enough for now

        if (recipe != null)
        {
            // refresh valid recipe
            Item item = new Item(recipe.result);
            resultSlotToolTip.enabled = true;
            resultSlotToolTip.text    = new ItemSlot(item).ToolTip(); // ItemSlot so that {AMOUNT} is replaced too
            resultSlotImage.color     = Color.white;
            resultSlotImage.sprite    = recipe.result.image;
        }
        else
        {
            // refresh invalid recipe
            resultSlotToolTip.enabled = false;
            resultSlotImage.color     = Color.clear;
            resultSlotImage.sprite    = null;
        }

        // craft result
        // (no recipe != null check because it will be null if those were
        //  the last two ingredients in our inventory)
        if (crafting.craftingState == CraftingState.Success)
        {
            resultText.color = successColor;
            resultText.text  = "Success!";
        }
        else if (crafting.craftingState == CraftingState.Failed)
        {
            resultText.color = failedColor;
            resultText.text  = "Failed :(";
        }
        else
        {
            resultText.text = "";
        }

        // craft button with 'Try' prefix to let people know that it might fail
        // (disabled while in progress)
        craftButton.GetComponentInChildren <Text>().text = recipe != null &&
                                                           recipe.probability < 1 ? "Try Craft" : "Craft";
        craftButton.interactable = recipe != null &&
                                   crafting.craftingState != CraftingState.InProgress &&
                                   inventory.CanAdd(new Item(recipe.result), 1);
        craftButton.onClick.SetListener(() => {
            crafting.craftingState = CraftingState.InProgress; // wait for result
            crafting.Craft(validIndices.ToArray());
        });
    }
Exemplo n.º 4
0
    void Update()
    {
        Player player = Player.localPlayer;

        if (player)
        {
            UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, player.crafting.indices.Count, ingredientContent);
            for (int i = 0; i < player.crafting.indices.Count; ++i)
            {
                UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent <UICraftingIngredientSlot>();
                slot.dragAndDropable.name = i.ToString();
                int itemIndex = player.crafting.indices[i];
                if (0 <= itemIndex && itemIndex < player.inventory.slots.Count &&
                    player.inventory.slots[itemIndex].amount > 0)
                {
                    ItemSlot itemSlot = player.inventory.slots[itemIndex];
                    slot.tooltip.enabled = true;
                    if (slot.tooltip.IsVisible())
                    {
                        slot.tooltip.text = itemSlot.ToolTip();
                    }
                    slot.dragAndDropable.dragable = true;
                    slot.image.color  = Color.white;
                    slot.image.sprite = itemSlot.item.image;
                    slot.amountOverlay.SetActive(itemSlot.amount > 1);
                    slot.amountText.text = itemSlot.amount.ToString();
                }
                else
                {
                    player.crafting.indices[i]    = -1;
                    slot.tooltip.enabled          = false;
                    slot.dragAndDropable.dragable = false;
                    slot.image.color  = Color.clear;
                    slot.image.sprite = null;
                    slot.amountOverlay.SetActive(false);
                }
            }
            List <int> validIndices = player.crafting.indices.Where(
                index => 0 <= index && index < player.inventory.slots.Count &&
                player.inventory.slots[index].amount > 0
                ).ToList();
            List <ItemSlot> items  = validIndices.Select(index => player.inventory.slots[index]).ToList();
            CraftingRecipe  recipe = CraftingRecipe.Find(items);
            if (recipe != null)
            {
                Item item = new Item(recipe.result);
                resultSlotToolTip.enabled = true;
                if (resultSlotToolTip.IsVisible())
                {
                    resultSlotToolTip.text = new ItemSlot(item).ToolTip();
                }
                resultSlotImage.color  = Color.white;
                resultSlotImage.sprite = recipe.result.image;
            }
            else
            {
                resultSlotToolTip.enabled = false;
                resultSlotImage.color     = Color.clear;
                resultSlotImage.sprite    = null;
            }
            if (player.crafting.craftingState == CraftingState.Success)
            {
                resultText.color = successColor;
                resultText.text  = "Success!";
            }
            else if (player.crafting.craftingState == CraftingState.Failed)
            {
                resultText.color = failedColor;
                resultText.text  = "Failed :(";
            }
            else
            {
                resultText.text = "";
            }
            craftButton.GetComponentInChildren <Text>().text = recipe != null &&
                                                               recipe.probability < 1 ? "Try Craft" : "Craft";
            craftButton.interactable = recipe != null &&
                                       player.crafting.craftingState != CraftingState.InProgress &&
                                       player.inventory.CanAdd(new Item(recipe.result), 1);
            craftButton.onClick.SetListener(() => {
                player.crafting.craftingState = CraftingState.InProgress;
                player.crafting.CmdCraft(recipe.name, validIndices.ToArray());
            });
        }
    }
Exemplo n.º 5
0
    void Update()
    {
        Player player = Utils.ClientLocalPlayer();
        if (!player) return;

        // hotkey (not while typing in chat, etc.)
        if (Input.GetKeyDown(hotKey) && !UIUtils.AnyInputActive())
            panel.SetActive(!panel.activeSelf);

        // only update the panel if it's active
        if (panel.activeSelf)
        {
            // instantiate/destroy enough slots
            UIUtils.BalancePrefabs(ingredientSlotPrefab.gameObject, player.craftingIndices.Count, ingredientContent);

            // refresh all
            for (int i = 0; i < player.craftingIndices.Count; ++i)
            {
                UICraftingIngredientSlot slot = ingredientContent.GetChild(i).GetComponent<UICraftingIngredientSlot>();
                slot.dragAndDropable.name = i.ToString(); // drag and drop index
                int itemIndex = player.craftingIndices[i];

                if (0 <= itemIndex && itemIndex < player.inventory.Count &&
                    player.inventory[itemIndex].amount > 0)
                {
                    ItemSlot itemSlot = player.inventory[itemIndex];

                    // refresh valid item
                    slot.tooltip.enabled = true;
                    slot.tooltip.text = itemSlot.ToolTip();
                    slot.dragAndDropable.dragable = true;
                    slot.image.color = Color.white;
                    slot.image.sprite = itemSlot.item.image;
                }
                else
                {
                    // reset the index because it's invalid
                    player.craftingIndices[i] = -1;

                    // refresh invalid item
                    slot.tooltip.enabled = false;
                    slot.dragAndDropable.dragable = false;
                    slot.image.color = Color.clear;
                    slot.image.sprite = null;
                }
            }

            // find valid indices => item templates => matching recipe
            List<int> validIndices = player.craftingIndices.Where(
                index => 0 <= index && index < player.inventory.Count &&
                       player.inventory[index].amount > 0
            ).ToList();
            List<ScriptableItem> items = validIndices.Select(index => player.inventory[index].item.data).ToList();
            ScriptableRecipe recipe = ScriptableRecipe.dict.Values.ToList().Find(r => r.CanCraftWith(items)); // good enough for now
            if (recipe != null)
            {
                // refresh valid recipe
                resultSlotToolTip.enabled = true;
                resultSlotToolTip.text = new Item(recipe.result).ToolTip();
                resultSlotImage.color = Color.white;
                resultSlotImage.sprite = recipe.result.image;
            }
            else
            {
                // refresh invalid recipe
                resultSlotToolTip.enabled = false;
                resultSlotImage.color = Color.clear;
                resultSlotImage.sprite = null;
            }

            // craft button
            craftButton.interactable = recipe != null && player.InventoryCanAdd(new Item(recipe.result), 1);
            craftButton.onClick.SetListener(() => {
                player.CmdCraft(validIndices.ToArray());
            });
        }

        // addon system hooks
        Utils.InvokeMany(typeof(UICrafting), this, "Update_");
    }