Упровадження інтерфейсу
Упровадження інтерфейсу — це тип твікінгу класу, який використовується для додавання реалізацій інтерфейсу до класів Minecraft у декомпільованому джерелі.
Реалізація, яка є видимою в декомпільованому вихідному коді класу, усуває необхідність приведення до інтерфейсу для використання його методів.
Крім того, упровадження інтерфейсу можуть бути прохідними, що дозволяє бібліотекам легше надавати додані методи модам, які залежать від них.
Щоб продемонструвати впровадження інтерфейсу, фрагменти цієї сторінки використовуватимуть приклад, де ми додаємо новий допоміжний метод до FlowingFluid.
Створення інтерфейсу
У пакеті, який не є вашим пакетом міксина, створіть інтерфейс, який ви хочете додати:
java
public interface BucketEmptySoundGetter {
default Optional<SoundEvent> example_mod$getBucketEmptySound() {
throw new AssertionError("Implemented in Mixin");
}
}1
2
3
4
5
2
3
4
5
У нашому випадку ми викидаємо усталено, оскільки ми плануємо реалізувати метод через міксин.
WARNING
Усі методи впровадження інтерфейсів мають бути default, щоб їх можна було впровадити за допомогою засобу налаштування класу, навіть якщо ви плануєте реалізувати методи в цільовому класі за допомогою міксина.
Методи також повинні мати префікс вашого ID мода з роздільником, таким як $ або _, щоб вони не конфліктували з доданими методами інших модів.
Реалізація інтерфейсу
TIP
Якщо методи інтерфейсу повністю реалізовано за допомогою інтерфейсу default, вам не потрібно використовувати міксин для впровадження інтерфейсу, запису твікера класу буде достатньо.
Щоб створити перевизначення методів інтерфейсу в цільовому класі, вам слід використовувати міксин, який реалізує інтерфейс і націлений на клас, у який ви хочете впровадити інтерфейс.
java
@Mixin(FlowingFluid.class)
abstract class FlowingFluidMixin extends Fluid implements BucketEmptySoundGetter {
@Override
public Optional<SoundEvent> example_mod$getBucketEmptySound() {
return Optional.of(this.is(FluidTags.LAVA) ? SoundEvents.BUCKET_EMPTY_LAVA : SoundEvents.BUCKET_EMPTY);
}
}1
2
3
4
5
6
7
2
3
4
5
6
7
Перевизначення буде додано до цільового класу під час виконання, але не буде видно в декомпільованому джерелі, навіть якщо ви використовуєте твікер класу, щоб зробити реалізацію інтерфейсу видимою.
Зроблення запису твікера класу
Упровадження інтерфейсу використовує такий синтаксис:
classtweaker
inject-interface <targetClassName> <injectedInterfaceName>Для твікінгу класів, класи та інтерфейси використовують свої внутрішні імена.
Для нашого прикладу інтерфейсу запис буде таким:
classtweaker
inject-interface net/minecraft/world/level/material/FlowingFluid com/example/docs/interface_injection/BucketEmptySoundGetter1
Загальні інтерфейси
Якщо у вашому інтерфейсі є загальні, ви можете вказати їх у записі. Для цього додайте кутові дужки <> в кінці назви інтерфейсу з узагальненими у форматі підпису байт-коду Java між дужками.
Формат сигнатури такий:
| Опис | Приклад Java | Синтаксис | Приклад формату сигнатури |
|---|---|---|---|
| Тип класу | java.lang.String | Формат дескриптора | Ljava/lang/String; |
| Тип масиву | java.lang.String[] | Формат дескриптора | [Ljava/lang/String; |
| Примітив | boolean | Символ дескриптора | Z |
| Тип змінної | T | T + назва + ; | TT; |
| Загальний тип класу | java.util.List<T> | L + унутрішнє ім'я + < + загальні + >; | Ljava/util/List<TT;>; |
| Символ підставлення | ?, java.util.List<?> | Символ * | *, java/util/List<*>; |
| Обмеження символу підставлення розширення | ? extends String | + + обмеження | +Ljava/lang/String; |
| Обмеження символу підставлення супер | ? super String | - + обмеження | -Ljava/lang/String; |
Отже, щоб додати інтерфейс:
java
package com.example.docs.interface_injection;
public interface GenericInterface<T, U> {
}1
2
3
4
5
2
3
4
5
із загальним <? extends String, Boolean[]>
Запис твікера класу буде таким:
classtweaker
inject-interface net/minecraft/world/level/material/FlowingFluid com/example/docs/interface_injection/GenericInterface<+Ljava/lang/String;[Ljava/lang/Boolean;>1
Застосування змін
Щоб побачити внесені реалізації інтерфейсу, оновіть проєкт Gradle за допомогою перегенерування джерел. Якщо зміни не показано, ви можете спробувати перевірити файл та перевірити на наявність помилок.
Додані методи тепер можна використовувати в екземплярах класу, в який було впроваджено інтерфейс:
java
void example(FlowingFluid flowingFluid) {
Optional<SoundEvent> sound = flowingFluid.example_mod$getBucketEmptySound();
/* ... */
}1
2
3
4
2
3
4
Ви також можете перевизначити методи в підкласах цільового впровадження інтерфейсу, якщо це необхідно.








