Closed saul closed 9 months ago
BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
AMD EPYC 7763, 1 CPU, 4 logical and 2 physical cores
.NET SDK 8.0.200
[Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
Job-LFXIPO : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
Job-KRGKAI : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
InvocationCount=1 MaxIterationCount=16 UnrollFactor=1
WarmupCount=1
Method | Job | Arguments | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|---|
ParseDemo | Job-LFXIPO | /p:Baseline=true | 2.335 s | 0.0972 s | 0.0955 s | 1.00 | 0.00 | 6000.0000 | 1000.0000 | 594.31 MB | 1.00 |
ParseDemo | Job-KRGKAI | Default | 2.195 s | 0.0119 s | 0.0106 s | 0.95 | 0.04 | 5000.0000 | 2000.0000 | 489.9 MB | 0.82 |
when i do this:
await demo.StartReadingAsync(File.OpenRead(path), default);
await demo.SeekToTickAsync(new DemoTick(500), default);
it gives me:
System.IndexOutOfRangeException
HResult=0x80131508
Message=Index was outside the bounds of the array.
Source=DemoFile
StackTrace:
at DemoFile.DemoParser.OnPacketEntities(CSVCMsg_PacketEntities msg) in /_/src/DemoFile/DemoParser.Entities.cs:line 418
at DemoFile.PacketEvents.ParseNetMessage(Int32 msgType, ReadOnlySpan`1 buf) in /_/src/DemoFile/PacketEvents.cs:line 136
at DemoFile.DemoParser.OnDemoPacket(CDemoPacket msg) in /_/src/DemoFile/DemoParser.cs:line 134
at DemoFile.DemoParser.OnDemoFullPacket(CDemoFullPacket fullPacket) in /_/src/DemoFile/DemoParser.FullPacket.cs:line 157
at DemoFile.DemoEvents.ReadDemoCommand(EDemoCommands msgType, ReadOnlySpan`1 buffer) in /_/src/DemoFile/DemoEvents.cs:line 48
at DemoFile.DemoParser.<MoveNextCoreAsync>d__67.MoveNext() in /_/src/DemoFile/DemoParser.cs:line 287
at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
at DemoFile.DemoParser.<SeekToTickAsync>d__125.MoveNext() in /_/src/DemoFile/DemoParser.FullPacket.cs:line 98
at Program.<Main>d__0.MoveNext()
at Program.<Main>(String[] args)
Just pushed a fix for the IndexOutOfRangeException - can you try now?
If I seek to 5000, it gives me 1 player death event, when I seek to 50000, there are no death events. Is this expected ?
Also, for match (map Overpass) : https://www.hltv.org/matches/2369507/faze-vs-spirit-iem-katowice-2024 I get this:
Unhandled exception. System.Exception: Delta on non-existent entity 1
at DemoFile.DemoParser.OnPacketEntities(CSVCMsg_PacketEntities msg) in /_/src/DemoFile/DemoParser.Entities.cs:line 366
at DemoFile.PacketEvents.ParseNetMessage(Int32 msgType, ReadOnlySpan`1 buf) in /_/src/DemoFile/PacketEvents.cs:line 136
at DemoFile.DemoParser.OnDemoPacket(CDemoPacket msg) in /_/src/DemoFile/DemoParser.cs:line 134
at DemoFile.DemoEvents.ReadDemoCommand(EDemoCommands msgType, ReadOnlySpan`1 buffer) in /_/src/DemoFile/DemoEvents.cs:line 33
at DemoFile.DemoParser.MoveNextCoreAsync(EDemoCommands msgType, Boolean isCompressed, Int32 size, CancellationToken cancellationToken) in /_/src/DemoFile/DemoParser.cs:line 303
at DemoFile.DemoParser.SeekToTickAsync(DemoTick targetTick, CancellationToken cancellationToken) in /_/src/DemoFile/DemoParser.FullPacket.cs:line 98
at Program.Main(String[] args) in /_/examples/DemoFile.Example.Basic/Program.cs:line 19
at Program.<Main>(String[] args)
You can't depend on game events etc. occuring while seeking. This is the reason why Valve removed the round_start/end events as you can't rely on them to know when rounds are starting and finishing.
As for this:
Unhandled exception. System.Exception: Delta on non-existent entity 1
Please can you share the code that reproduces the exception?
Please can you share the code that reproduces the exception?
var path = "test.dem";
var demo = new DemoParser();
demo.Source1GameEvents.PlayerDeath += e =>
{
Console.WriteLine($"{e.Attacker?.PlayerName} [{e.Weapon}] {e.Player?.PlayerName}");
};
await demo.StartReadingAsync(File.OpenRead(path), default);
await demo.SeekToTickAsync(new DemoTick(50000), default);
You can't depend on game events etc. occuring while seeking
But why are game events firing while seeking ? In my understanding, parser should ignore all events (and entity changes) while seeking.
I've just pushed another change that should fix the seeking to tick 50,000 issue
It works now, but game events are still being fired. Is it possible to seek without invoking any callbacks ? Or without parsing anything except StringTables ?
I get some weird error:
Unhandled exception. System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
at System.Collections.Generic.List`1.set_Item(Int32 index, T value)
at DemoFile.StringTable.ReadUpdate(ReadOnlySpan`1 stringData, Int32 entries) in /_/src/DemoFile/StringTable.cs:line 126
at DemoFile.DemoParser.OnUpdateStringTable(CSVCMsg_UpdateStringTable msg) in /_/src/DemoFile/DemoParser.StringTables.cs:line 61
at DemoFile.PacketEvents.ParseNetMessage(Int32 msgType, ReadOnlySpan`1 buf) in /_/src/DemoFile/PacketEvents.cs:line 106
at DemoFile.DemoParser.OnDemoPacket(CDemoPacket msg) in /_/src/DemoFile/DemoParser.cs:line 134
at DemoFile.DemoEvents.ReadDemoCommandCore[T](Action`1 callback, MessageParser`1 parser, ReadOnlySpan`1 buffer, Boolean isCompressed) in /_/src/DemoFile/DemoEvents.cs:line 79
at DemoFile.DemoEvents.ReadDemoCommand(EDemoCommands msgType, ReadOnlySpan`1 buffer, Boolean isCompressed) in /_/src/DemoFile/DemoEvents.cs:line 37
at DemoFile.DemoParser.MoveNextCoreAsync(EDemoCommands msgType, Boolean isCompressed, Int32 size, CancellationToken cancellationToken) in /_/src/DemoFile/DemoParser.cs:line 301
at Program.TestBug(String path) in /_/examples/DemoFile.Example.Basic/Program.cs:line 73
with this code :
public static async Task TestBug(string path)
{
var stream = new MemoryStream(File.ReadAllBytes(path));
var demo = new DemoParser();
await demo.StartReadingAsync(stream, default);
var tickCount = demo.TickCount.Value;
const int FullPacketInterval = 64 * 60;
for (int i = FullPacketInterval * 4; i <= tickCount; i += FullPacketInterval)
{
Console.WriteLine($"Seeking to tick {i}");
demo = new DemoParser();
//stream = new MemoryStream(File.ReadAllBytes(path));
stream.Position = 0;
await demo.StartReadingAsync(stream, default);
await demo.SeekToTickAsync(new DemoTick(i), default);
while (await demo.MoveNextAsync(default))
{
}
}
}
This is because DemFullPackets only contains the string tables that changed since the last DemFullPacket.
I'm going to have to rethink how stringtables are stored to allow seeking. Will let you know when I've pushed a fix.
This PR adds a new
SeekToTickAsync
method that can jump to arbitrary ticks within the demo. It supports seeking backwards and forwards, and makes use of Source 2 demo 'snapshot' ticks to do this efficiently.Closes #47