using System.Collections.Generic; using System.Linq; using Revitalize.Framework.Utilities; using StardewValley; namespace Revitalize.Framework.Crafting { public class Recipe { public Dictionary ingredients; public Dictionary outputs; private Item displayItem; public Item DisplayItem { get => this.displayItem ?? this.outputs.ElementAt(0).Key; set => this.displayItem = value; } public string outputDescription; public string outputName; public StatCost statCost; public Recipe() { } /// Constructor for single item output. /// All the ingredients required to make the output. /// The item given as output with how many public Recipe(Dictionary inputs, KeyValuePair output, StatCost StatCost=null) { this.ingredients = inputs; this.DisplayItem = output.Key; this.outputDescription = output.Key.getDescription(); this.outputName = output.Key.DisplayName; this.outputs = new Dictionary { [output.Key] = output.Value }; this.statCost = StatCost ?? new StatCost(); } public Recipe(Dictionary inputs, Dictionary outputs, string OutputName, string OutputDescription, Item DisplayItem = null,StatCost StatCost=null) { this.ingredients = inputs; this.outputs = outputs; this.outputName = OutputName; this.outputDescription = OutputDescription; this.DisplayItem = DisplayItem; this.statCost = StatCost ?? new StatCost(); } /// Checks if a player contains all recipe ingredients. public bool PlayerContainsAllIngredients() { return this.InventoryContainsAllIngredient(Game1.player.Items.ToList()); } /// Checks if a player contains a recipe ingredient. public bool PlayerContainsIngredient(KeyValuePair pair) { return this.InventoryContainsIngredient(Game1.player.Items.ToList(), pair); } /// Checks if an inventory contains all items. public bool InventoryContainsAllIngredient(List items) { foreach (KeyValuePair pair in this.ingredients) if (!this.InventoryContainsIngredient(items, pair)) return false; return true; } /// Checks if an inventory contains an ingredient. public bool InventoryContainsIngredient(List items, KeyValuePair pair) { foreach (Item i in items) { if (i != null && this.ItemEqualsOther(i, pair.Key) && pair.Value == i.Stack) return true; } return false; } /// Checks roughly if two items equal each other. public bool ItemEqualsOther(Item self, Item other) { return self.Name == other.Name && self.getCategoryName() == other.getCategoryName() && self.GetType() == other.GetType(); } public void consume(ref List from) { if (this.InventoryContainsAllIngredient(from)==false) return; InventoryManager manager = new InventoryManager(from); List removalList = new List(); foreach (KeyValuePair pair in this.ingredients) { foreach (Item item in manager.items) { if (item == null) continue; if (this.ItemEqualsOther(item, pair.Key)) { if (item.Stack == pair.Value) removalList.Add(item); //remove the item else item.Stack -= pair.Value; //or reduce the stack size. } } } foreach (var v in removalList) manager.items.Remove(v); removalList.Clear(); from = manager.items; } public void produce(ref List to, bool dropToGround = false, bool isPlayerInventory = false) { var manager = isPlayerInventory ? new InventoryManager(new List()) : new InventoryManager(to); foreach (KeyValuePair pair in this.outputs) { Item item = pair.Key.getOne(); item.addToStack(pair.Value - 1); bool added = manager.addItem(item); if (!added && dropToGround) Game1.createItemDebris(item, Game1.player.getStandingPosition(), Game1.player.getDirection()); } to = manager.items; } public void craft(ref List from, ref List to, bool dropToGround = false, bool isPlayerInventory = false) { InventoryManager manager = new InventoryManager(to); if (manager.ItemCount + this.outputs.Count >= manager.capacity) { if (isPlayerInventory) Game1.showRedMessage("Inventory Full"); else return; } this.consume(ref from); this.produce(ref to, dropToGround, isPlayerInventory); } public void craft() { List playerItems = Game1.player.Items.ToList(); List outPutItems = new List(); this.craft(ref playerItems, ref outPutItems, true, true); Game1.player.Items = playerItems; //Set the items to be post consumption. foreach (Item I in outPutItems) Game1.player.addItemToInventory(I); //Add all items produced. this.statCost.payCost(); } public bool PlayerCanCraft() { return this.PlayerContainsAllIngredients() && this.statCost.canSafelyAffordCost(); } public bool CanCraft(List items) { return this.InventoryContainsAllIngredient(items); } } }