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 = getMapChunkData(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 getMapChunkData(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 }