108 lines
3.5 KiB
C++
108 lines
3.5 KiB
C++
#include "demoreader.h"
|
|
#include "demofile/demofile.h"
|
|
#include "demofile/demotypes.h"
|
|
|
|
#include "game/sourcecontext.h"
|
|
#include "netmessages/nethandlers.h"
|
|
#include "netmessages/netcontants.h"
|
|
#include "demmessages/demhandlers.h"
|
|
#include "demmessages/dem_stringtables.h"
|
|
#include "sourcesdk/bitbuf.h"
|
|
#include <cstdint>
|
|
|
|
PacketTrailingBits ParsePacket(uint8_t* packet, size_t length,
|
|
SourceGameContext& context,
|
|
const NetHandlers::NetDataStructArray& netDataStructs)
|
|
{
|
|
assert(length <= NET_MAX_PAYLOAD);
|
|
bf_read bitbuf(packet, length);
|
|
NetPacket netPacket;
|
|
while (bitbuf.GetNumBitsLeft() >= NETMSG_TYPE_BITS)
|
|
{
|
|
netPacket.type = bitbuf.ReadUBitLong(NETMSG_TYPE_BITS);
|
|
netPacket.data = netDataStructs[netPacket.type];
|
|
NetHandlers::NetMsg_BitRead(netPacket.type, bitbuf, context, netPacket.data);
|
|
context.OnNetPacket(netPacket);
|
|
}
|
|
|
|
PacketTrailingBits trailingBits;
|
|
trailingBits.numTrailingBits = bitbuf.GetNumBitsLeft();
|
|
if (trailingBits.numTrailingBits)
|
|
{
|
|
trailingBits.value = bitbuf.ReadUBitLong(trailingBits.numTrailingBits);
|
|
}
|
|
else
|
|
{
|
|
trailingBits.value = 0;
|
|
}
|
|
return trailingBits;
|
|
}
|
|
|
|
bool DemoReader::ProcessDem(std::FILE* inputFp, SourceGameContext* context)
|
|
{
|
|
NetHandlers::NetDataStructArray netDataStructs;
|
|
DemHandlers::DemDataStructArray demDataStructs;
|
|
NetHandlers::CreateNetMsgStructs(netDataStructs);
|
|
DemHandlers::CreateDemMsgStructs(demDataStructs);
|
|
|
|
DemoFileReader reader(inputFp);
|
|
{
|
|
reader.ReadDemoHeader(context->header);
|
|
context->protocol = context->header.networkprotocol;
|
|
context->Start();
|
|
}
|
|
|
|
bool dirty = false;
|
|
try
|
|
{
|
|
CommandPacket packet;
|
|
do
|
|
{
|
|
reader.ReadCmdHeader(packet.cmd, packet.tick);
|
|
packet.data = demDataStructs[packet.cmd];
|
|
DemHandlers::DemMsg_FileRead(packet.cmd, reader, packet.data);
|
|
|
|
PacketTrailingBits trailingBits = PacketTrailingBits();
|
|
context->StartCommandPacket(packet);
|
|
|
|
if (packet.cmd == dem_packet || packet.cmd == dem_signon)
|
|
{
|
|
Array<uint8_t> buffer = reader.ReadRawData(NET_MAX_PAYLOAD);
|
|
trailingBits = ParsePacket(buffer.begin(), buffer.length(), *context, netDataStructs);
|
|
}
|
|
|
|
else if (packet.cmd == dem_stringtables)
|
|
{
|
|
DemMsg::Dem_StringTables *stringTables = (DemMsg::Dem_StringTables *)packet.data;
|
|
for (const auto& s : stringTables->stringtables)
|
|
{
|
|
StringTable *table = context->stringTables->GetStringTable(s.tableName.c_str(), false);
|
|
if (!table)
|
|
continue;
|
|
for (const auto& e : s.entries)
|
|
{
|
|
StringTableEntry entry;
|
|
entry.string.assign(e.entryName);
|
|
entry.data.assign(e.data.begin(), e.data.end());
|
|
table->AddEntry(&entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
context->EndCommandPacket(trailingBits);
|
|
} while (packet.cmd != dem_stop);
|
|
}
|
|
catch(const char *e)
|
|
{
|
|
dirty = true;
|
|
fprintf(stderr, "Error: %s\n", e);
|
|
}
|
|
|
|
context->Finish(dirty);
|
|
|
|
DemHandlers::DestroyDemMsgStructs(demDataStructs);
|
|
NetHandlers::DestroyNetMsgStructs(netDataStructs);
|
|
|
|
return !dirty;
|
|
}
|