Table of Contents

Создание пользовательского типа рецепта

На этой странице мы создадим наш собственный пользовательский тип рецепта, включая бесформенную версию! Мы не будем использовать какие-либо классы ванильного Майнкрафта, это будет полностью пользовательский тип рецепта.

Вы можете найти и узнать, как приготовить другие типы рецептов. Создание рецепта приготовления

Добавление блока

Нам нужно будет создать блок, чтобы открыть графический интерфейс рецепта. Некоторые из классов будут созданы позже.

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() {  
    		// Возобновление позже...
    	}
}

Создание класса рецептов

Теперь мы займемся самой интересной частью этой страницы - созданием класса рецептов.

Создание класса рецептов в форме

Рецепты в форме - это тип рецепта, для которого требуется, чтобы элемент находился в определенном слоте или шаблоне. В основном он используется в рецептах сетки, таких как рецепт крафта.

Интерфейс рецепта ожидает класс инвентаря в качестве параметра типа. Любой инвентарь, содержащий ингредиенты для рецепта, будет работать. Но мы будем использовать CraftingInventory.

TestRecipe.java
public class TestRecipe implements Recipe<CraftingInventory> {
	//Вы можете добавить сюда столько входных данных, сколько захотите.
	//Важно всегда использовать Ingredient, чтобы вы могли поддерживать теги.
	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));
	}
}

Теперь нам нужен Type Все, что вам нужно сделать, это создать экземпляр класса, который расширяет 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, а пока попробуйте разобраться в этом, используя ссылку на ИСТОЧНИК ниже.

ИСТОЧНИК: Определение Пользовательских Рецептов Крафта (англ.)