[Kotlin] Котлинотрансформеры

Версия Minecraft
1.7.10
1,976
68
220
Доброго времени суток о/

Я решил перенести свой джавакод на котлин, и столкнулся с одной проблемой при переносе трансформеров: на java он работает нормально, а его аналог на котлине - крашит. Собственно, вот сам код:
Java:
import static jdk.internal.org.objectweb.asm.Opcodes.*;

import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import net.minecraft.launchwrapper.IClassTransformer;

public class AlfheimClassTransformer implements IClassTransformer {

    @Override
    public byte[] transform(String name, String transformedName, byte[] basicClass) {
        if (transformedName.equals("vazkii.botania.common.item.relic.ItemRelic")) {
            ClassReader cr = new ClassReader(basicClass);
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            ItemRelic_ClassVisitor ct = new ItemRelic_ClassVisitor(cw);
            cr.accept(ct, ClassReader.SKIP_FRAMES);
            return cw.toByteArray();
        }
        return basicClass;
    }

    public static class ItemRelic_ClassVisitor extends ClassVisitor {

        public ItemRelic_ClassVisitor(ClassVisitor cv) {
            super(ASM5, cv);
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            if (name.equals("addBindInfo")) return new ItemRelic_addBindInfo_MethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
            return super.visitMethod(access, name, desc, signature, exceptions);
        }
    
        public static class ItemRelic_addBindInfo_MethodVisitor extends MethodVisitor {

            private boolean perform = false;
        
            public ItemRelic_addBindInfo_MethodVisitor(MethodVisitor mv) {
                super(ASM5, mv);
            }
        
            @Override
            public void visitJumpInsn(int opcode, Label label) {
                if (opcode == IF_ACMPNE) {
                    if (!perform) {
                        perform = true;
                        super.visitJumpInsn(opcode, label);
                    } else {
                        visitInsn(POP2);
                        visitInsn(ICONST_1);
                        super.visitJumpInsn(IFEQ, label);
                    }
                } else {
                    super.visitJumpInsn(opcode, label);
                }
            }
        }
    }
}
Kotlin:
import jdk.internal.org.objectweb.asm.Opcodes.*

import jdk.internal.org.objectweb.asm.ClassReader
import jdk.internal.org.objectweb.asm.ClassVisitor
import jdk.internal.org.objectweb.asm.ClassWriter
import jdk.internal.org.objectweb.asm.Label
import jdk.internal.org.objectweb.asm.MethodVisitor
import net.minecraft.launchwrapper.IClassTransformer

class AlfheimClassTransformerKT : IClassTransformer {

    override fun transform(name: String, transformedName: String, basicClass: ByteArray): ByteArray {
        if (transformedName.equals("vazkii.botania.common.item.relic.ItemRelic")) {
            var cr = ClassReader(basicClass)
            var cw = ClassWriter(ClassWriter.COMPUTE_MAXS)
            var ct = ItemRelic_ClassVisitor(cw)
            cr.accept(ct, ClassReader.SKIP_FRAMES)
            return cw.toByteArray()
        }
        return basicClass
    }

    class ItemRelic_ClassVisitor(var cv: ClassVisitor) : ClassVisitor(ASM5, cv) {
    
        override fun visitMethod(access: Int, name: String, desc: String, signature: String, exceptions: Array<String>) : MethodVisitor {
            if (name.equals("addBindInfo")) return ItemRelic_addBindInfo_MethodVisitor(super.visitMethod(access, name, desc, signature, exceptions))
            return super.visitMethod(access, name, desc, signature, exceptions)
        }
    
        class ItemRelic_addBindInfo_MethodVisitor(var mv: MethodVisitor) : MethodVisitor(ASM5, mv) {
            private var perform = false
        
            override fun visitJumpInsn(opcode: Int, label: Label) {
                if (opcode == IF_ACMPNE) {
                    if (!perform) {
                        perform = true
                        super.visitJumpInsn(opcode, label)
                    } else {
                        visitInsn(POP2)
                        visitInsn(ICONST_1)
                        super.visitJumpInsn(IFEQ, label)
                    }
                } else {
                    super.visitJumpInsn(opcode, label)
                }
            }
        }
    }
}
Код:
[Client thread/ERROR] [alfheim]: Skipping event FMLPreInitializationEvent and marking errored mod alfheim since required dependency Botania has errored
[Client thread/ERROR] [FML]: Fatal errors were detected during the transition from PREINITIALIZATION to INITIALIZATION. Loading cannot continue
[Client thread/ERROR] [FML]:
    States: 'U' = Unloaded 'L' = Loaded 'C' = Constructed 'H' = Pre-initialized 'I' = Initialized 'J' = Post-initialized 'A' = Available 'D' = Disabled 'E' = Errored
    UCH    mcp{9.05} [Minecraft Coder Pack] (minecraft.jar)
    UCH    FML{7.10.99.99} [Forge Mod Loader] (forgeSrc-1.7.10-10.13.4.1614-1.7.10.jar)
    UCH    Forge{10.13.4.1614} [Minecraft Forge] (forgeSrc-1.7.10-10.13.4.1614-1.7.10.jar)
    UCH    NotEnoughItems{1.0.5.120} [Not Enough Items] (NotEnoughItems-1.7.10-1.0.5.120-dev.jar)
    UCH    CodeChickenCore{1.0.7.47} [CodeChicken Core] (minecraft.jar)
    UCH    Baubles{1.0.1.10} [Baubles] (Baubles-deobf-1.7.10-1.0.1.10.jar)
    UCE    Botania{r1.8-249} [Botania] (Botania r1.8-249-deobf.jar)
    UCE    alfheim{BETA-BETA-pre5.22} [Alfheim] (bin)
    UCH    elvenstory{1.0} [elvenstory] (bin)
[Client thread/ERROR] [FML]: The following problems were captured during this phase
[Client thread/ERROR] [FML]: Caught exception from Botania
java.lang.NoClassDefFoundError: vazkii/botania/common/item/relic/ItemInfiniteFruit
    at vazkii.botania.common.core.proxy.CommonProxy.preInit(CommonProxy.java:104) ~[Botania%20r1.8-249-deobf.jar:?]
    at vazkii.botania.client.core.proxy.ClientProxy.preInit(ClientProxy.java:204) ~[Botania%20r1.8-249-deobf.jar:?]
    at vazkii.botania.common.Botania.preInit(Botania.java:67) ~[Botania%20r1.8-249-deobf.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_172]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_172]
    at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:532) ~[forgeSrc-1.7.10-10.13.4.1614-1.7.10.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_172]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_172]
    at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[guava-17.0.jar:?]
    at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:212) ~[forgeSrc-1.7.10-10.13.4.1614-1.7.10.jar:?]
    at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:190) ~[forgeSrc-1.7.10-10.13.4.1614-1.7.10.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_172]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_172]
    at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) ~[guava-17.0.jar:?]
    at com.google.common.eventbus.EventBus.post(EventBus.java:275) ~[guava-17.0.jar:?]
    at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:119) [LoadController.class:?]
    at cpw.mods.fml.common.Loader.preinitializeMods(Loader.java:556) [Loader.class:?]
    at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:243) [FMLClientHandler.class:?]
    at net.minecraft.client.Minecraft.startGame(Minecraft.java:522) [Minecraft.class:?]
    at net.minecraft.client.Minecraft.run(Minecraft.java:942) [Minecraft.class:?]
    at net.minecraft.client.main.Main.main(Main.java:164) [Main.class:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_172]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_172]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_172]
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
    at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source) [start/:?]
    at GradleStart.main(Unknown Source) [start/:?]
Caused by: java.lang.ClassNotFoundException: vazkii.botania.common.item.relic.ItemInfiniteFruit
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    ... 42 more
Caused by: java.lang.NoClassDefFoundError: vazkii/botania/common/item/relic/ItemRelic
    at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_172]
    at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.8.0_172]
    at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.8.0_172]
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    ... 42 more
Caused by: java.lang.ClassNotFoundException: vazkii.botania.common.item.relic.ItemRelic
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    at java.lang.ClassLoader.defineClass1(Native Method) ~[?:1.8.0_172]
    at java.lang.ClassLoader.defineClass(Unknown Source) ~[?:1.8.0_172]
    at java.security.SecureClassLoader.defineClass(Unknown Source) ~[?:1.8.0_172]
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    at java.lang.ClassLoader.loadClass(Unknown Source) ~[?:1.8.0_172]
    ... 42 more
[Client thread/INFO] [STDOUT]: [net.minecraft.client.Minecraft:displayCrashReport:388]: ---- Minecraft Crash Report ----
// There are four lights!

Description: There was a severe problem during mod loading that has caused the game to fail

cpw.mods.fml.common.LoaderException: java.lang.NoClassDefFoundError: vazkii/botania/common/item/relic/ItemInfiniteFruit
    at cpw.mods.fml.common.LoadController.transition(LoadController.java:163)
    at cpw.mods.fml.common.Loader.preinitializeMods(Loader.java:559)
    at cpw.mods.fml.client.FMLClientHandler.beginMinecraftLoading(FMLClientHandler.java:243)
    at net.minecraft.client.Minecraft.startGame(Minecraft.java:522)
    at net.minecraft.client.Minecraft.run(Minecraft.java:942)
    at net.minecraft.client.main.Main.main(Main.java:164)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
    at net.minecraftforge.gradle.GradleStartCommon.launch(Unknown Source)
    at GradleStart.main(Unknown Source)
Caused by: java.lang.NoClassDefFoundError: vazkii/botania/common/item/relic/ItemInfiniteFruit
    at vazkii.botania.common.core.proxy.CommonProxy.preInit(CommonProxy.java:104)
    at vazkii.botania.client.core.proxy.ClientProxy.preInit(ClientProxy.java:204)
    at vazkii.botania.common.Botania.preInit(Botania.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at cpw.mods.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:532)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74)
    at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47)
    at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
    at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304)
    at com.google.common.eventbus.EventBus.post(EventBus.java:275)
    at cpw.mods.fml.common.LoadController.sendEventToModContainer(LoadController.java:212)
    at cpw.mods.fml.common.LoadController.propogateStateMessage(LoadController.java:190)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74)
    at com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47)
    at com.google.common.eventbus.EventBus.dispatch(EventBus.java:322)
    at com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304)
    at com.google.common.eventbus.EventBus.post(EventBus.java:275)
    at cpw.mods.fml.common.LoadController.distributeStateMessage(LoadController.java:119)
    at cpw.mods.fml.common.Loader.preinitializeMods(Loader.java:556)
    ... 12 more
Caused by: java.lang.ClassNotFoundException: vazkii.botania.common.item.relic.ItemInfiniteFruit
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 42 more
Caused by: java.lang.NoClassDefFoundError: vazkii/botania/common/item/relic/ItemRelic
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:182)
    ... 44 more
Caused by: java.lang.ClassNotFoundException: vazkii.botania.common.item.relic.ItemRelic
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 48 more
Если что, ItemInfiniteFruit extends ItemRelic и он инициализируется первым из всех наследников ItemRelic.

Был совет повесить на мой класс IFMLLoadingPlugin'а аннотацию @TransformerExclusions("kotlin"), но и это не помогло.
Есть у кого какие идеи? Заранее спасибо :D

P.S. В котлине я немножко нуфаг, так что если ошибка очевидная, просьба не кидаться ссаными тряпками
 

Icosider

Kotliner
Администратор
3,600
99
663
Школьники не смогут скопировать код твоего мода и использовать его у себя.
Лол, не неси чушь.
Вопрос не по теме, но какое преимущество Kotlin над Java?И стоит ли переходить на него?
Удобство. С помощью котлина ты сможешь сократить свой код в разы, так же он станет более читабельным, но при этом придётся таскать с собой библиотеки котлина и соответственно вес самого мода увеличится причём ощутимо. Так же я бы не советовал переходить на него без базовых знаний Java. Конечно можно на него перейти и не зная этой самой базы, но толка от этого будет ноль.

@AlexSocol, что собсна должен должен сделать твой трансформер? Добавить, изменить, удалить что либо и т.п. Распиши, а я постараюсь воспроизвести рабочий код/исправить существующий, если кто-то раньше(фолкен, конь или дахака) не ответят.
 
1,976
68
220
что собсна должен должен сделать твой трансформер?
"Удалять" вот *этот* иф (делать его всегда тру)

постараюсь воспроизвести рабочий код
Вся фишка в том, что он рабочий. Но только до тех пор, пока написан на джава. Если пытаюсь использовать котлин - всё ломается.
 
7,099
324
1,509
Оставь эту часть кода на java
 
Сверху