Skip to content
This repository has been archived by the owner on Sep 22, 2021. It is now read-only.

ServerInfo #99

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion DemoInfo/DP/DemoPacketParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ public static void ParsePacket(IBitStream bitstream, DemoParser demo)
} else if (cmd == (int)SVC_Messages.svc_UpdateStringTable) {
new UpdateStringTable().Parse(bitstream, demo);
} else if (cmd == (int)NET_Messages.net_Tick) { //and all this other stuff
new NETTick().Parse(bitstream, demo);
new NETTick().Parse(bitstream, demo);
} else if (cmd == (int)SVC_Messages.svc_UserMessage) {
new UserMessage().Parse(bitstream, demo);
} else if (cmd == (int)SVC_Messages.svc_ServerInfo) {
new ServerInfo().Parse(bitstream, demo);
} else {
//You can use this flag to see what information the other packets contain,
//if you want. Then you can look into the objects. Has some advnatages, and some disdavantages (mostly speed),
Expand Down
137 changes: 137 additions & 0 deletions DemoInfo/DP/FastNetmessages/ServerInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using System;
using System.IO;

namespace DemoInfo
{
public struct ServerInfo
{
public Int32 Protocol;
public Int32 ServerCount;
public bool IsDedicated;
public bool IsOfficialValveServer;
public bool IsHltv;
public bool IsReplay;
public bool IsRedirectingToProxyRelay;
public Int32 COs;
public UInt32 MapCrc;
public UInt32 ClientCrc;
public UInt32 StringTableCrc;
public Int32 MaxClients;
public Int32 MaxClasses;
public Int32 PlayerSlot;
public float TickInterval;
public string GameDir;
public string MapName;
public string MapGroupName;
public string SkyName;
public string HostName;
public UInt32 PublicIp;
public UInt64 UgcMapId;


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;
}
}
}
}
}
}
70 changes: 68 additions & 2 deletions DemoInfo/DemoParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ public class DemoParser : IDisposable
/// </summary>
public event EventHandler<HeaderParsedEventArgs> HeaderParsed;

/// <summary>
/// Raised when header data is corrupted and timings are zero and null.
/// </summary>
public event EventHandler<HeaderParsedEventArgs> HeaderCorrupted;

/// <summary>
/// Raised when the time variables have been fixed for a demo with a corrupted header
/// </summary>
public event EventHandler<TimeFixedEventArgs> TimeFixed;

/// <summary>
/// Occurs when the match started, so when the "begin_new_match"-GameEvent is dropped.
/// This usually right before the freezetime of the 1st round. Be careful, since the players
Expand Down Expand Up @@ -259,6 +269,11 @@ public string Map {
/// <value>The header.</value>
public DemoHeader Header { get; private set; }

/// <summary>
/// True when header is corrupted
/// </summary>
public bool IsHeaderCorrupted { get; private set; }

/// <summary>
/// Gets the participants of this game
/// </summary>
Expand Down Expand Up @@ -448,16 +463,18 @@ public string TFlag
/// </summary>
/// <value>The tick rate.</value>
public float TickRate {
get { return this.Header.PlaybackFrames / this.Header.PlaybackTime; }
get { return IsHeaderCorrupted ? 1/_ticktime : this.Header.PlaybackFrames / this.Header.PlaybackTime; }
}

/// <summary>
/// How long a tick of the demo is in s^-1
/// </summary>
/// <value>The tick time.</value>
public float TickTime {
get { return this.Header.PlaybackTime / this.Header.PlaybackFrames; }
get { return IsHeaderCorrupted ? _ticktime : this.Header.PlaybackTime / this.Header.PlaybackFrames; }
}
private List<int> tickGaps = new List<int>();
private float _ticktime;

/// <summary>
/// Gets the parsing progess. 0 = beginning, ~1 = finished (it can actually be > 1, so be careful!)
Expand All @@ -474,6 +491,11 @@ public float ParsingProgess {
/// <value>The current tick.</value>
public int CurrentTick { get; private set; }

/// <summary>
/// The tickrate *of the server*
/// </summary>
public float TickInterval { get; internal set; }

/// <summary>
/// The current ingame-tick as reported by the demo-file.
/// </summary>
Expand Down Expand Up @@ -525,7 +547,18 @@ public void ParseHeader()
throw new InvalidDataException("Invalid Demo-Protocol");

Header = header;
IsHeaderCorrupted = (header.PlaybackTime == 0);

if (IsHeaderCorrupted)
{
Console.WriteLine("WARNING: The header for this demo file is corrupted. TickRate, TickTime, CurrentTime will be 0 for ticks at the start of the demo. ParsingProgress, PlaybackFrames, PlaybackTicks, PlaybackTime will always be 0.");
Console.WriteLine("HeaderCorrupted event raised, TimeFixed event will be raised when time variables are repaired.");

if (HeaderCorrupted != null)
{
HeaderCorrupted(this, new HeaderParsedEventArgs(Header));
}
}

if (HeaderParsed != null)
HeaderParsed(this, new HeaderParsedEventArgs(Header));
Expand All @@ -552,6 +585,28 @@ public void ParseToEnd(CancellationToken token)
}
}

private void FixTickTime()
{
// at the beginning of demos the tickgap can be erratic, so make sure we have 10 consecutive that are the same
int gap = tickGaps[1] - tickGaps[0];
bool isConsecutive = true;
for (int i = 1; i < tickGaps.Count - 1; i++) {
if (tickGaps[i + 1] - tickGaps[i] != gap)
{
tickGaps.Clear();
isConsecutive = false;
break;
}
}

if (isConsecutive) {
_ticktime = gap * TickInterval;

if (TimeFixed != null)
TimeFixed(this, new TimeFixedEventArgs());
}
}

/// <summary>
/// Parses the next tick of the demo.
/// </summary>
Expand All @@ -561,6 +616,15 @@ public bool ParseNextTick()
if (Header == null)
throw new InvalidOperationException ("You need to call ParseHeader first before you call ParseToEnd or ParseNextTick!");

if (IsHeaderCorrupted && _ticktime == 0 && IngameTick > 20) {
int consecutiveGaps = 10;
if (tickGaps.Count < consecutiveGaps)
tickGaps.Add(IngameTick);
else if (tickGaps.Count == consecutiveGaps) {
FixTickTime();
}
}

bool b = ParseTick();

for (int i = 0; i < RawPlayers.Length; i++) {
Expand Down Expand Up @@ -1462,6 +1526,8 @@ public void Dispose ()
this.FireNadeWithOwnerStarted = null;
this.FlashNadeExploded = null;
this.HeaderParsed = null;
this.HeaderCorrupted = null;
this.TimeFixed = null;
this.MatchStarted = null;
this.NadeReachedTarget = null;
this.PlayerKilled = null;
Expand Down
4 changes: 4 additions & 0 deletions DemoInfo/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public class TickDoneEventArgs : EventArgs
{
}

public class TimeFixedEventArgs : EventArgs
{
}

public class MatchStartedEventArgs : EventArgs
{
}
Expand Down