diff --git a/src/main/java/com/falsepattern/endlessids/Hooks.java b/src/main/java/com/falsepattern/endlessids/Hooks.java index 78f0687..15b5bc2 100644 --- a/src/main/java/com/falsepattern/endlessids/Hooks.java +++ b/src/main/java/com/falsepattern/endlessids/Hooks.java @@ -5,26 +5,74 @@ import com.falsepattern.endlessids.constants.ExtendedConstants; import com.falsepattern.endlessids.mixin.helpers.IChunkMixin; import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin; import lombok.val; +import lombok.var; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.NibbleArray; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; public class Hooks { - public static void getBlockData(final IExtendedBlockStorageMixin ebs, final byte[] data, final int offset) { - val lsb = ebs.getLSB(); - val msb = ebs.getMSB(); - Unsafer.arraycopy(lsb, 0, data, offset, lsb.length); - System.arraycopy(msb, 0, data, offset + lsb.length * 2, msb.length); + public static int getBlockData(final IExtendedBlockStorageMixin ebs, final byte[] data, int offset) { + val b1 = ebs.getB1(); + System.arraycopy(b1, 0, data, offset, b1.length); + offset += b1.length; + val b2Low = ebs.getB2Low(); + if (b2Low != null) { + System.arraycopy(b2Low.data, 0, data, offset, b2Low.data.length); + offset += b2Low.data.length; + val b2High = ebs.getB2High(); + if (b2High != null) { + System.arraycopy(b2High.data, 0, data, offset, b2High.data.length); + offset += b2High.data.length; + val b3 = ebs.getB3(); + if (b3 != null) { + System.arraycopy(b3, 0, data, offset, b3.length); + } + } + } + return ebs.getStorageFlag(); } - public static void setBlockData(final IExtendedBlockStorageMixin ebs, final byte[] data, final int offset) { - val lsb = ebs.getLSB(); - val msb = ebs.getMSB(); - Unsafer.arraycopy(data, offset, lsb, 0, lsb.length); - System.arraycopy(data, offset + lsb.length * 2, msb, 0, msb.length); + public static void setBlockData(final IExtendedBlockStorageMixin ebs, final byte[] data, int offset, final int storageFlag) { + val b1 = ebs.getB1(); + System.arraycopy(data, offset, b1, 0, b1.length); + offset += b1.length; + if (storageFlag == 0b00) { + ebs.clearB2Low(); + ebs.clearB2High(); + ebs.clearB3(); + return; + } + var b2Low = ebs.getB2Low(); + if (b2Low == null) { + b2Low = ebs.createB2Low(); + } + System.arraycopy(data, offset, b2Low.data, 0, b2Low.data.length); + offset += b2Low.data.length; + if (storageFlag == 0b01) { + ebs.clearB2High(); + ebs.clearB3(); + return; + } + var b2High = ebs.getB2High(); + if (b2High == null) { + b2High = ebs.createB2High(); + } + System.arraycopy(data, offset, b2High.data, 0, b2High.data.length); + offset += b2High.data.length; + if (storageFlag == 0b10) { + ebs.clearB3(); + return; + } + var b3 = ebs.getB3(); + if (b3 == null) { + b3 = ebs.createB3(); + } + System.arraycopy(data, offset, b3, 0, b3.length); } public static void getBlockMeta(final IExtendedBlockStorageMixin ebs, final byte[] data, final int offset) { @@ -38,103 +86,41 @@ public class Hooks { } public static void writeBlockDataToNBT(final NBTTagCompound nbt, final IExtendedBlockStorageMixin ebs) { - val ebsLSB = ebs.getLSB(); - val ebsMSB = ebs.getMSB(); - - val byte1Data = new byte[ebsLSB.length]; - byte[] byte2BottomNibbleData = null; - byte[] byte2TopNibbleData = null; - byte[] byte3Data = null; - for (int i = 0; i < ebsLSB.length; ++i) { - if (ebsMSB[i] != 0) { - if (byte3Data == null) { - byte3Data = new byte[ebsLSB.length]; - } - byte3Data[i] = ebsMSB[i]; - } - val idLSB = (ebsLSB[i] & 0xFFFF); - byte1Data[i] = (byte) (idLSB & 0xFF); - - if (idLSB <= 0xFF) { - continue; - } - val nibbleIndex = i >> 1; - val nibbleShift = (i & 1) * 4; - if (byte2BottomNibbleData == null) { - byte2BottomNibbleData = new byte[ebsLSB.length / 2]; - } - byte2BottomNibbleData[nibbleIndex] |= ((idLSB >>> 8) & 0xF) << nibbleShift; - - if (idLSB <= 0xFFF) { - continue; - } - if (byte2TopNibbleData == null) { - byte2TopNibbleData = new byte[ebsLSB.length / 2]; - } - byte2TopNibbleData[nibbleIndex] |= ((idLSB >>> 12) & 0xF) << nibbleShift; - + val b1 = ebs.getB1(); + val b2Low = ebs.getB2Low(); + val b2High = ebs.getB2High(); + val b3 = ebs.getB3(); + nbt.setByteArray("Blocks", b1); + if (b2Low != null) { + nbt.setByteArray("Add", b2Low.data); } - nbt.setByteArray("Blocks", byte1Data); - if (byte2BottomNibbleData != null) { - nbt.setByteArray("Add", byte2BottomNibbleData); + if (b2High != null) { + nbt.setByteArray("BlocksB2Hi", b2High.data); } - if (byte2TopNibbleData != null) { - nbt.setByteArray("BlocksB2Hi", byte2TopNibbleData); - } - if (byte3Data != null) { - nbt.setByteArray("BlocksB3", byte3Data); + if (b3 != null) { + nbt.setByteArray("BlocksB3", b3); } } public static void readBlockDataFromNBT(final IExtendedBlockStorageMixin ebs, final NBTTagCompound nbt) { assert nbt.hasKey("Blocks"); - val byte1Data = nbt.getByteArray("Blocks"); - val byte2BottomNibbleData = nbt.hasKey("Add") ? nbt.getByteArray("Add") : null; - val byte2TopNibbleData = nbt.hasKey("BlocksB2Hi") ? nbt.getByteArray("BlocksB2Hi") : null; - val byte3Data = nbt.hasKey("BlocksB3") ? nbt.getByteArray("BlocksB3") : null; + val b1 = nbt.getByteArray("Blocks"); + final byte[] b2Low = nbt.hasKey("Add") ? nbt.getByteArray("Add") : null; + final byte[] b2High = nbt.hasKey("BlocksB2Hi") ? nbt.getByteArray("BlocksB2Hi") : null; + final byte[] b3 = nbt.hasKey("BlocksB3") ? nbt.getByteArray("BlocksB3") : null; - val lsb = ebs.getLSB(); - val msb = ebs.getMSB(); - for (int i = 0; i < lsb.length; i++) { - if (byte3Data != null) { - msb[i] = byte3Data[i]; - } - int nibbleShift = (i & 1) * 4; - int id = byte1Data[i] & 0xFF; - if (byte2BottomNibbleData != null) { - id |= ((byte2BottomNibbleData[i >> 1] >> nibbleShift) & 0xF) << 8; - } - if (byte2TopNibbleData != null) { - id |= ((byte2TopNibbleData[i >> 1] >> nibbleShift) & 0xF) << 12; - } - lsb[i] = (short) id; + ebs.setB1(b1); + if (b2Low == null) { + ebs.clearB2Low(); + } else { + ebs.setB2Low(new NibbleArray(b2Low, 4)); } - } - - public static void removeInvalidBlocksHook(final IExtendedBlockStorageMixin ebs) { - val blkIdsLSB = ebs.getLSB(); - val blkIdsMSB = ebs.getMSB(); - int cntNonEmpty = 0; - int cntTicking = 0; - for (int off = 0; off < blkIdsLSB.length; ++off) { - final int id = - ((blkIdsLSB[off] & 0xFFFF) | ((blkIdsMSB[off] & 0xFF) << 16)) & ExtendedConstants.blockIDMask; - if (id > 0) { - final Block block = (Block) Block.blockRegistry.getObjectById(id); - if (block == null) { - if (GeneralConfig.removeInvalidBlocks) { - blkIdsLSB[off] = 0; - } - } else if (block != Blocks.air) { - ++cntNonEmpty; - if (block.getTickRandomly()) { - ++cntTicking; - } - } - } + if (b2High == null) { + ebs.clearB2High(); + } else { + ebs.setB2High(new NibbleArray(b2High, 4)); } - ebs.setBlockRefCount(cntNonEmpty); - ebs.setTickRefCount(cntTicking); + ebs.setB3(b3); } public static int getIdFromBlockWithCheck(final Block block, final Block oldBlock) { diff --git a/src/main/java/com/falsepattern/endlessids/mixin/helpers/IExtendedBlockStorageMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/helpers/IExtendedBlockStorageMixin.java index 871327a..42b9a60 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/helpers/IExtendedBlockStorageMixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/helpers/IExtendedBlockStorageMixin.java @@ -1,13 +1,29 @@ package com.falsepattern.endlessids.mixin.helpers; +import net.minecraft.world.chunk.NibbleArray; + public interface IExtendedBlockStorageMixin { - void setBlockRefCount(int value); + byte[] getB1(); + void setB1(byte[] data); - void setTickRefCount(int value); + NibbleArray getB2Low(); + void setB2Low(NibbleArray data); + void clearB2Low(); + NibbleArray createB2Low(); - short[] getLSB(); + NibbleArray getB2High(); + void setB2High(NibbleArray data); + void clearB2High(); + NibbleArray createB2High(); - byte[] getMSB(); + byte[] getB3(); + void setB3(byte[] data); + void clearB3(); + byte[] createB3(); + + int getStorageFlag(); + + int getID(int x, int y, int z); short[] getMetaArray(); } diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/client/blockitem/vanilla/ChunkMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/client/blockitem/vanilla/ChunkMixin.java index 9f2295e..d7a62af 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/client/blockitem/vanilla/ChunkMixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/client/blockitem/vanilla/ChunkMixin.java @@ -3,6 +3,7 @@ package com.falsepattern.endlessids.mixin.mixins.client.blockitem.vanilla; import com.falsepattern.endlessids.Hooks; import com.falsepattern.endlessids.constants.ExtendedConstants; import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin; +import lombok.val; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -25,9 +26,6 @@ public abstract class ChunkMixin { @Shadow private ExtendedBlockStorage[] storageArrays; - //This is needed because the array is not a field, but a local, and local arraylength overriding does not exist - private static byte[] fakeArray; - @Redirect(method = "fillChunk", at = @At(value = "FIELD", target = "Lnet/minecraft/world/chunk/Chunk;storageArrays:[Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;", @@ -47,15 +45,26 @@ public abstract class ChunkMixin { locals = LocalCapture.CAPTURE_FAILHARD, require = 1) private void blockData(byte[] p_76607_1_, int p_76607_2_, int p_76607_3_, boolean p_76607_4_, CallbackInfo ci, Iterator iterator, int k, boolean flag1, int l) { - Hooks.setBlockData((IExtendedBlockStorageMixin) this.storageArrays[l], p_76607_1_, k); + val storageFlag = (p_76607_3_ >>> l) & 0b11; + Hooks.setBlockData((IExtendedBlockStorageMixin) this.storageArrays[l], p_76607_1_, k, storageFlag); } + + //This is needed because the array is not a field, but a local, and local arraylength overriding does not exist + private static byte[][] fakeArrays; @Redirect(method = "fillChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;getBlockLSBArray()[B"), require = 1) private byte[] fakeLSBArray(ExtendedBlockStorage instance) { - return fakeArray != null ? fakeArray : (fakeArray = new byte[16 * 16 * 16 * ExtendedConstants.bytesPerID]); + if (fakeArrays == null) { + fakeArrays = new byte[4][]; + fakeArrays[0] = new byte[16 * 16 * 16 * 2 / 2]; + fakeArrays[1] = new byte[16 * 16 * 16 * 3 / 2]; + fakeArrays[2] = new byte[16 * 16 * 16 * 4 / 2]; + fakeArrays[3] = new byte[16 * 16 * 16 * 6 / 2]; + } + return fakeArrays[((IExtendedBlockStorageMixin)instance).getStorageFlag()]; } @Redirect(method = "fillChunk", diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/biome/vanilla/S26PacketMapChunkBulkMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/biome/vanilla/S26PacketMapChunkBulkMixin.java deleted file mode 100644 index 5f0d259..0000000 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/biome/vanilla/S26PacketMapChunkBulkMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.falsepattern.endlessids.mixin.mixins.common.biome.vanilla; - -import com.falsepattern.endlessids.constants.ExtendedConstants; -import com.falsepattern.endlessids.constants.VanillaConstants; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.ModifyConstant; - -import net.minecraft.network.play.server.S26PacketMapChunkBulk; - -@Mixin(S26PacketMapChunkBulk.class) -public abstract class S26PacketMapChunkBulkMixin { - - @ModifyConstant(method = "readPacketData", - constant = @Constant(intValue = VanillaConstants.bytesPerBiome * 16 * 16), - require = 1) - private int extend2(int contant) { - return ExtendedConstants.bytesPerBiome * 16 * 16; - } -} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/ubc/BiomeUndergroundDecoratorMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/ubc/BiomeUndergroundDecoratorMixin.java index 3ca4c4c..83ee3c3 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/ubc/BiomeUndergroundDecoratorMixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/ubc/BiomeUndergroundDecoratorMixin.java @@ -3,6 +3,7 @@ package com.falsepattern.endlessids.mixin.mixins.common.blockitem.ubc; import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin; import exterminatorJeff.undergroundBiomes.worldGen.BiomeUndergroundDecorator; import exterminatorJeff.undergroundBiomes.worldGen.OreUBifier; +import lombok.val; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -16,7 +17,7 @@ import java.util.logging.Logger; remap = false) public abstract class BiomeUndergroundDecoratorMixin { private static NibbleArray fakeArray; - private ThreadLocal ebs; + private IExtendedBlockStorageMixin ebs; @Redirect(method = {"replaceChunkOres(IILnet/minecraft/world/World;)V", "replaceChunkOres(Lnet/minecraft/world/chunk/IChunkProvider;II)V"}, @@ -24,13 +25,10 @@ public abstract class BiomeUndergroundDecoratorMixin { target = "Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;getBlockLSBArray()[B", remap = true), require = 2) - private byte[] returnMSBasLSB(ExtendedBlockStorage instance) { - if (ebs == null) { - ebs = new ThreadLocal<>(); - } + private byte[] returnLSB(ExtendedBlockStorage instance) { IExtendedBlockStorageMixin iebs = (IExtendedBlockStorageMixin) instance; - ebs.set(iebs); - return iebs.getMSB(); + ebs = iebs; + return iebs.getB1(); } @Redirect(method = {"replaceChunkOres(IILnet/minecraft/world/World;)V", @@ -50,17 +48,9 @@ public abstract class BiomeUndergroundDecoratorMixin { remap = true), require = 2) private int returnRestOfID(NibbleArray instance, int x, int y, int z) { - return ebs.get().getLSB()[y << 8 | z << 4 | x] & 0xFFFF; - } - - @Redirect(method = {"replaceChunkOres(IILnet/minecraft/world/World;)V", - "replaceChunkOres(Lnet/minecraft/world/chunk/IChunkProvider;II)V"}, - at = @At(value = "INVOKE", - target = "LexterminatorJeff/undergroundBiomes/worldGen/OreUBifier;blockReplacer(I)LexterminatorJeff/undergroundBiomes/worldGen/OreUBifier$BlockReplacer;"), - require = 2) - private OreUBifier.BlockReplacer reshuffleID(OreUBifier instance, int blockID) { - blockID = ((blockID & 0xFF) << 16) | ((blockID & 0xFFFF00) >>> 8); - return instance.blockReplacer(blockID); + val id = ebs.getID(x, y, z) >>> 8; + ebs = null; + return id; } @Redirect(method = "correctBiomeDecorators", diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java index 57bc226..b9c25ca 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/ExtendedBlockStorageMixin.java @@ -3,9 +3,10 @@ package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla; import com.falsepattern.endlessids.EndlessIDs; import com.falsepattern.endlessids.Hooks; import com.falsepattern.endlessids.Tags; +import com.falsepattern.endlessids.config.GeneralConfig; import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin; import lombok.val; -import org.objectweb.asm.Opcodes; +import lombok.var; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; @@ -28,30 +29,12 @@ public abstract class ExtendedBlockStorageMixin implements IExtendedBlockStorage private int tickRefCount; @Shadow private byte[] blockLSBArray; @Shadow private NibbleArray blockMetadataArray; - private short[] lsbArray; - private byte[] msbArray; + + @Shadow private NibbleArray blockMSBArray; + private NibbleArray b2High; + private byte[] b3; private short[] metaArray; - @Override - public void setBlockRefCount(int value) { - blockRefCount = value; - } - - @Override - public void setTickRefCount(int value) { - tickRefCount = value; - } - - @Override - public short[] getLSB() { - return lsbArray; - } - - @Override - public byte[] getMSB() { - return msbArray; - } - @Override public short[] getMetaArray() { return metaArray; @@ -61,26 +44,50 @@ public abstract class ExtendedBlockStorageMixin implements IExtendedBlockStorage at = @At(value = "RETURN"), require = 1) private void init(CallbackInfo ci) { - blockLSBArray = null; blockMetadataArray = null; - lsbArray = new short[16 * 16 * 16]; - msbArray = new byte[16 * 16 * 16]; metaArray = new short[16 * 16 * 16]; } - private int getID(int x, int y, int z) { + public int getID(int x, int y, int z) { int index = y << 8 | z << 4 | x; - int lsb = lsbArray[index] & 0xFFFF; - int msb = (msbArray[index] & 0xFF) << 16; - return lsb | msb; + int id = blockLSBArray[index] & 0xFF; + if (blockMSBArray != null) { + id |= blockMSBArray.get(x, y, z) << 8; + if (b2High != null) { + id |= b2High.get(x, y, z) << 12; + if (b3 != null) { + id |= (b3[index] & 0xFF) << 16; + } + } + } + return id; } private void setID(int x, int y, int z, int id) { int index = y << 8 | z << 4 | x; - int lsb = id & 0xFFFF; - int msb = (id >>> 16) & 0xFF; - lsbArray[index] = (short) lsb; - msbArray[index] = (byte) msb; + blockLSBArray[index] = (byte) (id & 0xFF); + if (id > 0xFF) { + if (blockMSBArray == null) { + blockMSBArray = new NibbleArray(blockLSBArray.length, 4); + } + if (id > 0xFFF) { + if (b2High == null) { + b2High = new NibbleArray(blockLSBArray.length, 4); + } + if (id > 0xFFFF && b3 == null) { + b3 = new byte[blockLSBArray.length]; + } + } + } + if (blockMSBArray != null) { + blockMSBArray.set(x, y, z, (id >>> 8) & 0xF); + if (b2High != null) { + b2High.set(x, y, z, (id >>> 12) & 0xF); + if (b3 != null) { + b3[index] = (byte) ((id >>> 16) & 0xFF); + } + } + } } /** @@ -137,13 +144,17 @@ public abstract class ExtendedBlockStorageMixin implements IExtendedBlockStorage metaArray[index] = (short)(meta & 0xFFFF); } - /** - * @author FalsePattern - * @reason Direct port from dumped code - */ - @Overwrite - public void removeInvalidBlocks() { - Hooks.removeInvalidBlocksHook(this); + @Redirect(method = "removeInvalidBlocks", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;getBlockByExtId(III)Lnet/minecraft/block/Block;"), + require = 1) + private Block removeInvalidBlocks(ExtendedBlockStorage instance, int x, int y, int z) { + var block = instance.getBlockByExtId(x, y, z); + if (block == null && GeneralConfig.removeInvalidBlocks) { + instance.func_150818_a(x, y, z, Blocks.air); + block = Blocks.air; + } + return block; } private UnsupportedOperationException emergencyCrash() { @@ -154,6 +165,90 @@ public abstract class ExtendedBlockStorageMixin implements IExtendedBlockStorage return new UnsupportedOperationException(crashMSG); } + @Override + public byte[] getB1() { + return blockLSBArray; + } + + @Override + public void setB1(byte[] data) { + blockLSBArray = data; + } + + @Override + public NibbleArray getB2Low() { + return blockMSBArray; + } + + @Override + public void clearB2Low() { + blockMSBArray = null; + } + + @Override + public void setB2Low(NibbleArray data) { + blockMSBArray = data; + } + + @Override + public NibbleArray createB2Low() { + return (blockMSBArray = new NibbleArray(blockLSBArray.length, 4)); + } + + @Override + public NibbleArray getB2High() { + return b2High; + } + + @Override + public void setB2High(NibbleArray data) { + b2High = data; + } + + @Override + public void clearB2High() { + b2High = null; + } + + @Override + public NibbleArray createB2High() { + return (b2High = new NibbleArray(blockLSBArray.length, 4)); + } + + @Override + public byte[] getB3() { + return b3; + } + + @Override + public void setB3(byte[] data) { + b3 = data; + } + + @Override + public void clearB3() { + b3 = null; + } + + @Override + public byte[] createB3() { + return b3 = new byte[blockLSBArray.length]; + } + + @Override + public int getStorageFlag() { + if (blockMSBArray == null) { + return 0b00; + } + if (b2High == null) { + return 0b01; + } + if (b3 == null) { + return 0b10; + } + return 0b11; + } + @Inject(method = {"getBlockMSBArray", "createBlockMSBArray"}, at = @At("HEAD")) private void crashMSBArray(CallbackInfoReturnable cir) { diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S21PacketChunkDataMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S21PacketChunkDataMixin.java index e762770..2d57aeb 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S21PacketChunkDataMixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S21PacketChunkDataMixin.java @@ -1,10 +1,10 @@ package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla; -import com.falsepattern.endlessids.EndlessIDs; import com.falsepattern.endlessids.Hooks; import com.falsepattern.endlessids.constants.ExtendedConstants; import com.falsepattern.endlessids.constants.VanillaConstants; import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin; +import lombok.val; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; @@ -37,16 +37,24 @@ public abstract class S21PacketChunkDataMixin { locals = LocalCapture.CAPTURE_FAILHARD, require = 1) private static void hookGetBlockData(Chunk p_149269_0_, boolean p_149269_1_, int p_149269_2_, CallbackInfoReturnable cir, int j, ExtendedBlockStorage[] aextendedblockstorage, int k, S21PacketChunkData.Extracted extracted, byte[] abyte, int l) { - Hooks.getBlockData((IExtendedBlockStorageMixin) aextendedblockstorage[l], abyte, j); + val ebs = (IExtendedBlockStorageMixin) aextendedblockstorage[l]; + extracted.field_150281_c |= Hooks.getBlockData(ebs, abyte, j) << l * 2; } - private static byte[] fakeArray; + private static byte[][] fakeArrays; @Redirect(method = "func_149269_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/chunk/storage/ExtendedBlockStorage;getBlockLSBArray()[B"), require = 1) private static byte[] hookGetBlockDataFakeArray(ExtendedBlockStorage instance) { - return fakeArray != null ? fakeArray : (fakeArray = new byte[16 * 16 * 16 * ExtendedConstants.bytesPerID]); + if (fakeArrays == null) { + fakeArrays = new byte[4][]; + fakeArrays[0] = new byte[16 * 16 * 16 * 2 / 2]; + fakeArrays[1] = new byte[16 * 16 * 16 * 3 / 2]; + fakeArrays[2] = new byte[16 * 16 * 16 * 4 / 2]; + fakeArrays[3] = new byte[16 * 16 * 16 * 6 / 2]; + } + return fakeArrays[((IExtendedBlockStorageMixin)instance).getStorageFlag()]; } @Redirect(method = "func_149269_a", @@ -103,11 +111,4 @@ public abstract class S21PacketChunkDataMixin { private static void hookGetBlockMetaNoCopy(Object src, int srcPos, Object dest, int destPos, int length) { } - - @ModifyConstant(method = "readPacketData", - constant = @Constant(intValue = VanillaConstants.bytesPerEBS), - require = 1) - private int increaseReadSize(int constant) { - return ExtendedConstants.bytesPerEBS; - } } diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S26PacketMapChunkBulkMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S26PacketMapChunkBulkMixin.java deleted file mode 100644 index 2789728..0000000 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/blockitem/vanilla/S26PacketMapChunkBulkMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.falsepattern.endlessids.mixin.mixins.common.blockitem.vanilla; - -import com.falsepattern.endlessids.constants.ExtendedConstants; -import com.falsepattern.endlessids.constants.VanillaConstants; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.Constant; -import org.spongepowered.asm.mixin.injection.ModifyConstant; - -import net.minecraft.network.play.server.S26PacketMapChunkBulk; - -@Mixin(S26PacketMapChunkBulk.class) -public abstract class S26PacketMapChunkBulkMixin { - @ModifyConstant(method = "readPacketData", - constant = @Constant(intValue = VanillaConstants.bytesPerIDPlusMetadata * 16 * 16 * 16), - require = 1) - private int extend1(int constant) { - return ExtendedConstants.bytesPerIDPlusMetadata * 16 * 16 * 16; - } -} diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S21PacketChunkDataMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S21PacketChunkDataMixin.java index 8c95d76..fc3f55f 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S21PacketChunkDataMixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S21PacketChunkDataMixin.java @@ -1,26 +1,99 @@ package com.falsepattern.endlessids.mixin.mixins.common.vanilla; -import com.falsepattern.endlessids.Hooks; import com.falsepattern.endlessids.constants.ExtendedConstants; import com.falsepattern.endlessids.constants.VanillaConstants; -import com.falsepattern.endlessids.mixin.helpers.IChunkMixin; -import com.falsepattern.endlessids.mixin.helpers.IExtendedBlockStorageMixin; +import io.netty.buffer.ByteBuf; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyConstant; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.server.S21PacketChunkData; -import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +import java.io.IOException; +import java.util.zip.DataFormatException; +import java.util.zip.Inflater; @Mixin(S21PacketChunkData.class) public abstract class S21PacketChunkDataMixin { + @Shadow private int field_149280_d; + + @Shadow private byte[] field_149278_f; + + @Shadow private int field_149284_a; + + @Shadow private int field_149282_b; + + @Shadow private boolean field_149279_g; + + @Shadow private int field_149283_c; + + @Shadow private int field_149285_h; + + @Shadow private static byte[] field_149286_i; + @ModifyConstant(method = {"", "func_149275_c"}, constant = @Constant(intValue = VanillaConstants.bytesPerChunk), require = 1) private static int increasePacketSize(int constant) { return ExtendedConstants.bytesPerChunk; } + + + @Inject(method = "writePacketData", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/network/PacketBuffer;writeShort(I)Lio/netty/buffer/ByteBuf;", + ordinal = 1), + require = 1) + private void extendWrite(PacketBuffer p_148840_1_, CallbackInfo ci) { + p_148840_1_.writeInt(this.field_149280_d); + p_148840_1_.writeInt(this.field_149278_f.length); + } + + @Redirect(method = "writePacketData", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/network/PacketBuffer;writeShort(I)Lio/netty/buffer/ByteBuf;", + ordinal = 1), + require = 1) + private ByteBuf suppressOldWrite(PacketBuffer instance, int p_writeShort_1_) { + return null; + } + + @Inject(method = "readPacketData", + at = @At("HEAD"), + require = 1, + cancellable = true) + private void customRead(PacketBuffer data, CallbackInfo ci) throws IOException { + this.field_149284_a = data.readInt(); + this.field_149282_b = data.readInt(); + this.field_149279_g = data.readBoolean(); + this.field_149283_c = data.readShort(); + this.field_149280_d = data.readInt(); + int length = data.readInt(); + this.field_149285_h = data.readInt(); + + if (field_149286_i.length < this.field_149285_h) { + field_149286_i = new byte[this.field_149285_h]; + } + + data.readBytes(field_149286_i, 0, this.field_149285_h); + + this.field_149278_f = new byte[length]; + Inflater inflater = new Inflater(); + inflater.setInput(field_149286_i, 0, this.field_149285_h); + + try { + inflater.inflate(this.field_149278_f); + } catch (DataFormatException dataformatexception) { + throw new IOException("Bad compressed data format"); + } finally { + inflater.end(); + } + ci.cancel(); + } } diff --git a/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S26PacketMapChunkBulkMixin.java b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S26PacketMapChunkBulkMixin.java new file mode 100644 index 0000000..ac053b1 --- /dev/null +++ b/src/main/java/com/falsepattern/endlessids/mixin/mixins/common/vanilla/S26PacketMapChunkBulkMixin.java @@ -0,0 +1,71 @@ +package com.falsepattern.endlessids.mixin.mixins.common.vanilla; + +import io.netty.buffer.ByteBuf; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S26PacketMapChunkBulk; + +import java.util.zip.Inflater; + +@Mixin(S26PacketMapChunkBulk.class) +public abstract class S26PacketMapChunkBulkMixin { + @Shadow private int[] field_149262_d; + + @Shadow private byte[][] field_149260_f; + + @Shadow private int[] field_149266_a; + + @Shadow private int[] field_149264_b; + + @Shadow private int[] field_149265_c; + + @Inject(method = "writePacketData", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/network/PacketBuffer;writeShort(I)Lio/netty/buffer/ByteBuf;", + ordinal = 2), + locals = LocalCapture.CAPTURE_FAILHARD, + require = 1) + private void extendWrite(PacketBuffer p_148840_1_, CallbackInfo ci, int i) { + p_148840_1_.writeInt(this.field_149262_d[i]); + p_148840_1_.writeInt(this.field_149260_f[i].length); + } + + @Redirect(method = "writePacketData", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/network/PacketBuffer;writeShort(I)Lio/netty/buffer/ByteBuf;", + ordinal = 2), + require = 1) + private ByteBuf suppressOldWrite(PacketBuffer instance, int p_writeShort_1_) { + return null; + } + + @Inject(method = "readPacketData", + at = @At(value = "INVOKE", + target = "Ljava/util/zip/Inflater;inflate([B)I", + shift = At.Shift.AFTER), + require = 1, + locals = LocalCapture.CAPTURE_FAILHARD, + cancellable = true) + private void customRead(PacketBuffer data, CallbackInfo ci, short short1, byte[] abyte, Inflater inflater) { + int i = 0; + + for (int j = 0; j < short1; ++j) { + this.field_149266_a[j] = data.readInt(); + this.field_149264_b[j] = data.readInt(); + this.field_149265_c[j] = data.readShort(); + this.field_149262_d[j] = data.readInt(); + byte[] dataBytes = new byte[data.readInt()]; + this.field_149260_f[j] = dataBytes; + System.arraycopy(abyte, i, dataBytes, 0, dataBytes.length); + i += dataBytes.length; + } + ci.cancel(); + } +} 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 9d09f40..4f243a5 100644 --- a/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java +++ b/src/main/java/com/falsepattern/endlessids/mixin/plugin/Mixin.java @@ -19,6 +19,7 @@ public enum Mixin implements IMixin { //region common //region vanilla S21PacketChunkDataMixin(Side.COMMON, always(), "vanilla.S21PacketChunkDataMixin"), + S26PacketMapChunkBulkMixin(Side.COMMON, always(), "vanilla.S26PacketMapChunkBulkMixin"), //endregion vanilla //region AntiIDConflict AIDCAntiIdConflictBaseMixin(Side.COMMON, require(TargetedMod.ANTIIDCONFLICT), "antiidconflict.AntiIdConflictBaseMixin"), @@ -38,7 +39,6 @@ public enum Mixin implements IMixin { GenLayerRiverMixMixin(Side.COMMON, condition(() -> GeneralConfig.extendBiome).and(avoid(TargetedMod.DRAGONAPI)), "biome.vanilla.GenLayerRiverMixMixin"), GenLayerVoronoiZoomMixin(Side.COMMON, condition(() -> GeneralConfig.extendBiome), "biome.vanilla.GenLayerVoronoiZoomMixin"), S21PacketChunkDataMixinBiome(Side.COMMON, condition(() -> GeneralConfig.extendBiome), "biome.vanilla.S21PacketChunkDataMixin"), - S26PacketMapChunkBulkMixinBiome(Side.COMMON, condition(() -> GeneralConfig.extendBiome), "biome.vanilla.S26PacketMapChunkBulkMixin"), //endregion vanilla //region AbyssalCraft AbyssalCraftMixin(Side.COMMON, condition(() -> GeneralConfig.extendBiome).and(require(TargetedMod.ABYSSALCRAFT)), "biome.abyssalcraft.AbyssalCraftMixin"), @@ -173,7 +173,6 @@ public enum Mixin implements IMixin { S21PacketChunkDataMixinBlockItem(Side.COMMON, condition(() -> GeneralConfig.extendBlockItem), "blockitem.vanilla.S21PacketChunkDataMixin"), S22PacketMultiBlockChangeMixin(Side.COMMON, condition(() -> GeneralConfig.extendBlockItem), "blockitem.vanilla.S22PacketMultiBlockChangeMixin"), S24PacketBlockActionMixin(Side.COMMON, condition(() -> GeneralConfig.extendBlockItem), "blockitem.vanilla.S24PacketBlockActionMixin"), - S26PacketMapChunkBulkMixinBlockItem(Side.COMMON, condition(() -> GeneralConfig.extendBlockItem), "blockitem.vanilla.S26PacketMapChunkBulkMixin"), StatListMixin(Side.COMMON, condition(() -> GeneralConfig.extendBlockItem), "blockitem.vanilla.StatListMixin"), WorldMixin(Side.COMMON, condition(() -> GeneralConfig.extendBlockItem), "blockitem.vanilla.WorldMixin"), //endregion vanilla