package net.minecraft.data.recipes; import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.advancements.Criterion; import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.critereon.EnterBlockTrigger.TriggerInstance; import net.minecraft.advancements.critereon.InventoryChangeTrigger.TriggerInstance.Slots; import net.minecraft.advancements.critereon.MinMaxBounds.Ints; import net.minecraft.core.HolderGetter; import net.minecraft.core.HolderLookup; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.data.BlockFamilies; import net.minecraft.data.BlockFamily; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.data.BlockFamily.Variant; import net.minecraft.data.PackOutput.PathProvider; import net.minecraft.data.recipes.RecipeProvider.Runner.1; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.HoneycombItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.AbstractCookingRecipe; import net.minecraft.world.item.crafting.BlastingRecipe; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SmeltingRecipe; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.SuspiciousEffectHolder; import org.jetbrains.annotations.Nullable; public abstract class RecipeProvider { protected final HolderLookup.Provider registries; private final HolderGetter items; protected final RecipeOutput output; private static final Map SHAPE_BUILDERS = ImmutableMap.builder() .put(Variant.BUTTON, (recipeProvider, itemLike, itemLike2) -> recipeProvider.buttonBuilder(itemLike, Ingredient.of(itemLike2))) .put( Variant.CHISELED, (recipeProvider, itemLike, itemLike2) -> recipeProvider.chiseledBuilder(RecipeCategory.BUILDING_BLOCKS, itemLike, Ingredient.of(itemLike2)) ) .put(Variant.CUT, (recipeProvider, itemLike, itemLike2) -> recipeProvider.cutBuilder(RecipeCategory.BUILDING_BLOCKS, itemLike, Ingredient.of(itemLike2))) .put(Variant.DOOR, (recipeProvider, itemLike, itemLike2) -> recipeProvider.doorBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.CUSTOM_FENCE, (recipeProvider, itemLike, itemLike2) -> recipeProvider.fenceBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.FENCE, (recipeProvider, itemLike, itemLike2) -> recipeProvider.fenceBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.CUSTOM_FENCE_GATE, (recipeProvider, itemLike, itemLike2) -> recipeProvider.fenceGateBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.FENCE_GATE, (recipeProvider, itemLike, itemLike2) -> recipeProvider.fenceGateBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.SIGN, (recipeProvider, itemLike, itemLike2) -> recipeProvider.signBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.SLAB, (recipeProvider, itemLike, itemLike2) -> recipeProvider.slabBuilder(RecipeCategory.BUILDING_BLOCKS, itemLike, Ingredient.of(itemLike2))) .put(Variant.STAIRS, (recipeProvider, itemLike, itemLike2) -> recipeProvider.stairBuilder(itemLike, Ingredient.of(itemLike2))) .put( Variant.PRESSURE_PLATE, (recipeProvider, itemLike, itemLike2) -> recipeProvider.pressurePlateBuilder(RecipeCategory.REDSTONE, itemLike, Ingredient.of(itemLike2)) ) .put( Variant.POLISHED, (recipeProvider, itemLike, itemLike2) -> recipeProvider.polishedBuilder(RecipeCategory.BUILDING_BLOCKS, itemLike, Ingredient.of(itemLike2)) ) .put(Variant.TRAPDOOR, (recipeProvider, itemLike, itemLike2) -> recipeProvider.trapdoorBuilder(itemLike, Ingredient.of(itemLike2))) .put(Variant.WALL, (recipeProvider, itemLike, itemLike2) -> recipeProvider.wallBuilder(RecipeCategory.DECORATIONS, itemLike, Ingredient.of(itemLike2))) .build(); protected RecipeProvider(HolderLookup.Provider provider, RecipeOutput recipeOutput) { this.registries = provider; this.items = provider.lookupOrThrow(Registries.ITEM); this.output = recipeOutput; } protected abstract void buildRecipes(); protected void generateForEnabledBlockFamilies(FeatureFlagSet featureFlagSet) { BlockFamilies.getAllFamilies().filter(BlockFamily::shouldGenerateRecipe).forEach(blockFamily -> this.generateRecipes(blockFamily, featureFlagSet)); } protected void oneToOneConversionRecipe(ItemLike itemLike, ItemLike itemLike2, @Nullable String string) { this.oneToOneConversionRecipe(itemLike, itemLike2, string, 1); } protected void oneToOneConversionRecipe(ItemLike itemLike, ItemLike itemLike2, @Nullable String string, int i) { this.shapeless(RecipeCategory.MISC, itemLike, i) .requires(itemLike2) .group(string) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output, getConversionRecipeName(itemLike, itemLike2)); } protected void oreSmelting(List list, RecipeCategory recipeCategory, ItemLike itemLike, float f, int i, String string) { this.oreCooking(RecipeSerializer.SMELTING_RECIPE, SmeltingRecipe::new, list, recipeCategory, itemLike, f, i, string, "_from_smelting"); } protected void oreBlasting(List list, RecipeCategory recipeCategory, ItemLike itemLike, float f, int i, String string) { this.oreCooking(RecipeSerializer.BLASTING_RECIPE, BlastingRecipe::new, list, recipeCategory, itemLike, f, i, string, "_from_blasting"); } private void oreCooking( RecipeSerializer recipeSerializer, AbstractCookingRecipe.Factory factory, List list, RecipeCategory recipeCategory, ItemLike itemLike, float f, int i, String string, String string2 ) { for (ItemLike itemLike2 : list) { SimpleCookingRecipeBuilder.generic(Ingredient.of(itemLike2), recipeCategory, itemLike, f, i, recipeSerializer, factory) .group(string) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output, getItemName(itemLike) + string2 + "_" + getItemName(itemLike2)); } } protected void netheriteSmithing(Item item, RecipeCategory recipeCategory, Item item2) { SmithingTransformRecipeBuilder.smithing( Ingredient.of(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE), Ingredient.of(item), this.tag(ItemTags.NETHERITE_TOOL_MATERIALS), recipeCategory, item2 ) .unlocks("has_netherite_ingot", this.has(ItemTags.NETHERITE_TOOL_MATERIALS)) .save(this.output, getItemName(item2) + "_smithing"); } protected void trimSmithing(Item item, ResourceKey> resourceKey) { SmithingTrimRecipeBuilder.smithingTrim(Ingredient.of(item), this.tag(ItemTags.TRIMMABLE_ARMOR), this.tag(ItemTags.TRIM_MATERIALS), RecipeCategory.MISC) .unlocks("has_smithing_trim_template", this.has(item)) .save(this.output, resourceKey); } protected void twoByTwoPacker(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.shaped(recipeCategory, itemLike, 1) .define('#', itemLike2) .pattern("##") .pattern("##") .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected void threeByThreePacker(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2, String string) { this.shapeless(recipeCategory, itemLike).requires(itemLike2, 9).unlockedBy(string, this.has(itemLike2)).save(this.output); } protected void threeByThreePacker(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.threeByThreePacker(recipeCategory, itemLike, itemLike2, getHasName(itemLike2)); } protected void planksFromLog(ItemLike itemLike, TagKey tagKey, int i) { this.shapeless(RecipeCategory.BUILDING_BLOCKS, itemLike, i).requires(tagKey).group("planks").unlockedBy("has_log", this.has(tagKey)).save(this.output); } protected void planksFromLogs(ItemLike itemLike, TagKey tagKey, int i) { this.shapeless(RecipeCategory.BUILDING_BLOCKS, itemLike, i).requires(tagKey).group("planks").unlockedBy("has_logs", this.has(tagKey)).save(this.output); } protected void woodFromLogs(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.BUILDING_BLOCKS, itemLike, 3) .define('#', itemLike2) .pattern("##") .pattern("##") .group("bark") .unlockedBy("has_log", this.has(itemLike2)) .save(this.output); } protected void woodenBoat(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.TRANSPORTATION, itemLike) .define('#', itemLike2) .pattern("# #") .pattern("###") .group("boat") .unlockedBy("in_water", insideOf(Blocks.WATER)) .save(this.output); } protected void chestBoat(ItemLike itemLike, ItemLike itemLike2) { this.shapeless(RecipeCategory.TRANSPORTATION, itemLike) .requires(Blocks.CHEST) .requires(itemLike2) .group("chest_boat") .unlockedBy("has_boat", this.has(ItemTags.BOATS)) .save(this.output); } private RecipeBuilder buttonBuilder(ItemLike material, Ingredient ingredient) { return this.shapeless(RecipeCategory.REDSTONE, material).requires(ingredient); } protected RecipeBuilder doorBuilder(ItemLike material, Ingredient ingredient) { return this.shaped(RecipeCategory.REDSTONE, material, 3).define('#', ingredient).pattern("##").pattern("##").pattern("##"); } private RecipeBuilder fenceBuilder(ItemLike material, Ingredient ingredient) { int i = material == Blocks.NETHER_BRICK_FENCE ? 6 : 3; Item item = material == Blocks.NETHER_BRICK_FENCE ? Items.NETHER_BRICK : Items.STICK; return this.shaped(RecipeCategory.DECORATIONS, material, i).define('W', ingredient).define('#', item).pattern("W#W").pattern("W#W"); } private RecipeBuilder fenceGateBuilder(ItemLike material, Ingredient ingredient) { return this.shaped(RecipeCategory.REDSTONE, material).define('#', Items.STICK).define('W', ingredient).pattern("#W#").pattern("#W#"); } protected void pressurePlate(ItemLike itemLike, ItemLike itemLike2) { this.pressurePlateBuilder(RecipeCategory.REDSTONE, itemLike, Ingredient.of(itemLike2)) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } private RecipeBuilder pressurePlateBuilder(RecipeCategory pressurePlate, ItemLike material, Ingredient ingredient) { return this.shaped(pressurePlate, material).define('#', ingredient).pattern("##"); } protected void slab(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.slabBuilder(recipeCategory, itemLike, Ingredient.of(itemLike2)).unlockedBy(getHasName(itemLike2), this.has(itemLike2)).save(this.output); } protected RecipeBuilder slabBuilder(RecipeCategory slab, ItemLike material, Ingredient ingredient) { return this.shaped(slab, material, 6).define('#', ingredient).pattern("###"); } protected RecipeBuilder stairBuilder(ItemLike material, Ingredient ingredient) { return this.shaped(RecipeCategory.BUILDING_BLOCKS, material, 4).define('#', ingredient).pattern("# ").pattern("## ").pattern("###"); } protected RecipeBuilder trapdoorBuilder(ItemLike material, Ingredient ingredient) { return this.shaped(RecipeCategory.REDSTONE, material, 2).define('#', ingredient).pattern("###").pattern("###"); } private RecipeBuilder signBuilder(ItemLike material, Ingredient ingredient) { return this.shaped(RecipeCategory.DECORATIONS, material, 3) .group("sign") .define('#', ingredient) .define('X', Items.STICK) .pattern("###") .pattern("###") .pattern(" X "); } protected void hangingSign(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.DECORATIONS, itemLike, 6) .group("hanging_sign") .define('#', itemLike2) .define('X', Items.CHAIN) .pattern("X X") .pattern("###") .pattern("###") .unlockedBy("has_stripped_logs", this.has(itemLike2)) .save(this.output); } protected void colorBlockWithDye(List list, List list2, String string) { this.colorWithDye(list, list2, null, string, RecipeCategory.BUILDING_BLOCKS); } protected void colorWithDye(List list, List list2, @Nullable Item item, String string, RecipeCategory recipeCategory) { for (int i = 0; i < list.size(); i++) { Item item2 = (Item)list.get(i); Item item3 = (Item)list2.get(i); Stream stream = list2.stream().filter(item2x -> !item2x.equals(item3)); if (item != null) { stream = Stream.concat(stream, Stream.of(item)); } this.shapeless(recipeCategory, item3) .requires(item2) .requires(Ingredient.of(stream)) .group(string) .unlockedBy("has_needed_dye", this.has(item2)) .save(this.output, "dye_" + getItemName(item3)); } } protected void carpet(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.DECORATIONS, itemLike, 3) .define('#', itemLike2) .pattern("##") .group("carpet") .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected void bedFromPlanksAndWool(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.DECORATIONS, itemLike) .define('#', itemLike2) .define('X', ItemTags.PLANKS) .pattern("###") .pattern("XXX") .group("bed") .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected void banner(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.DECORATIONS, itemLike) .define('#', itemLike2) .define('|', Items.STICK) .pattern("###") .pattern("###") .pattern(" | ") .group("banner") .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected void stainedGlassFromGlassAndDye(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.BUILDING_BLOCKS, itemLike, 8) .define('#', Blocks.GLASS) .define('X', itemLike2) .pattern("###") .pattern("#X#") .pattern("###") .group("stained_glass") .unlockedBy("has_glass", this.has(Blocks.GLASS)) .save(this.output); } protected void stainedGlassPaneFromStainedGlass(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.DECORATIONS, itemLike, 16) .define('#', itemLike2) .pattern("###") .pattern("###") .group("stained_glass_pane") .unlockedBy("has_glass", this.has(itemLike2)) .save(this.output); } protected void stainedGlassPaneFromGlassPaneAndDye(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.DECORATIONS, itemLike, 8) .define('#', Blocks.GLASS_PANE) .define('$', itemLike2) .pattern("###") .pattern("#$#") .pattern("###") .group("stained_glass_pane") .unlockedBy("has_glass_pane", this.has(Blocks.GLASS_PANE)) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output, getConversionRecipeName(itemLike, Blocks.GLASS_PANE)); } protected void coloredTerracottaFromTerracottaAndDye(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.BUILDING_BLOCKS, itemLike, 8) .define('#', Blocks.TERRACOTTA) .define('X', itemLike2) .pattern("###") .pattern("#X#") .pattern("###") .group("stained_terracotta") .unlockedBy("has_terracotta", this.has(Blocks.TERRACOTTA)) .save(this.output); } protected void concretePowder(ItemLike itemLike, ItemLike itemLike2) { this.shapeless(RecipeCategory.BUILDING_BLOCKS, itemLike, 8) .requires(itemLike2) .requires(Blocks.SAND, 4) .requires(Blocks.GRAVEL, 4) .group("concrete_powder") .unlockedBy("has_sand", this.has(Blocks.SAND)) .unlockedBy("has_gravel", this.has(Blocks.GRAVEL)) .save(this.output); } protected void candle(ItemLike itemLike, ItemLike itemLike2) { this.shapeless(RecipeCategory.DECORATIONS, itemLike) .requires(Blocks.CANDLE) .requires(itemLike2) .group("dyed_candle") .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected void wall(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.wallBuilder(recipeCategory, itemLike, Ingredient.of(itemLike2)).unlockedBy(getHasName(itemLike2), this.has(itemLike2)).save(this.output); } private RecipeBuilder wallBuilder(RecipeCategory wall, ItemLike material, Ingredient ingredient) { return this.shaped(wall, material, 6).define('#', ingredient).pattern("###").pattern("###"); } protected void polished(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.polishedBuilder(recipeCategory, itemLike, Ingredient.of(itemLike2)).unlockedBy(getHasName(itemLike2), this.has(itemLike2)).save(this.output); } private RecipeBuilder polishedBuilder(RecipeCategory result, ItemLike material, Ingredient ingredient) { return this.shaped(result, material, 4).define('S', ingredient).pattern("SS").pattern("SS"); } protected void cut(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.cutBuilder(recipeCategory, itemLike, Ingredient.of(itemLike2)).unlockedBy(getHasName(itemLike2), this.has(itemLike2)).save(this.output); } private ShapedRecipeBuilder cutBuilder(RecipeCategory cutResult, ItemLike material, Ingredient ingredient) { return this.shaped(cutResult, material, 4).define('#', ingredient).pattern("##").pattern("##"); } protected void chiseled(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.chiseledBuilder(recipeCategory, itemLike, Ingredient.of(itemLike2)).unlockedBy(getHasName(itemLike2), this.has(itemLike2)).save(this.output); } protected void mosaicBuilder(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.shaped(recipeCategory, itemLike) .define('#', itemLike2) .pattern("#") .pattern("#") .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected ShapedRecipeBuilder chiseledBuilder(RecipeCategory chiseledResult, ItemLike material, Ingredient ingredient) { return this.shaped(chiseledResult, material).define('#', ingredient).pattern("#").pattern("#"); } protected void stonecutterResultFromBase(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2) { this.stonecutterResultFromBase(recipeCategory, itemLike, itemLike2, 1); } protected void stonecutterResultFromBase(RecipeCategory recipeCategory, ItemLike itemLike, ItemLike itemLike2, int i) { SingleItemRecipeBuilder.stonecutting(Ingredient.of(itemLike2), recipeCategory, itemLike, i) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output, getConversionRecipeName(itemLike, itemLike2) + "_stonecutting"); } private void smeltingResultFromBase(ItemLike itemLike, ItemLike itemLike2) { SimpleCookingRecipeBuilder.smelting(Ingredient.of(itemLike2), RecipeCategory.BUILDING_BLOCKS, itemLike, 0.1F, 200) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output); } protected void nineBlockStorageRecipes(RecipeCategory recipeCategory, ItemLike itemLike, RecipeCategory recipeCategory2, ItemLike itemLike2) { this.nineBlockStorageRecipes(recipeCategory, itemLike, recipeCategory2, itemLike2, getSimpleRecipeName(itemLike2), null, getSimpleRecipeName(itemLike), null); } protected void nineBlockStorageRecipesWithCustomPacking( RecipeCategory recipeCategory, ItemLike itemLike, RecipeCategory recipeCategory2, ItemLike itemLike2, String string, String string2 ) { this.nineBlockStorageRecipes(recipeCategory, itemLike, recipeCategory2, itemLike2, string, string2, getSimpleRecipeName(itemLike), null); } protected void nineBlockStorageRecipesRecipesWithCustomUnpacking( RecipeCategory recipeCategory, ItemLike itemLike, RecipeCategory recipeCategory2, ItemLike itemLike2, String string, String string2 ) { this.nineBlockStorageRecipes(recipeCategory, itemLike, recipeCategory2, itemLike2, getSimpleRecipeName(itemLike2), null, string, string2); } private void nineBlockStorageRecipes( RecipeCategory recipeCategory, ItemLike itemLike, RecipeCategory recipeCategory2, ItemLike itemLike2, String string, @Nullable String string2, String string3, @Nullable String string4 ) { this.shapeless(recipeCategory, itemLike, 9) .requires(itemLike2) .group(string4) .unlockedBy(getHasName(itemLike2), this.has(itemLike2)) .save(this.output, ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(string3))); this.shaped(recipeCategory2, itemLike2) .define('#', itemLike) .pattern("###") .pattern("###") .pattern("###") .group(string2) .unlockedBy(getHasName(itemLike), this.has(itemLike)) .save(this.output, ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(string))); } protected void copySmithingTemplate(ItemLike itemLike, ItemLike itemLike2) { this.shaped(RecipeCategory.MISC, itemLike, 2) .define('#', Items.DIAMOND) .define('C', itemLike2) .define('S', itemLike) .pattern("#S#") .pattern("#C#") .pattern("###") .unlockedBy(getHasName(itemLike), this.has(itemLike)) .save(this.output); } protected void copySmithingTemplate(ItemLike itemLike, Ingredient ingredient) { this.shaped(RecipeCategory.MISC, itemLike, 2) .define('#', Items.DIAMOND) .define('C', ingredient) .define('S', itemLike) .pattern("#S#") .pattern("#C#") .pattern("###") .unlockedBy(getHasName(itemLike), this.has(itemLike)) .save(this.output); } protected void cookRecipes( String string, RecipeSerializer recipeSerializer, AbstractCookingRecipe.Factory factory, int i ) { this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.BEEF, Items.COOKED_BEEF, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.CHICKEN, Items.COOKED_CHICKEN, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.COD, Items.COOKED_COD, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.KELP, Items.DRIED_KELP, 0.1F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.SALMON, Items.COOKED_SALMON, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.MUTTON, Items.COOKED_MUTTON, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.PORKCHOP, Items.COOKED_PORKCHOP, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.POTATO, Items.BAKED_POTATO, 0.35F); this.simpleCookingRecipe(string, recipeSerializer, factory, i, Items.RABBIT, Items.COOKED_RABBIT, 0.35F); } private void simpleCookingRecipe( String string, RecipeSerializer recipeSerializer, AbstractCookingRecipe.Factory factory, int i, ItemLike itemLike, ItemLike itemLike2, float f ) { SimpleCookingRecipeBuilder.generic(Ingredient.of(itemLike), RecipeCategory.FOOD, itemLike2, f, i, recipeSerializer, factory) .unlockedBy(getHasName(itemLike), this.has(itemLike)) .save(this.output, getItemName(itemLike2) + "_from_" + string); } protected void waxRecipes(FeatureFlagSet featureFlagSet) { ((BiMap)HoneycombItem.WAXABLES.get()) .forEach( (block, block2) -> { if (block2.requiredFeatures().isSubsetOf(featureFlagSet)) { this.shapeless(RecipeCategory.BUILDING_BLOCKS, block2) .requires(block) .requires(Items.HONEYCOMB) .group(getItemName(block2)) .unlockedBy(getHasName(block), this.has(block)) .save(this.output, getConversionRecipeName(block2, Items.HONEYCOMB)); } } ); } protected void grate(Block block, Block block2) { this.shaped(RecipeCategory.BUILDING_BLOCKS, block, 4) .define('M', block2) .pattern(" M ") .pattern("M M") .pattern(" M ") .unlockedBy(getHasName(block2), this.has(block2)) .save(this.output); } protected void copperBulb(Block block, Block block2) { this.shaped(RecipeCategory.REDSTONE, block, 4) .define('C', block2) .define('R', Items.REDSTONE) .define('B', Items.BLAZE_ROD) .pattern(" C ") .pattern("CBC") .pattern(" R ") .unlockedBy(getHasName(block2), this.has(block2)) .save(this.output); } protected void suspiciousStew(Item item, SuspiciousEffectHolder suspiciousEffectHolder) { ItemStack itemStack = new ItemStack( Items.SUSPICIOUS_STEW.builtInRegistryHolder(), 1, DataComponentPatch.builder().set(DataComponents.SUSPICIOUS_STEW_EFFECTS, suspiciousEffectHolder.getSuspiciousEffects()).build() ); this.shapeless(RecipeCategory.FOOD, itemStack) .requires(Items.BOWL) .requires(Items.BROWN_MUSHROOM) .requires(Items.RED_MUSHROOM) .requires(item) .group("suspicious_stew") .unlockedBy(getHasName(item), this.has(item)) .save(this.output, getItemName(itemStack.getItem()) + "_from_" + getItemName(item)); } protected void generateRecipes(BlockFamily blockFamily, FeatureFlagSet featureFlagSet) { blockFamily.getVariants().forEach((variant, block) -> { if (block.requiredFeatures().isSubsetOf(featureFlagSet)) { RecipeProvider.FamilyRecipeProvider familyRecipeProvider = (RecipeProvider.FamilyRecipeProvider)SHAPE_BUILDERS.get(variant); ItemLike itemLike = this.getBaseBlock(blockFamily, variant); if (familyRecipeProvider != null) { RecipeBuilder recipeBuilder = familyRecipeProvider.create(this, block, itemLike); blockFamily.getRecipeGroupPrefix().ifPresent(string -> recipeBuilder.group(string + (variant == Variant.CUT ? "" : "_" + variant.getRecipeGroup()))); recipeBuilder.unlockedBy((String)blockFamily.getRecipeUnlockedBy().orElseGet(() -> getHasName(itemLike)), this.has(itemLike)); recipeBuilder.save(this.output); } if (variant == Variant.CRACKED) { this.smeltingResultFromBase(block, itemLike); } } }); } private Block getBaseBlock(BlockFamily variant, Variant variant2) { if (variant2 == Variant.CHISELED) { if (!variant.getVariants().containsKey(Variant.SLAB)) { throw new IllegalStateException("Slab is not defined for the family."); } else { return variant.get(Variant.SLAB); } } else { return variant.getBaseBlock(); } } private static Criterion insideOf(Block block) { return CriteriaTriggers.ENTER_BLOCK.createCriterion(new TriggerInstance(Optional.empty(), Optional.of(block.builtInRegistryHolder()), Optional.empty())); } private Criterion has(Ints item, ItemLike itemLike) { return inventoryTrigger(ItemPredicate.Builder.item().of(this.items, itemLike).withCount(item)); } protected Criterion has(ItemLike itemLike) { return inventoryTrigger(ItemPredicate.Builder.item().of(this.items, itemLike)); } protected Criterion has(TagKey tagKey) { return inventoryTrigger(ItemPredicate.Builder.item().of(this.items, tagKey)); } private static Criterion inventoryTrigger(ItemPredicate.Builder... items) { return inventoryTrigger((ItemPredicate[])Arrays.stream(items).map(ItemPredicate.Builder::build).toArray(ItemPredicate[]::new)); } private static Criterion inventoryTrigger(ItemPredicate... predicates) { return CriteriaTriggers.INVENTORY_CHANGED .createCriterion(new net.minecraft.advancements.critereon.InventoryChangeTrigger.TriggerInstance(Optional.empty(), Slots.ANY, List.of(predicates))); } protected static String getHasName(ItemLike itemLike) { return "has_" + getItemName(itemLike); } protected static String getItemName(ItemLike itemLike) { return BuiltInRegistries.ITEM.getKey(itemLike.asItem()).getPath(); } protected static String getSimpleRecipeName(ItemLike itemLike) { return getItemName(itemLike); } protected static String getConversionRecipeName(ItemLike result, ItemLike ingredient) { return getItemName(result) + "_from_" + getItemName(ingredient); } protected static String getSmeltingRecipeName(ItemLike itemLike) { return getItemName(itemLike) + "_from_smelting"; } protected static String getBlastingRecipeName(ItemLike itemLike) { return getItemName(itemLike) + "_from_blasting"; } protected Ingredient tag(TagKey tagKey) { return Ingredient.of(this.items.getOrThrow(tagKey)); } protected ShapedRecipeBuilder shaped(RecipeCategory recipeCategory, ItemLike itemLike) { return ShapedRecipeBuilder.shaped(this.items, recipeCategory, itemLike); } protected ShapedRecipeBuilder shaped(RecipeCategory recipeCategory, ItemLike itemLike, int i) { return ShapedRecipeBuilder.shaped(this.items, recipeCategory, itemLike, i); } protected ShapelessRecipeBuilder shapeless(RecipeCategory recipeCategory, ItemStack itemStack) { return ShapelessRecipeBuilder.shapeless(this.items, recipeCategory, itemStack); } protected ShapelessRecipeBuilder shapeless(RecipeCategory recipeCategory, ItemLike itemLike) { return ShapelessRecipeBuilder.shapeless(this.items, recipeCategory, itemLike); } protected ShapelessRecipeBuilder shapeless(RecipeCategory recipeCategory, ItemLike itemLike, int i) { return ShapelessRecipeBuilder.shapeless(this.items, recipeCategory, itemLike, i); } @FunctionalInterface interface FamilyRecipeProvider { RecipeBuilder create(RecipeProvider recipeProvider, ItemLike itemLike, ItemLike itemLike2); } protected abstract static class Runner implements DataProvider { private final PackOutput packOutput; private final CompletableFuture registries; protected Runner(PackOutput packOutput, CompletableFuture completableFuture) { this.packOutput = packOutput; this.registries = completableFuture; } @Override public final CompletableFuture run(CachedOutput output) { return this.registries.thenCompose(provider -> { PathProvider pathProvider = this.packOutput.createRegistryElementsPathProvider(Registries.RECIPE); PathProvider pathProvider2 = this.packOutput.createRegistryElementsPathProvider(Registries.ADVANCEMENT); Set>> set = Sets.>>newHashSet(); List> list = new ArrayList(); RecipeOutput recipeOutput = new 1(this, set, list, output, provider, pathProvider, pathProvider2); this.createRecipeProvider(provider, recipeOutput).buildRecipes(); return CompletableFuture.allOf((CompletableFuture[])list.toArray(CompletableFuture[]::new)); }); } protected abstract RecipeProvider createRecipeProvider(HolderLookup.Provider provider, RecipeOutput recipeOutput); } }