public void MessageNetSetConVar() { Int32 nConVars = bitBuffer.ReadByte(); for (Int32 i = 0; i < nConVars; i++) { bitBuffer.ReadString(); // name bitBuffer.ReadString(); // value } }
public void ReadDelta(BitBuffer bitBuffer, HalfLifeDelta delta, out Byte[] bitmaskBytes) { // read bitmask UInt32 nBitmaskBytes = bitBuffer.ReadUnsignedBits(3); // TODO: error check nBitmaskBytes against nEntries if (nBitmaskBytes == 0) { bitmaskBytes = null; return; } bitmaskBytes = new Byte[nBitmaskBytes]; for (Int32 i = 0; i < nBitmaskBytes; i++) { bitmaskBytes[i] = bitBuffer.ReadByte(); } for (Int32 i = 0; i < nBitmaskBytes; i++) { for (Int32 j = 0; j < 8; j++) { Int32 index = j + i * 8; if (index == entryList.Count) { return; } if ((bitmaskBytes[i] & (1 << j)) != 0) { Object value = ParseEntry(bitBuffer, entryList[index]); if (delta != null) { delta.SetEntryValue(index, value); } } } } }
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(); } } }
/// <summary> /// Parses S2C_CHALLENGE and returns the challenge number. /// </summary> /// <param name="data"></param> /// <returns></returns> private Int32 ParseServerQueryGetChallengeReply(Byte[] data) { BitBuffer bitBuffer = new BitBuffer(data); if (bitBuffer.ReadInt32() != -1) { throw new ApplicationException("Bad A2S_SERVERQUERY_GETCHALLENGE reply"); } Byte type = bitBuffer.ReadByte(); if (type != S2C_CHALLENGE) { throw new ApplicationException(String.Format("Bad A2S_SERVERQUERY_GETCHALLENGE type: {0}", type)); } return bitBuffer.ReadInt32(); }
/// <summary> /// Parses S2C_PLAYER. /// </summary> /// <param name="data"></param> /// <param name="si"></param> private void ParsePlayerQueryReply(BitBuffer bitBuffer) { Int32 nPlayers = bitBuffer.ReadByte(); for (Int32 i = 0; i < nPlayers; i++) { bitBuffer.SeekBytes(1); // skip index Player player = new Player(); player.Name = bitBuffer.ReadString(); player.Score = bitBuffer.ReadInt32(); Single time = bitBuffer.ReadSingle(); player.Time = (time == -1 ? "BOT" : Common.DurationString(time)); mainWindowInterface.AddPlayerToServer(this, player); } }
/// <summary> /// Parses S2C_INFO. /// </summary> /// <param name="data"></param> /// <param name="si"></param> private void ParseInfoQueryReply(Byte[] data) { BitBuffer bitBuffer = new BitBuffer(data); if (bitBuffer.ReadInt32() != -1) { throw new ApplicationException("Bad A2S_INFO reply"); } // read reply type Byte type = bitBuffer.ReadByte(); Boolean sourceEngine; if (type == S2C_INFO_SOURCE) { sourceEngine = true; } else if (type == S2C_INFO_GOLDSRC) { sourceEngine = false; } else { throw new ApplicationException(String.Format("Bad A2S_INFO type: {0}", type)); } mainWindowInterface.SetServerProperty(this, "SourceEngine", sourceEngine); // read the rest if (!sourceEngine) { bitBuffer.ReadString(); //si.Address = bitBuffer.ReadString(); // resolved hostname } else { bitBuffer.SeekBytes(1); // network version } mainWindowInterface.SetServerProperty(this, "Title", bitBuffer.ReadString()); // server name mainWindowInterface.SetServerProperty(this, "Map", bitBuffer.ReadString()); // map String gameFolder = bitBuffer.ReadString(); mainWindowInterface.SetServerProperty(this, "GameFolder", gameFolder); // game folder String gameName = bitBuffer.ReadString(); // game name if (sourceEngine) { bitBuffer.SeekBytes(2); // app id } mainWindowInterface.SetServerProperty(this, "NumSpectators", bitBuffer.ReadByte()); // num spectators mainWindowInterface.SetServerProperty(this, "MaxSpectators", bitBuffer.ReadByte()); // max spectators bitBuffer.SeekBytes(1); // goldsrc: network version, source: num bots bitBuffer.SeekBytes(1); // dedicated bitBuffer.SeekBytes(1); // os mainWindowInterface.SetServerProperty(this, "PasswordProtected", (bitBuffer.ReadByte() == 1)); // determine game name Game game = GameManager.Find((sourceEngine ? Game.Engines.Source : Game.Engines.HalfLife), gameFolder); if (game == null) { mainWindowInterface.SetServerProperty(this, "GameName", gameName); } else { mainWindowInterface.SetServerProperty(this, "GameName", game.Name); } }
public void ReadDelta(BitBuffer bitBuffer, HalfLifeDelta delta, out Byte[] bitmaskBytes) { // read bitmask UInt32 nBitmaskBytes = bitBuffer.ReadUnsignedBits(3); // TODO: error check nBitmaskBytes against nEntries if (nBitmaskBytes == 0) { bitmaskBytes = null; return; } bitmaskBytes = new Byte[nBitmaskBytes]; for (Int32 i = 0; i < nBitmaskBytes; i++) { bitmaskBytes[i] = bitBuffer.ReadByte(); } for (Int32 i = 0; i < nBitmaskBytes; i++) { for (Int32 j = 0; j < 8; j++) { Int32 index = j + i * 8; if (index == entryList.Count) { return; } if ((bitmaskBytes[i] & (1 << j)) != 0) { Object value = ParseEntry(bitBuffer, entryList[index]); if (delta != null) { delta.SetEntryValue(index, value); } } } } }
public void ParseGameDataMessages(Byte[] frameData, Function <Byte, Byte> userMessageCallback) { Int64 gameDataStartOffset = fileStream.Position - frameData.Length; // read game data frame into memory bitBuffer = new BitBuffer(frameData); readingGameData = true; try { BeginMessageLog(gameDataStartOffset, frameData); // start parsing messages while (true) { Int32 messageFrameOffset = bitBuffer.CurrentByte; Byte messageId = bitBuffer.ReadByte(); String messageName = Enum.GetName(typeof(MessageId), messageId); if (messageName == null) // a user message, presumably { messageName = FindMessageIdString(messageId); } LogMessage(messageId, messageName, messageFrameOffset); MessageHandler messageHandler = FindMessageHandler(messageId); // Handle the conversion of user message id's. // Used by demo writing to convert to the current network protocol. if (messageId > 64 && userMessageCallback != null) { Byte newMessageId = userMessageCallback(messageId); if (newMessageId != messageId) { // write the new id to the bitbuffer bitBuffer.SeekBytes(-1); bitBuffer.RemoveBytes(1); bitBuffer.InsertBytes(new Byte[] { newMessageId }); } } // unknown message if (messageHandler == null) { throw new ApplicationException(String.Format("Cannot find message handler for message id \"[{0}] {1}\"", messageId, messageName)); } // callback takes priority over length if (messageHandler.Callback != null) { messageHandler.Callback(); } else if (messageHandler.Length != -1) { Seek(messageHandler.Length); } else { // user messages if (messageId >= 64) { // All non-engine user messages start with a byte that is the number of bytes in the message remaining. Byte length = bitBuffer.ReadByte(); Seek(length); } else { throw new ApplicationException(String.Format("Unknown message id \"{0}\"", messageId)); } } // Check if we've reached the end of the frame, or if any of the messages have called SkipGameDataFrame (readingGameData will be false). if (bitBuffer.CurrentByte == bitBuffer.Length || !readingGameData) { break; } } } finally { readingGameData = false; } }
public Int32 FindUserMessageLength(String name) { // shouldn't return null, since this method should be called from a message handler, and that message handler couldn't be called if there wasn't a UserMessage entry UserMessage userMessage = (UserMessage)userMessageTable[name]; if (userMessage.Length == -1) { // if svc_newusermsg length is -1, first byte is length return(bitBuffer.ReadByte()); } return(userMessage.Length); }