diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/MyRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/MyRecipesGenerator.java index dfd094f6a..930cd9443 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/MyRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/MyRecipesGenerator.java @@ -2,24 +2,25 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.recipe.*; -import dev.dubhe.anvilcraft.data.recipe.TagIngredient; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipePredicate; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItemIngredient; import dev.dubhe.anvilcraft.init.ModItems; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.nbt.IntTag; import net.minecraft.tags.BlockTags; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; -import java.util.List; import java.util.function.Consumer; public class MyRecipesGenerator extends FabricRecipeProvider { @@ -31,109 +32,57 @@ public MyRecipesGenerator(FabricDataOutput output) { public void buildRecipes(Consumer exporter) { VanillaRecipesGenerator.buildRecipes(exporter); // 铁砧物品处理 - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.ROYAL_STEEL_INGOT) - .requires(Items.IRON_INGOT) - .requires(Items.EMERALD) - .requires(Items.DIAMOND) - .requires(Items.AMETHYST_SHARD) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.CAULDRON) + .hasBlock(new Vec3(0.0, -2.0, 0.0), BlockTags.CAMPFIRES) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), Items.IRON_INGOT) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), Items.EMERALD) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), Items.DIAMOND) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), Items.AMETHYST_SHARD) + .spawnItem(new Vec3(0.0, -1.0, 0.0), ModItems.ROYAL_STEEL_INGOT) .unlockedBy(MyRecipesGenerator.hasItem(Items.IRON_INGOT), FabricRecipeProvider.has(Items.IRON_INGOT)) .unlockedBy(MyRecipesGenerator.hasItem(Items.EMERALD), FabricRecipeProvider.has(Items.EMERALD)) .unlockedBy(MyRecipesGenerator.hasItem(Items.DIAMOND), FabricRecipeProvider.has(Items.DIAMOND)) .unlockedBy(MyRecipesGenerator.hasItem(Items.AMETHYST_SHARD), FabricRecipeProvider.has(Items.AMETHYST_SHARD)) .save(exporter, AnvilCraft.of("craft_a_royal_steel_ingot")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.SMITHING_TABLE) - .requires(Items.ANCIENT_DEBRIS) - .result(ModItems.DEBRIS_SCRAP, 1) - .result(Items.ANCIENT_DEBRIS, 1) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.SMITHING_TABLE) + .hasItem(Items.ANCIENT_DEBRIS) + .spawnItem(ModItems.DEBRIS_SCRAP) .unlockedBy(MyRecipesGenerator.hasItem(Items.ANCIENT_DEBRIS), FabricRecipeProvider.has(Items.ANCIENT_DEBRIS)) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) .save(exporter); - TagIngredient ingredient = TagIngredient.of(TagIngredient.Value.of(Items.ELYTRA).with("Damage", IntTag.valueOf(0))); + ItemPredicate.Builder predicate = ItemPredicate.Builder.item().of(Items.ELYTRA) + .hasDurability(MinMaxBounds.Ints.atLeast(Items.ELYTRA.getMaxDamage())); + RecipePredicate hasItemIngredient = new HasItemIngredient(Vec3.ZERO, predicate.build()); ItemStack result = Items.ELYTRA.getDefaultInstance(); result.setDamageValue(432); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.SMITHING_TABLE) - .requires(ingredient) - .result(ModItems.ELYTRA_FRAME, 1) - .result(Items.PHANTOM_MEMBRANE, 1) - .result(result) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.SMITHING_TABLE) + .addPredicates(hasItemIngredient) + .spawnItem(ModItems.ELYTRA_FRAME) + .spawnItem(Items.PHANTOM_MEMBRANE) + .spawnItem(result) .unlockedBy(MyRecipesGenerator.hasItem(Items.ELYTRA), FabricRecipeProvider.has(Items.ELYTRA)) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.WATER_CAULDRON) - .requires(ModItems.SEED_OF_THE_SEA) - .result(ModItems.FRUIT_OF_THE_SEA) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.SEED_OF_THE_SEA), FabricRecipeProvider.has(ModItems.SEED_OF_THE_SEA)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.WATER_CAULDRON) - .requires(ModItems.SPONGE_GEMMULE) - .result(Items.WET_SPONGE) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.SPONGE_GEMMULE), FabricRecipeProvider.has(ModItems.SPONGE_GEMMULE)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.POWDER_SNOW_CAULDRON) - .requires(ModItems.SEED_OF_THE_SEA) - .result(ModItems.TEAR_OF_THE_SEA) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.SEED_OF_THE_SEA), FabricRecipeProvider.has(ModItems.SEED_OF_THE_SEA)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .requires(ModItems.FRUIT_OF_THE_SEA) - .result(ModItems.KERNEL_OF_THE_SEA) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.FRUIT_OF_THE_SEA), FabricRecipeProvider.has(ModItems.FRUIT_OF_THE_SEA)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .requires(Items.PRISMARINE_SHARD) - .requires(ModItems.TEAR_OF_THE_SEA) - .result(ModItems.BLADE_OF_THE_SEA) - .unlockedBy(MyRecipesGenerator.hasItem(Items.PRISMARINE_SHARD), FabricRecipeProvider.has(Items.PRISMARINE_SHARD)) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.TEAR_OF_THE_SEA), FabricRecipeProvider.has(ModItems.TEAR_OF_THE_SEA)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.SMITHING_TABLE) - .requires(ModItems.KERNEL_OF_THE_SEA) - .result(Items.PRISMARINE_SHARD) - .result(Items.HEART_OF_THE_SEA) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.SMITHING_TABLE) + .hasItemIngredient(ModItems.KERNEL_OF_THE_SEA) + .spawnItem(Items.HEART_OF_THE_SEA) + .spawnItem(Items.PRISMARINE_SHARD) .unlockedBy(MyRecipesGenerator.hasItem(ModItems.KERNEL_OF_THE_SEA), FabricRecipeProvider.has(ModItems.KERNEL_OF_THE_SEA)) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .requires(Items.SOUL_SOIL) - .requires(ModItems.NETHERITE_COIL) - .result(Items.ANCIENT_DEBRIS) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.SOUL_SOIL) + .hasItemIngredient(ModItems.NETHERITE_COIL) + .setBlock(Blocks.ANCIENT_DEBRIS) .unlockedBy(MyRecipesGenerator.hasItem(Items.SOUL_SOIL), FabricRecipeProvider.has(Items.SOUL_SOIL)) .unlockedBy(MyRecipesGenerator.hasItem(ModItems.NETHERITE_COIL), FabricRecipeProvider.has(ModItems.NETHERITE_COIL)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) .save(exporter); SmashRecipesGenerator.buildRecipes(exporter); CookingRecipesGenerator.buildRecipes(exporter); CompressRecipesGenerator.buildRecipes(exporter); StampingRecipesGenerator.buildRecipes(exporter); - BulgingRecipesGenerator.buildRecipes(exporter); + BulgingAndCrystallizeRecipesGenerator.buildRecipes(exporter); // 铁砧方块处理 SqueezeRecipesGenerator.buildRecipes(exporter); SmashBlockRecipesGenerator.buildRecipes(exporter); diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/BulgingAndCrystallizeRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/BulgingAndCrystallizeRecipesGenerator.java new file mode 100644 index 000000000..02f0e0086 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/BulgingAndCrystallizeRecipesGenerator.java @@ -0,0 +1,92 @@ +package dev.dubhe.anvilcraft.data.generator.recipe; + +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; +import dev.dubhe.anvilcraft.init.ModItems; +import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.minecraft.world.phys.Vec3; + +import java.util.function.Consumer; + +public abstract class BulgingAndCrystallizeRecipesGenerator { + private BulgingAndCrystallizeRecipesGenerator() { + } + + public static void buildRecipes(Consumer exporter) { + bulging(Items.DIRT, Items.CLAY, exporter); + bulging(Items.CRIMSON_FUNGUS, Items.NETHER_WART_BLOCK, exporter); + bulging(Items.WARPED_FUNGUS, Items.WARPED_WART_BLOCK, exporter); + bulging(Items.SPIDER_EYE, Items.FERMENTED_SPIDER_EYE, exporter); + bulging(Items.BRAIN_CORAL, Items.BRAIN_CORAL_BLOCK, exporter); + bulging(Items.BUBBLE_CORAL, Items.BUBBLE_CORAL_BLOCK, exporter); + bulging(Items.FIRE_CORAL, Items.FIRE_CORAL_BLOCK, exporter); + bulging(Items.HORN_CORAL, Items.HORN_CORAL_BLOCK, exporter); + bulging(Items.TUBE_CORAL, Items.TUBE_CORAL_BLOCK, exporter); + bulging(ModItems.FLOUR, ModItems.DOUGH, exporter); + bulging(ModItems.SEED_OF_THE_SEA, ModItems.FRUIT_OF_THE_SEA, exporter); + crystallize(ModItems.SEED_OF_THE_SEA, ModItems.TEAR_OF_THE_SEA, exporter); + bulging(ModItems.SPONGE_GEMMULE, Items.WET_SPONGE, exporter); + } + + public static void bulging(Item item, Item item1, Consumer exporter) { + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(item1) + .hasBlock(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), item) + .spawnItem(new Vec3(0.0, -1.0, 0.0), item1) + .setBlock(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) + .save(exporter, AnvilCraft.of("bulging/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_3")); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(item1) + .hasBlock(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), item) + .spawnItem(new Vec3(0.0, -1.0, 0.0), item1) + .setBlock(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) + .save(exporter, AnvilCraft.of("bulging/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_2")); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(item1) + .hasBlock(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), item) + .spawnItem(new Vec3(0.0, -1.0, 0.0), item1) + .setBlock(Blocks.CAULDRON) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) + .save(exporter, AnvilCraft.of("bulging/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_1")); + } + + public static void crystallize(Item item, Item item1, Consumer exporter) { + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(item1) + .hasBlock(Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), item) + .spawnItem(new Vec3(0.0, -1.0, 0.0), item1) + .setBlock(Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) + .save(exporter, AnvilCraft.of("crystallize/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_3")); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(item1) + .hasBlock(Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), item) + .spawnItem(new Vec3(0.0, -1.0, 0.0), item1) + .setBlock(Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) + .save(exporter, AnvilCraft.of("crystallize/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_2")); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(item1) + .hasBlock(Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) + .hasItemIngredient(new Vec3(0.0, -1.0, 0.0), item) + .spawnItem(new Vec3(0.0, -1.0, 0.0), item1) + .setBlock(Blocks.CAULDRON) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) + .save(exporter, AnvilCraft.of("crystallize/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_1")); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/BulgingRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/BulgingRecipesGenerator.java deleted file mode 100644 index 1eac28141..000000000 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/BulgingRecipesGenerator.java +++ /dev/null @@ -1,65 +0,0 @@ -package dev.dubhe.anvilcraft.data.generator.recipe; - -import dev.dubhe.anvilcraft.AnvilCraft; -import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.Component; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; -import dev.dubhe.anvilcraft.init.ModItems; -import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; -import net.minecraft.core.Direction; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.data.recipes.FinishedRecipe; -import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LayeredCauldronBlock; -import net.minecraft.world.level.block.piston.PistonBaseBlock; - -import java.util.function.Consumer; - -public abstract class BulgingRecipesGenerator { - private BulgingRecipesGenerator() { - } - - public static void buildRecipes(Consumer exporter) { - bulging(Items.DIRT, Items.CLAY, exporter); - bulging(Items.CRIMSON_FUNGUS, Items.NETHER_WART_BLOCK, exporter); - bulging(Items.WARPED_FUNGUS, Items.WARPED_WART_BLOCK, exporter); - bulging(Items.SPIDER_EYE, Items.FERMENTED_SPIDER_EYE, exporter); - bulging(Items.BRAIN_CORAL, Items.BRAIN_CORAL_BLOCK, exporter); - bulging(Items.BUBBLE_CORAL, Items.BUBBLE_CORAL_BLOCK, exporter); - bulging(Items.FIRE_CORAL, Items.FIRE_CORAL_BLOCK, exporter); - bulging(Items.HORN_CORAL, Items.HORN_CORAL_BLOCK, exporter); - bulging(Items.TUBE_CORAL, Items.TUBE_CORAL_BLOCK, exporter); - bulging(ModItems.FLOUR, ModItems.DOUGH, exporter); - } - - public static void bulging(Item item, Item item1, Consumer exporter) { - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, item1) - .requires(item) - .component(Component.of(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3))) - //.result(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) - .save(exporter, AnvilCraft.of("bulging/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_3")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, item1) - .requires(item) - .component(Component.of(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2))) - //.result(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) - .save(exporter, AnvilCraft.of("bulging/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_2")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, item1) - .requires(item) - .component(Component.of(Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1))) - //.result(Blocks.CAULDRON.defaultBlockState()) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) - .save(exporter, AnvilCraft.of("bulging/" + BuiltInRegistries.ITEM.getKey(item1).getPath() + "_1")); - } -} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompactionRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompactionRecipesGenerator.java index 9111694ad..72faeac5d 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompactionRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompactionRecipesGenerator.java @@ -2,7 +2,7 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.anvil.block.BlockAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.init.ModBlockTags; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.minecraft.core.registries.BuiltInRegistries; @@ -12,6 +12,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; @@ -32,17 +33,19 @@ public static void buildRecipes(Consumer exporter) { } public static void compaction(Block block, @NotNull Block block1, @NotNull Block block2, Consumer exporter) { - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.AIR.defaultBlockState(), block2.defaultBlockState()) - .component(block) - .component(block1) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlockIngredient(block) + .hasBlock(new Vec3(0.0, -2.0, 0.0), block1) + .setBlock(new Vec3(0.0, -2.0, 0.0), block2) .unlockedBy(MyRecipesGenerator.hasItem(block.asItem()), FabricRecipeProvider.has(block.asItem())) .save(exporter, AnvilCraft.of("smash_block/" + BuiltInRegistries.BLOCK.getKey(block).getPath() + "_and_" + BuiltInRegistries.BLOCK.getKey(block1).getPath() + "_2_" + BuiltInRegistries.BLOCK.getKey(block2).getPath())); } public static void compaction(TagKey block, @NotNull Block block1, @NotNull Block block2, Consumer exporter) { - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.AIR.defaultBlockState(), block2.defaultBlockState()) - .component(block) - .component(block1) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlockIngredient(block) + .hasBlock(new Vec3(0.0, -2.0, 0.0), block1) + .setBlock(new Vec3(0.0, -2.0, 0.0), block2) .unlockedBy(MyRecipesGenerator.hasItem(block1.asItem()), FabricRecipeProvider.has(block1.asItem())) .save(exporter, AnvilCraft.of("smash_block/" + block.location().getPath() + "_and_" + BuiltInRegistries.BLOCK.getKey(block1).getPath() + "_2_" + BuiltInRegistries.BLOCK.getKey(block2).getPath())); } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompressRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompressRecipesGenerator.java index 61b6a942e..257ecd81a 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompressRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CompressRecipesGenerator.java @@ -1,14 +1,11 @@ package dev.dubhe.anvilcraft.data.generator.recipe; -import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.init.ModItems; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.tags.BlockTags; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; @@ -19,29 +16,40 @@ private CompressRecipesGenerator() { } public static void buildRecipes(Consumer exporter) { - ItemAnvilRecipeBuilder.item(RecipeCategory.TOOLS, ModItems.INTERACT_MACHINE) - .requires(Items.ANVIL) - .requires(Items.DISPENSER) - .component(Blocks.CAULDRON) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.CAULDRON) + .unlockedBy(MyRecipesGenerator.hasItem(ModItems.FRUIT_OF_THE_SEA), FabricRecipeProvider.has(ModItems.FRUIT_OF_THE_SEA)) + .hasItemIngredient(ModItems.FRUIT_OF_THE_SEA) + .spawnItem(ModItems.KERNEL_OF_THE_SEA) + .save(exporter); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.CAULDRON) + .hasItemIngredient(Items.PRISMARINE_SHARD) + .hasItemIngredient(ModItems.TEAR_OF_THE_SEA) + .spawnItem(ModItems.BLADE_OF_THE_SEA) + .unlockedBy(MyRecipesGenerator.hasItem(Items.PRISMARINE_SHARD), FabricRecipeProvider.has(Items.PRISMARINE_SHARD)) + .unlockedBy(MyRecipesGenerator.hasItem(ModItems.TEAR_OF_THE_SEA), FabricRecipeProvider.has(ModItems.TEAR_OF_THE_SEA)) + .save(exporter); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.CAULDRON) + .hasItemIngredient(Items.ANVIL) + .hasItemIngredient(Items.DISPENSER) + .spawnItem(ModItems.INTERACT_MACHINE) .unlockedBy(MyRecipesGenerator.hasItem(Items.ANVIL), FabricRecipeProvider.has(Items.ANVIL)) .unlockedBy(MyRecipesGenerator.hasItem(Items.DISPENSER), FabricRecipeProvider.has(Items.DISPENSER)) .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.TOOLS, ModItems.AUTO_CRAFTER) - .requires(Items.ANVIL) - .requires(Items.CRAFTING_TABLE, 8) - .component(Blocks.CAULDRON) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.CAULDRON) + .hasItemIngredient(Items.ANVIL) + .hasItemIngredient(8, Items.CRAFTING_TABLE) + .spawnItem(ModItems.AUTO_CRAFTER) .unlockedBy(MyRecipesGenerator.hasItem(Items.ANVIL), FabricRecipeProvider.has(Items.ANVIL)) .unlockedBy(MyRecipesGenerator.hasItem(Items.DISPENSER), FabricRecipeProvider.has(Items.DISPENSER)) .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.TOOLS, Items.BONE_BLOCK) - .requires(Items.BONE, 3) - .component(Blocks.CAULDRON) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.CAULDRON) + .hasItemIngredient(3,Items.BONE) + .spawnItem(Items.BONE_BLOCK) .unlockedBy(MyRecipesGenerator.hasItem(Items.BONE), FabricRecipeProvider.has(Items.BONE)) .save(exporter); } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CookingRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CookingRecipesGenerator.java index 00c96618f..338e76a77 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CookingRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/CookingRecipesGenerator.java @@ -1,16 +1,16 @@ package dev.dubhe.anvilcraft.data.generator.recipe; -import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.init.ModItems; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.tags.BlockTags; +import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; import java.util.function.Consumer; @@ -19,83 +19,23 @@ private CookingRecipesGenerator() { } public static void buildRecipes(Consumer exporter) { - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .result(ModItems.FLOUR) - .requires(Items.WHEAT) - .component(Blocks.IRON_TRAPDOOR) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.IN) + AnvilRecipe.Builder.create(RecipeCategory.FOOD) + .hasBlock(Blocks.IRON_TRAPDOOR) + .hasItemIngredient(Items.WHEAT) + .spawnItem(new Vec3(0.0, -1.0, 0.0), ModItems.FLOUR) .unlockedBy(MyRecipesGenerator.hasItem(Items.WHEAT), FabricRecipeProvider.has(Items.WHEAT)) .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .result(ModItems.MEAT_STUFFING, 2) - .requires(Items.BEEF) - .component(Blocks.IRON_TRAPDOOR) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(Items.BEEF), FabricRecipeProvider.has(Items.BEEF)) - .save(exporter, AnvilCraft.of("meat_stuffing_1")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .result(ModItems.MEAT_STUFFING, 2) - .requires(Items.PORKCHOP) - .component(Blocks.IRON_TRAPDOOR) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(Items.PORKCHOP), FabricRecipeProvider.has(Items.PORKCHOP)) - .save(exporter, AnvilCraft.of("meat_stuffing_2")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.WATER_CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.BEEF_MUSHROOM_STEW) - .requires(ModItems.BEEF_MUSHROOM_STEW_RAW) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.BEEF_MUSHROOM_STEW_RAW), FabricRecipeProvider.has(ModItems.BEEF_MUSHROOM_STEW_RAW)) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.WATER_CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.DUMPLING, 4) - .requires(ModItems.DUMPLING_RAW, 4) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.DUMPLING_RAW), FabricRecipeProvider.has(ModItems.DUMPLING_RAW)) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.WATER_CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.SWEET_DUMPLING, 4) - .requires(ModItems.SWEET_DUMPLING_RAW, 4) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.SWEET_DUMPLING_RAW), FabricRecipeProvider.has(ModItems.SWEET_DUMPLING_RAW)) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.MEATBALLS, 4) - .requires(ModItems.MEATBALLS_RAW, 4) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.MEATBALLS_RAW), FabricRecipeProvider.has(ModItems.MEATBALLS_RAW)) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.UTUSAN) - .requires(ModItems.UTUSAN_RAW) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.UTUSAN_RAW), FabricRecipeProvider.has(ModItems.UTUSAN_RAW)) - .save(exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .component(Blocks.CAULDRON) - .component(BlockTags.CAMPFIRES) - .result(ModItems.SHENGJIAN, 4) - .requires(ModItems.SHENGJIAN_RAW, 4) - .location(ItemAnvilRecipe.Location.IN) - .resultLocation(ItemAnvilRecipe.Location.IN) - .unlockedBy(MyRecipesGenerator.hasItem(ModItems.SHENGJIAN_RAW), FabricRecipeProvider.has(ModItems.SHENGJIAN_RAW)) + cook(ModItems.BEEF_MUSHROOM_STEW_RAW, 1, ModItems.BEEF_MUSHROOM_STEW, 1, exporter); + cook(ModItems.UTUSAN_RAW, 1, ModItems.UTUSAN, 4, exporter); + } + + public static void cook(Item item, int count, Item item1, int count1, Consumer exporter) { + AnvilRecipe.Builder.create(RecipeCategory.FOOD) + .hasBlock(Blocks.CAULDRON) + .hasBlock(new Vec3(0.0, -2.0, 0.0), BlockTags.CAMPFIRES) + .hasItemIngredient(count, item) + .spawnItem(item1, count1) + .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) .save(exporter); } } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashBlockRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashBlockRecipesGenerator.java index 8ef42c8bd..a80141ead 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashBlockRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashBlockRecipesGenerator.java @@ -2,20 +2,13 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.anvil.block.BlockAnvilRecipeBuilder; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; -import dev.dubhe.anvilcraft.init.ModBlocks; -import dev.dubhe.anvilcraft.init.ModItems; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LayeredCauldronBlock; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; @@ -41,8 +34,9 @@ public static void buildRecipes(Consumer exporter) { } public static void smash(Block block, @NotNull Block block1, Consumer exporter) { - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, block1.defaultBlockState()) - .component(block) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(block) + .setBlock(block1) .unlockedBy(MyRecipesGenerator.hasItem(block.asItem()), FabricRecipeProvider.has(block.asItem())) .save(exporter, AnvilCraft.of("smash_block/" + BuiltInRegistries.BLOCK.getKey(block1).getPath())); } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashRecipesGenerator.java index 5f5976474..87620093e 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SmashRecipesGenerator.java @@ -2,8 +2,7 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.init.ModItems; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.minecraft.core.registries.BuiltInRegistries; @@ -29,12 +28,10 @@ public static void buildRecipes(Consumer exporter) { } public static void smash(Item item, @NotNull Item item1, int count, Consumer exporter) { - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC) - .requires(item) - .result(item1, count) - .component(Blocks.IRON_TRAPDOOR) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.IN) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.IRON_TRAPDOOR) + .hasItemIngredient(item) + .spawnItem(item1, count) .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) .save(exporter, AnvilCraft.of("smash/" + BuiltInRegistries.ITEM.getKey(item).getPath() + "_2_" + BuiltInRegistries.ITEM.getKey(item1).getPath())); } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SqueezeRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SqueezeRecipesGenerator.java index e321444df..c21536d9c 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SqueezeRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/SqueezeRecipesGenerator.java @@ -2,16 +2,21 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.Component; -import dev.dubhe.anvilcraft.data.recipe.anvil.block.BlockAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.init.ModBlocks; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.world.item.Items; +import net.minecraft.world.item.HoneycombItem; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LayeredCauldronBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import java.util.Optional; import java.util.function.Consumer; public abstract class SqueezeRecipesGenerator { @@ -19,176 +24,76 @@ private SqueezeRecipesGenerator() { } public static void buildRecipes(Consumer exporter) { - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.NETHERRACK.defaultBlockState(), ModBlocks.LAVA_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) - .component(Blocks.MAGMA_BLOCK) - .component(Blocks.CAULDRON) - .unlockedBy(MyRecipesGenerator.hasItem(Items.WET_SPONGE), FabricRecipeProvider.has(Items.WET_SPONGE)) - .save(exporter, AnvilCraft.of("squeeze/magma_block_lava_cauldron_1")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.NETHERRACK.defaultBlockState(), ModBlocks.LAVA_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) - .component(Blocks.MAGMA_BLOCK) - .component(Component.of(Component.Value.of(ModBlocks.LAVA_CAULDRON).with("level", 1))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.WET_SPONGE), FabricRecipeProvider.has(Items.WET_SPONGE)) - .save(exporter, AnvilCraft.of("squeeze/magma_block_lava_cauldron_2")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.NETHERRACK.defaultBlockState(), Blocks.LAVA_CAULDRON.defaultBlockState()) - .component(Blocks.MAGMA_BLOCK) - .component(Component.of(Component.Value.of(ModBlocks.LAVA_CAULDRON).with("level", 2))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.WET_SPONGE), FabricRecipeProvider.has(Items.WET_SPONGE)) - .save(exporter, AnvilCraft.of("squeeze/magma_block_lava_cauldron_3")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.SPONGE.defaultBlockState(), Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) - .component(Blocks.WET_SPONGE) - .component(Blocks.CAULDRON) - .unlockedBy(MyRecipesGenerator.hasItem(Items.WET_SPONGE), FabricRecipeProvider.has(Items.WET_SPONGE)) - .save(exporter, AnvilCraft.of("squeeze/wet_sponge_2_water_cauldron_1")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.SPONGE.defaultBlockState(), Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) - .component(Blocks.WET_SPONGE) - .component(Component.of(Component.Value.of(Blocks.WATER_CAULDRON).with("level", 1))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.WET_SPONGE), FabricRecipeProvider.has(Items.WET_SPONGE)) - .save(exporter, AnvilCraft.of("squeeze/wet_sponge_2_water_cauldron_2")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.SPONGE.defaultBlockState(), Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)) - .component(Blocks.WET_SPONGE) - .component(Component.of(Component.Value.of(Blocks.WATER_CAULDRON).with("level", 2))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.WET_SPONGE), FabricRecipeProvider.has(Items.WET_SPONGE)) - .save(exporter, AnvilCraft.of("squeeze/wet_sponge_2_water_cauldron_3")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.MOSS_CARPET.defaultBlockState(), Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) - .component(Blocks.MOSS_BLOCK) - .component(Blocks.CAULDRON) - .unlockedBy(MyRecipesGenerator.hasItem(Items.MOSS_BLOCK), FabricRecipeProvider.has(Items.MOSS_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/moss_2_water_cauldron_1")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.MOSS_CARPET.defaultBlockState(), Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) - .component(Blocks.MOSS_BLOCK) - .component(Component.of(Component.Value.of(Blocks.WATER_CAULDRON).with("level", 1))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.MOSS_BLOCK), FabricRecipeProvider.has(Items.MOSS_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/moss_2_water_cauldron_2")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.MOSS_CARPET.defaultBlockState(), Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)) - .component(Blocks.MOSS_BLOCK) - .component(Component.of(Component.Value.of(Blocks.WATER_CAULDRON).with("level", 2))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.MOSS_BLOCK), FabricRecipeProvider.has(Items.MOSS_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/moss_2_water_cauldron_3")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.ICE.defaultBlockState(), Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) - .component(Blocks.SNOW_BLOCK) - .component(Blocks.CAULDRON) - .unlockedBy(MyRecipesGenerator.hasItem(Items.SNOW_BLOCK), FabricRecipeProvider.has(Items.SNOW_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/snow_2_powder_snow_cauldron_1")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.ICE.defaultBlockState(), Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) - .component(Blocks.SNOW_BLOCK) - .component(Component.of(Component.Value.of(Blocks.POWDER_SNOW_CAULDRON).with("level", 1))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.SNOW_BLOCK), FabricRecipeProvider.has(Items.SNOW_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/snow_2_powder_snow_cauldron_2")); - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.ICE.defaultBlockState(), Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)) - .component(Blocks.SNOW_BLOCK) - .component(Component.of(Component.Value.of(Blocks.POWDER_SNOW_CAULDRON).with("level", 2))) - .unlockedBy(MyRecipesGenerator.hasItem(Items.SNOW_BLOCK), FabricRecipeProvider.has(Items.SNOW_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/snow_2_powder_snow_cauldron_3")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.MOSS_BLOCK.defaultBlockState(), Blocks.MOSSY_COBBLESTONE.defaultBlockState()) - .component(Blocks.MOSS_BLOCK) - .component(Blocks.COBBLESTONE) - .unlockedBy(MyRecipesGenerator.hasItem(Items.MOSS_BLOCK), FabricRecipeProvider.has(Items.MOSS_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/mossy_cobblestone")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.MOSS_BLOCK.defaultBlockState(), Blocks.MOSSY_STONE_BRICKS.defaultBlockState()) - .component(Blocks.MOSS_BLOCK) - .component(Blocks.STONE_BRICKS) - .unlockedBy(MyRecipesGenerator.hasItem(Items.MOSS_BLOCK), FabricRecipeProvider.has(Items.MOSS_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/mossy_stone_bricks")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_COPPER_BLOCK.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.COPPER_BLOCK) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_copper_block")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_WEATHERED_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.WEATHERED_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_weathered_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_EXPOSED_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.EXPOSED_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_exposed_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_OXIDIZED_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.OXIDIZED_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_oxidized_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_OXIDIZED_CUT_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.OXIDIZED_CUT_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_oxidized_cut_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_WEATHERED_CUT_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.WEATHERED_CUT_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_weathered_cut_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_EXPOSED_CUT_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.EXPOSED_CUT_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_exposed_cut_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_CUT_COPPER.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.CUT_COPPER) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_cut_copper")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_OXIDIZED_CUT_COPPER_STAIRS.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.OXIDIZED_CUT_COPPER_STAIRS) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_oxidized_cut_copper_stairs")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_WEATHERED_CUT_COPPER_STAIRS.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.WEATHERED_CUT_COPPER_STAIRS) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_weathered_cut_copper_stairs")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_EXPOSED_CUT_COPPER_STAIRS.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.EXPOSED_CUT_COPPER_STAIRS) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_exposed_cut_copper_stairs")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_CUT_COPPER_STAIRS.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.CUT_COPPER_STAIRS) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_cut_copper_stairs")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_OXIDIZED_CUT_COPPER_SLAB.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.OXIDIZED_CUT_COPPER_SLAB) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_oxidized_cut_copper_slab")); - - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_WEATHERED_CUT_COPPER_SLAB.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.WEATHERED_CUT_COPPER_SLAB) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_weathered_cut_copper_slab")); + squeeze(Blocks.MAGMA_BLOCK, Blocks.NETHERRACK, ModBlocks.LAVA_CAULDRON, exporter); + squeeze(Blocks.WET_SPONGE, Blocks.SPONGE, Blocks.WATER_CAULDRON, exporter); + squeeze(Blocks.MOSS_BLOCK, Blocks.MOSS_CARPET, Blocks.WATER_CAULDRON, exporter); + squeeze(Blocks.SNOW_BLOCK, Blocks.ICE, Blocks.POWDER_SNOW_CAULDRON, exporter); + + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.MOSS_BLOCK) + .hasBlock(new Vec3(0.0, -2.0, 0.0), Blocks.COBBLESTONE) + .setBlock(new Vec3(0.0, -2.0, 0.0), Blocks.MOSSY_COBBLESTONE) + .unlockedBy(MyRecipesGenerator.hasItem(Blocks.MOSS_BLOCK.asItem()), FabricRecipeProvider.has(Blocks.MOSS_BLOCK.asItem())) + .save(exporter, AnvilCraft.of("daub/" + BuiltInRegistries.BLOCK.getKey(Blocks.MOSSY_COBBLESTONE).getPath())); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.MOSS_BLOCK) + .hasBlock(new Vec3(0.0, -2.0, 0.0), Blocks.STONE_BRICKS) + .setBlock(new Vec3(0.0, -2.0, 0.0), Blocks.MOSSY_STONE_BRICKS) + .unlockedBy(MyRecipesGenerator.hasItem(Blocks.MOSS_BLOCK.asItem()), FabricRecipeProvider.has(Blocks.MOSS_BLOCK.asItem())) + .save(exporter, AnvilCraft.of("daub/" + BuiltInRegistries.BLOCK.getKey(Blocks.MOSSY_STONE_BRICKS).getPath())); + + waxed(Blocks.COPPER_BLOCK, exporter); + waxed(Blocks.WEATHERED_COPPER, exporter); + waxed(Blocks.EXPOSED_COPPER, exporter); + waxed(Blocks.OXIDIZED_COPPER, exporter); + waxed(Blocks.OXIDIZED_CUT_COPPER, exporter); + waxed(Blocks.WEATHERED_CUT_COPPER, exporter); + waxed(Blocks.EXPOSED_CUT_COPPER, exporter); + waxed(Blocks.CUT_COPPER, exporter); + waxed(Blocks.OXIDIZED_CUT_COPPER_STAIRS, exporter); + waxed(Blocks.WEATHERED_CUT_COPPER_STAIRS, exporter); + waxed(Blocks.EXPOSED_CUT_COPPER_STAIRS, exporter); + waxed(Blocks.CUT_COPPER_STAIRS, exporter); + waxed(Blocks.OXIDIZED_CUT_COPPER_SLAB, exporter); + waxed(Blocks.WEATHERED_CUT_COPPER_SLAB, exporter); + waxed(Blocks.EXPOSED_CUT_COPPER_SLAB, exporter); + waxed(Blocks.CUT_COPPER_SLAB, exporter); + } - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_EXPOSED_CUT_COPPER_SLAB.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.EXPOSED_CUT_COPPER_SLAB) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_exposed_cut_copper_slab")); + public static void waxed(@NotNull Block block, Consumer exporter) { + Optional waxed = HoneycombItem.getWaxed(block.defaultBlockState()); + if (waxed.isPresent()) { + BlockState state = waxed.get(); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.HONEYCOMB_BLOCK) + .hasBlock(new Vec3(0.0, -2.0, 0.0), block) + .setBlock(new Vec3(0.0, -2.0, 0.0), state) + .unlockedBy(MyRecipesGenerator.hasItem(Blocks.HONEYCOMB_BLOCK.asItem()), FabricRecipeProvider.has(Blocks.HONEYCOMB_BLOCK.asItem())) + .save(exporter, AnvilCraft.of("daub/" + BuiltInRegistries.BLOCK.getKey(state.getBlock()).getPath())); + } + } - BlockAnvilRecipeBuilder.block(RecipeCategory.MISC, Blocks.HONEYCOMB_BLOCK.defaultBlockState(), Blocks.WAXED_CUT_COPPER_SLAB.defaultBlockState()) - .component(Blocks.HONEYCOMB_BLOCK) - .component(Blocks.CUT_COPPER_SLAB) - .unlockedBy(MyRecipesGenerator.hasItem(Items.HONEYCOMB_BLOCK), FabricRecipeProvider.has(Items.HONEYCOMB_BLOCK)) - .save(exporter, AnvilCraft.of("squeeze/waxed_cut_copper_slab")); + public static void squeeze(@NotNull Block block, @NotNull Block block1, @NotNull Block block2, Consumer exporter) { + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(block) + .hasBlock(new Vec3(0.0, -2.0, 0.0), Blocks.CAULDRON) + .setBlock(block1) + .setBlock(new Vec3(0.0, -2.0, 0.0), block2.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) + .unlockedBy(MyRecipesGenerator.hasItem(block.asItem()), FabricRecipeProvider.has(block.asItem())) + .save(exporter, AnvilCraft.of("squeeze/" + BuiltInRegistries.BLOCK.getKey(block).getPath() + "_" + BuiltInRegistries.BLOCK.getKey(block2).getPath() + "_1")); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(block) + .hasBlock(new Vec3(0.0, -2.0, 0.0), block2.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 1)) + .setBlock(block1) + .setBlock(new Vec3(0.0, -2.0, 0.0), block2.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) + .unlockedBy(MyRecipesGenerator.hasItem(block.asItem()), FabricRecipeProvider.has(block.asItem())) + .save(exporter, AnvilCraft.of("squeeze/" + BuiltInRegistries.BLOCK.getKey(block).getPath() + "_" + BuiltInRegistries.BLOCK.getKey(block2).getPath() + "_2")); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(block) + .hasBlock(new Vec3(0.0, -2.0, 0.0), block2.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 2)) + .setBlock(block1) + .setBlock(new Vec3(0.0, -2.0, 0.0), block2.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3)) + .unlockedBy(MyRecipesGenerator.hasItem(block.asItem()), FabricRecipeProvider.has(block.asItem())) + .save(exporter, AnvilCraft.of("squeeze/" + BuiltInRegistries.BLOCK.getKey(block).getPath() + "_" + BuiltInRegistries.BLOCK.getKey(block2).getPath() + "_3")); } } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/StampingRecipesGenerator.java b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/StampingRecipesGenerator.java index 1ca144976..d6b25f124 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/StampingRecipesGenerator.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/StampingRecipesGenerator.java @@ -2,16 +2,13 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.generator.MyRecipesGenerator; -import dev.dubhe.anvilcraft.data.recipe.Component; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipeBuilder; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.init.ModItems; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.minecraft.core.Direction; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeCategory; -import net.minecraft.tags.BlockTags; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.block.Blocks; @@ -29,51 +26,45 @@ public static void buildRecipes(Consumer exporter) { stamping(Items.SUGAR_CANE, Items.PAPER, exporter); stamping(Items.SNOWBALL, Items.SNOW, exporter); stamping(ModItems.DOUGH, ModItems.FLATDOUGH, exporter); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, ModItems.COCOA_BUTTER) - .result(ModItems.COCOA_POWDER) - .requires(Items.COCOA_BEANS) - .component(Component.of(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP))) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP)) + .hasItemIngredient(Items.COCOA_BEANS) + .spawnItem(ModItems.COCOA_BUTTER) + .spawnItem(ModItems.COCOA_POWDER) .unlockedBy(MyRecipesGenerator.hasItem(Items.COCOA_BEANS), FabricRecipeProvider.has(Items.COCOA_BEANS)) .save(exporter, AnvilCraft.of("stamping/cocoa")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, ModItems.CREAM, 4) - .result(Items.BUCKET) - .requires(Items.MILK_BUCKET) - .component(Component.of(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP))) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP)) + .hasItemIngredient(Items.MILK_BUCKET) + .spawnItem(ModItems.CREAM) + .spawnItem(Items.BUCKET) .unlockedBy(MyRecipesGenerator.hasItem(Items.MILK_BUCKET), FabricRecipeProvider.has(Items.MILK_BUCKET)) .save(exporter, AnvilCraft.of("stamping/cream")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, ModItems.GREASE) - .requires(Items.MELON_SEEDS) - .component(Component.of(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP))) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP)) + .hasItemIngredient(Items.MELON_SEEDS) + .spawnItem(ModItems.GREASE) .unlockedBy(MyRecipesGenerator.hasItem(Items.MELON_SEEDS), FabricRecipeProvider.has(Items.MELON_SEEDS)) .save(exporter, AnvilCraft.of("stamping/melon_seeds_2_grease")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, ModItems.GREASE) - .requires(Items.PUMPKIN_SEEDS) - .component(Component.of(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP))) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP)) + .hasItemIngredient(Items.PUMPKIN_SEEDS) + .spawnItem(ModItems.GREASE) .unlockedBy(MyRecipesGenerator.hasItem(Items.PUMPKIN_SEEDS), FabricRecipeProvider.has(Items.PUMPKIN_SEEDS)) .save(exporter, AnvilCraft.of("stamping/pumpkin_seeds_2_grease")); - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, ModItems.GREASE,8) - .requires(Items.COOKED_PORKCHOP) - .component(Component.of(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP))) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP)) + .hasItemIngredient(Items.COOKED_PORKCHOP) + .spawnItem(ModItems.GREASE, 8) .unlockedBy(MyRecipesGenerator.hasItem(Items.COOKED_PORKCHOP), FabricRecipeProvider.has(Items.COOKED_PORKCHOP)) .save(exporter, AnvilCraft.of("stamping/cooked_porkchop_2_grease")); } public static void stamping(Item item, Item item1, Consumer exporter) { - ItemAnvilRecipeBuilder.item(RecipeCategory.MISC, item1) - .requires(item) - .component(Component.of(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP))) - .location(ItemAnvilRecipe.Location.UP) - .resultLocation(ItemAnvilRecipe.Location.UP) + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .hasBlock(Blocks.PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.UP)) + .hasItemIngredient(item) + .spawnItem(item1) .unlockedBy(MyRecipesGenerator.hasItem(item), FabricRecipeProvider.has(item)) .save(exporter, AnvilCraft.of("stamping/" + BuiltInRegistries.ITEM.getKey(item1).getPath())); } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeSerializerBase.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeSerializerBase.java index 14b9a8df6..c926150ef 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeSerializerBase.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeSerializerBase.java @@ -9,7 +9,6 @@ import com.google.gson.JsonSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.datafixers.util.Pair; -import dev.dubhe.anvilcraft.AnvilCraft; import net.minecraft.commands.arguments.blocks.BlockStateParser; import net.minecraft.core.*; import net.minecraft.core.registries.BuiltInRegistries; @@ -35,6 +34,7 @@ import java.util.stream.Stream; @SuppressWarnings("unused") +@Deprecated public interface RecipeSerializerBase> extends RecipeSerializer { default @NotNull NonNullList itemsFromJson(@NotNull JsonArray ingredientArray) { NonNullList nonNullList = NonNullList.create(); @@ -161,6 +161,7 @@ default int lastNonSpace(@NotNull String entry) { return i; } + @SuppressWarnings("DuplicatedCode") default @NotNull ItemStack itemStackFromJson(JsonElement element) { if (!element.isJsonObject()) throw new JsonSyntaxException("Expected item to be string"); JsonObject object = element.getAsJsonObject(); @@ -184,6 +185,7 @@ default int lastNonSpace(@NotNull String entry) { return stack; } + @SuppressWarnings("DuplicatedCode") default NonNullList getBlockResults(@NotNull JsonArray array) { NonNullList results = NonNullList.create(); for (JsonElement element : array) { diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilCraftingContainer.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilCraftingContainer.java index a668123cd..4084c9acf 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilCraftingContainer.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilCraftingContainer.java @@ -1,5 +1,7 @@ package dev.dubhe.anvilcraft.data.recipe.anvil; +import lombok.Getter; +import lombok.Setter; import net.minecraft.core.BlockPos; import net.minecraft.world.Container; import net.minecraft.world.entity.item.FallingBlockEntity; @@ -10,8 +12,20 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; -public record AnvilCraftingContainer(Level level, BlockPos pos, FallingBlockEntity entity) +@Getter +public class AnvilCraftingContainer implements Container, StackedContentsCompatible { + private final Level level; + private final BlockPos pos; + private final FallingBlockEntity entity; + @Setter + private boolean isAnvilDamage = false; + + public AnvilCraftingContainer(Level level, BlockPos pos, FallingBlockEntity entity) { + this.level = level; + this.pos = pos; + this.entity = entity; + } @Override public int getContainerSize() { diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java new file mode 100644 index 000000000..106660a80 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java @@ -0,0 +1,586 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.*; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasBlock; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasBlockIngredient; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItem; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItemIngredient; +import dev.dubhe.anvilcraft.util.IItemStackInjector; +import lombok.Getter; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementRewards; +import net.minecraft.advancements.CriterionTriggerInstance; +import net.minecraft.advancements.RequirementsStrategy; +import net.minecraft.advancements.critereon.*; +import net.minecraft.core.NonNullList; +import net.minecraft.core.RegistryAccess; +import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.data.recipes.RecipeBuilder; +import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +@SuppressWarnings("unused") +public class AnvilRecipe implements Recipe { + private final ResourceLocation id; + private final List predicates = new ArrayList<>(); + private final List outcomes = new ArrayList<>(); + private final ItemStack icon; + + public AnvilRecipe(ResourceLocation id, ItemStack icon) { + this.id = id; + this.icon = icon; + } + + @SuppressWarnings("UnusedReturnValue") + public AnvilRecipe addPredicates(RecipePredicate... predicates) { + this.predicates.addAll(Arrays.stream(predicates).toList()); + return this; + } + + @SuppressWarnings("UnusedReturnValue") + public AnvilRecipe addOutcomes(RecipeOutcome... outcomes) { + this.outcomes.addAll(Arrays.stream(outcomes).toList()); + return this; + } + + @Override + public boolean matches(AnvilCraftingContainer container, Level level) { + for (RecipePredicate predicate : this.predicates) { + if (!predicate.matches(container)) return false; + } + return true; + } + + public boolean craft(@NotNull AnvilCraftingContainer container) { + if (!this.matches(container, container.getLevel())) return false; + for (RecipePredicate predicate : this.predicates) predicate.process(container); + for (RecipeOutcome outcome : this.outcomes) outcome.process(container); + return true; + } + + @Override + public @NotNull ItemStack assemble(AnvilCraftingContainer container, RegistryAccess registryAccess) { + return ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return true; + } + + @Override + public @NotNull ItemStack getResultItem(RegistryAccess registryAccess) { + return this.icon; + } + + @Override + public @NotNull ResourceLocation getId() { + return this.id; + } + + @Override + public @NotNull RecipeSerializer getSerializer() { + return Serializer.INSTANCE; + } + + @Override + public @NotNull RecipeType getType() { + return Type.INSTANCE; + } + + public enum Serializer implements RecipeSerializer { + INSTANCE; + + @Override + public @NotNull AnvilRecipe fromJson(ResourceLocation recipeId, @NotNull JsonObject serializedRecipe) { + ItemStack icon = ItemStack.EMPTY; + if (serializedRecipe.has("icon")) { + icon = IItemStackInjector.fromJson(serializedRecipe.get("icon")); + } + AnvilRecipe recipe = new AnvilRecipe(recipeId, icon); + JsonArray predicates = GsonHelper.getAsJsonArray(serializedRecipe, "predicates"); + for (JsonElement predicate : predicates) { + if (!predicate.isJsonObject()) { + throw new JsonSyntaxException("The predicate in the Anvil Recipe should be an object."); + } + recipe.addPredicates(RecipePredicate.fromJson(predicate.getAsJsonObject())); + } + JsonArray outcomes = GsonHelper.getAsJsonArray(serializedRecipe, "outcomes"); + for (JsonElement outcome : outcomes) { + if (!outcome.isJsonObject()) { + throw new JsonSyntaxException("The outcome in the Anvil Recipe should be an object."); + } + recipe.addOutcomes(RecipeOutcome.fromJson(outcome.getAsJsonObject())); + } + return recipe; + } + + @Override + public @NotNull AnvilRecipe fromNetwork(ResourceLocation recipeId, @NotNull FriendlyByteBuf buffer) { + AnvilRecipe recipe = new AnvilRecipe(recipeId, buffer.readItem()); + int size; + size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + recipe.addPredicates(RecipePredicate.fromNetwork(buffer)); + } + size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + recipe.addOutcomes(RecipeOutcome.fromNetwork(buffer)); + } + return recipe; + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer, @NotNull AnvilRecipe recipe) { + buffer.writeItem(recipe.icon); + buffer.writeVarInt(recipe.predicates.size()); + for (RecipePredicate predicate : recipe.predicates) { + predicate.toNetwork(buffer); + } + buffer.writeVarInt(recipe.outcomes.size()); + for (RecipeOutcome outcome : recipe.outcomes) { + outcome.toNetwork(buffer); + } + } + } + + public static class Builder implements RecipeBuilder { + @Getter + private final RecipeCategory category; + private ItemStack icon; + private final NonNullList predicates = NonNullList.create(); + private final NonNullList outcomes = NonNullList.create(); + @Getter + private final Advancement.Builder advancement = Advancement.Builder.recipeAdvancement(); + @Nullable + private String group = null; + + private Builder(RecipeCategory category, ItemStack icon) { + this.category = category; + this.icon = icon; + } + + public static @NotNull Builder create(RecipeCategory category) { + return new Builder(category, Items.ANVIL.getDefaultInstance()); + } + + public static @NotNull Builder create(RecipeCategory category, ItemStack icon) { + return new Builder(category, icon); + } + + public @NotNull Builder icon(ItemStack icon) { + this.icon = icon; + return this; + } + + public @NotNull Builder icon(ItemLike icon) { + this.icon = icon.asItem().getDefaultInstance(); + return this; + } + + public @NotNull Builder addPredicates(RecipePredicate... predicates) { + this.predicates.addAll(Arrays.stream(predicates).toList()); + return this; + } + + public @NotNull Builder addOutcomes(RecipeOutcome... outcomes) { + this.outcomes.addAll(Arrays.stream(outcomes).toList()); + return this; + } + + public @NotNull Builder hasItem(Vec3 offset, int count, ItemLike... items) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().of(items).withCount(MinMaxBounds.Ints.atLeast(count)); + return this.addPredicates(new HasItem(offset, item.build())); + } + + public @NotNull Builder hasItem(Vec3 offset, ItemLike... items) { + return this.hasItem(offset, 1, items); + } + + public @NotNull Builder hasItem(Vec3 offset, int count, TagKey items) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().of(items).withCount(MinMaxBounds.Ints.atLeast(count)); + return this.addPredicates(new HasItem(offset, item.build())); + } + + public @NotNull Builder hasItem(Vec3 offset, TagKey items) { + return this.hasItem(offset, 1, items); + } + + public @NotNull Builder hasItem(Vec3 offset, @NotNull ItemStack itemStack) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().of(itemStack.getItem()) + .withCount(MinMaxBounds.Ints.atLeast(itemStack.getCount())); + if (itemStack.hasTag()) item.hasNbt(itemStack.getOrCreateTag()); + return this.addPredicates(new HasItem(offset, item.build())); + } + + public @NotNull Builder hasItemIngredient(Vec3 offset, int count, ItemLike... items) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().of(items).withCount(MinMaxBounds.Ints.atLeast(count)); + return this.addPredicates(new HasItemIngredient(offset, item.build())); + } + + public @NotNull Builder hasItemIngredient(Vec3 offset, ItemLike... items) { + return this.hasItemIngredient(offset, 1, items); + } + + public @NotNull Builder hasItemIngredient(Vec3 offset, int count, TagKey items) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().of(items).withCount(MinMaxBounds.Ints.atLeast(count)); + return this.addPredicates(new HasItemIngredient(offset, item.build())); + } + + public @NotNull Builder hasItemIngredient(Vec3 offset, TagKey items) { + return this.hasItemIngredient(offset, 1, items); + } + + public @NotNull Builder hasItemIngredient(Vec3 offset, @NotNull ItemStack itemStack) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().of(itemStack.getItem()) + .withCount(MinMaxBounds.Ints.atLeast(itemStack.getCount())); + if (itemStack.hasTag()) item.hasNbt(itemStack.getOrCreateTag()); + return this.addPredicates(new HasItemIngredient(offset, item.build())); + } + + public @NotNull Builder hasItem(ItemLike... items) { + return this.hasItem(Vec3.ZERO, items); + } + + public @NotNull Builder hasItem(TagKey items) { + return this.hasItem(Vec3.ZERO, items); + } + + public @NotNull Builder hasItem(int count, ItemLike... items) { + return this.hasItem(Vec3.ZERO, count, items); + } + + public @NotNull Builder hasItem(int count, TagKey items) { + return this.hasItem(Vec3.ZERO, count, items); + } + + public @NotNull Builder hasItem(@NotNull ItemStack itemStack) { + return this.hasItem(Vec3.ZERO, itemStack); + } + + public @NotNull Builder hasItemIngredient(ItemLike... items) { + return this.hasItemIngredient(Vec3.ZERO, items); + } + + public @NotNull Builder hasItemIngredient(TagKey items) { + return this.hasItemIngredient(Vec3.ZERO, items); + } + + public @NotNull Builder hasItemIngredient(int count, ItemLike... items) { + return this.hasItemIngredient(Vec3.ZERO, count, items); + } + + public @NotNull Builder hasItemIngredient(int count, TagKey items) { + return this.hasItemIngredient(Vec3.ZERO, count, items); + } + + public @NotNull Builder hasItemIngredient(@NotNull ItemStack itemStack) { + return this.hasItemIngredient(Vec3.ZERO, itemStack); + } + + public @NotNull Builder hasBlock(Vec3 offset, Block... blocks) { + BlockPredicate.Builder block = BlockPredicate.Builder.block().of(blocks); + return this.addPredicates(new HasBlock(offset, block.build())); + } + + public @NotNull Builder hasBlock(Vec3 offset, TagKey blocks) { + BlockPredicate.Builder block = BlockPredicate.Builder.block().of(blocks); + return this.addPredicates(new HasBlock(offset, block.build())); + + } + + @SuppressWarnings("unchecked") + public > @NotNull Builder hasBlock(Vec3 offset, @NotNull BlockState blockState) { + BlockState defaultBlockState = blockState.getBlock().defaultBlockState(); + StatePropertiesPredicate.Builder properties = StatePropertiesPredicate.Builder.properties(); + for (Map.Entry, Comparable> entry : blockState.getValues().entrySet()) { + if (((T) defaultBlockState.getValue(entry.getKey())).compareTo((T) entry.getValue()) == 0) continue; + properties.hasProperty(entry.getKey(), entry.getValue().toString()); + } + BlockPredicate.Builder block = BlockPredicate.Builder.block().of(blockState.getBlock()).setProperties(properties.build()); + return this.addPredicates(new HasBlock(offset, block.build())); + } + + public @NotNull Builder hasBlockIngredient(Vec3 offset, Block... blocks) { + BlockPredicate.Builder block = BlockPredicate.Builder.block().of(blocks); + return this.addPredicates(new HasBlockIngredient(offset, block.build())); + } + + public @NotNull Builder hasBlockIngredient(Vec3 offset, TagKey blocks) { + BlockPredicate.Builder block = BlockPredicate.Builder.block().of(blocks); + return this.addPredicates(new HasBlockIngredient(offset, block.build())); + } + + public @NotNull Builder hasBlockIngredient(Vec3 offset, @NotNull BlockState blockState) { + BlockPredicate.Builder block = BlockPredicate.Builder.block().of(blockState.getBlock()); + return this.addPredicates(new HasBlockIngredient(offset, block.build())); + } + + public @NotNull Builder hasBlock(Block... blocks) { + return this.hasBlock(new Vec3(0.0, -1.0, 0.0), blocks); + } + + public @NotNull Builder hasBlock(TagKey blocks) { + return this.hasBlock(new Vec3(0.0, -1.0, 0.0), blocks); + } + + public @NotNull Builder hasBlock(BlockState blockState) { + return this.hasBlock(new Vec3(0.0, -1.0, 0.0), blockState); + } + + public @NotNull Builder hasBlockIngredient(Block... blocks) { + return this.hasBlockIngredient(new Vec3(0.0, -1.0, 0.0), blocks); + } + + public @NotNull Builder hasBlockIngredient(TagKey blocks) { + return this.hasBlockIngredient(new Vec3(0.0, -1.0, 0.0), blocks); + } + + public @NotNull Builder hasBlockIngredient(BlockState blockState) { + return this.hasBlockIngredient(new Vec3(0.0, -1.0, 0.0), blockState); + } + + public @NotNull Builder damageAnvil(double chance) { + return this.addOutcomes(new DamageAnvil(chance)); + } + + public @NotNull Builder damageAnvil() { + return this.damageAnvil(1.0); + } + + public @NotNull Builder setBlock(Vec3 offset, double chance, BlockState block) { + if (this.icon.is(Items.ANVIL)) this.icon = block.getBlock().asItem().getDefaultInstance(); + return this.addOutcomes(new SetBlock(offset, chance, block)); + } + + public @NotNull Builder setBlock(double chance, BlockState block) { + return this.setBlock(new Vec3(0.0, -1.0, 0.0), chance, block); + } + + public @NotNull Builder setBlock(Vec3 offset, BlockState block) { + return this.setBlock(offset, 1.0, block); + } + + public @NotNull Builder setBlock(BlockState block) { + return this.setBlock(1.0, block); + } + + public @NotNull Builder setBlock(Vec3 offset, double chance, @NotNull Block block) { + return this.setBlock(offset, chance, block.defaultBlockState()); + } + + public @NotNull Builder setBlock(double chance, @NotNull Block block) { + return this.setBlock(chance, block.defaultBlockState()); + } + + public @NotNull Builder setBlock(Vec3 offset, @NotNull Block block) { + return this.setBlock(offset, block.defaultBlockState()); + } + + public @NotNull Builder setBlock(@NotNull Block block) { + return this.setBlock(block.defaultBlockState()); + } + + public @NotNull Builder spawnItem(Vec3 offset, double chance, ItemStack item) { + if (this.icon.is(Items.ANVIL)) this.icon = item; + return this.addOutcomes(new SpawnItem(offset, chance, item)); + } + + public @NotNull Builder spawnItem(double chance, ItemStack item) { + return this.spawnItem(Vec3.ZERO, chance, item); + } + + public @NotNull Builder spawnItem(Vec3 offset, ItemStack item) { + return this.spawnItem(offset, 1.0, item); + } + + public @NotNull Builder spawnItem(ItemStack item) { + return this.spawnItem(1.0, item); + } + + public @NotNull Builder spawnItem(Vec3 offset, double chance, @NotNull ItemLike item, int count) { + ItemStack stack = item.asItem().getDefaultInstance(); + stack.setCount(count); + return this.spawnItem(offset, chance, stack); + } + + public @NotNull Builder spawnItem(double chance, @NotNull ItemLike item, int count) { + return this.spawnItem(Vec3.ZERO, chance, item, count); + } + + public @NotNull Builder spawnItem(Vec3 offset, @NotNull ItemLike item, int count) { + return this.spawnItem(offset, 1.0, item, count); + } + + public @NotNull Builder spawnItem(@NotNull ItemLike item, int count) { + return this.spawnItem(Vec3.ZERO, 1.0, item, count); + } + + public @NotNull Builder spawnItem(Vec3 offset, double chance, @NotNull ItemLike item) { + return this.spawnItem(offset, chance, item, 1); + } + + public @NotNull Builder spawnItem(double chance, ItemLike item) { + return this.spawnItem(Vec3.ZERO, chance, item); + } + + public @NotNull Builder spawnItem(Vec3 offset, ItemLike item) { + return this.spawnItem(offset, 1.0, item); + } + + public @NotNull Builder spawnItem(ItemLike item) { + return this.spawnItem(1.0, item); + } + + public @NotNull Builder spawnExperience(Vec3 offset, double chance, int experience) { + return this.addOutcomes(new SpawnExperience(offset, chance, experience)); + } + + public @NotNull Builder spawnExperience(double chance, int experience) { + return this.spawnExperience(Vec3.ZERO, chance, experience); + } + + public @NotNull Builder spawnExperience(Vec3 offset, int experience) { + return this.spawnExperience(offset, 1.0, experience); + } + + public @NotNull Builder spawnExperience(int experience) { + return this.spawnExperience(1.0, experience); + } + + public @NotNull Builder runCommand(Vec3 offset, double chance, String command) { + return this.addOutcomes(new RunCommand(offset, chance, command)); + } + + public @NotNull Builder runCommand(Vec3 offset, String command) { + return this.runCommand(offset, 1.0, command); + } + + public @NotNull Builder runCommand(double chance, String command) { + return this.runCommand(Vec3.ZERO, chance, command); + } + + public @NotNull Builder runCommand(String command) { + return this.runCommand(1.0, command); + } + + @Override + public @NotNull Builder unlockedBy(String criterionName, CriterionTriggerInstance criterionTrigger) { + this.advancement.addCriterion(criterionName, criterionTrigger); + return this; + } + + @Override + public @NotNull Builder group(@Nullable String groupName) { + this.group = groupName; + return this; + } + + @Override + public @NotNull Item getResult() { + return this.icon.getItem(); + } + + @Override + public void save(@NotNull Consumer finishedRecipeConsumer, ResourceLocation recipeId) { + this.advancement.parent(ROOT_RECIPE_ADVANCEMENT).addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(recipeId)).rewards(AdvancementRewards.Builder.recipe(recipeId)).requirements(RequirementsStrategy.OR); + finishedRecipeConsumer.accept(new Result(recipeId, this.icon, this.predicates, this.outcomes, null == this.group ? "" : this.group, this.advancement, recipeId.withPrefix("recipes/" + this.category.getFolderName() + "/"))); + } + + static class Result implements FinishedRecipe { + @Getter + private final ResourceLocation id; + private final ItemStack icon; + private final NonNullList predicates; + private final NonNullList outcomes; + private final String group; + @Getter + private final Advancement.Builder advancement; + @Getter + private final ResourceLocation advancementId; + + Result(ResourceLocation id, ItemStack icon, NonNullList predicates, NonNullList outcomes, String group, Advancement.Builder advancement, ResourceLocation advancementId) { + this.id = id; + this.icon = icon; + this.predicates = predicates; + this.outcomes = outcomes; + this.advancement = advancement; + this.group = group; + this.advancementId = advancementId; + } + + @Override + public void serializeRecipeData(JsonObject json) { + if (!this.group.isEmpty()) { + json.addProperty("group", this.group); + } + this.icon.toJson(); + json.add("icon", this.icon.toJson()); + JsonArray predicates = new JsonArray(); + for (RecipePredicate predicate : this.predicates) { + predicates.add(predicate.toJson()); + } + json.add("predicates", predicates); + JsonArray outcomes = new JsonArray(); + for (RecipeOutcome outcome : this.outcomes) { + outcomes.add(outcome.toJson()); + } + json.add("outcomes", outcomes); + } + + @Nullable + @Override + public JsonObject serializeAdvancement() { + return this.advancement.serializeToJson(); + } + + @Override + public @NotNull RecipeSerializer getType() { + return Serializer.INSTANCE; + } + } + } + + public enum Type implements RecipeType { + INSTANCE + } + + static { + RecipePredicate.register("has_item", HasItem::new, HasItem::new); + RecipePredicate.register("has_item_ingredient", HasItemIngredient::new, HasItemIngredient::new); + RecipePredicate.register("has_block", HasBlock::new, HasBlock::new); + RecipePredicate.register("has_block_ingredient", HasBlockIngredient::new, HasBlockIngredient::new); + RecipeOutcome.register("damage_anvil", DamageAnvil::new, DamageAnvil::new); + RecipeOutcome.register("set_block", SetBlock::new, SetBlock::new); + RecipeOutcome.register("spawn_item", SpawnItem::new, SpawnItem::new); + RecipeOutcome.register("spawn_experience", SpawnExperience::new, SpawnExperience::new); + RecipeOutcome.register("run_command", RunCommand::new, RunCommand::new); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/RecipeOutcome.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/RecipeOutcome.java new file mode 100644 index 000000000..0bdee6ee6 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/RecipeOutcome.java @@ -0,0 +1,46 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.function.Function; + +public interface RecipeOutcome { + Map> JSON_DECODER = new HashMap<>(); + Map> NETWORK_DECODER = new HashMap<>(); + + static void register(String id, Function jsonDecoder, Function networkDecoder) { + RecipeOutcome.JSON_DECODER.put(id, jsonDecoder); + RecipeOutcome.NETWORK_DECODER.put(id, networkDecoder); + } + + String getType(); + + boolean process(AnvilCraftingContainer container); + + static @NotNull RecipeOutcome fromJson(JsonObject serializedRecipe) { + String id = GsonHelper.getAsString(serializedRecipe, "type"); + if (!RecipeOutcome.JSON_DECODER.containsKey(id)) { + throw new NoSuchElementException("Outcome type %s doesn't exist.".formatted(id)); + } + return RecipeOutcome.JSON_DECODER.get(id).apply(serializedRecipe); + } + + static @NotNull RecipeOutcome fromNetwork(@NotNull FriendlyByteBuf buffer) { + String id = buffer.readUtf(); + if (!RecipeOutcome.NETWORK_DECODER.containsKey(id)) { + throw new NoSuchElementException("Outcome type %s doesn't exist.".formatted(id)); + } + return RecipeOutcome.NETWORK_DECODER.get(id).apply(buffer); + } + + void toNetwork(FriendlyByteBuf buffer); + + JsonElement toJson(); +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/RecipePredicate.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/RecipePredicate.java new file mode 100644 index 000000000..eb984bf91 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/RecipePredicate.java @@ -0,0 +1,48 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.function.Function; + +public interface RecipePredicate { + Map> JSON_DECODER = new HashMap<>(); + Map> NETWORK_DECODER = new HashMap<>(); + + static void register(String id, Function jsonDecoder, Function networkDecoder) { + RecipePredicate.JSON_DECODER.put(id, jsonDecoder); + RecipePredicate.NETWORK_DECODER.put(id, networkDecoder); + } + + String getType(); + + boolean matches(AnvilCraftingContainer container); + + boolean process(AnvilCraftingContainer container); + + static @NotNull RecipePredicate fromJson(JsonObject serializedRecipe) { + String id = GsonHelper.getAsString(serializedRecipe, "type"); + if (!RecipePredicate.JSON_DECODER.containsKey(id)) { + throw new NoSuchElementException("Outcome type %s doesn't exist.".formatted(id)); + } + return RecipePredicate.JSON_DECODER.get(id).apply(serializedRecipe); + } + + static @NotNull RecipePredicate fromNetwork(@NotNull FriendlyByteBuf buffer) { + String id = buffer.readUtf(); + if (!RecipePredicate.NETWORK_DECODER.containsKey(id)) { + throw new NoSuchElementException("Outcome type %s doesn't exist.".formatted(id)); + } + return RecipePredicate.NETWORK_DECODER.get(id).apply(buffer); + } + + void toNetwork(FriendlyByteBuf buffer); + + @NotNull JsonElement toJson(); +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipe.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipe.java index d5854acf6..e1f541285 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipe.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipe.java @@ -25,6 +25,7 @@ @Getter @SuppressWarnings("ClassCanBeRecord") +@Deprecated public class BlockAnvilRecipe implements Recipe { private final ResourceLocation id; private final NonNullList components; @@ -42,7 +43,7 @@ public BlockAnvilRecipe(ResourceLocation id, NonNullList components, @Override public boolean matches(@NotNull AnvilCraftingContainer container, Level level) { - BlockPos pos = new BlockPos(container.pos()); + BlockPos pos = new BlockPos(container.getPos()); for (Component component : this.components) { pos = pos.below(); BlockState state = level.getBlockState(pos); @@ -54,7 +55,7 @@ public boolean matches(@NotNull AnvilCraftingContainer container, Level level) { @SuppressWarnings({"BooleanMethodIsAlwaysInverted", "UnusedReturnValue"}) public boolean craft(@NotNull AnvilCraftingContainer container, Level level) { if (!this.matches(container, level)) return false; - BlockPos pos = new BlockPos(container.pos()); + BlockPos pos = new BlockPos(container.getPos()); for (BlockState result : this.results) { pos = pos.below(); level.setBlockAndUpdate(pos, result); diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipeBuilder.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipeBuilder.java index 36589ddcf..85cf281e1 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipeBuilder.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/block/BlockAnvilRecipeBuilder.java @@ -31,6 +31,7 @@ import java.util.stream.Stream; @SuppressWarnings("unused") +@Deprecated public class BlockAnvilRecipeBuilder implements RecipeBuilder { @Getter private final RecipeCategory category; diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipe.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipe.java index 1b8205ce5..aa467429a 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipe.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipe.java @@ -36,6 +36,8 @@ import java.util.Set; @Getter +@Deprecated +@SuppressWarnings("ClassCanBeRecord") public class ItemAnvilRecipe implements Recipe { private final ResourceLocation id; private final NonNullList recipeItems; @@ -44,6 +46,7 @@ public class ItemAnvilRecipe implements Recipe { private final List results; private final Location resultLocation; private final boolean isAnvilDamage; + public ItemAnvilRecipe(ResourceLocation id, NonNullList recipeItems, Location location, NonNullList components, List results, Location resultLocation, boolean isAnvilDamage) { this.id = id; this.recipeItems = recipeItems; @@ -53,15 +56,16 @@ public ItemAnvilRecipe(ResourceLocation id, NonNullList recipeIte this.resultLocation = resultLocation; this.isAnvilDamage = isAnvilDamage; } + @Override public boolean matches(@NotNull AnvilCraftingContainer container, Level level) { - BlockPos pos = new BlockPos(container.pos()); + BlockPos pos = new BlockPos(container.getPos()); for (Component component : this.components) { pos = pos.below(); BlockState state = level.getBlockState(pos); if (!component.test(state)) return false; } - pos = new BlockPos(container.pos()); + pos = new BlockPos(container.getPos()); if (this.location == Location.IN) pos = pos.below(); if (this.location == Location.UNDER) pos = pos.below(2); AABB aabb = new AABB(pos); @@ -78,10 +82,11 @@ public boolean matches(@NotNull AnvilCraftingContainer container, Level level) { }); return recipeItems.isEmpty(); } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean craft(@NotNull AnvilCraftingContainer container, Level level) { if (!this.matches(container, level)) return false; - BlockPos pos = new BlockPos(container.pos()); + BlockPos pos = new BlockPos(container.getPos()); if (this.location == Location.IN) pos = pos.below(); if (this.location == Location.UNDER) pos = pos.below(2); List itemEntities = level.getEntities(EntityTypeTest.forClass(ItemEntity.class), new AABB(pos), Entity::isAlive); @@ -113,39 +118,49 @@ public boolean craft(@NotNull AnvilCraftingContainer container, Level level) { } return true; } + @Override public @NotNull ItemStack assemble(AnvilCraftingContainer container, RegistryAccess registryAccess) { return this.getResultItem(registryAccess).copy(); } + @Override public boolean canCraftInDimensions(int width, int height) { return true; } + @Override public @NotNull ItemStack getResultItem(RegistryAccess registryAccess) { return this.results.isEmpty() ? ItemStack.EMPTY : this.results.get(0); } + @Override public @NotNull RecipeSerializer getSerializer() { return Serializer.INSTANCE; } + @Override public @NotNull RecipeType getType() { return Type.INSTANCE; } + public @NotNull NonNullList getTagIngredients() { return this.recipeItems; } + public static class Type implements RecipeType { public static final Type INSTANCE = new Type(); + private Type() { } } - + public static class Serializer implements RecipeSerializerBase { public static final Serializer INSTANCE = new Serializer(); + private Serializer() { } + @Override public @NotNull ItemAnvilRecipe fromJson(ResourceLocation id, JsonObject json) { NonNullList input = shapelessFromJson(GsonHelper.getAsJsonArray(json, "ingredients")); @@ -160,6 +175,7 @@ private Serializer() { boolean isAnvilDamage = json.has("is_anvil_damage") && json.get("is_anvil_damage").getAsBoolean(); return new ItemAnvilRecipe(id, input, location, components, results, resultLocation, isAnvilDamage); } + @Override public @NotNull ItemAnvilRecipe fromNetwork(ResourceLocation id, @NotNull FriendlyByteBuf buffer) { NonNullList ingredients = NonNullList.withSize(buffer.readVarInt(), TagIngredient.EMPTY); @@ -176,6 +192,7 @@ private Serializer() { boolean isAnvilDamage = buffer.readBoolean(); return new ItemAnvilRecipe(id, ingredients, location, components, results, resultLocation, isAnvilDamage); } + @Override public void toNetwork(@NotNull FriendlyByteBuf buffer, @NotNull ItemAnvilRecipe recipe) { buffer.writeVarInt(recipe.getTagIngredients().size()); @@ -195,12 +212,14 @@ public void toNetwork(@NotNull FriendlyByteBuf buffer, @NotNull ItemAnvilRecipe buffer.writeBoolean(recipe.isAnvilDamage); } } - + public enum Location { UP, UNDER, IN; + public @NotNull String getId() { return this.name().toLowerCase(); } + public static Location byId(@NotNull String id) { return Location.valueOf(id.toUpperCase()); } diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipeBuilder.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipeBuilder.java index d9a5195a0..72224c810 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipeBuilder.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/item/ItemAnvilRecipeBuilder.java @@ -34,6 +34,7 @@ import java.util.function.Consumer; @SuppressWarnings("unused") +@Deprecated public class ItemAnvilRecipeBuilder implements RecipeBuilder { @Getter private final RecipeCategory category; diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/DamageAnvil.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/DamageAnvil.java new file mode 100644 index 000000000..c83b60985 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/DamageAnvil.java @@ -0,0 +1,54 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.outcome; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; +import lombok.Getter; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import org.jetbrains.annotations.NotNull; + +@Getter +public class DamageAnvil implements RecipeOutcome { + private final String type = "damage_anvil"; + private final double chance; + + public DamageAnvil(double chance) { + this.chance = chance; + } + + public DamageAnvil() { + this(1.0); + } + + public DamageAnvil(@NotNull FriendlyByteBuf buffer) { + this(buffer.readDouble()); + } + + public DamageAnvil(@NotNull JsonObject serializedRecipe) { + if (serializedRecipe.has("chance")) { + this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance"); + } else this.chance = 1.0; + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + container.setAnvilDamage(true); + return true; + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeDouble(this.chance); + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("type", this.getType()); + object.addProperty("chance", this.chance); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/RunCommand.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/RunCommand.java new file mode 100644 index 000000000..ed565195d --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/RunCommand.java @@ -0,0 +1,97 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.outcome; + +import com.google.gson.*; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; +import lombok.Getter; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class RunCommand implements RecipeOutcome { + @Getter + private final String type = "run_command"; + private final Vec3 offset; + private final double chance; + private final String command; + + public RunCommand(Vec3 offset, double chance, String command) { + this.offset = offset; + this.chance = chance; + this.command = command; + } + + public RunCommand(@NotNull FriendlyByteBuf buffer) { + this.offset = new Vec3(buffer.readVector3f()); + this.chance = buffer.readDouble(); + this.command = buffer.readUtf(); + } + + public RunCommand(@NotNull JsonObject serializedRecipe) { + double[] vec3 = {0.0d, 0.0d, 0.0d}; + if (serializedRecipe.has("offset")) { + JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset"); + for (int i = 0; i < array.size() && i < 3; i++) { + JsonElement element = array.get(i); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + vec3[i] = element.getAsDouble(); + } else + throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); + } + } + this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (serializedRecipe.has("chance")) { + this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance"); + } else this.chance = 1.0; + this.command = GsonHelper.getAsString(serializedRecipe, "command"); + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + if (!(level instanceof ServerLevel serverLevel)) return true; + FallingBlockEntity entity = container.getEntity(); + CommandSourceStack stack = new CommandSourceStack(entity, this.offset, new Vec2(entity.getXRot(), entity.getYRot()), + serverLevel, + (level.getServer() instanceof DedicatedServer server) ? server.getProperties().functionPermissionLevel : 2, + "Anvil", Component.literal("Anvil"), serverLevel.getServer(), entity + ); + try { + serverLevel.getServer().getCommands().getDispatcher().execute(this.command, stack); + } catch (CommandSyntaxException exception) { + AnvilCraft.LOGGER.printStackTrace(exception); + } + return false; + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeDouble(this.chance); + buffer.writeUtf(this.command); + } + + @Override + public JsonElement toJson() { + double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()}; + JsonArray offset = new JsonArray(); + for (double v : vec3) offset.add(new JsonPrimitive(v)); + JsonObject object = new JsonObject(); + object.addProperty("type", this.getType()); + object.add("offset", offset); + object.addProperty("chance", this.chance); + object.addProperty("command", this.command); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SetBlock.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SetBlock.java new file mode 100644 index 000000000..ea17802d7 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SetBlock.java @@ -0,0 +1,87 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.outcome; + +import com.google.gson.*; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; +import dev.dubhe.anvilcraft.util.IBlockStateInjector; +import lombok.Getter; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class SetBlock implements RecipeOutcome { + @Getter + private final String type = "set_block"; + private final Vec3 offset; + private final double chance; + private final BlockState result; + + public SetBlock(Vec3 offset, double chance, BlockState result) { + this.offset = offset; + this.chance = chance; + this.result = result; + } + + public SetBlock(@NotNull FriendlyByteBuf buffer) { + this.offset = new Vec3(buffer.readVector3f()); + this.chance = buffer.readDouble(); + this.result = IBlockStateInjector.fromJson(AnvilCraft.GSON.fromJson(buffer.readUtf(), JsonElement.class)); + } + + public SetBlock(@NotNull JsonObject serializedRecipe) { + double[] vec3 = {0.0d, 0.0d, 0.0d}; + if (serializedRecipe.has("offset")) { + JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset"); + for (int i = 0; i < array.size() && i < 3; i++) { + JsonElement element = array.get(i); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + vec3[i] = element.getAsDouble(); + } else + throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); + } + } + this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (serializedRecipe.has("chance")) { + this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance"); + } else this.chance = 1.0; + this.result = IBlockStateInjector.fromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result")); + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + RandomSource random = level.getRandom(); + if (random.nextDouble() > this.chance) return true; + BlockPos pos = container.getPos(); + Vec3 vec3 = pos.getCenter().add(this.offset); + BlockPos blockPos = BlockPos.containing(vec3.x, vec3.y, vec3.z); + return level.setBlock(blockPos, this.result, 3); + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeDouble(this.chance); + buffer.writeUtf(this.result.toJson().toString()); + } + + @Override + public JsonElement toJson() { + double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()}; + JsonArray offset = new JsonArray(); + for (double v : vec3) offset.add(new JsonPrimitive(v)); + JsonObject object = new JsonObject(); + object.addProperty("type", this.getType()); + object.add("offset", offset); + object.addProperty("chance", this.chance); + object.add("result", this.result.toJson()); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnExperience.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnExperience.java new file mode 100644 index 000000000..cdc9f0b4e --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnExperience.java @@ -0,0 +1,79 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.outcome; + +import com.google.gson.*; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; +import lombok.Getter; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class SpawnExperience implements RecipeOutcome { + @Getter + private final String type = "spawn_experience"; + private final Vec3 offset; + private final double chance; + private final int experience; + + public SpawnExperience(Vec3 offset, double chance, int experience) { + this.offset = offset; + this.chance = chance; + this.experience = experience; + } + + public SpawnExperience(@NotNull FriendlyByteBuf buffer) { + this.offset = new Vec3(buffer.readVector3f()); + this.chance = buffer.readDouble(); + this.experience = buffer.readVarInt(); + } + + public SpawnExperience(@NotNull JsonObject serializedRecipe) { + double[] vec3 = {0.0d, 0.0d, 0.0d}; + if (serializedRecipe.has("offset")) { + JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset"); + for (int i = 0; i < array.size() && i < 3; i++) { + JsonElement element = array.get(i); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + vec3[i] = element.getAsDouble(); + } else + throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); + } + } + this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (serializedRecipe.has("chance")) { + this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance"); + } else this.chance = 1.0; + this.experience = GsonHelper.getAsInt(serializedRecipe, "experience"); + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + ExperienceOrb entity = new ExperienceOrb(level,this.offset.x,this.offset.y,this.offset.z,this.experience); + return level.addFreshEntity(entity); + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeDouble(this.chance); + buffer.writeVarInt(this.experience); + } + + @Override + public JsonElement toJson() { + double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()}; + JsonArray offset = new JsonArray(); + for (double v : vec3) offset.add(new JsonPrimitive(v)); + JsonObject object = new JsonObject(); + object.addProperty("type", this.getType()); + object.add("offset", offset); + object.addProperty("chance", this.chance); + object.addProperty("experience", this.experience); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java new file mode 100644 index 000000000..a78444be8 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java @@ -0,0 +1,87 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.outcome; + +import com.google.gson.*; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; +import dev.dubhe.anvilcraft.util.IItemStackInjector; +import lombok.Getter; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class SpawnItem implements RecipeOutcome { + @Getter + private final String type = "spawn_item"; + private final Vec3 offset; + private final double chance; + private final ItemStack result; + + public SpawnItem(Vec3 offset, double chance, ItemStack result) { + this.offset = offset; + this.chance = chance; + this.result = result; + } + + public SpawnItem(@NotNull FriendlyByteBuf buffer) { + this.offset = new Vec3(buffer.readVector3f()); + this.chance = buffer.readDouble(); + this.result = buffer.readItem(); + } + + public SpawnItem(@NotNull JsonObject serializedRecipe) { + double[] vec3 = {0.0d, 0.0d, 0.0d}; + if (serializedRecipe.has("offset")) { + JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset"); + for (int i = 0; i < array.size() && i < 3; i++) { + JsonElement element = array.get(i); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + vec3[i] = element.getAsDouble(); + } else + throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); + } + } + this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (serializedRecipe.has("chance")) { + this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance"); + } else this.chance = 1.0; + this.result = IItemStackInjector.fromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result")); + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + RandomSource random = level.getRandom(); + if (random.nextDouble() > this.chance) return true; + BlockPos pos = container.getPos(); + Vec3 vec3 = pos.getCenter().add(this.offset); + ItemEntity entity = new ItemEntity(level, vec3.x, vec3.y, vec3.z, this.result.copy(), 0.0d, 0.0d, 0.0d); + return level.addFreshEntity(entity); + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeDouble(this.chance); + buffer.writeItem(this.result); + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()}; + JsonArray offset = new JsonArray(); + for (double v : vec3) offset.add(new JsonPrimitive(v)); + object.addProperty("type", this.getType()); + object.add("offset", offset); + object.addProperty("chance", this.chance); + object.add("result", this.result.toJson()); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasBlock.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasBlock.java new file mode 100644 index 000000000..96e2c1cd3 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasBlock.java @@ -0,0 +1,83 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.predicate; + +import com.google.gson.*; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipePredicate; +import lombok.Getter; +import net.minecraft.advancements.critereon.BlockPredicate; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +public class HasBlock implements RecipePredicate { + @Getter + private final String type = "has_block"; + protected final Vec3 offset; + protected final BlockPredicate matchBlock; + + public HasBlock(Vec3 offset, BlockPredicate matchBlock) { + this.offset = offset; + this.matchBlock = matchBlock; + } + + public HasBlock(JsonObject serializedRecipe) { + JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset"); + double[] vec3 = {0.0d, 0.0d, 0.0d}; + for (int i = 0; i < array.size() && i < 3; i++) { + JsonElement element = array.get(i); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + vec3[i] = element.getAsDouble(); + } else throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); + } + this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (!serializedRecipe.has("match_block")) throw new JsonSyntaxException("Missing match_block"); + this.matchBlock = BlockPredicate.fromJson(serializedRecipe.get("match_block")); + } + + public HasBlock(@NotNull FriendlyByteBuf buffer) { + this.offset = new Vec3(buffer.readVector3f()); + this.matchBlock = BlockPredicate.fromJson(AnvilCraft.GSON.fromJson(buffer.readUtf(), JsonElement.class)); + } + + @Override + public boolean matches(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + if (!(level instanceof ServerLevel level1)) return false; + BlockPos pos = container.getPos(); + Vec3 vec3 = pos.getCenter().add(this.offset); + BlockPos blockPos = BlockPos.containing(vec3.x, vec3.y, vec3.z); + return this.matchBlock.matches(level1, blockPos); + } + + @Override + public boolean process(AnvilCraftingContainer container) { + return true; + } + + @Override + public void toNetwork(FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeUtf(this.matchBlock.serializeToJson().toString()); + } + + @Override + public @NotNull JsonElement toJson() { + double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()}; + JsonArray offset = new JsonArray(); + for (double v : vec3) { + offset.add(new JsonPrimitive(v)); + } + JsonElement matchBlock = this.matchBlock.serializeToJson(); + JsonObject object = new JsonObject(); + object.addProperty("type", this.getType()); + object.add("offset", offset); + object.add("match_block", matchBlock); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasBlockIngredient.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasBlockIngredient.java new file mode 100644 index 000000000..e19a736aa --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasBlockIngredient.java @@ -0,0 +1,38 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.predicate; + +import com.google.gson.JsonObject; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import lombok.Getter; +import net.minecraft.advancements.critereon.BlockPredicate; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +@Getter +public class HasBlockIngredient extends HasBlock { + private final String type = "has_block_ingredient"; + + public HasBlockIngredient(Vec3 offset, BlockPredicate matchBlock) { + super(offset, matchBlock); + } + + public HasBlockIngredient(JsonObject serializedRecipe) { + super(serializedRecipe); + } + + public HasBlockIngredient(@NotNull FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + BlockPos pos = container.getPos(); + Vec3 vec3 = pos.getCenter().add(this.offset); + BlockPos blockPos = BlockPos.containing(vec3.x, vec3.y, vec3.z); + return level.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java new file mode 100644 index 000000000..d99afc448 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java @@ -0,0 +1,92 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.predicate; + +import com.google.common.base.Predicates; +import com.google.gson.*; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipePredicate; +import lombok.Getter; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.entity.EntityTypeTest; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class HasItem implements RecipePredicate { + @Getter + private final String type = "has_item"; + protected final Vec3 offset; + protected final ItemPredicate matchItem; + + public HasItem(Vec3 offset, ItemPredicate matchItem) { + this.offset = offset; + this.matchItem = matchItem; + } + + public HasItem(JsonObject serializedRecipe) { + JsonArray array = GsonHelper.getAsJsonArray(serializedRecipe, "offset"); + double[] vec3 = {0.0d, 0.0d, 0.0d}; + for (int i = 0; i < array.size() && i < 3; i++) { + JsonElement element = array.get(i); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + vec3[i] = element.getAsDouble(); + } else throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); + } + this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (!serializedRecipe.has("match_item")) throw new JsonSyntaxException("Missing match_item"); + this.matchItem = ItemPredicate.fromJson(serializedRecipe.get("match_item")); + } + + public HasItem(@NotNull FriendlyByteBuf buffer) { + this.offset = new Vec3(buffer.readVector3f()); + this.matchItem = ItemPredicate.fromJson(AnvilCraft.GSON.fromJson(buffer.readUtf(), JsonElement.class)); + } + + @Override + public boolean matches(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + BlockPos pos = container.getPos(); + AABB aabb = new AABB(pos).move(this.offset); + List entities = level.getEntities(EntityTypeTest.forClass(ItemEntity.class), aabb, Predicates.alwaysTrue()); + for (ItemEntity entity : entities) { + ItemStack item = entity.getItem(); + if (this.matchItem.matches(item)) return true; + } + return false; + } + + @Override + public boolean process(AnvilCraftingContainer container) { + return true; + } + + @Override + public void toNetwork(@NotNull FriendlyByteBuf buffer) { + buffer.writeUtf(this.getType()); + buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeUtf(this.matchItem.serializeToJson().toString()); + } + + @Override + public @NotNull JsonElement toJson() { + double[] vec3 = {this.offset.x(), this.offset.y(), this.offset.z()}; + JsonArray offset = new JsonArray(); + for (double v : vec3) { + offset.add(new JsonPrimitive(v)); + } + JsonElement matchItem = this.matchItem.serializeToJson(); + JsonObject object = new JsonObject(); + object.addProperty("type", this.getType()); + object.add("offset", offset); + object.add("match_item", matchItem); + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItemIngredient.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItemIngredient.java new file mode 100644 index 000000000..754e33535 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItemIngredient.java @@ -0,0 +1,77 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil.predicate; + +import com.google.common.base.Predicates; +import com.google.gson.JsonObject; +import dev.dubhe.anvilcraft.data.recipe.TagIngredient; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import lombok.Getter; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.entity.EntityTypeTest; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class HasItemIngredient extends HasItem { + private final String type = "has_item_ingredient"; + + public HasItemIngredient(Vec3 offset, ItemPredicate matchItem) { + super(offset, matchItem); + } + + public HasItemIngredient(JsonObject serializedRecipe) { + super(serializedRecipe); + } + + public HasItemIngredient(@NotNull FriendlyByteBuf buffer) { + super(buffer); + } + + public static @NotNull HasItemIngredient of(Vec3 offset, @NotNull Ingredient ingredient) { + return HasItemIngredient.of(offset, ingredient, 1); + } + + public static @NotNull HasItemIngredient of(Vec3 offset, @NotNull Ingredient ingredient, int count) { + ItemPredicate.Builder item = ItemPredicate.Builder.item().withCount(MinMaxBounds.Ints.atLeast(count)); + List items = new ArrayList<>(); + for (Ingredient.Value value : ingredient.values) { + if (value instanceof Ingredient.TagValue tagValue) + item.of(tagValue.tag); + if (value instanceof Ingredient.ItemValue itemValue) + items.add(itemValue.item.getItem()); + } + item.of(items.toArray(ItemLike[]::new)); + return new HasItemIngredient(offset, item.build()); + } + + @Override + public boolean process(@NotNull AnvilCraftingContainer container) { + Level level = container.getLevel(); + BlockPos pos = container.getPos(); + AABB aabb = new AABB(pos).move(this.offset); + List entities = level.getEntities(EntityTypeTest.forClass(ItemEntity.class), aabb, Predicates.alwaysTrue()); + for (ItemEntity entity : entities) { + ItemStack item = entity.getItem(); + if (this.matchItem.matches(item)) { + int count = this.matchItem.count.getMin() != null ? this.matchItem.count.getMin() : 1; + item.shrink(count); + entity.setItem(item.copy()); + return true; + } + } + return false; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/event/AnvilEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/AnvilEventListener.java index 1104bd4e3..2a758e472 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/AnvilEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/AnvilEventListener.java @@ -5,6 +5,7 @@ import dev.dubhe.anvilcraft.api.event.entity.AnvilFallOnLandEvent; import dev.dubhe.anvilcraft.api.event.entity.AnvilHurtEntityEvent; import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.data.recipe.anvil.block.BlockAnvilRecipe; import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; import dev.dubhe.anvilcraft.init.ModBlockTags; @@ -34,6 +35,7 @@ import java.util.List; import java.util.Optional; +@SuppressWarnings("deprecation") public class AnvilEventListener { @SubscribeEvent public void onLand(@NotNull AnvilFallOnLandEvent event) { @@ -42,11 +44,14 @@ public void onLand(@NotNull AnvilFallOnLandEvent event) { AnvilCraftingContainer container = new AnvilCraftingContainer(level, pos, event.getEntity()); MinecraftServer server = level.getServer(); if (null == server) return; - Optional optional = server.getRecipeManager().getRecipeFor(ModRecipeTypes.ANVIL_ITEM, container, level); + Optional optional = server.getRecipeManager().getRecipeFor(ModRecipeTypes.ANVIL_RECIPE, container, level); if (optional.isEmpty()) { - Optional optional1 = server.getRecipeManager().getRecipeFor(ModRecipeTypes.ANVIL_BLOCK, container, level); - optional1.ifPresent(blockAnvilRecipe -> blockProcess(blockAnvilRecipe, container, level, event)); - } else itemProcess(optional.get(), container, level, event); + Optional optional1 = server.getRecipeManager().getRecipeFor(ModRecipeTypes.ANVIL_ITEM, container, level); + if (optional1.isEmpty()) { + Optional optional2 = server.getRecipeManager().getRecipeFor(ModRecipeTypes.ANVIL_BLOCK, container, level); + optional2.ifPresent(blockAnvilRecipe -> blockProcess(blockAnvilRecipe, container, level, event)); + } else itemProcess(optional1.get(), container, level, event); + } else anvilProcess(optional.get(), container, event); BlockPos belowPos = pos.below(); BlockState state = level.getBlockState(belowPos); if (state.is(Blocks.REDSTONE_BLOCK)) redstoneEMP(level, belowPos); @@ -55,13 +60,22 @@ public void onLand(@NotNull AnvilFallOnLandEvent event) { if (state.is(Blocks.STONECUTTER)) brokeBlock(level, belowPos.above(), event); } + private void anvilProcess(AnvilRecipe recipe, AnvilCraftingContainer container, AnvilFallOnLandEvent event) { + int counts = 0; + while (counts < AnvilCraft.config.anvilEfficiency) { + if (!recipe.craft(container)) break; + counts++; + } + if (container.isAnvilDamage()) event.setAnvilDamage(true); + } + private void itemProcess(ItemAnvilRecipe recipe, AnvilCraftingContainer container, Level level, AnvilFallOnLandEvent event) { int counts = 0; while (counts < AnvilCraft.config.anvilEfficiency) { if (!recipe.craft(container, level)) break; counts++; } - BlockPos resultPos = new BlockPos(container.pos()); + BlockPos resultPos = new BlockPos(container.getPos()); if (recipe.getResultLocation() == ItemAnvilRecipe.Location.IN) resultPos = resultPos.below(); if (recipe.getResultLocation() == ItemAnvilRecipe.Location.UNDER) resultPos = resultPos.below(2); for (ItemStack itemStack : recipe.getResults()) { diff --git a/src/main/java/dev/dubhe/anvilcraft/event/ServerEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/ServerEventListener.java index 34cb65838..4a1d1fb6c 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/ServerEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/ServerEventListener.java @@ -6,9 +6,11 @@ import dev.dubhe.anvilcraft.api.event.SubscribeEvent; import dev.dubhe.anvilcraft.api.event.server.ServerEndDataPackReloadEvent; import dev.dubhe.anvilcraft.api.event.server.ServerStartedEvent; -import dev.dubhe.anvilcraft.data.recipe.Component; -import dev.dubhe.anvilcraft.data.recipe.TagIngredient; -import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; +import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.SpawnItem; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasBlock; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItemIngredient; +import net.minecraft.advancements.critereon.BlockPredicate; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; @@ -17,10 +19,13 @@ import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.*; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ServerEventListener { @SubscribeEvent @@ -72,56 +77,41 @@ public static void processRecipes(@NotNull MinecraftServer server) { if (oldRecipe instanceof ShapelessRecipe recipe) { if (recipe.getIngredients().size() == 1) { location = AnvilCraft.of("smash/" + id.getPath()); + AnvilRecipe recipe1 = new AnvilRecipe(location, result); Ingredient ingredient = recipe.getIngredients().get(0); - TagIngredient ingredient1 = TagIngredient.of(ingredient); - ItemAnvilRecipe recipe1 = new ItemAnvilRecipe( - location, - NonNullList.withSize(1, ingredient1), - ItemAnvilRecipe.Location.UP, - NonNullList.withSize(1, Component.of(Blocks.IRON_TRAPDOOR)), - List.of(result), - ItemAnvilRecipe.Location.IN, - false - ); - return new Pair<>(location, recipe1); - } else if(isIngredientsSame(recipe.getIngredients())){ - Ingredient ingredient = recipe.getIngredients().get(0); - TagIngredient ingredient1 = TagIngredient.of(ingredient); - int ingredientCount = recipe.getIngredients().size(); - ItemAnvilRecipe recipe1 = new ItemAnvilRecipe( - location, - NonNullList.withSize(ingredientCount, ingredient1), - ItemAnvilRecipe.Location.IN, - NonNullList.withSize(1, Component.of(Blocks.CAULDRON)), - List.of(result), - ItemAnvilRecipe.Location.IN, - false + recipe1.addPredicates( + HasItemIngredient.of(Vec3.ZERO, ingredient), + new HasBlock(new Vec3(0.0, -1.0, 0.0), BlockPredicate.Builder.block().of(Blocks.IRON_TRAPDOOR).build()) ); + recipe1.addOutcomes(new SpawnItem(new Vec3(0.0, -1.0, 0.0), 1.0, result.copy())); return new Pair<>(location, recipe1); + } else if (isIngredientsSame(recipe.getIngredients())) { + return getResourceLocationRecipePair(result, location, recipe.getIngredients()); } } else if (oldRecipe instanceof ShapedRecipe recipe) { List ingredients = recipe.getIngredients(); if (isIngredientsSame(ingredients)) { if (recipe.getHeight() != recipe.getWidth()) return null; if (recipe.getIngredients().size() != recipe.getWidth() * recipe.getHeight()) return null; - Ingredient ingredient = recipe.getIngredients().get(0); - TagIngredient ingredient1 = TagIngredient.of(ingredient); - int ingredientCount = recipe.getIngredients().size(); - ItemAnvilRecipe recipe1 = new ItemAnvilRecipe( - location, - NonNullList.withSize(ingredientCount, ingredient1), - ItemAnvilRecipe.Location.IN, - NonNullList.withSize(1, Component.of(Blocks.CAULDRON)), - List.of(result), - ItemAnvilRecipe.Location.IN, - false - ); - return new Pair<>(location, recipe1); + return getResourceLocationRecipePair(result, location, recipe.getIngredients()); } } return null; } + @NotNull + private static Pair> getResourceLocationRecipePair(ItemStack result, ResourceLocation location, @NotNull NonNullList ingredients) { + Ingredient ingredient = ingredients.get(0); + int ingredientCount = ingredients.size(); + AnvilRecipe recipe = new AnvilRecipe(location, result); + recipe.addPredicates( + HasItemIngredient.of(new Vec3(0.0, -1.0, 0.0), ingredient, ingredientCount), + new HasBlock(new Vec3(0.0, -1.0, 0.0), BlockPredicate.Builder.block().of(Blocks.CAULDRON).build()) + ); + recipe.addOutcomes(new SpawnItem(new Vec3(0.0, -1.0, 0.0), 1.0, result.copy())); + return new Pair<>(location, recipe); + } + public static boolean isIngredientsSame(@NotNull List ingredients) { Ingredient ingredient = ingredients.get(0); for (Ingredient ingredient1 : ingredients) { diff --git a/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java b/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java index 57169509b..74a2aea28 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java @@ -2,6 +2,7 @@ import com.mojang.datafixers.util.Pair; import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; import dev.dubhe.anvilcraft.data.recipe.anvil.block.BlockAnvilRecipe; import dev.dubhe.anvilcraft.data.recipe.anvil.item.ItemAnvilRecipe; import dev.dubhe.anvilcraft.data.recipe.crafting_table.ShapedTagRecipe; @@ -24,6 +25,8 @@ public class ModRecipeTypes { public static final @Nullable RecipeType TAG_CRAFTING_SHAPED = ModRecipeTypes.registerRecipeType("tag_crafting_shaped", ShapedTagRecipe.Serializer.INSTANCE, null); public static final RecipeType ANVIL_ITEM = ModRecipeTypes.registerRecipeType("anvil_item_processing", ItemAnvilRecipe.Serializer.INSTANCE, ItemAnvilRecipe.Type.INSTANCE); public static final RecipeType ANVIL_BLOCK = ModRecipeTypes.registerRecipeType("anvil_block_processing", BlockAnvilRecipe.Serializer.INSTANCE, BlockAnvilRecipe.Type.INSTANCE); + public static final RecipeType ANVIL_RECIPE = ModRecipeTypes.registerRecipeType("anvil_processing", AnvilRecipe.Serializer.INSTANCE, AnvilRecipe.Type.INSTANCE); + private static > @Nullable RecipeType registerRecipeType(String id, @Nullable RecipeSerializer serializer, @Nullable RecipeType type) { RECIPE_TYPES.put(id, new Pair<>(serializer, type)); return type; diff --git a/src/main/java/dev/dubhe/anvilcraft/mixin/BlockStateInjector.java b/src/main/java/dev/dubhe/anvilcraft/mixin/BlockStateInjector.java new file mode 100644 index 000000000..29427fb63 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/mixin/BlockStateInjector.java @@ -0,0 +1,36 @@ +package dev.dubhe.anvilcraft.mixin; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.util.IBlockStateInjector; +import net.fabricmc.fabric.api.block.v1.FabricBlockState; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.stream.Collectors; + +@Mixin(BlockState.class) +public abstract class BlockStateInjector extends BlockBehaviour.BlockStateBase implements IBlockStateInjector, FabricBlockState { + protected BlockStateInjector(Block owner, ImmutableMap, Comparable> values, MapCodec propertiesCodec) { + super(owner, values, propertiesCodec); + } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("block", BuiltInRegistries.BLOCK.getKey(this.getBlock()).toString()); + if (!this.getValues().isEmpty()) { + String stringBuilder = '[' + + this.getValues().entrySet().stream().map(PROPERTY_ENTRY_TO_STRING_FUNCTION).collect(Collectors.joining(",")) + + ']'; + object.addProperty("state", stringBuilder); + } + return object; + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/mixin/ItemStackInjector.java b/src/main/java/dev/dubhe/anvilcraft/mixin/ItemStackInjector.java index 1b6679c12..861828b73 100644 --- a/src/main/java/dev/dubhe/anvilcraft/mixin/ItemStackInjector.java +++ b/src/main/java/dev/dubhe/anvilcraft/mixin/ItemStackInjector.java @@ -1,12 +1,16 @@ package dev.dubhe.anvilcraft.mixin; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import dev.dubhe.anvilcraft.util.IItemStackInjector; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentHelper; @@ -54,6 +58,9 @@ public abstract class ItemStackInjector implements IItemStackInjector { @Shadow public abstract CompoundTag getOrCreateTag(); + @Shadow + public abstract Item getItem(); + @Override public ItemStack dataCopy(@NotNull ItemStack stack) { stack.setDamageValue(this.getDamageValue()); @@ -80,7 +87,7 @@ public boolean removeEnchant(Enchantment enchantment) { if (!(tag1 instanceof CompoundTag tag2)) continue; ResourceLocation id = EnchantmentHelper.getEnchantmentId(tag2); ResourceLocation id1 = EnchantmentHelper.getEnchantmentId(enchantment); - if (null == id|| null == id1) return false; + if (null == id || null == id1) return false; if (!id.equals(id1)) continue; listTag.remove(tag1); bl = true; @@ -90,4 +97,13 @@ public boolean removeEnchant(Enchantment enchantment) { this.setTag(tag); return bl; } + + @Override + public JsonElement toJson() { + JsonObject object = new JsonObject(); + object.addProperty("item", BuiltInRegistries.ITEM.getKey(this.getItem()).toString()); + if (this.getCount() > 1) object.addProperty("count", this.getCount()); + if (this.hasTag()) object.addProperty("data", this.getOrCreateTag().toString()); + return object; + } } diff --git a/src/main/java/dev/dubhe/anvilcraft/mixin/ShapedRecipeMixin.java b/src/main/java/dev/dubhe/anvilcraft/mixin/ShapedRecipeMixin.java index dcf9a18df..b95df0ad1 100644 --- a/src/main/java/dev/dubhe/anvilcraft/mixin/ShapedRecipeMixin.java +++ b/src/main/java/dev/dubhe/anvilcraft/mixin/ShapedRecipeMixin.java @@ -13,10 +13,11 @@ @Mixin(ShapedRecipe.class) abstract class ShapedRecipeMixin { - @ModifyExpressionValue(method = "itemStackFromJson", at = @At(value = "INVOKE", target = "Lcom/google/gson/JsonObject;has(Ljava/lang/String;)Z")) + @ModifyExpressionValue(method = "itemStackFromJson", at = @At(value = "INVOKE", target = "Lcom/google/gson/JsonObject;has(Ljava/lang/String;)Z", remap = false)) private static boolean validNbt(boolean original) { return false; } + @ModifyExpressionValue(method = "itemStackFromJson", at = @At(value = "NEW", target = "(Lnet/minecraft/world/level/ItemLike;I)Lnet/minecraft/world/item/ItemStack;")) private static ItemStack readNbt(ItemStack original, JsonObject stackObject) { if (stackObject.has("data")) { diff --git a/src/main/java/dev/dubhe/anvilcraft/util/IBlockStateInjector.java b/src/main/java/dev/dubhe/anvilcraft/util/IBlockStateInjector.java new file mode 100644 index 000000000..188ce03e3 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/util/IBlockStateInjector.java @@ -0,0 +1,72 @@ +package dev.dubhe.anvilcraft.util; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.datafixers.util.Pair; +import net.minecraft.commands.arguments.blocks.BlockStateParser; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.HolderOwner; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +public interface IBlockStateInjector { + @SuppressWarnings("DuplicatedCode") + static @NotNull BlockState fromJson(JsonElement stateJson) { + if (!stateJson.isJsonObject()) throw new JsonSyntaxException("Expected item to be object"); + JsonObject object = stateJson.getAsJsonObject(); + if (!object.has("block")) throw new JsonSyntaxException("The field block is missing"); + JsonElement blockElement = object.get("block"); + if (!blockElement.isJsonPrimitive()) throw new JsonSyntaxException("Expected item to be string"); + StringBuilder block = new StringBuilder(blockElement.getAsString()); + if (object.has("state")) { + block.append(GsonHelper.getAsString(object,"state")); + } + HolderLookup blocks = new BlockHolderLookup(); + BlockStateParser.BlockResult blockResult; + try { + blockResult = BlockStateParser.parseForBlock(blocks, block.toString(), true); + } catch (CommandSyntaxException e) { + throw new RuntimeException(e); + } + return blockResult.blockState(); + } + + default JsonElement toJson() { + return new JsonObject(); + } + + class BlockHolderLookup implements HolderLookup, HolderOwner { + @Override + public @NotNull Stream> listElements() { + return BuiltInRegistries.BLOCK.stream().map(BuiltInRegistries.BLOCK::getResourceKey).filter(Optional::isPresent).map(key -> BuiltInRegistries.BLOCK.getHolderOrThrow(key.get())); + } + + @Override + public @NotNull Stream> listTags() { + return BuiltInRegistries.BLOCK.getTags().map(Pair::getSecond); + } + + @Override + public @NotNull Optional> get(ResourceKey resourceKey) { + return Optional.of(BuiltInRegistries.BLOCK.getHolderOrThrow(resourceKey)); + } + + @Override + public @NotNull Optional> get(TagKey tagKey) { + return BuiltInRegistries.BLOCK.getTag(tagKey); + } + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/util/IItemStackInjector.java b/src/main/java/dev/dubhe/anvilcraft/util/IItemStackInjector.java index 69ca7727b..e80e9700d 100644 --- a/src/main/java/dev/dubhe/anvilcraft/util/IItemStackInjector.java +++ b/src/main/java/dev/dubhe/anvilcraft/util/IItemStackInjector.java @@ -1,7 +1,17 @@ package dev.dubhe.anvilcraft.util; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.TagParser; +import net.minecraft.util.GsonHelper; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.enchantment.Enchantment; +import org.jetbrains.annotations.NotNull; public interface IItemStackInjector { default ItemStack dataCopy(ItemStack stack) { @@ -11,4 +21,32 @@ default ItemStack dataCopy(ItemStack stack) { default boolean removeEnchant(Enchantment enchantment) { return false; } + + @SuppressWarnings("DuplicatedCode") + static @NotNull ItemStack fromJson(@NotNull JsonElement element) { + if (!element.isJsonObject()) throw new JsonSyntaxException("Expected item to be string"); + JsonObject object = element.getAsJsonObject(); + Item item = ShapedRecipe.itemFromJson(object); + int i = GsonHelper.getAsInt(object, "count", 1); + if (i < 1) { + throw new JsonSyntaxException("Invalid output count: " + i); + } + ItemStack stack = item.getDefaultInstance(); + stack.setCount(i); + if (object.has("data")) { + if (!object.get("data").isJsonPrimitive()) throw new JsonSyntaxException("Expected item to be string"); + CompoundTag tag; + try { + tag = TagParser.parseTag(object.get("data").getAsString()); + } catch (CommandSyntaxException ignored) { + throw new JsonSyntaxException("Invalid NBT string"); + } + stack.setTag(stack.getOrCreateTag().merge(tag)); + } + return stack; + } + + default JsonElement toJson() { + return new JsonObject(); + } } diff --git a/src/main/resources/anvilcraft.accesswidener b/src/main/resources/anvilcraft.accesswidener index 579a46c48..408ac50bf 100644 --- a/src/main/resources/anvilcraft.accesswidener +++ b/src/main/resources/anvilcraft.accesswidener @@ -1,11 +1,13 @@ accessWidener v1 named -extendable method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen renderSlot (Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/inventory/Slot;)V +accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue accessible class net/minecraft/server/MinecraftServer$ReloadableResources +accessible class net/minecraft/world/item/crafting/Ingredient$Value +accessible class net/minecraft/world/item/crafting/Ingredient$TagValue +extendable method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen renderSlot (Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/inventory/Slot;)V accessible method net/minecraft/server/MinecraftServer$ReloadableResources resourceManager ()Lnet/minecraft/server/packs/resources/CloseableResourceManager; accessible field net/minecraft/world/item/crafting/RecipeManager recipes Ljava/util/Map; accessible field net/minecraft/world/item/crafting/Ingredient values [Lnet/minecraft/world/item/crafting/Ingredient$Value; -accessible class net/minecraft/world/item/crafting/Ingredient$Value -accessible class net/minecraft/world/item/crafting/Ingredient$TagValue accessible field net/minecraft/world/item/crafting/Ingredient$TagValue tag Lnet/minecraft/tags/TagKey; -accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue accessible field net/minecraft/world/item/crafting/Ingredient$ItemValue item Lnet/minecraft/world/item/ItemStack; +accessible field net/minecraft/advancements/critereon/ItemPredicate count Lnet/minecraft/advancements/critereon/MinMaxBounds$Ints; +accessible field net/minecraft/world/level/block/state/StateHolder PROPERTY_ENTRY_TO_STRING_FUNCTION Ljava/util/function/Function; diff --git a/src/main/resources/anvilcraft.mixins.json b/src/main/resources/anvilcraft.mixins.json index caf2be0c0..0a4a9511d 100644 --- a/src/main/resources/anvilcraft.mixins.json +++ b/src/main/resources/anvilcraft.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "AnvilBlockMixin", + "BlockStateInjector", "ClientboundUpdateRecipesPacketMixin", "ItemEntityMixin", "ItemStackInjector", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6fd1aa903..5be5ede7c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -39,6 +39,9 @@ "loom:injected_interfaces": { "net/minecraft/class_1799": [ "dev/dubhe/anvilcraft/util/IItemStackInjector" + ], + "net/minecraft/class_2680": [ + "dev/dubhe/anvilcraft/util/IBlockStateInjector" ] } }