rodecomp/Source/Client/ReplayPacketRecorder.cpp

92 lines
2.7 KiB
C++

#include "Client/ReplayPacketRecorder.h"
#include "Network/Packets/PacketLengths.h"
#include "Network/Packets/PacketId.h"
#include <cstring>
#include <vector>
#include <windows.h>
#include <timeapi.h>
// OFFSET: 0x00B86880
// FUNCTION: fn_19332
bool ReplayPacketRecorder::Record(std::uint16_t bytes, const void* packet, int event, std::uint32_t delay) {
if (bytes == 0 || !packet) {
return false;
}
std::uint16_t id;
std::memcpy(&id, packet, sizeof(id));
if (id != ID_REPLAY_WINDOW_RESPONSE) {
if (this->lengths.IsRecorded(id) == 0) {
return false;
}
switch (id) {
case ID_ZC_NOTIFY_CHAT:
case ID_ZC_NOTIFY_PLAYERCHAT:
case ID_ZC_WHISPER:
case ID_ZC_NOTIFY_CHAT_PARTY:
case ID_ZC_GUILD_CHAT:
case ID_ZC_BATTLEFIELD_CHAT:
case ID_ZC_ALLY_CHAT:
if (this->recordRestricted == 0) {
return false;
}
break;
default:
break;
}
}
std::vector<unsigned char> record(static_cast<std::size_t>(bytes) + 10, 0);
std::memcpy(record.data() + 8, &bytes, sizeof(bytes));
if (event == 42 || event == 43) {
const std::uint32_t frameDelta = this->frame - this->baseFrame;
const std::uint32_t tick = event == 43 ? delay - this->started + timeGetTime() : timeGetTime() - this->started;
std::memcpy(record.data(), &frameDelta, sizeof(frameDelta));
std::memcpy(record.data() + 4, &tick, sizeof(tick));
}
std::memcpy(record.data() + 10, packet, bytes);
this->cipherKey = this->key1 >> 3;
this->cipherIndex = 0;
this->cipherBase = this->key0 >> 5;
for (unsigned index = 0; index < bytes / 4u; ++index) {
std::uint32_t word;
std::memcpy(&word, record.data() + 10 + index * 4, sizeof(word));
word ^= this->cipherKey * (++this->cipherIndex + this->cipherBase);
std::memcpy(record.data() + 10 + index * 4, &word, sizeof(word));
}
std::fseek(this->file, static_cast<long>(this->fileOffset), SEEK_SET);
std::fwrite(record.data(), record.size(), 1, this->file);
this->fileOffset += static_cast<std::uint32_t>(record.size());
++this->records;
return true;
}
// OFFSET: 0x00A82F00
// FUNCTION: fn_16999
void WindowResponseRecorder::Record(int windowId, int response, std::intptr_t b, std::intptr_t c, std::intptr_t d) {
if (this->mode != 2) {
return;
}
#pragma pack(push, 1)
struct Response {
std::uint32_t marker;
std::uint16_t bytes;
std::int32_t windowId;
std::int32_t response;
std::uint32_t arguments[3];
};
#pragma pack(pop)
static_assert(sizeof(Response) == 26);
const Response packet{0x038408AEu, 26, windowId, response, {static_cast<std::uint32_t>(b), static_cast<std::uint32_t>(c), static_cast<std::uint32_t>(d)}};
this->packets.Record(sizeof(packet), &packet, 42, 0);
}