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 recievedID;
029        public static long recievedSize;
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                ++recievedID;
157                recievedSize += (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            ++recievedID;
167            recievedSize += (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, false, 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    }