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 }