public void Seek(Int64 offset, SeekOrigin origin) { if (readingGameData) { Debug.Assert(offset <= Int32.MaxValue); bitBuffer.SeekBytes((Int32)offset, origin); } else { fileStream.Seek(offset, origin); } }
/// <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 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; } }