RecipeProvider.java

net.minecraft.data.recipes.RecipeProvider

信息

  • 全限定名:net.minecraft.data.recipes.RecipeProvider
  • 类型:public abstract class
  • 包:net.minecraft.data.recipes
  • 源码路径:src/main/java/net/minecraft/data/recipes/RecipeProvider.java
  • 起始行号:L61
  • 职责:

    TODO

字段/常量

  • registries

    • 类型: HolderLookup.Provider
    • 修饰符: protected final
    • 源码定位: L62
    • 说明:

      TODO

  • items

    • 类型: HolderGetter<Item>
    • 修饰符: private final
    • 源码定位: L63
    • 说明:

      TODO

  • output

    • 类型: RecipeOutput
    • 修饰符: protected final
    • 源码定位: L64
    • 说明:

      TODO

  • SHAPE_BUILDERS

    • 类型: Map<BlockFamily.Variant,RecipeProvider.FamilyCraftingRecipeProvider>
    • 修饰符: private static final
    • 源码定位: L65
    • 说明:

      TODO

  • STONECUTTER_RECIPE_BUILDERS

    • 类型: Map<BlockFamily.Variant,RecipeProvider.FamilyStonecutterRecipeProvider>
    • 修饰符: private static final
    • 源码定位: L84
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.data.recipes.RecipeProvider.FamilyCraftingRecipeProvider

    • 类型: interface
    • 修饰符: private
    • 源码定位: L852
    • 说明:

      TODO

  • net.minecraft.data.recipes.RecipeProvider.FamilyStonecutterRecipeProvider

    • 类型: interface
    • 修饰符: private
    • 源码定位: L857
    • 说明:

      TODO

  • net.minecraft.data.recipes.RecipeProvider.Runner

    • 类型: class
    • 修饰符: protected abstract static
    • 源码定位: L861
    • 说明:

      TODO

构造器

protected RecipeProvider(HolderLookup.Provider registries, RecipeOutput output) @ L96

  • 构造器名:RecipeProvider
  • 源码定位:L96
  • 修饰符:protected

参数:

  • registries: HolderLookup.Provider
  • output: RecipeOutput

说明:

TODO

方法

下面的方法块按源码顺序生成。

protected abstract void buildRecipes() @ L102

  • 方法名:buildRecipes
  • 源码定位:L102
  • 返回类型:void
  • 修饰符:protected abstract

参数:

说明:

TODO

protected void generateForEnabledBlockFamilies(FeatureFlagSet flagSet) @ L104

  • 方法名:generateForEnabledBlockFamilies
  • 源码定位:L104
  • 返回类型:void
  • 修饰符:protected

参数:

  • flagSet: FeatureFlagSet

说明:

TODO

protected void oneToOneConversionRecipe(ItemLike product, ItemLike resource, String group) @ L108

  • 方法名:oneToOneConversionRecipe
  • 源码定位:L108
  • 返回类型:void
  • 修饰符:protected

参数:

  • product: ItemLike
  • resource: ItemLike
  • group: String

说明:

TODO

protected void oneToOneConversionRecipe(ItemLike product, ItemLike resource, String group, int productCount) @ L112

  • 方法名:oneToOneConversionRecipe
  • 源码定位:L112
  • 返回类型:void
  • 修饰符:protected

参数:

  • product: ItemLike
  • resource: ItemLike
  • group: String
  • productCount: int

说明:

TODO

protected void oreSmelting(List<ItemLike> smeltables, RecipeCategory craftingCategory, CookingBookCategory cookingCategory, ItemLike result, float experience, int cookingTime, String group) @ L120

  • 方法名:oreSmelting
  • 源码定位:L120
  • 返回类型:void
  • 修饰符:protected

参数:

  • smeltables: List
  • craftingCategory: RecipeCategory
  • cookingCategory: CookingBookCategory
  • result: ItemLike
  • experience: float
  • cookingTime: int
  • group: String

说明:

TODO

protected void oreBlasting(List<ItemLike> smeltables, RecipeCategory craftingCategory, CookingBookCategory cookingCategory, ItemLike result, float experience, int cookingTime, String group) @ L132

  • 方法名:oreBlasting
  • 源码定位:L132
  • 返回类型:void
  • 修饰符:protected

参数:

  • smeltables: List
  • craftingCategory: RecipeCategory
  • cookingCategory: CookingBookCategory
  • result: ItemLike
  • experience: float
  • cookingTime: int
  • group: String

说明:

TODO

private <T extends AbstractCookingRecipe> void oreCooking(AbstractCookingRecipe.Factory<T> factory, List<ItemLike> smeltables, RecipeCategory craftingCategory, CookingBookCategory cookingCategory, ItemLike result, float experience, int cookingTime, String group, String fromDesc) @ L144

  • 方法名:oreCooking
  • 源码定位:L144
  • 返回类型: void
  • 修饰符:private

参数:

  • factory: AbstractCookingRecipe.Factory
  • smeltables: List
  • craftingCategory: RecipeCategory
  • cookingCategory: CookingBookCategory
  • result: ItemLike
  • experience: float
  • cookingTime: int
  • group: String
  • fromDesc: String

说明:

TODO

protected void netheriteSmithing(Item base, RecipeCategory category, Item result) @ L163

  • 方法名:netheriteSmithing
  • 源码定位:L163
  • 返回类型:void
  • 修饰符:protected

参数:

  • base: Item
  • category: RecipeCategory
  • result: Item

说明:

TODO

protected void trimSmithing(Item trimTemplate, ResourceKey<TrimPattern> patternId, ResourceKey<Recipe<?>> id) @ L171

  • 方法名:trimSmithing
  • 源码定位:L171
  • 返回类型:void
  • 修饰符:protected

参数:

  • trimTemplate: Item
  • patternId: ResourceKey
  • id: ResourceKey<Recipe<?>>

说明:

TODO

protected void twoByTwoPacker(RecipeCategory category, ItemLike result, ItemLike ingredient) @ L180

  • 方法名:twoByTwoPacker
  • 源码定位:L180
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • ingredient: ItemLike

说明:

TODO

protected void threeByThreePacker(RecipeCategory category, ItemLike result, ItemLike ingredient, String unlockedBy) @ L189

  • 方法名:threeByThreePacker
  • 源码定位:L189
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • ingredient: ItemLike
  • unlockedBy: String

说明:

TODO

protected void threeByThreePacker(RecipeCategory category, ItemLike result, ItemLike ingredient) @ L193

  • 方法名:threeByThreePacker
  • 源码定位:L193
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • ingredient: ItemLike

说明:

TODO

protected void planksFromLog(ItemLike result, TagKey<Item> logs, int count) @ L197

  • 方法名:planksFromLog
  • 源码定位:L197
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • logs: TagKey
  • count: int

说明:

TODO

protected void planksFromLogs(ItemLike result, TagKey<Item> logs, int count) @ L201

  • 方法名:planksFromLogs
  • 源码定位:L201
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • logs: TagKey
  • count: int

说明:

TODO

protected void woodFromLogs(ItemLike result, ItemLike log) @ L205

  • 方法名:woodFromLogs
  • 源码定位:L205
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • log: ItemLike

说明:

TODO

protected void woodenBoat(ItemLike result, ItemLike planks) @ L215

  • 方法名:woodenBoat
  • 源码定位:L215
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • planks: ItemLike

说明:

TODO

protected void chestBoat(ItemLike chestBoat, ItemLike boat) @ L225

  • 方法名:chestBoat
  • 源码定位:L225
  • 返回类型:void
  • 修饰符:protected

参数:

  • chestBoat: ItemLike
  • boat: ItemLike

说明:

TODO

private RecipeBuilder buttonBuilder(ItemLike result, Ingredient base) @ L234

  • 方法名:buttonBuilder
  • 源码定位:L234
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected RecipeBuilder doorBuilder(ItemLike result, Ingredient base) @ L238

  • 方法名:doorBuilder
  • 源码定位:L238
  • 返回类型:RecipeBuilder
  • 修饰符:protected

参数:

  • result: ItemLike
  • base: Ingredient

说明:

TODO

private RecipeBuilder fenceBuilder(ItemLike result, Ingredient base) @ L242

  • 方法名:fenceBuilder
  • 源码定位:L242
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • result: ItemLike
  • base: Ingredient

说明:

TODO

private RecipeBuilder fenceGateBuilder(ItemLike result, Ingredient planks) @ L248

  • 方法名:fenceGateBuilder
  • 源码定位:L248
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • result: ItemLike
  • planks: Ingredient

说明:

TODO

protected void pressurePlate(ItemLike result, ItemLike base) @ L252

  • 方法名:pressurePlate
  • 源码定位:L252
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • base: ItemLike

说明:

TODO

private RecipeBuilder pressurePlateBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L256

  • 方法名:pressurePlateBuilder
  • 源码定位:L256
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected void slab(RecipeCategory category, ItemLike result, ItemLike base) @ L260

  • 方法名:slab
  • 源码定位:L260
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

protected void shelf(ItemLike result, ItemLike strippedLogs) @ L264

  • 方法名:shelf
  • 源码定位:L264
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • strippedLogs: ItemLike

说明:

TODO

protected RecipeBuilder slabBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L275

  • 方法名:slabBuilder
  • 源码定位:L275
  • 返回类型:RecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected RecipeBuilder stairBuilder(ItemLike result, Ingredient base) @ L279

  • 方法名:stairBuilder
  • 源码定位:L279
  • 返回类型:RecipeBuilder
  • 修饰符:protected

参数:

  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected RecipeBuilder trapdoorBuilder(ItemLike result, Ingredient base) @ L283

  • 方法名:trapdoorBuilder
  • 源码定位:L283
  • 返回类型:RecipeBuilder
  • 修饰符:protected

参数:

  • result: ItemLike
  • base: Ingredient

说明:

TODO

private RecipeBuilder signBuilder(ItemLike result, Ingredient planks) @ L287

  • 方法名:signBuilder
  • 源码定位:L287
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • result: ItemLike
  • planks: Ingredient

说明:

TODO

protected void hangingSign(ItemLike result, ItemLike ingredient) @ L297

  • 方法名:hangingSign
  • 源码定位:L297
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • ingredient: ItemLike

说明:

TODO

protected void colorItemWithDye(List<Item> dyes, List<Item> items, String groupName, RecipeCategory category) @ L309

  • 方法名:colorItemWithDye
  • 源码定位:L309
  • 返回类型:void
  • 修饰符:protected

参数:

  • dyes: List
  • items: List
  • groupName: String
  • category: RecipeCategory

说明:

TODO

protected void colorWithDye(List<Item> dyes, List<Item> dyedItems, Item uncoloredItem, String groupName, RecipeCategory category) @ L313

  • 方法名:colorWithDye
  • 源码定位:L313
  • 返回类型:void
  • 修饰符:protected

参数:

  • dyes: List
  • dyedItems: List
  • uncoloredItem: Item
  • groupName: String
  • category: RecipeCategory

说明:

TODO

protected void carpet(ItemLike result, ItemLike sourceItem) @ L331

  • 方法名:carpet
  • 源码定位:L331
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • sourceItem: ItemLike

说明:

TODO

protected void bedFromPlanksAndWool(ItemLike result, ItemLike wool) @ L340

  • 方法名:bedFromPlanksAndWool
  • 源码定位:L340
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • wool: ItemLike

说明:

TODO

protected void banner(ItemLike result, ItemLike wool) @ L351

  • 方法名:banner
  • 源码定位:L351
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • wool: ItemLike

说明:

TODO

protected void stainedGlassFromGlassAndDye(ItemLike result, ItemLike dye) @ L365

  • 方法名:stainedGlassFromGlassAndDye
  • 源码定位:L365
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • dye: ItemLike

说明:

TODO

protected void dryGhast(ItemLike result) @ L377

  • 方法名:dryGhast
  • 源码定位:L377
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike

说明:

TODO

protected void harness(ItemLike result, ItemLike wool) @ L389

  • 方法名:harness
  • 源码定位:L389
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • wool: ItemLike

说明:

TODO

protected void stainedGlassPaneFromStainedGlass(ItemLike result, ItemLike stainedGlass) @ L401

  • 方法名:stainedGlassPaneFromStainedGlass
  • 源码定位:L401
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • stainedGlass: ItemLike

说明:

TODO

protected void stainedGlassPaneFromGlassPaneAndDye(ItemLike result, ItemLike dye) @ L411

  • 方法名:stainedGlassPaneFromGlassPaneAndDye
  • 源码定位:L411
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • dye: ItemLike

说明:

TODO

protected void coloredTerracottaFromTerracottaAndDye(ItemLike result, ItemLike dye) @ L424

  • 方法名:coloredTerracottaFromTerracottaAndDye
  • 源码定位:L424
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • dye: ItemLike

说明:

TODO

protected void concretePowder(ItemLike result, ItemLike dye) @ L436

  • 方法名:concretePowder
  • 源码定位:L436
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • dye: ItemLike

说明:

TODO

protected void candle(ItemLike result, ItemLike dye) @ L447

  • 方法名:candle
  • 源码定位:L447
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: ItemLike
  • dye: ItemLike

说明:

TODO

protected void wall(RecipeCategory category, ItemLike result, ItemLike base) @ L456

  • 方法名:wall
  • 源码定位:L456
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

private RecipeBuilder wallBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L460

  • 方法名:wallBuilder
  • 源码定位:L460
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

private RecipeBuilder bricksBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L464

  • 方法名:bricksBuilder
  • 源码定位:L464
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

private RecipeBuilder tilesBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L468

  • 方法名:tilesBuilder
  • 源码定位:L468
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected void polished(RecipeCategory category, ItemLike result, ItemLike base) @ L472

  • 方法名:polished
  • 源码定位:L472
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

private RecipeBuilder polishedBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L476

  • 方法名:polishedBuilder
  • 源码定位:L476
  • 返回类型:RecipeBuilder
  • 修饰符:private

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected void cut(RecipeCategory category, ItemLike result, ItemLike base) @ L480

  • 方法名:cut
  • 源码定位:L480
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

private ShapedRecipeBuilder cutBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L484

  • 方法名:cutBuilder
  • 源码定位:L484
  • 返回类型:ShapedRecipeBuilder
  • 修饰符:private

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected void chiseled(RecipeCategory category, ItemLike result, ItemLike base) @ L488

  • 方法名:chiseled
  • 源码定位:L488
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

protected void mosaicBuilder(RecipeCategory category, ItemLike result, ItemLike base) @ L492

  • 方法名:mosaicBuilder
  • 源码定位:L492
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

protected ShapedRecipeBuilder chiseledBuilder(RecipeCategory category, ItemLike result, Ingredient base) @ L496

  • 方法名:chiseledBuilder
  • 源码定位:L496
  • 返回类型:ShapedRecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: Ingredient

说明:

TODO

protected void stonecutterResultFromBase(RecipeCategory category, ItemLike result, ItemLike base) @ L500

  • 方法名:stonecutterResultFromBase
  • 源码定位:L500
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike

说明:

TODO

protected void stonecutterResultFromBase(RecipeCategory category, ItemLike result, ItemLike base, int count) @ L504

  • 方法名:stonecutterResultFromBase
  • 源码定位:L504
  • 返回类型:void
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemLike
  • base: ItemLike
  • count: int

说明:

TODO

private void smeltingResultFromBase(ItemLike result, ItemLike base) @ L510

  • 方法名:smeltingResultFromBase
  • 源码定位:L510
  • 返回类型:void
  • 修饰符:private

参数:

  • result: ItemLike
  • base: ItemLike

说明:

TODO

protected void nineBlockStorageRecipes(RecipeCategory unpackedFormCategory, ItemLike unpackedForm, RecipeCategory packedFormCategory, ItemLike packedForm) @ L516

  • 方法名:nineBlockStorageRecipes
  • 源码定位:L516
  • 返回类型:void
  • 修饰符:protected

参数:

  • unpackedFormCategory: RecipeCategory
  • unpackedForm: ItemLike
  • packedFormCategory: RecipeCategory
  • packedForm: ItemLike

说明:

TODO

protected void nineBlockStorageRecipesWithCustomPacking(RecipeCategory unpackedFormCategory, ItemLike unpackedForm, RecipeCategory packedFormCategory, ItemLike packedForm, String packingRecipeId, String packingRecipeGroup) @ L522

  • 方法名:nineBlockStorageRecipesWithCustomPacking
  • 源码定位:L522
  • 返回类型:void
  • 修饰符:protected

参数:

  • unpackedFormCategory: RecipeCategory
  • unpackedForm: ItemLike
  • packedFormCategory: RecipeCategory
  • packedForm: ItemLike
  • packingRecipeId: String
  • packingRecipeGroup: String

说明:

TODO

protected void nineBlockStorageRecipesRecipesWithCustomUnpacking(RecipeCategory unpackedFormCategory, ItemLike unpackedForm, RecipeCategory packedFormCategory, ItemLike packedForm, String unpackingRecipeId, String unpackingRecipeGroup) @ L535

  • 方法名:nineBlockStorageRecipesRecipesWithCustomUnpacking
  • 源码定位:L535
  • 返回类型:void
  • 修饰符:protected

参数:

  • unpackedFormCategory: RecipeCategory
  • unpackedForm: ItemLike
  • packedFormCategory: RecipeCategory
  • packedForm: ItemLike
  • unpackingRecipeId: String
  • unpackingRecipeGroup: String

说明:

TODO

private void nineBlockStorageRecipes(RecipeCategory unpackedFormCategory, ItemLike unpackedForm, RecipeCategory packedFormCategory, ItemLike packedForm, String packingRecipeId, String packingRecipeGroup, String unpackingRecipeId, String unpackingRecipeGroup) @ L548

  • 方法名:nineBlockStorageRecipes
  • 源码定位:L548
  • 返回类型:void
  • 修饰符:private

参数:

  • unpackedFormCategory: RecipeCategory
  • unpackedForm: ItemLike
  • packedFormCategory: RecipeCategory
  • packedForm: ItemLike
  • packingRecipeId: String
  • packingRecipeGroup: String
  • unpackingRecipeId: String
  • unpackingRecipeGroup: String

说明:

TODO

protected void copySmithingTemplate(ItemLike smithingTemplate, ItemLike baseMaterial) @ L573

  • 方法名:copySmithingTemplate
  • 源码定位:L573
  • 返回类型:void
  • 修饰符:protected

参数:

  • smithingTemplate: ItemLike
  • baseMaterial: ItemLike

说明:

TODO

protected void copySmithingTemplate(ItemLike smithingTemplate, Ingredient baseMaterials) @ L585

  • 方法名:copySmithingTemplate
  • 源码定位:L585
  • 返回类型:void
  • 修饰符:protected

参数:

  • smithingTemplate: ItemLike
  • baseMaterials: Ingredient

说明:

TODO

protected <T extends AbstractCookingRecipe> void cookRecipes(String source, AbstractCookingRecipe.Factory<T> factory, int cookingTime) @ L597

  • 方法名:cookRecipes
  • 源码定位:L597
  • 返回类型: void
  • 修饰符:protected

参数:

  • source: String
  • factory: AbstractCookingRecipe.Factory
  • cookingTime: int

说明:

TODO

private <T extends AbstractCookingRecipe> void simpleCookingRecipe(String source, AbstractCookingRecipe.Factory<T> factory, int cookingTime, ItemLike base, ItemLike result, float experience) @ L609

  • 方法名:simpleCookingRecipe
  • 源码定位:L609
  • 返回类型: void
  • 修饰符:private

参数:

  • source: String
  • factory: AbstractCookingRecipe.Factory
  • cookingTime: int
  • base: ItemLike
  • result: ItemLike
  • experience: float

说明:

TODO

protected void waxRecipes(FeatureFlagSet flagSet) @ L617

  • 方法名:waxRecipes
  • 源码定位:L617
  • 返回类型:void
  • 修饰符:protected

参数:

  • flagSet: FeatureFlagSet

说明:

TODO

protected void grate(Block grateBlock, Block material) @ L638

  • 方法名:grate
  • 源码定位:L638
  • 返回类型:void
  • 修饰符:protected

参数:

  • grateBlock: Block
  • material: Block

说明:

TODO

protected void copperBulb(Block copperBulb, Block copperMaterial) @ L649

  • 方法名:copperBulb
  • 源码定位:L649
  • 返回类型:void
  • 修饰符:protected

参数:

  • copperBulb: Block
  • copperMaterial: Block

说明:

TODO

protected void waxedChiseled(Block result, Block material) @ L662

  • 方法名:waxedChiseled
  • 源码定位:L662
  • 返回类型:void
  • 修饰符:protected

参数:

  • result: Block
  • material: Block

说明:

TODO

protected void suspiciousStew(Item item, SuspiciousEffectHolder effectHolder) @ L672

  • 方法名:suspiciousStew
  • 源码定位:L672
  • 返回类型:void
  • 修饰符:protected

参数:

  • item: Item
  • effectHolder: SuspiciousEffectHolder

说明:

TODO

protected void dyedItem(Item target, String group) @ L686

  • 方法名:dyedItem
  • 源码定位:L686
  • 返回类型:void
  • 修饰符:protected

参数:

  • target: Item
  • group: String

说明:

TODO

protected void dyedShulkerBoxRecipe(Item dye, Item dyedResult) @ L696

  • 方法名:dyedShulkerBoxRecipe
  • 源码定位:L696
  • 返回类型:void
  • 修饰符:protected

参数:

  • dye: Item
  • dyedResult: Item

说明:

TODO

protected void dyedBundleRecipe(Item dye, Item dyedResult) @ L703

  • 方法名:dyedBundleRecipe
  • 源码定位:L703
  • 返回类型:void
  • 修饰符:protected

参数:

  • dye: Item
  • dyedResult: Item

说明:

TODO

protected void generateRecipes(BlockFamily family, FeatureFlagSet flagSet) @ L710

  • 方法名:generateRecipes
  • 源码定位:L710
  • 返回类型:void
  • 修饰符:protected

参数:

  • family: BlockFamily
  • flagSet: FeatureFlagSet

说明:

TODO

private void generateCraftingRecipe(BlockFamily family, BlockFamily.Variant variant, Block result, ItemLike base) @ L729

  • 方法名:generateCraftingRecipe
  • 源码定位:L729
  • 返回类型:void
  • 修饰符:private

参数:

  • family: BlockFamily
  • variant: BlockFamily.Variant
  • result: Block
  • base: ItemLike

说明:

TODO

private void generateStonecutterRecipe(BlockFamily family, BlockFamily.Variant variant, Block base) @ L740

  • 方法名:generateStonecutterRecipe
  • 源码定位:L740
  • 返回类型:void
  • 修饰符:private

参数:

  • family: BlockFamily
  • variant: BlockFamily.Variant
  • base: Block

说明:

TODO

private Block getBaseBlockForCrafting(BlockFamily family, BlockFamily.Variant variant) @ L758

  • 方法名:getBaseBlockForCrafting
  • 源码定位:L758
  • 返回类型:Block
  • 修饰符:private

参数:

  • family: BlockFamily
  • variant: BlockFamily.Variant

说明:

TODO

private static Criterion<EnterBlockTrigger.TriggerInstance> insideOf(Block block) @ L770

  • 方法名:insideOf
  • 源码定位:L770
  • 返回类型:Criterion<EnterBlockTrigger.TriggerInstance>
  • 修饰符:private static

参数:

  • block: Block

说明:

TODO

protected Criterion<BredAnimalsTrigger.TriggerInstance> bredAnimal() @ L775

  • 方法名:bredAnimal
  • 源码定位:L775
  • 返回类型:Criterion<BredAnimalsTrigger.TriggerInstance>
  • 修饰符:protected

参数:

说明:

TODO

private Criterion<InventoryChangeTrigger.TriggerInstance> has(MinMaxBounds.Ints count, ItemLike item) @ L780

  • 方法名:has
  • 源码定位:L780
  • 返回类型:Criterion<InventoryChangeTrigger.TriggerInstance>
  • 修饰符:private

参数:

  • count: MinMaxBounds.Ints
  • item: ItemLike

说明:

TODO

protected Criterion<InventoryChangeTrigger.TriggerInstance> has(ItemLike item) @ L784

  • 方法名:has
  • 源码定位:L784
  • 返回类型:Criterion<InventoryChangeTrigger.TriggerInstance>
  • 修饰符:protected

参数:

  • item: ItemLike

说明:

TODO

protected Criterion<InventoryChangeTrigger.TriggerInstance> has(TagKey<Item> tag) @ L788

  • 方法名:has
  • 源码定位:L788
  • 返回类型:Criterion<InventoryChangeTrigger.TriggerInstance>
  • 修饰符:protected

参数:

  • tag: TagKey

说明:

TODO

private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryTrigger(ItemPredicate.Builder... predicates) @ L792

  • 方法名:inventoryTrigger
  • 源码定位:L792
  • 返回类型:Criterion<InventoryChangeTrigger.TriggerInstance>
  • 修饰符:private static

参数:

  • predicates: ItemPredicate.Builder…

说明:

TODO

private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryTrigger(ItemPredicate... predicates) @ L796

  • 方法名:inventoryTrigger
  • 源码定位:L796
  • 返回类型:Criterion<InventoryChangeTrigger.TriggerInstance>
  • 修饰符:private static

参数:

  • predicates: ItemPredicate…

说明:

TODO

protected static String getHasName(ItemLike baseBlock) @ L803

  • 方法名:getHasName
  • 源码定位:L803
  • 返回类型:String
  • 修饰符:protected static

参数:

  • baseBlock: ItemLike

说明:

TODO

protected static String getItemName(ItemLike itemLike) @ L807

  • 方法名:getItemName
  • 源码定位:L807
  • 返回类型:String
  • 修饰符:protected static

参数:

  • itemLike: ItemLike

说明:

TODO

protected static String getSimpleRecipeName(ItemLike itemLike) @ L811

  • 方法名:getSimpleRecipeName
  • 源码定位:L811
  • 返回类型:String
  • 修饰符:protected static

参数:

  • itemLike: ItemLike

说明:

TODO

protected static String getConversionRecipeName(ItemLike product, ItemLike material) @ L815

  • 方法名:getConversionRecipeName
  • 源码定位:L815
  • 返回类型:String
  • 修饰符:protected static

参数:

  • product: ItemLike
  • material: ItemLike

说明:

TODO

protected static String getSmeltingRecipeName(ItemLike product) @ L819

  • 方法名:getSmeltingRecipeName
  • 源码定位:L819
  • 返回类型:String
  • 修饰符:protected static

参数:

  • product: ItemLike

说明:

TODO

protected static String getBlastingRecipeName(ItemLike product) @ L823

  • 方法名:getBlastingRecipeName
  • 源码定位:L823
  • 返回类型:String
  • 修饰符:protected static

参数:

  • product: ItemLike

说明:

TODO

protected Ingredient tag(TagKey<Item> id) @ L827

  • 方法名:tag
  • 源码定位:L827
  • 返回类型:Ingredient
  • 修饰符:protected

参数:

  • id: TagKey

说明:

TODO

protected ShapedRecipeBuilder shaped(RecipeCategory category, ItemLike item) @ L831

  • 方法名:shaped
  • 源码定位:L831
  • 返回类型:ShapedRecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • item: ItemLike

说明:

TODO

protected ShapedRecipeBuilder shaped(RecipeCategory category, ItemLike item, int count) @ L835

  • 方法名:shaped
  • 源码定位:L835
  • 返回类型:ShapedRecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • item: ItemLike
  • count: int

说明:

TODO

protected ShapelessRecipeBuilder shapeless(RecipeCategory category, ItemStackTemplate result) @ L839

  • 方法名:shapeless
  • 源码定位:L839
  • 返回类型:ShapelessRecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • result: ItemStackTemplate

说明:

TODO

protected ShapelessRecipeBuilder shapeless(RecipeCategory category, ItemLike item) @ L843

  • 方法名:shapeless
  • 源码定位:L843
  • 返回类型:ShapelessRecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • item: ItemLike

说明:

TODO

protected ShapelessRecipeBuilder shapeless(RecipeCategory category, ItemLike item, int count) @ L847

  • 方法名:shapeless
  • 源码定位:L847
  • 返回类型:ShapelessRecipeBuilder
  • 修饰符:protected

参数:

  • category: RecipeCategory
  • item: ItemLike
  • count: int

说明:

TODO

代码

public abstract class RecipeProvider {
    protected final HolderLookup.Provider registries;
    private final HolderGetter<Item> items;
    protected final RecipeOutput output;
    private static final Map<BlockFamily.Variant, RecipeProvider.FamilyCraftingRecipeProvider> SHAPE_BUILDERS = ImmutableMap.<BlockFamily.Variant, RecipeProvider.FamilyCraftingRecipeProvider>builder()
        .put(BlockFamily.Variant.BUTTON, (context, result, base) -> context.buttonBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.CHISELED, (context, result, base) -> context.chiseledBuilder(RecipeCategory.BUILDING_BLOCKS, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.CUT, (context, result, base) -> context.cutBuilder(RecipeCategory.BUILDING_BLOCKS, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.DOOR, (context, result, base) -> context.doorBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.CUSTOM_FENCE, (context, result, base) -> context.fenceBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.FENCE, (context, result, base) -> context.fenceBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.CUSTOM_FENCE_GATE, (context, result, base) -> context.fenceGateBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.FENCE_GATE, (context, result, base) -> context.fenceGateBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.SIGN, (context, result, base) -> context.signBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.SLAB, (context, result, base) -> context.slabBuilder(RecipeCategory.BUILDING_BLOCKS, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.STAIRS, (context, result, base) -> context.stairBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.PRESSURE_PLATE, (context, result, base) -> context.pressurePlateBuilder(RecipeCategory.REDSTONE, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.POLISHED, (context, result, base) -> context.polishedBuilder(RecipeCategory.BUILDING_BLOCKS, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.TRAPDOOR, (context, result, base) -> context.trapdoorBuilder(result, Ingredient.of(base)))
        .put(BlockFamily.Variant.WALL, (context, result, base) -> context.wallBuilder(RecipeCategory.DECORATIONS, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.BRICKS, (context, result, base) -> context.bricksBuilder(RecipeCategory.BUILDING_BLOCKS, result, Ingredient.of(base)))
        .put(BlockFamily.Variant.TILES, (context, result, base) -> context.tilesBuilder(RecipeCategory.BUILDING_BLOCKS, result, Ingredient.of(base)))
        .build();
    private static final Map<BlockFamily.Variant, RecipeProvider.FamilyStonecutterRecipeProvider> STONECUTTER_RECIPE_BUILDERS = ImmutableMap.<BlockFamily.Variant, RecipeProvider.FamilyStonecutterRecipeProvider>builder()
        .put(BlockFamily.Variant.SLAB, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 2))
        .put(BlockFamily.Variant.STAIRS, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .put(BlockFamily.Variant.BRICKS, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .put(BlockFamily.Variant.WALL, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.DECORATIONS, result, base, 1))
        .put(BlockFamily.Variant.CHISELED, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .put(BlockFamily.Variant.POLISHED, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .put(BlockFamily.Variant.CUT, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .put(BlockFamily.Variant.TILES, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .put(BlockFamily.Variant.COBBLED, (context, result, base) -> context.stonecutterResultFromBase(RecipeCategory.BUILDING_BLOCKS, result, base, 1))
        .build();
 
    protected RecipeProvider(HolderLookup.Provider registries, RecipeOutput output) {
        this.registries = registries;
        this.items = registries.lookupOrThrow(Registries.ITEM);
        this.output = output;
    }
 
    protected abstract void buildRecipes();
 
    protected void generateForEnabledBlockFamilies(FeatureFlagSet flagSet) {
        BlockFamilies.getAllFamilies().forEach(family -> this.generateRecipes(family, flagSet));
    }
 
    protected void oneToOneConversionRecipe(ItemLike product, ItemLike resource, @Nullable String group) {
        this.oneToOneConversionRecipe(product, resource, group, 1);
    }
 
    protected void oneToOneConversionRecipe(ItemLike product, ItemLike resource, @Nullable String group, int productCount) {
        this.shapeless(RecipeCategory.MISC, product, productCount)
            .requires(resource)
            .group(group)
            .unlockedBy(getHasName(resource), this.has(resource))
            .save(this.output, getConversionRecipeName(product, resource));
    }
 
    protected void oreSmelting(
        List<ItemLike> smeltables,
        RecipeCategory craftingCategory,
        CookingBookCategory cookingCategory,
        ItemLike result,
        float experience,
        int cookingTime,
        String group
    ) {
        this.oreCooking(SmeltingRecipe::new, smeltables, craftingCategory, cookingCategory, result, experience, cookingTime, group, "_from_smelting");
    }
 
    protected void oreBlasting(
        List<ItemLike> smeltables,
        RecipeCategory craftingCategory,
        CookingBookCategory cookingCategory,
        ItemLike result,
        float experience,
        int cookingTime,
        String group
    ) {
        this.oreCooking(BlastingRecipe::new, smeltables, craftingCategory, cookingCategory, result, experience, cookingTime, group, "_from_blasting");
    }
 
    private <T extends AbstractCookingRecipe> void oreCooking(
        AbstractCookingRecipe.Factory<T> factory,
        List<ItemLike> smeltables,
        RecipeCategory craftingCategory,
        CookingBookCategory cookingCategory,
        ItemLike result,
        float experience,
        int cookingTime,
        String group,
        String fromDesc
    ) {
        for (ItemLike item : smeltables) {
            SimpleCookingRecipeBuilder.generic(Ingredient.of(item), craftingCategory, cookingCategory, result, experience, cookingTime, factory)
                .group(group)
                .unlockedBy(getHasName(item), this.has(item))
                .save(this.output, getItemName(result) + fromDesc + "_" + getItemName(item));
        }
    }
 
    protected void netheriteSmithing(Item base, RecipeCategory category, Item result) {
        SmithingTransformRecipeBuilder.smithing(
                Ingredient.of(Items.NETHERITE_UPGRADE_SMITHING_TEMPLATE), Ingredient.of(base), this.tag(ItemTags.NETHERITE_TOOL_MATERIALS), category, result
            )
            .unlocks("has_netherite_ingot", this.has(ItemTags.NETHERITE_TOOL_MATERIALS))
            .save(this.output, getItemName(result) + "_smithing");
    }
 
    protected void trimSmithing(Item trimTemplate, ResourceKey<TrimPattern> patternId, ResourceKey<Recipe<?>> id) {
        Holder.Reference<TrimPattern> pattern = this.registries.lookupOrThrow(Registries.TRIM_PATTERN).getOrThrow(patternId);
        SmithingTrimRecipeBuilder.smithingTrim(
                Ingredient.of(trimTemplate), this.tag(ItemTags.TRIMMABLE_ARMOR), this.tag(ItemTags.TRIM_MATERIALS), pattern, RecipeCategory.MISC
            )
            .unlocks("has_smithing_trim_template", this.has(trimTemplate))
            .save(this.output, id);
    }
 
    protected void twoByTwoPacker(RecipeCategory category, ItemLike result, ItemLike ingredient) {
        this.shaped(category, result, 1)
            .define('#', ingredient)
            .pattern("##")
            .pattern("##")
            .unlockedBy(getHasName(ingredient), this.has(ingredient))
            .save(this.output);
    }
 
    protected void threeByThreePacker(RecipeCategory category, ItemLike result, ItemLike ingredient, String unlockedBy) {
        this.shapeless(category, result).requires(ingredient, 9).unlockedBy(unlockedBy, this.has(ingredient)).save(this.output);
    }
 
    protected void threeByThreePacker(RecipeCategory category, ItemLike result, ItemLike ingredient) {
        this.threeByThreePacker(category, result, ingredient, getHasName(ingredient));
    }
 
    protected void planksFromLog(ItemLike result, TagKey<Item> logs, int count) {
        this.shapeless(RecipeCategory.BUILDING_BLOCKS, result, count).requires(logs).group("planks").unlockedBy("has_log", this.has(logs)).save(this.output);
    }
 
    protected void planksFromLogs(ItemLike result, TagKey<Item> logs, int count) {
        this.shapeless(RecipeCategory.BUILDING_BLOCKS, result, count).requires(logs).group("planks").unlockedBy("has_logs", this.has(logs)).save(this.output);
    }
 
    protected void woodFromLogs(ItemLike result, ItemLike log) {
        this.shaped(RecipeCategory.BUILDING_BLOCKS, result, 3)
            .define('#', log)
            .pattern("##")
            .pattern("##")
            .group("bark")
            .unlockedBy("has_log", this.has(log))
            .save(this.output);
    }
 
    protected void woodenBoat(ItemLike result, ItemLike planks) {
        this.shaped(RecipeCategory.TRANSPORTATION, result)
            .define('#', planks)
            .pattern("# #")
            .pattern("###")
            .group("boat")
            .unlockedBy("in_water", insideOf(Blocks.WATER))
            .save(this.output);
    }
 
    protected void chestBoat(ItemLike chestBoat, ItemLike boat) {
        this.shapeless(RecipeCategory.TRANSPORTATION, chestBoat)
            .requires(Blocks.CHEST)
            .requires(boat)
            .group("chest_boat")
            .unlockedBy("has_boat", this.has(ItemTags.BOATS))
            .save(this.output);
    }
 
    private RecipeBuilder buttonBuilder(ItemLike result, Ingredient base) {
        return this.shapeless(RecipeCategory.REDSTONE, result).requires(base);
    }
 
    protected RecipeBuilder doorBuilder(ItemLike result, Ingredient base) {
        return this.shaped(RecipeCategory.REDSTONE, result, 3).define('#', base).pattern("##").pattern("##").pattern("##");
    }
 
    private RecipeBuilder fenceBuilder(ItemLike result, Ingredient base) {
        int count = result == Blocks.NETHER_BRICK_FENCE ? 6 : 3;
        Item base2 = result == Blocks.NETHER_BRICK_FENCE ? Items.NETHER_BRICK : Items.STICK;
        return this.shaped(RecipeCategory.DECORATIONS, result, count).define('W', base).define('#', base2).pattern("W#W").pattern("W#W");
    }
 
    private RecipeBuilder fenceGateBuilder(ItemLike result, Ingredient planks) {
        return this.shaped(RecipeCategory.REDSTONE, result).define('#', Items.STICK).define('W', planks).pattern("#W#").pattern("#W#");
    }
 
    protected void pressurePlate(ItemLike result, ItemLike base) {
        this.pressurePlateBuilder(RecipeCategory.REDSTONE, result, Ingredient.of(base)).unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    private RecipeBuilder pressurePlateBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result).define('#', base).pattern("##");
    }
 
    protected void slab(RecipeCategory category, ItemLike result, ItemLike base) {
        this.slabBuilder(category, result, Ingredient.of(base)).unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    protected void shelf(ItemLike result, ItemLike strippedLogs) {
        this.shaped(RecipeCategory.DECORATIONS, result, 6)
            .define('#', strippedLogs)
            .pattern("###")
            .pattern("   ")
            .pattern("###")
            .group("shelf")
            .unlockedBy(getHasName(strippedLogs), this.has(strippedLogs))
            .save(this.output);
    }
 
    protected RecipeBuilder slabBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result, 6).define('#', base).pattern("###");
    }
 
    protected RecipeBuilder stairBuilder(ItemLike result, Ingredient base) {
        return this.shaped(RecipeCategory.BUILDING_BLOCKS, result, 4).define('#', base).pattern("#  ").pattern("## ").pattern("###");
    }
 
    protected RecipeBuilder trapdoorBuilder(ItemLike result, Ingredient base) {
        return this.shaped(RecipeCategory.REDSTONE, result, 2).define('#', base).pattern("###").pattern("###");
    }
 
    private RecipeBuilder signBuilder(ItemLike result, Ingredient planks) {
        return this.shaped(RecipeCategory.DECORATIONS, result, 3)
            .group("sign")
            .define('#', planks)
            .define('X', Items.STICK)
            .pattern("###")
            .pattern("###")
            .pattern(" X ");
    }
 
    protected void hangingSign(ItemLike result, ItemLike ingredient) {
        this.shaped(RecipeCategory.DECORATIONS, result, 6)
            .group("hanging_sign")
            .define('#', ingredient)
            .define('X', Items.IRON_CHAIN)
            .pattern("X X")
            .pattern("###")
            .pattern("###")
            .unlockedBy("has_stripped_logs", this.has(ingredient))
            .save(this.output);
    }
 
    protected void colorItemWithDye(List<Item> dyes, List<Item> items, String groupName, RecipeCategory category) {
        this.colorWithDye(dyes, items, null, groupName, category);
    }
 
    protected void colorWithDye(List<Item> dyes, List<Item> dyedItems, @Nullable Item uncoloredItem, String groupName, RecipeCategory category) {
        for (int dyeIndex = 0; dyeIndex < dyes.size(); dyeIndex++) {
            Item dye = dyes.get(dyeIndex);
            Item dyedItem = dyedItems.get(dyeIndex);
            Stream<Item> sourceItems = dyedItems.stream().filter(b -> !b.equals(dyedItem));
            if (uncoloredItem != null) {
                sourceItems = Stream.concat(sourceItems, Stream.of(uncoloredItem));
            }
 
            this.shapeless(category, dyedItem)
                .requires(dye)
                .requires(Ingredient.of(sourceItems))
                .group(groupName)
                .unlockedBy("has_needed_dye", this.has(dye))
                .save(this.output, "dye_" + getItemName(dyedItem));
        }
    }
 
    protected void carpet(ItemLike result, ItemLike sourceItem) {
        this.shaped(RecipeCategory.DECORATIONS, result, 3)
            .define('#', sourceItem)
            .pattern("##")
            .group("carpet")
            .unlockedBy(getHasName(sourceItem), this.has(sourceItem))
            .save(this.output);
    }
 
    protected void bedFromPlanksAndWool(ItemLike result, ItemLike wool) {
        this.shaped(RecipeCategory.DECORATIONS, result)
            .define('#', wool)
            .define('X', ItemTags.PLANKS)
            .pattern("###")
            .pattern("XXX")
            .group("bed")
            .unlockedBy(getHasName(wool), this.has(wool))
            .save(this.output);
    }
 
    protected void banner(ItemLike result, ItemLike wool) {
        this.shaped(RecipeCategory.DECORATIONS, result)
            .define('#', wool)
            .define('|', Items.STICK)
            .pattern("###")
            .pattern("###")
            .pattern(" | ")
            .group("banner")
            .unlockedBy(getHasName(wool), this.has(wool))
            .save(this.output);
        SpecialRecipeBuilder.special(() -> new BannerDuplicateRecipe(Ingredient.of(result), new ItemStackTemplate(result.asItem())))
            .save(this.output, getItemName(result) + "_duplicate");
    }
 
    protected void stainedGlassFromGlassAndDye(ItemLike result, ItemLike dye) {
        this.shaped(RecipeCategory.BUILDING_BLOCKS, result, 8)
            .define('#', Blocks.GLASS)
            .define('X', dye)
            .pattern("###")
            .pattern("#X#")
            .pattern("###")
            .group("stained_glass")
            .unlockedBy("has_glass", this.has(Blocks.GLASS))
            .save(this.output);
    }
 
    protected void dryGhast(ItemLike result) {
        this.shaped(RecipeCategory.BUILDING_BLOCKS, result, 1)
            .define('#', Items.GHAST_TEAR)
            .define('X', Items.SOUL_SAND)
            .pattern("###")
            .pattern("#X#")
            .pattern("###")
            .group("dry_ghast")
            .unlockedBy(getHasName(Items.GHAST_TEAR), this.has(Items.GHAST_TEAR))
            .save(this.output);
    }
 
    protected void harness(ItemLike result, ItemLike wool) {
        this.shaped(RecipeCategory.COMBAT, result)
            .define('#', wool)
            .define('G', Items.GLASS)
            .define('L', Items.LEATHER)
            .pattern("LLL")
            .pattern("G#G")
            .group("harness")
            .unlockedBy("has_dried_ghast", this.has(Blocks.DRIED_GHAST))
            .save(this.output);
    }
 
    protected void stainedGlassPaneFromStainedGlass(ItemLike result, ItemLike stainedGlass) {
        this.shaped(RecipeCategory.DECORATIONS, result, 16)
            .define('#', stainedGlass)
            .pattern("###")
            .pattern("###")
            .group("stained_glass_pane")
            .unlockedBy("has_glass", this.has(stainedGlass))
            .save(this.output);
    }
 
    protected void stainedGlassPaneFromGlassPaneAndDye(ItemLike result, ItemLike dye) {
        this.shaped(RecipeCategory.DECORATIONS, result, 8)
            .define('#', Blocks.GLASS_PANE)
            .define('$', dye)
            .pattern("###")
            .pattern("#$#")
            .pattern("###")
            .group("stained_glass_pane")
            .unlockedBy("has_glass_pane", this.has(Blocks.GLASS_PANE))
            .unlockedBy(getHasName(dye), this.has(dye))
            .save(this.output, getConversionRecipeName(result, Blocks.GLASS_PANE));
    }
 
    protected void coloredTerracottaFromTerracottaAndDye(ItemLike result, ItemLike dye) {
        this.shaped(RecipeCategory.BUILDING_BLOCKS, result, 8)
            .define('#', Blocks.TERRACOTTA)
            .define('X', dye)
            .pattern("###")
            .pattern("#X#")
            .pattern("###")
            .group("stained_terracotta")
            .unlockedBy("has_terracotta", this.has(Blocks.TERRACOTTA))
            .save(this.output);
    }
 
    protected void concretePowder(ItemLike result, ItemLike dye) {
        this.shapeless(RecipeCategory.BUILDING_BLOCKS, result, 8)
            .requires(dye)
            .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 result, ItemLike dye) {
        this.shapeless(RecipeCategory.DECORATIONS, result)
            .requires(Blocks.CANDLE)
            .requires(dye)
            .group("dyed_candle")
            .unlockedBy(getHasName(dye), this.has(dye))
            .save(this.output);
    }
 
    protected void wall(RecipeCategory category, ItemLike result, ItemLike base) {
        this.wallBuilder(category, result, Ingredient.of(base)).unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    private RecipeBuilder wallBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result, 6).define('#', base).pattern("###").pattern("###");
    }
 
    private RecipeBuilder bricksBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result, 4).define('#', base).pattern("##").pattern("##");
    }
 
    private RecipeBuilder tilesBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result, 4).define('#', base).pattern("##").pattern("##");
    }
 
    protected void polished(RecipeCategory category, ItemLike result, ItemLike base) {
        this.polishedBuilder(category, result, Ingredient.of(base)).unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    private RecipeBuilder polishedBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result, 4).define('S', base).pattern("SS").pattern("SS");
    }
 
    protected void cut(RecipeCategory category, ItemLike result, ItemLike base) {
        this.cutBuilder(category, result, Ingredient.of(base)).unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    private ShapedRecipeBuilder cutBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result, 4).define('#', base).pattern("##").pattern("##");
    }
 
    protected void chiseled(RecipeCategory category, ItemLike result, ItemLike base) {
        this.chiseledBuilder(category, result, Ingredient.of(base)).unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    protected void mosaicBuilder(RecipeCategory category, ItemLike result, ItemLike base) {
        this.shaped(category, result).define('#', base).pattern("#").pattern("#").unlockedBy(getHasName(base), this.has(base)).save(this.output);
    }
 
    protected ShapedRecipeBuilder chiseledBuilder(RecipeCategory category, ItemLike result, Ingredient base) {
        return this.shaped(category, result).define('#', base).pattern("#").pattern("#");
    }
 
    protected void stonecutterResultFromBase(RecipeCategory category, ItemLike result, ItemLike base) {
        this.stonecutterResultFromBase(category, result, base, 1);
    }
 
    protected void stonecutterResultFromBase(RecipeCategory category, ItemLike result, ItemLike base, int count) {
        SingleItemRecipeBuilder.stonecutting(Ingredient.of(base), category, result, count)
            .unlockedBy(getHasName(base), this.has(base))
            .save(this.output, getConversionRecipeName(result, base) + "_stonecutting");
    }
 
    private void smeltingResultFromBase(ItemLike result, ItemLike base) {
        SimpleCookingRecipeBuilder.smelting(Ingredient.of(base), RecipeCategory.BUILDING_BLOCKS, CookingBookCategory.BLOCKS, result, 0.1F, 200)
            .unlockedBy(getHasName(base), this.has(base))
            .save(this.output);
    }
 
    protected void nineBlockStorageRecipes(RecipeCategory unpackedFormCategory, ItemLike unpackedForm, RecipeCategory packedFormCategory, ItemLike packedForm) {
        this.nineBlockStorageRecipes(
            unpackedFormCategory, unpackedForm, packedFormCategory, packedForm, getSimpleRecipeName(packedForm), null, getSimpleRecipeName(unpackedForm), null
        );
    }
 
    protected void nineBlockStorageRecipesWithCustomPacking(
        RecipeCategory unpackedFormCategory,
        ItemLike unpackedForm,
        RecipeCategory packedFormCategory,
        ItemLike packedForm,
        String packingRecipeId,
        String packingRecipeGroup
    ) {
        this.nineBlockStorageRecipes(
            unpackedFormCategory, unpackedForm, packedFormCategory, packedForm, packingRecipeId, packingRecipeGroup, getSimpleRecipeName(unpackedForm), null
        );
    }
 
    protected void nineBlockStorageRecipesRecipesWithCustomUnpacking(
        RecipeCategory unpackedFormCategory,
        ItemLike unpackedForm,
        RecipeCategory packedFormCategory,
        ItemLike packedForm,
        String unpackingRecipeId,
        String unpackingRecipeGroup
    ) {
        this.nineBlockStorageRecipes(
            unpackedFormCategory, unpackedForm, packedFormCategory, packedForm, getSimpleRecipeName(packedForm), null, unpackingRecipeId, unpackingRecipeGroup
        );
    }
 
    private void nineBlockStorageRecipes(
        RecipeCategory unpackedFormCategory,
        ItemLike unpackedForm,
        RecipeCategory packedFormCategory,
        ItemLike packedForm,
        String packingRecipeId,
        @Nullable String packingRecipeGroup,
        String unpackingRecipeId,
        @Nullable String unpackingRecipeGroup
    ) {
        this.shapeless(unpackedFormCategory, unpackedForm, 9)
            .requires(packedForm)
            .group(unpackingRecipeGroup)
            .unlockedBy(getHasName(packedForm), this.has(packedForm))
            .save(this.output, ResourceKey.create(Registries.RECIPE, Identifier.parse(unpackingRecipeId)));
        this.shaped(packedFormCategory, packedForm)
            .define('#', unpackedForm)
            .pattern("###")
            .pattern("###")
            .pattern("###")
            .group(packingRecipeGroup)
            .unlockedBy(getHasName(unpackedForm), this.has(unpackedForm))
            .save(this.output, ResourceKey.create(Registries.RECIPE, Identifier.parse(packingRecipeId)));
    }
 
    protected void copySmithingTemplate(ItemLike smithingTemplate, ItemLike baseMaterial) {
        this.shaped(RecipeCategory.MISC, smithingTemplate, 2)
            .define('#', Items.DIAMOND)
            .define('C', baseMaterial)
            .define('S', smithingTemplate)
            .pattern("#S#")
            .pattern("#C#")
            .pattern("###")
            .unlockedBy(getHasName(smithingTemplate), this.has(smithingTemplate))
            .save(this.output);
    }
 
    protected void copySmithingTemplate(ItemLike smithingTemplate, Ingredient baseMaterials) {
        this.shaped(RecipeCategory.MISC, smithingTemplate, 2)
            .define('#', Items.DIAMOND)
            .define('C', baseMaterials)
            .define('S', smithingTemplate)
            .pattern("#S#")
            .pattern("#C#")
            .pattern("###")
            .unlockedBy(getHasName(smithingTemplate), this.has(smithingTemplate))
            .save(this.output);
    }
 
    protected <T extends AbstractCookingRecipe> void cookRecipes(String source, AbstractCookingRecipe.Factory<T> factory, int cookingTime) {
        this.simpleCookingRecipe(source, factory, cookingTime, Items.BEEF, Items.COOKED_BEEF, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.CHICKEN, Items.COOKED_CHICKEN, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.COD, Items.COOKED_COD, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.KELP, Items.DRIED_KELP, 0.1F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.SALMON, Items.COOKED_SALMON, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.MUTTON, Items.COOKED_MUTTON, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.PORKCHOP, Items.COOKED_PORKCHOP, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.POTATO, Items.BAKED_POTATO, 0.35F);
        this.simpleCookingRecipe(source, factory, cookingTime, Items.RABBIT, Items.COOKED_RABBIT, 0.35F);
    }
 
    private <T extends AbstractCookingRecipe> void simpleCookingRecipe(
        String source, AbstractCookingRecipe.Factory<T> factory, int cookingTime, ItemLike base, ItemLike result, float experience
    ) {
        SimpleCookingRecipeBuilder.generic(Ingredient.of(base), RecipeCategory.FOOD, CookingBookCategory.FOOD, result, experience, cookingTime, factory)
            .unlockedBy(getHasName(base), this.has(base))
            .save(this.output, getItemName(result) + "_from_" + source);
    }
 
    protected void waxRecipes(FeatureFlagSet flagSet) {
        HoneycombItem.WAXABLES
            .get()
            .forEach(
                (block, waxedBlock) -> {
                    if (waxedBlock.requiredFeatures().isSubsetOf(flagSet)) {
                        Pair<RecipeCategory, String> pair = HoneycombItem.WAXED_RECIPES
                            .getOrDefault(waxedBlock, Pair.of(RecipeCategory.BUILDING_BLOCKS, getItemName(waxedBlock)));
                        RecipeCategory recipeCategory = pair.getFirst();
                        String group = pair.getSecond();
                        this.shapeless(recipeCategory, waxedBlock)
                            .requires(block)
                            .requires(Items.HONEYCOMB)
                            .group(group)
                            .unlockedBy(getHasName(block), this.has(block))
                            .save(this.output, getConversionRecipeName(waxedBlock, Items.HONEYCOMB));
                    }
                }
            );
    }
 
    protected void grate(Block grateBlock, Block material) {
        this.shaped(RecipeCategory.BUILDING_BLOCKS, grateBlock, 4)
            .define('M', material)
            .pattern(" M ")
            .pattern("M M")
            .pattern(" M ")
            .group(getItemName(grateBlock))
            .unlockedBy(getHasName(material), this.has(material))
            .save(this.output);
    }
 
    protected void copperBulb(Block copperBulb, Block copperMaterial) {
        this.shaped(RecipeCategory.REDSTONE, copperBulb, 4)
            .define('C', copperMaterial)
            .define('R', Items.REDSTONE)
            .define('B', Items.BLAZE_ROD)
            .pattern(" C ")
            .pattern("CBC")
            .pattern(" R ")
            .unlockedBy(getHasName(copperMaterial), this.has(copperMaterial))
            .group(getItemName(copperBulb))
            .save(this.output);
    }
 
    protected void waxedChiseled(Block result, Block material) {
        this.shaped(RecipeCategory.BUILDING_BLOCKS, result)
            .define('M', material)
            .pattern(" M ")
            .pattern(" M ")
            .group(getItemName(result))
            .unlockedBy(getHasName(material), this.has(material))
            .save(this.output);
    }
 
    protected void suspiciousStew(Item item, SuspiciousEffectHolder effectHolder) {
        ItemStackTemplate stew = new ItemStackTemplate(
            Items.SUSPICIOUS_STEW, DataComponentPatch.builder().set(DataComponents.SUSPICIOUS_STEW_EFFECTS, effectHolder.getSuspiciousEffects()).build()
        );
        this.shapeless(RecipeCategory.FOOD, stew)
            .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(stew.item().value()) + "_from_" + getItemName(item));
    }
 
    protected void dyedItem(Item target, String group) {
        CustomCraftingRecipeBuilder.customCrafting(
                RecipeCategory.MISC,
                (commonInfo, bookInfo) -> new DyeRecipe(commonInfo, bookInfo, Ingredient.of(target), this.tag(ItemTags.DYES), new ItemStackTemplate(target))
            )
            .unlockedBy(getHasName(target), this.has(target))
            .group(group)
            .save(this.output, getItemName(target) + "_dyed");
    }
 
    protected void dyedShulkerBoxRecipe(Item dye, Item dyedResult) {
        TransmuteRecipeBuilder.transmute(RecipeCategory.DECORATIONS, this.tag(ItemTags.SHULKER_BOXES), Ingredient.of(dye), dyedResult)
            .group("shulker_box_dye")
            .unlockedBy("has_shulker_box", this.has(ItemTags.SHULKER_BOXES))
            .save(this.output);
    }
 
    protected void dyedBundleRecipe(Item dye, Item dyedResult) {
        TransmuteRecipeBuilder.transmute(RecipeCategory.TOOLS, this.tag(ItemTags.BUNDLES), Ingredient.of(dye), dyedResult)
            .group("bundle_dye")
            .unlockedBy(getHasName(dye), this.has(dye))
            .save(this.output);
    }
 
    protected void generateRecipes(BlockFamily family, FeatureFlagSet flagSet) {
        family.getVariants().forEach((variant, result) -> {
            if (result.requiredFeatures().isSubsetOf(flagSet)) {
                if (family.shouldGenerateCraftingRecipe()) {
                    ItemLike base = this.getBaseBlockForCrafting(family, variant);
                    this.generateCraftingRecipe(family, variant, result, base);
                    if (variant == BlockFamily.Variant.CRACKED) {
                        this.smeltingResultFromBase(result, base);
                    }
                }
 
                if (family.shouldGenerateStonecutterRecipe()) {
                    Block base = family.getBaseBlock();
                    this.generateStonecutterRecipe(family, variant, base);
                }
            }
        });
    }
 
    private void generateCraftingRecipe(BlockFamily family, BlockFamily.Variant variant, Block result, ItemLike base) {
        RecipeProvider.FamilyCraftingRecipeProvider recipeFunction = SHAPE_BUILDERS.get(variant);
        if (recipeFunction != null) {
            RecipeBuilder builder = recipeFunction.create(this, result, base);
            family.getRecipeGroupPrefix()
                .ifPresent(prefix -> builder.group(prefix + (variant == BlockFamily.Variant.CUT ? "" : "_" + variant.getRecipeGroup())));
            builder.unlockedBy(family.getRecipeUnlockedBy().orElseGet(() -> getHasName(base)), this.has(base));
            builder.save(this.output);
        }
    }
 
    private void generateStonecutterRecipe(BlockFamily family, BlockFamily.Variant variant, Block base) {
        RecipeProvider.FamilyStonecutterRecipeProvider recipeFunction = STONECUTTER_RECIPE_BUILDERS.get(variant);
        if (recipeFunction != null) {
            recipeFunction.create(this, family.get(variant), base);
        }
 
        if (variant == BlockFamily.Variant.POLISHED
            || variant == BlockFamily.Variant.CUT
            || variant == BlockFamily.Variant.BRICKS
            || variant == BlockFamily.Variant.TILES
            || variant == BlockFamily.Variant.COBBLED) {
            BlockFamily childVariantFamily = BlockFamilies.getFamily(family.get(variant));
            if (childVariantFamily != null) {
                childVariantFamily.getVariants().forEach((childVariant, r) -> this.generateStonecutterRecipe(childVariantFamily, childVariant, base));
            }
        }
    }
 
    private Block getBaseBlockForCrafting(BlockFamily family, BlockFamily.Variant variant) {
        if (variant == BlockFamily.Variant.CHISELED) {
            if (!family.getVariants().containsKey(BlockFamily.Variant.SLAB)) {
                throw new IllegalStateException("Slab is not defined for the family.");
            } else {
                return family.get(BlockFamily.Variant.SLAB);
            }
        } else {
            return family.getBaseBlock();
        }
    }
 
    private static Criterion<EnterBlockTrigger.TriggerInstance> insideOf(Block block) {
        return CriteriaTriggers.ENTER_BLOCK
            .createCriterion(new EnterBlockTrigger.TriggerInstance(Optional.empty(), Optional.of(block.builtInRegistryHolder()), Optional.empty()));
    }
 
    protected Criterion<BredAnimalsTrigger.TriggerInstance> bredAnimal() {
        return CriteriaTriggers.BRED_ANIMALS
            .createCriterion(new BredAnimalsTrigger.TriggerInstance(Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()));
    }
 
    private Criterion<InventoryChangeTrigger.TriggerInstance> has(MinMaxBounds.Ints count, ItemLike item) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(this.items, item).withCount(count));
    }
 
    protected Criterion<InventoryChangeTrigger.TriggerInstance> has(ItemLike item) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(this.items, item));
    }
 
    protected Criterion<InventoryChangeTrigger.TriggerInstance> has(TagKey<Item> tag) {
        return inventoryTrigger(ItemPredicate.Builder.item().of(this.items, tag));
    }
 
    private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryTrigger(ItemPredicate.Builder... predicates) {
        return inventoryTrigger(Arrays.stream(predicates).map(ItemPredicate.Builder::build).toArray(ItemPredicate[]::new));
    }
 
    private static Criterion<InventoryChangeTrigger.TriggerInstance> inventoryTrigger(ItemPredicate... predicates) {
        return CriteriaTriggers.INVENTORY_CHANGED
            .createCriterion(
                new InventoryChangeTrigger.TriggerInstance(Optional.empty(), InventoryChangeTrigger.TriggerInstance.Slots.ANY, List.of(predicates))
            );
    }
 
    protected static String getHasName(ItemLike baseBlock) {
        return "has_" + getItemName(baseBlock);
    }
 
    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 product, ItemLike material) {
        return getItemName(product) + "_from_" + getItemName(material);
    }
 
    protected static String getSmeltingRecipeName(ItemLike product) {
        return getItemName(product) + "_from_smelting";
    }
 
    protected static String getBlastingRecipeName(ItemLike product) {
        return getItemName(product) + "_from_blasting";
    }
 
    protected Ingredient tag(TagKey<Item> id) {
        return Ingredient.of(this.items.getOrThrow(id));
    }
 
    protected ShapedRecipeBuilder shaped(RecipeCategory category, ItemLike item) {
        return ShapedRecipeBuilder.shaped(this.items, category, item);
    }
 
    protected ShapedRecipeBuilder shaped(RecipeCategory category, ItemLike item, int count) {
        return ShapedRecipeBuilder.shaped(this.items, category, item, count);
    }
 
    protected ShapelessRecipeBuilder shapeless(RecipeCategory category, ItemStackTemplate result) {
        return ShapelessRecipeBuilder.shapeless(this.items, category, result);
    }
 
    protected ShapelessRecipeBuilder shapeless(RecipeCategory category, ItemLike item) {
        return ShapelessRecipeBuilder.shapeless(this.items, category, item);
    }
 
    protected ShapelessRecipeBuilder shapeless(RecipeCategory category, ItemLike item, int count) {
        return ShapelessRecipeBuilder.shapeless(this.items, category, item, count);
    }
 
    @FunctionalInterface
    private interface FamilyCraftingRecipeProvider {
        RecipeBuilder create(RecipeProvider context, ItemLike result, ItemLike base);
    }
 
    @FunctionalInterface
    private interface FamilyStonecutterRecipeProvider {
        void create(RecipeProvider context, ItemLike result, ItemLike base);
    }
 
    protected abstract static class Runner implements DataProvider {
        private final PackOutput packOutput;
        private final CompletableFuture<HolderLookup.Provider> registries;
 
        protected Runner(PackOutput packOutput, CompletableFuture<HolderLookup.Provider> registries) {
            this.packOutput = packOutput;
            this.registries = registries;
        }
 
        @Override
        public final CompletableFuture<?> run(CachedOutput cache) {
            return this.registries
                .thenCompose(
                    registries -> {
                        final PackOutput.PathProvider recipePathProvider = this.packOutput.createRegistryElementsPathProvider(Registries.RECIPE);
                        final PackOutput.PathProvider advancementPathProvider = this.packOutput.createRegistryElementsPathProvider(Registries.ADVANCEMENT);
                        final Set<ResourceKey<Recipe<?>>> allRecipes = Sets.newHashSet();
                        final List<CompletableFuture<?>> tasks = new ArrayList<>();
                        RecipeOutput recipeOutput = new RecipeOutput() {
                            {
                                Objects.requireNonNull(Runner.this);
                            }
 
                            @Override
                            public void accept(ResourceKey<Recipe<?>> id, Recipe<?> recipe, @Nullable AdvancementHolder advancementHolder) {
                                if (!allRecipes.add(id)) {
                                    throw new IllegalStateException("Duplicate recipe " + id.identifier());
                                } else {
                                    this.saveRecipe(id, recipe);
                                    if (advancementHolder != null) {
                                        this.saveAdvancement(advancementHolder);
                                    }
                                }
                            }
 
                            @Override
                            public Advancement.Builder advancement() {
                                return Advancement.Builder.recipeAdvancement().parent(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT);
                            }
 
                            @Override
                            public void includeRootAdvancement() {
                                AdvancementHolder root = Advancement.Builder.recipeAdvancement()
                                    .addCriterion("impossible", CriteriaTriggers.IMPOSSIBLE.createCriterion(new ImpossibleTrigger.TriggerInstance()))
                                    .build(RecipeBuilder.ROOT_RECIPE_ADVANCEMENT);
                                this.saveAdvancement(root);
                            }
 
                            private void saveRecipe(ResourceKey<Recipe<?>> id, Recipe<?> recipe) {
                                tasks.add(DataProvider.saveStable(cache, registries, Recipe.CODEC, recipe, recipePathProvider.json(id.identifier())));
                            }
 
                            private void saveAdvancement(AdvancementHolder advancementHolder) {
                                tasks.add(
                                    DataProvider.saveStable(
                                        cache, registries, Advancement.CODEC, advancementHolder.value(), advancementPathProvider.json(advancementHolder.id())
                                    )
                                );
                            }
                        };
                        this.createRecipeProvider(registries, recipeOutput).buildRecipes();
                        return CompletableFuture.allOf(tasks.toArray(CompletableFuture[]::new));
                    }
                );
        }
 
        protected abstract RecipeProvider createRecipeProvider(HolderLookup.Provider registries, RecipeOutput output);
    }
}

引用的其他类