====== Динамическая генерация рецептов ====== Динамически добавляемые рецепты - это рецепты, добавляемые с помощью кода вместо файлов .json. Это можно использовать, например, для изменения рецепта, если определенный мод установлен вместе с вашим модом, или для изменения рецепта, чтобы использовать теги из другого мода. Для начала мы хотим иметь какую-то функцию, которая создаст объект Json для нашего пользовательского рецепта: public static JsonObject createShapedRecipeJson(ArrayList keys, ArrayList items, ArrayList type, ArrayList pattern, Identifier output) { //Создаем новый объект json, где мы будем хранить наш рецепт. JsonObject json = new JsonObject(); //"Тип" рецепта, который мы создаем. В данном случае - форменный рецепт. json.addProperty("type", "minecraft:crafting_shaped"); //Это создаст: //"type": "minecraft:crafting_shaped" //Мы создаем новый элемент Json и добавляем к нему наш шаблон создания. JsonArray jsonArray = new JsonArray(); jsonArray.add(pattern.get(0)); jsonArray.add(pattern.get(1)); jsonArray.add(pattern.get(2)); //Затем мы добавляем шаблон к нашему объекту json. json.add("pattern", jsonArray); //Это создаст: //"pattern": [ // "###", // " | ", // " | " //] //Далее нам нужно определить, каковы ключи в шаблоне. Для этого нам нужны разные JsonObjects для каждого определения ключа и один основной JsonObject, который будет содержать все определенные ключи. JsonObject individualKey; //Индивидуальный ключ JsonObject keyList = new JsonObject(); //Основной ключевой объект, содержащий все ключи for (int i = 0; i < keys.size(); ++i) { individualKey = new JsonObject(); individualKey.addProperty(type.get(i), items.get(i).toString()); //Это создаст ключ в форме "type": "input", где type - это либо "item", либо "tag", а input - это наш элемент ввода. keyList.add(keys.get(i) + "", individualKey); //Затем мы добавляем этот ключ к основному ключевому объекту. //Это добавит: //"#": { "tag": "c:copper_ingots" } //и после этого //"|": { "item": "minecraft:sticks" } //и так далее. } json.add("key", keyList); //И так мы получаем: //"key": { // "#": { // "tag": "c:copper_ingots" // }, // "|": { // "item": "minecraft:stick" // } //}, //Наконец, мы определяем наш конечный объект JsonObject result = new JsonObject(); result.addProperty("item", output.toString()); result.addProperty("count", 1); json.add("result", result); //Это создаст: //"result": { // "item": "modid:copper_pickaxe", // "count": 1 //} return json; } ==== Основной файл мода ==== Во-первых, мы хотим проверить, загружен ли определенный мод. Чтобы сделать это, мы проверяем с помощью: FabricLoader.getInstance().isModLoaded("custom_mod"); Где ''"custom_mod"'' - это имя мода, который мы хотим проверить. Если мод загружен, мы можем создать наш рецепт: public class ExampleMod implements ModInitializer { public static JsonObject COPPER_PICKAXE_RECIPE = null; @Override public void onInitialize() { if (FabricLoader.getInstance().isModLoaded("custom_mod")) { COPPER_PICKAXE_RECIPE = createShapedRecipeJson( Lists.newArrayList( '#', '|' ), //Ключи, которые мы используем для входных предметов/тегов. Lists.newArrayList(new Identifier("c", "copper_ingots"), new Identifier("stick")), //Предметы/теги, которые мы используем в качестве входных данных. Lists.newArrayList("tag", "item"), //Независимо от того, является ли предоставленный нами ввод тегом или предметом. Lists.newArrayList( "###", " | ", " | " ), //Шаблон создания. new Identifier("examplemod:copper_pickaxe") //Результат крафта ); } } //Функция, которую мы создали ранее. public static JsonObject createShapedRecipeJson(...) { [...] } } ==== Миксин RecipeManager ==== Наконец, нам нужно сделать миксин в RecipeManager, чтобы мы могли передать рецепт в Minecraft: @Mixin(RecipeManager.class) public class RecipeManagerMixin { @Inject(method = "apply", at = @At("HEAD")) public void interceptApply(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo info) { if (ExampleMod.COPPER_PICKAXE_RECIPE != null) { map.put(new Identifier("examplemod", "copper_pickaxe"), ExampleMod.COPPER_PICKAXE_RECIPE); } } }