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