    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    }