Начинающий
- Статус
- Оффлайн
- Регистрация
- 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) Пишем класс в который хотим зайти
2) выбираем нужный путь и нажимаем tab
3)
получается как то так
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 не показывает это как ошибку.
Название темы - небольшая отсылка. Кто знает тот поймет почему ночью.
Для начала:
Миксин - класс который обозначен как миксин какого то класса игры(перед объявлением класса надо написать @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) Пишем класс в который хотим зайти
2) выбираем нужный путь и нажимаем tab
3)
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 не показывает это как ошибку.
Название темы - небольшая отсылка. Кто знает тот поймет почему ночью.