====== 创建自定义的合成配方类型 ====== 在此界面,我们将创建我们自己的合成配方,包括无序合成的版本! 我们将不使用任何原版的类型,创建一个完全自定义的合成配方类型! 你也可以尝试制作其他的配方类型。 [[tutorial:zh_cn:cooking_recipe_type|添加烹饪配方类型]] ===== 添加合成方块 ===== 我们先要创建一个能打开合成界面的方块,关于合成的其他类型之后再说。 public class TestRecipeBlock extends Block { private static final Text TITLE = new TranslatableText("container.test_crafting"); public TestRecipeBlock(Settings settings) { super(settings); } @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { if(world.isClient) { return ActionResult.SUCCESS; } else { player.openHandledScreen(state.createScreenHandlerFactory(world, pos)); player.incrementStat(Stats.INTERACT_WITH_CRAFTING_TABLE); return ActionResult.CONSUME; } } @Override public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) { return new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> { return new TestCraftingScreenHandler(i, playerInventory, ScreenHandlerContext.create(world, pos)); }, TITLE); } } 现在我们得注册这个方块(Block)和其对应的在物品栏显示的物品(BlockItem)。 public class ExampleCustomRecipeMod implements ModInitializer { public static final TestRecipeBlock TEST_RECIPE_BLOCK = new TestRecipeBlock(FabricBlockSettings.of(Material.METAL)); @Override public void onInitialize() { // Resuming later... } } ===== 创建配方类型 ===== 现在我们要做的是该文档最有意思的部分,即创建配方类型。 ==== 创建有序合成配方类型 ==== 有序合成配方是配方类型中的一种,其要求合成原料被放置在特定的物品槽中,常被使用于合成原料需要以一定方式放置的合成配方中。 Recipe 接口需要一个 Inventory 类作为类型参数。任何能放置合成原料的物品栏都是可行的。这里我们将使用 CraftingInventory。 public class TestRecipe implements Recipe { //你想添加多少个原料(input)都是可以的 //总是使用 Ingredient 类是重要的,因为这样你可以支持具有 nbt 标签的物品。 private final Ingredient inputA; private final Ingredient inputB; private final ItemStack result; private final Identifier id; public TestRecipe(Identifier id, ItemStack result, Ingredient inputA, Ingredient inputB) { this.id = id; this.inputA = inputA; this.inputB = inputB; this.result = result; } public Ingredient getInputA() { return this.inputA; } public Ingredient getInputB() { return this.inputB; } @Override public ItemStack getOutput() { return this.result; } @Override public Identifier getId() { return this.id; } //[...] } 之后,我们需要关注合成时运行的代码,返回正确的合成结果。其中,我们应该使用 ''this.getOutput().copy()''(来避免浅拷贝的问题),并且 ''fits'' 方法应该返回 true。 public class TestRecipe implements Recipe { //[...] @Override public ItemStack craft(CraftingInventory inv) { return this.getOutput().copy(); } @Override public boolean fits(int width, int height) { return true; } } 在 ''matches'' 方法中,当物品栏中的原料和配方中的排列顺序和物品一致时,返回 true。 public class TestRecipe implements Recipe { //[...] @Override public boolean matches(CraftingInventory inv, World world) { if(inv.size(0) < 2) return false; return inputA.test(inventory.getStack(0)) && inputB.test(inventory.getStack(1)); } } 现在我们需要给予这个配方一个''类型'',你所要做的是创建一个继承 RecipeType 的实例。 public class TestRecipe implements Recipe { //[...] public static class Type implements RecipeType { private Type() {} public static final Type INSTANCE = new Type(); public static final String ID = "test_recipe"; } @Override pubilc RecipeType getType() { return Type.INSTANCE; } } 之后还需要 RecipeSerializer ,但原作者并没有写完此部分。如果你想继续,请在下面的来源中找到此部分。 来源: [[https://github.com/natanfudge/fabric-docs/blob/master/newdocs/Modding-Tutorials/Crafting-Recipes/defining-custom-crafting-recipes.md|Defining Custom Crafting Recipes]]