This commit is contained in:
Chiller Dragon 2024-09-07 20:19:57 +02:00 committed by GitHub
commit c93cb1ba15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 227 additions and 37 deletions

View file

@ -115,6 +115,8 @@ public:
const char *FailedObjOn() const; const char *FailedObjOn() const;
const char *GetMsgName(int Type) 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); void *SecureUnpackMsg(int Type, CUnpacker *pUnpacker);
bool TeeHistorianRecordMsg(int Type); bool TeeHistorianRecordMsg(int Type);
const char *FailedMsgOn() const; const char *FailedMsgOn() const;
@ -133,7 +135,9 @@ def gen_network_source():
#include <engine/shared/packer.h> #include <engine/shared/packer.h>
#include <engine/shared/protocol.h> #include <engine/shared/protocol.h>
#include <engine/shared/uuid_manager.h> #include <engine/shared/uuid_manager.h>
#include <engine/shared/snapshot.h>
#include <game/gamecore.h>
#include <game/mapitems_ex.h> #include <game/mapitems_ex.h>
CNetObjHandler::CNetObjHandler() CNetObjHandler::CNetObjHandler()
@ -245,8 +249,47 @@ const char *CNetObjHandler::GetMsgName(int Type) const
} }
return "(out of range)"; 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 = []
lines += ["""\ lines += ["""\
void *CNetObjHandler::SecureUnpackObj(int Type, CUnpacker *pUnpacker) void *CNetObjHandler::SecureUnpackObj(int Type, CUnpacker *pUnpacker)

View file

@ -233,6 +233,15 @@ class NetObject:
lines += ["};"] lines += ["};"]
return 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): def emit_uncompressed_unpack_and_validate(self, objects):
lines = [] lines = []
lines += [f"case {self.enum_name}:"] lines += [f"case {self.enum_name}:"]
@ -240,12 +249,7 @@ class NetObject:
lines += [f"\t{self.struct_name} *pData = ({self.struct_name} *)m_aUnpackedData;"] lines += [f"\t{self.struct_name} *pData = ({self.struct_name} *)m_aUnpackedData;"]
unpack_lines = [] unpack_lines = []
variables = self.variables variables = self.members_from_this_and_parents(objects)
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
for v in variables: for v in variables:
if not self.validate_size and v.default is None: 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.") 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;"] lines += ["} break;"]
return lines 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): class NetEvent(NetObject):
def __init__(self, name, variables, ex=None): def __init__(self, name, variables, ex=None):
NetObject.__init__(self, name, variables, ex=ex) NetObject.__init__(self, name, variables, ex=ex)
@ -340,6 +364,8 @@ class NetVariable:
return [] return []
def emit_unpack_msg_check(self): def emit_unpack_msg_check(self):
return [] 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): class NetString(NetVariable):
def emit_declaration(self): def emit_declaration(self):
@ -384,6 +410,16 @@ class NetIntAny(NetVariable):
return [f"pData->{self.name} = pUnpacker->GetIntOrDefault({self.default});"] return [f"pData->{self.name} = pUnpacker->GetIntOrDefault({self.default});"]
def emit_pack(self): def emit_pack(self):
return [f"pPacker->AddInt({self.name});"] 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): class NetIntRange(NetIntAny):
def __init__(self, name, min_val, max_val, default=None): 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});"] return [f"pData->{self.name} = ClampInt(\"{self.name}\", pData->{self.name}, {self.min}, {self.max});"]
def emit_unpack_msg_check(self): def emit_unpack_msg_check(self):
return [f"if(pData->{self.name} < {self.min} || pData->{self.name} > {self.max}) {{ m_pMsgFailedOn = \"{self.name}\"; break; }}"] 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): class NetBool(NetIntRange):
def __init__(self, name, default=None): def __init__(self, name, default=None):
@ -403,6 +456,9 @@ class NetBool(NetIntRange):
class NetTick(NetIntAny): class NetTick(NetIntAny):
def __init__(self, name, default=None): def __init__(self, name, default=None):
NetIntAny.__init__(self,name,default=default) 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): class NetArray(NetVariable):
def __init__(self, var, size): def __init__(self, var, size):

View file

@ -1,7 +1,8 @@
# pylint: skip-file # pylint: skip-file
# See https://github.com/ddnet/ddnet/issues/3507 # 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"] Emotes = ["NORMAL", "PAIN", "HAPPY", "SURPRISE", "ANGRY", "BLINK"]
PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD", "AIM"] PlayerFlags = ["PLAYING", "IN_MENU", "CHATTING", "SCOREBOARD", "AIM"]
@ -215,17 +216,15 @@ Objects = [
NetObject("ClientInfo", [ NetObject("ClientInfo", [
# 4*4 = 16 characters # 4*4 = 16 characters
NetIntAny("m_Name0"), NetIntAny("m_Name1"), NetIntAny("m_Name2"), NetArray(NetTwIntString("m_aName"), 4),
NetIntAny("m_Name3"),
# 4*3 = 12 characters # 4*3 = 12 characters
NetIntAny("m_Clan0"), NetIntAny("m_Clan1"), NetIntAny("m_Clan2"), NetArray(NetTwIntString("m_aClan"), 3),
NetIntAny("m_Country"), NetIntAny("m_Country"),
# 4*6 = 24 characters # 4*6 = 24 characters
NetIntAny("m_Skin0"), NetIntAny("m_Skin1"), NetIntAny("m_Skin2"), NetArray(NetTwIntString("m_aSkin"), 6),
NetIntAny("m_Skin3"), NetIntAny("m_Skin4"), NetIntAny("m_Skin5"),
NetIntRange("m_UseCustomColor", 0, 1), NetIntRange("m_UseCustomColor", 0, 1),

View file

@ -87,6 +87,7 @@ def main():
print("#ifndef GAME_GENERATED_PROTOCOL7_H") print("#ifndef GAME_GENERATED_PROTOCOL7_H")
print("#define GAME_GENERATED_PROTOCOL7_H") print("#define GAME_GENERATED_PROTOCOL7_H")
print("class CUnpacker;") print("class CUnpacker;")
print("class CSnapshot;")
print("#include <engine/message.h>") print("#include <engine/message.h>")
print("namespace protocol7 {") print("namespace protocol7 {")
print(network.RawHeader) print(network.RawHeader)
@ -150,6 +151,8 @@ def main():
CNetObjHandler(); CNetObjHandler();
int ValidateObj(int Type, const void *pData, int Size); 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; const char *GetObjName(int Type) const;
int GetObjSize(int Type) const; int GetObjSize(int Type) const;
const char *FailedObjOn() const; const char *FailedObjOn() const;
@ -174,6 +177,7 @@ def main():
lines += ['#include <base/system.h>'] lines += ['#include <base/system.h>']
lines += ['#include <engine/shared/packer.h>'] lines += ['#include <engine/shared/packer.h>']
lines += ['#include <engine/shared/protocol.h>'] lines += ['#include <engine/shared/protocol.h>']
lines += ['#include <engine/shared/snapshot.h>']
lines += ['namespace protocol7 {'] lines += ['namespace protocol7 {']
@ -269,6 +273,46 @@ def main():
lines += ['};'] lines += ['};']
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 += ['void *CNetObjHandler::SecureUnpackMsg(int Type, CUnpacker *pUnpacker)']
lines += ['{'] lines += ['{']
lines += ['\tm_pMsgFailedOn = 0;'] lines += ['\tm_pMsgFailedOn = 0;']

View file

@ -234,24 +234,38 @@ class NetObject:
lines += ["\t"+line for line in v.emit_declaration()] lines += ["\t"+line for line in v.emit_declaration()]
lines += ["};"] lines += ["};"]
return lines return lines
def emit_validate(self, objects): def members_from_this_and_parents(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.variables variables = self.variables
next_base_name = self.base next_base_name = self.base
while next_base_name is not None: while next_base_name is not None:
base_item = only([i for i in objects if i.name == next_base_name]) base_item = only([i for i in objects if i.name == next_base_name])
variables = base_item.variables + variables variables = base_item.variables + variables
next_base_name = base_item.base 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: for v in variables:
lines += ["\t"+line for line in v.emit_validate()] lines += ["\t"+line for line in v.emit_validate()]
lines += ["\treturn 0;"] lines += ["\treturn 0;"]
lines += ["}"] lines += ["}"]
return 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): class NetEvent(NetObject):
@ -312,6 +326,8 @@ class NetVariable:
return [] return []
def emit_unpack_check(self): def emit_unpack_check(self):
return [] 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): class NetString(NetVariable):
def emit_declaration(self): def emit_declaration(self):
@ -338,6 +354,9 @@ class NetIntAny(NetVariable):
return [f"pMsg->{self.name} = pUnpacker->GetIntOrDefault({self.default});"] return [f"pMsg->{self.name} = pUnpacker->GetIntOrDefault({self.default});"]
def emit_pack(self): def emit_pack(self):
return [f"pPacker->AddInt({self.name});"] 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): class NetIntRange(NetIntAny):
def __init__(self, name, min_val, max_val, default=None): 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;"] return [f"if(!CheckInt(\"{self.name}\", pObj->{self.name}, {self.min}, {self.max})) return -1;"]
def emit_unpack_check(self): def emit_unpack_check(self):
return [f"if(!CheckInt(\"{self.name}\", pMsg->{self.name}, {self.min}, {self.max})) break;"] 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): class NetEnum(NetIntRange):
def __init__(self, name, enum): 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;"] return [f"if(!CheckFlag(\"{self.name}\", pObj->{self.name}, {self.mask})) return -1;"]
def emit_unpack_check(self): def emit_unpack_check(self):
return [f"if(!CheckFlag(\"{self.name}\", pMsg->{self.name}, {self.mask})) break;"] 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): class NetBool(NetIntRange):
def __init__(self, name, default=None): def __init__(self, name, default=None):

View file

@ -347,6 +347,9 @@ public:
virtual const char *Version() const = 0; virtual const char *Version() const = 0;
virtual const char *NetVersion() const = 0; virtual const char *NetVersion() const = 0;
virtual CNetObjHandler *GetNetObjHandler() = 0;
virtual protocol7::CNetObjHandler *GetNetObjHandler7() = 0;
// DDRace // DDRace
virtual void OnPreTickTeehistorian() = 0; virtual void OnPreTickTeehistorian() = 0;

View file

@ -53,6 +53,7 @@ public:
}; };
int NumItems() const { return m_NumItems; } int NumItems() const { return m_NumItems; }
int DataSize() const { return m_DataSize; }
const CSnapshotItem *GetItem(int Index) const; const CSnapshotItem *GetItem(int Index) const;
int GetItemSize(int Index) const; int GetItemSize(int Index) const;
int GetItemIndex(int Key) const; int GetItemIndex(int Key) const;
@ -62,6 +63,9 @@ public:
const void *FindItem(int Type, int Id) const; const void *FindItem(int Type, int Id) const;
unsigned Crc() 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; void DebugDump() const;
bool IsValid(size_t ActualSize) const; bool IsValid(size_t ActualSize) const;

View file

@ -1533,13 +1533,13 @@ void CGameClient::OnNewSnapshot()
{ {
CClientData *pClient = &m_aClients[ClientId]; 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"); 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; 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_UseCustomColor = pInfo->m_UseCustomColor;
pClient->m_ColorBody = pInfo->m_ColorBody; pClient->m_ColorBody = pInfo->m_ColorBody;

View file

@ -146,10 +146,10 @@ int CGameClient::TranslateSnap(CSnapshot *pSnapDstSix, CSnapshot *pSnapSrcSeven,
return -2; return -2;
CNetObj_ClientInfo Info6 = {}; CNetObj_ClientInfo Info6 = {};
StrToInts(&Info6.m_Name0, 4, Client.m_aName); StrToInts(Info6.m_aName, 4, Client.m_aName);
StrToInts(&Info6.m_Clan0, 3, Client.m_aClan); StrToInts(Info6.m_aClan, 3, Client.m_aClan);
Info6.m_Country = Client.m_Country; 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_UseCustomColor = Client.m_UseCustomColor;
Info6.m_ColorBody = Client.m_ColorBody; Info6.m_ColorBody = Client.m_ColorBody;
Info6.m_ColorFeet = Client.m_ColorFeet; Info6.m_ColorFeet = Client.m_ColorFeet;

View file

@ -169,6 +169,8 @@ public:
IAntibot *Antibot() { return m_pAntibot; } IAntibot *Antibot() { return m_pAntibot; }
CTeeHistorian *TeeHistorian() { return &m_TeeHistorian; } CTeeHistorian *TeeHistorian() { return &m_TeeHistorian; }
bool TeeHistorianActive() const { return m_TeeHistorianActive; } bool TeeHistorianActive() const { return m_TeeHistorianActive; }
CNetObjHandler *GetNetObjHandler() override { return &m_NetObjHandler; }
protocol7::CNetObjHandler *GetNetObjHandler7() override { return &m_NetObjHandler7; }
CGameContext(); CGameContext();
CGameContext(int Reset); CGameContext(int Reset);

View file

@ -317,10 +317,10 @@ void CPlayer::Snap(int SnappingClient)
if(!pClientInfo) if(!pClientInfo)
return; return;
StrToInts(&pClientInfo->m_Name0, 4, Server()->ClientName(m_ClientId)); StrToInts(pClientInfo->m_aName, 4, Server()->ClientName(m_ClientId));
StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientId)); StrToInts(pClientInfo->m_aClan, 3, Server()->ClientClan(m_ClientId));
pClientInfo->m_Country = Server()->ClientCountry(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_UseCustomColor = m_TeeInfos.m_UseCustomColor;
pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody; pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet; pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
@ -467,9 +467,9 @@ void CPlayer::FakeSnap()
if(!pClientInfo) if(!pClientInfo)
return; return;
StrToInts(&pClientInfo->m_Name0, 4, " "); StrToInts(pClientInfo->m_aName, 4, " ");
StrToInts(&pClientInfo->m_Clan0, 3, ""); StrToInts(pClientInfo->m_aClan, 3, "");
StrToInts(&pClientInfo->m_Skin0, 6, "default"); StrToInts(pClientInfo->m_aSkin, 6, "default");
if(m_Paused != PAUSE_PAUSED) if(m_Paused != PAUSE_PAUSED)
return; return;

View file

@ -98,7 +98,7 @@ public:
if(ClientId < MAX_CLIENTS) if(ClientId < MAX_CLIENTS)
{ {
CClientData *pClient = &m_aClients[ClientId]; 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));
} }
} }
} }