Начало работы с генерацией данных

Генерация данных - новый модуль Fabric API, он позволяет вам динамически создавать Рецепты, Языковые Файлы, Таблицы Добычи, Достижения и почти все, что связано с пользовательскими провайдерами.

Сначала мы добавим новую gradle задачу, которая будет брать наш код для генерации данных и выдавать файлы которые Minecraft может прочитать. Каждый раз, когда вы изменяете код который создает Достижения (или что-нибудь еще, что datagen может создать, например, таблицы добычи и тому подобное) вам потребуется запустить gradle задачу runDatagenClient. Мы сделаем это позже, сначала откройте build.gradle файл и добавьте следующую задачу:

// ... (Остальная часть файла)
 
loom {
    runs {
        //
        // Здесь создается новая gradle задача, которая запускает datagen API: "gradlew runDatagenClient"
        //
        datagenClient {
            inherit client
            name "Data Generation"
            vmArg "-Dfabric-api.datagen"
            vmArg "-Dfabric-api.datagen.output-dir=${file("src/main/generated")}"
            vmArg "-Dfabric-api.datagen.modid=${modid}"
 
            runDir "build/datagen"
        }
    }
}
 
//
// Добавление сгенерированных файлов в jar, который вы предоставляете игрокам.
//
sourceSets {
    main {
        resources {
            srcDirs += [
                    'src/main/generated'
            ]
        }
    }
}

Вы заметите, что в нем используется переменная ${modid}. Она должна быть представлена в gradle.properties файле. Проверьте, имеется ли она у вас, и если нет, вы можете добавить её этим способом:

// .. (Остальная часть файла)
 
modid=имя-вашего-мода-измени-меня-пожалуйста
 
// .. (Остальная часть файла)

Далее мы определим новый класс в нашем проекте DataGeneration который реализует DataGeneratorEntrypoint.

import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
 
public class DataGeneration implements DataGeneratorEntrypoint {
 
    @Override
    public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
 
    }
}

Теперь нужно сообщить в fabric об этой входной точке в fabric.mod.json file:

{
 
  // ... (Остальная часть файла)
 
  "entrypoints": {
    "fabric-datagen": [
      "DataGeneration"
    ],
    "main": [
      "AdvancementsTutorial"
    ],
    "client": [
      "AdvancementsTutorialClient"
    ]
  },
 
  // ... (Остальная часть файла)
 
}

Перед тем как продолжить, давайте посмотрим, все ли работает или имеются ошибки. Запустите runDatagenClient задачу. Ваша IDE может сделать это, в другом случае откройте терминал в корневой директории вашего проекта и запустите:

./gradlew runDatagenClient

Прочитайте выходные данные и убедитесь, что в них нет ошибок.

Если вы получили ошибку, то обычно она явно указывает на то, что пропустили или написали неправильно, но если вы не можете разобраться, вы можете перейти в discord, и попросить помощь.

Должна быть новая папка в src/main названая generated. В данный момент она пуста, но как только мы начнем генерировать данные (например, достижения), в ней они будут сохранены.

Добавление провайдеров

Это обобщенное руководство о том как добавить провайдера, для более детальной информации о каждом провайдере, посмотрите соответствующие страницы:

В этом примере, мы будем создавать провайдера для тегов, поскольку его проще всего понять.

Для начала, внутри MyModDatagen класса, создайте новый private static class который extends FabricTagProvider<T>:

Если вы хотите, вы можете поместить этот класс в отдельном файле, но рекомендуем оставить его в вашем datagen entrypoint классе.

private static class MyTagGenerator extends FabricTagProvider<Item> {
        public MyTagGenerator(FabricDataGenerator dataGenerator) {
            super(dataGenerator, Registries.ITEM);  // for versions 1.19.2 and below, use Registry.ITEM
        }
 
        @Override
        protected void generateTags() {
 
        }
}

Мы добавим несколько основных тегов внутри generateTags() ради примера.

// Мы создадим тег элемента с названием "smelly_items".
private static final TagKey<Item> SMELLY_ITEMS = TagKey.of(RegistryKeys.ITEM, new Identifier("tutorial", "smelly_items"));
 
@Override
protected void generateTags() {
     // Создание конструктора тегов, куда мы добавляем шарики слизи, гнилую плоть и все, что находится в minecraft:dirt теге.
     getOrCreateTagBuilder(SMELLY_ITEMS)
              .add(Items.SLIME_BALL)
              .add(Items.ROTTEN_FLESH)
              .addOptionalTag(ItemTags.DIRT);
     // Это автоматические сгенерирует "assets/tutorial/tags/items/smelly_items.json" в папке "generated".
}

Теперь нам нужно будет зарегистрировать этого провайдера в генераторе данных в onInitializeDataGenerator в вашем entrypoint классе так:

public class DataGeneration implements DataGeneratorEntrypoint {
    @Override
    public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
        fabricDataGenerator.addProvider(MyTagGenerator::new);
    }
}

Когда мы запускаем gradlew runDatagenClient, мы должны увидеть сгенерированные папки, тег элемента json должен присутствовать:

smelly_items.json
{
  "replace": false,
  "values": [
    "minecraft:slime_ball",
    "minecraft:rotten_flesh",
    {
      "id": "#minecraft:dirt",
      "required": false
    }
  ]
}