    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    }