    001    package net.minecraft.network.packet;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.io.DataInputStream;
    006    import java.io.DataOutputStream;
    007    import java.io.IOException;
    008    import java.util.zip.DataFormatException;
    009    import java.util.zip.Deflater;
    010    import java.util.zip.Inflater;
    011    import net.minecraft.world.chunk.Chunk;
    012    import net.minecraft.world.chunk.NibbleArray;
    013    import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
    014
    015    public class Packet51MapChunk extends Packet
    016    {
    017        /** The x-position of the transmitted chunk, in chunk coordinates. */
    018        public int xCh;
    019
    020        /** The z-position of the transmitted chunk, in chunk coordinates. */
    021        public int zCh;
    022
    023        /**
    024         * The y-position of the lowest chunk Section in the transmitted chunk, in chunk coordinates.
    025         */
    026        public int yChMin;
    027
    028        /**
    029         * The y-position of the highest chunk Section in the transmitted chunk, in chunk coordinates.
    030         */
    031        public int yChMax;
    032
    033        /** The transmitted chunk data, decompressed. */
    034        private byte[] chunkData;
    035        private byte[] field_73596_g;
    036
    037        /**
    038         * Whether to initialize the Chunk before applying the effect of the Packet51MapChunk.
    039         */
    040        public boolean includeInitialize;
    041
    042        /** The length of the compressed chunk data byte array. */
    043        private int tempLength;
    044
    045        /** A temporary storage for the compressed chunk data byte array. */
    046        private static byte[] temp = new byte[196864];
    047
    048        public Packet51MapChunk()
    049        {
    050            this.isChunkDataPacket = true;
    051        }
    052
    053        public Packet51MapChunk(Chunk par1Chunk, boolean par2, int par3)
    054        {
    055            this.isChunkDataPacket = true;
    056            this.xCh = par1Chunk.xPosition;
    057            this.zCh = par1Chunk.zPosition;
    058            this.includeInitialize = par2;
    059            Packet51MapChunkData var4 = getMapChunkData(par1Chunk, par2, par3);
    060            Deflater var5 = new Deflater(-1);
    061            this.yChMax = var4.field_74581_c;
    062            this.yChMin = var4.field_74580_b;
    063
    064            try
    065            {
    066                this.field_73596_g = var4.field_74582_a;
    067                var5.setInput(var4.field_74582_a, 0, var4.field_74582_a.length);
    068                var5.finish();
    069                this.chunkData = new byte[var4.field_74582_a.length];
    070                this.tempLength = var5.deflate(this.chunkData);
    071            }
    072            finally
    073            {
    074                var5.end();
    075            }
    076        }
    077
    078        /**
    079         * Abstract. Reads the raw packet data from the data stream.
    080         */
    081        public void readPacketData(DataInputStream par1DataInputStream) throws IOException
    082        {
    083            this.xCh = par1DataInputStream.readInt();
    084            this.zCh = par1DataInputStream.readInt();
    085            this.includeInitialize = par1DataInputStream.readBoolean();
    086            this.yChMin = par1DataInputStream.readShort();
    087            this.yChMax = par1DataInputStream.readShort();
    088            this.tempLength = par1DataInputStream.readInt();
    089
    090            if (temp.length < this.tempLength)
    091            {
    092                temp = new byte[this.tempLength];
    093            }
    094
    095            par1DataInputStream.readFully(temp, 0, this.tempLength);
    096            int var2 = 0;
    097            int var3;
    098
    099            for (var3 = 0; var3 < 16; ++var3)
    100            {
    101                var2 += this.yChMin >> var3 & 1;
    102            }
    103
    104            var3 = 12288 * var2;
    105
    106            int msb = 0; //BugFix: MC does not read the MSB array from the packet properly, causing issues for servers that use blocks > 256
    107            for (int x = 0; x < 16; x++)
    108            {
    109                msb += (yChMax >> x) & 1;
    110            }
    111            var3 += (2048 * msb);
    112
    113            if (this.includeInitialize)
    114            {
    115                var3 += 256;
    116            }
    117
    118            this.field_73596_g = new byte[var3];
    119            Inflater var4 = new Inflater();
    120            var4.setInput(temp, 0, this.tempLength);
    121
    122            try
    123            {
    124                var4.inflate(this.field_73596_g);
    125            }
    126            catch (DataFormatException var9)
    127            {
    128                throw new IOException("Bad compressed data format");
    129            }
    130            finally
    131            {
    132                var4.end();
    133            }
    134        }
    135
    136        /**
    137         * Abstract. Writes the raw packet data to the data stream.
    138         */
    139        public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException
    140        {
    141            par1DataOutputStream.writeInt(this.xCh);
    142            par1DataOutputStream.writeInt(this.zCh);
    143            par1DataOutputStream.writeBoolean(this.includeInitialize);
    144            par1DataOutputStream.writeShort((short)(this.yChMin & 65535));
    145            par1DataOutputStream.writeShort((short)(this.yChMax & 65535));
    146            par1DataOutputStream.writeInt(this.tempLength);
    147            par1DataOutputStream.write(this.chunkData, 0, this.tempLength);
    148        }
    149
    150        /**
    151         * Passes this Packet on to the NetHandler for processing.
    152         */
    153        public void processPacket(NetHandler par1NetHandler)
    154        {
    155            par1NetHandler.handleMapChunk(this);
    156        }
    157
    158        /**
    159         * Abstract. Return the size of the packet (not counting the header).
    160         */
    161        public int getPacketSize()
    162        {
    163            return 17 + this.tempLength;
    164        }
    165
    166        public static Packet51MapChunkData getMapChunkData(Chunk par0Chunk, boolean par1, int par2)
    167        {
    168            int var3 = 0;
    169            ExtendedBlockStorage[] var4 = par0Chunk.getBlockStorageArray();
    170            int var5 = 0;
    171            Packet51MapChunkData var6 = new Packet51MapChunkData();
    172            byte[] var7 = temp;
    173
    174            if (par1)
    175            {
    176                par0Chunk.deferRender = true;
    177            }
    178
    179            int var8;
    180
    181            for (var8 = 0; var8 < var4.length; ++var8)
    182            {
    183                if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0)
    184                {
    185                    var6.field_74580_b |= 1 << var8;
    186
    187                    if (var4[var8].getBlockMSBArray() != null)
    188                    {
    189                        var6.field_74581_c |= 1 << var8;
    190                        ++var5;
    191                    }
    192                }
    193            }
    194
    195            for (var8 = 0; var8 < var4.length; ++var8)
    196            {
    197                if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0)
    198                {
    199                    byte[] var9 = var4[var8].getBlockLSBArray();
    200                    System.arraycopy(var9, 0, var7, var3, var9.length);
    201                    var3 += var9.length;
    202                }
    203            }
    204
    205            NibbleArray var10;
    206
    207            for (var8 = 0; var8 < var4.length; ++var8)
    208            {
    209                if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0)
    210                {
    211                    var10 = var4[var8].getMetadataArray();
    212                    System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
    213                    var3 += var10.data.length;
    214                }
    215            }
    216
    217            for (var8 = 0; var8 < var4.length; ++var8)
    218            {
    219                if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0)
    220                {
    221                    var10 = var4[var8].getBlocklightArray();
    222                    System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
    223                    var3 += var10.data.length;
    224                }
    225            }
    226
    227            for (var8 = 0; var8 < var4.length; ++var8)
    228            {
    229                if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0)
    230                {
    231                    var10 = var4[var8].getSkylightArray();
    232                    System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
    233                    var3 += var10.data.length;
    234                }
    235            }
    236
    237            if (var5 > 0)
    238            {
    239                for (var8 = 0; var8 < var4.length; ++var8)
    240                {
    241                    if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && var4[var8].getBlockMSBArray() != null && (par2 & 1 << var8) != 0)
    242                    {
    243                        var10 = var4[var8].getBlockMSBArray();
    244                        System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
    245                        var3 += var10.data.length;
    246                    }
    247                }
    248            }
    249
    250            if (par1)
    251            {
    252                byte[] var11 = par0Chunk.getBiomeArray();
    253                System.arraycopy(var11, 0, var7, var3, var11.length);
    254                var3 += var11.length;
    255            }
    256
    257            var6.field_74582_a = new byte[var3];
    258            System.arraycopy(var7, 0, var6.field_74582_a, 0, var3);
    259            return var6;
    260        }
    261
    262        @SideOnly(Side.CLIENT)
    263        public byte[] func_73593_d()
    264        {
    265            return this.field_73596_g;
    266        }
    267    }