Skip to content

Forge 1.12.2 Coremodding: java.lang.ClassCircularityError

I try to make a coremod on 1.12.2 Forge in order to patch some missing stuff in the Lost Cities mod. (Source: https://github.com/McJtyMods/LostCities/blob/1.12/src/main/java/mcjty/lostcities/dimensions/world/lost/BuildingInfo.java)

A friend and I have written this LostCitiesClassTransformer.java:

package com.seemdmax.lcpatches;

import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.GETSTATIC;
import static org.objectweb.asm.Opcodes.IFEQ;
import static org.objectweb.asm.Opcodes.IFGT;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;

import java.util.Arrays;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;

import mcjty.lostcities.api.ILostCityBuilding;
import mcjty.lostcities.dimensions.world.lost.BuildingInfo;
import net.minecraft.launchwrapper.IClassTransformer;

public class LostCitiesClassTransformer implements IClassTransformer {
    private static final String[] classesBeingTransformed = { "mcjty.lostcities.dimensions.world.lost.BuildingInfo" };

    @Override
    public byte[] transform(String name, String transformedName, byte[] classBeingTransformed) {
        boolean isObfuscated = !name.equals(transformedName);
        int index = Arrays.asList(classesBeingTransformed).indexOf(transformedName);
        return index != -1 ? transform(index, classBeingTransformed, isObfuscated) : classBeingTransformed;
    }

    private static byte[] transform(int index, byte[] classBeingTransformed, boolean isObfuscated) {
        System.out.println("Transform " + classesBeingTransformed[index] + " got called!");
        try {
            ClassNode classNode = new ClassNode();
            ClassReader classReader = new ClassReader(classBeingTransformed);
            classReader.accept(classNode, 0);

            System.out.println("Transforming " + classesBeingTransformed[index] + " Is Obf: " + isObfuscated);
            switch (index) {
            case 0:
                transformLCCellars(classNode, isObfuscated);
                break;
            }

            ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
            classNode.accept(classWriter);
            return classWriter.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return classBeingTransformed;
    }

    private static void transformLCCellars(ClassNode buildingInfoClass, boolean isObfuscated) {
        final String BUILDING_INFO = isObfuscated ? "<init>" : "<init>";
        final String BUILDING_INFO_DESC = isObfuscated
                ? "(IILmcjty/lostcities/dimensions/world/LostCityChunkGenerator;)V"
                : "(IILmcjty/lostcities/dimensions/world/LostCityChunkGenerator;)V";

        for (MethodNode method : buildingInfoClass.methods) {
            if (method.name.equals(BUILDING_INFO) && method.desc.equals(BUILDING_INFO_DESC)) {
                System.out.println("Found method in BuildingInfo to transform");
                AbstractInsnNode targetNode = null;
                for (AbstractInsnNode instruction : method.instructions.toArray()) {
                    if (instruction.getOpcode() == ILOAD) {
                        if (((VarInsnNode) instruction).var == 13 & instruction.getNext().getOpcode() == IFGT) {
                            System.out.println("Matched");
                            targetNode = instruction;
                            break;
                        }
                    }
                }
                if (targetNode != null) {
                    System.out.println("Target Node valid");
                    LabelNode newLabelNode = new LabelNode();

                    InsnList toInsert = new InsnList();
                    toInsert.add(new VarInsnNode(ALOAD, 0));
                    toInsert.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(BuildingInfo.class),
                            "getBuilding", "()Lmcjty/lostcities/api/ILostCityBuilding", false));
                    toInsert.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ILostCityBuilding.class),
                            "getMinCellars", "()I", false));
                    toInsert.add(
                            new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Math.class), "max", "(II)I", false));
                    method.instructions.insertBefore(targetNode, toInsert);
                    System.out.println("Transform done!");
                } else {
                    System.out.println("Something went wrong transforming BuildingInfo!");
                }
            }
        }
    }
}

The original code we want to patch (Bytecode Outline):

L101
    LINENUMBER 764 L101
    ALOAD 0
    GETFIELD mcjty/lostcities/dimensions/world/lost/BuildingInfo.profile : Lmcjty/lostcities/config/LostCityProfile;
    GETFIELD mcjty/lostcities/config/LostCityProfile.BUILDING_MINCELLARS : I
    ILOAD 13
    IFGT L102
    ICONST_0
    GOTO L103
L102
   FRAME FULL [mcjty/lostcities/dimensions/world/lost/BuildingInfo I I mcjty/lostcities/dimensions/world/LostCityChunkGenerator mcjty/lostcities/api/LostChunkCharacteristics java/util/Random I mcjty/lostcities/dimensions/world/lost/cityassets/CityStyle mcjty/lostcities/dimensions/world/lost/cityassets/PredefinedCity$PredefinedBuilding F I I I I] [I]
    ALOAD 5
    ILOAD 13
    INVOKEVIRTUAL java/util/Random.nextInt (I)I
L103
   FRAME FULL [mcjty/lostcities/dimensions/world/lost/BuildingInfo I I mcjty/lostcities/dimensions/world/LostCityChunkGenerator mcjty/lostcities/api/LostChunkCharacteristics java/util/Random I mcjty/lostcities/dimensions/world/lost/cityassets/CityStyle mcjty/lostcities/dimensions/world/lost/cityassets/PredefinedCity$PredefinedBuilding F I I I I] [I I]
    IADD
    ISTORE 14
L104
    LINENUMBER 765 L104
    ALOAD 0
    INVOKEVIRTUAL mcjty/lostcities/dimensions/world/lost/BuildingInfo.getMaxHighwayLevel ()I
    IFLT L105
L167
    LOCALVARIABLE topleft Lmcjty/lostcities/dimensions/world/lost/BuildingInfo; L58 L73 8
    LOCALVARIABLE reldest F L96 L94 13
    LOCALVARIABLE predefinedBuilding Lmcjty/lostcities/dimensions/world/lost/cityassets/PredefinedCity$PredefinedBuilding; L75 L74 8
    LOCALVARIABLE cityFactor F L85 L74 9
    LOCALVARIABLE maxfloors I L86 L74 10
    LOCALVARIABLE f I L87 L74 11
    LOCALVARIABLE minfloors I L91 L74 12
    LOCALVARIABLE maxcellars I L101 L74 13
    LOCALVARIABLE fb I L104 L74 14
    LOCALVARIABLE r F L115 L74 15
    LOCALVARIABLE conditionContext Lmcjty/lostcities/dimensions/world/lost/cityassets/ConditionContext; L130 L140 10
    LOCALVARIABLE randomPart Ljava/lang/String; L131 L140 11
    LOCALVARIABLE i I L127 L128 9
    LOCALVARIABLE this Lmcjty/lostcities/dimensions/world/lost/BuildingInfo; L0 L167 0
    LOCALVARIABLE chunkX I L0 L167 1
    LOCALVARIABLE chunkZ I L0 L167 2
    LOCALVARIABLE provider Lmcjty/lostcities/dimensions/world/LostCityChunkGenerator; L0 L167 3
    LOCALVARIABLE characteristics Lmcjty/lostcities/api/LostChunkCharacteristics; L31 L167 4
    LOCALVARIABLE rand Ljava/util/Random; L37 L167 5
    LOCALVARIABLE b Z L39 L167 6
    LOCALVARIABLE cs Lmcjty/lostcities/dimensions/world/lost/cityassets/CityStyle; L55 L167 7
    LOCALVARIABLE building Lmcjty/lostcities/dimensions/world/lost/cityassets/Building; L126 L167 8
    MAXSTACK = 14
    MAXLOCALS = 16

The Bytecode Outline containing our fix:

   L101
    LINENUMBER 764 L101
    ALOAD 0
    GETFIELD mcjty/lostcities/dimensions/world/lost/BuildingInfo.profile : Lmcjty/lostcities/config/LostCityProfile;
    GETFIELD mcjty/lostcities/config/LostCityProfile.BUILDING_MINCELLARS : I
    ALOAD 0
    INVOKEVIRTUAL mcjty/lostcities/dimensions/world/lost/BuildingInfo.getBuilding ()Lmcjty/lostcities/api/ILostCityBuilding
    INVOKEINTERFACE mcjty/lostcities/api/ILostCityBuilding.getMinCellars ()I
    INVOKESTATIC java/lang/Math.max (II)I
    ILOAD 13
    IFGT L102
    ICONST_0
    GOTO L103
   L102
   FRAME FULL [mcjty/lostcities/dimensions/world/lost/BuildingInfo I I mcjty/lostcities/dimensions/world/LostCityChunkGenerator mcjty/lostcities/api/LostChunkCharacteristics java/util/Random I mcjty/lostcities/dimensions/world/lost/cityassets/CityStyle mcjty/lostcities/dimensions/world/lost/cityassets/PredefinedCity$PredefinedBuilding F I I I I] [I]
    ALOAD 5
    ILOAD 13
   L104
    LINENUMBER 765 L104
    INVOKEVIRTUAL java/util/Random.nextInt (I)I
   L103
   FRAME FULL [mcjty/lostcities/dimensions/world/lost/BuildingInfo I I mcjty/lostcities/dimensions/world/LostCityChunkGenerator mcjty/lostcities/api/LostChunkCharacteristics java/util/Random I mcjty/lostcities/dimensions/world/lost/cityassets/CityStyle mcjty/lostcities/dimensions/world/lost/cityassets/PredefinedCity$PredefinedBuilding F I I I I] [I I]
    IADD
    ISTORE 14

...

L168
    LOCALVARIABLE topleft Lmcjty/lostcities/dimensions/world/lost/BuildingInfo; L58 L73 8
    LOCALVARIABLE reldest F L96 L94 13
    LOCALVARIABLE predefinedBuilding Lmcjty/lostcities/dimensions/world/lost/cityassets/PredefinedCity$PredefinedBuilding; L75 L74 8
    LOCALVARIABLE cityFactor F L85 L74 9
    LOCALVARIABLE maxfloors I L86 L74 10
    LOCALVARIABLE f I L87 L74 11
    LOCALVARIABLE minfloors I L91 L74 12
    LOCALVARIABLE maxcellars I L101 L74 13
    LOCALVARIABLE fb I L105 L74 14
    LOCALVARIABLE r F L116 L74 15
    LOCALVARIABLE conditionContext Lmcjty/lostcities/dimensions/world/lost/cityassets/ConditionContext; L131 L141 10
    LOCALVARIABLE randomPart Ljava/lang/String; L132 L141 11
    LOCALVARIABLE i I L128 L129 9
    LOCALVARIABLE this Lmcjty/lostcities/dimensions/world/lost/BuildingInfo; L0 L168 0
    LOCALVARIABLE chunkX I L0 L168 1
    LOCALVARIABLE chunkZ I L0 L168 2
    LOCALVARIABLE provider Lmcjty/lostcities/dimensions/world/LostCityChunkGenerator; L0 L168 3
    LOCALVARIABLE characteristics Lmcjty/lostcities/api/LostChunkCharacteristics; L31 L168 4
    LOCALVARIABLE rand Ljava/util/Random; L37 L168 5
    LOCALVARIABLE b Z L39 L168 6
    LOCALVARIABLE cs Lmcjty/lostcities/dimensions/world/lost/cityassets/CityStyle; L55 L168 7
    LOCALVARIABLE building Lmcjty/lostcities/dimensions/world/lost/cityassets/Building; L127 L168 8
    MAXSTACK = 14
    MAXLOCALS = 16

The Stacktrace we get:

net.minecraft.util.ReportedException: Exception generating new chunk
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:930) ~[WorldServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.loadAllWorlds(IntegratedServer.java:124) ~[IntegratedServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.init(IntegratedServer.java:160) ~[IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:552) [MinecraftServer.class:?]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_281]
Caused by: java.lang.NoClassDefFoundError: mcjty/lostcities/dimensions/world/lost/BuildingInfo
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more
Caused by: java.lang.ClassNotFoundException: mcjty.lostcities.dimensions.world.lost.BuildingInfo
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_281]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_281]
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more
Caused by: net.minecraftforge.fml.common.asm.ASMTransformerWrapper$TransformerException: Exception in class transformer com.seemdmax.lcpatches.LostCitiesClassTransformer@1bec3ef7 from coremod Lost Cities Patches
    at net.minecraftforge.fml.common.asm.ASMTransformerWrapper$TransformerWrapper.transform(ASMTransformerWrapper.java:260) ~[forgeSrc-1.12.2-14.23.5.2847.jar:?]
    at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_281]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_281]
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more
Caused by: java.lang.ClassCircularityError: mcjty/lostcities/dimensions/world/lost/BuildingInfo
    at com.seemdmax.lcpatches.LostCitiesClassTransformer.transformLCCellars(LostCitiesClassTransformer.java:100) ~[bin/:?]
    at com.seemdmax.lcpatches.LostCitiesClassTransformer.transform(LostCitiesClassTransformer.java:55) ~[bin/:?]
    at com.seemdmax.lcpatches.LostCitiesClassTransformer.transform(LostCitiesClassTransformer.java:39) ~[bin/:?]
    at net.minecraftforge.fml.common.asm.ASMTransformerWrapper$TransformerWrapper.transform(ASMTransformerWrapper.java:256) ~[forgeSrc-1.12.2-14.23.5.2847.jar:?]
    at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_281]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_281]
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more

What we tried: We tried to get the building using different ways, e.g. using GETFIELD. Error remain the same.

Any help would be appreciated. If you need to know more details, feel free to ask. Thanks in advance.

Edit: After hardcoding the String, I got another Stacktrace. Is this still related to me doing something wrong with ASM?

net.minecraft.util.ReportedException: Exception generating new chunk
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:930) ~[WorldServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.loadAllWorlds(IntegratedServer.java:124) ~[IntegratedServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.init(IntegratedServer.java:160) ~[IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:552) [MinecraftServer.class:?]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_281]
Caused by: java.lang.NoClassDefFoundError: mcjty/lostcities/dimensions/world/lost/BuildingInfo
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more
Caused by: java.lang.ClassNotFoundException: mcjty.lostcities.dimensions.world.lost.BuildingInfo
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_281]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_281]
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: 41
    at org.objectweb.asm.Type.getType(Type.java:490) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.Type.getReturnType(Type.java:384) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.commons.Remapper.mapMethodDesc(Remapper.java:125) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.commons.RemappingMethodAdapter.doVisitMethodInsn(RemappingMethodAdapter.java:157) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.commons.RemappingMethodAdapter.visitMethodInsn(RemappingMethodAdapter.java:143) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.ClassReader.readCode(ClassReader.java:1496) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1032) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.ClassReader.accept(ClassReader.java:708) ~[asm-debug-all-5.2.jar:5.2]
    at org.objectweb.asm.ClassReader.accept(ClassReader.java:521) ~[asm-debug-all-5.2.jar:5.2]
    at net.minecraftforge.fml.common.asm.transformers.DeobfuscationTransformer.transform(DeobfuscationTransformer.java:76) ~[forgeSrc-1.12.2-14.23.5.2847.jar:?]
    at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279) ~[launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176) ~[launchwrapper-1.12.jar:?]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_281]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_281]
    at mcjty.lostcities.dimensions.world.LostCityChunkGenerator.generateChunk(LostCityChunkGenerator.java:216) ~[LostCityChunkGenerator.class:?]
    at net.minecraft.world.gen.ChunkProviderServer.provideChunk(ChunkProviderServer.java:155) ~[ChunkProviderServer.class:?]
    at net.minecraft.world.World.getChunkFromChunkCoords(World.java:362) ~[World.class:?]
    at net.minecraft.world.World.getChunkFromBlockCoords(World.java:354) ~[World.class:?]
    at net.minecraft.world.World.getBlockState(World.java:995) ~[World.class:?]
    at net.minecraft.world.World.isAirBlock(World.java:279) ~[World.class:?]
    at net.minecraft.world.World.getGroundAboveSeaLevel(World.java:252) ~[World.class:?]
    at net.minecraft.world.WorldProvider.canCoordinateBeSpawn(WorldProvider.java:102) ~[WorldProvider.class:?]
    at net.minecraft.world.WorldServer.createSpawnPosition(WorldServer.java:989) ~[WorldServer.class:?]
    at net.minecraft.world.WorldServer.initialize(WorldServer.java:908) ~[WorldServer.class:?]
    ... 4 more

Answer

The problem is that you do Type.getInternalName(BuildingInfo.class). That’s the very class you’re trying to transform as it’s being loaded, so you created a circular reference by using it in a way that would need it to be loaded. You’ll need to hardcode the string "mcjty/lostcities/dimensions/world/lost/BuildingInfo" there instead.

Also, in "()Lmcjty/lostcities/api/ILostCityBuilding", that’s supposed to have a semicolon at the end, so change it to "()Lmcjty/lostcities/api/ILostCityBuilding;".

Finally, you need to change false to true in new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ILostCityBuilding.class), "getMinCellars", "()I", false));, since it is in fact an interface method.