User Tools

Site Tools


zh_cn:tutorial:recipe_type

创建自定义的合成配方类型

在此界面,我们将创建我们自己的合成配方,包括无序合成的版本! 我们将不使用任何原版的类型,创建一个完全自定义的合成配方类型!

你也可以尝试制作其他的配方类型。 添加烹饪配方类型

添加合成方块

我们先要创建一个能打开合成界面的方块,关于合成的其他类型之后再说。

TestRecipeBlock.java
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)。

ExampleCustomRecipeMod.java
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。

TestRecipe.java
public class TestRecipe implements Recipe<CraftingInventory> {
	//你想添加多少个原料(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。

TestRecipe.java
public class TestRecipe implements Recipe<CraftingInventory> {
	//[...]
	@Override
	public ItemStack craft(CraftingInventory inv) {
		return this.getOutput().copy();
	}
 
	@Override
	public boolean fits(int width, int height) {
		return true;
	}
}

matches 方法中,当物品栏中的原料和配方中的排列顺序和物品一致时,返回 true。

TestRecipe.java
public class TestRecipe implements Recipe<CraftingInventory> {
	//[...]
	@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<TestRecipe> 的实例。

TestRecipe.java
public class TestRecipe implements Recipe<CraftingInventory> {
	//[...]
	public static class Type implements RecipeType<TestRecipe> {
		private Type() {}
		public static final Type INSTANCE = new Type();
		public static final String ID = "test_recipe";
	}
	@Override
	pubilc RecipeType<?> getType() {
		return Type.INSTANCE;
	}
}

之后还需要 RecipeSerializer ,但原作者并没有写完此部分。如果你想继续,请在下面的来源中找到此部分。

来源: Defining Custom Crafting Recipes

zh_cn/tutorial/recipe_type.txt · Last modified: 2023/01/12 04:41 by tao0lu