From 732798444c8226ee3d2b8236477217aa3c7d146b Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sun, 7 Apr 2024 08:58:04 +0800 Subject: [PATCH 1/2] More detailed snapshot debug dump The method CSnapShot::DebugDump() used to print just the raw snap items. Without item names or field names: ``` 2024-04-07 09:10:01 I snapshot: data_size=356 num_items=10 2024-04-07 09:10:01 I snapshot: type=0 id=32767 2024-04-07 09:10:01 I snapshot: 0 -1824658838 933dea6a 2024-04-07 09:10:01 I snapshot: 1 -629591830 da7930ea 2024-04-07 09:10:01 I snapshot: 2 -1450210576 a98f8af0 2024-04-07 09:10:01 I snapshot: 3 914991429 3689a945 2024-04-07 09:10:01 I snapshot: type=0 id=32766 2024-04-07 09:10:01 I snapshot: 0 583701389 22ca938d 2024-04-07 09:10:01 I snapshot: 1 327171627 13803e2b 2024-04-07 09:10:01 I snapshot: 2 -1636052395 9e7bd255 2024-04-07 09:10:01 I snapshot: 3 -1901674991 8ea6be11 2024-04-07 09:10:01 I snapshot: type=0 id=32765 2024-04-07 09:10:01 I snapshot: 0 1993229659 76ce455b 2024-04-07 09:10:01 I snapshot: 1 -102024632 f9eb3a48 2024-04-07 09:10:01 I snapshot: 2 -1378361269 add7e04b 2024-04-07 09:10:01 I snapshot: 3 -1810037668 941d045c 2024-04-07 09:10:01 I snapshot: type=6 id=0 2024-04-07 09:10:01 I snapshot: 0 0 00000000 2024-04-07 09:10:01 I snapshot: 1 0 00000000 2024-04-07 09:10:01 I snapshot: 2 0 00000000 2024-04-07 09:10:01 I snapshot: 3 0 00000000 2024-04-07 09:10:01 I snapshot: 4 0 00000000 2024-04-07 09:10:01 I snapshot: 5 0 00000000 2024-04-07 09:10:01 I snapshot: 6 0 00000000 2024-04-07 09:10:01 I snapshot: 7 1 00000001 2024-04-07 09:10:01 I snapshot: type=32767 id=0 2024-04-07 09:10:01 I snapshot: 0 247983155 0ec7ec33 2024-04-07 09:10:01 I snapshot: 1 9 00000009 2024-04-07 09:10:01 I snapshot: 2 64 00000040 2024-04-07 09:10:01 I snapshot: type=11 id=0 2024-04-07 09:10:01 I snapshot: 0 -1008145940 c3e8e9ec 2024-04-07 09:10:01 I snapshot: 1 -320474428 ece5f2c4 2024-04-07 09:10:01 I snapshot: 2 -220076049 f2e1e7ef 2024-04-07 09:10:01 I snapshot: 3 -293568512 ee808000 2024-04-07 09:10:01 I snapshot: 4 -1330727040 b0aeb780 2024-04-07 09:10:01 I snapshot: 5 -2139062144 80808080 2024-04-07 09:10:01 I snapshot: 6 -2139062272 80808000 2024-04-07 09:10:01 I snapshot: 7 64 00000040 2024-04-07 09:10:01 I snapshot: 8 -403511835 e7f2e5e5 2024-04-07 09:10:01 I snapshot: 9 -286001183 eef3f7e1 2024-04-07 09:10:01 I snapshot: 10 -219905920 f2e48080 2024-04-07 09:10:01 I snapshot: 11 -2139062144 80808080 2024-04-07 09:10:01 I snapshot: 12 -2139062144 80808080 2024-04-07 09:10:01 I snapshot: 13 -2139062272 80808000 2024-04-07 09:10:01 I snapshot: 14 0 00000000 2024-04-07 09:10:01 I snapshot: 15 7199301 006dda45 2024-04-07 09:10:01 I snapshot: 16 2345678 0023cace 2024-04-07 09:10:01 I snapshot: type=10 id=0 2024-04-07 09:10:01 I snapshot: 0 1 00000001 2024-04-07 09:10:01 I snapshot: 1 0 00000000 2024-04-07 09:10:01 I snapshot: 2 0 00000000 2024-04-07 09:10:01 I snapshot: 3 -9999 ffffd8f1 2024-04-07 09:10:01 I snapshot: 4 0 00000000 2024-04-07 09:10:01 I snapshot: type=32766 id=0 2024-04-07 09:10:01 I snapshot: 0 1 00000001 2024-04-07 09:10:01 I snapshot: 1 0 00000000 2024-04-07 09:10:01 I snapshot: type=9 id=0 2024-04-07 09:10:01 I snapshot: 0 438 000001b6 2024-04-07 09:10:01 I snapshot: 1 1968 000007b0 2024-04-07 09:10:01 I snapshot: 2 913 00000391 2024-04-07 09:10:01 I snapshot: 3 0 00000000 2024-04-07 09:10:01 I snapshot: 4 0 00000000 2024-04-07 09:10:01 I snapshot: 5 0 00000000 2024-04-07 09:10:01 I snapshot: 6 0 00000000 2024-04-07 09:10:01 I snapshot: 7 0 00000000 2024-04-07 09:10:01 I snapshot: 8 -1 ffffffff 2024-04-07 09:10:01 I snapshot: 9 0 00000000 2024-04-07 09:10:01 I snapshot: 10 0 00000000 2024-04-07 09:10:01 I snapshot: 11 1968 000007b0 2024-04-07 09:10:01 I snapshot: 12 913 00000391 2024-04-07 09:10:01 I snapshot: 13 0 00000000 2024-04-07 09:10:01 I snapshot: 14 0 00000000 2024-04-07 09:10:01 I snapshot: 15 1 00000001 2024-04-07 09:10:01 I snapshot: 16 10 0000000a 2024-04-07 09:10:01 I snapshot: 17 10 0000000a 2024-04-07 09:10:01 I snapshot: 18 0 00000000 2024-04-07 09:10:01 I snapshot: 19 1 00000001 2024-04-07 09:10:01 I snapshot: 20 5 00000005 2024-04-07 09:10:01 I snapshot: 21 0 00000000 2024-04-07 09:10:01 I snapshot: type=32765 id=0 2024-04-07 09:10:01 I snapshot: 0 49152 0000c000 2024-04-07 09:10:01 I snapshot: 1 0 00000000 2024-04-07 09:10:01 I snapshot: 2 2 00000002 2024-04-07 09:10:01 I snapshot: 3 0 00000000 2024-04-07 09:10:01 I snapshot: 4 0 00000000 2024-04-07 09:10:01 I snapshot: 5 0 00000000 2024-04-07 09:10:01 I snapshot: 6 0 00000000 2024-04-07 09:10:01 I snapshot: 7 0 00000000 2024-04-07 09:10:01 I snapshot: 8 1 00000001 2024-04-07 09:10:01 I snapshot: 9 0 00000000 ``` Now there is also `CNetObjHandler::DebugDumpSnapshot(const CSnapshot *pSnap)` which prints the name of the snap item and also the names of all fields: ``` 2024-04-07 09:21:42 I snapshot: data_size=356 num_items=10 2024-04-07 09:21:42 I snapshot: EX/UUID type=0 id=32767 size=16 2024-04-07 09:21:42 I snapshot: 0 -1824658838 933dea6a 2024-04-07 09:21:42 I snapshot: 1 -629591830 da7930ea 2024-04-07 09:21:42 I snapshot: 2 -1450210576 a98f8af0 2024-04-07 09:21:42 I snapshot: 3 914991429 3689a945 2024-04-07 09:21:42 I snapshot: EX/UUID type=0 id=32766 size=16 2024-04-07 09:21:42 I snapshot: 0 583701389 22ca938d 2024-04-07 09:21:42 I snapshot: 1 327171627 13803e2b 2024-04-07 09:21:42 I snapshot: 2 -1636052395 9e7bd255 2024-04-07 09:21:42 I snapshot: 3 -1901674991 8ea6be11 2024-04-07 09:21:42 I snapshot: EX/UUID type=0 id=32765 size=16 2024-04-07 09:21:42 I snapshot: 0 1993229659 76ce455b 2024-04-07 09:21:42 I snapshot: 1 -102024632 f9eb3a48 2024-04-07 09:21:42 I snapshot: 2 -1378361269 add7e04b 2024-04-07 09:21:42 I snapshot: 3 -1810037668 941d045c 2024-04-07 09:21:42 I snapshot: GameInfo type=6 id=0 size=32 2024-04-07 09:21:42 I snapshot: 0 0 00000000 m_GameFlags=0 (min=0 max=256) 2024-04-07 09:21:42 I snapshot: 1 0 00000000 m_GameStateFlags=0 (min=0 max=256) 2024-04-07 09:21:42 I snapshot: 2 0 00000000 m_RoundStartTick=0 (NetTick) 2024-04-07 09:21:42 I snapshot: 3 0 00000000 m_WarmupTimer=0 (min=min_int(-2147483648) max=max_int(2147483647)) 2024-04-07 09:21:42 I snapshot: 4 0 00000000 m_ScoreLimit=0 (min=0 max=max_int(2147483647)) 2024-04-07 09:21:42 I snapshot: 5 0 00000000 m_TimeLimit=0 (min=0 max=max_int(2147483647)) 2024-04-07 09:21:42 I snapshot: 6 0 00000000 m_RoundNum=0 (min=0 max=max_int(2147483647)) 2024-04-07 09:21:42 I snapshot: 7 1 00000001 m_RoundCurrent=1 (min=0 max=max_int(2147483647)) 2024-04-07 09:21:42 I snapshot: (out of range) type=32767 id=0 size=12 2024-04-07 09:21:42 I snapshot: 0 247983155 0ec7ec33 2024-04-07 09:21:42 I snapshot: 1 9 00000009 2024-04-07 09:21:42 I snapshot: 2 64 00000040 2024-04-07 09:21:42 I snapshot: ClientInfo type=11 id=0 size=68 2024-04-07 09:21:42 I snapshot: 0 -1008145940 c3e8e9ec m_Name0=-1008145940 IntsToStr: Chil 2024-04-07 09:21:42 I snapshot: 1 -320474428 ece5f2c4 m_Name1=-320474428 IntsToStr: lerD 2024-04-07 09:21:42 I snapshot: 2 -220076049 f2e1e7ef m_Name2=-220076049 IntsToStr: rago 2024-04-07 09:21:42 I snapshot: 3 -293568512 ee808000 m_Name3=-293568512 IntsToStr: n 2024-04-07 09:21:42 I snapshot: 4 -1330727040 b0aeb780 m_Clan0=-1330727040 IntsToStr: 0.7 2024-04-07 09:21:42 I snapshot: 5 -2139062144 80808080 m_Clan1=-2139062144 IntsToStr: 2024-04-07 09:21:42 I snapshot: 6 -2139062272 80808000 m_Clan2=-2139062272 IntsToStr: 2024-04-07 09:21:42 I snapshot: 7 64 00000040 m_Country=64 2024-04-07 09:21:42 I snapshot: 8 -403511835 e7f2e5e5 m_Skin0=-403511835 IntsToStr: gree 2024-04-07 09:21:42 I snapshot: 9 -286001183 eef3f7e1 m_Skin1=-286001183 IntsToStr: nswa 2024-04-07 09:21:42 I snapshot: 10 -219905920 f2e48080 m_Skin2=-219905920 IntsToStr: rd 2024-04-07 09:21:42 I snapshot: 11 -2139062144 80808080 m_Skin3=-2139062144 IntsToStr: 2024-04-07 09:21:42 I snapshot: 12 -2139062144 80808080 m_Skin4=-2139062144 IntsToStr: 2024-04-07 09:21:42 I snapshot: 13 -2139062272 80808000 m_Skin5=-2139062272 IntsToStr: 2024-04-07 09:21:42 I snapshot: 14 0 00000000 m_UseCustomColor=0 (min=0 max=1) 2024-04-07 09:21:42 I snapshot: 15 7199301 006dda45 m_ColorBody=7199301 2024-04-07 09:21:42 I snapshot: 16 2345678 0023cace m_ColorFeet=2345678 2024-04-07 09:21:42 I snapshot: PlayerInfo type=10 id=0 size=20 2024-04-07 09:21:42 I snapshot: 0 1 00000001 m_Local=1 (min=0 max=1) 2024-04-07 09:21:42 I snapshot: 1 0 00000000 m_ClientId=0 (min=0 max=MAX_CLIENTS-1(63)) 2024-04-07 09:21:42 I snapshot: 2 0 00000000 m_Team=0 (min=TEAM_SPECTATORS(-1) max=TEAM_BLUE(1)) 2024-04-07 09:21:42 I snapshot: 3 -9999 ffffd8f1 m_Score=-9999 2024-04-07 09:21:42 I snapshot: 4 0 00000000 m_Latency=0 2024-04-07 09:21:42 I snapshot: (out of range) type=32766 id=0 size=8 2024-04-07 09:21:42 I snapshot: 0 1 00000001 2024-04-07 09:21:42 I snapshot: 1 0 00000000 2024-04-07 09:21:42 I snapshot: Character type=9 id=0 size=88 2024-04-07 09:21:42 I snapshot: 0 176 000000b0 m_Tick=176 2024-04-07 09:21:42 I snapshot: 1 1968 000007b0 m_X=1968 2024-04-07 09:21:42 I snapshot: 2 913 00000391 m_Y=913 2024-04-07 09:21:42 I snapshot: 3 0 00000000 m_VelX=0 2024-04-07 09:21:42 I snapshot: 4 0 00000000 m_VelY=0 2024-04-07 09:21:42 I snapshot: 5 0 00000000 m_Angle=0 2024-04-07 09:21:42 I snapshot: 6 0 00000000 m_Direction=0 (min=-1 max=1) 2024-04-07 09:21:42 I snapshot: 7 0 00000000 m_Jumped=0 (min=0 max=3) 2024-04-07 09:21:42 I snapshot: 8 -1 ffffffff m_HookedPlayer=-1 (min=-1 max=MAX_CLIENTS-1(63)) 2024-04-07 09:21:42 I snapshot: 9 0 00000000 m_HookState=0 (min=-1 max=5) 2024-04-07 09:21:42 I snapshot: 10 0 00000000 m_HookTick=0 (NetTick) 2024-04-07 09:21:42 I snapshot: 11 1968 000007b0 m_HookX=1968 2024-04-07 09:21:42 I snapshot: 12 913 00000391 m_HookY=913 2024-04-07 09:21:42 I snapshot: 13 0 00000000 m_HookDx=0 2024-04-07 09:21:42 I snapshot: 14 0 00000000 m_HookDy=0 2024-04-07 09:21:42 I snapshot: 15 1 00000001 m_PlayerFlags=1 (min=0 max=256) 2024-04-07 09:21:42 I snapshot: 16 10 0000000a m_Health=10 (min=0 max=10) 2024-04-07 09:21:42 I snapshot: 17 10 0000000a m_Armor=10 (min=0 max=10) 2024-04-07 09:21:42 I snapshot: 18 0 00000000 m_AmmoCount=0 (min=0 max=10) 2024-04-07 09:21:42 I snapshot: 19 1 00000001 m_Weapon=1 (min=0 max=NUM_WEAPONS-1(5)) 2024-04-07 09:21:42 I snapshot: 20 5 00000005 m_Emote=5 (min=0 max=6) 2024-04-07 09:21:42 I snapshot: 21 0 00000000 m_AttackTick=0 (min=0 max=max_int(2147483647)) 2024-04-07 09:21:42 I snapshot: (out of range) type=32765 id=0 size=40 2024-04-07 09:21:42 I snapshot: 0 49152 0000c000 2024-04-07 09:21:42 I snapshot: 1 0 00000000 2024-04-07 09:21:42 I snapshot: 2 2 00000002 2024-04-07 09:21:42 I snapshot: 3 0 00000000 2024-04-07 09:21:42 I snapshot: 4 0 00000000 2024-04-07 09:21:42 I snapshot: 5 0 00000000 2024-04-07 09:21:42 I snapshot: 6 0 00000000 2024-04-07 09:21:42 I snapshot: 7 0 00000000 2024-04-07 09:21:42 I snapshot: 8 1 00000001 2024-04-07 09:21:42 I snapshot: 9 0 00000000 ``` --- datasrc/compile.py | 51 +++++++++++++++++++++++--- datasrc/datatypes.py | 68 +++++++++++++++++++++++++++++++---- datasrc/network.py | 15 ++++---- datasrc/seven/compile.py | 44 +++++++++++++++++++++++ datasrc/seven/datatypes.py | 53 +++++++++++++++++++++++---- src/engine/server.h | 3 ++ src/engine/shared/snapshot.h | 4 +++ src/game/server/gamecontext.h | 2 ++ 8 files changed, 216 insertions(+), 24 deletions(-) diff --git a/datasrc/compile.py b/datasrc/compile.py index fa8522aa3..2306fc744 100644 --- a/datasrc/compile.py +++ b/datasrc/compile.py @@ -115,6 +115,8 @@ public: const char *FailedObjOn() const; const char *GetMsgName(int Type) const; + void DebugDumpSnapshot(const class CSnapshot *pSnap) const; + int DumpObj(int Type, const void *pData, int Size) const; void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker); bool TeeHistorianRecordMsg(int Type); const char *FailedMsgOn() const; @@ -133,7 +135,9 @@ def gen_network_source(): #include #include #include +#include +#include #include CNetObjHandler::CNetObjHandler() @@ -245,8 +249,47 @@ const char *CNetObjHandler::GetMsgName(int Type) const } return "(out of range)"; } + +void CNetObjHandler::DebugDumpSnapshot(const CSnapshot *pSnap) const +{ + dbg_msg("snapshot", "data_size=%d num_items=%d", pSnap->DataSize(), pSnap->NumItems()); + for(int i = 0; i < pSnap->NumItems(); i++) + { + const CSnapshotItem *pItem = pSnap->GetItem(i); + int Size = pSnap->GetItemSize(i); + int Type = pSnap->GetItemType(i); + const char *pName = GetObjName(pItem->Type()); + if(Type > OFFSET_UUID && Type < g_UuidManager.NumUuids() + OFFSET_UUID) + pName = g_UuidManager.GetName(Type); + dbg_msg("snapshot", "\\t%s type=%d id=%d size=%d", pName, pItem->Type(), pItem->Id(), Size); + if(!DumpObj(Type, pItem->Data(), Size)) + continue; + + for(size_t b = 0; b < Size / sizeof(int32_t); b++) + dbg_msg("snapshot", "\\t\\t%3d %12d\\t%08x", (int)b, pItem->Data()[b], pItem->Data()[b]); + } +} + """) + lines = [] + lines += ['int CNetObjHandler::DumpObj(int Type, const void *pData, int Size) const'] + lines += ['{'] + lines += ["\tchar aRawData[512];"] + lines += ['\tswitch(Type)'] + lines += ['\t{'] + + for item in network.Objects: + for line in item.emit_dump(network.Objects): + lines += ["\t" + line] + lines += ['\t'] + lines += ['\t}'] + lines += ['\treturn -1;'] + lines += ['};'] + lines += [''] + for line in lines: + print(line) + lines = [] lines += ["""\ void *CNetObjHandler::SecureUnpackObj(int Type, CUnpacker *pUnpacker) @@ -275,10 +318,10 @@ void *CNetObjHandler::SecureUnpackObj(int Type, CUnpacker *pUnpacker) m_pObjFailedOn = "(type out of range)"; break; } - + if(pUnpacker->Error()) m_pObjFailedOn = "(unpack error)"; - + if(m_pObjFailedOn) return 0; m_pObjFailedOn = ""; @@ -308,10 +351,10 @@ void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker) m_pMsgFailedOn = "(type out of range)"; break; } - + if(pUnpacker->Error()) m_pMsgFailedOn = "(unpack error)"; - + if(m_pMsgFailedOn) return 0; m_pMsgFailedOn = ""; diff --git a/datasrc/datatypes.py b/datasrc/datatypes.py index 8d3ce023b..98e50fdf6 100644 --- a/datasrc/datatypes.py +++ b/datasrc/datatypes.py @@ -233,6 +233,15 @@ class NetObject: lines += ["};"] return lines + def members_from_this_and_parents(self, objects): + variables = self.variables + next_base_name = self.base + while next_base_name is not None: + base_item = only([i for i in objects if i.name == next_base_name]) + variables = base_item.variables + variables + next_base_name = base_item.base + return variables + def emit_uncompressed_unpack_and_validate(self, objects): lines = [] lines += [f"case {self.enum_name}:"] @@ -240,12 +249,7 @@ class NetObject: lines += [f"\t{self.struct_name} *pData = ({self.struct_name} *)m_aUnpackedData;"] unpack_lines = [] - variables = self.variables - next_base_name = self.base - while next_base_name is not None: - base_item = only([i for i in objects if i.name == next_base_name]) - variables = base_item.variables + variables - next_base_name = base_item.base + variables = self.members_from_this_and_parents(objects) for v in variables: if not self.validate_size and v.default is None: raise ValueError(f"{v.name} in {self.name} has no default value. Member variables that do not have a default value cannot be used in a structure whose size is not validated.") @@ -260,6 +264,26 @@ class NetObject: lines += ["} break;"] return lines + def emit_dump(self, objects): + lines = [] + lines += [f"case {self.enum_name}:"] + lines += ["{"] + lines += [f"\t{self.struct_name} *pObj = ({self.struct_name} *)pData;"] + unpack_lines = [] + variables = self.members_from_this_and_parents(objects) + offset = 0 + for v in variables: + unpack_lines += ["\t"+line for line in v.emit_dump(offset)] + offset += 1 + + if len(unpack_lines) > 0: + lines += unpack_lines + else: + lines += ["\t(void)pData;"] + lines += ["return 0;"] + lines += ["};"] + return lines + class NetEvent(NetObject): def __init__(self, name, variables, ex=None): NetObject.__init__(self, name, variables, ex=ex) @@ -340,6 +364,8 @@ class NetVariable: return [] def emit_unpack_msg_check(self): return [] + def emit_dump(self, offset): + return [f"str_format(aRawData, sizeof(aRawData), \"\\t\\t%3d %12d\\t%08x\", {offset}, ((const int *)pData)[{offset}], ((const int *)pData)[{offset}]);"] class NetString(NetVariable): def emit_declaration(self): @@ -384,6 +410,16 @@ class NetIntAny(NetVariable): return [f"pData->{self.name} = pUnpacker->GetIntOrDefault({self.default});"] def emit_pack(self): return [f"pPacker->AddInt({self.name});"] + def emit_dump(self, offset): + return NetVariable(self.name).emit_dump(offset) + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d\", aRawData, pObj->{self.name});"] + +class NetTwIntString(NetIntAny): + def emit_dump(self, offset): + return NetVariable(self.name).emit_dump(offset) + \ + [f"aInts[0] = pObj->{self.name};"] + \ + ["IntsToStr(aInts, std::size(aInts), aStr, std::size(aStr));"] + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d\\tIntToStr: %s\", aRawData, pObj->{self.name}, aStr);"] class NetIntRange(NetIntAny): def __init__(self, name, min_val, max_val, default=None): @@ -394,6 +430,23 @@ class NetIntRange(NetIntAny): return [f"pData->{self.name} = ClampInt(\"{self.name}\", pData->{self.name}, {self.min}, {self.max});"] def emit_unpack_msg_check(self): return [f"if(pData->{self.name} < {self.min} || pData->{self.name} > {self.max}) {{ m_pMsgFailedOn = \"{self.name}\"; break; }}"] + def emit_dump(self, offset): + min_fmt=f"min={self.min}" + min_arg = '' + try: + int(self.min) + except ValueError: + min_fmt = f"min={self.min}(%d)" + min_arg = f", (int){self.min}" + max_fmt=f"max={self.max}" + max_arg = '' + try: + int(self.max) + except ValueError: + max_fmt = f"max={self.max}(%d)" + max_arg = f", (int){self.max}" + return NetVariable(self.name).emit_dump(offset) + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d ({min_fmt} {max_fmt})\", aRawData, pObj->{self.name}{min_arg}{max_arg});"] class NetBool(NetIntRange): def __init__(self, name, default=None): @@ -403,6 +456,9 @@ class NetBool(NetIntRange): class NetTick(NetIntAny): def __init__(self, name, default=None): NetIntAny.__init__(self,name,default=default) + def emit_dump(self, offset): + return NetVariable(self.name).emit_dump(offset) + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d (NetTick)\", aRawData, pObj->{self.name});"] class NetArray(NetVariable): def __init__(self, var, size): diff --git a/datasrc/network.py b/datasrc/network.py index 04c02748b..1c8fcd911 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -1,7 +1,8 @@ # pylint: skip-file # See https://github.com/ddnet/ddnet/issues/3507 -from datatypes import Enum, Flags, NetArray, NetBool, NetEvent, NetEventEx, NetIntAny, NetIntRange, NetMessage, NetMessageEx, NetObject, NetObjectEx, NetString, NetStringHalfStrict, NetStringStrict, NetTick +from datatypes import Enum, Flags, NetArray, NetBool, NetEvent, NetEventEx, NetIntAny, NetTwIntString, NetIntRange +from datatypes import NetMessage, NetMessageEx, NetObject, NetObjectEx, NetString, NetStringHalfStrict, NetStringStrict, NetTick Emotes = ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"] PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD", "AIM"] @@ -215,17 +216,17 @@ Objects = [ NetObject("ClientInfo", [ # 4*4 = 16 characters - NetIntAny("m_Name0"), NetIntAny("m_Name1"), NetIntAny("m_Name2"), - NetIntAny("m_Name3"), + NetTwIntString("m_Name0"), NetTwIntString("m_Name1"), NetTwIntString("m_Name2"), + NetTwIntString("m_Name3"), # 4*3 = 12 characters - NetIntAny("m_Clan0"), NetIntAny("m_Clan1"), NetIntAny("m_Clan2"), + NetTwIntString("m_Clan0"), NetTwIntString("m_Clan1"), NetTwIntString("m_Clan2"), NetIntAny("m_Country"), # 4*6 = 24 characters - NetIntAny("m_Skin0"), NetIntAny("m_Skin1"), NetIntAny("m_Skin2"), - NetIntAny("m_Skin3"), NetIntAny("m_Skin4"), NetIntAny("m_Skin5"), + NetTwIntString("m_Skin0"), NetTwIntString("m_Skin1"), NetTwIntString("m_Skin2"), + NetTwIntString("m_Skin3"), NetTwIntString("m_Skin4"), NetTwIntString("m_Skin5"), NetIntRange("m_UseCustomColor", 0, 1), @@ -552,7 +553,7 @@ Messages = [ NetIntAny("m_ServerTimeBest"), NetIntAny("m_PlayerTimeBest"), ]), - + NetMessageEx("Sv_KillMsgTeam", "killmsgteam@netmsg.ddnet.tw", [ NetIntRange("m_Team", 0, 'MAX_CLIENTS-1'), NetIntRange("m_First", -1, 'MAX_CLIENTS-1'), diff --git a/datasrc/seven/compile.py b/datasrc/seven/compile.py index 75616ca60..3d2c2119f 100644 --- a/datasrc/seven/compile.py +++ b/datasrc/seven/compile.py @@ -87,6 +87,7 @@ def main(): print("#ifndef GAME_GENERATED_PROTOCOL7_H") print("#define GAME_GENERATED_PROTOCOL7_H") print("class CUnpacker;") + print("class CSnapshot;") print("#include ") print("namespace protocol7 {") print(network.RawHeader) @@ -150,6 +151,8 @@ def main(): CNetObjHandler(); int ValidateObj(int Type, const void *pData, int Size); + void DebugDumpSnapshot(const CSnapshot *pSnap) const; + int DumpObj(int Type, const void *pData, int Size) const; const char *GetObjName(int Type) const; int GetObjSize(int Type) const; const char *FailedObjOn() const; @@ -174,6 +177,7 @@ def main(): lines += ['#include '] lines += ['#include '] lines += ['#include '] + lines += ['#include '] lines += ['namespace protocol7 {'] @@ -269,6 +273,46 @@ def main(): lines += ['};'] lines += [''] + for l in lines: + print(l) + + print("""\ +void CNetObjHandler::DebugDumpSnapshot(const ::CSnapshot *pSnap) const +{ + dbg_msg("snapshot", "data_size=%d num_items=%d", pSnap->DataSize(), pSnap->NumItems()); + for(int i = 0; i < pSnap->NumItems(); i++) + { + const CSnapshotItem *pItem = pSnap->GetItem(i); + int Size = pSnap->GetItemSize(i); + int Type = pSnap->GetItemType(i); + const char *pName = GetObjName(pItem->Type()); + if(Type > OFFSET_UUID && Type < g_UuidManager.NumUuids() + OFFSET_UUID) + pName = g_UuidManager.GetName(Type); + dbg_msg("snapshot", "\\t%s type=%d id=%d size=%d", pName, pItem->Type(), pItem->Id(), Size); + if(!DumpObj(Type, pItem->Data(), Size)) + continue; + + for(size_t b = 0; b < Size / sizeof(int32_t); b++) + dbg_msg("snapshot", "\\t\\t%3d %12d\\t%08x", (int)b, pItem->Data()[b], pItem->Data()[b]); + } +}\n""") + + lines = [] + lines += ['int CNetObjHandler::DumpObj(int Type, const void *pData, int Size) const'] + lines += ['{'] + lines += ["\tchar aRawData[512];"] + lines += ['\tswitch(Type)'] + lines += ['\t{'] + + for item in network.Objects: + for line in item.emit_dump(network.Objects): + lines += ["\t" + line] + lines += ['\t'] + lines += ['\t}'] + lines += ['\treturn -1;'] + lines += ['};'] + lines += [''] + lines += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)'] lines += ['{'] lines += ['\tm_pMsgFailedOn = 0;'] diff --git a/datasrc/seven/datatypes.py b/datasrc/seven/datatypes.py index bb3b75c33..f42da2b3d 100644 --- a/datasrc/seven/datatypes.py +++ b/datasrc/seven/datatypes.py @@ -234,24 +234,38 @@ class NetObject: lines += ["\t"+line for line in v.emit_declaration()] lines += ["};"] return lines - def emit_validate(self, objects): - lines = [f"case {self.enum_name}:"] - lines += ["{"] - lines += [f"\t{self.struct_name} *pObj = ({self.struct_name} *)pData;"] - lines += ["\tif(sizeof(*pObj) != Size) return -1;"] - + def members_from_this_and_parents(self, objects): variables = self.variables next_base_name = self.base while next_base_name is not None: base_item = only([i for i in objects if i.name == next_base_name]) variables = base_item.variables + variables next_base_name = base_item.base - + return variables + def emit_validate(self, objects): + lines = [f"case {self.enum_name}:"] + lines += ["{"] + lines += [f"\t{self.struct_name} *pObj = ({self.struct_name} *)pData;"] + lines += ["\tif(sizeof(*pObj) != Size) return -1;"] + variables = self.members_from_this_and_parents(objects) for v in variables: lines += ["\t"+line for line in v.emit_validate()] lines += ["\treturn 0;"] lines += ["}"] return lines + def emit_dump(self, objects): + lines = [f"case {self.enum_name}:"] + lines += ["{"] + lines += [f"\t{self.struct_name} *pObj = ({self.struct_name} *)pData;"] + lines += ["\tif(sizeof(*pObj) != Size) return -1;"] + variables = self.members_from_this_and_parents(objects) + offset = 0 + for v in variables: + lines += ["\t"+line for line in v.emit_dump(offset)] + offset += 1 + lines += ["\treturn 0;"] + lines += ["}"] + return lines class NetEvent(NetObject): @@ -312,6 +326,8 @@ class NetVariable: return [] def emit_unpack_check(self): return [] + def emit_dump(self, offset): + return [f"str_format(aRawData, sizeof(aRawData), \"\\t\\t%3d %12d\\t%08x\", {offset}, ((const int *)pData)[{offset}], ((const int *)pData)[{offset}]);"] class NetString(NetVariable): def emit_declaration(self): @@ -338,6 +354,9 @@ class NetIntAny(NetVariable): return [f"pMsg->{self.name} = pUnpacker->GetIntOrDefault({self.default});"] def emit_pack(self): return [f"pPacker->AddInt({self.name});"] + def emit_dump(self, offset): + return NetVariable(self.name).emit_dump(offset) + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d\", aRawData, pObj->{self.name});"] class NetIntRange(NetIntAny): def __init__(self, name, min_val, max_val, default=None): @@ -348,6 +367,23 @@ class NetIntRange(NetIntAny): return [f"if(!CheckInt(\"{self.name}\", pObj->{self.name}, {self.min}, {self.max})) return -1;"] def emit_unpack_check(self): return [f"if(!CheckInt(\"{self.name}\", pMsg->{self.name}, {self.min}, {self.max})) break;"] + def emit_dump(self, offset): + min_fmt=f"min={self.min}" + min_arg = '' + try: + int(self.min) + except ValueError: + min_fmt = f"min={self.min}(%d)" + min_arg = f", (int){self.min}" + max_fmt=f"max={self.max}" + max_arg = '' + try: + int(self.max) + except ValueError: + max_fmt = f"max={self.max}(%d)" + max_arg = f", (int){self.max}" + return NetVariable(self.name).emit_dump(offset) + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d ({min_fmt} {max_fmt})\", aRawData, pObj->{self.name}{min_arg}{max_arg});"] class NetEnum(NetIntRange): def __init__(self, name, enum): @@ -366,6 +402,9 @@ class NetFlag(NetIntAny): return [f"if(!CheckFlag(\"{self.name}\", pObj->{self.name}, {self.mask})) return -1;"] def emit_unpack_check(self): return [f"if(!CheckFlag(\"{self.name}\", pMsg->{self.name}, {self.mask})) break;"] + def emit_dump(self, offset): + return NetVariable(self.name).emit_dump(offset) + \ + [f"dbg_msg(\"snapshot\", \"%s\\t{self.name}=%d (mask=%d)\", aRawData, pObj->{self.name}, {self.mask});"] class NetBool(NetIntRange): def __init__(self, name, default=None): diff --git a/src/engine/server.h b/src/engine/server.h index 462afbb97..148590721 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -347,6 +347,9 @@ public: virtual const char *Version() const = 0; virtual const char *NetVersion() const = 0; + virtual CNetObjHandler *GetNetObjHandler() = 0; + virtual protocol7::CNetObjHandler *GetNetObjHandler7() = 0; + // DDRace virtual void OnPreTickTeehistorian() = 0; diff --git a/src/engine/shared/snapshot.h b/src/engine/shared/snapshot.h index 24aeaafa9..d7d44fe99 100644 --- a/src/engine/shared/snapshot.h +++ b/src/engine/shared/snapshot.h @@ -53,6 +53,7 @@ public: }; int NumItems() const { return m_NumItems; } + int DataSize() const { return m_DataSize; } const CSnapshotItem *GetItem(int Index) const; int GetItemSize(int Index) const; int GetItemIndex(int Key) const; @@ -62,6 +63,9 @@ public: const void *FindItem(int Type, int Id) const; unsigned Crc() const; + // Prints the raw snapshot data showing item and int boundaries. + // See also `CNetObjHandler::DebugDumpSnapshot(const CSnapshot *pSnap)` + // For more detailed annotations of the data. void DebugDump() const; bool IsValid(size_t ActualSize) const; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index dd5868d07..4388fed40 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -169,6 +169,8 @@ public: IAntibot *Antibot() { return m_pAntibot; } CTeeHistorian *TeeHistorian() { return &m_TeeHistorian; } bool TeeHistorianActive() const { return m_TeeHistorianActive; } + CNetObjHandler *GetNetObjHandler() override { return &m_NetObjHandler; } + protocol7::CNetObjHandler *GetNetObjHandler7() override { return &m_NetObjHandler7; } CGameContext(); CGameContext(int Reset); From 8fc437bea6ea906002c28240fea62f2ef2d8ce4e Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Fri, 19 Jul 2024 08:40:19 +0800 Subject: [PATCH 2/2] Use arrays for snap strings --- datasrc/network.py | 8 +++----- src/game/client/gameclient.cpp | 6 +++--- src/game/client/sixup_translate_snapshot.cpp | 6 +++--- src/game/server/player.cpp | 12 ++++++------ src/tools/demo_extract_chat.cpp | 2 +- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/datasrc/network.py b/datasrc/network.py index 1c8fcd911..f36527c48 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -216,17 +216,15 @@ Objects = [ NetObject("ClientInfo", [ # 4*4 = 16 characters - NetTwIntString("m_Name0"), NetTwIntString("m_Name1"), NetTwIntString("m_Name2"), - NetTwIntString("m_Name3"), + NetArray(NetTwIntString("m_aName"), 4), # 4*3 = 12 characters - NetTwIntString("m_Clan0"), NetTwIntString("m_Clan1"), NetTwIntString("m_Clan2"), + NetArray(NetTwIntString("m_aClan"), 3), NetIntAny("m_Country"), # 4*6 = 24 characters - NetTwIntString("m_Skin0"), NetTwIntString("m_Skin1"), NetTwIntString("m_Skin2"), - NetTwIntString("m_Skin3"), NetTwIntString("m_Skin4"), NetTwIntString("m_Skin5"), + NetArray(NetTwIntString("m_aSkin"), 6), NetIntRange("m_UseCustomColor", 0, 1), diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 84bb4ddff..c54c59bc4 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1533,13 +1533,13 @@ void CGameClient::OnNewSnapshot() { CClientData *pClient = &m_aClients[ClientId]; - if(!IntsToStr(&pInfo->m_Name0, 4, pClient->m_aName, std::size(pClient->m_aName))) + if(!IntsToStr(pInfo->m_aName, 4, pClient->m_aName, std::size(pClient->m_aName))) { str_copy(pClient->m_aName, "nameless tee"); } - IntsToStr(&pInfo->m_Clan0, 3, pClient->m_aClan, std::size(pClient->m_aClan)); + IntsToStr(pInfo->m_aClan, 3, pClient->m_aClan, std::size(pClient->m_aClan)); pClient->m_Country = pInfo->m_Country; - IntsToStr(&pInfo->m_Skin0, 6, pClient->m_aSkinName, std::size(pClient->m_aSkinName)); + IntsToStr(pInfo->m_aSkin, 6, pClient->m_aSkinName, std::size(pClient->m_aSkinName)); pClient->m_UseCustomColor = pInfo->m_UseCustomColor; pClient->m_ColorBody = pInfo->m_ColorBody; diff --git a/src/game/client/sixup_translate_snapshot.cpp b/src/game/client/sixup_translate_snapshot.cpp index 2c33f4e1d..8555fe78c 100644 --- a/src/game/client/sixup_translate_snapshot.cpp +++ b/src/game/client/sixup_translate_snapshot.cpp @@ -146,10 +146,10 @@ int CGameClient::TranslateSnap(CSnapshot *pSnapDstSix, CSnapshot *pSnapSrcSeven, return -2; CNetObj_ClientInfo Info6 = {}; - StrToInts(&Info6.m_Name0, 4, Client.m_aName); - StrToInts(&Info6.m_Clan0, 3, Client.m_aClan); + StrToInts(Info6.m_aName, 4, Client.m_aName); + StrToInts(Info6.m_aClan, 3, Client.m_aClan); Info6.m_Country = Client.m_Country; - StrToInts(&Info6.m_Skin0, 6, Client.m_aSkinName); + StrToInts(Info6.m_aSkin, 6, Client.m_aSkinName); Info6.m_UseCustomColor = Client.m_UseCustomColor; Info6.m_ColorBody = Client.m_ColorBody; Info6.m_ColorFeet = Client.m_ColorFeet; diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 2b638cc8b..c2fc83fd5 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -317,10 +317,10 @@ void CPlayer::Snap(int SnappingClient) if(!pClientInfo) return; - StrToInts(&pClientInfo->m_Name0, 4, Server()->ClientName(m_ClientId)); - StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientId)); + StrToInts(pClientInfo->m_aName, 4, Server()->ClientName(m_ClientId)); + StrToInts(pClientInfo->m_aClan, 3, Server()->ClientClan(m_ClientId)); pClientInfo->m_Country = Server()->ClientCountry(m_ClientId); - StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_aSkinName); + StrToInts(pClientInfo->m_aSkin, 6, m_TeeInfos.m_aSkinName); pClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor; pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody; pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet; @@ -467,9 +467,9 @@ void CPlayer::FakeSnap() if(!pClientInfo) return; - StrToInts(&pClientInfo->m_Name0, 4, " "); - StrToInts(&pClientInfo->m_Clan0, 3, ""); - StrToInts(&pClientInfo->m_Skin0, 6, "default"); + StrToInts(pClientInfo->m_aName, 4, " "); + StrToInts(pClientInfo->m_aClan, 3, ""); + StrToInts(pClientInfo->m_aSkin, 6, "default"); if(m_Paused != PAUSE_PAUSED) return; diff --git a/src/tools/demo_extract_chat.cpp b/src/tools/demo_extract_chat.cpp index 323b139c9..da37c5056 100644 --- a/src/tools/demo_extract_chat.cpp +++ b/src/tools/demo_extract_chat.cpp @@ -98,7 +98,7 @@ public: if(ClientId < MAX_CLIENTS) { CClientData *pClient = &m_aClients[ClientId]; - IntsToStr(&pInfo->m_Name0, 4, pClient->m_aName, sizeof(pClient->m_aName)); + IntsToStr(pInfo->m_aName, 4, pClient->m_aName, sizeof(pClient->m_aName)); } } }