001    package net.minecraft.network.packet;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.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            if (!par0Chunk.worldObj.provider.hasNoSky)
228            {
229                for (var8 = 0; var8 < var4.length; ++var8)
230                {
231                    if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0)
232                    {
233                        var10 = var4[var8].getSkylightArray();
234                        System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
235                        var3 += var10.data.length;
236                    }
237                }
238            }
239    
240            if (var5 > 0)
241            {
242                for (var8 = 0; var8 < var4.length; ++var8)
243                {
244                    if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && var4[var8].getBlockMSBArray() != null && (par2 & 1 << var8) != 0)
245                    {
246                        var10 = var4[var8].getBlockMSBArray();
247                        System.arraycopy(var10.data, 0, var7, var3, var10.data.length);
248                        var3 += var10.data.length;
249                    }
250                }
251            }
252    
253            if (par1)
254            {
255                byte[] var11 = par0Chunk.getBiomeArray();
256                System.arraycopy(var11, 0, var7, var3, var11.length);
257                var3 += var11.length;
258            }
259    
260            var6.field_74582_a = new byte[var3];
261            System.arraycopy(var7, 0, var6.field_74582_a, 0, var3);
262            return var6;
263        }
264    
265        @SideOnly(Side.CLIENT)
266        public byte[] func_73593_d()
267        {
268            return this.field_73596_g;
269        }
270    }