Міксин доступу 26.1.2
Дізнайтеся, як отримати доступ до методів і полів за допомогою засобів доступу та викликів міксина.
Міксини зазвичай використовуються для модифікації наявного коду для створення та налаштування поведінки. Однак Mixin також надає інструменти доступу до недоступних полів і методів у вигляді міксинів доступу.
Твікери класу надає подібний інструмент у формі розширювачів доступу, але міксини доступу не вимагають перезавантаження Gradle і можуть застосовуватися до цілей, які не належать до Minecraft.
Розширення доступу все ще необхідне для перевизначення кінцевих методів або підкласів кінцевих класів, або для посилання на приватні класи, оскільки засоби доступу можуть орієнтуватися лише на поля та методи.
Створення інтерфейсу доступу
Міксини доступу мають завжди бути інтерфейсом і містити лише методи, анотовані @Accessor або @Invoker. Інтерфейс має бути анотований @Mixin, як і інші класи міксинів.
Інтерфейси доступу традиційно називаються за цільовим класом із суфіксом Accessor і розміщуються у підпакеті accessor у вашому пакеті міксинів. Тобто ваш.пакет.міксинів.доступу
Поля доступу
Доступ до полів можна отримати за допомогою методів анотованих геттерів та/або сеттерів за допомогою @Accessor:
Синтаксис геттера/сеттера:
Методи доступу до екземплярів повинні мати префікс ID вашого мода та роздільника (зазвичай $ або _), щоб переконатися, що він не конфліктує з будь-яким іншим методом.
java
@Accessor("<field name>")
FieldType example_mod$getFieldName();
@Accessor("<field name>")
void example_mod$setFieldName(FieldType value);1
2
3
4
5
2
3
4
5
Приклад:
java
@Mixin(Gui.class)
public interface GuiAccessor {
@Accessor("overlayMessageTime")
int example_mod$getOverlayMessageTime();
@Accessor("overlayMessageTime")
void example_mod$setOverlayMessageTime(int messageTime);
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Використання:
java
void exampleInstanceFieldAccessorUsage(Gui gui, int newMessageTime) {
int oldMessageTime = ((GuiAccessor) gui).example_mod$getOverlayMessageTime();
((GuiAccessor) gui).example_mod$setOverlayMessageTime(newMessageTime);
}1
2
3
4
5
2
3
4
5
Налаштування кінцевих полів
Якщо цільове поле є остаточним, додайте до методу налаштування засобу доступу @Mutable, щоб видалити позначку кінцевого під час застосування:
java
@Mixin(Villager.class)
public interface VillagerAccessor {
@Accessor("FOOD_POINTS")
@Mutable
void example_mod$setItemFoodValues(Map<Item, Integer> items);
}1
2
3
4
5
6
2
3
4
5
6
Викликачі метода
Щоб викликати недоступні методи або конструктори, створіть метод, який відповідає сигнатурі, анотованій @Invoker:
Синтаксис:
Методи виклику екземплярів повинні мати префікс ID вашого мода та роздільника (зазвичай $ або _), щоб переконатися, що він не конфліктує з будь-яким іншим методом.
Методи виклику зазвичай називаються безпосередньо після цільового методу, invoke або call, за якими йде назва методу.
java
@Invoker("<method name>")
MethodReturnType example_mod$methodName(/* matching parameters */)1
2
2
Приклад:
java
@Mixin(Inventory.class)
public interface InventoryAccessor {
@Invoker("hasRemainingSpaceForItem")
boolean example_mod$hasRemainingSpaceForItem(ItemStack slotItemStack, ItemStack newItemStack);
}1
2
3
4
5
2
3
4
5
Використання:
java
void exampleInstanceMethodInvokerUsage(Inventory inventory, ItemStack slotItemStack, ItemStack newItemStack) {
if (((InventoryAccessor) inventory).example_mod$hasRemainingSpaceForItem(slotItemStack, newItemStack)) {
/* ... */
}
}1
2
3
4
5
2
3
4
5
Використання засобів доступу для кінцевих класів
Оскільки компілятор Java суворіший щодо кінцевих класів, він не дозволяє нам безпосередньо передати його екземпляри до інтерфейсу доступу.
Щоб обійти це, нам потрібно лише спочатку привести до Object, а потім до інтерфейсу доступу:
java
((TargetClassAccessor) (Object) targetClassInstance).example_mod$accessorMethod(/* ... */)1




