Создание достижений 26.1.2
Руководство по настройке генерации достижений через datagen.
ТРЕБОВАНИЯ
Сначала убедитесь, что вы установили datagen.
Установка
Для начала нам нужно создать провайдера. Создайте класс, который расширяет FabricAdvancementProvider и заполните базовые методы:
java
No lines matched.1
Чтобы завершить настройку, добавьте этот провайдер к вашей DataGeneratorEntrypoint в методе onInitializeDataGenerator.
java
No lines matched.1
Структура достижений
Достижение состоит из нескольких различных компонентов. Помимо требований, называемых "критериями" (criterion), оно может содержать:
DisplayInfo— указывает игре, как именно отображать достижение игрокам.AdvancementRequirements— списки списков критериев; для выполнения достижения требуется завершить как минимум один критерий из каждого подсписка.AdvancementRewards— награды, которые игрок получает за выполнение достижения.Strategy— стратегия, которая определяет, как достижение обрабатывает несколько критериев.Parent— родительское достижение. Организует иерархию, которую можно увидеть на экране "Достижения".
Простые достижения
Вот пример простого достижения за получение блока земли:
java
No lines matched.1
Вывод JSON
json
{
"criteria": {
"got_dirt": {
"conditions": {
"items": [
{
"items": "minecraft:dirt"
}
]
},
"trigger": "minecraft:inventory_changed"
}
},
"display": {
"background": "minecraft:gui/advancements/backgrounds/adventure",
"description": "Now make a house from it",
"icon": {
"id": "minecraft:dirt"
},
"title": "Your First Dirt Block"
},
"requirements": [
[
"got_dirt"
]
],
"sends_telemetry_event": true
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Родительские достижения (Parents)
Чтобы создать или расширить дерево достижений, мы можем указать родителя для нашего достижения. Для этого вызовите метод Advancement.Builder#parent(...) и передайте ссылку на родительское достижение:
No region #reference-parent found in path: /home/runner/work/fabric-docs/fabric-docs/reference/latest/src/client/java/com/example/docs/datagen/ExampleModAdvancementProvider.java1
Если прямой ссылки на родительское достижения нет (например, в качестве родителя используется ванильное достижение), можно создать плейсхолдер с помощью static метода класса Identifier.
No region #placeholder-parent found in path: /home/runner/work/fabric-docs/fabric-docs/reference/latest/src/client/java/com/example/docs/datagen/ExampleModAdvancementProvider.java1
Теперь ваши достижения будут отображаться в виде древовидной структуры в меню достижений.

Множественные критерии (Multiple Criteria)
Чтобы использовать более сложные условия в наших достижениях, мы можем вызывать метод Advancement.Builder#addCriteria(...) несколько раз, добавляя дополнительные критерии:
No region #multiple-criteria found in path: /home/runner/work/fabric-docs/fabric-docs/reference/latest/src/client/java/com/example/docs/datagen/ExampleModAdvancementProvider.java1
По умолчанию для выполнения достижения должны быть выполнены все указанные критерии. Мы можем изменить это поведение, задав другую стратегию требований (AdvancementRequirements.Strategy):
No region #requirements-strategy found in path: /home/runner/work/fabric-docs/fabric-docs/reference/latest/src/client/java/com/example/docs/datagen/ExampleModAdvancementProvider.java1
Награды (Rewards)
Мы можем привязывать награды к нашим достижениям, которые будут выдаваться игроку сразу после их выполнения. Для этого нужно вызвать метод Advancement.Builder#rewards(...) и передать туда награды, которые мы хотим добавить:
No region #experience-reward found in path: /home/runner/work/fabric-docs/fabric-docs/reference/latest/src/client/java/com/example/docs/datagen/ExampleModAdvancementProvider.java1
Также доступны и другие типы наград:
No region #reward-types found in path: /home/runner/work/fabric-docs/fabric-docs/reference/latest/src/client/java/com/example/docs/datagen/ExampleModAdvancementProvider.java1
Пользовательские критерии (Custom Criteria)
WARNING
Хотя генерация данных (datagen) может выполняться на стороне клиента, сами классы критериев (Criterion) и предикатов (Predicate) должны находиться в основном наборе исходного кода (main source set), доступном для обеих сторон, поскольку именно сервер должен отслеживать и проверять их выполнение.
Определения
Критерий (Criterion / мн. ч. Criteria) — это действие, которое может совершить игрок (или событие, которое может с ним произойти), засчитывающееся для прогресса достижения. В игре уже есть много стандартных критериев, которые находятся в пакете net.minecraft.advancements.criterion. Как правило, новый критерий нужен только в том случае, если вы добавляете в игру свою уникальную механику.
Условия (Conditions) — это параметры, которые проверяются критерием. Критерий засчитывается только в том случае, если выполнены все связанные условия. Обычно условия выражаются с помощью предикатов.
Предикат (Predicate) — это функциональный интерфейс, принимающий входное значение и возвращающий результат типа boolean(логическое значение). Например, предикат Predicate<Item> может возвращать true, если предмет является алмазом, а предикат Predicate<LivingEntity> — если существо не агрессивно по отношению к деревенским жителям.
Создание пользовательских критериев
Во-первых, нам понадобится новая механика. Давайте сообщать игроку, какой инструмент он использовал, каждый раз, когда он разбивает блок.
java
No lines matched.1
Обратите внимание, что этот код очень плохой. Так как HashMap не хранится в постоянном месте, она будет сбрасываться при каждом перезапуске игры. Это сделано исключительно для демонстрации критериев (Criterions). Начните игру и попробуйте!
Далее создадим наш пользовательский критерий UseToolCriterion. Для него понадобится собственный класс Conditions, поэтому мы создадим их оба сразу:
java
No lines matched.1
Ух, как много всего! Давайте во всём разберёмся.
UseToolCriterion— это класс-наследникSimpleCriterionTrigger, к которому могут применяться условияConditions.- В
Conditionsесть полеplayerPredicate. Все условияConditionsдолжны содержать предикат игрока (технически —LootContextPredicate). - У
Conditionsтакже естьCODEC. ЭтотCodec- просто кодек для одного поля,playerPredicate, с дополнительными инструкциями для преобразования между ними (xmap).
INFO
Чтобы узнать больше о кодеках, см. страницу Codecs.
Нам понадобится способ проверить, выполнены ли условия. Давайте добавим вспомогательный метод в Conditions:
java
No lines matched.1
Теперь, когда у нас есть критерий и его условия, нам нужно найти способ запустить его. Добавьте метод триггера к UseToolCriterion:
java
No lines matched.1
Почти готово! Далее нам нужен экземпляр нашего критерия для работы. Давайте поместим его в новый класс, названный ModCriteria.
java
No lines matched.1
Чтобы убедиться, что наши критерии инициализируются в нужное время, добавьте пустой метод init:
java
No lines matched.1
И вызовите его в инициализаторе вашего мода:
java
No lines matched.1
Наконец, нам нужно запустить наши критерии. Добавьте это туда, где мы отправили сообщение игроку в основном классе мода.
java
No lines matched.1
Теперь ваш новый блестящий критерий готов к использованию! Давайте добавим его в наш провайдер:
java
No lines matched.1
Запустите задачу datagen снова — ваше новое достижение готово к использованию!
Условия с параметрами
Всё это хорошо, но что если мы хотим выдавать достижение только после 5-кратного выполнения условия? А почему не еще один в 10 раз? Для этого нам нужно задать условию параметр. Вы можете продолжать использовать UseToolCriterion или перейти на новый ParameterizedUseToolCriterion. На практике вам нужно иметь только параметризованный, но в этом уроке мы оставим оба.
Давайте работать снизу вверх. Нам нужно проверить, выполнены ли требования, поэтому давайте отредактируем наш метод Conditions#requirementsMet:
java
No lines matched.1
requiredTimes не существует, поэтому сделайте его параметром Conditions:
java
No lines matched.1
Теперь наш кодек выдает ошибку. Давайте напишем новый кодек для новых изменений:
java
No lines matched.1
Двигаемся дальше, теперь нам нужно исправить наш метод trigger:
java
No lines matched.1
Если вы создали новый критерий, нам нужно добавить его в ModCriteria
java
No lines matched.1
И вызываем его в нашем основном классе, прямо там, где был старый вариант:
java
No lines matched.1
Добавьте достижение в ваш provider:
java
No lines matched.1
Запустите datagen еще раз, и вы наконец-то закончили!





