public void MessageCreateStringTable()
        {
            bitBuffer.ReadString(); // table name

            UInt32 maxEntries = bitBuffer.ReadUnsignedBits(16);
            UInt32 nEntries   = bitBuffer.ReadUnsignedBits(Common.LogBase2((Int32)maxEntries) + 1);

            UInt32 nBits = bitBuffer.ReadUnsignedBits(20);

            if (bitBuffer.ReadBoolean()) // userdata bit
            {
                bitBuffer.SeekBits(12);  // "user data size"
                bitBuffer.SeekBits(4);   // "user data bits"
            }

            bitBuffer.SeekBits((Int32)nBits);

            if (demo.NetworkProtocol >= 15)
            {
                bitBuffer.SeekBits(1);
            }
        }
        private void MessageCreateStringTable()
        {
            String tableName   = parser.BitBuffer.ReadString();
            Int32  maxEntries  = (Int32)parser.BitBuffer.ReadUnsignedBits(16); // TODO: sanity check on maxEntries?
            Int32  entriesBits = Common.LogBase2(maxEntries) + 1;
            Int32  nEntries    = (Int32)parser.BitBuffer.ReadUnsignedBits(entriesBits);
            Int32  nBits       = (Int32)parser.BitBuffer.ReadUnsignedBits(20);

            UInt32 userDataSize = 0;

            if (parser.BitBuffer.ReadBoolean()) // userdata bit
            {
                userDataSize = parser.BitBuffer.ReadUnsignedBits(12);
                parser.BitBuffer.SeekBits(4); // "user data bits"
            }

            if (tableName == "userinfo")
            {
                userInfoStringTableIndex          = currentStringTableIndex;
                userInfoStringTableEntryIndexBits = entriesBits;

                for (int i = 0; i < nEntries; i++)
                {
                    parser.BitBuffer.SeekBits(2);       // unknown

                    if (parser.BitBuffer.ReadBoolean()) // delta bit
                    {
                        parser.BitBuffer.SeekBits(10);  // 5 bits history index, 5 bits history length
                        parser.BitBuffer.ReadString();  // delta entry
                    }
                    else
                    {
                        parser.BitBuffer.ReadString(); // entry
                    }

                    if (userDataSize == 0)                  // ??? could be wrong
                    {
                        if (parser.BitBuffer.ReadBoolean()) // userdata bit
                        {
                            // parse userinfo
                            UInt32 nUserDataBytes = parser.BitBuffer.ReadUnsignedBits(12);

                            if (nUserDataBytes > 0)
                            {
                                Int32 currentOffset = parser.BitBuffer.CurrentBit;
                                ParseUserInfo();
                                parser.BitBuffer.SeekBits(currentOffset + (Int32)nUserDataBytes * 8, SeekOrigin.Begin);
                            }

                            if (demo.NetworkProtocol >= 14)
                            {
                                parser.BitBuffer.SeekBits(2); // unknown
                            }
                        }
                    }
                    else
                    {
                        parser.BitBuffer.SeekBits(3); // unknown
                    }
                }
            }
            else
            {
                parser.BitBuffer.SeekBits(nBits);
            }

            currentStringTableIndex++;
        }