demboyz/demboyz/game/logic.cpp

196 lines
5.5 KiB
C++

#include "logic.h"
#include "netmessages/svc_serverinfo.h"
#include <cstring>
#include <iostream>
Logic::Logic(SourceGameContext* context):
context(context)
{
//memset(clients, 0, sizeof(clients));
data = json({
{"header", {}},
{"serverinfo", {}},
{"players", {}},
{"chat", {}}
});
}
Logic::~Logic()
{
}
void Logic::Start()
{
data["demoheader"] = json({
{"demofilestamp", context->header.demofilestamp},
{"demoprotocol", context->header.demoprotocol},
{"networkprotocol", context->header.networkprotocol},
{"servername", context->header.servername},
{"clientname", context->header.clientname},
{"mapname", context->header.mapname},
{"gamedirectory", context->header.gamedirectory},
{"playback_time", context->header.playback_time},
{"playback_ticks", context->header.playback_ticks},
{"playback_frames", context->header.playback_frames},
{"signonlength", context->header.signonlength}
});
// std::cout << data.dump(2, ' ', false, json::error_handler_t::replace) << "\n";
}
void Logic::Finish(bool dirty)
{
// disconnect all remaining clients
for (int client = 0; client < MAX_PLAYERS; client++)
{
if (clients[client].connected == -1)
continue;
OnClientDisconnected(client, "#demoend");
}
// fix header if demo is corrupt
data["demoheader"]["dirty"] = dirty;
if (dirty)
{
data["demoheader"]["playback_ticks"] = curTick;
data["demoheader"]["playback_time"] = curTick * context->fTickRate;
data["demoheader"]["playback_frames"] = context->curFrame;
}
std::string out = data.dump(2, ' ', false, json::error_handler_t::replace);
out.append("\n");
fwrite(out.c_str(), out.size(), 1, context->outputFp);
}
void Logic::OnServerInfo(NetMsg::SVC_ServerInfo* serverInfo)
{
char mapMD5[32+1];
for (int i = 0; i < 16; ++i)
{
mapMD5[(i * 2)] = "0123456789ABCDEF"[serverInfo->mapMD5[i] / 16];
mapMD5[(i * 2) + 1] = "0123456789ABCDEF"[serverInfo->mapMD5[i] % 16];
}
mapMD5[32] = 0;
json info = {
{"protocol", serverInfo->protocol},
{"serverCount", serverInfo->serverCount},
{"isHLTV", serverInfo->isHLTV},
{"isDedicated", serverInfo->isDedicated},
{"clientCRC", serverInfo->clientCRC},
{"maxClasses", serverInfo->maxClasses},
{"mapCRC", serverInfo->mapCRC},
{"mapMD5", mapMD5},
{"playerSlot", serverInfo->playerSlot},
{"maxClients", serverInfo->maxClients},
{"tickInterval", serverInfo->tickInterval},
{"os", serverInfo->os},
{"gameDir", serverInfo->gameDir},
{"mapName", serverInfo->mapName},
{"skyName", serverInfo->skyName},
{"hostName", serverInfo->hostName},
{"isReplay", serverInfo->isReplay}
};
data["serverinfo"] = info;
// std::cout << info.dump(2, ' ', false, json::error_handler_t::replace) << "\n";
}
void Logic::OnClientConnected(int client)
{
assert(clients[client].connected == -1);
const auto& info = context->players[client].info;
auto& player = data["players"][info.guid];
if (player.is_null())
{
player = json({
{"names", {}},
{"sprays", {}},
{"disconnect_reasons", {}},
{"playtime", 0},
{"voicetime", 0.0f}
});
}
clients[client].connected = curTick;
OnClientSettingsChanged(client);
}
void Logic::OnClientDisconnected(int client, const char* reason)
{
assert(clients[client].connected != -1);
const auto& info = context->players[client].info;
auto& player = data["players"][info.guid];
// cumulative play time
unsigned int playtime = curTick - clients[client].connected;
playtime += player["playtime"].get<unsigned int>();
player["playtime"] = playtime;
// cumulative voice chat time
float voicetime = clients[client].voiceTime;
voicetime += player["voicetime"].get<float>();
player["voicetime"] = voicetime;
player["disconnect_reasons"] += reason;
clients[client].connected = -1;
}
void Logic::OnClientSettingsChanged(int client)
{
assert(clients[client].connected != -1);
const auto& info = context->players[client].info;
auto& player = data["players"][info.guid];
// list of names
if (std::find(player["names"].begin(), player["names"].end(), info.name) == player["names"].end())
player["names"].push_back(info.name);
// list of spray hashes
if (info.customFiles[0])
{
char logohex[16];
sprintf(logohex, "%08x", info.customFiles[0]);
if (std::find(player["sprays"].begin(), player["sprays"].end(), logohex) == player["sprays"].end())
player["sprays"].push_back(logohex);
}
}
void Logic::OnClientChat(int client, bool bWantsToChat, const char* msgName, const char* msgSender, const char* msgText)
{
const auto& info = context->players[client].info;
json chat = {
{"tick", curTick},
{"steamid", info.guid},
{"msgName", msgName},
{"msgSender", msgSender},
{"msgText", msgText}
};
data["chat"] += chat;
}
void Logic::OnClientVoiceChat(int client, float length)
{
assert(clients[client].connected != -1);
clients[client].voiceTime += length;
}
void Logic::OnVoiceCodec(const char* codec, int quality, int sampleRate)
{
data["voice_init"] = json({
{"codec", codec},
{"quality", quality},
{"sampleRate", sampleRate}
});
}