====== 创建自定义的合成配方类型 ======
在此界面,我们将创建我们自己的合成配方,包括无序合成的版本!
我们将不使用任何原版的类型,创建一个完全自定义的合成配方类型!
你也可以尝试制作其他的配方类型。
[[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]]