001 package net.minecraft.src; 002 003 import java.io.DataInputStream; 004 import java.io.DataOutputStream; 005 import java.io.EOFException; 006 import java.io.IOException; 007 import java.net.Socket; 008 import java.util.HashMap; 009 import java.util.HashSet; 010 import java.util.Map; 011 import java.util.Set; 012 013 public abstract class Packet 014 { 015 /** Maps packet id to packet class */ 016 public static IntHashMap packetIdToClassMap = new IntHashMap(); 017 018 /** Maps packet class to packet id */ 019 private static Map packetClassToIdMap = new HashMap(); 020 021 /** List of the client's packet IDs. */ 022 private static Set clientPacketIdList = new HashSet(); 023 024 /** List of the server's packet IDs. */ 025 private static Set serverPacketIdList = new HashSet(); 026 027 /** the system time in milliseconds when this packet was created. */ 028 public final long creationTimeMillis = System.currentTimeMillis(); 029 public static long receivedID; 030 public static long receivedSize; 031 032 /** Assumed to be sequential by the profiler. */ 033 public static long sentID; 034 public static long sentSize; 035 036 /** 037 * Only true for Packet51MapChunk, Packet52MultiBlockChange, Packet53BlockChange and Packet59ComplexEntity. Used to 038 * separate them into a different send queue. 039 */ 040 public boolean isChunkDataPacket = false; 041 042 /** 043 * Adds a two way mapping between the packet ID and packet class. 044 */ 045 static void addIdClassMapping(int par0, boolean par1, boolean par2, Class par3Class) 046 { 047 if (packetIdToClassMap.containsItem(par0)) 048 { 049 throw new IllegalArgumentException("Duplicate packet id:" + par0); 050 } 051 else if (packetClassToIdMap.containsKey(par3Class)) 052 { 053 throw new IllegalArgumentException("Duplicate packet class:" + par3Class); 054 } 055 else 056 { 057 packetIdToClassMap.addKey(par0, par3Class); 058 packetClassToIdMap.put(par3Class, Integer.valueOf(par0)); 059 060 if (par1) 061 { 062 clientPacketIdList.add(Integer.valueOf(par0)); 063 } 064 065 if (par2) 066 { 067 serverPacketIdList.add(Integer.valueOf(par0)); 068 } 069 } 070 } 071 072 /** 073 * Returns a new instance of the specified Packet class. 074 */ 075 public static Packet getNewPacket(int par0) 076 { 077 try 078 { 079 Class var1 = (Class)packetIdToClassMap.lookup(par0); 080 return var1 == null ? null : (Packet)var1.newInstance(); 081 } 082 catch (Exception var2) 083 { 084 var2.printStackTrace(); 085 System.out.println("Skipping packet with id " + par0); 086 return null; 087 } 088 } 089 090 /** 091 * Writes a byte array to the DataOutputStream 092 */ 093 public static void writeByteArray(DataOutputStream par0DataOutputStream, byte[] par1ArrayOfByte) throws IOException 094 { 095 par0DataOutputStream.writeShort(par1ArrayOfByte.length); 096 par0DataOutputStream.write(par1ArrayOfByte); 097 } 098 099 /** 100 * the first short in the stream indicates the number of bytes to read 101 */ 102 public static byte[] readBytesFromStream(DataInputStream par0DataInputStream) throws IOException 103 { 104 short var1 = par0DataInputStream.readShort(); 105 106 if (var1 < 0) 107 { 108 throw new IOException("Key was smaller than nothing! Weird key!"); 109 } 110 else 111 { 112 byte[] var2 = new byte[var1]; 113 par0DataInputStream.read(var2); 114 return var2; 115 } 116 } 117 118 /** 119 * Returns the ID of this packet. 120 */ 121 public final int getPacketId() 122 { 123 return ((Integer)packetClassToIdMap.get(this.getClass())).intValue(); 124 } 125 126 /** 127 * Read a packet, prefixed by its ID, from the data stream. 128 */ 129 public static Packet readPacket(DataInputStream par0DataInputStream, boolean par1, Socket par2Socket) throws IOException 130 { 131 boolean var3 = false; 132 Packet var4 = null; 133 int var5 = par2Socket.getSoTimeout(); 134 int var8; 135 136 try 137 { 138 var8 = par0DataInputStream.read(); 139 140 if (var8 == -1) 141 { 142 return null; 143 } 144 145 if (par1 && !serverPacketIdList.contains(Integer.valueOf(var8)) || !par1 && !clientPacketIdList.contains(Integer.valueOf(var8))) 146 { 147 throw new IOException("Bad packet id " + var8); 148 } 149 150 var4 = getNewPacket(var8); 151 152 if (var4 == null) 153 { 154 throw new IOException("Bad packet id " + var8); 155 } 156 157 if (var4 instanceof Packet254ServerPing) 158 { 159 par2Socket.setSoTimeout(1500); 160 } 161 162 var4.readPacketData(par0DataInputStream); 163 ++receivedID; 164 receivedSize += (long)var4.getPacketSize(); 165 } 166 catch (EOFException var7) 167 { 168 System.out.println("Reached end of stream"); 169 return null; 170 } 171 172 PacketCount.countPacket(var8, (long)var4.getPacketSize()); 173 ++receivedID; 174 receivedSize += (long)var4.getPacketSize(); 175 par2Socket.setSoTimeout(var5); 176 return var4; 177 } 178 179 /** 180 * Writes a packet, prefixed by its ID, to the data stream. 181 */ 182 public static void writePacket(Packet par0Packet, DataOutputStream par1DataOutputStream) throws IOException 183 { 184 par1DataOutputStream.write(par0Packet.getPacketId()); 185 par0Packet.writePacketData(par1DataOutputStream); 186 ++sentID; 187 sentSize += (long)par0Packet.getPacketSize(); 188 } 189 190 /** 191 * Writes a String to the DataOutputStream 192 */ 193 public static void writeString(String par0Str, DataOutputStream par1DataOutputStream) throws IOException 194 { 195 if (par0Str.length() > 32767) 196 { 197 throw new IOException("String too big"); 198 } 199 else 200 { 201 par1DataOutputStream.writeShort(par0Str.length()); 202 par1DataOutputStream.writeChars(par0Str); 203 } 204 } 205 206 /** 207 * Reads a string from a packet 208 */ 209 public static String readString(DataInputStream par0DataInputStream, int par1) throws IOException 210 { 211 short var2 = par0DataInputStream.readShort(); 212 213 if (var2 > par1) 214 { 215 throw new IOException("Received string length longer than maximum allowed (" + var2 + " > " + par1 + ")"); 216 } 217 else if (var2 < 0) 218 { 219 throw new IOException("Received string length is less than zero! Weird string!"); 220 } 221 else 222 { 223 StringBuilder var3 = new StringBuilder(); 224 225 for (int var4 = 0; var4 < var2; ++var4) 226 { 227 var3.append(par0DataInputStream.readChar()); 228 } 229 230 return var3.toString(); 231 } 232 } 233 234 /** 235 * Abstract. Reads the raw packet data from the data stream. 236 */ 237 public abstract void readPacketData(DataInputStream var1) throws IOException; 238 239 /** 240 * Abstract. Writes the raw packet data to the data stream. 241 */ 242 public abstract void writePacketData(DataOutputStream var1) throws IOException; 243 244 /** 245 * Passes this Packet on to the NetHandler for processing. 246 */ 247 public abstract void processPacket(NetHandler var1); 248 249 /** 250 * Abstract. Return the size of the packet (not counting the header). 251 */ 252 public abstract int getPacketSize(); 253 254 /** 255 * only false for the abstract Packet class, all real packets return true 256 */ 257 public boolean isRealPacket() 258 { 259 return false; 260 } 261 262 /** 263 * eg return packet30entity.entityId == entityId; WARNING : will throw if you compare a packet to a different packet 264 * class 265 */ 266 public boolean containsSameEntityIDAs(Packet par1Packet) 267 { 268 return false; 269 } 270 271 /** 272 * if this returns false, processPacket is deffered for processReadPackets to handle 273 */ 274 public boolean isWritePacket() 275 { 276 return false; 277 } 278 279 public String toString() 280 { 281 String var1 = this.getClass().getSimpleName(); 282 return var1; 283 } 284 285 /** 286 * Reads a ItemStack from the InputStream 287 */ 288 public static ItemStack readItemStack(DataInputStream par0DataInputStream) throws IOException 289 { 290 ItemStack var1 = null; 291 short var2 = par0DataInputStream.readShort(); 292 293 if (var2 >= 0) 294 { 295 byte var3 = par0DataInputStream.readByte(); 296 short var4 = par0DataInputStream.readShort(); 297 var1 = new ItemStack(var2, var3, var4); 298 var1.stackTagCompound = readNBTTagCompound(par0DataInputStream); 299 } 300 301 return var1; 302 } 303 304 /** 305 * Writes the ItemStack's ID (short), then size (byte), then damage. (short) 306 */ 307 public static void writeItemStack(ItemStack par0ItemStack, DataOutputStream par1DataOutputStream) throws IOException 308 { 309 if (par0ItemStack == null) 310 { 311 par1DataOutputStream.writeShort(-1); 312 } 313 else 314 { 315 par1DataOutputStream.writeShort(par0ItemStack.itemID); 316 par1DataOutputStream.writeByte(par0ItemStack.stackSize); 317 par1DataOutputStream.writeShort(par0ItemStack.getItemDamage()); 318 NBTTagCompound var2 = null; 319 320 if (par0ItemStack.getItem().isDamageable() || par0ItemStack.getItem().getShareTag()) 321 { 322 var2 = par0ItemStack.stackTagCompound; 323 } 324 325 writeNBTTagCompound(var2, par1DataOutputStream); 326 } 327 } 328 329 /** 330 * Reads a compressed NBTTagCompound from the InputStream 331 */ 332 public static NBTTagCompound readNBTTagCompound(DataInputStream par0DataInputStream) throws IOException 333 { 334 short var1 = par0DataInputStream.readShort(); 335 336 if (var1 < 0) 337 { 338 return null; 339 } 340 else 341 { 342 byte[] var2 = new byte[var1]; 343 par0DataInputStream.readFully(var2); 344 return CompressedStreamTools.decompress(var2); 345 } 346 } 347 348 /** 349 * Writes a compressed NBTTagCompound to the OutputStream 350 */ 351 protected static void writeNBTTagCompound(NBTTagCompound par0NBTTagCompound, DataOutputStream par1DataOutputStream) throws IOException 352 { 353 if (par0NBTTagCompound == null) 354 { 355 par1DataOutputStream.writeShort(-1); 356 } 357 else 358 { 359 byte[] var2 = CompressedStreamTools.compress(par0NBTTagCompound); 360 par1DataOutputStream.writeShort((short)var2.length); 361 par1DataOutputStream.write(var2); 362 } 363 } 364 365 static 366 { 367 addIdClassMapping(0, true, true, Packet0KeepAlive.class); 368 addIdClassMapping(1, true, true, Packet1Login.class); 369 addIdClassMapping(2, false, true, Packet2ClientProtocol.class); 370 addIdClassMapping(3, true, true, Packet3Chat.class); 371 addIdClassMapping(4, true, false, Packet4UpdateTime.class); 372 addIdClassMapping(5, true, false, Packet5PlayerInventory.class); 373 addIdClassMapping(6, true, false, Packet6SpawnPosition.class); 374 addIdClassMapping(7, false, true, Packet7UseEntity.class); 375 addIdClassMapping(8, true, false, Packet8UpdateHealth.class); 376 addIdClassMapping(9, true, true, Packet9Respawn.class); 377 addIdClassMapping(10, true, true, Packet10Flying.class); 378 addIdClassMapping(11, true, true, Packet11PlayerPosition.class); 379 addIdClassMapping(12, true, true, Packet12PlayerLook.class); 380 addIdClassMapping(13, true, true, Packet13PlayerLookMove.class); 381 addIdClassMapping(14, false, true, Packet14BlockDig.class); 382 addIdClassMapping(15, false, true, Packet15Place.class); 383 addIdClassMapping(16, false, true, Packet16BlockItemSwitch.class); 384 addIdClassMapping(17, true, false, Packet17Sleep.class); 385 addIdClassMapping(18, true, true, Packet18Animation.class); 386 addIdClassMapping(19, false, true, Packet19EntityAction.class); 387 addIdClassMapping(20, true, false, Packet20NamedEntitySpawn.class); 388 addIdClassMapping(21, true, false, Packet21PickupSpawn.class); 389 addIdClassMapping(22, true, false, Packet22Collect.class); 390 addIdClassMapping(23, true, false, Packet23VehicleSpawn.class); 391 addIdClassMapping(24, true, false, Packet24MobSpawn.class); 392 addIdClassMapping(25, true, false, Packet25EntityPainting.class); 393 addIdClassMapping(26, true, false, Packet26EntityExpOrb.class); 394 addIdClassMapping(28, true, false, Packet28EntityVelocity.class); 395 addIdClassMapping(29, true, false, Packet29DestroyEntity.class); 396 addIdClassMapping(30, true, false, Packet30Entity.class); 397 addIdClassMapping(31, true, false, Packet31RelEntityMove.class); 398 addIdClassMapping(32, true, false, Packet32EntityLook.class); 399 addIdClassMapping(33, true, false, Packet33RelEntityMoveLook.class); 400 addIdClassMapping(34, true, false, Packet34EntityTeleport.class); 401 addIdClassMapping(35, true, false, Packet35EntityHeadRotation.class); 402 addIdClassMapping(38, true, false, Packet38EntityStatus.class); 403 addIdClassMapping(39, true, false, Packet39AttachEntity.class); 404 addIdClassMapping(40, true, false, Packet40EntityMetadata.class); 405 addIdClassMapping(41, true, false, Packet41EntityEffect.class); 406 addIdClassMapping(42, true, false, Packet42RemoveEntityEffect.class); 407 addIdClassMapping(43, true, false, Packet43Experience.class); 408 addIdClassMapping(51, true, false, Packet51MapChunk.class); 409 addIdClassMapping(52, true, false, Packet52MultiBlockChange.class); 410 addIdClassMapping(53, true, false, Packet53BlockChange.class); 411 addIdClassMapping(54, true, false, Packet54PlayNoteBlock.class); 412 addIdClassMapping(55, true, false, Packet55BlockDestroy.class); 413 addIdClassMapping(56, true, false, Packet56MapChunks.class); 414 addIdClassMapping(60, true, false, Packet60Explosion.class); 415 addIdClassMapping(61, true, false, Packet61DoorChange.class); 416 addIdClassMapping(62, true, false, Packet62LevelSound.class); 417 addIdClassMapping(70, true, false, Packet70GameEvent.class); 418 addIdClassMapping(71, true, false, Packet71Weather.class); 419 addIdClassMapping(100, true, false, Packet100OpenWindow.class); 420 addIdClassMapping(101, true, true, Packet101CloseWindow.class); 421 addIdClassMapping(102, false, true, Packet102WindowClick.class); 422 addIdClassMapping(103, true, false, Packet103SetSlot.class); 423 addIdClassMapping(104, true, false, Packet104WindowItems.class); 424 addIdClassMapping(105, true, false, Packet105UpdateProgressbar.class); 425 addIdClassMapping(106, true, true, Packet106Transaction.class); 426 addIdClassMapping(107, true, true, Packet107CreativeSetSlot.class); 427 addIdClassMapping(108, false, true, Packet108EnchantItem.class); 428 addIdClassMapping(130, true, true, Packet130UpdateSign.class); 429 addIdClassMapping(131, true, true, Packet131MapData.class); 430 addIdClassMapping(132, true, false, Packet132TileEntityData.class); 431 addIdClassMapping(200, true, false, Packet200Statistic.class); 432 addIdClassMapping(201, true, false, Packet201PlayerInfo.class); 433 addIdClassMapping(202, true, true, Packet202PlayerAbilities.class); 434 addIdClassMapping(203, true, true, Packet203AutoComplete.class); 435 addIdClassMapping(204, false, true, Packet204ClientInfo.class); 436 addIdClassMapping(205, false, true, Packet205ClientCommand.class); 437 addIdClassMapping(250, true, true, Packet250CustomPayload.class); 438 addIdClassMapping(252, true, true, Packet252SharedKey.class); 439 addIdClassMapping(253, true, false, Packet253ServerAuthData.class); 440 addIdClassMapping(254, false, true, Packet254ServerPing.class); 441 addIdClassMapping(255, true, true, Packet255KickDisconnect.class); 442 } 443 }