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