/// <summary>
 /// Generates a standard SlotValidator/CraftValidator/CraftPerformer trio using a simple set of input IDs and an output Item
 /// </summary>
 /// <param name="recipes">A list of recipes consisting of the ingredient IDs, the item output, and the amount of possible random extra output.</param>
 public static Tuple <SlotValidator, CraftValidator, CraftPerformer> CreateSimpleCraftPerformer(params Tuple <int[], Item, int>[] recipes)
 {
     return(Tuple.Create <SlotValidator, CraftValidator, CraftPerformer>((Item newItem, Item[] items, int slot) =>
     {
         return recipes.Any(x => x.Item1.Length > slot && newItem.id == x.Item1[slot]);
     }, (Item[] items) =>
     {
         return recipes.Any(x =>
         {
             for (int i = 0; i < x.Item1.Length; i++)
             {
                 if (x.Item1[i] > 0 && (items.Length <= i || items[i] == null || items[i].q < 1 || items[i].id != x.Item1[i]))
                 {
                     return false;
                 }
             }
             return items[items.Length - 1] == null || items[items.Length - 1].q == 0 || (GadgetCoreAPI.CanItemsStack(items[items.Length - 1], x.Item2) && items[items.Length - 1].q + x.Item2.q + x.Item3 <= 9999);
         });
     }, (Item[] items) =>
     {
         foreach (Tuple <int[], Item, int> recipe in recipes)
         {
             bool recipeValid = true;
             for (int i = 0; i < recipe.Item1.Length; i++)
             {
                 if (recipe.Item1[i] > 0 && (items.Length <= i || items[i] == null || items[i].q < 1 || items[i].id != recipe.Item1[i]))
                 {
                     recipeValid = false;
                     break;
                 }
             }
             if (recipeValid)
             {
                 for (int i = 0; i < recipe.Item1.Length; i++)
                 {
                     if (recipe.Item1[i] > 0)
                     {
                         items[i].q--;
                     }
                 }
                 if (items[items.Length - 1].id == recipe.Item2.id && items[items.Length - 1].q > 0)
                 {
                     items[items.Length - 1].q += recipe.Item2.q;
                 }
                 else
                 {
                     items[items.Length - 1] = GadgetCoreAPI.CopyItem(recipe.Item2);
                 }
                 if (recipe.Item3 > 0)
                 {
                     items[items.Length - 1].q += UnityEngine.Random.Range(0, recipe.Item3 + 1);
                 }
                 if (recipe.Item3 < 0)
                 {
                     items[items.Length - 1].q -= UnityEngine.Random.Range(0, -recipe.Item3 + 1);
                 }
                 break;
             }
         }
     }));
 }