====== Инжекторы Миксинов ======
===== Вступление =====
Инжекторы позволяют размещать пользовательский код в указанной позиции внутри существующего метода. Для рабочего примера просмотрите [[ru:tutorial:mixin_injects#Пример|категорию внизу этой страницы]]. Стандартная форма внедрения выглядит так, как показано в коде:
@Inject(method = "", at = @At("INJECTION POINT REFERENCE"))
private void injectMethod(METHOD ARGS, CallbackInfo info) {
}
[[https://github.com/SpongePowered/Mixin/wiki/Injection-Point-Reference|Контрольная-Точка-Внедрения]] определяет, где код внутри тела метода вводится внутри целевого метода. В следующей таблице описаны некоторые из вариантов:
^ Имя ^ Описание ^
| HEAD | Верхняя часть метода |
| RETURN | Перед каждым оператором return |
| INVOKE | При вызове метода |
| TAIL | Перед заключительным оператором возврата |
В случае точек внедрения, которые ссылаются на операторы или элементы, целевое значение может быть установлено внутри //@At//. Целевое значение задается с помощью дескрипторов байт-кода JVM.
Oracle определяет следующее [[https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-4.html#jvms-4.3.2|поля дескрипторов]]:
^ Дескриптор ^ Тип ^ Описание ^
| B | byte | Записанный байт |
| C | char | Кодовая точка символа Юникода в базовой многоязычной плоскости, закодированная с помощью UTF-16 |
| D | double | Значение с плавающей точкой двойной точности |
| F | float | Значение с плавающей точкой одинарной точности |
| I | int | Целое число |
| J | long | Длинное целое число |
| L//ClassName//; | reference | экземпляр //ClassName// |
| S | short | Краткая запись |
| Z | boolean | ''true''(правда) или ''false''(ложь) |
| [ | reference | Одно измерение массива |
Дескриптор метода состоит из имени метода, за которым следует набор круглых скобок, содержащих типы ввода, за которыми следует тип вывода. Метод, определенный в Java как ''Object m(int i, double[] d, Thread t)'' будет иметь дескриптор метода ''m(I[DLjava/lang/Thread;)Ljava/lang/Object;''.
Типы дженериков не учитываются, так как дженерики не существуют во время выполнения. Значит ''Pair>'' станет ''Lcom/mojang/datafixers/util/Pair''.
//@Inject// методы всегда имеют возвращаемый тип void. Имя метода не имеет значения; лучше всего использовать что-то, описывающее, что делает внедрение. Аргументы целевого метода помещаются первыми в заголовок метода, за которым следует объект "CallbackInfo". Если целевой метод имеет возвращаемый тип (T), вместо "CallbackInfoReturnable" используется "Callbackinfo".
=== Возврат и отмена при внедрении ===
Чтобы отменить или вернуться раньше внутри метода, используйте ''CallbackInfo#cancel'' или ''CallbackInfoReturnable#setReturnValue(T)''. Обратите внимание, что "cancel" не обязательно вызывается после "setReturnValue". В обоих случаях для параметра "cancellable" в аннотации внедрения должно быть установлено значение true:
@Inject(method = "...", at = @At("..."), cancellable = true)
=== Внедрение в конструкторы ===
Чтобы внедрить в конструктор, используйте ''()V'' в качестве целевого метода, ''()'' содержит дескрипторы аргументов конструктора. При вводе в конструкторы "@At" должно быть установлено либо на "TAIL", либо на "RETURN". Никакие другие формы внедрения официально не поддерживаются. Обратите внимание, что некоторые классы имеют методы с именем "init", которые отличаются от "". Не путайте!
Чтобы внедрить в статический конструктор, используйте "" в качестве имени метода.
===== Пример =====
В следующем примере вводится оператор печати в верхней части "TitleScreen#init" (примечание: метод "init" является обычным методом, а не конструктором).
@Mixin(TitleScreen.class)
public class ExampleMixin {
@Inject(at = @At("HEAD"), method = "init()V")
private void init(CallbackInfo info) {
System.out.println("Эта строка написана модом через миксин!");
}
}
Для получения дополнительной информации об этом конкретном примере ознакомьтесь с его использованием в [[https://github.com/FabricMC/fabric-example-mod/blob/master/src/main/java/net/fabricmc/example/mixin/ExampleMixin.java|репозитории Fabric Example Mod]].