[Гайд][Легко][1.6+] Модификация чужого кода при запуске (трансфомеры)

Что значит Can not found target method of hook. В еклипсе все было нормально, а вот на сервере такое пишет и патч не проходит.


Получается что Cauldron нельзя патчить? В клиенте работает, а там нет.
 
Методы закинул в папку с ресурсами мода?


GloomyFolken написал(а):
Пришел к выводу, что большинству удобнее упаковывать хуклибу в свой мод, и переписал урок под это.

Можешь, если не сложно, расписать, как сделать через либу (под отдельным спойлером, например)? Я собрал все, но когда загружается мой мод вылетает NoClassDefFoundError: HookLoader.
Пофиксил диким костылем, хотелось бы узнать, как надо.
 
Dahaka написал(а):
Можешь, если не сложно, расписать, как сделать через либу (под отдельным спойлером, например)? Я собрал все, но когда загружается мой мод вылетает NoClassDefFoundError: HookLoader.
Пофиксил диким костылем, хотелось бы узнать, как надо.

Лучше не надо делать через отдельную либу :V
Там сейчас есть проблемка: если хуклиба лежит отдельно, и грузится позже, чем ваш кормод, то ничего не работает (и как раз с NoClassDefFoundError'ами). У меня проблема решена тем, что джарник с хуклибой называется "AHookLib.jar" (и грузится форджем раньше других модов только из-за названия). Вот это точно "дикий костыль" :D

А если просто положить классы хуклибы в ваш мод, то всё должно хорошо работать, и не знаю, откуда там может быть NoClassDefFoundError. Может быть, неправильно переименовываешь пакет? Например, при сборке у тебя в проекте gloomyfolken.hooklib, и только после сборки переименовываешь папку в yourmod.hooklib? Если нет, можно полный крашлог?


alex0 написал(а):
Получается что Cauldron нельзя патчить? В клиенте работает, а там нет.

Можно, что-то не так со словарём названий методов. Точно-точно не забыл упаковать methods.bin в мод для колдрона? Поищи в логе ошибку "Can not load obfuscated method names".
 
GloomyFolken написал(а):
У меня проблема решена тем, что джарник с хуклибой называется "AHookLib.jar" (и грузится форджем раньше других модов только из-за названия). Вот это точно "дикий костыль"
Ухаха)) Вот именно так я и сделал, только с маленькой буквы)))


GloomyFolken написал(а):
и не знаю, откуда там может быть NoClassDefFoundError.
Да не, если все внутрь закинуть, все отлично работает.
 
Все упаковано было. Да и оно должно было встать после Gradle build полюбому же не?
 
Dahaka хочет юзать отдельной либой, видимо, из разных модов
 
alex0 написал(а):
Все упаковано было. Да и оно должно было встать после Gradle build полюбому же не?

Проблема с колдроном все еще не решена? Если нет, дай лог запуска сервера, пожалуйста.
 
Да все решил уже, методы не ремапятся в @hook. Открыл methods.csv форрджевский и вписал нужные srg имена методов.
 
Не получается заюзать на 1.10.2 версии.
Че делал:
Скачал MCP, сгенерил methods.dat, закинул его в resources
Добавил аннотацию @IFMLLoadingPlugin.MCVersion(value = "1.10.2"), т.к. майн в логе просил.
Вот такой код:
Код:
@IFMLLoadingPlugin.MCVersion(value = "1.10.2")//без нее тоже не пашет
public class ExampleHookLoader extends HookLoader {

    @Override
    public void registerHooks() {
        registerHookContainer("ete.asm.ItemRender");
    }
}
Код:
public class ItemRender {//ни один из хуков не пашет
    @Hook()
    public static ActionResult<ItemStack> onItemRightClick(Item item, ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) {//Для теста пробовал кидать жемчуг, кликать палкой по траве
        System.out.println("test");
        return new ActionResult(EnumActionResult.PASS, itemStackIn);
    }
    @Hook(returnCondition = ReturnCondition.ALWAYS)
    public static void renderItem(ItemRenderer ir, EntityLivingBase entityIn, ItemStack heldStack, ItemCameraTransforms.TransformType transform) {//это должно было каждый тик вызывать, вроде
        System.out.println("test");
    }
}
Лог консоли: https://pastebin.com/pQ1EJhSf
Заранее спасибо за помощь
 
Agravaine написал(а):
Странно, но если неявно трогать объект класса, то будет вываливаться ClassNotFoundException.
Не знаю, нужно ли тебе, или нет, но я нашел такой комментарий в hooklib.asm.SafeClassWriter:
Код:
/**
 * ClassWriter с другой реализацией метода getCommonSuperClass: при его использовании не происходит загрузки классов.
 * Однако, сама по себе загрузка классов редко является проблемой, потому что инициализация класса (вызов статических
 * блоков) происходит не при загрузке класса. Проблемы появляются, когда хуки вставляются в зависимые друг от друга
 * классы, тогда стандартная реализация отваливается с ClassCircularityError.
 */
Кажется, из-за этого у тебя вываливался ClassNotFoundException.
 
Вопрос, можно ли добавить методы в класс не подменяя его вместе с аннотацией @Override?
Просто ну очень не охото делать/учиться подмене.(Если я подменю класс, то могу сломать другие моды, возможно, хотя с другой стороны я уже сломал ModLoader и теперь половину модов нужно портировать. )
 
Хуки дают совместимость с другими модами "из коробки" в 95%(примерно) случаев(остальные 5% - это когда целиком заменяется метод и может возникнуть несовместимость)
 
hohserg написал(а):
Хуки дают совместимость с другими модами "из коробки" в 95%(примерно) случаев(остальные 5% - это когда целиком заменяется метод и может возникнуть несовместимость)
Там вообще этих методов нет, поэтому их нужно туда запилить и переопределить. Ибо наследование. И собственно это пара предметов из другого мода, который забросили уже года эдак 3-4
 
talosdx написал(а):
Там вообще этих методов нет, поэтому их нужно туда запилить и переопределить. Ибо наследование. И собственно это пара предметов из другого мода, который забросили уже года эдак 3-4

Самому изредка такое нужно, но, к сожалению, через хуклибу действительно никак не переопределить метод суперкласса.

Ещё проблемы возникают, когда нужно заменить логику конструктора, который начинается с вызова конструктора суперкласса. Нормально получается хукаться только в конец таких конструкторов =(

Возможно, когда-нибудь решу эти проблемы, но пока что сам костылю через вручную написанные трансформеры и не могу предложить вам ничего другого.
 
Обновил либу до версии 0.8.1 (качайте с гитхаба)
Гайд тоже немного обновил, теперь там больше подробностей о том, как работать с хуклибой на версиях майна 1.7 и выше.

Changelog:

1. Наконец-то можно создавать отсутствующие методы. Это нужно, когда есть необходимость переопределить метод суперкласса.
Делается как-то так:
Код:
@Hook(createMethod = true, returnCondition = ALWAYS)
public static int idDropped(BlockDirt blockDirt, int meta, Random rng, int fortune) {
   return 2;
}
То есть тут мы в классе BlockDirt создаем метод idDropped(int, Random, int). Такой же метод есть в классе Block и нам надо его переопределить.

  • createMethod = true значит, что при провалившейся попытке найти целевой метод для вставки хука создается новый метод.
  • Список аргументов создаваемого метода берется из аргументов хук-метода.
  • Возвращаемый тип создаваемого метода можно задать через targetMethodReturnType.
  • Если targetMethodReturnType не указан, то возвращаемый тип берется из возвращаемого типа хук-метода.

Сначала хуклиба создает в классе BlockDirt простой вызов супер-метода:
Код:
public int idDropped(int meta, Random rng, int fortune) {
    return super.idDropped(meta, rng, fortune);
}


Потом сюда по обычным правилам вставляется хук:
Код:
public int idDropped(int meta, Random rng, int fortune) {
    return MyHooks.idDropped(this, meta, rng, fortune);
    //return super.idDropped(meta, rng, fortune); <-- никогда не вызывается
}

2. Исправил проблемы со вставкой хуков в конструкторы. Теперь вы смело можете вставлять хуки хоть в начало, хоть в конец конструкторов. 
Как и раньше, чтобы вставить хук в конструктор, нужно написать в аннотации targetMethod = "<init>", но теперь это работает не через раз, а всегда. Вставка в начало конструктора производится после вызова super-конструктора. Пример:
Код:
@Hook(targetMethod = "<init>")
public static void blockSandConstructor(BlockSand blockSand, int id){
    System.out.println("Constructing BlockSand!");
}

Отработает это так:
Код:
public BlockSand(int id) {
    super(id, Material.sand);
    MyHooks.blockSandConstructor(this, id); // хук в начале конструктора
    this.setCreativeTab(CreativeTabs.tabBlock);
}

3. Добавил "обязательные" хуки. Если вставка такого хука не удастся, хуклиба не просто выдаст предупреждение в лог, а крашнет игру. Чтобы пометить хук обязательным, в параметрах аннотации добавьте isMandatory = true.


Спасибо @Dahaka за репорты год назад, теперь вот я таки исправил то, о чем он говорил :V
Ещё спасибо @talosdx за просьбу добавить возможность создавать методы, благодаря этой просьбе мне стало ясно, что я - не единственный, кому такая фича нужна.
 
Хэхэй, теперь можно сделать столько всего! Великий день! (смогу наконец-то провернуть модификацию WorldSurface). Огромнейшее спасибо!
 
!!!!!!!!!!!!
Просто шикарно!! Все три пункта гипер полезные!


GloomyFolken написал(а):
благодаря этой просьбе мне стало ясно, что я - не единственный, кому такая фича нужна.
Конечно нужна. А я думал, что нет возможности такое провернуть.


Если еще перевести комментарии на инглиш, еще лучше будет :)


Кстати, АТ можно юзать в версиях 1.7.10-, на там как-то немного по-другому. Еще нашел гайд, получше, чем мой. И ещё.
 
Либа умеет работать и с протект-методами? :huh:

Мой хук


оригинальный код


Результат - 



Хук сработал в protected метод.
 
Agravaine написал(а):
Он и приватный схавает.

А чего в гайде написано, что целевой метод обязательно публичным должен быть?
 
Назад
Сверху