Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Гайд Миксины и с чем их хавают ночью

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
7 Ноя 2025
Сообщения
256
Реакции
2
Всем хай! Думаю вы зашли на эту тему если не понимаете миксины и хотите разобраться / переходите с MCP на fabric.
Для начала:
Миксин - класс который обозначен как миксин какого то класса игры(перед объявлением класса надо написать @Mixin(название_класса.class). Например MinecraftClientMixin - миксин класса MinecraftClient(главного класса игры).
Зачем это надо? В fabric ты не можешь зайти в класс и добавить что то просто так. Чтобы добавить что то свое в класс игры надо создать миксин.

Например тот же самый миксин в класс MinecraftClient. Мы хотим запостить ивент(например ивент тик) чтобы он работал. На MCP мы бы просто зашли в главный класс и добавили туда пост ивента, а через миксин мы пишет
@Mixin(MinecraftClient.class)
public class MinecraftClientMixin {

@Inject(method = "tick", at = @At("HEAD"))
public void onTick(CallbackInfo ci) {
Client.getInstance().getEventBus().post(new EventTick());
}

}

Что мы сделали? В начале сказали что это миксин класса MinecraftClient. Потом написали инжект(вставить свой код куда то(потом мы написали HEAD, т.е в начале) в методе который указан в инжекте(в нашем случае tick)), написали public void onTick() и потом нажимаем show context actions -> fix method signature. потом мы постим ивент.

Кроме HEAD есть еще TAIL(вставить в конце), RETURN(перед каждым выходом из метода(т.е в конце и перед каждым return), NEW(при создании объекта), FIELD(при чтении/записи филдов), INVOKE(около чего то, потом еще поговорим об этом), так же есть другие но они слишком редко используются и я решил не писать про них.

Кроме инжекта есть:
ModifyArg - изменяет 1 аргумент при вызове другого метода внутри целевого метода
ModifyArgs - изменяет все аргументы ⬆️
Redirect - меняет вызов выбранного метода на вызов вашего метода
ModifyVariable - меняет значение локальной переменной
ModifyExpressionValue - изменяет результат вызова метода
Overwrite - переписывает весь метод(не использовать без крайней необходимости)

Некоторые из этих аннотаций просят target(место в котором надо что то сделать).
Как его получить?

1) Пишем класс в который хотим зайти
1768725760754.png


2) выбираем нужный путь и нажимаем tab
3)
1768725787450.png
получается как то так
4) кликаем по нему мышкой и нажимаем CTRL + B(так мы перейдем в этот декомпилированый класс)
5) теперь находим место из которого мы хотим получить target(я взял рандомную строку) -> ПКМ -> Copy / Paste special -> Mixin target reference. Вставляем то что скопировалось в таргет.


Что требует таргет? Inject(когда в at INVOKE, NEW или FIELD) и все остальное. Так же есть такая штука как At.Shift.значение для INVOKE, NEW, FIELD. С помощью него мы можем выбирать где будет вставлен код(AFTER - после, BY(int n) - на n строчек(может быть отрицательным), BEFORE - перед, NONE - по умолчанию(можно не писать)).

Так же вы наверное заметили что у меня в примере используется CallbackInfo ci. Зачем он нужен? Я могу написать ci.cancel() и метод не сработает. Так же есть CallbackInfoReturnable(канцельнуть его нельзя, можно только подменить возвращаемое значение названиеЕгоАргумента.setReturnValue(null) / другое значение которое вам надо). Так же чтобы ci.cancel() работал, надо чтобы в инжекте было прописано cancellable(оно предложит это сделать если вы напишете ci.cancel())


Частые ошибки:

1) Отмена какого то важного метода без осознания последствий. Например если отменить метод tick то игра не будет работать
2) Использование ci.cancel() без cancellable = true, такое происходит из за того что idea не показывает это как ошибку.



Название темы - небольшая отсылка. Кто знает тот поймет почему ночью.
 
Всем хай! Думаю вы зашли на эту тему если не понимаете миксины и хотите разобраться / переходите с MCP на fabric.
Для начала:
Миксин - класс который обозначен как миксин какого то класса игры(перед объявлением класса надо написать @Mixin(название_класса.class). Например MinecraftClientMixin - миксин класса MinecraftClient(главного класса игры).
Зачем это надо? В fabric ты не можешь зайти в класс и добавить что то просто так. Чтобы добавить что то свое в класс игры надо создать миксин.

Например тот же самый миксин в класс MinecraftClient. Мы хотим запостить ивент(например ивент тик) чтобы он работал. На MCP мы бы просто зашли в главный класс и добавили туда пост ивента, а через миксин мы пишет
@Mixin(MinecraftClient.class)
public class MinecraftClientMixin {

@Inject(method = "tick", at = @At("HEAD"))
public void onTick(CallbackInfo ci) {
Client.getInstance().getEventBus().post(new EventTick());
}

}

Что мы сделали? В начале сказали что это миксин класса MinecraftClient. Потом написали инжект(вставить свой код куда то(потом мы написали HEAD, т.е в начале) в методе который указан в инжекте(в нашем случае tick)), написали public void onTick() и потом нажимаем show context actions -> fix method signature. потом мы постим ивент.

Кроме HEAD есть еще TAIL(вставить в конце), RETURN(перед каждым выходом из метода(т.е в конце и перед каждым return), NEW(при создании объекта), FIELD(при чтении/записи филдов), INVOKE(около чего то, потом еще поговорим об этом), так же есть другие но они слишком редко используются и я решил не писать про них.

Кроме инжекта есть:
ModifyArg - изменяет 1 аргумент при вызове другого метода внутри целевого метода
ModifyArgs - изменяет все аргументы ⬆️
Redirect - меняет вызов выбранного метода на вызов вашего метода
ModifyVariable - меняет значение локальной переменной
ModifyExpressionValue - изменяет результат вызова метода
Overwrite - переписывает весь метод(не использовать без крайней необходимости)

Некоторые из этих аннотаций просят target(место в котором надо что то сделать).
Как его получить?

1) Пишем класс в который хотим зайти
Посмотреть вложение 325073

2) выбираем нужный путь и нажимаем tab
3)Посмотреть вложение 325074получается как то так
4) кликаем по нему мышкой и нажимаем CTRL + B(так мы перейдем в этот декомпилированый класс)
5) теперь находим место из которого мы хотим получить target(я взял рандомную строку) -> ПКМ -> Copy / Paste special -> Mixin target reference. Вставляем то что скопировалось в таргет.


Что требует таргет? Inject(когда в at INVOKE, NEW или FIELD) и все остальное. Так же есть такая штука как At.Shift.значение для INVOKE, NEW, FIELD. С помощью него мы можем выбирать где будет вставлен код(AFTER - после, BY(int n) - на n строчек(может быть отрицательным), BEFORE - перед, NONE - по умолчанию(можно не писать)).

Так же вы наверное заметили что у меня в примере используется CallbackInfo ci. Зачем он нужен? Я могу написать ci.cancel() и метод не сработает. Так же есть CallbackInfoReturnable(канцельнуть его нельзя, можно только подменить возвращаемое значение названиеЕгоАргумента.setReturnValue(null) / другое значение которое вам надо). Так же чтобы ci.cancel() работал, надо чтобы в инжекте было прописано cancellable(оно предложит это сделать если вы напишете ci.cancel())


Частые ошибки:

1) Отмена какого то важного метода без осознания последствий. Например если отменить метод tick то игра не будет работать
2) Использование ci.cancel() без cancellable = true, такое происходит из за того что idea не показывает это как ошибку.



Название темы - небольшая отсылка. Кто знает тот поймет почему ночью.
а утром не едят миксины?
 
Назад
Сверху Снизу