1#include <base/mem.h>
2
3#include <engine/shared/masterserver.h>
4
5#include <game/client/gameclient.h>
6
7void CClient::PreprocessConnlessPacket7(CNetChunk *pPacket)
8{
9 if(mem_comp(a: pPacket->m_pData, b: SERVERBROWSE_INFO, size: sizeof(SERVERBROWSE_INFO)) == 0)
10 {
11 CUnpacker Up;
12 Up.Reset(pData: (unsigned char *)pPacket->m_pData + sizeof(SERVERBROWSE_INFO), Size: pPacket->m_DataSize - sizeof(SERVERBROWSE_INFO));
13 CServerInfo Info = {};
14
15 auto GetString = [&Up](auto &Buf) {
16 str_copy(Buf, Up.GetString(SanitizeType: CUnpacker::SANITIZE_CC | CUnpacker::SKIP_START_WHITESPACES));
17 };
18
19 TOKEN Token = Up.GetInt();
20 GetString(Info.m_aVersion);
21 GetString(Info.m_aName);
22 str_clean_whitespaces(str: Info.m_aName);
23
24 Up.GetString(SanitizeType: CUnpacker::SANITIZE_CC | CUnpacker::SKIP_START_WHITESPACES); // Hostname
25 GetString(Info.m_aMap);
26 GetString(Info.m_aGameType);
27 Info.m_Flags = Up.GetInt();
28 Up.GetInt(); // Server level
29 Info.m_NumPlayers = Up.GetInt();
30 Info.m_MaxPlayers = Up.GetInt();
31 Info.m_NumClients = Up.GetInt();
32 Info.m_MaxClients = Up.GetInt();
33
34 Info.m_vClients.resize(sz: std::clamp(val: Info.m_NumClients, lo: 0, hi: (int)SERVERINFO_MAX_CLIENTS));
35 for(auto &Client : Info.m_vClients)
36 {
37 GetString(Client.m_aName);
38 GetString(Client.m_aClan);
39 Client.m_Country = Up.GetInt();
40 if(!in_range(a: Client.m_Country, lower: CountryCode::MINIMUM, upper: CountryCode::MAXIMUM))
41 {
42 Client.m_Country = CountryCode::DEFAULT;
43 }
44 Client.m_Score = Up.GetInt();
45 Client.m_Player = !(Up.GetInt() & 1);
46 }
47
48 const bool IsNotVanilla = Info.m_MaxPlayers > VANILLA_MAX_CLIENTS || Info.m_MaxClients > VANILLA_MAX_CLIENTS;
49 CPacker Packer;
50 Packer.Reset();
51
52 auto PutInt = [&Packer](int Num) {
53 char aBuf[16];
54 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%d", Num);
55 Packer.AddString(pStr: aBuf);
56 };
57
58 if(!IsNotVanilla)
59 {
60 Token = Token & 0xff;
61 }
62 PutInt(Token);
63 Packer.AddString(pStr: Info.m_aVersion);
64 Packer.AddString(pStr: Info.m_aName);
65 Packer.AddString(pStr: Info.m_aMap);
66
67 if(IsNotVanilla)
68 {
69 PutInt(0); // map crc
70 PutInt(0); // map size
71 }
72
73 Packer.AddString(pStr: Info.m_aGameType);
74
75 PutInt(Info.m_Flags);
76 PutInt(Info.m_NumPlayers);
77 PutInt(Info.m_MaxPlayers);
78 PutInt(Info.m_NumClients);
79 PutInt(Info.m_MaxClients);
80
81 if(IsNotVanilla)
82 {
83 Packer.AddString(pStr: ""); // extra info, reserved
84 }
85
86 for(const auto &Client : Info.m_vClients)
87 {
88 Packer.AddString(pStr: Client.m_aName);
89 Packer.AddString(pStr: Client.m_aClan);
90
91 PutInt(Client.m_Country);
92 PutInt(Client.m_Score);
93 PutInt(Client.m_Player);
94
95 if(IsNotVanilla)
96 {
97 Packer.AddString(pStr: ""); // extra info, reserved
98 }
99 }
100
101 if(IsNotVanilla)
102 {
103 mem_copy(dest: (unsigned char *)pPacket->m_pData, source: SERVERBROWSE_INFO_EXTENDED, size: sizeof(SERVERBROWSE_INFO_EXTENDED));
104 }
105 mem_copy(dest: (unsigned char *)pPacket->m_pData + SERVERBROWSE_SIZE, source: Packer.Data(), size: Packer.Size());
106 pPacket->m_DataSize = SERVERBROWSE_SIZE + Packer.Size();
107 }
108}
109