From 662f42945ec323e8e78b94459b2ceb0a12d52b08 Mon Sep 17 00:00:00 2001 From: UncraftedName Date: Mon, 9 Feb 2026 16:08:28 -0800 Subject: [PATCH] Add portal 2 specific usercmd fields --- .../src/Parser/Components/Packets/UserCmd.cs | 18 ++++++++++++++++++ .../src/Utils/BitStreams/BitStreamReader.cs | 1 + 2 files changed, 19 insertions(+) diff --git a/DemoParser/src/Parser/Components/Packets/UserCmd.cs b/DemoParser/src/Parser/Components/Packets/UserCmd.cs index 372aff1..cd9dab0 100644 --- a/DemoParser/src/Parser/Components/Packets/UserCmd.cs +++ b/DemoParser/src/Parser/Components/Packets/UserCmd.cs @@ -19,6 +19,11 @@ public class UserCmd : DemoPacket { public byte? Impulse; public uint? WeaponSelect, WeaponSubtype; public short? MouseDx, MouseDy; + // portal 2 + public short? PlayerHeldEntityIndex; + public short? PlayerHeldEntityThroughPortalIndex; + public ushort? CommandAcksPending; + public byte? PredictedPortalTeleports; public UserCmd(SourceDemo? demoRef, PacketFrame frameRef) : base(demoRef, frameRef) {} @@ -43,6 +48,13 @@ protected override void Parse(ref BitStreamReader bsr) { } MouseDx = (short?)uBsr.ReadUShortIfExists(); MouseDy = (short?)uBsr.ReadUShortIfExists(); + if (DemoInfo.Game == SourceGame.PORTAL_2) { + PlayerHeldEntityIndex = uBsr.ReadSShortIfExists(); + PlayerHeldEntityThroughPortalIndex = uBsr.ReadSShortIfExists(); + CommandAcksPending = uBsr.ReadUShortIfExists(); + PredictedPortalTeleports = uBsr.ReadByteIfExists(); + } + // missing fields for Dota 2 & Alien swarm - shared/usercmd.cpp if (uBsr.HasOverflowed) DemoRef.LogError($"{GetType().Name}: reader overflowed"); TimingAdjustment.AdjustFromUserCmd(this); @@ -67,6 +79,12 @@ public override void PrettyWrite(IPrettyWriter pw) { WeaponSelect?.ToString() ?? "null", WeaponSubtype?.ToString() ?? "null"); pw.AppendFormat("mouseDx, mouseDy: {0,4}, {1,4}", MouseDx?.ToString() ?? "null", MouseDy?.ToString() ?? "null"); + if (DemoInfo.Game == SourceGame.PORTAL_2) { + pw.Append($"\nplayer held entity index: {PlayerHeldEntityIndex?.ToString() ?? "null"}\n"); + pw.Append($"held entity through portal index: {PlayerHeldEntityThroughPortalIndex?.ToString() ?? "null"}\n"); + pw.Append($"command acknowledgements pending: {CommandAcksPending?.ToString() ?? "null"}\n"); + pw.Append($"predicted portal teleports: {PredictedPortalTeleports?.ToString() ?? "null"}"); + } } } diff --git a/DemoParser/src/Utils/BitStreams/BitStreamReader.cs b/DemoParser/src/Utils/BitStreams/BitStreamReader.cs index 99c4ca0..9e0de67 100644 --- a/DemoParser/src/Utils/BitStreams/BitStreamReader.cs +++ b/DemoParser/src/Utils/BitStreams/BitStreamReader.cs @@ -275,6 +275,7 @@ public void ReadVector3(out Vector3 vec3) { public byte? ReadByteIfExists() => ReadBool() ? ReadByte() : (byte?) null; public uint? ReadUIntIfExists() => ReadBool() ? ReadUInt() : (uint?)null; public ushort? ReadUShortIfExists() => ReadBool() ? ReadUShort() : (ushort?)null; + public short? ReadSShortIfExists() => ReadBool() ? ReadSShort() : (short?)null; public float? ReadFloatIfExists() => ReadBool() ? ReadFloat() : (float?)null; public uint? ReadUIntIfExists(int numBits) => ReadBool() ? ReadUInt(numBits) : (uint?)null; public int? ReadSIntIfExists(int numBits) => ReadBool() ? ReadSInt(numBits) : (int?)null;