Skip to content

Commit

Permalink
Use CJsonWriter for creating server info JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
furo321 committed Aug 23, 2024
1 parent 37fd57c commit f897af8
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 112 deletions.
5 changes: 3 additions & 2 deletions src/engine/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -365,10 +366,10 @@ class IGameServer : public IInterface
/**
* 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();
Expand Down
131 changes: 68 additions & 63 deletions src/engine/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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()));

bool FirstPlayer = true;
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();

for(int i = 0; i < MAX_CLIENTS; i++)
{
if(m_aClients[i].IncludedInServerInfo())
{
char aCName[32];
char aCClan[32];

char aExtraPlayerInfo[512];
GameServer()->OnUpdatePlayerServerInfo(aExtraPlayerInfo, sizeof(aExtraPlayerInfo), 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;
}
}

str_append(aInfo, "]}");

m_pRegister->OnNewInfo(aInfo);
JsonWriter.BeginObject();

JsonWriter.WriteAttribute("name");
JsonWriter.WriteStrValue(ClientName(i));

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();
}
}

JsonWriter.EndArray();
JsonWriter.EndObject();

m_pRegister->OnNewInfo(JsonWriter.GetOutputString().c_str());
}

void CServer::UpdateServerInfo(bool Resend)
Expand Down
75 changes: 29 additions & 46 deletions src/game/server/gamecontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
2 changes: 1 addition & 1 deletion src/game/server/gamecontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ class CGameContext : public IGameServer
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;

Expand Down

0 comments on commit f897af8

Please sign in to comment.