示例#1
0
        private static int findMatchStartRound(FileStream fileStream)
        {
            int result = 0;
            using (var parser = new DemoParser(fileStream))
            {
                parser.ParseHeader();
                int roundNumber = 0;

                parser.MatchStarted += (sender, e) =>
                {
                    if (roundNumber <= 16)
                    {
                        roundNumber = 0;
                        result++;
                    }
                };

                parser.RoundEnd += (object sender, RoundEndedEventArgs e) =>
                {
                    roundNumber++;
                };

                parser.ParseToEnd();
            }

            Console.WriteLine("Match starts at round number " + result);
            return result;
        }
示例#2
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            while (!bitstream.ChunkFinished) {
                var desc = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;
                if (wireType != 0)
                    throw new InvalidDataException();

                var val = (uint)bitstream.ReadProtobufVarInt();

                switch (fieldnum) {
                case 1:
                    Tick = val;
                    break;
                case 4:
                    HostComputationTime = val;
                    break;
                case 5:
                    HostComputationTimeStdDeviation = val;
                    break;
                case 6:
                    HostFramestartTimeStdDeviation = val;
                    break;
                default:
                    // silently drop
                    break;
                }
            }

            parser.IngameTick = (int)Tick;
        }
		public EseaAnalyzer(Demo demo)
		{
			Parser = new DemoParser(File.OpenRead(demo.Path));
			// Reset to have update on UI
			demo.ResetStats();
			Demo = demo;
			RegisterEvents();
		}
		public EbotAnalyzer(Demo demo)
		{
			Parser = new DemoParser(File.OpenRead(demo.Path));
			// Reset to have update on UI
			demo.ResetStats();
			Demo = demo;
			RegisterEvents();
			IsMatchStarted = true;
		}
示例#5
0
		public void Parse(IBitStream bitstream, DemoParser parser)
		{
			while (!bitstream.ChunkFinished) {
				var desc = bitstream.ReadProtobufVarInt();
				var wireType = desc & 7;
				var fieldnum = desc >> 3;

				if (wireType == 2) {
					if (fieldnum == 1) {
						Name = bitstream.ReadProtobufString();
						continue;
					} else if (fieldnum == 8) {
						// String data is special.
						// We'll simply hope that gaben is nice and sends
						// string_data last, just like he should.
						var len = bitstream.ReadProtobufVarInt();
						bitstream.BeginChunk(len * 8);
						DemoInfo.DP.Handler.CreateStringTableUserInfoHandler.Apply(this, bitstream, parser);
						bitstream.EndChunk();
						if (!bitstream.ChunkFinished)
							throw new NotImplementedException("Lord Gaben wasn't nice to us :/");
						break;
					} else
						throw new InvalidDataException("yes I know we should drop this but we" +
							"probably want to know that they added a new big field");
				}

				if (wireType != 0)
					throw new InvalidDataException();

				var val = bitstream.ReadProtobufVarInt();

				switch (fieldnum) {
				case 2:
					MaxEntries = val;
					break;
				case 3:
					NumEntries = val;
					break;
				case 4:
					_UserDataFixedSize = val;
					break;
				case 5:
					UserDataSize = val;
					break;
				case 6:
					UserDataSizeBits = val;
					break;
				case 7:
					Flags = val;
					break;
				default:
					// silently drop
					break;
				}
			}
		}
示例#6
0
		public void Parse(IBitStream bitstream, DemoParser parser)
		{
			while (!bitstream.ChunkFinished) {
				var desc = bitstream.ReadProtobufVarInt();
				var wireType = desc & 7;
				var fieldnum = desc >> 3;

				if ((fieldnum == 7) && (wireType == 2)) {
					// Entity data is special.
					// We'll simply hope that gaben is nice and sends
					// entity_data last, just like he should.

					var len = bitstream.ReadProtobufVarInt();
					bitstream.BeginChunk(len * 8);
					DemoInfo.DP.Handler.PacketEntitesHandler.Apply(this, bitstream, parser);
					bitstream.EndChunk();
					if (!bitstream.ChunkFinished)
						throw new NotImplementedException("Lord Gaben wasn't nice to us :/");
					break;
				}

				if (wireType != 0)
					throw new InvalidDataException();

				var val = bitstream.ReadProtobufVarInt();

				switch (fieldnum) {
				case 1:
					MaxEntries = val;
					break;
				case 2:
					UpdatedEntries = val;
					break;
				case 3:
					_IsDelta = val;
					break;
				case 4:
					_UpdateBaseline = val;
					break;
				case 5:
					Baseline = val;
					break;
				case 6:
					DeltaFrom = val;
					break;
				default:
					// silently drop
					break;
				}
			}
		}
示例#7
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            while (!bitstream.ChunkFinished)
            {
                var desc     = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;

                if ((wireType == 2) && (fieldnum == 3))
                {
                    // String data is special.
                    // We'll simply hope that gaben is nice and sends
                    // string_data last, just like he should.
                    var len = bitstream.ReadProtobufVarInt();
                    bitstream.BeginChunk(len * 8);
                    DemoInfo.DP.Handler.UpdateStringTableUserInfoHandler.Apply(this, bitstream, parser);
                    bitstream.EndChunk();
                    if (!bitstream.ChunkFinished)
                    {
                        throw new NotImplementedException("Lord Gaben wasn't nice to us :/");
                    }
                    break;
                }

                if (wireType != 0)
                {
                    throw new Exception();
                }

                var val = bitstream.ReadProtobufVarInt();

                switch (fieldnum)
                {
                case 1:
                    TableId = val;
                    break;

                case 2:
                    NumChangedEntries = val;
                    break;

                default:
                    // silently drop
                    break;
                }
            }
        }
示例#8
0
 public Match Parse(FileInfo fileInfo)
 {
     _Match.DemoName = fileInfo.Name;
     using (var stream = new FileStream(fileInfo.FullName, FileMode.Open))
     {
         var parser = new DemoInfo.DemoParser(stream);
         parser.MatchStarted += OnMatchStarted;
         parser.PlayerKilled += OnPlayerKilled;
         parser.PlayerTeam   += OnPlayerTeam;
         parser.RoundEnd     += OnRoundEnd;
         parser.ParseHeader();
         _Match.Map = parser.Map;
         parser.ParseToEnd();
         RemoveSpectators();
     }
     return(_Match);
 }
示例#9
0
        public Program(DemoParser parser)
        {
            this.parser = parser;

            parser.RoundEnd += (object sender, RoundEndedEventArgs e) => {
                // The reason I'm doing this after tick_done is that
                // entity-updates only come in the same tick as round_end
                // comes, meaning the score-update might not be transmitted yet
                // which would be sad - we always want the current score!
                // so we wait 1 second.

                roundEndedCount = 1;
            };

            parser.TickDone += (object sender, TickDoneEventArgs e) => {
                if (roundEndedCount == 0)
                    return;

                roundEndedCount++;

                // Wait twice the tickrate of the demo (~2 seconds) to make sure the
                // screen has been updated. I *LOVE* demo files :)
                if (roundEndedCount < parser.TickRate * 2)
                {
                    return;
                }

                roundEndedCount = 0;

                if(i == 0)
                {
                    Console.WriteLine("------------------------------------------------------------");

                    Console.WriteLine("Round {0}, CT: {1}, T: {2}", ++i, parser.CTScore, parser.TScore);
                    Console.WriteLine("Ts\t" + parser.TClanName);
                    Console.WriteLine("CTs\t" + parser.CTClanName);

                    Console.WriteLine();

                    //DatabaseConnection connection = new DatabaseConnection();
                    //connection.addTeam(parser.TClanName);
                    //connection.addTeam(parser.CTClanName);
                }
            };
        }
        public static void GenerateFrags(DemoParser parser)
        {
            parser.ParseHeader ();

            // Make a print on round-start so you can see the actual frags per round.
            parser.RoundStart += (sender, e) => Console.WriteLine ("New Round, Current Score: T {0} : {1} CT", parser.TScore, parser.CTScore);

            parser.PlayerKilled += (sender, e) => {
                if(e.Killer == null) {
                    // The player has murdered himself (falling / own nade / ...)
                    Console.WriteLine("<World><0><None>");
                } else {
                    Console.Write("<{0}><{1}><{2}>", e.Killer.Name, e.Killer.SteamID, ShortTeam(e.Killer.Team));
                }

                if(e.Assister == null) {
                    // nothing
                } else {
                    Console.Write(" + <{0}><{1}><{2}>", e.Assister.Name, e.Assister.SteamID, ShortTeam(e.Assister.Team));
                }

                Console.Write(" [{0}]", e.Weapon.Weapon);

                if(e.Headshot) {
                    Console.Write("[HS]");
                }

                if(e.PenetratedObjects > 0) {
                    Console.Write("[Wall]");
                }

                Console.Write(" ");

                Console.Write("<{0}><{1}><{2}>", e.DeathPerson.Name, e.DeathPerson.SteamID, ShortTeam(e.DeathPerson.Team));

                Console.WriteLine();
            };

            parser.ParseToEnd ();
        }
示例#11
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            while (!bitstream.ChunkFinished)
            {
                var desc     = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;
                if (wireType != 0)
                {
                    throw new Exception();
                }

                var val = (uint)bitstream.ReadProtobufVarInt();

                switch (fieldnum)
                {
                case 1:
                    Tick = val;
                    break;

                case 4:
                    HostComputationTime = val;
                    break;

                case 5:
                    HostComputationTimeStdDeviation = val;
                    break;

                case 6:
                    HostFramestartTimeStdDeviation = val;
                    break;

                default:
                    // silently drop
                    break;
                }
            }

            parser.IngameTick = (int)Tick;
        }
示例#12
0
        public static void Main(string[] args)
        {
            using (var input = File.OpenRead(args[0]))
            {
                var parser = new DemoParser(input);

                parser.ParseHeader();

                parser.WeaponFired += (sender, e) => {
                    Console.WriteLine("Weapon_fire");
                    Console.WriteLine("{");
                    Console.WriteLine("velx=" + e.Shooter.Velocity.X);
                    Console.WriteLine("vely=" + e.Shooter.Velocity.Y);
                    Console.WriteLine("weapon=" + e.Weapon.Weapon);
                    Console.WriteLine("playername=" + e.Shooter.Name);
                    Console.WriteLine("playersteamid=" + e.Shooter.SteamID);
                    Console.WriteLine("}");

                };

                parser.ParseToEnd();
                Console.WriteLine("End");
            }
        }
示例#13
0
        static List<String> parseDemo(string fileName)
        {
            List<String> playerIDs = new List<String>();
            using (var fileStream = File.OpenRead(fileName))
            {
                using (var parser = new DemoParser(fileStream))
                {
                    //hasMatchStarted framkallar viðvörun um að mögulegt sé
                    //að það verði aldrei notað, með þessu slökkvum við á
                    //þessari viðvörun.
                    #pragma warning disable 0219
                    bool hasMatchStarted = false;
                    #pragma warning restore 0219

                    parser.ParseHeader();

                    parser.MatchStarted += (sender, e) =>
                    {
                        hasMatchStarted = true;

                        foreach (var player in parser.PlayingParticipants)
                        {
                            string test = player.SteamID.ToString();
                            playerIDs.Add(test);
                        }
                    };
                    //Þetta fyrir neðan er algjörlega ógeðslegt, ég veit.
                    //En er samt nauðsynlegt svo að playerIDs verði fyllt.
                    for (int i = 0; i < 3000; i++)
                    {
                        parser.ParseNextTick();
                    }
                }
            }
            return playerIDs;
        }
示例#14
0
 public string GetMapName()
 {
     if (string.IsNullOrEmpty(mapName))
     {
         if (availableOffline)
         {
             using (FileStream fs = new FileStream(GetMatchFilePath(), FileMode.Open, FileAccess.Read))
                 using (DemoInfo.DemoParser dp = new DemoInfo.DemoParser(fs))
                 {
                     dp.ParseHeader();
                     mapName = dp.Map;
                 }
         }
         else
         {
             var lastRound = GetLastRoundStats();
             if (lastRound != null)
             {
                 mapName = ((GameType)lastRound.reservation.game_type).ToString();
             }
         }
     }
     return(mapName);
 }
示例#15
0
		public static void Main(string[] args)
		{

			using (var input = File.OpenRead(args[0])) {
				var parser = new DemoParser(input);
				
				parser.ParseHeader ();

				#if DEBUG
				Dictionary<Player, int> failures = new Dictionary<Player, int>();
				parser.TickDone += (sender, e) => {
					//Problem: The HP coming from CCSPlayerEvent are sent 1-4 ticks later
					//I guess this is because the think()-method of the CCSPlayerResource isn't called
					//that often. Haven't checked though.
					foreach(var p in parser.PlayingParticipants)
					{
						//Make sure the array is never empty ;)
						failures[p] = failures.ContainsKey(p) ? failures[p] : 0;

						if(p.HP == p.AdditionaInformations.ScoreboardHP)
							failures[p] = 0;
						else
							failures[p]++; //omg this is hacky. 

						//Okay, if it's wrong 2 seconds in a row, something's off
						//Since there should be a tick where it's right, right?
						//And if there's something off (e.g. two players are swapped)
						//there will be 2 seconds of ticks where it's wrong
						//So no problem here :)
						Debug.Assert(
							failures[p] < parser.TickRate * 2, 
							string.Format(
								"The player-HP({0}) of {2} (Clan: {3}) and it's Scoreboard HP ({1}) didn't match for {4} ticks. ", 
								p.HP, p.AdditionaInformations.ScoreboardHP, p.Name, p.AdditionaInformations.Clantag, parser.TickRate * 2
							)
						);

					}
				};

				

				if (args.Length >= 2) {
					// progress reporting requested
					using (var progressFile = File.OpenWrite(args[1]))
					using (var progressWriter = new StreamWriter(progressFile) { AutoFlush = false }) {
						int lastPercentage = -1;
						while (parser.ParseNextTick()) {
							var newProgress = (int)(parser.ParsingProgess * 100);
							if (newProgress != lastPercentage) {
								progressWriter.Write(lastPercentage = newProgress);
								progressWriter.Flush();
							}
						}
					}

					return;
				}
				#endif
				
				parser.ParseToEnd();
			}
		}
示例#16
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            while (!bitstream.ChunkFinished)
            {
                var desc     = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;

                if (wireType == 5)
                {
                    if (fieldnum == 14)
                    {
                        parser.TickInterval = bitstream.ReadFloat();
                    }
                    else
                    {
                        var val = bitstream.ReadInt(32);
                        switch (fieldnum)
                        {
                        case 8:
                            MapCrc = val;
                            break;

                        case 9:
                            ClientCrc = val;
                            break;

                        case 10:
                            StringTableCrc = val;
                            break;
                        }
                    }
                }
                else if (wireType == 2)
                {
                    var val = bitstream.ReadProtobufString();

                    switch (fieldnum)
                    {
                    case 15:
                        GameDir = val;
                        break;

                    case 16:
                        MapName = val;
                        break;

                    case 17:
                        MapGroupName = val;
                        break;

                    case 18:
                        SkyName = val;
                        break;

                    case 19:
                        HostName = val;
                        break;
                    }
                }
                else if (wireType == 0)
                {
                    var val     = bitstream.ReadProtobufVarInt();
                    var boolval = (val == 0) ? false : true;

                    switch (fieldnum)
                    {
                    case 1:
                        Protocol = val;
                        break;

                    case 2:
                        ServerCount = val;
                        break;

                    case 3:
                        IsDedicated = boolval;
                        break;

                    case 4:
                        IsOfficialValveServer = boolval;
                        break;

                    case 5:
                        IsHltv = boolval;
                        break;

                    case 6:
                        IsReplay = boolval;
                        break;

                    case 7:
                        COs = val;
                        break;

                    case 11:
                        MaxClients = val;
                        break;

                    case 12:
                        MaxClasses = val;
                        break;

                    case 13:
                        PlayerSlot = val;
                        break;

                    case 20:
                        PublicIp = (uint)val;
                        break;

                    case 21:
                        IsRedirectingToProxyRelay = boolval;
                        break;

                    case 22:
                        UgcMapId = (uint)val;
                        break;
                    }
                }
            }
        }
示例#17
0
        static void Main(string[] args)
        {
            int demosParsed = 0;
            int errors = 0;
            String[] directories = Directory.GetDirectories(@"D:\demos\extracted\");

            foreach (String directory in directories)
            {
                if(directory.Length != 28 || !directory.StartsWith(@"D:\demos\extracted\demo190"))
                {
                    continue;
                }

                foreach(String file in Directory.GetFiles(directory))
                {
                    DemoParser parser = new DemoParser(File.OpenRead(file));

                    try
                    {
                        parser.ParseHeader();

                        Program program = new Program(parser);
                        parser.ParseToEnd();

                        demosParsed++;
                    } catch (Exception e)
                    {
                        parser = null;
                        errors++;
                        break;
                    }
                }

                if(demosParsed > 100)
                {
                    break;
                }
            }

            Console.WriteLine("Errors: " + errors);
            Console.WriteLine("Demos Parsed: " + demosParsed);

            Console.Read();
        }
示例#18
0
 private static void PrintMatchResults(DemoParser parser, StreamWriter outputStream, string demoName, string mapName, float currentTime, string clientName, int networkProtocol, int protocol, int signonLength, float playbackTime, string whoWonFirstRound, string winner)
 {
     string nameEvent = "matchEnd";
     outputStream.WriteLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}",
     demoName,
     nameEvent,
     mapName,
     currentTime,
     clientName,
     networkProtocol,
     protocol,
     signonLength,
     playbackTime,
     whoWonFirstRound.Replace(" ", string.Empty),
     winner.Replace(" ", string.Empty)
     ));
 }
        static void Main(string[] args)
        {
            if (args.Length == 0 || args[0] == "-help")
            {
                DisplayHelp();
                return;
            }

            /*
             * One argument per demofile, thus we iterate over all of them
             * > generator.exe demo1.dem demo2.dem
             */
            foreach (var fileName in args)
            {
                /*
                 * Initializing DemoParser with fileStream needs to be done
                 * with "using". Orig.Author warned about memoryleaks if we
                 * do not dispose fileStream / DemoParser.
                 */
                using (var fileStream = File.OpenRead(fileName))
                {
                    Console.WriteLine("Beginning parsing of " +fileName);
                    using (var parser = new DemoParser(fileStream)){
                        /*
                         * After initialization, always parse demoheader
                         * Create outPutFile&Stream
                         * Create CSVHeader for outPutFile
                         */
                        parser.ParseHeader();
                        DateTime timenow = DateTime.Now;

                        string map = parser.Map;
                        string outPutFileName = timenow.ToString("d") + "." + map + ".csv";
                        var outPutStream = new StreamWriter(outPutFileName);
                        outPutStream.WriteLine(GenerateCSVHeader());

                        /*
                         * Let's get srated on analyzing demo
                         * According to DemoInfo author, CSGO
                         * is mainly based on events. Therefore
                         * we use binding and event driven programing
                         * to do our bidding.
                         */

                        bool hasMatchStarted = false;
                        List<Player> ingame = new List<Player>();
                        Dictionary<Player, List<double>> dicPlayerFiredVelocity = new Dictionary<Player, List<double>>();
                        parser.MatchStarted += (sender, e) =>
                        {
                            hasMatchStarted = true;
                            ingame.AddRange(parser.PlayingParticipants);
                        };

                        parser.RoundStart += (sender, e) =>
                        {
                            if (!hasMatchStarted) { return; }
                            dicPlayerFiredVelocity.Clear();

                        };
                        /*
                         * Event WeaponFired has 2 parameters,
                         * Shooter(Player) & Weapon(Weapon)
                         */
                        parser.WeaponFired += (sender, e) =>
                        {
                            if (hasMatchStarted)
                            {
                                if (dicPlayerFiredVelocity.ContainsKey(e.Shooter))
                                {
                                    dicPlayerFiredVelocity[e.Shooter].Add(e.Shooter.Velocity.Absolute);

                                }
                                else
                                {
                                    dicPlayerFiredVelocity.Add(e.Shooter, new List<double> { e.Shooter.Velocity.Absolute });
                                }
                            }
                        };

                        /*
                         * On roundEnd, print information to
                         * outputstream
                         */
                        parser.RoundEnd += (sender, e) =>
                        {
                            if (!hasMatchStarted) { return; }
                            OutPutStreamRoundResults(parser, outPutStream, dicPlayerFiredVelocity);
                        };

                        /*
                         * Call this after binding events
                         * Parses demofile to the end.
                         * Remember to close StreamWriter.
                         */

                        parser.ParseToEnd();
                        outPutStream.Close();
                    }
                }
            }
        }
示例#20
0
        public DataStreamManager(DemoParser parser)
        {
            this.parser = parser;

            createObservables();
        }
示例#21
0
 static void PrintKillEvent(DemoParser parser, StreamWriter outputStream, string demoName, string mapName, string killerName, Vector killerPosition, string killerWeapon, bool isHeadshot, int penetradedObjects, string killedName, Vector killedPosition)
 {
     string nameEvent = "kill";
     outputStream.WriteLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}",
     demoName,
     nameEvent,
     mapName,
     killerName,
     "X:" + killerPosition.X + ";Y:" + killerPosition.Y + ";Z:" + killerPosition.Z,
     killerWeapon,
     isHeadshot,
     penetradedObjects,
     killedName,
     "X:" + killedPosition.X + ";Y:" + killedPosition.Y + ";Z:" + killedPosition.Z
     ));
 }
示例#22
0
        static void parseDemo(FileStream fileStream, string fileName, int matchStartEventNumber)
        {
            using (var parser = new DemoParser(fileStream))
            {
                string demoName = Path.GetFileName(fileName);
                // So now we've initialized a demo-parser.
                // let's parse the head of the demo-file to get which map the match is on!
                // this is always the first step you need to do.
                parser.ParseHeader();

                // and now, do some magic: grab the match!
                string map = parser.Map;

                // And now, generate the filename of the resulting file
                string output_roundResults = fileName + "_roundResults.csv";
                string output_killEvents = fileName + "_killEvents.csv";
                string output_matchResults = fileName + "_matchResults.csv";
                /*string output_smokeNades = fileName + "_smokeNades.csv";
                string output_fireNades = fileName + "_fireNades.csv";
                string output_flashNades = fileName + "_flashNades.csv";
                string output_decoyNades = fileName + "_decoyNades.csv";
                string output_heNades = fileName + "_heNades.csv";*/
                // and open it.
                var outputStream_roundResults = new StreamWriter(output_roundResults, false, Encoding.UTF8);
                var outputStream_killEvents = new StreamWriter(output_killEvents, false, Encoding.UTF8);
                var outputStream_matchResults = new StreamWriter(output_matchResults, false, Encoding.UTF8);
                /*var outputStream_smokeNades = new StreamWriter(output_smokeNades, false, Encoding.UTF8);
                var outputStream_fireNades = new StreamWriter(output_fireNades, false, Encoding.UTF8);
                var outputStream_flashNades = new StreamWriter(output_flashNades, false, Encoding.UTF8);
                var outputStream_decoyNades = new StreamWriter(output_decoyNades, false, Encoding.UTF8);
                var outputStream_heNades = new StreamWriter(output_heNades, false, Encoding.UTF8);*/

                //And write a header so you know what is what in the resulting file
                //outputStream.WriteLine(GenerateCSVHeader());

                int ctStartroundMoney = 0, tStartroundMoney = 0, ctEquipValue = 0, tEquipValue = 0, ctSaveAmount = 0, tSaveAmount = 0;
                int numberOfEventsMatchStarted = 0;
                int roundNumber = 0;

                List<String> ctWeapons = new List<String>();
                List<String> tWeapons = new List<String>();

                float ctWay = 0, tWay = 0;

                bool teamsSwap = false;

                int CTScore = 0;
                int TScore = 0;

                int defuses = 0;
                int plants = 0;

                string firstRoundWinner = "";
                string lastRoundWinner = "";

                Dictionary<Player, int> killsThisRound = new Dictionary<Player, int>();

                // Since most of the parsing is done via "Events" in CS:GO, we need to use them.
                // So you bind to events in C# as well.

                // AFTER we have bound the events, we start the parser!

                parser.MatchStarted += (sender, e) =>
                {
                    numberOfEventsMatchStarted++;
                };

                parser.PlayerKilled += (object sender, PlayerKilledEventArgs e) =>
                {

                    if (numberOfEventsMatchStarted!=matchStartEventNumber)
                        return;

                    //the killer is null if you're killed by the world - eg. by falling
                    if (e.Killer != null)
                    {
                        if (!killsThisRound.ContainsKey(e.Killer))
                            killsThisRound[e.Killer] = 0;

                        //Remember how many kills each player made this rounds
                        try
                        {
                            killsThisRound[e.Killer]++;
                            string killerSteamID = e.Killer.SteamID.ToString();
                            Vector killerPosition = e.Killer.Position;
                            string killingWeapon = e.Weapon.Weapon.ToString();
                            bool isHeadshot = e.Headshot;
                            int penetratedObjects = e.PenetratedObjects;
                            string victimSteamID = e.Victim.SteamID.ToString();
                            Vector victimPosition = e.Victim.Position;
                            PrintKillEvent(parser, outputStream_killEvents, demoName, map, killerSteamID, killerPosition, killingWeapon, isHeadshot, penetratedObjects, victimSteamID, victimPosition);
                        }
                        catch (Exception)
                        {
                            return;
                        }
                    }
                };

                parser.RoundStart += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;
                    //How much money had each team at the start of the round?
                    ctStartroundMoney = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).Sum(a => a.Money);
                    tStartroundMoney = parser.Participants.Where(a => a.Team == Team.Terrorist).Sum(a => a.Money);

                    //And how much they did they save from the last round?
                    ctSaveAmount = parser.Participants.Where(a => a.Team == Team.CounterTerrorist && a.IsAlive).Sum(a => a.CurrentEquipmentValue);
                    tSaveAmount = parser.Participants.Where(a => a.Team == Team.Terrorist && a.IsAlive).Sum(a => a.CurrentEquipmentValue);

                    //And let's reset those statistics
                    ctWay = 0; tWay = 0;
                    plants = 0; defuses = 0;
                    ctWeapons = new List<String>();
                    tWeapons = new List<String>();

                    killsThisRound.Clear();
                };

                parser.FreezetimeEnded += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    // At the end of the freezetime (when players can start walking)
                    // calculate the equipment value of each team!
                    ctEquipValue = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).Sum(a => a.CurrentEquipmentValue);
                    List<Player> ctPLayers = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).ToList();
                    tEquipValue = parser.Participants.Where(a => a.Team == Team.Terrorist).Sum(a => a.CurrentEquipmentValue);
                    List<Player> tPLayers = parser.Participants.Where(a => a.Team == Team.Terrorist).ToList();

                    foreach (Player p in ctPLayers)
                    {
                        foreach (Equipment e2 in p.Weapons)
                            ctWeapons.Add(e2.Weapon.ToString());
                        ctWeapons.Add("END");
                    }
                    foreach (Player p in tPLayers)
                    {
                        foreach (Equipment e2 in p.Weapons)
                            tWeapons.Add(e2.Weapon.ToString());
                        tWeapons.Add("END");
                    }
                };

                parser.BombPlanted += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    plants++;
                };

                /*parser.SmokeNadeStarted += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    Vector nadePosition = e.Position;
                    PrintSmokeEvent(parser, outputStream_smokeNades, demoName, map, nadePosition);

                };

                parser.FireNadeStarted += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    Vector nadePosition = e.Position;
                    PrintFireNadeEvent(parser, outputStream_fireNades, demoName, map, nadePosition);

                };

                parser.FlashNadeExploded += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    Vector nadePosition = e.Position;
                    PrintFlashNadeEvent(parser, outputStream_flashNades, demoName, map, nadePosition);

                };

                parser.DecoyNadeStarted += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    Vector nadePosition = e.Position;
                    PrintDecoyNadeEvent(parser, outputStream_decoyNades, demoName, map, nadePosition);

                };

                parser.ExplosiveNadeExploded += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    Vector nadePosition = e.Position;
                    PrintHeNadeExplosionEvent(parser, outputStream_heNades, demoName, map, nadePosition);

                };*/

                parser.BombDefused += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    defuses++;
                };

                parser.LastRoundHalf += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    teamsSwap = true;

                };

                parser.TickDone += (sender, e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                        return;

                    // Okay, let's measure how far each team travelled.
                    // As you might know from school the amount walked
                    // by a player is the sum of it's velocities

                    foreach (var player in parser.PlayingParticipants)
                    {
                        // We multiply it by the time of one tick
                        // Since the velocity is given in
                        // ingame-units per second
                        float currentWay = (float)(player.Velocity.Absolute * parser.TickTime);

                        // This is just an example of what kind of stuff you can do
                        // with this parser.
                        // Of course you could find out who makes the most footsteps, and find out
                        // which player ninjas the most - just to give you an example

                        if (player.Team == Team.CounterTerrorist)
                            ctWay += currentWay;
                        else if (player.Team == Team.Terrorist)
                            tWay += currentWay;
                    }
                };

                //So now lets do some fancy output
                parser.RoundEnd += (object sender, RoundEndedEventArgs e) =>
                {
                    if (numberOfEventsMatchStarted != matchStartEventNumber)
                    {
                        return;
                    }

                    roundNumber++;

                    // We do this in a method-call since we'd else need to duplicate code
                    // The much parameters are there because I simply extracted a method
                    // Sorry for this - you should be able to read it anywys :)
                    string winningFaction = e.Winner.ToString();

                    if (roundNumber == 1)
                    {
                        if (winningFaction.Equals("CounterTerrorist"))
                        {
                            firstRoundWinner = parser.CTClanName;
                        }
                        if (winningFaction.Equals("Terrorist"))
                        {
                            firstRoundWinner = parser.TClanName;
                        }
                    }

                    if (winningFaction.Equals("CounterTerrorist"))
                    {
                        CTScore++;
                        lastRoundWinner = parser.CTClanName;
                    }
                    if (winningFaction.Equals("Terrorist"))
                    {
                        lastRoundWinner = parser.TClanName;
                        TScore++;
                    }

                    PrintRoundResults(parser, outputStream_roundResults, demoName, map, CTScore, TScore, ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, defuses, plants, killsThisRound, winningFaction, ctWeapons, tWeapons);

                    if (teamsSwap)
                    {
                        teamsSwap = false;
                        int tempCTscore = CTScore;
                        int tempTscore = TScore;
                        CTScore = tempTscore;
                        TScore = tempCTscore;
                    }

                };

                //Now let's parse the demo!
                parser.ParseToEnd();

                PrintMatchResults(parser, outputStream_matchResults, demoName, map, parser.CurrentTime, parser.Header.ClientName, parser.Header.NetworkProtocol, parser.Header.Protocol, parser.Header.SignonLength, parser.Header.PlaybackTime, firstRoundWinner, lastRoundWinner);

                outputStream_roundResults.Close();
                outputStream_killEvents.Close();
                outputStream_matchResults.Close();
               /* outputStream_smokeNades.Close();
                outputStream_fireNades.Close();
                outputStream_flashNades.Close();
                outputStream_decoyNades.Close();
                outputStream_heNades.Close();*/
            }
        }
示例#23
0
		public void Parse(IBitStream bitstream, DemoParser parser)
		{
			Keys = new List<object>();
			while (!bitstream.ChunkFinished) {
				var desc = bitstream.ReadProtobufVarInt();
				var wireType = desc & 7;
				var fieldnum = desc >> 3;
				if ((wireType == 2) && (fieldnum == 1)) {
					EventName = bitstream.ReadProtobufString();
				} else if ((wireType == 0) && (fieldnum == 2)) {
					EventId = bitstream.ReadProtobufVarInt();
				} else if ((wireType == 2) && (fieldnum == 3)) {
					bitstream.BeginChunk(bitstream.ReadProtobufVarInt() * 8);
					/*
					 * Hope and pray that gaben is once again nice to us and
					 * sends 'type' first, then the respective member, then NOTHING.
					 */
					desc = bitstream.ReadProtobufVarInt();
					wireType = desc & 7;
					fieldnum = desc >> 3;
					if ((wireType != 0) || (fieldnum != 1))
						throw new InvalidDataException("Lord Gaben wasn't nice to us :/");

					var typeMember = bitstream.ReadProtobufVarInt();
					desc = bitstream.ReadProtobufVarInt();
					wireType = desc & 7;
					fieldnum = desc >> 3;

					if (fieldnum != (typeMember + 1))
						throw new InvalidDataException("Lord Gaben wasn't nice to us :/ (srsly wtf!?)");

					switch (typeMember) {
					case 1: // string
						if (wireType != 2)
							throw new InvalidDataException("proto definition differs");
						Keys.Add(bitstream.ReadProtobufString());
						break;
					case 2: // float
						if (wireType != 5)
							throw new InvalidDataException("proto definition differs");
						Keys.Add(bitstream.ReadFloat());
						break;
					case 3: // long
					case 4: // short
					case 5: // byte
						if (wireType != 0)
							throw new InvalidDataException("proto definition differs");
						Keys.Add(bitstream.ReadProtobufVarInt());
						break;
					case 6: // bool
						if (wireType != 0)
							throw new InvalidDataException("proto definition differs");
						Keys.Add(bitstream.ReadProtobufVarInt() != 0);
						break;
					default:
						throw new InvalidDataException("Looks like they introduced a new type");
					}

					if (!bitstream.ChunkFinished)
						throw new InvalidDataException("Lord Gaben tricked us! D:");

					bitstream.EndChunk();
				} else
					throw new InvalidDataException();
			}

			GameEventHandler.Apply(this, parser);
		}
        public static void GenerateScoreboards(DemoParser parser)
        {
            int i = 0;

            parser.ParseHeader ();

            Console.WriteLine ("map: " + parser.Map);

            int roundEndedCount = 0;

            parser.RoundEnd += (object sender, RoundEndedEventArgs e) => {
                // The reason I'm doing this after tick_done is that
                // entity-updates only come in the same tick as round_end
                // comes, meaning the score-update might not be transmitted yet
                // which would be sad - we always want the current score!
                // so we wait 1 second.

                roundEndedCount = 1;
            };

            parser.TickDone += (object sender, TickDoneEventArgs e) => {
                if(roundEndedCount == 0)
                    return;

                roundEndedCount ++;

                // Wait twice the tickrate of the demo (~2 seconds) to make sure the
                // screen has been updated. I *LOVE* demo files :)
                if(roundEndedCount < parser.TickRate * 2) {
                    return;
                }

                roundEndedCount = 0;

                Console.WriteLine ("------------------------------------------------------------");

                Console.WriteLine ("Round {0}, CT: {1}, T: {2}", ++i, parser.CTScore, parser.TScore);

                Console.WriteLine("Ts\t" + parser.TClanName);
                Console.WriteLine("Tag\tName\tSteamID\tKills\tDeaths\tAssists\tScore\t");
                foreach(var player in parser.PlayingParticipants.Where(a => a.Team == Team.Terrorist))
                    Console.WriteLine (
                        "{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}",
                        player.AdditionaInformations.Clantag,
                        player.Name, player.SteamID,
                        player.AdditionaInformations.Kills,
                        player.AdditionaInformations.Deaths,
                        player.AdditionaInformations.Assists,
                        player.AdditionaInformations.Score
                    );

                Console.WriteLine("CTs\t" + parser.CTClanName);
                Console.WriteLine("Tag\tName\tSteamID\tKills\tDeaths\tAssists\tScore\t");
                foreach(var player in parser.PlayingParticipants.Where(a => a.Team == Team.CounterTerrorist))
                    Console.WriteLine (
                        "{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}",
                        player.AdditionaInformations.Clantag,
                        player.Name, player.SteamID,
                        player.AdditionaInformations.Kills,
                        player.AdditionaInformations.Deaths,
                        player.AdditionaInformations.Assists,
                        player.AdditionaInformations.Score
                    );

                Console.WriteLine ();

            };

            parser.ParseToEnd ();
        }
 static void PrintRoundResults(DemoParser parser, StreamWriter outputStream, int ctStartroundMoney, int tStartroundMoney, int ctEquipValue, int tEquipValue, int ctSaveAmount, int tSaveAmount, float ctWay, float tWay, int defuses, int plants, Dictionary<Player, int> killsThisRound)
 {
     //okay, get the topfragger:
     var topfragger = killsThisRound.OrderByDescending (x => x.Value).FirstOrDefault ();
     if (topfragger.Equals (default(KeyValuePair<Player, int>)))
         topfragger = new KeyValuePair<Player, int> (new Player (), 0);
     //At the end of each round, let's write down some statistics!
     outputStream.WriteLine (string.Format ("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9};{10};{11};{12};{13};{14};{15};{16};{17};{18};{19};{20};{21};{22};{23};", parser.CTScore + parser.TScore, //Round-Number
     parser.CTScore, parser.TScore, //how many CTs are still alive?
     parser.PlayingParticipants.Count (a => a.IsAlive && a.Team == Team.CounterTerrorist), //how many Ts are still alive?
     parser.PlayingParticipants.Count (a => a.IsAlive && a.Team == Team.Terrorist), ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, //The kills of all CTs so far
     parser.PlayingParticipants.Where (a => a.Team == Team.CounterTerrorist).Sum (a => a.AdditionaInformations.Kills), parser.PlayingParticipants.Where (a => a.Team == Team.Terrorist).Sum (a => a.AdditionaInformations.Kills), //The deaths of all CTs so far
     parser.PlayingParticipants.Where (a => a.Team == Team.CounterTerrorist).Sum (a => a.AdditionaInformations.Deaths), parser.PlayingParticipants.Where (a => a.Team == Team.Terrorist).Sum (a => a.AdditionaInformations.Deaths), //The assists of all CTs so far
     parser.PlayingParticipants.Where (a => a.Team == Team.CounterTerrorist).Sum (a => a.AdditionaInformations.Assists), parser.PlayingParticipants.Where (a => a.Team == Team.Terrorist).Sum (a => a.AdditionaInformations.Assists), plants, defuses, "\"" + topfragger.Key.Name + "\"", //The name of the topfragger this round
     topfragger.Key.SteamID, //The steamid of the topfragger this round
     topfragger.Value//The amount of kills he got
     ));
 }
        public static void Main(string[] args)
        {
            // First, check wether the user needs assistance:
            if (args.Length == 0 || args [0] == "--help") {
                PrintHelp ();
                return;
            }

            if (args [0] == "--scoreboard") {
                using (var fileStream = File.OpenRead (args[1])) {
                    using (var parser = new DemoParser(fileStream)) {
                        ScoreboardGenerator.GenerateScoreboards(parser);
                    }
                }
                return;
            }

            if (args [0] == "--frags") {
                using (var fileStream = File.OpenRead (args[1])) {
                    using (var parser = new DemoParser(fileStream)) {
                        FragGenerator.GenerateFrags(parser);
                    }
                }
                return;
            }

            // Every argument is a file, so let's iterate over all the arguments
            // So you can call this program like
            // > StatisticsGenerator.exe hello.dem bye.dem
            // It'll generate the statistics.
            foreach (var fileName in args) {
                // Okay, first we need to initalize a demo-parser
                // It takes a stream, so we simply open with a filestream
                using (var fileStream = File.OpenRead (fileName)) {
                    // By using "using" we make sure that the fileStream is properly disposed
                    // the same goes for the DemoParser which NEEDS to be disposed (else it'll
                    // leak memory and kittens will die.

                    Console.WriteLine ("Parsing demo " + fileName);

                    using (var parser = new DemoParser (fileStream)) {
                        // So now we've initialized a demo-parser.
                        // let's parse the head of the demo-file to get which map the match is on!
                        // this is always the first step you need to do.
                        parser.ParseHeader ();

                        // and now, do some magic: grab the match!
                        string map = parser.Map;

                        // And now, generate the filename of the resulting file
                        string outputFileName = fileName + "." + map + ".csv";
                        // and open it.
                        var outputStream = new StreamWriter (outputFileName);

                        //And write a header so you know what is what in the resulting file
                        outputStream.WriteLine (GenerateCSVHeader ());

                        // Cool! Now let's get started generating the analysis-data.

                        //Let's just declare some stuff we need to remember

                        // Here we'll save how far a player has travelled each round.
                        // Here we remember wheter the match has started yet.
                        bool hasMatchStarted = false;

                        int ctStartroundMoney = 0, tStartroundMoney = 0, ctEquipValue = 0, tEquipValue = 0, ctSaveAmount = 0, tSaveAmount = 0;

                        float ctWay = 0, tWay = 0;

                        int defuses = 0;
                        int plants = 0;

                        Dictionary<Player, int> killsThisRound = new Dictionary<Player, int> ();

                        List<Player> ingame = new List<Player> ();

                        // Since most of the parsing is done via "Events" in CS:GO, we need to use them.
                        // So you bind to events in C# as well.

                        // AFTER we have bound the events, we start the parser!

                        parser.MatchStarted += (sender, e) => {
                            hasMatchStarted = true;
                            //Okay let's output who's really in this game!

                            Console.WriteLine("Participants: ");
                            Console.WriteLine("  Terrorits \"{0}\": ", parser.CTClanName);

                            foreach(var player in parser.PlayingParticipants.Where(a => a.Team == Team.Terrorist))
                                Console.WriteLine ("    {0} {1} (Steamid: {2})", player.AdditionaInformations.Clantag, player.Name, player.SteamID);

                            Console.WriteLine("  Counter-Terrorits \"{0}\": ", parser.TClanName);
                            foreach(var player in parser.PlayingParticipants.Where(a => a.Team == Team.CounterTerrorist))
                                Console.WriteLine ("    {0} {1} (Steamid: {2})", player.AdditionaInformations.Clantag, player.Name, player.SteamID);

                            // Okay, problem: At the end of the demo
                            // a player might have already left the game,
                            // so we need to store some information
                            // about the players before they left :)
                            ingame.AddRange(parser.PlayingParticipants);
                        };

                        parser.PlayerKilled += (object sender, PlayerKilledEventArgs e) => {
                            //the killer is null if you're killed by the world - eg. by falling
                            if(e.Killer != null) {
                                if(!killsThisRound.ContainsKey(e.Killer))
                                    killsThisRound[e.Killer] = 0;

                                //Remember how many kills each player made this rounds
                                killsThisRound[e.Killer]++;
                            }
                        };

                        parser.RoundStart += (sender, e) => {
                            if(!hasMatchStarted)
                                return;

                            //How much money had each team at the start of the round?
                            ctStartroundMoney = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).Sum(a => a.Money);
                            tStartroundMoney = parser.Participants.Where(a => a.Team == Team.Terrorist).Sum(a => a.Money);

                            //And how much they did they save from the last round?
                            ctSaveAmount = parser.Participants.Where(a => a.Team == Team.CounterTerrorist && a.IsAlive).Sum(a => a.CurrentEquipmentValue);
                            tSaveAmount = parser.Participants.Where(a => a.Team == Team.Terrorist && a.IsAlive).Sum(a => a.CurrentEquipmentValue);

                            //And let's reset those statistics
                            ctWay = 0; tWay = 0;
                            plants = 0; defuses = 0;

                            killsThisRound.Clear();
                        };

                        parser.FreezetimeEnded += (sender, e) => {
                            if(!hasMatchStarted)
                                return;

                            // At the end of the freezetime (when players can start walking)
                            // calculate the equipment value of each team!
                            ctEquipValue = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).Sum(a => a.CurrentEquipmentValue);
                            tEquipValue = parser.Participants.Where(a => a.Team == Team.Terrorist).Sum(a => a.CurrentEquipmentValue);
                        };

                        parser.BombPlanted += (sender, e) => {
                            if(!hasMatchStarted)
                                return;

                            plants++;
                        };

                        parser.BombDefused += (sender, e) => {
                            if(!hasMatchStarted)
                                return;

                            defuses++;
                        };

                        parser.TickDone += (sender, e) => {
                            if(!hasMatchStarted)
                                return;

                            // Okay, let's measure how far each team travelled.
                            // As you might know from school the amount walked
                            // by a player is the sum of it's velocities

                            foreach(var player in parser.PlayingParticipants)
                            {
                                // We multiply it by the time of one tick
                                // Since the velocity is given in
                                // ingame-units per second
                                float currentWay = (float)(player.Velocity.Absolute * parser.TickTime);

                                // This is just an example of what kind of stuff you can do
                                // with this parser.
                                // Of course you could find out who makes the most footsteps, and find out
                                // which player ninjas the most - just to give you an example

                                if(player.Team == Team.CounterTerrorist)
                                    ctWay += currentWay;
                                else if(player.Team == Team.Terrorist)
                                    tWay += currentWay;
                            }
                        };

                        //So now lets do some fancy output
                        parser.RoundEnd += (sender, e) => {
                            if(!hasMatchStarted)
                                return;

                            // We do this in a method-call since we'd else need to duplicate code
                            // The much parameters are there because I simply extracted a method
                            // Sorry for this - you should be able to read it anywys :)
                            PrintRoundResults (parser, outputStream, ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, defuses, plants, killsThisRound);
                        };

                        //Now let's parse the demo!
                        parser.ParseToEnd ();

                        //And output the result of the last round again.
                        PrintRoundResults (parser, outputStream, ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, defuses, plants, killsThisRound);

                        //Lets just display an end-game-scoreboard!

                        Console.WriteLine("Finished! Results: ");
                        Console.WriteLine("  Terrorits \"{0}\": ", parser.CTClanName);

                        foreach(var player in ingame.Where(a => a.Team == Team.Terrorist))
                            Console.WriteLine (
                                "    {0} {1} (Steamid: {2}): K: {3}, D: {4}, A: {5}",
                                player.AdditionaInformations.Clantag,
                                player.Name, player.SteamID,
                                player.AdditionaInformations.Kills,
                                player.AdditionaInformations.Deaths,
                                player.AdditionaInformations.Assists
                            );

                        Console.WriteLine("  Counter-Terrorits \"{0}\": ", parser.TClanName);
                        foreach(var player in ingame.Where(a => a.Team == Team.CounterTerrorist))
                            Console.WriteLine (
                                "    {0} {1} (Steamid: {2}): K: {3}, D: {4}, A: {5}",
                                player.AdditionaInformations.Clantag,
                                player.Name, player.SteamID,
                                player.AdditionaInformations.Kills,
                                player.AdditionaInformations.Deaths,
                                player.AdditionaInformations.Assists
                            );

                        outputStream.Close ();
                    }

                }
            }
        }
示例#27
0
		public static Demo ParseDemoHeader(string pathDemoFile)
		{
			DemoParser parser = new DemoParser(File.OpenRead(pathDemoFile));

			DateTime dateFile = File.GetCreationTime(pathDemoFile);
			string dateAsString = dateFile.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);

			Demo demo = new Demo
			{
				Name = Path.GetFileName(pathDemoFile),
				Path = pathDemoFile,
				Date = dateAsString
			};

			try
			{
				parser.ParseHeader();
			}
			catch (InvalidDataException)
			{
				// Silently ignore no CSGO demos
				return null;
			}

			DemoHeader header = parser.Header;
			DateTime dateTime = File.GetCreationTime(pathDemoFile);
			int seconds = (int)(dateTime.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
			demo.Id = header.MapName.Replace("/", "") + seconds + header.SignonLength + header.PlaybackFrames;
			demo.ClientName = header.ClientName;
			demo.Hostname = header.ServerName;
			if (header.PlaybackTicks != 0 && header.PlaybackTime != 0)
			{
				demo.ServerTickrate = header.PlaybackTicks / header.PlaybackTime;
			}
			if (header.PlaybackFrames != 0 && header.PlaybackTime != 0)
			{
				demo.Tickrate = (int)Math.Round((double)header.PlaybackFrames / header.PlaybackTime);
			}
			demo.Duration = header.PlaybackTime;
			demo.MapName = header.MapName;
			demo.Source = DetermineDemoSource(demo, parser, header);

			return demo;
		}
示例#28
0
		private static Source DetermineDemoSource(Demo demo, DemoParser parser, DemoHeader header)
		{
			// Check if it's a POV demo
			Match match = LocalRegex.Match(header.ServerName);
			if (match.Success)
			{
				demo.Type = "POV";
				return Source.Factory("pov");
			}

			// Check for esea demos, appart the filename there is no magic to detect it
			if (demo.Name.Contains("esea"))
			{
				return Source.Factory("esea");
			}

			// Check for faceit demos
			// (Before May 2015) Faceit : uses regex - no false positive but could miss some Faceit demo (when premade playing because of custom team name)
			// (May 2015) Faceit : uses hostname
			if (demo.Hostname.Contains("FACEIT.com") || FILENAME_FACEIT_REGEX.Match(demo.Name).Success)
			{
				return Source.Factory("faceit");
			}

			// Check for cevo demos
			if (demo.Hostname.Contains("CEVO.com"))
			{
				return Source.Factory("cevo");
			}

			// Check for ebot demos
			if (demo.Hostname.Contains("eBot") || FILENAME_EBOT_REGEX.Match(demo.Name).Success)
			{
				return Source.Factory("ebot");
			}

			// If none of the previous checks matched, we use ValveAnalyzer
			return Source.Factory("valve");
		}
        public static void DoStuff(string[] args)
        {
            foreach (var fileName in args) {
                using (var fileStream = File.OpenRead (fileName)) {
                    Console.WriteLine ("Parsing demo " + fileName);
                    using (var parser = new DemoParser (fileStream)) {
                        parser.ParseHeader ();
                        string map = parser.Map, outputFileName = fileName + "." + map + ".csv";
                        var outputStream = new StreamWriter (outputFileName);
                        bool hasMatchStarted = false;
                        int ctStartroundMoney = 0, tStartroundMoney = 0, ctEquipValue = 0, tEquipValue = 0, ctSaveAmount = 0, tSaveAmount = 0;
                        float ctWay = 0, tWay = 0;
                        int defuses = 0;
                        int plants = 0;
                        Dictionary<Player, int> killsThisRound = new Dictionary<Player, int> ();

                        parser.MatchStarted += (sender, e) => {
                            hasMatchStarted = true;
                        };

                        parser.PlayerKilled += (object sender, PlayerKilledEventArgs e) => {
                            if(e.Killer != null) {
                                if(!killsThisRound.ContainsKey(e.Killer))
                                    killsThisRound[e.Killer] = 0;
                                killsThisRound[e.Killer]++;
                            }
                        };

                        parser.RoundStart += (sender, e) => {
                            if(!hasMatchStarted)
                                return;
                            ctStartroundMoney = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).Sum(a => a.Money);
                            tStartroundMoney = parser.Participants.Where(a => a.Team == Team.Terrorist).Sum(a => a.Money);
                            ctSaveAmount = parser.Participants.Where(a => a.Team == Team.CounterTerrorist && a.IsAlive).Sum(a => a.CurrentEquipmentValue);
                            tSaveAmount = parser.Participants.Where(a => a.Team == Team.Terrorist && a.IsAlive).Sum(a => a.CurrentEquipmentValue);
                            ctWay = 0; tWay = 0;
                            plants = 0; defuses = 0;
                            killsThisRound.Clear();
                        };

                        parser.FreezetimeEnded += (sender, e) => {
                            if(!hasMatchStarted)
                                return;
                            ctEquipValue = parser.Participants.Where(a => a.Team == Team.CounterTerrorist).Sum(a => a.CurrentEquipmentValue);
                            tEquipValue = parser.Participants.Where(a => a.Team == Team.Terrorist).Sum(a => a.CurrentEquipmentValue);
                        };

                        parser.BombPlanted += (sender, e) => {
                            if(!hasMatchStarted)
                                return;
                            plants++;
                        };

                        parser.BombDefused += (sender, e) => {
                            if(!hasMatchStarted)
                                return;
                            defuses++;
                        };

                        parser.TickDone += (sender, e) => {
                            if(!hasMatchStarted)
                                return;
                            foreach(var player in parser.PlayingParticipants)
                            {
                                float currentWay = (float)(player.Velocity.Absolute * parser.TickTime);
                                if(player.Team == Team.CounterTerrorist)
                                    ctWay += currentWay;
                                else if(player.Team == Team.Terrorist)
                                    tWay += currentWay;
                            }
                        };

                        parser.RoundEnd += (sender, e) => {
                            if(!hasMatchStarted)
                                return;
                            PrintRoundResults (parser, outputStream, ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, defuses, plants, killsThisRound);
                        };

                        parser.ParseToEnd ();
                        PrintRoundResults (parser, outputStream, ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, defuses, plants, killsThisRound);
                        outputStream.Close ();
                    }
                }
            }
        }
示例#30
0
 public void Parse(IBitStream bitstream, DemoParser parser)
 {
     GameEventHandler.HandleGameEventList(ReadDescriptors(bitstream), parser);
 }
示例#31
0
		public static Demo ParseDemoHeader(string pathDemoFile)
		{
			DemoParser parser = new DemoParser(File.OpenRead(pathDemoFile));

			DateTime dateFile = File.GetCreationTime(pathDemoFile);
			Demo demo = new Demo
			{
				Name = Path.GetFileName(pathDemoFile),
				Path = pathDemoFile,
				Date = dateFile
			};

			try
			{
				parser.ParseHeader();
			}
			catch (Exception)
			{
				// Silently ignore no CSGO demos or unreadable file
				return null;
			}

			DemoHeader header = parser.Header;
			DateTime dateTime = File.GetCreationTime(pathDemoFile);
			int seconds = (int)(dateTime.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
			demo.Id = header.MapName.Replace("/", "") + "_" + seconds + header.SignonLength + header.PlaybackFrames;
			demo.ClientName = header.ClientName;
			demo.Hostname = header.ServerName;
			if (header.PlaybackTicks != 0 && header.PlaybackTime != 0)
			{
				demo.ServerTickrate = header.PlaybackTicks / header.PlaybackTime;
			}
			if (header.PlaybackFrames != 0 && header.PlaybackTime != 0)
			{
				demo.Tickrate = (int)Math.Round((double)header.PlaybackFrames / header.PlaybackTime);
			}
			demo.Duration = header.PlaybackTime;
			demo.MapName = header.MapName;
			demo.Source = DetermineDemoSource(demo, header);

			// Read .info file to get the real match date
			string infoFilePath = demo.Path + ".info";
			if (File.Exists(infoFilePath))
			{
				using (FileStream file = File.OpenRead(infoFilePath))
				{
					try
					{
						CDataGCCStrike15_v2_MatchInfo infoMsg = Serializer.Deserialize<CDataGCCStrike15_v2_MatchInfo>(file);
						DateTime unixTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
						demo.Date = unixTime.AddSeconds(infoMsg.matchtime);
					}
					catch (Exception)
					{
						// silently ignore old .info files
						// Maybe add the old message to handle it?
					}
				}
			}

			return demo;
		}
示例#32
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            while (!bitstream.ChunkFinished)
            {
                var desc     = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;

                if (wireType == 2)
                {
                    if (fieldnum == 1)
                    {
                        Name = bitstream.ReadProtobufString();
                        continue;
                    }
                    else if (fieldnum == 8)
                    {
                        // String data is special.
                        // We'll simply hope that gaben is nice and sends
                        // string_data last, just like he should.
                        var len = bitstream.ReadProtobufVarInt();
                        bitstream.BeginChunk(len * 8);
                        DemoInfo.DP.Handler.CreateStringTableUserInfoHandler.Apply(this, bitstream, parser);
                        bitstream.EndChunk();
                        if (!bitstream.ChunkFinished)
                        {
                            throw new NotImplementedException("Lord Gaben wasn't nice to us :/");
                        }
                        break;
                    }
                    else
                    {
                        throw new Exception("yes I know we should drop this but we" +
                                            "probably want to know that they added a new big field");
                    }
                }

                if (wireType != 0)
                {
                    throw new Exception();
                }

                var val = bitstream.ReadProtobufVarInt();

                switch (fieldnum)
                {
                case 2:
                    MaxEntries = val;
                    break;

                case 3:
                    NumEntries = val;
                    break;

                case 4:
                    _UserDataFixedSize = val;
                    break;

                case 5:
                    UserDataSize = val;
                    break;

                case 6:
                    UserDataSizeBits = val;
                    break;

                case 7:
                    Flags = val;
                    break;

                default:
                    // silently drop
                    break;
                }
            }
        }
示例#33
0
        public static void Analyze(string demoPath)
        {
            using (var fileStream = File.OpenRead(demoPath))
            {
                Console.WriteLine("Parsing demo " + demoPath);
                using (var parser = new DemoParser(fileStream))
                {
                    parser.ParseHeader();

                    string map = parser.Map;

                    Console.WriteLine("Map: " + map);

                    bool hasMatchStarted = false;
                    bool firstBlood = true;
                    int round = 0;
                    Dictionary<Player, int> killsThisRound = new Dictionary<Player, int>();
                    Dictionary<Player, int> entryFrags = new Dictionary<Player, int>();
                    Dictionary<Player, int> entryFragAttempts = new Dictionary<Player, int>();
                    Dictionary<Player, Rating> ratings = new Dictionary<Player, Rating>();

                    parser.MatchStarted += (sender, e) =>
                    {
                        hasMatchStarted = true;
                    };

                    parser.RoundStart += (sender, e) =>
                    {
                        if (!hasMatchStarted)
                            return;

                        firstBlood = true;
                        round++;
                        killsThisRound.Clear();
                        foreach (var player in parser.PlayingParticipants)
                        {
                            if (!ratings.ContainsKey(player))
                            {
                                ratings.Add(player, new Rating());
                            }

                            ratings[player].roundsPlayed++;
                        }
                    };

                    parser.RoundEnd += (sender, e) =>
                    {
                        if (!hasMatchStarted)
                            return;

                        //firstBlood = true;
                        //round++;
                        //killsThisRound.Clear();
                        foreach (var player in killsThisRound.Keys)
                        {
                            if (!ratings.ContainsKey(player))
                            {
                                ratings.Add(player,new Rating());
                            }

                            ratings[player].multipleKillsDictionary[killsThisRound[player]]++;
                        }
                    };

                    parser.PlayerKilled += (object sender, PlayerKilledEventArgs e) => {

                    if (!hasMatchStarted)
                        return;
                        //the killer is null if you're killed by the world - eg. by falling
                        if (e.Killer != null)
                        {
                            if (!killsThisRound.ContainsKey(e.Killer))
                                killsThisRound[e.Killer] = 0;

                            if(e.Killer.Team == e.Victim.Team)
                            {
                                //killsThisRound[e.Killer]--;

                            }
                            else
                            {
                                killsThisRound[e.Killer]++;
                            }
                            //Remember how many kills each player made this rounds

                            if (!ratings.ContainsKey(e.Victim))
                            {
                                ratings.Add(e.Victim, new Rating());
                            }

                            ratings[e.Victim].deaths++;

                            if (firstBlood)
                            {
                                if (!entryFrags.ContainsKey(e.Killer))
                                    entryFrags[e.Killer] = 0;

                                entryFrags[e.Killer]++;

                                if (!entryFragAttempts.ContainsKey(e.Killer))
                                    entryFragAttempts[e.Killer] = 0;

                                entryFragAttempts[e.Killer]++;

                                if (!entryFragAttempts.ContainsKey(e.Victim))
                                    entryFragAttempts[e.Victim] = 0;

                                entryFragAttempts[e.Victim]++;

                                firstBlood = false;
                            }
                        }
                    };

                    parser.ParseToEnd();

                    //foreach(var player in killsThisRound.Keys)
                    //{
                    //    if (!entryFragAttempts.ContainsKey(player))
                    //    {
                    //        entryFragAttempts[player] = 0;
                    //    }

                    //    if (!entryFrags.ContainsKey(player))
                    //    {
                    //        entryFrags[player] = 0;
                    //    }

                    //    Console.WriteLine(player.Name + "(" + player.Team + ")" + " entry frags: " + entryFrags[player] + "/" + entryFragAttempts[player]);
                    //}

                    foreach (var player in ratings.Keys)
                    {
                        Console.WriteLine(player.Name + "(" + player.Team + ")" + " rating: " + ratings[player].getRating());
                    }

                }
            }
        }
示例#34
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            while (!bitstream.ChunkFinished)
            {
                var desc     = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;

                if ((fieldnum == 7) && (wireType == 2))
                {
                    // Entity data is special.
                    // We'll simply hope that gaben is nice and sends
                    // entity_data last, just like he should.

                    var len = bitstream.ReadProtobufVarInt();
                    bitstream.BeginChunk(len * 8);
                    DemoInfo.DP.Handler.PacketEntitesHandler.Apply(this, bitstream, parser);
                    bitstream.EndChunk();
                    if (!bitstream.ChunkFinished)
                    {
                        throw new NotImplementedException("Lord Gaben wasn't nice to us :/");
                    }
                    break;
                }

                if (wireType != 0)
                {
                    throw new Exception();
                }

                var val = bitstream.ReadProtobufVarInt();

                switch (fieldnum)
                {
                case 1:
                    MaxEntries = val;
                    break;

                case 2:
                    UpdatedEntries = val;
                    break;

                case 3:
                    _IsDelta = val;
                    break;

                case 4:
                    _UpdateBaseline = val;
                    break;

                case 5:
                    Baseline = val;
                    break;

                case 6:
                    DeltaFrom = val;
                    break;

                default:
                    // silently drop
                    break;
                }
            }
        }
示例#35
0
 static void PrintRoundResults(DemoParser parser, StreamWriter outputStream, string demoName, string mapName, int ctScore, int tScore, int ctStartroundMoney, int tStartroundMoney, int ctEquipValue, int tEquipValue, int ctSaveAmount, int tSaveAmount, float ctWay, float tWay, int defuses, int plants, Dictionary<Player, int> killsThisRound, string winningFaction, List<String> ctEquipment, List<String> tEquipment)
 {
     //okay, get the topfragger:
     string nameEvent = "roundResults";
     var ctWeapons = String.Join("-", ctEquipment.ToArray());
     var tWeapons = String.Join("-", tEquipment.ToArray());
     var topfragger = killsThisRound.OrderByDescending (x => x.Value).FirstOrDefault ();
     if (topfragger.Equals (default(KeyValuePair<Player, int>)))
         topfragger = new KeyValuePair<Player, int> (new Player (), 0);
     //At the end of each round, let's write down some statistics!
     outputStream.WriteLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21},{22},{23},{24},{25},{26},{27},{28}",
     demoName,
     nameEvent,
     mapName,
     ctScore + tScore, //Round-Number
     ctScore, tScore, //how many CTs are still alive?
     parser.PlayingParticipants.Count (a => a.IsAlive && a.Team == Team.CounterTerrorist), //how many Ts are still alive?
     parser.PlayingParticipants.Count (a => a.IsAlive && a.Team == Team.Terrorist), ctStartroundMoney, tStartroundMoney, ctEquipValue, tEquipValue, ctSaveAmount, tSaveAmount, ctWay, tWay, //The kills of all CTs so far
     parser.PlayingParticipants.Where (a => a.Team == Team.CounterTerrorist).Sum (a => a.AdditionaInformations.Kills), parser.PlayingParticipants.Where (a => a.Team == Team.Terrorist).Sum (a => a.AdditionaInformations.Kills), //The deaths of all CTs so far
     parser.PlayingParticipants.Where (a => a.Team == Team.CounterTerrorist).Sum (a => a.AdditionaInformations.Deaths), parser.PlayingParticipants.Where (a => a.Team == Team.Terrorist).Sum (a => a.AdditionaInformations.Deaths), //The assists of all CTs so far
     parser.PlayingParticipants.Where (a => a.Team == Team.CounterTerrorist).Sum (a => a.AdditionaInformations.Assists), parser.PlayingParticipants.Where (a => a.Team == Team.Terrorist).Sum (a => a.AdditionaInformations.Assists), plants, defuses,
     topfragger.Key.SteamID, //The steamid of the topfragger this round
     topfragger.Value, //The amount of kills he got
     winningFaction,
     ctWeapons,
     tWeapons
     ));
 }
示例#36
0
    public static void CreateMatchInfo(MatchInfo match, out CDataGCCStrike15_v2_MatchInfo matchInfo, out ExtraMatchStats extraStats, System.Threading.CancellationToken cancelToken)
    {
        matchInfo  = null;
        extraStats = null;
        if (match.availableOffline)
        {
            CDataGCCStrike15_v2_MatchInfo tempMatchInfo = new CDataGCCStrike15_v2_MatchInfo();
            ExtraMatchStats tempExtraStats = new ExtraMatchStats();

            #region File Name Data
            ulong reservationId          = 0;
            bool  reservationIdSpecified = false;

            string[] fileNameSplits = match.fileName.Split('_');
            if (match.fileName.IndexOf("match730_") == 0 && fileNameSplits.Length == 4)
            {
                try
                {
                    reservationId          = Convert.ToUInt64(fileNameSplits[1]);
                    reservationIdSpecified = true;

                    WatchableMatchInfo watchablematchinfo = new WatchableMatchInfo();
                    watchablematchinfo.tv_port       = Convert.ToUInt32(fileNameSplits[2]);
                    watchablematchinfo.server_ip     = Convert.ToUInt32(fileNameSplits[3]);
                    tempMatchInfo.watchablematchinfo = watchablematchinfo;
                }
                catch (Exception)
                { }
            }
            #endregion

            using (FileStream fileStream = File.Open(match.GetMatchFilePath(), FileMode.Open, FileAccess.Read))
                using (DemoInfo.DemoParser dp = new DemoInfo.DemoParser(fileStream))
                {
                    #region Data Analysis
                    #region Match Info Variables
                    int matchStartTick = 0;

                    CMsgGCCStrike15_v2_MatchmakingServerRoundStats currentRoundStats = null;
                    Dictionary <uint, int>         totalAssists        = new Dictionary <uint, int>();
                    Dictionary <uint, int>         totalDeaths         = new Dictionary <uint, int>();
                    Dictionary <uint, int>         totalEnemyHeadshots = new Dictionary <uint, int>();
                    Dictionary <uint, int>         totalEnemyKills     = new Dictionary <uint, int>();
                    Dictionary <uint, int>         totalKills          = new Dictionary <uint, int>();
                    Dictionary <uint, int>         totalMvps           = new Dictionary <uint, int>();
                    Dictionary <uint, int>         totalScores         = new Dictionary <uint, int>();
                    List <List <DemoInfo.Player> > playerTeams         = new List <List <DemoInfo.Player> >();

                    //List<uint> accountIds = new List<uint>();
                    int[] totalTeamScore = new int[2];
                    #endregion

                    Action <uint> AddPlayerToCurrentRound = (accountId) =>
                    {
                        currentRoundStats.reservation.account_ids.Add(accountId);
                        currentRoundStats.assists.Add(0);
                        currentRoundStats.deaths.Add(0);
                        currentRoundStats.enemy_headshots.Add(0);
                        currentRoundStats.enemy_kills.Add(0);
                        currentRoundStats.kills.Add(0);
                        currentRoundStats.mvps.Add(0);
                        currentRoundStats.scores.Add(0);
                    };
                    Func <uint, int> GetPlayerIndex = (accountId) =>
                    {
                        int playerIndex = currentRoundStats.reservation.account_ids.IndexOf(accountId);
                        if (playerIndex < 0)
                        {
                            AddPlayerToCurrentRound(accountId);
                            playerIndex = currentRoundStats.reservation.account_ids.Count - 1;
                        }
                        return(playerIndex);
                    };

                    EventHandler <DemoInfo.MatchStartedEventArgs> matchStartedHandler = (obj, msea) =>
                    {
                        matchStartTick = dp.CurrentTick;

                        foreach (var player in dp.PlayerInformations)
                        {
                            if (player != null && player.SteamID > 0)
                            {
                                uint accountId = new SteamKit2.SteamID((ulong)player.SteamID).AccountID;

                                #region Extra Stats Data
                                tempExtraStats.accountIds.Add(accountId);
                                tempExtraStats.playerNames.Add(player.Name);
                                #endregion

                                var teamToAddTo = playerTeams.Find((team) => team.Exists((teamPlayer) => teamPlayer.Team == player.Team));
                                if (teamToAddTo == null)
                                {
                                    teamToAddTo = new List <DemoInfo.Player>();
                                    playerTeams.Add(teamToAddTo);
                                }
                                teamToAddTo.Add(player);
                            }
                        }
                    };
                    EventHandler <DemoInfo.RoundStartedEventArgs> roundStartedHandler = (obj, rsea) =>
                    {
                        #region Match Info Data
                        currentRoundStats = new CMsgGCCStrike15_v2_MatchmakingServerRoundStats();
                        tempMatchInfo.roundstatsall.Add(currentRoundStats);

                        currentRoundStats.team_scores.AddRange(totalTeamScore);

                        CMsgGCCStrike15_v2_MatchmakingGC2ServerReserve reservation = new CMsgGCCStrike15_v2_MatchmakingGC2ServerReserve();
                        currentRoundStats.reservation = reservation;
                        foreach (var player in dp.PlayerInformations)
                        {
                            if (player != null && player.SteamID > 0)
                            {
                                AddPlayerToCurrentRound(new SteamKit2.SteamID((ulong)player.SteamID).AccountID);
                            }
                        }
                        #endregion
                        #region Extra Stats Data
                        tempExtraStats.roundStartTicks.Add(dp.CurrentTick);
                        #endregion
                    };
                    EventHandler <DemoInfo.PlayerKilledEventArgs> playerKilledHandler = (obj, pkea) =>
                    {
                        if (currentRoundStats != null)
                        {
                            if (pkea.Victim?.SteamID > 0)
                            {
                                uint victimAccountId = new SteamKit2.SteamID((ulong)pkea.Victim.SteamID).AccountID;
                                int  victimIndex     = GetPlayerIndex(victimAccountId);
                                UnityEngine.Debug.Assert(victimIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + victimIndex + " accountId: " + victimAccountId + " name " + pkea.Victim.Name);
                                if (victimIndex > -1)
                                {
                                    if (!totalDeaths.ContainsKey(victimAccountId))
                                    {
                                        totalDeaths[victimAccountId] = 0;
                                    }
                                    currentRoundStats.deaths[victimIndex] = ++totalDeaths[victimAccountId];
                                }
                            }
                            if (pkea.Killer?.SteamID > 0)
                            {
                                uint killerAccountId = new SteamKit2.SteamID((ulong)pkea.Killer.SteamID).AccountID;
                                int  killerIndex     = GetPlayerIndex(killerAccountId);
                                UnityEngine.Debug.Assert(killerIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + killerIndex + " accountId: " + killerAccountId + " name " + pkea.Killer.Name);
                                if (killerIndex > -1)
                                {
                                    if (!totalKills.ContainsKey(killerAccountId))
                                    {
                                        totalKills[killerAccountId] = 0;
                                    }
                                    currentRoundStats.kills[killerIndex] = ++totalKills[killerAccountId];

                                    bool enemyKill = pkea.Victim.TeamID != pkea.Killer.TeamID;
                                    if (!totalEnemyKills.ContainsKey(killerAccountId))
                                    {
                                        totalEnemyKills[killerAccountId] = 0;
                                    }
                                    currentRoundStats.enemy_kills[killerIndex] += enemyKill ? ++totalEnemyKills[killerAccountId] : 0;
                                    if (!totalEnemyHeadshots.ContainsKey(killerAccountId))
                                    {
                                        totalEnemyHeadshots[killerAccountId] = 0;
                                    }
                                    currentRoundStats.enemy_headshots[killerIndex] += enemyKill && pkea.Headshot ? ++totalEnemyHeadshots[killerAccountId] : 0;
                                }
                            }
                            if (pkea.Assister?.SteamID > 0)
                            {
                                uint assisterAccountId = new SteamKit2.SteamID((ulong)pkea.Assister.SteamID).AccountID;
                                int  assisterIndex     = GetPlayerIndex(assisterAccountId);
                                UnityEngine.Debug.Assert(assisterIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + assisterIndex + " accountId: " + assisterAccountId + " name " + pkea.Assister.Name);
                                if (assisterIndex > -1)
                                {
                                    if (!totalAssists.ContainsKey(assisterAccountId))
                                    {
                                        totalAssists[assisterAccountId] = 0;
                                    }
                                    currentRoundStats.assists[assisterIndex] = ++totalAssists[assisterAccountId];
                                }
                            }
                        }
                    };
                    EventHandler <DemoInfo.RoundMVPEventArgs> roundMVPHandler = (obj, rmea) =>
                    {
                        if (rmea.Player?.SteamID > 0)
                        {
                            uint playerAccountId = new SteamKit2.SteamID((ulong)rmea.Player.SteamID).AccountID;
                            if (!totalMvps.ContainsKey(playerAccountId))
                            {
                                totalMvps[playerAccountId] = 0;
                            }

                            int playerIndex = GetPlayerIndex(playerAccountId);
                            UnityEngine.Debug.Assert(playerIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + playerIndex + " accountId: " + playerAccountId + " name " + rmea.Player.Name);
                            if (playerIndex > -1 && playerIndex < currentRoundStats.mvps.Count)
                            {
                                currentRoundStats.mvps[playerIndex] = ++totalMvps[playerAccountId];
                            }
                        }
                    };
                    EventHandler <DemoInfo.RoundEndedEventArgs> roundEndedHandler = (obj, reea) =>
                    {
                        #region Match Info Data
                        Debug.Assert(currentRoundStats != null, "How can you end a round without starting it!? @tick " + dp.CurrentTick);
                        if (currentRoundStats != null)
                        {
                            if (reea.Winner != DemoInfo.Team.Spectate)
                            {
                                int teamIndex = playerTeams.FindIndex((team) => team[0].Team == reea.Winner);
                                if (teamIndex > -1 && teamIndex < totalTeamScore.Length)
                                {
                                    currentRoundStats.team_scores[teamIndex] = ++totalTeamScore[teamIndex];
                                }
                            }
                            currentRoundStats.match_duration = (int)((dp.CurrentTick - matchStartTick) * dp.TickTime);

                            foreach (var player in dp.PlayerInformations)
                            {
                                if (player != null && player.SteamID > 0)
                                {
                                    uint playerAccountId = new SteamKit2.SteamID((ulong)player.SteamID).AccountID;
                                    int  playerIndex     = GetPlayerIndex(playerAccountId);
                                    Debug.Assert(playerIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + playerIndex + " accountId: " + playerAccountId + " name " + player.Name);
                                    currentRoundStats.scores[playerIndex] = player.AdditionaInformations.Score;
                                }
                            }
                        }
                        #endregion
                        #region Extra Stats Data
                        tempExtraStats.roundEndTicks.Add(dp.CurrentTick);
                        tempExtraStats.roundWinner.Add((int)reea.Winner);
                        #endregion
                    };
                    #endregion

                    dp.MatchStarted += matchStartedHandler;
                    dp.RoundStart   += roundStartedHandler;
                    dp.PlayerKilled += playerKilledHandler;
                    dp.RoundMVP     += roundMVPHandler;
                    dp.RoundEnd     += roundEndedHandler;

                    dp.ParseHeader();
                    while (dp.ParseNextTick() && !cancelToken.IsCancellationRequested)
                    {
                        match.infoProgress = dp.CurrentTick / (float)dp.Header.PlaybackFrames;
                    }

                    dp.MatchStarted -= matchStartedHandler;
                    dp.RoundStart   -= roundStartedHandler;
                    dp.PlayerKilled -= playerKilledHandler;
                    dp.RoundMVP     -= roundMVPHandler;
                    dp.RoundEnd     -= roundEndedHandler;

                    #region Last round stats
                    if (reservationIdSpecified)
                    {
                        currentRoundStats.reservationid = reservationId;
                    }
                    currentRoundStats.reservation.game_type = (uint)(GameType)Enum.Parse(typeof(GameType), dp.Map);

                    if (totalTeamScore[0] != totalTeamScore[1])
                    {
                        var winningTeam = (DemoInfo.Team)currentRoundStats.round_result;
                        currentRoundStats.match_result = (winningTeam == DemoInfo.Team.Terrorist ? 1 : 2); //1 is CT, 2 is T. I do the switching because of team switching at half
                    }
                    else
                    {
                        currentRoundStats.match_result = 0;
                    }
                    #endregion
                }

            if (cancelToken.IsCancellationRequested)
            {
                tempMatchInfo  = null;
                tempExtraStats = null;
            }
            matchInfo  = tempMatchInfo;
            extraStats = tempExtraStats;
        }
    }
示例#37
0
		public void Parse(IBitStream bitstream, DemoParser parser)
		{
			GameEventHandler.HandleGameEventList(ReadDescriptors(bitstream), parser);
		}
示例#38
0
        public void Parse(IBitStream bitstream, DemoParser parser)
        {
            Keys = new List <object>();
            while (!bitstream.ChunkFinished)
            {
                var desc     = bitstream.ReadProtobufVarInt();
                var wireType = desc & 7;
                var fieldnum = desc >> 3;
                if ((wireType == 2) && (fieldnum == 1))
                {
                    EventName = bitstream.ReadProtobufString();
                }
                else if ((wireType == 0) && (fieldnum == 2))
                {
                    EventId = bitstream.ReadProtobufVarInt();
                }
                else if ((wireType == 2) && (fieldnum == 3))
                {
                    bitstream.BeginChunk(bitstream.ReadProtobufVarInt() * 8);

                    /*
                     * Hope and pray that gaben is once again nice to us and
                     * sends 'type' first, then the respective member, then NOTHING.
                     */
                    desc     = bitstream.ReadProtobufVarInt();
                    wireType = desc & 7;
                    fieldnum = desc >> 3;
                    if ((wireType != 0) || (fieldnum != 1))
                    {
                        throw new Exception("Lord Gaben wasn't nice to us :/");
                    }

                    var typeMember = bitstream.ReadProtobufVarInt();
                    desc     = bitstream.ReadProtobufVarInt();
                    wireType = desc & 7;
                    fieldnum = desc >> 3;

                    if (fieldnum != (typeMember + 1))
                    {
                        throw new Exception("Lord Gaben wasn't nice to us :/ (srsly wtf!?)");
                    }

                    switch (typeMember)
                    {
                    case 1:                     // string
                        if (wireType != 2)
                        {
                            throw new Exception("proto definition differs");
                        }
                        Keys.Add(bitstream.ReadProtobufString());
                        break;

                    case 2:                     // float
                        if (wireType != 5)
                        {
                            throw new Exception("proto definition differs");
                        }
                        Keys.Add(bitstream.ReadFloat());
                        break;

                    case 3:                     // long
                    case 4:                     // short
                    case 5:                     // byte
                        if (wireType != 0)
                        {
                            throw new Exception("proto definition differs");
                        }
                        Keys.Add(bitstream.ReadProtobufVarInt());
                        break;

                    case 6:                     // bool
                        if (wireType != 0)
                        {
                            throw new Exception("proto definition differs");
                        }
                        Keys.Add(bitstream.ReadProtobufVarInt() != 0);
                        break;

                    default:
                        throw new Exception("Looks like they introduced a new type");
                    }

                    if (!bitstream.ChunkFinished)
                    {
                        throw new Exception("Lord Gaben tricked us! D:");
                    }

                    bitstream.EndChunk();
                }
                else
                {
                    throw new Exception();
                }
            }

            GameEventHandler.Apply(this, parser);
        }
        /*
         * For now, do everything here
         * and send directly to streamwriter
         */
        static void OutPutStreamRoundResults(DemoParser parser, StreamWriter outPutStream, Dictionary<Player,List<double>> dicPlayerVelocity)
        {
            string roundsPlayed = string.Format("{0}", parser.TScore + parser.CTScore);
            int vel020=0, vel2150=0, vel5170=0, vel71=0;
            foreach (var player in dicPlayerVelocity)
            {
                string playerName = player.Key.Name;
                player.Value.ForEach(delegate(double vel){
                    if (vel >= 0 && vel < 21)
                    {
                        vel020++;
                    }
                    if (vel >= 21 && vel < 51)
                    {
                        vel2150++;
                    }
                    if (vel >= 51 && vel < 71)
                    {
                        vel5170++;
                    }
                    if (vel >= 71)
                    {
                        vel71++;
                    }
                });

                /*
                 * We have everything.
                 * Time to create new line in .csv
                 */
                outPutStream.WriteLine(string.Format("{0};{1};{2};{3};{4};{5};",
                    roundsPlayed,
                    playerName,
                    vel020,
                    vel2150,
                    vel5170,
                    vel71));
            }
        }