//Initialisation step, should fire when parsing the demo for first time
        public static void getDataInstanceAsync(DemoParser parser, Action <float> updateProgress = null, Action <demodatainstance> getResult = null) //Report progress
        {
            BackgroundWorker bg = new BackgroundWorker();

            demodatainstance testinstance = new demodatainstance(null);

            //Assign basic information
            testinstance.info.mapname    = parser.Map;
            testinstance.info.ctName     = parser.CTClanName;
            testinstance.info.tName      = parser.TClanName;
            testinstance.info.serverName = parser.Header.ServerName;
            testinstance.info.ctScore    = parser.CTScore;
            testinstance.info.tScore     = parser.TScore;

            bg.DoWork += (sender, ee) =>
            {
                //Subscribe to events here
                parser.WeaponFired += (object o, WeaponFiredEventArgs e) =>
                {
                    //Add the weapon fired position to that players most recent round
                    testinstance.players[e.Shooter.EntityID].rounds.Last().shotsFired.Add(new vector3(
                                                                                              e.Shooter.Position.X,
                                                                                              e.Shooter.Position.Y,
                                                                                              e.Shooter.Position.Z));
                };

                //Add a new round to each player on each team, on round start
                parser.RoundStart += (object o, RoundStartedEventArgs e) =>
                {
                    //foreach (p_Team recTeam in teams)
                    //foreach (p_Player player in testinstance.players.Values.ToList())
                    //     player.rounds.Add(new p_Round());

                    //Loop over each player on round start and assign the team to it
                    foreach (DemoInfo.Player player in parser.PlayingParticipants)
                    {
                        if (player.IsAlive)
                        {
                            testinstance.players[player.EntityID].rounds.Add(new p_Round());

                            p_Team_Identifier tIdentify = p_Team_Identifier.counterterrorist;
                            if (player.Team == Team.Terrorist)
                            {
                                tIdentify = p_Team_Identifier.terrorist;
                            }

                            testinstance.players[player.EntityID].rounds.Last().teamPlayedOnRound = tIdentify;
                        }
                    }
                };

                //Log all player deaths
                parser.PlayerKilled += (object o, PlayerKilledEventArgs e) =>
                {
                    //Do a team check
                    int team = 0;
                    if (e.Victim.Team == Team.Terrorist)
                    {
                        team = 1;
                    }

                    //Add the player death
                    testinstance.players[e.Victim.EntityID].deathPositions.Add(new vector3(
                                                                                   e.Victim.Position.X,
                                                                                   e.Victim.Position.Y,
                                                                                   e.Victim.Position.Z));
                };

                int uProg      = 0;
                int tickSwitch = 0;

                //Loop through ticks here
                while (parser.ParseNextTick() != false)
                {
                    foreach (DemoInfo.Player player in parser.PlayingParticipants)
                    {
                        //Check if the player exists on the teams
                        if (!testinstance.players.ContainsKey(player.EntityID))
                        {
                            testinstance.players.Add(player.EntityID, new p_Player(player.Name, player.SteamID));
                        }
                    }

                    if (tickSwitch > 5)
                    {
                        foreach (DemoInfo.Player player in parser.PlayingParticipants)
                        {
                            //Check if the player is alive
                            if (player.IsAlive)
                            {
                                //Add the players position
                                testinstance.players[player.EntityID].rounds.Last().positions.Add(new vector3(player.Position.X, player.Position.Y, player.Position.Z));
                            }
                        }

                        tickSwitch = 0;
                    }

                    tickSwitch++;

                    //Report its progress
                    //updateProgress?.Invoke(parser.ParsingProgess);
                    uProg++;
                    if (uProg > 1000)
                    {
                        bg.ReportProgress(Convert.ToInt32(parser.ParsingProgess * 100));
                        uProg = 0;
                    }
                }


                ee.Result = testinstance;
            };
            bg.RunWorkerCompleted += (sender, e) =>
            {
                demodatainstance result = (demodatainstance)e.Result;
                getResult?.Invoke(result);
            };
            bg.WorkerReportsProgress = true;
            bg.ProgressChanged      += (sender, e) =>
            {
                updateProgress(e.ProgressPercentage);
            };

            bg.RunWorkerAsync();
        }
        public demodatainstance(DemoParser parser, Action <float> updateProgress = null) //Report progress
        {
            if (parser == null)
            {
                return;
            }


            //Assign basic information
            info.mapname    = parser.Map;
            info.ctName     = parser.CTClanName;
            info.tName      = parser.TClanName;
            info.serverName = parser.Header.ServerName;
            info.ctScore    = parser.CTScore;
            info.tScore     = parser.TScore;

            #region event subscription
            //Subscribe to events here
            parser.WeaponFired += (object o, WeaponFiredEventArgs e) =>
            {
                //Add the weapon fired position to that players most recent round
                players[e.Shooter.EntityID].rounds.Last().shotsFired.Add(new vector3(
                                                                             e.Shooter.Position.X,
                                                                             e.Shooter.Position.Y,
                                                                             e.Shooter.Position.Z));
            };

            //Add a new round to each player on each team, on round start
            parser.RoundStart += (object o, RoundStartedEventArgs e) =>
            {
                //foreach (p_Team recTeam in teams)
                foreach (p_Player player in players.Values.ToList())
                {
                    player.rounds.Add(new p_Round());
                }

                //Loop over each player on round start and assign the team to it
                foreach (DemoInfo.Player player in parser.PlayingParticipants)
                {
                    p_Team_Identifier tIdentify = p_Team_Identifier.counterterrorist;
                    if (player.Team == Team.Terrorist)
                    {
                        tIdentify = p_Team_Identifier.terrorist;
                    }

                    players[player.EntityID].rounds.Last().teamPlayedOnRound = tIdentify;
                }
            };

            //Log all player deaths
            parser.PlayerKilled += (object o, PlayerKilledEventArgs e) =>
            {
                //Do a team check
                int team = 0;
                if (e.Victim.Team == Team.Terrorist)
                {
                    team = 1;
                }

                //Add the player death
                players[e.Victim.EntityID].deathPositions.Add(new vector3(
                                                                  e.Victim.Position.X,
                                                                  e.Victim.Position.Y,
                                                                  e.Victim.Position.Z));
            };
            #endregion
            try
            {
                int currentRound = 0;

                //Loop through ticks here
                while (parser.ParseNextTick() != false)
                {
                    foreach (DemoInfo.Player player in parser.PlayingParticipants)
                    {
                        //Check if the player exists on the teams
                        if (!players.ContainsKey(player.EntityID))
                        {
                            players.Add(player.EntityID, new p_Player(player.Name, player.SteamID));
                        }

                        //Check if the player is alive
                        if (player.IsAlive)
                        {
                            //Add the players position
                            players[player.EntityID].rounds[currentRound].positions.Add(new vector3(player.Position.X, player.Position.Y, player.Position.Z));
                        }
                    }

                    //Report its progress
                    updateProgress?.Invoke(parser.ParsingProgess);
                }
            }
            catch
            {
                //TODO: Work out the error types
                Console.WriteLine("Error while parsing, usual...");
            }
        }