178 lines
4.7 KiB
C++
178 lines
4.7 KiB
C++
|
|
#include "sourcecontext.h"
|
|
#include "netmessages/netmath.h"
|
|
#include "netmessages/svc_gameeventlist.h"
|
|
#include "netmessages/usermessages.h"
|
|
#include "netmessages/svc_usermessage.h"
|
|
#include "netmessages/svc_serverinfo.h"
|
|
#include "sourcesdk/bitbuf.h"
|
|
#include "game/gameevents.h"
|
|
#include "game/logic.h"
|
|
#include "io/voicewriter/voicedatawriter.h"
|
|
#include <iostream>
|
|
|
|
#include "netmessages/svc_voiceinit.h"
|
|
#include "netmessages/svc_voicedata.h"
|
|
|
|
SourceGameContext::SourceGameContext(std::string outputDir, std::string outputDirVoice):
|
|
outputDir(outputDir),
|
|
outputDirVoice(outputDirVoice)
|
|
{
|
|
stringTables = new StringTableContainer(this);
|
|
memset(players, 0, sizeof(players));
|
|
}
|
|
|
|
SourceGameContext::~SourceGameContext()
|
|
{
|
|
delete logic;
|
|
logic = nullptr;
|
|
|
|
protocol = 0;
|
|
delete gameEventList;
|
|
gameEventList = nullptr;
|
|
delete stringTables;
|
|
stringTables = nullptr;
|
|
|
|
fclose(outputFp);
|
|
}
|
|
|
|
bool SourceGameContext::init()
|
|
{
|
|
outputFp = fopen((outputDir + "/out.json").c_str(), "wb");
|
|
if (!outputFp)
|
|
{
|
|
fprintf(stderr, "Error: Could not open out.json\n");
|
|
return false;
|
|
}
|
|
|
|
voiceWriter = new VoiceDataWriter(this, outputDirVoice.c_str());
|
|
logic = new Logic(this);
|
|
return true;
|
|
}
|
|
|
|
void SourceGameContext::Start()
|
|
{
|
|
logic->Start();
|
|
voiceWriter->Start();
|
|
}
|
|
|
|
void SourceGameContext::Finish(bool dirty)
|
|
{
|
|
logic->Finish(dirty);
|
|
voiceWriter->Finish();
|
|
}
|
|
|
|
void SourceGameContext::StartCommandPacket(const CommandPacket& packet)
|
|
{
|
|
curFrame += (packet.cmd == dem_packet);
|
|
|
|
if(curTick == -1 && packet.tick > 0)
|
|
return;
|
|
|
|
curTick = packet.tick;
|
|
logic->curTick = curTick;
|
|
|
|
voiceWriter->StartCommandPacket(packet);
|
|
}
|
|
|
|
void SourceGameContext::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
|
{
|
|
if(curTick == -1)
|
|
return;
|
|
|
|
voiceWriter->EndCommandPacket(trailingBits);
|
|
}
|
|
|
|
void SourceGameContext::OnNetPacket(NetPacket& packet)
|
|
{
|
|
if(packet.type == NetMsg::svc_ServerInfo)
|
|
{
|
|
NetMsg::SVC_ServerInfo* serverInfo = static_cast<NetMsg::SVC_ServerInfo*>(packet.data);
|
|
fTickInterval = serverInfo->tickInterval;
|
|
fTickRate = 1.f / fTickInterval;
|
|
logic->OnServerInfo(serverInfo);
|
|
}
|
|
|
|
else if(packet.type == NetMsg::svc_UserMessage)
|
|
{
|
|
NetMsg::SVC_UserMessage* umsg = static_cast<NetMsg::SVC_UserMessage*>(packet.data);
|
|
|
|
bf_read msg(umsg->data.get(), math::BitsToBytes(umsg->dataLengthInBits));
|
|
|
|
if(umsg->msgType == UserMsg::SayText2)
|
|
{
|
|
int client = msg.ReadByte();
|
|
bool bWantsToChat = msg.ReadByte();
|
|
|
|
char msgName[2048] = {0};
|
|
char msgSender[2048] = {0};
|
|
char msgText[2048] = {0};
|
|
|
|
msg.ReadString(msgName, sizeof(msgName));
|
|
msg.ReadString(msgSender, sizeof(msgSender));
|
|
msg.ReadString(msgText, sizeof(msgText));
|
|
|
|
logic->OnClientChat(client, bWantsToChat, msgName, msgSender, msgText);
|
|
}
|
|
}
|
|
|
|
else if(packet.type == NetMsg::svc_VoiceInit || packet.type == NetMsg::svc_VoiceData)
|
|
{
|
|
voiceWriter->OnNetPacket(packet);
|
|
}
|
|
|
|
}
|
|
|
|
void SourceGameContext::OnGameEvent(const char *name, GameEvents::EventDataMap &data)
|
|
{
|
|
// GameEvents::PrintEvent(name, data);
|
|
|
|
if (strcmp(name, "player_disconnect") == 0)
|
|
{
|
|
int userid = data["userid"].i16Value;
|
|
for (int client = 0; client < MAX_PLAYERS; client++)
|
|
{
|
|
auto& p = players[client];
|
|
if (!p.connected || p.info.userID != userid)
|
|
continue;
|
|
|
|
p.connected = false;
|
|
logic->OnClientDisconnected(client, data["reason"].strValue.c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void SourceGameContext::OnStringtable(StringTable* table)
|
|
{
|
|
if (table->tableName == "userinfo")
|
|
{
|
|
table->callback = std::bind(&SourceGameContext::UserInfoChanged, this, std::placeholders::_1, std::placeholders::_2);
|
|
}
|
|
}
|
|
|
|
void SourceGameContext::UserInfoChanged(int tableIdx, int entryIdx)
|
|
{
|
|
StringTableEntry &entry = stringTables->tables[tableIdx].entries[entryIdx];
|
|
|
|
int client = std::stoi(entry.string);
|
|
player_info_t *info = (player_info_t *)entry.data.data();
|
|
|
|
if (entry.data.size() != sizeof(player_info_t))
|
|
{
|
|
memset(&players[client].info, 0, sizeof(player_info_t));
|
|
players[client].connected = false;
|
|
return;
|
|
}
|
|
|
|
memcpy(&players[client].info, info, sizeof(player_info_t));
|
|
|
|
if (!players[client].connected)
|
|
logic->OnClientConnected(client);
|
|
else
|
|
logic->OnClientSettingsChanged(client);
|
|
|
|
players[client].connected = true;
|
|
|
|
//std::cout << client << " (" << info->userID << "): N:" << info->name << " G:" << info->guid << " F:" << info->friendsID << "\n";
|
|
}
|