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

7,099
324
1,510
Зачем нужна переменная visitingHook? Она нигде больше не юзается
Java:
//HookInjectorMethodVisitor

/**
 * Вставляет хук в байткод.
 */
protected final void visitHook() {
    if (!cv.visitingHook) {
        cv.visitingHook = true;
        hook.inject(this);
        cv.visitingHook = false;
    }
}
 
7,099
324
1,510
hook.inject может порождать другие вызовы visitHook?
 
У меня не работает на последних версия Forge, вылетает практически сразу при загрузке игры.
В eclipse все нормально, а в собранном проекте - нет. Methods.bin в корень мода положил.
Вот, что в логах пишет.
HTML:
[00:15:58] [main/INFO]: [HOOKLIB]  Obfuscated: true
[00:15:58] [main/ERROR]: Unable to launch
java.lang.RuntimeException: An error occurred trying to configure the Minecraft home at D:\Games\Minecraft\Profiles\MyMod for Forge Mod Loader
    at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupHome(FMLLaunchHandler.java:111) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupClient(FMLLaunchHandler.java:81) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.FMLLaunchHandler.configureForClientLaunch(FMLLaunchHandler.java:42) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.common.launcher.FMLTweaker.injectIntoClassLoader(FMLTweaker.java:139) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:115) [launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
Caused by: java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method) ~[?:1.8.0_51]
    at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_51]
    at net.minecraftforge.fml.relauncher.CoreModManager.loadCoreMod(CoreModManager.java:526) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.CoreModManager.discoverCoreMods(CoreModManager.java:450) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.CoreModManager.handleLaunch(CoreModManager.java:264) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupHome(FMLLaunchHandler.java:107) ~[forge-1.12.2-14.23.5.2768.jar:?]
    ... 5 more
Caused by: java.lang.NullPointerException
    at net.minecraftforge.fml.common.asm.transformers.DeobfuscationTransformer.<init>(DeobfuscationTransformer.java:61) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at author.hooklib.minecraft.HookLoader.<clinit>(HookLoader.java:24) ~[HookLoader.class:?]
    at java.lang.Class.forName0(Native Method) ~[?:1.8.0_51]
    at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_51]
    at net.minecraftforge.fml.relauncher.CoreModManager.loadCoreMod(CoreModManager.java:526) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.CoreModManager.discoverCoreMods(CoreModManager.java:450) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.CoreModManager.handleLaunch(CoreModManager.java:264) ~[forge-1.12.2-14.23.5.2768.jar:?]
    at net.minecraftforge.fml.relauncher.FMLLaunchHandler.setupHome(FMLLaunchHandler.java:107) ~[forge-1.12.2-14.23.5.2768.jar:?]
    ... 5 more
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]: net.minecraftforge.fml.relauncher.FMLSecurityManager$ExitTrappedException
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]:     at net.minecraftforge.fml.relauncher.FMLSecurityManager.checkPermission(FMLSecurityManager.java:49)
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]:     at java.lang.SecurityManager.checkExit(SecurityManager.java:761)
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]:     at java.lang.Runtime.exit(Runtime.java:107)
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]:     at java.lang.System.exit(System.java:971)
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]:     at net.minecraft.launchwrapper.Launch.launch(Launch.java:138)
[00:15:58] [main/INFO]: [java.lang.ThreadGroup:uncaughtException:1052]:     at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
 
Последнее редактирование:
7,099
324
1,510
Скинь хук, который юзаешь и версию forge. Проверь, работает ли без хуков.
 
Последнее редактирование:
7,099
324
1,510
Я попробовал на версии forge-1.12.2-14.23.5.2768(recommended), со стандартными хуками из примеров - все работает
 
На версии 14.23.5.2768 не работает. Даже с убранными хуками, в моде где есть только непосредственно хук лоадер.
 
7,099
324
1,510
Я использовал для тестов свой форк хуклбы, но он не отличается теми классами, фигурирующими в краше, от оригинальной хуклибы.
Какую версию java юзаешь? Под 8 работает.
 
Java используется поставляемая с Minecraft, однако когда попробовал использовать свою - 8, результат не изменился.

Последняя версия Forge с которой все работает - 14.23.4.2762 , а вот в changelog версии 14.23.4.2763 написаны такие изменения:
Class transformer optimizations (#5159)
* Filter packages for deobf transformation
* Only serialize transformed class with TerminalTransformer if bytecode changed

Может с этим как-то связано?
 
7,099
324
1,510
Вполне возможно. У тебя не работает только в собранном моде? Или в среде тоже?
 
В среде как-раз таки работает, хотя версия Forge там тоже почти самая новая - 14.23.4.2760 . Так что не понимаю, что не так.
 
7,099
324
1,510
Понятно, завтра потестирую
 
808
3
124
Java используется поставляемая с Minecraft, однако когда попробовал использовать свою - 8, результат не изменился.

Последняя версия Forge с которой все работает - 14.23.4.2762 , а вот в changelog версии 14.23.4.2763 написаны такие изменения:
Class transformer optimizations (#5159)
* Filter packages for deobf transformation
* Only serialize transformed class with TerminalTransformer if bytecode changed

Может с этим как-то связано?

Спасибо, ставить фордж разбираться мне было лень, но от этого патча в фордже понятным образом ломается хуклиба, связано с порядком инициализации. Мне лень коммитить/тестить фикс (тем более что для использования в 1.12 классы хуклибы и так нужно руками патчить), но оно должно тривиально чиниться. HookLoader#deobfuscationTransformer сейчас создается в static инициализации, надо же только при необходимости. Что-то вроде этого в HookLoader:
Java:
    static DeobfuscationTransformer getDeobfuscationTransformer() {
        if (HookLibPlugin.getObfuscated() && deobfuscationTransformer == null) {
            deobfuscationTransformer = new DeobfuscationTransformer();
        }
        return deobfuscationTransformer;
    }

(само поле deobfuscationTransformer сделать private, в полутора местах где оно используется юзать геттер)
 
808
3
124
Подлянка со стороны форджа конечно, уже собранные моды под 1.12 сломаются с новым форджем =(
 
7,099
324
1,510
Т.е. его экземпляр нужно создавать только один раз?
 
808
3
124
Не суть, можно хоть вообще выпилить кеширующее поле и каждый раз создавать новый
 
7,099
324
1,510
Суть в ленивой инициализации - создавать значение, когда понадобится?
 
808
3
124
Суть в ленивой инициализации - создавать значение, когда понадобится?
Суть в том чтобы не грузить класс раньше чем он может загрузиться, вот и всё
Ленивой инициализацией это проще всего добиться
 
235
3
21
Допустим если нужно изменить алгоритм в классе EntityRendered, который высчитывает расстояние для действий игрока, но до и после расчетов имеются вызовы приватных переменных, которые я не могу никак дублировать в хуке, есть ли еще варианты кроме костыльной вставки кода по строке, тк если я буду делать так будет производиться 2 расчета, 1 из которых не нужен?
 
Сверху