package org.betterx.bclib.recipes; import org.betterx.bclib.util.CollectionsUtil; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Container; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import com.google.common.collect.Maps; import java.util.*; import java.util.Map.Entry; import java.util.function.Function; public class BCLRecipeManager { private static final Map> _RECIPES = Maps.newHashMap(); private static final Map> _SORTED = Maps.newHashMap(); private static final String MINECRAFT = "minecraft"; @SuppressWarnings("unchecked") private static > Map, Map> RECIPES() { return (Map, Map>) _RECIPES; } @SuppressWarnings("unchecked") private static > Map, List> SORTED() { return (Map, List>) _SORTED; } public static > Optional getSortedRecipe( RecipeType type, C inventory, Level level, Function, Map> getter ) { List recipes = BCLRecipeManager.SORTED().computeIfAbsent(type, t -> { Collection values = getter.apply(type).values(); List list = new ArrayList<>(values); list.sort((v1, v2) -> { boolean b1 = v1.getId().getNamespace().equals(MINECRAFT); boolean b2 = v2.getId().getNamespace().equals(MINECRAFT); return b1 ^ b2 ? (b1 ? 1 : -1) : v1.getId().compareTo(v2.getId()); }); return list; }); return recipes.stream().filter(recipe -> recipe.matches(inventory, level)).findFirst(); } public static > void addRecipe(RecipeType type, T recipe) { Map list = BCLRecipeManager.RECIPES().computeIfAbsent(type, i -> Maps.newHashMap()); list.put(recipe.getId(), recipe); } public static > T getRecipe(RecipeType type, ResourceLocation id) { Map map = BCLRecipeManager.RECIPES().get(type); return map != null ? map.get(id) : null; } public static > Map, Map> getMap( Map, Map> recipes ) { Map, Map> result = Maps.newHashMap(); for (RecipeType type : recipes.keySet()) { Map typeList = Maps.newHashMap(); typeList.putAll(recipes.get(type)); result.put(type, typeList); } SORTED().clear(); BCLRecipeManager.RECIPES().forEach((type, list) -> { if (list != null) { Map typeList = result.computeIfAbsent(type, i -> Maps.newHashMap()); for (Entry entry : list.entrySet()) { ResourceLocation id = entry.getKey(); typeList.computeIfAbsent(id, i -> entry.getValue()); } } }); return result; } public static > Map getMapByName(Map recipes) { Map result = CollectionsUtil.getMutable(recipes); BCLRecipeManager.RECIPES().values() .forEach(map -> map.forEach((location, recipe) -> result.computeIfAbsent( location, i -> recipe ))); return result; } public static , T extends Recipe> S registerSerializer( String modID, String id, S serializer ) { return Registry.register(Registry.RECIPE_SERIALIZER, modID + ":" + id, serializer); } public static > RecipeType registerType(String modID, String type) { ResourceLocation recipeTypeId = new ResourceLocation(modID, type); return Registry.register(Registry.RECIPE_TYPE, recipeTypeId, new RecipeType() { public String toString() { return type; } }); } public static boolean exists(ItemLike item) { if (item instanceof Block) { return Registry.BLOCK.getKey((Block) item) != Registry.BLOCK.getDefaultKey(); } else { return item != Items.AIR && Registry.ITEM.getKey(item.asItem()) != Registry.ITEM.getDefaultKey(); } } public static boolean exists(ItemLike... items) { for (ItemLike item : items) { if (!exists(item)) { return false; } } return true; } }