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 this.yChMax = var4.field_74581_c; 061 this.yChMin = var4.field_74580_b; 062 this.field_73596_g = var4.field_74582_a; 063 } 064 065 private void deflate() 066 { 067 Deflater var5 = new Deflater(-1); 068 try 069 { 070 var5.setInput(field_73596_g, 0, field_73596_g.length); 071 var5.finish(); 072 this.chunkData = new byte[field_73596_g.length]; 073 this.tempLength = var5.deflate(this.chunkData); 074 } 075 finally 076 { 077 var5.end(); 078 } 079 } 080 081 /** 082 * Abstract. Reads the raw packet data from the data stream. 083 */ 084 public void readPacketData(DataInputStream par1DataInputStream) throws IOException 085 { 086 this.xCh = par1DataInputStream.readInt(); 087 this.zCh = par1DataInputStream.readInt(); 088 this.includeInitialize = par1DataInputStream.readBoolean(); 089 this.yChMin = par1DataInputStream.readShort(); 090 this.yChMax = par1DataInputStream.readShort(); 091 this.tempLength = par1DataInputStream.readInt(); 092 093 if (temp.length < this.tempLength) 094 { 095 temp = new byte[this.tempLength]; 096 } 097 098 par1DataInputStream.readFully(temp, 0, this.tempLength); 099 int var2 = 0; 100 int var3; 101 int msb = 0; //BugFix: MC does not read the MSB array from the packet properly, causing issues for servers that use blocks > 256 102 103 for (var3 = 0; var3 < 16; ++var3) 104 { 105 var2 += this.yChMin >> var3 & 1; 106 msb += this.yChMax >> var3 & 1; 107 } 108 109 var3 = 12288 * var2; 110 var3 += 2048 * msb; 111 112 if (this.includeInitialize) 113 { 114 var3 += 256; 115 } 116 117 this.field_73596_g = new byte[var3]; 118 Inflater var4 = new Inflater(); 119 var4.setInput(temp, 0, this.tempLength); 120 121 try 122 { 123 var4.inflate(this.field_73596_g); 124 } 125 catch (DataFormatException var9) 126 { 127 throw new IOException("Bad compressed data format"); 128 } 129 finally 130 { 131 var4.end(); 132 } 133 } 134 135 /** 136 * Abstract. Writes the raw packet data to the data stream. 137 */ 138 public void writePacketData(DataOutputStream par1DataOutputStream) throws IOException 139 { 140 if (chunkData == null) 141 { 142 deflate(); 143 } 144 145 par1DataOutputStream.writeInt(this.xCh); 146 par1DataOutputStream.writeInt(this.zCh); 147 par1DataOutputStream.writeBoolean(this.includeInitialize); 148 par1DataOutputStream.writeShort((short)(this.yChMin & 65535)); 149 par1DataOutputStream.writeShort((short)(this.yChMax & 65535)); 150 par1DataOutputStream.writeInt(this.tempLength); 151 par1DataOutputStream.write(this.chunkData, 0, this.tempLength); 152 } 153 154 /** 155 * Passes this Packet on to the NetHandler for processing. 156 */ 157 public void processPacket(NetHandler par1NetHandler) 158 { 159 par1NetHandler.handleMapChunk(this); 160 } 161 162 /** 163 * Abstract. Return the size of the packet (not counting the header). 164 */ 165 public int getPacketSize() 166 { 167 return 17 + this.tempLength; 168 } 169 170 public static Packet51MapChunkData getMapChunkData(Chunk par0Chunk, boolean par1, int par2) 171 { 172 int var3 = 0; 173 ExtendedBlockStorage[] var4 = par0Chunk.getBlockStorageArray(); 174 int var5 = 0; 175 Packet51MapChunkData var6 = new Packet51MapChunkData(); 176 byte[] var7 = temp; 177 178 if (par1) 179 { 180 par0Chunk.deferRender = true; 181 } 182 183 int var8; 184 185 for (var8 = 0; var8 < var4.length; ++var8) 186 { 187 if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) 188 { 189 var6.field_74580_b |= 1 << var8; 190 191 if (var4[var8].getBlockMSBArray() != null) 192 { 193 var6.field_74581_c |= 1 << var8; 194 ++var5; 195 } 196 } 197 } 198 199 for (var8 = 0; var8 < var4.length; ++var8) 200 { 201 if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) 202 { 203 byte[] var9 = var4[var8].getBlockLSBArray(); 204 System.arraycopy(var9, 0, var7, var3, var9.length); 205 var3 += var9.length; 206 } 207 } 208 209 NibbleArray var10; 210 211 for (var8 = 0; var8 < var4.length; ++var8) 212 { 213 if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) 214 { 215 var10 = var4[var8].getMetadataArray(); 216 System.arraycopy(var10.data, 0, var7, var3, var10.data.length); 217 var3 += var10.data.length; 218 } 219 } 220 221 for (var8 = 0; var8 < var4.length; ++var8) 222 { 223 if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) 224 { 225 var10 = var4[var8].getBlocklightArray(); 226 System.arraycopy(var10.data, 0, var7, var3, var10.data.length); 227 var3 += var10.data.length; 228 } 229 } 230 231 if (!par0Chunk.worldObj.provider.hasNoSky) 232 { 233 for (var8 = 0; var8 < var4.length; ++var8) 234 { 235 if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && (par2 & 1 << var8) != 0) 236 { 237 var10 = var4[var8].getSkylightArray(); 238 System.arraycopy(var10.data, 0, var7, var3, var10.data.length); 239 var3 += var10.data.length; 240 } 241 } 242 } 243 244 if (var5 > 0) 245 { 246 for (var8 = 0; var8 < var4.length; ++var8) 247 { 248 if (var4[var8] != null && (!par1 || !var4[var8].isEmpty()) && var4[var8].getBlockMSBArray() != null && (par2 & 1 << var8) != 0) 249 { 250 var10 = var4[var8].getBlockMSBArray(); 251 System.arraycopy(var10.data, 0, var7, var3, var10.data.length); 252 var3 += var10.data.length; 253 } 254 } 255 } 256 257 if (par1) 258 { 259 byte[] var11 = par0Chunk.getBiomeArray(); 260 System.arraycopy(var11, 0, var7, var3, var11.length); 261 var3 += var11.length; 262 } 263 264 var6.field_74582_a = new byte[var3]; 265 System.arraycopy(var7, 0, var6.field_74582_a, 0, var3); 266 return var6; 267 } 268 269 @SideOnly(Side.CLIENT) 270 public byte[] func_73593_d() 271 { 272 return this.field_73596_g; 273 } 274 }