Merge pull request #8795 from furo321/cjsonwriter-master

Use `CJsonWriter` for creating server info JSON
This commit is contained in:
Dennis Felsing 2024-08-23 18:25:44 +00:00 committed by GitHub
commit 5dff5e9e81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 94 additions and 105 deletions

View file

@ -12,6 +12,7 @@
#include "kernel.h"
#include "message.h"
#include <engine/shared/jsonwriter.h>
#include <engine/shared/protocol.h>
#include <game/generated/protocol.h>
#include <game/generated/protocol7.h>
@ -365,10 +366,10 @@ public:
/**
* Used to report custom player info to master servers.
*
* @param aBuf Should be the json key values to add, starting with a ',' beforehand, like: ',"skin": "default", "team": 1'
* @param pJsonWriter A pointer to a CJsonStringWriter which the custom data will be added to.
* @param i The client id.
*/
virtual void OnUpdatePlayerServerInfo(char *aBuf, int BufSize, int Id) = 0;
virtual void OnUpdatePlayerServerInfo(CJsonStringWriter *pJSonWriter, int Id) = 0;
};
extern IGameServer *CreateGameServer();

View file

@ -24,6 +24,7 @@
#include <engine/shared/host_lookup.h>
#include <engine/shared/http.h>
#include <engine/shared/json.h>
#include <engine/shared/jsonwriter.h>
#include <engine/shared/masterserver.h>
#include <engine/shared/netban.h>
#include <engine/shared/network.h>
@ -2315,77 +2316,81 @@ void CServer::UpdateRegisterServerInfo()
int MaxPlayers = maximum(m_NetServer.MaxClients() - maximum(g_Config.m_SvSpectatorSlots, g_Config.m_SvReservedSlots), PlayerCount);
int MaxClients = maximum(m_NetServer.MaxClients() - g_Config.m_SvReservedSlots, ClientCount);
char aName[256];
char aGameType[32];
char aMapName[64];
char aVersion[64];
char aMapSha256[SHA256_MAXSTRSIZE];
sha256_str(m_aCurrentMapSha256[MAP_TYPE_SIX], aMapSha256, sizeof(aMapSha256));
char aInfo[16384];
str_format(aInfo, sizeof(aInfo),
"{"
"\"max_clients\":%d,"
"\"max_players\":%d,"
"\"passworded\":%s,"
"\"game_type\":\"%s\","
"\"name\":\"%s\","
"\"map\":{"
"\"name\":\"%s\","
"\"sha256\":\"%s\","
"\"size\":%d"
"},"
"\"version\":\"%s\","
"\"client_score_kind\":\"time\","
"\"requires_login\":false,"
"\"clients\":[",
MaxClients,
MaxPlayers,
JsonBool(g_Config.m_Password[0]),
EscapeJson(aGameType, sizeof(aGameType), GameServer()->GameType()),
EscapeJson(aName, sizeof(aName), g_Config.m_SvName),
EscapeJson(aMapName, sizeof(aMapName), m_aCurrentMap),
aMapSha256,
m_aCurrentMapSize[MAP_TYPE_SIX],
EscapeJson(aVersion, sizeof(aVersion), GameServer()->Version()));
CJsonStringWriter JsonWriter;
JsonWriter.BeginObject();
JsonWriter.WriteAttribute("max_clients");
JsonWriter.WriteIntValue(MaxClients);
JsonWriter.WriteAttribute("max_players");
JsonWriter.WriteIntValue(MaxPlayers);
JsonWriter.WriteAttribute("passworded");
JsonWriter.WriteBoolValue(g_Config.m_Password[0]);
JsonWriter.WriteAttribute("game_type");
JsonWriter.WriteStrValue(GameServer()->GameType());
JsonWriter.WriteAttribute("name");
JsonWriter.WriteStrValue(g_Config.m_SvName);
JsonWriter.WriteAttribute("map");
JsonWriter.BeginObject();
JsonWriter.WriteAttribute("name");
JsonWriter.WriteStrValue(m_aCurrentMap);
JsonWriter.WriteAttribute("sha256");
JsonWriter.WriteStrValue(aMapSha256);
JsonWriter.WriteAttribute("size");
JsonWriter.WriteIntValue(m_aCurrentMapSize[MAP_TYPE_SIX]);
JsonWriter.EndObject();
JsonWriter.WriteAttribute("version");
JsonWriter.WriteStrValue(GameServer()->Version());
JsonWriter.WriteAttribute("client_score_kind");
JsonWriter.WriteStrValue("time"); // "points" or "time"
JsonWriter.WriteAttribute("requires_login");
JsonWriter.WriteBoolValue(false);
JsonWriter.WriteAttribute("clients");
JsonWriter.BeginArray();
bool FirstPlayer = true;
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(m_aClients[i].IncludedInServerInfo())
{
char aCName[32];
char aCClan[32];
JsonWriter.BeginObject();
char aExtraPlayerInfo[512];
GameServer()->OnUpdatePlayerServerInfo(aExtraPlayerInfo, sizeof(aExtraPlayerInfo), i);
JsonWriter.WriteAttribute("name");
JsonWriter.WriteStrValue(ClientName(i));
char aClientInfo[1024];
str_format(aClientInfo, sizeof(aClientInfo),
"%s{"
"\"name\":\"%s\","
"\"clan\":\"%s\","
"\"country\":%d,"
"\"score\":%d,"
"\"is_player\":%s"
"%s"
"}",
!FirstPlayer ? "," : "",
EscapeJson(aCName, sizeof(aCName), ClientName(i)),
EscapeJson(aCClan, sizeof(aCClan), ClientClan(i)),
m_aClients[i].m_Country,
m_aClients[i].m_Score.value_or(-9999),
JsonBool(GameServer()->IsClientPlayer(i)),
aExtraPlayerInfo);
str_append(aInfo, aClientInfo);
FirstPlayer = false;
JsonWriter.WriteAttribute("clan");
JsonWriter.WriteStrValue(ClientClan(i));
JsonWriter.WriteAttribute("country");
JsonWriter.WriteIntValue(m_aClients[i].m_Country);
JsonWriter.WriteAttribute("score");
JsonWriter.WriteIntValue(m_aClients[i].m_Score.value_or(-9999));
JsonWriter.WriteAttribute("is_player");
JsonWriter.WriteBoolValue(GameServer()->IsClientPlayer(i));
GameServer()->OnUpdatePlayerServerInfo(&JsonWriter, i);
JsonWriter.EndObject();
}
}
str_append(aInfo, "]}");
JsonWriter.EndArray();
JsonWriter.EndObject();
m_pRegister->OnNewInfo(aInfo);
m_pRegister->OnNewInfo(JsonWriter.GetOutputString().c_str());
}
void CServer::UpdateServerInfo(bool Resend)

View file

@ -4842,78 +4842,61 @@ bool CGameContext::RateLimitPlayerMapVote(int ClientId) const
return false;
}
void CGameContext::OnUpdatePlayerServerInfo(char *aBuf, int BufSize, int Id)
void CGameContext::OnUpdatePlayerServerInfo(CJsonStringWriter *pJSonWriter, int Id)
{
if(BufSize <= 0)
return;
aBuf[0] = '\0';
if(!m_apPlayers[Id])
return;
char aCSkinName[64];
CTeeInfo &TeeInfo = m_apPlayers[Id]->m_TeeInfos;
char aJsonSkin[400];
aJsonSkin[0] = '\0';
pJSonWriter->WriteAttribute("skin");
pJSonWriter->BeginObject();
// 0.6
if(!Server()->IsSixup(Id))
{
// 0.6
pJSonWriter->WriteAttribute("name");
pJSonWriter->WriteStrValue(TeeInfo.m_aSkinName);
if(TeeInfo.m_UseCustomColor)
{
str_format(aJsonSkin, sizeof(aJsonSkin),
"\"name\":\"%s\","
"\"color_body\":%d,"
"\"color_feet\":%d",
EscapeJson(aCSkinName, sizeof(aCSkinName), TeeInfo.m_aSkinName),
TeeInfo.m_ColorBody,
TeeInfo.m_ColorFeet);
}
else
{
str_format(aJsonSkin, sizeof(aJsonSkin),
"\"name\":\"%s\"",
EscapeJson(aCSkinName, sizeof(aCSkinName), TeeInfo.m_aSkinName));
pJSonWriter->WriteAttribute("color_body");
pJSonWriter->WriteIntValue(TeeInfo.m_ColorBody);
pJSonWriter->WriteAttribute("color_feet");
pJSonWriter->WriteIntValue(TeeInfo.m_ColorFeet);
}
}
// 0.7
else
{
const char *apPartNames[protocol7::NUM_SKINPARTS] = {"body", "marking", "decoration", "hands", "feet", "eyes"};
char aPartBuf[64];
for(int i = 0; i < protocol7::NUM_SKINPARTS; ++i)
{
str_format(aPartBuf, sizeof(aPartBuf),
"%s\"%s\":{"
"\"name\":\"%s\"",
i == 0 ? "" : ",",
apPartNames[i],
EscapeJson(aCSkinName, sizeof(aCSkinName), TeeInfo.m_apSkinPartNames[i]));
pJSonWriter->WriteAttribute(apPartNames[i]);
pJSonWriter->BeginObject();
str_append(aJsonSkin, aPartBuf);
pJSonWriter->WriteAttribute("name");
pJSonWriter->WriteStrValue(TeeInfo.m_apSkinPartNames[i]);
if(TeeInfo.m_aUseCustomColors[i])
{
str_format(aPartBuf, sizeof(aPartBuf),
",\"color\":%d",
TeeInfo.m_aSkinPartColors[i]);
str_append(aJsonSkin, aPartBuf);
pJSonWriter->WriteAttribute("color");
pJSonWriter->WriteIntValue(TeeInfo.m_aSkinPartColors[i]);
}
str_append(aJsonSkin, "}");
pJSonWriter->EndObject();
}
}
pJSonWriter->EndObject();
pJSonWriter->WriteAttribute("afk");
pJSonWriter->WriteBoolValue(m_apPlayers[Id]->IsAfk());
const int Team = m_pController->IsTeamPlay() ? m_apPlayers[Id]->GetTeam() : m_apPlayers[Id]->GetTeam() == TEAM_SPECTATORS ? -1 : GetDDRaceTeam(Id);
str_format(aBuf, BufSize,
",\"skin\":{"
"%s"
"},"
"\"afk\":%s,"
"\"team\":%d",
aJsonSkin,
JsonBool(m_apPlayers[Id]->IsAfk()),
Team);
pJSonWriter->WriteAttribute("team");
pJSonWriter->WriteIntValue(Team);
}

View file

@ -357,7 +357,7 @@ public:
bool RateLimitPlayerVote(int ClientId);
bool RateLimitPlayerMapVote(int ClientId) const;
void OnUpdatePlayerServerInfo(char *aBuf, int BufSize, int Id) override;
void OnUpdatePlayerServerInfo(CJsonStringWriter *pJSonWriter, int Id) override;
std::shared_ptr<CScoreRandomMapResult> m_SqlRandomMapResult;