/**
 * This class was created by <Darkhax>. It is distributed as part of Bookshelf. You can find
 * the original source here: https://github.com/Darkhax-Minecraft/Bookshelf
 *
 * Bookshelf is Open Source and distributed under the GNU Lesser General Public License version
 * 2.1.
 */
package net.darkhax.bookshelf.util;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import net.darkhax.bookshelf.Bookshelf;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;

public final class RecipeUtils {
    
    /**
     * Gets the active recipe manager. One the client this is updated from the recipe updated
     * event. On the server this is updated when the server first launches and when it is
     * stopped.
     * 
     * @return The current recipe manager in use.
     */
    @Nullable
    @Deprecated
    public static RecipeManager getActiveRecipeManager () {
        
        return Bookshelf.SIDED.getActiveRecipeManager();
    }
    
    /**
     * Looks up the map of all known recipes for a given recipe type.
     * 
     * @param <T> The type of the IRecipe object.
     * @param recipeType The recipe type to look up.
     * @param manager The recipe manager to pull data from.
     * @return A map of recipes for the provided recipe type. Key is ResourceLocation, value is
     *         the recipe object.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <T extends IRecipe<?>> Map<ResourceLocation, T> getRecipes (IRecipeType<T> recipeType, RecipeManager manager) {
        
        return (Map) manager.recipes.getOrDefault(recipeType, Collections.emptyMap());
    }
    
    /**
     * Gets a list of all recipes for a given recipe type. This list will be sorted using the
     * translation key of the output item.
     * 
     * @param <T> The type of the IRecipe object.
     * @param recipeType The recipe type to look up.
     * @param manager The recipe manager to pull data from.
     * @return A list of recipes for the given recipe type.
     */
    public static <T extends IRecipe<?>> List<T> getRecipeList (IRecipeType<T> recipeType, RecipeManager manager) {
        
        return getRecipeList(recipeType, manager, Comparator.comparing(recipe -> recipe.getRecipeOutput().getTranslationKey()));
    }
    
    /**
     * Gets a list of all recipes for a given recipe type. This list will be sorted using the
     * provided comparator.
     * 
     * @param <T> The type of the IRecipe object.
     * @param recipeType The recipe type to look up.
     * @param manager The recipe manager to pull data from.
     * @param comparator A comparator that will be used to sort the map.
     * @return A list of recipes for the given recipe type.
     */
    public static <T extends IRecipe<?>> List<T> getRecipeList (IRecipeType<T> recipeType, RecipeManager manager, Comparator<T> comparator) {
        
        return getRecipes(recipeType, manager).values().stream().sorted(comparator).collect(Collectors.toList());
    }
    
    /**
     * Gets all recipes for a given recipe type.
     * 
     * @param <C> The inventory type of the recipe.
     * @param <T> The type of the recipe.
     * @param world The world to read data from.
     * @param recipeType The recipe type you want to get.
     * @return A map of recipes keyed to their IDs.
     */
    public static <C extends IInventory, T extends IRecipe<C>> Map<ResourceLocation, IRecipe<C>> getRecipes (World world, IRecipeType<T> recipeType) {
        
        return getRecipes(world.getRecipeManager(), recipeType);
    }
    
    /**
     * Gets all recipes for a given recipe type.
     * 
     * @param <C> The inventory type of the recipe.
     * @param <T> The type of the recipe.
     * @param manager An instance of the recipe manager.
     * @param recipeType The recipe type you want to get.
     * @return A map of recipes keyed to their IDs.
     */
    public static <C extends IInventory, T extends IRecipe<C>> Map<ResourceLocation, IRecipe<C>> getRecipes (RecipeManager manager, IRecipeType<T> recipeType) {
        
        return manager.getRecipes(recipeType);
    }
}
@@ -314,16 +314,41 @@
 .util;%0A%0A
+import java.util.Arrays;%0A
 import j
@@ -598,16 +598,48 @@
 entory;%0A
+import net.minecraft.item.Item;%0A
 import n
@@ -757,29 +757,107 @@
 rafting.
-RecipeManager
+Ingredient;%0Aimport net.minecraft.item.crafting.RecipeManager;%0Aimport net.minecraft.tags.Tag
 ;%0Aimport
@@ -4569,9 +4569,421 @@
 ;%0A    %7D%0A
+    %0A    /**%0A     * Creates an ingredient using an array of item tags.%0A     * %0A     * @param tags The tags to create an ingredient for.%0A     * @return An ingredient for these tags.%0A     */%0A    @SafeVarargs%0A    public static Ingredient ingredientFromTags (Tag%3CItem%3E... tags) %7B%0A        %0A        return Ingredient.fromItems(Arrays.stream(tags).flatMap(t -%3E t.getAllElements().stream()).toArray(Item%5B%5D::new));%0A    %7D%0A
 %7D

Add a way to get an ingredient using multiple tags.