public bool CraftItem(ResourceInventory ResourceInv, InventoryController SourceInv, InventoryController TargetInv, Recipe CraftRecipe, bool ByPassCraftCheck = false)
    {
        if (!ByPassCraftCheck) //optimization to skip checking if we can craft this recipe
        {
            if (!CanCraft(ResourceInv, SourceInv, TargetInv, CraftRecipe))
            {
                return(false);
            }
        }
        foreach (var itemIn in CraftRecipe.ItemInput) //TODO Optimize data structure to allow use of a single foreach for inputs
        {
            SourceInv.RemoveFromItemBucket(itemIn.item, itemIn.amount);
        }
        foreach (var resourceIn in CraftRecipe.ResourceInput)
        {
            ResourceInv.RemoveResource(resourceIn.resource, resourceIn.amount);
        }

        TargetInv.AddToItemBucket(CraftRecipe.Output.item, CraftRecipe.Output.amount);

        if (!CraftRecipe.CreatesByProducts)
        {
            return(true);
        }

        foreach (var itemOut in CraftRecipe.ItemByProducts)//TODO Optimize data structure to allow use of a single foreach for outputs
        {
            TargetInv.AddToItemBucket(itemOut.item, itemOut.amount);
        }
        foreach (var resOut in CraftRecipe.ResourceByProducts)
        {
            ResourceInv.AddResource(resOut.resource, resOut.amount);
        }
        return(true);
    }
 // Update is called once per frame
 void Update()
 {
     if (Time.time >= NextUpdate)
     {
         LinkedInventory.AddResource(NaniteResource, NanitesPerTick);
         NextUpdate = Time.time + NextTimeShiftValue;
     }
 }
    public bool CraftConsumable(ResourceInventory ResourceInv, InventoryController SourceInv, ResourceInventory TargetInv, ConsumableRecipe CraftRecipe, bool ByPassCraftCheck = false)
    {
        if (!ByPassCraftCheck) //optimization to skip checking if we can craft this recipe
        {
            if (!CanCraftConsumable(ResourceInv, SourceInv, TargetInv, CraftRecipe))
            {
                return(false);
            }
        }

        foreach (var itemIn in CraftRecipe.ItemInput) //TODO Optimize data structure to allow use of a single foreach for inputs
        {
            SourceInv.RemoveFromItemBucket(itemIn.item, itemIn.amount);
        }
        foreach (var resourceIn in CraftRecipe.ResourceInput)
        {
            ResourceInv.RemoveResource(resourceIn.resource, resourceIn.amount);
        }

        if (CraftRecipe.isUpgrade)
        {
            Debug.Log("Before Amount: " + TargetInv.GetResource(CraftRecipe.Output));
            //if(CraftRecipe.Output.name == "Health")
            //{
            //    UIRootModule.UIRoot.GetScreen<GameHUD>().healthUpgrade.Upgrade(CraftRecipe.OutputAmount);
            //}
            if (CraftRecipe.Output.name == "Fuel")
            {
                UIRootModule.UIRoot.GetScreen <GameHUD>().fuelUpgrade.Upgrade(CraftRecipe.OutputAmount);
            }
            //Add Resource already contains a clamp so resource cannot go over max
            TargetInv.AddResource(CraftRecipe.Output, CraftRecipe.Output.GetMaximum());
            Debug.Log("After Amount: " + TargetInv.GetResource(CraftRecipe.Output));
        }
        else
        {
            //Add Resource already contains a clamp so resource cannot go over max
            TargetInv.AddResource(CraftRecipe.Output, CraftRecipe.OutputAmount);
        }
        return(true);
    }
    /* public void TryOffload(ResourceInventory Target)
     * {
     *   string temp;
     *   TryOffload(Target,out temp);
     * }*/


    public void TryOffload(ResourceInventory Target)
    {
        if (Target.CanAdd(NaniteResource, NaniteOffloadAmount))
        {
            if (LinkedInventory.GetResource(NaniteResource) >= NaniteOffloadAmount)
            {
                //player-facing poptext
                if (AntiSpamTimer <= Time.time)
                {
                    var poptext = Instantiate(popText); //No this doesn't cause memleaks, I know it looks bad but it doesn't
                    poptext.popText.SetText($"{NaniteResource.DisplayName} added");
                    AntiSpamTimer = Time.time + AntiSpam;
                }


                Target.AddResource(NaniteResource, NaniteOffloadAmount);
                LinkedInventory.RemoveResource(NaniteResource, NaniteOffloadAmount);
                Debug.Log(Target.GetResource(NaniteResource));
            }
            else
            {
                //player-facing poptext
                if (AntiSpamTimer <= Time.time)
                {
                    var poptext = Instantiate(popText);
                    poptext.popText.SetText($"No {NaniteResource.DisplayName} available");
                    AntiSpamTimer = Time.time + AntiSpam;
                }

                //error = OffloadEmptyMsg;
                return;
            }
        }
        else
        {
            //player-facing poptext
            var poptext = Instantiate(popText);
            poptext.popText.SetText($"{NaniteResource.DisplayName} full");

            //error = OffloadFullMsg;
            Debug.Log("Player Inv Full");
            return;
        }
        //error = null;
    }