У програмуванні навіть найкращі неодмінно стикаються з проблемами, баґами та помилками.
У цьому посібнику описано деякі загальні кроки, які ви можете виконати, щоб потенційно виявити та вирішити їх, навіть без допомоги інших. Самостійне розв’язування проблем може навчити вас багатьох речей, а також принесе вам задоволення.
Однак, якщо ви застрягли та не можете знайти виправлення самостійно, не проблема попросити інших про допомогу!
Консоль та реєстратор
Найпростіший і найшвидший спосіб виявити проблеми — це зайти в консоль.
Там можуть друкуватися значення під час виконання, інформуючи розробника про поточний стан коду та полегшуючи аналіз змін і потенційних помилок.
У класі точки входу мода, що реалізує ModInitializer, усталено визначено LOGGER для друку бажаного виводу на консоль.
java
public class ExampleModDebug implements ModInitializer {
public static final String MOD_ID = "example-mod";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
// ...
}1
2
3
4
5
6
2
3
4
5
6
Щоразу, коли вам потрібно знати значення для чогось у будь-якому місці коду, використовуйте цей LOGGER, передавши String його методам.
java
ExampleModDebug.LOGGER.info("You interacted with an entity!");1
Реєстратор підтримує кілька режимів друку тексту на консолі. Залежно від режиму, який ви використовуєте, зареєстрований рядок показується різними кольорами.
java
ExampleModDebug.LOGGER.info("Neutral, informative text...");
ExampleModDebug.LOGGER.warn("Non-critical issues...");
ExampleModDebug.LOGGER.error("Critical exceptions, bugs..."); 1
2
3
2
3
INFO
Усі режими журналювальника підтримують кілька перевантажень; таким чином ви можете надати більше інформації, наприклад трасування стека!
Наприклад, переконаймося, що коли TestItem використовується для сутності, він виводить її поточний стан на консоль.
java
@Override
public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) {
Level level = user.level();
// Values are used in a String to provide more information in the console
String output = "Is Client World: %s | Health: %s / %s | The item was used with the %s"
.formatted(user.level().isClientSide(), entity.getHealth(), entity.getMaxHealth(), hand.name());
ExampleModDebug.LOGGER.info(output);
if (!user.level().isClientSide()) {
// you can log non-critical issues differently as a warning
ExampleModDebug.LOGGER.warn("Don't touch that!");
// The LOGGER can print the Stacktrace too in addition to the logging message
if (stack.getCount() > 1) {
IllegalArgumentException exception = new IllegalArgumentException("Only one item is allowed");
ExampleModDebug.LOGGER.error("Error while interacting with an entity", exception);
throw exception;
}
}
return InteractionResult.SUCCESS;
}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
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

У журнальованому рядку ви можете знайти:
Time— час, коли було надруковано журнальовану інформаціюThread— потік, у якому було надруковано. Ви часто побачите серверний і рендерний потоки; це говорить вам, на якій стороні було виконано кодName— назва журналювальника. Найкраще використовувати тут свій ID мода, щоб журнали та збої показували, який мод журнальованоMessage— це має бути стислим, але описовим. Додайте відповідні значення або контекстStack Trace— якщо надано трасування стека винятку, реєстратор також може надрукувати це
Збереження консолі чистою
Майте на увазі, що все це також буде надруковано, якщо мод використовується в будь-якому іншому середовищі.
Якщо дані, які ви журналюєте, стосуються лише розробки, може бути корисним створити спеціальний метод LOGGER і використовувати його, щоб уникнути друку даних у виробництві.
java
// This method will only log if the Minecraft instance
// is running in a Development Environment, like your IDE
public static void devLogger(String loggerInput) {
if (!FabricLoader.getInstance().isDevelopmentEnvironment()) {
return;
}
LOGGER.info("DEV - [ %s ]".formatted(loggerInput));
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Якщо ви не впевнені, чи журнали поза сеансом налагодження, хорошим емпіричним правилом є журнали, лише якщо щось пішло не так. Розробників і користувачів пакетів модів не дуже хвилює, наприклад, ініціалізація предметів; вони хотіли б знати, якщо, наприклад, чому пакет даних не завантажується правильно.
Пошук проблем
Реєстратор друкує ID вашого мода перед лінією. Ви можете знайти його (⌘/CTRL+F), щоб виділити його.
Відсутні ресурси та текстури (фіолетовий і чорний заповнювач) також журналюють попередження на консолі та зазвичай згадують очікувані значення.

Точки зупину
Складніший спосіб налагодження — використання точок зупину в IDE. Як випливає з назви, вони використовуються для зупинки виконуваного коду в певних точках, щоб дозволити перевірити та змінити стан програмного забезпечення.
TIP
Щоб використовувати точки зупину, ви повинні виконати екземпляр за допомогою параметра Debug замість параметра Run:

Давайте знову використаємо наш власний предмет як приклад. CUSTOM_NAME та DataComponentType предмета має змінитися, якщо він використовується по будь-якому камені. Однак у цьому прикладі предмет завжди викликає анімацію руки «успіх», але, здається, кругляк не змінює назву.
Як ми можемо розв'язувати пару проблем? Розслідуймо…
java
// problematic example code:
public class TestItem extends Item {
public TestItem(Properties properties) {
super(properties);
}
@Override
public InteractionResult useOn(UseOnContext context) {
Level level = context.getLevel();
Player user = context.getPlayer();
BlockPos targetPos = context.getBlockPos();
ItemStack itemStack = context.getItemInHand();
BlockState state = level.getBlockState(targetPos);
if (state.is(ConventionalBlockTags.STONES)) {
Component newName = Component.literal("[").append(state.getBlock().getName()).append(Component.literal("]"));
itemStack.set(DataComponents.CUSTOM_NAME, newName);
if (user != null) {
user.displayClientMessage(Component.literal("Changed Item Name"), true);
}
}
return InteractionResult.SUCCESS;
}
}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
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
Поставте точку зупину, натиснувши номер рядка. Ви можете розмістити більше однієї одночасно, якщо потрібно. Точка зупину зупиниться безпосередньо перед виконанням вибраного рядка.

Потім дозвольте запущеному екземпляру Minecraft виконати цю частину коду. Ви також можете розміщувати контрольні точки під час роботи гри.
У цьому випадку власний предмет потрібно використовувати по блоку. Вікно Minecraft має зависнути, а в IntelliJ жовта стрілка з’явиться прямо біля точки зупину, що вказує на те, що налагоджувач досяг цієї точки.
Унизу має відкритися вікно Debug, і перегляд Threads & Variables має бути вибрано автоматично. Ви можете використовувати керування зі стрілками у вікні Debug, щоб перемістити точку виконання. Такий спосіб переміщення кодом називається «покроковим».

| Дія | Опис |
|---|---|
| Переступ | Перехід до наступного виконаного рядка, фактично переміщення екземпляра в логіці |
| Уступ | Метод уступу для показу, що відбувається всередині. Якщо в одному рядку є кілька методів, ви можете вибрати, до якого переходити, натиснувши його. Це також необхідно для лямбда-виразів. |
| Перейти до курсору | Проходить через логіку, доки не досягне курсора в коді. Це корисно для пропуску великих фрагментів коду. |
| Показати точку виконання | Переміщує вікно кодування до точки, де зараз знаходиться налагоджувач. Це також працює, якщо ви зараз працюєте з іншими файлами та вкладками. |
INFO
Дії «Переступ» F8 і «Уступ» F7 є найпоширенішими, тож спробуйте звикнути до комбінацій клавіш!
Якщо ви завершили поточну перевірку, ви можете натиснути зелену кнопку Відновити програму (F9). Це розморозить екземпляр Minecraft, і можна буде проводити подальше тестування, доки не буде досягнуто іншої точки зупину. Але давайте поки що продовжимо дивитися на вікно Debug.
Угорі ви можете побачити всі запущені екземпляри. Якщо обидва запущені, ви можете перемкнутися між екземпляром клієнта та сервером. Нижче ви маєте дії з налагодження та керування. Ви також можете перейти до перегляду консолі, якщо вам потрібно переглянути журнали.
Ліворуч ви можете побачити поточний активний потік, а під ним трасування стека.
З правого боку ви можете перевіряти та маніпулювати завантаженими значеннями та об’єктами. Ви також можете навести курсор на значення в коді: якщо вони знаходяться в області видимості та все ще завантажуються, спливне вікно також покаже їхні конкретні значення.
Якщо вас цікавить вміст певного об’єкта, ви можете скористатися маленьким значком стрілки поруч із ним. Це розгорне всі вкладені дані.
Очевидно, що значення не завантажуються, якщо точка виконання не пройшла повз них або якщо вони розташовані в зовсім іншому контексті.

Ви можете використовувати рядок введення у вікні Debug для багатьох різних речей, наприклад, ви можете отримати доступ до поточних завантажених об'єктів і використовувати для них методи. Нижче буде додано новий запис із запитаними даними.

Перейдімо в наш приклад, щоб завантажилася змінна BlockState. Тепер ми можемо перевірити, чи насправді BlockState цільового блока міститься в тезі Block.
TIP
Натисніть значок + праворуч від рядка введення, щоб закріпити результат для поточного сеансу налагодження.

Як ми бачимо, теґ ConventionalBlockTags.STONES не включає кругляк, оскільки для цього існує окремий теґ.
Перемикач точки зупину та умови
Іноді вам потрібно лише зупинити код, коли виконуються певні умови. Для цього створіть точку зупину та натисніть ПКМ, щоб відкрити її налаштування. Там ви можете встановити логічний оператор як умову.
Порожні значки точок зупину вказують на неактивні точки зупину, які не зупинять активний екземпляр Minecraft. Ви можете перемикати точки зупину у спливному вікні налаштувань точки зупину або просто натиснувши СКМ по самій точці зупину.
Усі точки зупину будуть перераховані у вікні Bookmarks IntelliJ.


Швидка заміна активного екземпляра
Ви можете вносити обмежені зміни в код під час роботи екземпляра, використовуючи дію «Створити > Створити проєкт» зі значком молотка. Ви також можете розмістити значок поруч з елементом спадного меню Run Configuration, натиснувши ПКМ порожнє місце у верхній панелі меню IntelliJ.

Цей процес, також званий «швидка заміна», вимагає запуску екземпляра Minecraft у режимі Debug замість режиму Run (див. вище).
Завдяки цьому вам не потрібно перезапускати екземпляр Minecraft знову. Це також пришвидшує тестування вирівнювання елементів екрана та балансування інших функцій. IntelliJ повідомить вас, якщо «швидка зміна» був успішним.

Виняток становлять міксини. Ви можете налаштувати своє налаштування запуску, щоб вони також могли змінюватися під час виконання. Для детальної інформації, перегляньте швидку зміну міксинів.
Інші зміни можна перезавантажити в грі.
- зміни в теці
assets/—> натисніть F3+T - зміни в теці
data/—> скористайтеся командою/reload
Щоб завершити наведений раніше приклад, додаймо умову до оператора. Коли ми досягаємо точки зупину, ми бачимо, що ми завжди отримуємо «успішної» анімацію руки, оскільки ми ніколи не повертали нічого іншого.
Застосуйте виправлення та використовуйте гарячу заміну, щоб миттєво побачити зміни в грі.
java
@Override
public InteractionResult useOn(UseOnContext context) {
Level level = context.getLevel();
Player user = context.getPlayer();
BlockPos targetPos = context.getClickedPos();
ItemStack itemStack = context.getItemInHand();
BlockState state = level.getBlockState(targetPos);
if (state.is(ConventionalBlockTags.STONES) || state.is(ConventionalBlockTags.COBBLESTONES)) {
Component newName = Component.literal("[").append(state.getBlock().getName()).append(Component.literal("]"));
itemStack.set(DataComponents.CUSTOM_NAME, newName);
if (user != null) {
user.displayClientMessage(Component.literal("Changed Item Name"), true);
}
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Журнали та збої
Консолі попередньо запущених екземплярів експортуються як файли журналів, розташовані в каталозі logs екземпляра Minecraft. Найновіший журнал зазвичай називається latest.log.
Користувачі зможуть поділитися цим файлом із розробником мода для подальшої перевірки, як пояснюється в вивантаженнях журналів.
У середовищі розробки ви можете знайти попередні журнали у вікні Проєкт у теці run > logs, а звіти про збої — у теці run > crash-reports.
Запитайте спільноту!
Усе ще не можете зрозуміти, що відбувається? Ви можете приєднатися до сервера Fabric Discord і поспілкуватися зі спільнотою!
Ви також можете переглянути офіційну вікі Fabric для складніших запитів.


