private void MessageNewUserMsg()
        {
            Int32 messageStartOffset = parser.BitBuffer.CurrentByte;

            // read message
            Byte id = parser.BitBuffer.ReadByte();
            SByte length = parser.BitBuffer.ReadSByte();
            String name = parser.BitBuffer.ReadString(16);

            parser.AddUserMessage(id, length, name);

            // FIXME: clean this up
            if (!demo.ConvertNetworkProtocol() && name != "CDChallenge" && name != "CDSalt")
            {
                return;
            }

            if (demo.Game == null || demo.Game.UserMessages == null)
            {
                return;
            }

            Byte newId;

            if (demo.Game.UserMessages.ContainsKey(name))
            {
                newId = demo.Game.UserMessages[name];
            }
            else
            {
                // cheating death
                // TODO: probably should have a list of "bad" user messages to remove...
                // TODO: should remove these messages even when not converting network protocols
                if (name == "CDChallenge" || name == "CDSalt")
                {
                    // remove message
                    Int32 messageFinishOffset = parser.BitBuffer.CurrentByte;
                    parser.BitBuffer.SeekBytes(messageStartOffset - 1, SeekOrigin.Begin);
                    parser.BitBuffer.RemoveBytes(messageFinishOffset - messageStartOffset + 1); // +1 for message id
                    return;
                }

                // user message doesn't exist in CS 1.6. shouldn't happen, but meh...
                // TODO: use an id unused by compatibleUserMessageTable
                //newId = (Byte?)id;
                newId = firstFreeUserMessage;

                if (firstFreeUserMessage == 255)
                {
                    throw new NoFreeUserMessageException();
                }

                firstFreeUserMessage++;

                demo.Game.UserMessages.Add(name, newId);
            }

            BitWriter bitWriter = new BitWriter();
            bitWriter.WriteByte((Byte)newId);
            bitWriter.WriteSByte(length);
            bitWriter.WriteString(name, 16);

            // insert new message
            ReWriteMessage(messageStartOffset, bitWriter.Data);
        }
Exemple #2
0
        private void RefreshThread()
        {
            using (TimedUdpClient client = new TimedUdpClient())
            {
                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);

                mainWindowInterface.SetServerProperty(this, "Title", "Connecting to Server");
                mainWindowInterface.SetServerProperty(this, "State", StateEnum.Querying);

                // reset properties
                mainWindowInterface.SetServerProperty(this, "Ping", null);
                mainWindowInterface.SetServerProperty(this, "GameName", null);
                mainWindowInterface.SetServerProperty(this, "Map", null);
                mainWindowInterface.SetServerProperty(this, "NumSpectators", null);
                mainWindowInterface.SetServerProperty(this, "MaxSpectators", null);
                mainWindowInterface.SetServerProperty(this, "PasswordProtected", null);

                try
                {
                    DateTime connectTime = DateTime.Now;

                    // attempt to connect
                    Int32 colonIndex = address.IndexOf(':');
                    // what's the timeout???
                    client.Connect(address.Remove(colonIndex), Convert.ToInt32(address.Substring(colonIndex + 1)));

                    // update title as "connected"
                    mainWindowInterface.SetServerProperty(this, "Title", "Connected");

                    if (abortRefresh)
                    {
                        Common.AbortThread(Thread);
                    }

                    // send A2S_INFO
                    // -1 (int), A2S_INFO, "Source Engine Query" (string)
                    DateTime sendTime = DateTime.Now;
                    client.Send(new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, A2S_INFO, 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x00 });

                    // receive A2S_INFO reply
                    Byte[] infoReply = client.Receive(ref ipEndPoint);
                    if (infoReply == null)
                    {
                        throw new ApplicationException("Server not responding.");
                    }

                    // calculate ping
                    TimeSpan ping = DateTime.Now - connectTime;
                    mainWindowInterface.SetServerProperty(this, "Ping", ping.Milliseconds);

                    // parse A2S_INFO reply
                    ParseInfoQueryReply(infoReply);

                    if (client.Available > 0) // fuuuuuuckkkk yoooooouuu Vaaaaaaalllvvvveeee
                    {
                        client.Receive(ref ipEndPoint);
                    }

                    // send A2S_SERVERQUERY_GETCHALLENGE
                    // -1 (int), A2S_SERVERQUERY_GETCHALLENGE
                    /*client.Send(new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, A2S_SERVERQUERY_GETCHALLENGE });

                    // receive and parse A2S_SERVERQUERY_GETCHALLENGE reply
                    Byte[] serverQueryGetChallengeReply = client.Receive(ref ipEndPoint);
                    if (serverQueryGetChallengeReply == null)
                    {
                        throw new ApplicationException("Server ignored challenge.");
                    }*/

                    //Int32 challengeNumber = ParseServerQueryGetChallengeReply(serverQueryGetChallengeReply);
                    Int32 challengeNumber = -1;

                    while (true)
                    {
                        if (abortRefresh)
                        {
                            Common.AbortThread(Thread);
                        }

                        // send A2S_PLAYER
                        BitWriter bitWriter = new BitWriter();
                        bitWriter.WriteInt32(-1);
                        bitWriter.WriteByte(A2S_PLAYER);
                        bitWriter.WriteInt32(challengeNumber);
                        client.Send(bitWriter.Data);

                        // receive and parse A2S_PLAYER reply
                        Byte[] playerReply = client.Receive(ref ipEndPoint);
                        if (playerReply == null)
                        {
                            if (challengeNumber != -1)
                            {
                                // oh, it's a sourcetv server and valve are too incompetent to implement s2c_player
                                break;
                            }

                            throw new ApplicationException("Player query failed.");
                        }

                        // check for a challenge number (source servers)
                        BitBuffer bitBuffer = new BitBuffer(playerReply);

                        if (bitBuffer.ReadInt32() != -1)
                        {
                            throw new ApplicationException("Bad A2S_PLAYER reply");
                        }

                        Byte type = bitBuffer.ReadByte();

                        if (type == S2C_CHALLENGE)
                        {
                            challengeNumber = bitBuffer.ReadInt32();
                            continue;
                        }
                        else if (type == S2C_PLAYER)
                        {
                            ParsePlayerQueryReply(bitBuffer);
                        }
                        else
                        {
                            throw new ApplicationException(String.Format("Bad A2S_PLAYER type: {0}", type));
                        }

                        break;
                    }

                    mainWindowInterface.SetServerProperty(this, "State", StateEnum.Succeeded);
                }
                catch (ThreadAbortException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if (!abortRefresh)
                    {
                        mainWindowInterface.SetServerProperty(this, "Title", ex.Message);
                        mainWindowInterface.SetServerProperty(this, "State", StateEnum.Failed);
                    }
                }
                finally
                {
                    client.Close();
                }
            }
        }
        private void MessageDeltaPacketEntities()
        {
            if (!demo.ConvertNetworkProtocol() || demo.IsBetaSteam())
            {
                parser.MessageDeltaPacketEntities();
                return;
            }

            Int32 messageStartOffset = parser.BitBuffer.CurrentByte;
            BitWriter bitWriter = new BitWriter();

            // read message
            bitWriter.WriteUInt16(parser.BitBuffer.ReadUInt16()); // nEntities/maxEntities

            if (demo.NetworkProtocol <= 43)
            {
                parser.BitBuffer.Endian = BitBuffer.EndianType.Big;
            }

            bitWriter.WriteByte(parser.BitBuffer.ReadByte()); // delta sequence number

            UInt32 entityNumber = 0;

            while (true)
            {
                // check for footer
                UInt16 footer = parser.BitBuffer.ReadUInt16();

                if (footer == 0)
                {
                    bitWriter.WriteUInt16(footer);
                    break;
                }

                parser.BitBuffer.SeekBits(-16);

                // option bits
                Boolean removeEntity = parser.BitBuffer.ReadBoolean();
                bitWriter.WriteBoolean(removeEntity);
                Boolean absoluteEntityNumber = parser.BitBuffer.ReadBoolean();
                bitWriter.WriteBoolean(absoluteEntityNumber);

                // entity number
                if (absoluteEntityNumber)
                {
                    entityNumber = parser.BitBuffer.ReadUnsignedBits(11);
                    bitWriter.WriteUnsignedBits(entityNumber, 11);
                }
                else
                {
                    UInt32 deltaEntityNumber = parser.BitBuffer.ReadUnsignedBits(6);
                    bitWriter.WriteUnsignedBits(deltaEntityNumber, 6);
                    entityNumber += deltaEntityNumber;
                }

                if (!removeEntity)
                {
                    // entity type
                    Boolean custom = parser.BitBuffer.ReadBoolean();
                    bitWriter.WriteBoolean(custom);

                    if (demo.NetworkProtocol <= 43)
                    {
                        parser.BitBuffer.SeekBits(1); // unknown, always 0
                    }

                    String entityType = "entity_state_t";

                    if (entityNumber > 0 && entityNumber <= demo.MaxClients)
                    {
                        entityType = "entity_state_player_t";
                    }
                    else if (custom)
                    {
                        entityType = "custom_entity_state_t";
                    }

                    // delta compressed data
                    Byte[] bitmaskBytes;
                    HalfLifeDeltaStructure deltaDecoder = parser.GetDeltaStructure(entityType);
                    HalfLifeDelta deltaEntity = deltaDecoder.CreateDelta();
                    deltaDecoder.ReadDelta(parser.BitBuffer, deltaEntity, out bitmaskBytes);

                    if (demo.Game != null)
                    {
                        demo.Game.ConvertPacketEntititiesCallback(deltaEntity, entityType, demo.GameVersion);
                    }

                    deltaDecoder.WriteDelta(bitWriter, deltaEntity, bitmaskBytes);
                }
            }

            parser.BitBuffer.SkipRemainingBits();
            parser.BitBuffer.Endian = BitBuffer.EndianType.Little;

            // insert new message
            ReWriteMessage(messageStartOffset, bitWriter.Data);
        }
        public void ProcessFirstGameDataFrame(ref Byte[] frameData)
        {
            // A svc_director message preceeds svc_spawnbaseline in newer HLTV demos. The director message is used to initialise and reset the HUD. Since old HLTV demos omit this message, it can be added here (and set the perspective to first-person too).
            if (demo.Perspective != Demo.Perspectives.Hltv || haveParsedDirectorMessage)
            {
                return;
            }

            const Byte DRC_CMD_START = 1;
            const Byte DRC_CMD_MODE = 3;
            const Byte OBS_IN_EYE = 4;

            // Create a svc_director message to initialise the HUD.
            BitWriter directorMessage = new BitWriter();
            directorMessage.WriteByte((Byte)HalfLifeDemoParser.MessageId.svc_director);
            directorMessage.WriteByte(1); // length
            directorMessage.WriteByte(DRC_CMD_START);

            // Create a svc_director message to set the perspective to first-person.
            directorMessage.WriteByte((Byte)HalfLifeDemoParser.MessageId.svc_director);
            directorMessage.WriteByte(2); // length
            directorMessage.WriteByte(DRC_CMD_MODE);
            directorMessage.WriteByte(OBS_IN_EYE);

            // Insert the new messages.
            BitBuffer bitBuffer = new BitBuffer(frameData);
            bitBuffer.InsertBytes(directorMessage.Data);

            frameData = bitBuffer.Data;
        }
        public void WriteDelta(BitWriter bitWriter, HalfLifeDelta delta, Byte[] bitmaskBytes)
        {
            if (bitmaskBytes == null) // no bitmask bytes
            {
                bitWriter.WriteUnsignedBits(0, 3);
                return;
            }

            bitWriter.WriteUnsignedBits((UInt32)bitmaskBytes.Length, 3);

            for (Int32 i = 0; i < bitmaskBytes.Length; i++)
            {
                bitWriter.WriteByte(bitmaskBytes[i]);
            }

            for (Int32 i = 0; i < bitmaskBytes.Length; i++)
            {
                for (Int32 j = 0; j < 8; j++)
                {
                    Int32 index = j + i * 8;

                    if (index == entryList.Count)
                    {
                        return;
                    }

                    if ((bitmaskBytes[i] & (1 << j)) != 0)
                    {
                        WriteEntry(delta, bitWriter, entryList[index]);
                    }
                }
            }
        }
Exemple #6
0
        private void MessageDeltaPacketEntities()
        {
            if (!demo.ConvertNetworkProtocol() || demo.IsBetaSteam())
            {
                parser.MessageDeltaPacketEntities();
                return;
            }

            Int32     messageStartOffset = parser.BitBuffer.CurrentByte;
            BitWriter bitWriter          = new BitWriter();

            // read message
            bitWriter.WriteUInt16(parser.BitBuffer.ReadUInt16()); // nEntities/maxEntities

            if (demo.NetworkProtocol <= 43)
            {
                parser.BitBuffer.Endian = BitBuffer.EndianType.Big;
            }

            bitWriter.WriteByte(parser.BitBuffer.ReadByte()); // delta sequence number

            UInt32 entityNumber = 0;

            while (true)
            {
                // check for footer
                UInt16 footer = parser.BitBuffer.ReadUInt16();

                if (footer == 0)
                {
                    bitWriter.WriteUInt16(footer);
                    break;
                }

                parser.BitBuffer.SeekBits(-16);

                // option bits
                Boolean removeEntity = parser.BitBuffer.ReadBoolean();
                bitWriter.WriteBoolean(removeEntity);
                Boolean absoluteEntityNumber = parser.BitBuffer.ReadBoolean();
                bitWriter.WriteBoolean(absoluteEntityNumber);

                // entity number
                if (absoluteEntityNumber)
                {
                    entityNumber = parser.BitBuffer.ReadUnsignedBits(11);
                    bitWriter.WriteUnsignedBits(entityNumber, 11);
                }
                else
                {
                    UInt32 deltaEntityNumber = parser.BitBuffer.ReadUnsignedBits(6);
                    bitWriter.WriteUnsignedBits(deltaEntityNumber, 6);
                    entityNumber += deltaEntityNumber;
                }

                if (!removeEntity)
                {
                    // entity type
                    Boolean custom = parser.BitBuffer.ReadBoolean();
                    bitWriter.WriteBoolean(custom);

                    if (demo.NetworkProtocol <= 43)
                    {
                        parser.BitBuffer.SeekBits(1); // unknown, always 0
                    }

                    String entityType = "entity_state_t";

                    if (entityNumber > 0 && entityNumber <= demo.MaxClients)
                    {
                        entityType = "entity_state_player_t";
                    }
                    else if (custom)
                    {
                        entityType = "custom_entity_state_t";
                    }

                    // delta compressed data
                    Byte[] bitmaskBytes;
                    HalfLifeDeltaStructure deltaDecoder = parser.GetDeltaStructure(entityType);
                    HalfLifeDelta          deltaEntity  = deltaDecoder.CreateDelta();
                    deltaDecoder.ReadDelta(parser.BitBuffer, deltaEntity, out bitmaskBytes);

                    if (demo.Game != null)
                    {
                        demo.Game.ConvertPacketEntititiesCallback(deltaEntity, entityType, demo.GameVersion);
                    }

                    deltaDecoder.WriteDelta(bitWriter, deltaEntity, bitmaskBytes);
                }
            }

            parser.BitBuffer.SkipRemainingBits();
            parser.BitBuffer.Endian = BitBuffer.EndianType.Little;

            // insert new message
            ReWriteMessage(messageStartOffset, bitWriter.Data);
        }
Exemple #7
0
        private void MessageNewUserMsg()
        {
            Int32 messageStartOffset = parser.BitBuffer.CurrentByte;

            // read message
            Byte   id     = parser.BitBuffer.ReadByte();
            SByte  length = parser.BitBuffer.ReadSByte();
            String name   = parser.BitBuffer.ReadString(16);

            parser.AddUserMessage(id, length, name);

            // FIXME: clean this up
            if (!demo.ConvertNetworkProtocol() && name != "CDChallenge" && name != "CDSalt")
            {
                return;
            }

            if (demo.Game == null || demo.Game.UserMessages == null)
            {
                return;
            }

            Byte newId;

            if (demo.Game.UserMessages.ContainsKey(name))
            {
                newId = demo.Game.UserMessages[name];
            }
            else
            {
                // cheating death
                // TODO: probably should have a list of "bad" user messages to remove...
                // TODO: should remove these messages even when not converting network protocols
                if (name == "CDChallenge" || name == "CDSalt")
                {
                    // remove message
                    Int32 messageFinishOffset = parser.BitBuffer.CurrentByte;
                    parser.BitBuffer.SeekBytes(messageStartOffset - 1, SeekOrigin.Begin);
                    parser.BitBuffer.RemoveBytes(messageFinishOffset - messageStartOffset + 1); // +1 for message id
                    return;
                }

                // user message doesn't exist in CS 1.6. shouldn't happen, but meh...
                // TODO: use an id unused by compatibleUserMessageTable
                //newId = (Byte?)id;
                newId = firstFreeUserMessage;

                if (firstFreeUserMessage == 255)
                {
                    throw new NoFreeUserMessageException();
                }

                firstFreeUserMessage++;

                demo.Game.UserMessages.Add(name, newId);
            }

            BitWriter bitWriter = new BitWriter();

            bitWriter.WriteByte((Byte)newId);
            bitWriter.WriteSByte(length);
            bitWriter.WriteString(name, 16);

            // insert new message
            ReWriteMessage(messageStartOffset, bitWriter.Data);
        }