diff --git a/src/main/java/com/falsepattern/endlessids/IEPlugin.java b/src/main/java/com/falsepattern/endlessids/IEPlugin.java index 767822e..392fe90 100644 --- a/src/main/java/com/falsepattern/endlessids/IEPlugin.java +++ b/src/main/java/com/falsepattern/endlessids/IEPlugin.java @@ -15,12 +15,14 @@ import java.util.Set; import static cpw.mods.fml.relauncher.IFMLLoadingPlugin.DependsOn; import static cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import static cpw.mods.fml.relauncher.IFMLLoadingPlugin.Name; +import static cpw.mods.fml.relauncher.IFMLLoadingPlugin.SortingIndex; import static cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; @MCVersion("1.7.10") @Name(Tags.MODID) @TransformerExclusions({"com.falsepattern.endlessids.asm"}) @DependsOn("falsepatternlib") +@SortingIndex(1001) public class IEPlugin implements IFMLLoadingPlugin { static { try { diff --git a/src/main/java/com/falsepattern/endlessids/asm/ClassEdit.java b/src/main/java/com/falsepattern/endlessids/asm/ClassEdit.java index f115ddb..977c5a5 100644 --- a/src/main/java/com/falsepattern/endlessids/asm/ClassEdit.java +++ b/src/main/java/com/falsepattern/endlessids/asm/ClassEdit.java @@ -1,5 +1,6 @@ package com.falsepattern.endlessids.asm; +import com.falsepattern.endlessids.asm.transformer.ChunkProviderSuperPatcher; import com.falsepattern.endlessids.asm.transformer.DragonAPIModList; import com.falsepattern.endlessids.asm.transformer.FmlRegistry; @@ -9,6 +10,7 @@ import java.util.Map; public enum ClassEdit { FmlRegistry(new FmlRegistry(), new String[]{"cpw.mods.fml.common.registry.GameData", "cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry"}), + ChunkProviderSuperPatcher(new ChunkProviderSuperPatcher(), new String[0]), DragonAPIModList(new DragonAPIModList(), new String[]{"Reika.DragonAPI.ModList"}); private static final Map editMap; diff --git a/src/main/java/com/falsepattern/endlessids/asm/IETransformer.java b/src/main/java/com/falsepattern/endlessids/asm/IETransformer.java index 2acf153..3014ce0 100644 --- a/src/main/java/com/falsepattern/endlessids/asm/IETransformer.java +++ b/src/main/java/com/falsepattern/endlessids/asm/IETransformer.java @@ -1,16 +1,20 @@ package com.falsepattern.endlessids.asm; import com.falsepattern.endlessids.Tags; +import com.falsepattern.endlessids.asm.transformer.ChunkProviderSuperPatcher; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.util.CheckClassAdapter; import net.minecraft.launchwrapper.IClassTransformer; +import java.util.Arrays; + public class IETransformer implements IClassTransformer { public static final Logger logger; public static boolean isObfuscated; @@ -27,14 +31,18 @@ public class IETransformer implements IClassTransformer { if (bytes == null) { return bytes; } - final ClassEdit edit = ClassEdit.get(transformedName); + ClassEdit edit = ClassEdit.get(transformedName); + final ClassNode cn = new ClassNode(Opcodes.ASM5); + final ClassReader reader = new ClassReader(bytes); + reader.accept(cn, edit == null ? ClassReader.EXPAND_FRAMES : 0); if (edit == null) { - return bytes; + if (cn.interfaces.contains("net/minecraft/world/chunk/IChunkProvider")) { + edit = ClassEdit.ChunkProviderSuperPatcher; + } else { + return bytes; + } } IETransformer.logger.debug("Patching {} with {}...", transformedName, edit.getName()); - final ClassNode cn = new ClassNode(327680); - final ClassReader reader = new ClassReader(bytes); - reader.accept(cn, 0); try { edit.getTransformer().transform(cn, IETransformer.isObfuscated); } catch (AsmTransformException t) { @@ -46,7 +54,7 @@ public class IETransformer implements IClassTransformer { t2.getMessage()); throw new RuntimeException(t2); } - final ClassWriter writer = new ClassWriter(0); + final ClassWriter writer = new ClassWriter(edit == ClassEdit.ChunkProviderSuperPatcher ? ClassWriter.COMPUTE_FRAMES : 0); try { final ClassVisitor check = new CheckClassAdapter(writer); cn.accept(check); @@ -55,7 +63,7 @@ public class IETransformer implements IClassTransformer { t3.getMessage()); throw new RuntimeException(t3); } - IETransformer.logger.debug("Patched {} successfully.", edit.getName()); + IETransformer.logger.debug("Patched {} successfully.", transformedName); return writer.toByteArray(); } } diff --git a/src/main/java/com/falsepattern/endlessids/asm/transformer/ChunkProviderSuperPatcher.java b/src/main/java/com/falsepattern/endlessids/asm/transformer/ChunkProviderSuperPatcher.java new file mode 100644 index 0000000..fcbc4bf --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/asm/transformer/ChunkProviderSuperPatcher.java @@ -0,0 +1,339 @@ +package com.falsepattern.endlessids.asm.transformer; + +import com.falsepattern.endlessids.asm.IClassNodeTransformer; +import com.falsepattern.endlessids.asm.IETransformer; +import lombok.Data; +import lombok.val; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.FrameNode; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * This class is the bread and butter of the patching logic from now on. It covers about 90% of cases where manual patching + * was required, and so with a heavy heart, I (finally) implemented a universal patch. + * + * See the end of the file for the 2 possibilities that this transformer handles. + */ +public class ChunkProviderSuperPatcher implements IClassNodeTransformer { + private static final String BIOME_GEN_BASE_CLASS = "net/minecraft/world/biome/BiomeGenBase"; + private static final String CHUNK_CLASS = "net/minecraft/world/chunk/Chunk"; + private static final String BIOME_ID_FIELD = IETransformer.isObfuscated ? "field_76756_M" : "biomeID"; + private static final String GET_BIOME_ARRAY_METHOD = IETransformer.isObfuscated ? "func_76605_m" : "getBiomeArray"; + private static final Map> STATES = new HashMap<>(); + static { + STATES.put(0, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ALOAD) { + memory.chunkIndex = insn.var; + memory.startingInsn = memory.currentInsn; + return 1; + } + return 0; + })); + STATES.put(1, casting(MethodInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.INVOKEVIRTUAL && + insn.owner.equals(CHUNK_CLASS) && + insn.name.equals(GET_BIOME_ARRAY_METHOD) && + insn.desc.equals("()[B")) { + memory.getBiomeArrayInsn = memory.currentInsn; + return 2; + } + return 0; + })); + STATES.put(2, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ASTORE) { + memory.biomeArrayIndex = insn.var; + return 3; + } + return 0; + })); + STATES.put(3, casting(LabelNode.class, 0, 4)); + STATES.put(4, casting(InsnNode.class, 0, (insn) -> insn.getOpcode() == Opcodes.ICONST_0 ? 5 : 0)); + STATES.put(5, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ISTORE) { + memory.iteratorIndex = insn.var; + return 6; + } + return 0; + })); + STATES.put(6, casting(LabelNode.class, 0, 7)); + STATES.put(7, casting(FrameNode.class, 0, (insn, memory) -> { + //validate chunk, chunk array, and iterator + if (memory.locals.get(memory.chunkIndex).equals(CHUNK_CLASS) && + memory.locals.get(memory.biomeArrayIndex).equals("[B") && + memory.locals.get(memory.iteratorIndex).equals(1)) { + return 8; + } + return 0; + })); + STATES.put(8, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ILOAD && + insn.var == memory.iteratorIndex) { + memory.tmp = 1; + return 9; + } else if (insn.getOpcode() == Opcodes.ALOAD && + insn.var == memory.biomeArrayIndex) { + memory.tmp = 2; + return 10; + } + memory.tmp = 0; + return 0; + })); + STATES.put(9, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (memory.tmp == 1) { + if (insn.getOpcode() == Opcodes.ALOAD && + insn.var == memory.biomeArrayIndex) { + return 10; + } + } else if (memory.tmp == 2) { + if (insn.getOpcode() == Opcodes.ILOAD && + insn.var == memory.iteratorIndex) { + return 11; + } + } + memory.tmp = 0; + return 0; + })); + STATES.put(10, casting(InsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ARRAYLENGTH) { + if (memory.tmp == 1) { + return 11; + } else if (memory.tmp == 2) { + return 9; + } + } + memory.tmp = 0; + return 0; + })); + STATES.put(11, casting(JumpInsnNode.class, 0, (insn, memory) -> { + if ((memory.tmp == 1 && insn.getOpcode() == Opcodes.IF_ICMPGE) || + (memory.tmp == 2 && insn.getOpcode() == Opcodes.IF_ICMPLE)) { + memory.tmp = 0; + return 12; + } + memory.tmp = 0; + return 0; + })); + STATES.put(12, casting(LabelNode.class, 0, 13)); + STATES.put(13, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ALOAD && + insn.var == memory.biomeArrayIndex) { + return 14; + } + return 0; + })); + STATES.put(14, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ILOAD && + insn.var == memory.iteratorIndex) { + return 15; + } + return 0; + })); + STATES.put(15, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ALOAD) { + if (insn.var == 0) { + memory.altFlags = 1; + return 16; + } else if (memory.locals.get(insn.var).equals("[L" + BIOME_GEN_BASE_CLASS + ";")) { + memory.altFlags = 0; + memory.biomesForGenerationIndex = insn.var; + return 17; + } + } + return 0; + })); + STATES.put(16, casting(FieldInsnNode.class, 0, (insn, memory) -> { + if ((insn.getOpcode() == Opcodes.GETFIELD || insn.getOpcode() == Opcodes.GETSTATIC) && + insn.desc.equals("[L" + BIOME_GEN_BASE_CLASS + ";")) { + memory.biomesForGenerationFieldOwner = insn.owner; + memory.biomesForGenerationFieldName = insn.name; + return 17; + } + return 0; + })); + STATES.put(17, casting(VarInsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.ILOAD && + insn.var == memory.iteratorIndex) { + return 18; + } + return 0; + })); + STATES.put(18, casting(InsnNode.class, 0, (insn) -> insn.getOpcode() == Opcodes.AALOAD ? 19 : 0)); + STATES.put(19, casting(FieldInsnNode.class, 0, (insn) -> { + if (insn.getOpcode() == Opcodes.GETFIELD && + insn.owner.equals(BIOME_GEN_BASE_CLASS) && + insn.name.equals(BIOME_ID_FIELD) && + insn.desc.equals("I")) { + return 20; + } + return 0; + })); + STATES.put(20, casting(InsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.I2B) { + memory.castInsn = memory.currentInsn; + return 21; + } + return 0; + })); + STATES.put(21, casting(InsnNode.class, 0, (insn, memory) -> { + if (insn.getOpcode() == Opcodes.BASTORE) { + memory.arrayStoreInsn = memory.currentInsn; + return -2; + } + return 0; + })); + } + private static BiFunction casting(Class clazz, int failState, int okState) { + return casting(clazz, failState, (insn, memory) -> okState); + } + + private static BiFunction casting(Class clazz, int failState, Function okCode) { + return casting(clazz, failState, (insn, memory) -> okCode.apply(insn)); + } + + private static BiFunction casting(Class clazz, int failState, BiFunction okCode) { + return (insn, memory) -> { + if (insn instanceof LineNumberNode) { + return -1; + } else if (clazz.isInstance(insn)) { + return okCode.apply(clazz.cast(insn), memory); + } else { + return failState; + } + }; + } + + @Override + public void transform(final ClassNode cn, final boolean obfuscated) { + for (val method: cn.methods) { + val memory = findTheTarget(method); + if (memory != null) { + val insnList = method.instructions; + for (val node: method.localVariables) { + if (node.desc.equals("[B") && node.index == memory.biomeArrayIndex) { + node.desc = "[S"; + } + } + insnList.set(insnList.get(memory.getBiomeArrayInsn), new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/world/chunk/Chunk", "getBiomeShortArray", "()[S", false)); + insnList.set(insnList.get(memory.castInsn), new InsnNode(Opcodes.I2S)); + insnList.set(insnList.get(memory.arrayStoreInsn), new InsnNode(Opcodes.SASTORE)); + } + } + } + + + private static Memory findTheTarget(MethodNode method) { + val insnList = method.instructions; + int state = 0; + val memory = new Memory(); + for (int insnIndex = 0; insnIndex < insnList.size(); insnIndex++) { + memory.currentInsn = insnIndex; + val insn = insnList.get(insnIndex); + if (insn instanceof FrameNode) { + val frame = (FrameNode) insn; + switch (frame.type) { + case Opcodes.F_NEW: + memory.locals.clear(); + memory.locals.addAll(frame.local); + break; + } + } + val newState = STATES.get(state).apply(insn, memory); + switch (newState) { + case -1: + continue; + case -2: + return memory; + default: + state = newState; + } + } + return null; + } + + @Data + private static class Memory { + int currentInsn; + + int startingInsn; + int getBiomeArrayInsn; + int castInsn; + int arrayStoreInsn; + + int chunkIndex; + int biomeArrayIndex; + int iteratorIndex; + + long altFlags; + String biomesForGenerationFieldOwner; + String biomesForGenerationFieldName; + int biomesForGenerationIndex; + + int tmp; + + final List locals = new ArrayList<>(); + } +} +/* + Java form: + ... + byte[] abyte = chunk.getBiomeArray(); //replace byte[] with short[] and getBiomeArray with getBiomeShortArray + + for (int k = 0; k < abyte.length; ++k) { + //Possibility A: + abyte[k] = (byte)abiomegenbase[k].biomeID; //from local variable //replace byte cast with short cast + + //Possibility B: + abyte[k] = (byte)this.biomesToGenerate[k].biomeID; //from arbitrary field //replace byte cast with short cast + } + ... + In ASM form: + + L1 + ALOAD chunk + INVOKEVIRTUAL net/minecraft/world/chunk/Chunk.getBiomeArray ()[B //Replace with INVOKEVIRTUAL net/minecraft/world/chunk/Chunk.getBiomeShortArray ()[S + ASTORE abyte + L2 + ICONST_0 + ISTORE k + L3 + FRAME + ILOAD k + ALOAD abyte + ARRAYLENGTH + IF_ICMPGE L6 + L4 + ALOAD abyte + ILOAD k + + //Possibility A: + ALOAD abiomegenbase + //Possibility B: + ALOAD + GETFIELD classname.fieldname : [Lnet/minecraft/world/biome/BiomeGenBase; + + ILOAD k + AALOAD + GETFIELD net/minecraft/world/biome/BiomeGenBase.biomeID : I + I2B //Replace with I2S + BASTORE //Replace with SASTORE + L5 + IINC 8 1 + GOTO L3 + L6 + */ \ No newline at end of file diff --git a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java index e4d33f3..3ad3c0e 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java @@ -43,10 +43,10 @@ public enum Mixin implements IMixin { WorldMixin(Side.COMMON, always(), "vanilla.misc.WorldMixin"), //endregion Minecraft->common->misc //region Minecraft->common->worldgen - ChunkProviderEndMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderEndMixin"), - ChunkProviderFlatMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderFlatMixin"), - ChunkProviderGenerateMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderGenerateMixin"), - ChunkProviderHellMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderHellMixin"), +// ChunkProviderEndMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderEndMixin"), +// ChunkProviderFlatMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderFlatMixin"), +// ChunkProviderGenerateMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderGenerateMixin"), +// ChunkProviderHellMixin(Side.COMMON, always(), "vanilla.worldgen.ChunkProviderHellMixin"), GenLayerRiverMixMixin(Side.COMMON, avoid(TargetedMod.DRAGONAPI), "vanilla.worldgen.GenLayerRiverMixMixin"), GenLayerVoronoiZoomMixin(Side.COMMON, always(), "vanilla.worldgen.GenLayerVoronoiZoomMixin"), //endregion Minecraft->common->worldgen @@ -60,17 +60,17 @@ public enum Mixin implements IMixin { //endregion Minecraft //region AbyssalCraft->common AbyssalCraftMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), "abyssalcraft.AbyssalCraftMixin"), - ChunkProviderAbyssMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), "abyssalcraft.ChunkProviderAbyssMixin"), - ChunkProviderDarkRealmMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), - "abyssalcraft.ChunkProviderDarkRealmMixin"), - ChunkProviderDreadlandsMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), - "abyssalcraft.ChunkProviderDreadlandsMixin"), - ChunkProviderOmotholMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), "abyssalcraft.ChunkProviderOmotholMixin"), +// ChunkProviderAbyssMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), "abyssalcraft.ChunkProviderAbyssMixin"), +// ChunkProviderDarkRealmMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), +// "abyssalcraft.ChunkProviderDarkRealmMixin"), +// ChunkProviderDreadlandsMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), +// "abyssalcraft.ChunkProviderDreadlandsMixin"), +// ChunkProviderOmotholMixin(Side.COMMON, require(TargetedMod.ABYSSALCRAFT), "abyssalcraft.ChunkProviderOmotholMixin"), //endregion AbyssalCraft->common //region ATG->common ATGBiomeConfigMixin(Side.COMMON, require(TargetedMod.ATG), "atg.ATGBiomeConfigMixin"), ATGBiomeManagerMixin(Side.COMMON, require(TargetedMod.ATG), "atg.ATGBiomeManagerMixin"), - ATGChunkProviderMixin(Side.COMMON, require(TargetedMod.ATG), "atg.ATGChunkProviderMixin"), +// ATGChunkProviderMixin(Side.COMMON, require(TargetedMod.ATG), "atg.ATGChunkProviderMixin"), ATGWorldGenRocksMixin(Side.COMMON, require(TargetedMod.ATG), "atg.ATGWorldGenRocksMixin"), //endregion ATG->common //region AntiqueAtlas->commond @@ -91,12 +91,12 @@ public enum Mixin implements IMixin { AIDCPotionsManagerMixin(Side.COMMON, require(TargetedMod.ANTIIDCONFLICT), "antiidconflict.PotionsManagerMixin"), //endregion AntiIDConflict->common //region Atum->common - AtumChunkProviderMixin(Side.COMMON, require(TargetedMod.ATUM), "atum.AtumChunkProviderMixin"), +// AtumChunkProviderMixin(Side.COMMON, require(TargetedMod.ATUM), "atum.AtumChunkProviderMixin"), //endregion Atum->common //region BoP->common BOPBiomeManagerMixin(Side.COMMON, require(TargetedMod.BOP), "bop.BOPBiomeManagerMixin"), - ChunkProviderBOPEndMixin(Side.COMMON, require(TargetedMod.BOP), "bop.ChunkProviderBOPEndMixin"), - ChunkProviderBOPHellMixin(Side.COMMON, require(TargetedMod.BOP), "bop.ChunkProviderBOPHellMixin"), +// ChunkProviderBOPEndMixin(Side.COMMON, require(TargetedMod.BOP), "bop.ChunkProviderBOPEndMixin"), +// ChunkProviderBOPHellMixin(Side.COMMON, require(TargetedMod.BOP), "bop.ChunkProviderBOPHellMixin"), //endregion BoP->common //region BiomeTweaker->common BiomeEventHandlerMixin(Side.COMMON, require(TargetedMod.BIOMETWEAKER), "biometweaker.BiomeEventHandlerMixin"), @@ -113,10 +113,10 @@ public enum Mixin implements IMixin { CoFHLibCofhBlockHelperMixin(Side.COMMON, require(TargetedMod.COFHLIB), "cofhlib.BlockHelperMixin"), //endregion CoFHLib->common //region DarkWorld->common - ChunkProviderDarkWorldAlphaMixin(Side.COMMON, require(TargetedMod.DARKWORLD), - "darkworld.ChunkProviderDarkWorldAlphaMixin"), - ChunkProviderDarkWorldBetaMixin(Side.COMMON, require(TargetedMod.DARKWORLD), - "darkworld.ChunkProviderDarkWorldBetaMixin"), +// ChunkProviderDarkWorldAlphaMixin(Side.COMMON, require(TargetedMod.DARKWORLD), +// "darkworld.ChunkProviderDarkWorldAlphaMixin"), +// ChunkProviderDarkWorldBetaMixin(Side.COMMON, require(TargetedMod.DARKWORLD), +// "darkworld.ChunkProviderDarkWorldBetaMixin"), DarkWorldModBiomesMixin(Side.COMMON, require(TargetedMod.DARKWORLD), "darkworld.ModBiomesMixin"), //endregion DarkWorld->common //region DragonAPI->common @@ -129,22 +129,22 @@ public enum Mixin implements IMixin { DragonAPIIDTypeMixin(Side.COMMON, require(TargetedMod.DRAGONAPI), "dragonapi.IDTypeMixin"), //endregion DragonAPI->common //region Erebus->common - ChunkProviderErebusMixin(Side.COMMON, require(TargetedMod.EREBUS), "erebus.ChunkProviderErebusMixin"), +// ChunkProviderErebusMixin(Side.COMMON, require(TargetedMod.EREBUS), "erebus.ChunkProviderErebusMixin"), ErebusModBiomesMixin(Side.COMMON, require(TargetedMod.EREBUS), "erebus.ModBiomesMixin"), //endregion Erebus->common //region ExtraUtilities->common ChunkProviderEndOfTimeMixin(Side.COMMON, require(TargetedMod.EXTRAUTILITIES), "extrautilities.ChunkProviderEndOfTimeMixin"), - ChunkProviderUnderdarkMixin(Side.COMMON, require(TargetedMod.EXTRAUTILITIES), "extrautilities.ChunkProviderUnderdarkMixin"), +// ChunkProviderUnderdarkMixin(Side.COMMON, require(TargetedMod.EXTRAUTILITIES), "extrautilities.ChunkProviderUnderdarkMixin"), //endregion ExtraUtilities->common //region Futurepack->common - FuturepackChunkProviderSpaceMixin(Side.COMMON, require(TargetedMod.FUTUREPACK), "futurepack.ChunkProviderSpaceMixin"), +// FuturepackChunkProviderSpaceMixin(Side.COMMON, require(TargetedMod.FUTUREPACK), "futurepack.ChunkProviderSpaceMixin"), FuturepackBiomeGenSpaceMixin(Side.COMMON, require(TargetedMod.FUTUREPACK), "futurepack.BiomeGenSpaceMixin"), //endregion Futurepack->common //region GalactiCraftCore->common GalactiCraftChunkProviderOrbitMixin(Side.COMMON, require(TargetedMod.GALACTICRAFTCORE), "galacticraft.ChunkProviderOrbitMixin"), - GalactiCraftChunkProviderSpaceMixin(Side.COMMON, require(TargetedMod.GALACTICRAFTCORE), - "galacticraft.ChunkProviderSpaceMixin"), +// GalactiCraftChunkProviderSpaceMixin(Side.COMMON, require(TargetedMod.GALACTICRAFTCORE), +// "galacticraft.ChunkProviderSpaceMixin"), GalactiCraftConfigManagerCoreMixin(Side.COMMON, require(TargetedMod.GALACTICRAFTCORE), "galacticraft.ConfigManagerCoreMixin"), //endregion GalactiCraftCore->common @@ -162,8 +162,8 @@ public enum Mixin implements IMixin { //region Netherlicious->common NetherliciousBiomeConfigurationMixin(Side.COMMON, require(TargetedMod.NETHERLICIOUS), "netherlicious.BiomeConfigurationMixin"), - NetherliciousNetherChunkProviderMixin(Side.COMMON, require(TargetedMod.NETHERLICIOUS), - "netherlicious.NetherChunkProviderMixin"), +// NetherliciousNetherChunkProviderMixin(Side.COMMON, require(TargetedMod.NETHERLICIOUS), +// "netherlicious.NetherChunkProviderMixin"), //endregion Netherlicious->common //region RTG->common RTGChunkProviderRTGMixin(Side.COMMON, require(TargetedMod.RTG), "rtg.ChunkProviderRTGMixin"), @@ -174,14 +174,14 @@ public enum Mixin implements IMixin { ThaumcraftUtilsMixin(Side.COMMON, require(TargetedMod.THAUMCRAFT), "thaumcraft.UtilsMixin"), //endregion Thaumcraft->common //region Tropicraft->common - ChunkProviderTropicraftMixin(Side.COMMON, require(TargetedMod.TROPICRAFT), - "tropicraft.ChunkProviderTropicraftMixin"), +// ChunkProviderTropicraftMixin(Side.COMMON, require(TargetedMod.TROPICRAFT), +// "tropicraft.ChunkProviderTropicraftMixin"), GenLayerTropiVoronoiZoomMixin(Side.COMMON, require(TargetedMod.TROPICRAFT), "tropicraft.GenLayerTropiVoronoiZoomMixin"), //endregion Tropicraft->common //region TwilightForest->common - ChunkProviderTwilightForestMixin(Side.COMMON, require(TargetedMod.TWILIGHTFOREST), - "twilightforest.ChunkProviderTwilightForestMixin"), +// ChunkProviderTwilightForestMixin(Side.COMMON, require(TargetedMod.TWILIGHTFOREST), +// "twilightforest.ChunkProviderTwilightForestMixin"), TFBiomeBaseMixin(Side.COMMON, require(TargetedMod.TWILIGHTFOREST), "twilightforest.TFBiomeBaseMixin"), //endregion TwilightForest->common //region UBC->common