diff --git a/build.gradle b/build.gradle index 1d63c9e..0140027 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ repositories { } dependencies { - implementation("org.dimdev:mixin:0.7.11-SNAPSHOT") { + implementation("org.spongepowered:mixin:0.8") { exclude module: "asm-commons" exclude module: "asm-tree" exclude module: "launchwrapper" diff --git a/src/main/java/org/dimdev/jeid/mixin/core/MixinChunk.java b/src/main/java/org/dimdev/jeid/mixin/core/MixinChunk.java index eaead83..31c83ac 100644 --- a/src/main/java/org/dimdev/jeid/mixin/core/MixinChunk.java +++ b/src/main/java/org/dimdev/jeid/mixin/core/MixinChunk.java @@ -1,22 +1,26 @@ package org.dimdev.jeid.mixin.core; +import net.minecraft.init.Biomes; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeProvider; import net.minecraft.world.chunk.Chunk; import org.dimdev.jeid.INewChunk; import org.dimdev.jeid.JEID; -import org.dimdev.jeid.Utils; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.injection.*; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.spongepowered.asm.mixin.Shadow; import java.util.Arrays; @Mixin(Chunk.class) public class MixinChunk implements INewChunk { + + + @Shadow @Final private World world; + private static final byte errorBiomeID = (byte) Biome.REGISTRY.getIDForObject(JEID.errorBiome); private final int[] intBiomeArray = generateIntBiomeArray(); @@ -36,6 +40,9 @@ public void setIntBiomeArray(int[] intBiomeArray) { System.arraycopy(intBiomeArray, 0, this.intBiomeArray, 0, this.intBiomeArray.length); } + /** + * @author Unknown + */ @Overwrite public byte[] getBiomeArray() { byte[] arr = new byte[256]; @@ -43,18 +50,35 @@ public byte[] getBiomeArray() { return arr; } - @Redirect(method = "getBiome", at = @At(value = "FIELD", target = "Lnet/minecraft/world/chunk/Chunk;blockBiomeArray:[B", args = "array=get")) - private int getIntBiomeIdFromArray(byte[] array, int index) { - return this.intBiomeArray[index]; - } + /** + * @author Clienthax + * @reason No way to modify locals in the manner we need currently.. + */ + @Overwrite + public Biome getBiome(BlockPos pos, BiomeProvider provider) + { + int i = pos.getX() & 15; + int j = pos.getZ() & 15; + //JEID START + int k = this.intBiomeArray[j << 4 | i]; + //JEID END - @Inject(method = "getBiome", at = @At(value = "FIELD", target = "Lnet/minecraft/world/chunk/Chunk;blockBiomeArray:[B", args = "array=set"), locals = LocalCapture.CAPTURE_FAILHARD) - private void setIntBiomeIdInArray(BlockPos pos, BiomeProvider provider, CallbackInfoReturnable cir, int i, int j, int k, Biome biome) { - this.intBiomeArray[j << 4 | i] = k; - } + if (k == 255) + { + // Forge: checking for client ensures that biomes are only generated on integrated server + // in singleplayer. Generating biomes on the client may corrupt the biome ID arrays on + // the server while they are being generated because IntCache can't be thread safe, + // so client and server may end up filling the same array. + // This is not necessary in 1.13 and newer versions. + Biome biome = world.isRemote ? Biomes.PLAINS : provider.getBiome(pos, Biomes.PLAINS); + k = Biome.getIdForBiome(biome); + //JEID START + this.intBiomeArray[j << 4 | i] = k; + //JEID END + } - @ModifyConstant(method = "getBiome", constant = @Constant(intValue = 0xFF)) - private int getBiomeBitmask(int oldValue) { - return 0xFFFFFFFF; + Biome biome1 = Biome.getBiome(k); + return biome1 == null ? Biomes.PLAINS : biome1; } + } diff --git a/src/main/java/org/dimdev/jeid/mixin/init/MixinLoader.java b/src/main/java/org/dimdev/jeid/mixin/init/MixinLoader.java index 45e04f0..180205c 100644 --- a/src/main/java/org/dimdev/jeid/mixin/init/MixinLoader.java +++ b/src/main/java/org/dimdev/jeid/mixin/init/MixinLoader.java @@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.transformer.MixinTransformer; +import org.spongepowered.asm.mixin.transformer.MixinProcessor; import org.spongepowered.asm.mixin.transformer.Proxy; import java.lang.reflect.Field; @@ -45,17 +45,25 @@ private void beforeConstructingMods(List injectedModContainers, Callback Proxy mixinProxy = (Proxy) Launch.classLoader.getTransformers().stream().filter(transformer -> transformer instanceof Proxy).findFirst().get(); try { + //This will very likely break on the next major mixin release. + Class mixinTransformerClass = Class.forName("org.spongepowered.asm.mixin.transformer.MixinTransformer"); + Field transformerField = Proxy.class.getDeclaredField("transformer"); transformerField.setAccessible(true); - MixinTransformer transformer = (MixinTransformer) transformerField.get(mixinProxy); + Object transformer = transformerField.get(mixinProxy); + + //Get MixinProcessor from MixinTransformer + Field processorField = mixinTransformerClass.getDeclaredField("processor"); + processorField.setAccessible(true); + Object processor = processorField.get(transformer); - Method selectConfigsMethod = MixinTransformer.class.getDeclaredMethod("selectConfigs", MixinEnvironment.class); + Method selectConfigsMethod = MixinProcessor.class.getDeclaredMethod("selectConfigs", MixinEnvironment.class); selectConfigsMethod.setAccessible(true); - selectConfigsMethod.invoke(transformer, MixinEnvironment.getCurrentEnvironment()); + selectConfigsMethod.invoke(processor, MixinEnvironment.getCurrentEnvironment()); - Method prepareConfigsMethod = MixinTransformer.class.getDeclaredMethod("prepareConfigs", MixinEnvironment.class); + Method prepareConfigsMethod = MixinProcessor.class.getDeclaredMethod("prepareConfigs", MixinEnvironment.class); prepareConfigsMethod.setAccessible(true); - prepareConfigsMethod.invoke(transformer, MixinEnvironment.getCurrentEnvironment()); + prepareConfigsMethod.invoke(processor, MixinEnvironment.getCurrentEnvironment()); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } diff --git a/src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/TwilightMixinPlugin.java b/src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/TwilightMixinPlugin.java index 2f39e2d..f8fc946 100644 --- a/src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/TwilightMixinPlugin.java +++ b/src/main/java/org/dimdev/jeid/mixin/modsupport/twilightforest/TwilightMixinPlugin.java @@ -3,7 +3,7 @@ import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModContainer; import org.dimdev.jeid.Utils; -import org.spongepowered.asm.lib.tree.ClassNode; +import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -55,12 +55,12 @@ public List getMixins() { } @Override - public void preApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) { + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } @Override - public void postApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) { + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } }