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 }