Розширення переліку
Розширення переліку (Enum) — це функція міксинів, яка може надійно додавати нові записи до підрахунку.
Націлюючись на переліки Minecraft, ви можете використовувати міксини разом із твікінгом класу для показу нових записів переліку в декомпільованому джерелі. Якщо для нього встановлено транзитивним, моди, які залежать від вашого, також бачитимуть ваші додані записи.
WARNING
Для розширення переліку потрібен принаймні 0.19.0 Завантажувача для підтримки міксинів і принаймні Loom 1.16 для підтримки налаштування класу.
Крім того, у заголовках файлів твікерів класу має бути вказано v2 як версію для використання розширень переліку.
Створення міксину
Перш ніж створювати міксин клас, переконайтеся, що 0.19.0 Завантажувача або вище є явною залежністю у вашому файлі fabric.mod.json:
json
...
"depends": {
...
"fabricloader": ">=0.19.0"
...
}
...Навіть якщо ви використовуєте правильну версію завантажувача як залежність Gradle, ви повинні явно залежати принаймні від версії 0.19.0, щоб увімкнути цю функцію міксина.
Щоб створити розширення переліку, створіть enum у своєму пакеті міксинів, додайте до нього анотацію @Mixin і додайте до нього свої константи, ніби вони були частиною цільового класу переліку. Наприклад, додаймо новий запис до RecipeBookType:
java
@Mixin(RecipeBookType.class)
enum RecipeBookTypeMixin {
EXAMPLE_MOD_RECIPE_BOOK_TYPE
}1
2
3
4
2
3
4
ВАЖЛИВО
Ви завжди повинні додавати префікс до констант переліку, які ви додаєте, своїм ID мода, щоб забезпечити унікальність. Для документації ми використовуватимемо EXAMPLE_MOD_.
Передача аргументів конструктора
Якщо цільовий перелік не має конструктора в усталено, ви повинні затінити конструктор цільового класу та передати необхідні аргументи до оголошення доданого запису.
Наприклад, додаймо новий запис RecipeCategory. Створіть конструктор, який відповідає бажаному в цільовому класі, і додайте до нього анотацію @Shadow.
java
@Mixin(RecipeCategory.class)
enum RecipeCategoryMixin {
EXAMPLE_MOD_RECIPE_CATEGORY("exampleModRecipeFolderName");
@Shadow
RecipeCategoryMixin(String recipeFolderName) {
}
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Реалізація абстрактних методів
Щоб реалізувати абстрактні методи цільового переліку, затініть абстрактний метод, а потім перевизначте та реалізуйте його у своєму доданому записі. Наприклад, додаймо новий запис ConversionType:
java
@Mixin(ConversionType.class)
enum ConversionTypeMixin {
EXAMPLE_MOD_CONVERSION_TYPE(false) {
@Override
void convert(Mob from, Mob to, ConversionParams params) {
/* ... */
}
};
@Shadow
abstract void convert(Mob from, Mob to, ConversionParams params);
@Shadow
ConversionTypeMixin(final boolean discardAfterConversion) {
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Створення запису твікера класу
Якщо ви націлюєтеся на перелік Minecraft, ви можете використати запис для налаштування класу, щоб помітно змінити цільовий перелік у декомпільованому джерелі.
Щоб увімкнути цю функцію, не забудьте використовувати Loom 1.16 або новішої версії та встановити версію заголовка файлу на v2.
Синтаксис для запису розширення переліку такий:
extend-enum <targetClassName> <ENUM_CONSTANT_NAME>Для твікінгу класів, класи використовують свої внутрішні імена.
Наприклад, запис твікера класу для константи RecipeBookType, яку ми додали в розділ міксина, буде таким:
classtweaker
extend-enum net/minecraft/world/inventory/RecipeBookType EXAMPLE_MOD_RECIPE_BOOK_TYPEЗастосування змін
Вам доведеться оновити проєкт Gradle і перегенерувати джерела, перш ніж ви зможете побачити додані записи переліку в декомпільованих джерелах. Якщо зміни не показано, ви можете спробувати перевірити на дійсність та на наявність помилок.
INFO
Ви не побачите переданих аргументів конструктора, реалізацій методів чи інших елементів у декомпільованому вихідному коді. Це тому, що вони обробляються міксином і застосовуються лише під час виконання.
Тепер ви можете використовувати константу переліку у своєму коді:
java
void exampleRecipeBookTypeMethod(RecipeBookType recipeBookType) {
if (recipeBookType == RecipeBookType.EXAMPLE_MOD_RECIPE_BOOK_TYPE) {
/* ... */
}
}1
2
3
4
5
2
3
4
5
Якщо ви додаєте його лише за допомогою міксина і його немає в декомпільованому джерелі, ви можете перевірити його, порівнявши назви:
java
void exampleRecipeBookTypeMethodNoCT(RecipeBookType recipeBookType) {
if (recipeBookType.name().equals("EXAMPLE_MOD_RECIPE_BOOK_TYPE")) {
/* ... */
}
}1
2
3
4
5
2
3
4
5
Якщо вам потрібно використовувати константу в кількох областях, отримайте її, викликавши valueOf і збережіть результат у полі:
java
public static final RecipeBookType ADDED_RECIPE_BOOK_TYPE = RecipeBookType.valueOf("EXAMPLE_MOD_RECIPE_BOOK_TYPE");1
Підводні камені
Розширення переліку не може гарантувати, що додані вами записи нічого не пошкодять.
Це ваша відповідальність за перегляд використання цільового переліку та намагання запобігти проблемам, де це можливо. Якщо ви не можете вирішити деякі з них і виникають збої, можливо, краще взагалі не використовувати розширення переліку.
Цей розділ розглядає деякі шаблони, на які слід звернути увагу та яких слід уникати під час розширення переліків, але він не є вичерпним.
Вирази перемикання
Інструкції перемикання часто використовуються для обробки констант переліку. Через це може статися збій, якщо вираз перемикання не обробляє записи, додані іншими модами. Наприклад, скажімо, ми маємо такий вираз перемикання:
java
void exampleProblematicSwitch(RecipeBookType recipeBookType) {
String s = switch (recipeBookType) {
case SMOKER -> "smoker";
case CRAFTING -> "crafting";
case FURNACE -> "furnace";
case BLAST_FURNACE -> "blast_furnace";
case EXAMPLE_MOD_RECIPE_BOOK_TYPE -> "example_mod_recipe_book_type";
};
/* ... */
}1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Зверніть увагу, що немає пункту default. Попри те, що ми обробили всі значення в стандартному переліку та наші власні, це виникне, якщо інший мод додасть інший запис.
Як можна цьому запобігти? Немає єдиного універсального способу уникнути збоїв — ваш підхід слід адаптувати в кожному конкретному випадку. Але загалом:
- Якщо вираз
switchмістить стандартний метод, ви можете використовувати міксин для його редагування - Якщо вираз
switchпоходить від мода, вам слід спробувати зв’язатися з розробниками, щоб разом знайти сумісний підхід. В іншому випадку вам, можливо, доведеться створити міксин на іншому моді.
Серіалізація переліків
Деякі записи переліків серіалізуються автоматично. Прикладом є перелік Variants у класі Axolotl.
Розширення цих переліків серіалізує ваш власний запис у просторі імен Minecraft, а в деяких версіях це може статися на основі числового ID. Це не дуже добре, оскільки може вплинути на індекси всіх інших записів.
Найкраще уникати повного розширення переліків, якщо їхні записи серіалізовані таким чином. Натомість ви можете пошукати API, якщо він доступний.






