Reconstruct readable C++ and organize cohesive source subsystems

Administrative source import: native x86 compilation passed for 423 authored units. Source placement and submission states are migrated separately; this commit does not imply peer acceptance.

Previous head: 35d2a8cb36
Payload SHA256: 592f016d2730c5593bb653aa054c1e5f76a6df72c8f5a09e66f74876e2e33dee
This commit is contained in:
ragnarok-clanker 2026-10-25 07:42:41 +00:00
commit a47d20f8be
890 changed files with 11796 additions and 16664 deletions

View file

@ -0,0 +1,127 @@
#include "Contents/Emblems/EmblemCache.h"
#include "UI/Window/UIWindow.h"
#include "UI/Window/WindowManagerWindows.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <direct.h>
#include <io.h>
#include <memory>
#include <sstream>
#include <sys/stat.h>
#include <windows.h>
#include <zlib.h>
namespace {
std::string Basename(std::string path) {
const auto separator = path.rfind('\\');
if (separator != std::string::npos) {
return path.substr(separator + 1);
}
return path;
}
}
// OFFSET: 0x0065ED00
// FUNCTION: fn_05178
std::string EmblemCache::Filename(std::uint32_t guild, std::uint32_t revision) const {
std::ostringstream name;
name << this->accountName << '_' << guild << '_' << (revision + 0x7FFFFFFFu) << ".ebm";
return name.str();
}
// OFFSET: 0x0065E6F0
// FUNCTION: fn_05176
bool EmblemCache::IsInvalid(std::string path) const {
return this->invalid.contains(Basename(path));
}
// OFFSET: 0x0065DFB0
// FUNCTION: fn_05171
void EmblemCache::MarkInvalid(std::string path) {
this->invalid.insert(Basename(path));
}
// OFFSET: 0x0065E890
// FUNCTION: fn_05177
void EmblemCache::Store(const void* bytes, std::uint32_t size, std::uint32_t guild, std::uint32_t revision) {
const std::string directory = std::string(this->rootDirectory) + "\\_tmpEmblem\\";
const std::string filename = this->Filename(guild, revision);
uLongf compressedSize = compressBound(size);
std::unique_ptr<unsigned char[]> compressed(new unsigned char[compressedSize]);
if (compress(compressed.get(), &compressedSize, static_cast<const Bytef*>(bytes), size) != Z_OK) {
this->MarkInvalid(filename);
return;
}
if (_access(directory.c_str(), 0) != 0 && _mkdir(directory.c_str()) == -1) {
return;
}
std::ostringstream pattern;
pattern << this->accountName << '_' << guild << "_*.ebm";
WIN32_FIND_DATAA found{};
const HANDLE search = FindFirstFileA((directory + pattern.str()).c_str(), &found);
std::list<std::string> names;
if (search != INVALID_HANDLE_VALUE) {
do {
if (std::strcmp(found.cFileName, ".") != 0 && std::strcmp(found.cFileName, "..") != 0) {
names.emplace_back(found.cFileName);
}
} while (FindNextFileA(search, &found));
}
FindClose(search);
for (const std::string& name : names) {
const std::string path = directory + name;
_chmod(path.c_str(), _S_IWRITE);
_unlink(path.c_str());
}
const std::string path = directory + filename;
FILE* file = std::fopen(path.c_str(), "wb");
if (file) {
std::fwrite(compressed.get(), compressedSize, 1, file);
std::fclose(file);
}
}
// OFFSET: 0x00D588E0
// FUNCTION: fn_21954
void EmblemCache::Receive(std::uint16_t state, std::uint32_t guild, std::uint32_t revision, const unsigned char* bytes, int size) {
if (state == 0) {
this->guildId = guild;
this->version = revision;
this->data.clear();
} else if (state == 1) {
if (guild == this->guildId && revision == this->version) {
this->data.insert(this->data.end(), bytes, bytes + size);
}
} else if (state == 2 && guild == this->guildId && revision == this->version) {
this->Store(this->data.data(), static_cast<std::uint32_t>(this->data.size()), guild, revision);
this->Refresh(guild);
}
}
// OFFSET: 0x0065EE50
// FUNCTION: fn_05180
void EmblemCache::Refresh(std::uint32_t guild) {
if (this->modeWindows) {
for (UIWindow* window : *this->modeWindows) {
window->SendMsg(nullptr, 60, guild, 0, 0, 0);
}
}
UIWindow* window = this->windows.LookupWindow(60);
if (window) {
window->Invalidate();
}
}

View file

@ -0,0 +1,31 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMCACHE_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMCACHE_H
#include <cstdint>
#include <list>
#include <set>
#include <string>
#include <vector>
class UIWindow;
class WindowManagerWindows;
struct EmblemCache {
std::uint32_t& guildId;
std::uint32_t& version;
std::vector<unsigned char>& data;
std::set<std::string>& invalid;
const std::string& accountName;
const char* rootDirectory;
const std::list<UIWindow*>* const& modeWindows;
WindowManagerWindows& windows;
std::string Filename(std::uint32_t guild, std::uint32_t revision) const;
bool IsInvalid(std::string path) const;
void MarkInvalid(std::string path);
void Store(const void* bytes, std::uint32_t size, std::uint32_t guild, std::uint32_t revision);
void Receive(std::uint16_t state, std::uint32_t guild, std::uint32_t revision, const unsigned char* bytes, int size);
void Refresh(std::uint32_t guild);
};
#endif

View file

@ -0,0 +1,86 @@
#include "Contents/Emblems/EmblemDataDownloadAsyncWork.h"
#include "Contents/Emblems/EmblemDownload.h"
#include "Network/Http/CURLPostHander.h"
#include "Network/TextEncoding.h"
#include <cstdio>
#include <windows.h>
#include <timeapi.h>
namespace {
constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\Emblem\\CEmblemDataDownloadAsyncWork.cpp";
AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) {
std::string message = text;
return AsyncDiagnostic(&success, &message, sourceFile, &line);
}
}
// OFFSET: 0x005E9C00
// FUNCTION: fn_03963
CEmblemDataDownloadAsyncWork::CEmblemDataDownloadAsyncWork()
: NAsyncWork("Emblem_Download"), m_accountId(0), m_guildId(0), m_version(0), m_responseCode(500), m_diagnostic(Diagnostic(false, "unknwon", 29)),
m_connection(nullptr) {
}
// OFFSET: 0x005E9FE0
// FUNCTION: fn_03964
CEmblemDataDownloadAsyncWork::~CEmblemDataDownloadAsyncWork() = default;
// OFFSET: 0x005EA350
// FUNCTION: fn_03966
void CEmblemDataDownloadAsyncWork::Reset() {
}
// OFFSET: 0x005EA0D0
// FUNCTION: fn_03965
void CEmblemDataDownloadAsyncWork::Bind(
std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::uint32_t version, CConnection& connection
) {
this->m_group = timeGetTime();
this->m_key = 0;
this->m_url = url;
this->m_accountId = accountId;
this->m_token = token;
this->m_accountName = accountName;
this->m_guildId = guildId;
this->m_version = version;
AsyncDiagnostic diagnostic = Diagnostic(false, "unknwon", 57);
this->m_diagnostic.MoveFrom(diagnostic);
this->m_connection = &connection;
}
// OFFSET: 0x005EA430
// FUNCTION: fn_03968
bool CEmblemDataDownloadAsyncWork::Execute() {
char account[64] = {}, guild[64] = {}, version[10] = {};
_snprintf_s(account, sizeof(account), _TRUNCATE, "%d", static_cast<std::int32_t>(this->m_accountId));
_snprintf_s(guild, sizeof(guild), _TRUNCATE, "%d", static_cast<std::int32_t>(this->m_guildId));
_snprintf_s(version, sizeof(version), _TRUNCATE, "%d", static_cast<std::int32_t>(this->m_version));
std::string name = ToUtf8(this->m_accountName);
CCURLPostHander handler(this->m_url);
handler.AddField("AID", account, 4);
handler.AddField("AuthToken", this->m_token, 4);
handler.AddField("WorldName", name, 4);
handler.AddField("GDID", guild, 4);
handler.AddField("Version", version, 4);
if (handler.Perform() == 0) {
this->m_responseCode = static_cast<int>(handler.ResponseCode());
this->m_response = handler.Response();
AsyncDiagnostic diagnostic = Diagnostic(true, "good", 96);
this->m_diagnostic.MoveFrom(diagnostic);
} else {
AsyncDiagnostic diagnostic = Diagnostic(false, "fail", 105);
this->m_diagnostic.MoveFrom(diagnostic);
}
return false;
}
// OFFSET: 0x005EA360
// FUNCTION: fn_03967
void CEmblemDataDownloadAsyncWork::Complete() {
CompleteEmblemDownload(this->m_diagnostic, this->m_responseCode, this->m_response, this->m_guildId, this->m_version, *this->m_connection);
}

View file

@ -0,0 +1,37 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATADOWNLOADASYNCWORK_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATADOWNLOADASYNCWORK_H
#include "Utility/Async/AsyncDiagnostic.h"
#include "Utility/Async/NAsyncWork.h"
class CConnection;
class CEmblemDataDownloadAsyncWork : public NAsyncWork {
public:
CEmblemDataDownloadAsyncWork();
~CEmblemDataDownloadAsyncWork() override;
void Reset() override;
bool Execute() override;
void Complete() override;
void Bind(
std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::uint32_t version, CConnection& connection
);
protected:
/* 0028 */ std::string m_url;
/* 0040 */ std::uint32_t m_accountId;
/* 0044 */ std::string m_token;
/* 005C */ std::string m_accountName;
/* 0074 */ std::uint32_t m_guildId;
/* 0078 */ std::uint32_t m_version;
/* 007C */ std::string m_response;
/* 0094 */ int m_responseCode;
/* 0098 */ AsyncDiagnostic m_diagnostic;
CConnection* m_connection;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(CEmblemDataDownloadAsyncWork) == 212);
#endif
#endif

View file

@ -0,0 +1,86 @@
#include "Contents/UserData/AccountService.h"
#include "Contents/Async/AsyncWorkMgr.h"
#include "Contents/Emblems/EmblemDataMgr.h"
#include <new>
// STATIC: 0x013898D4
// GLOBAL: gl_24355
CEmblemDataMgr* g_emblemDataMgr;
// OFFSET: 0x005EB150
// FUNCTION: fn_03970
CEmblemDataMgr::CEmblemDataMgr() : m_enabled(true), m_uploading(false) {
}
// OFFSET: 0x005EB0D0
// FUNCTION: fn_03969
CEmblemDataMgr::~CEmblemDataMgr() = default;
// OFFSET: 0x005EB150
// FUNCTION: fn_03970
bool CEmblemDataMgr::Initialize() {
if (g_emblemDataMgr) {
return false;
}
g_emblemDataMgr = new (std::nothrow) CEmblemDataMgr;
if (!g_emblemDataMgr) {
return false;
}
if (!g_emblemDataMgr->m_enabled) {
delete g_emblemDataMgr;
g_emblemDataMgr = nullptr;
return false;
}
return true;
}
// OFFSET: 0x005EB240
// FUNCTION: fn_03971
void CEmblemDataMgr::Shutdown() {
if (g_emblemDataMgr) {
delete g_emblemDataMgr;
g_emblemDataMgr = nullptr;
}
}
// OFFSET: 0x005EB580
// FUNCTION: fn_03974
void CEmblemDataMgr::RefreshUrls(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) {
const std::string base = ResolveAccountServiceBase(settings, tables, host, port, overrideKey);
if (!base.empty()) {
this->m_uploadUrl = base + "/emblem/upload";
this->m_downloadUrl = base + "/emblem/download";
}
}
// OFFSET: 0x005EB260
// FUNCTION: fn_03972
void CEmblemDataMgr::Download(
std::uint32_t guildId, std::uint32_t version, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection,
CAsyncWorkMgr& manager
) {
const std::string token(token16, 16);
manager.DownloadEmblem(this->m_downloadUrl, accountId, token, accountName, guildId, version, connection);
}
// OFFSET: 0x005EB410
// FUNCTION: fn_03973
bool CEmblemDataMgr::Upload(
std::uint32_t guildId, std::string path, std::uint32_t accountId, const std::string& accountName, const char* token16, EmblemUploadContext& context,
CAsyncWorkMgr& manager
) {
if (this->m_uploading) {
return false;
}
const std::string token(token16, 16);
manager.UploadEmblem(this->m_uploadUrl, accountId, token, accountName, guildId, path, *this, context);
return true;
}

View file

@ -0,0 +1,45 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAMGR_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAMGR_H
#include <cstdint>
#include <string>
class LuaScript;
class CConnection;
class CAsyncWorkMgr;
struct AsyncDiagnostic;
struct EmblemUploadContext;
class CEmblemDataMgr {
public:
CEmblemDataMgr();
virtual ~CEmblemDataMgr();
static bool Initialize();
static void Shutdown();
void RefreshUrls(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey);
void Download(
std::uint32_t guildId, std::uint32_t version, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection,
CAsyncWorkMgr& manager
);
bool Upload(
std::uint32_t guildId, std::string path, std::uint32_t accountId, const std::string& accountName, const char* token16, EmblemUploadContext& context,
CAsyncWorkMgr& manager
);
void CompleteUpload(AsyncDiagnostic diagnostic, std::string response, std::uint32_t guildId, EmblemUploadContext& context);
protected:
/* 0004 */ bool m_enabled;
/* 0008 */ std::string m_uploadUrl;
/* 0020 */ std::string m_downloadUrl;
/* 0038 */ bool m_uploading;
};
// STATIC: 0x013898D4
// GLOBAL: gl_24355
extern CEmblemDataMgr* g_emblemDataMgr;
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(CEmblemDataMgr) == 60);
#endif
#endif

View file

@ -0,0 +1,94 @@
#include "Contents/Emblems/EmblemDataMgr.h"
#include "Contents/Emblems/EmblemDataUploadAsyncWork.h"
#include "Network/Http/CURLPostHander.h"
#include "Network/TextEncoding.h"
#include <cctype>
#include <cstdio>
#include <windows.h>
#include <timeapi.h>
namespace {
constexpr char sourceFile[] = "C:\\repositories\\RagnarokClient\\RagnarokClient\\Contents\\Emblem\\CEmblemDataUploadAsyncWork.cpp";
AsyncDiagnostic Diagnostic(bool success, const char* text, std::uint32_t line) {
std::string message = text;
return AsyncDiagnostic(&success, &message, sourceFile, &line);
}
}
// OFFSET: 0x005EBF50
// FUNCTION: fn_03978
CEmblemDataUploadAsyncWork::CEmblemDataUploadAsyncWork()
: NAsyncWork("Emblem_Upload"), m_accountId(0), m_guildId(0), m_diagnostic(Diagnostic(false, "unknwon", 27)), m_owner(nullptr), m_context(nullptr) {
}
// OFFSET: 0x005EC350
// FUNCTION: fn_03979
CEmblemDataUploadAsyncWork::~CEmblemDataUploadAsyncWork() = default;
// OFFSET: 0x005EC6F0
// FUNCTION: fn_03981
void CEmblemDataUploadAsyncWork::Reset() {
}
// OFFSET: 0x005EC450
// FUNCTION: fn_03980
void CEmblemDataUploadAsyncWork::Bind(
std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::string path, CEmblemDataMgr& owner,
EmblemUploadContext& context
) {
this->m_group = timeGetTime();
this->m_key = 0;
this->m_url = url;
this->m_accountId = accountId;
this->m_token = token;
this->m_accountName = accountName;
this->m_guildId = guildId;
this->m_path = path;
AsyncDiagnostic diagnostic = Diagnostic(false, "unknwon", 54);
this->m_diagnostic.MoveFrom(diagnostic);
this->m_owner = &owner;
this->m_context = &context;
}
// OFFSET: 0x005EC7C0
// FUNCTION: fn_03983
bool CEmblemDataUploadAsyncWork::Execute() {
char account[64] = {}, guild[64] = {};
_snprintf_s(account, sizeof(account), _TRUNCATE, "%d", static_cast<std::int32_t>(this->m_accountId));
_snprintf_s(guild, sizeof(guild), _TRUNCATE, "%d", static_cast<std::int32_t>(this->m_guildId));
std::string name = ToUtf8(this->m_accountName);
std::string path = ToUtf8(this->m_path);
std::string extension = this->m_path.substr(this->m_path.size() - 3, this->m_path.size());
for (char& value : extension) {
value = static_cast<char>(std::toupper(static_cast<unsigned char>(value)));
}
extension = ToUtf8(extension);
CCURLPostHander handler(this->m_url);
handler.AddField("AID", account, 4);
handler.AddField("AuthToken", this->m_token, 4);
handler.AddField("WorldName", name, 4);
handler.AddField("GDID", guild, 4);
handler.AddField("ImgType", extension, 4);
handler.AddField("Img", path, 10);
if (handler.Perform() == 0) {
this->m_response = FromUtf8(handler.Response());
AsyncDiagnostic diagnostic = Diagnostic(true, "good", 100);
this->m_diagnostic.MoveFrom(diagnostic);
} else {
AsyncDiagnostic diagnostic = Diagnostic(false, "fail", 109);
this->m_diagnostic.MoveFrom(diagnostic);
}
return false;
}
// OFFSET: 0x005EC700
// FUNCTION: fn_03982
void CEmblemDataUploadAsyncWork::Complete() {
this->m_owner->CompleteUpload(this->m_diagnostic, this->m_response, this->m_guildId, *this->m_context);
}

View file

@ -0,0 +1,39 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAUPLOADASYNCWORK_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDATAUPLOADASYNCWORK_H
#include "Utility/Async/AsyncDiagnostic.h"
#include "Utility/Async/NAsyncWork.h"
class CEmblemDataMgr;
struct EmblemUploadContext;
class CEmblemDataUploadAsyncWork : public NAsyncWork {
public:
CEmblemDataUploadAsyncWork();
~CEmblemDataUploadAsyncWork() override;
void Reset() override;
bool Execute() override;
void Complete() override;
void Bind(
std::string url, std::uint32_t accountId, std::string token, std::string accountName, std::uint32_t guildId, std::string path, CEmblemDataMgr& owner,
EmblemUploadContext& context
);
protected:
/* 0028 */ std::string m_url;
/* 0040 */ std::uint32_t m_accountId;
/* 0044 */ std::string m_token;
/* 005C */ std::string m_accountName;
/* 0074 */ std::uint32_t m_guildId;
/* 0078 */ std::string m_path;
/* 0090 */ std::string m_response;
/* 00A8 */ AsyncDiagnostic m_diagnostic;
CEmblemDataMgr* m_owner;
EmblemUploadContext* m_context;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(CEmblemDataUploadAsyncWork) == 232);
#endif
#endif

View file

@ -0,0 +1,78 @@
#include "Contents/Emblems/EmblemDownload.h"
#include "Network/Connection/Connection.h"
#include "Utility/Async/AsyncDiagnostic.h"
#include <algorithm>
#include <cstdlib>
#include <cstring>
namespace {
#pragma pack(push, 1)
struct EmblemPacket {
std::uint16_t id;
std::uint16_t bytes;
std::uint16_t state;
std::uint32_t guildId;
std::uint32_t version;
unsigned char data[1010];
};
#pragma pack(pop)
static_assert(sizeof(EmblemPacket) == 1024);
struct EmblemPacketAllocation {
std::uint32_t marker;
std::uint32_t unused;
EmblemPacket packet;
};
static_assert(sizeof(EmblemPacketAllocation) == 1032);
}
// OFFSET: 0x005EB800
// FUNCTION: fn_03975
void CompleteEmblemDownload(
AsyncDiagnostic diagnostic, int responseCode, std::string response, std::uint32_t guildId, std::uint32_t version, CConnection& connection
) {
if (!diagnostic.success || responseCode != 200) {
return;
}
auto* storage = static_cast<EmblemPacketAllocation*>(std::malloc(sizeof(EmblemPacketAllocation)));
if (!storage) {
return;
}
storage->marker = 0xDDDD;
EmblemPacket& packet = storage->packet;
packet.id = 0x0B36;
packet.bytes = 14;
packet.state = 2;
packet.guildId = guildId;
packet.version = version;
connection.Prepend(packet.bytes, &packet);
int remaining = static_cast<int>(response.size());
while (remaining > 0) {
const int bytes = std::min(remaining, 1010);
remaining -= bytes;
packet.id = 0x0B36;
packet.bytes = static_cast<std::uint16_t>(bytes + 14);
packet.state = 1;
packet.guildId = guildId;
packet.version = version;
std::memcpy(packet.data, response.data() + remaining, bytes);
connection.Prepend(packet.bytes, &packet);
}
packet.id = 0x0B36;
packet.bytes = 14;
packet.state = 0;
packet.guildId = guildId;
packet.version = version;
connection.Prepend(packet.bytes, &packet);
if (storage->marker == 0xDDDD) {
std::free(storage);
}
}

View file

@ -0,0 +1,14 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDOWNLOAD_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMDOWNLOAD_H
#include <cstdint>
#include <string>
class CConnection;
struct AsyncDiagnostic;
void CompleteEmblemDownload(
AsyncDiagnostic diagnostic, int responseCode, std::string response, std::uint32_t guildId, std::uint32_t version, CConnection& connection
);
#endif

View file

@ -0,0 +1,56 @@
#include "Contents/Emblems/EmblemDataMgr.h"
#include "Contents/Emblems/EmblemUpload.h"
#include "Contents/MessageTable.h"
#include "Network/Connection/Connection.h"
#include "Network/Packets/PacketLengths.h"
#include "UI/Window/WindowDialogs.h"
#include "Utility/Async/AsyncDiagnostic.h"
#include <json/reader.h>
#include <json/value.h>
namespace {
#pragma pack(push, 1)
struct EmblemVersionPacket {
std::uint16_t id;
std::uint32_t guildId;
std::int32_t version;
};
#pragma pack(pop)
static_assert(sizeof(EmblemVersionPacket) == 10);
}
// OFFSET: 0x005EBAD0
// FUNCTION: fn_03976
void CEmblemDataMgr::CompleteUpload(AsyncDiagnostic diagnostic, std::string response, std::uint32_t guildId, EmblemUploadContext& context) {
if (!diagnostic.success) {
return;
}
Json::Value root;
Json::Reader reader;
const std::string document(response.c_str());
if (!reader.parse(document, root, true)) {
return;
}
switch (root["Type"].asInt()) {
case 1: {
EmblemVersionPacket packet{0x0B46, guildId, root["version"].asInt()};
context.connection.Send(context.lengths.FixedLength(packet.id), &packet);
break;
}
case 2:
case 3:
case 4: {
const char* message = LookupMessage(3586, context.languagePrefix, context.serviceType, context.language);
context.dialogs.Confirm(message, 0, true, false, 0, "Message", 280, 120, 0);
break;
}
default:
break;
}
this->m_uploading = false;
}

View file

@ -0,0 +1,19 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMUPLOAD_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_EMBLEMUPLOAD_H
#include <cstdint>
class CConnection;
struct PacketLengths;
struct WindowDialogs;
struct EmblemUploadContext {
CConnection& connection;
const PacketLengths& lengths;
WindowDialogs& dialogs;
const bool& languagePrefix;
const int& serviceType;
const std::uint16_t& language;
};
#endif

View file

@ -0,0 +1,56 @@
#include "Contents/Emblems/EmblemDataMgr.h"
#include "Contents/Emblems/GuildEmblemReqBundle.h"
#include <algorithm>
#include <windows.h>
#include <timeapi.h>
// OFFSET: 0x0065C5F0
CGuildEmblemReqBundle::CGuildEmblemReqBundle() = default;
// OFFSET: 0x0065C8C0
// FUNCTION: fn_05153
CGuildEmblemReqBundle::~CGuildEmblemReqBundle() = default;
// OFFSET: 0x0065CA90
// FUNCTION: fn_05154
void CGuildEmblemReqBundle::Add(std::uint32_t guildId, std::uint32_t version) {
const auto request = std::pair{guildId, version};
if (std::find(this->m_pending.begin(), this->m_pending.end(), request) == this->m_pending.end()) {
this->m_pending.push_back(request);
}
}
// OFFSET: 0x0065CB90
// FUNCTION: fn_05155
void CGuildEmblemReqBundle::Update(
CEmblemDataMgr& emblems, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection, CAsyncWorkMgr& manager
) {
while (!this->m_recent.empty()) {
if (timeGetTime() < this->m_recent.front().tick + 60000u) {
break;
}
this->m_recent.pop_front();
}
while (!this->m_pending.empty()) {
const auto request = this->m_pending.front();
const bool recent = std::any_of(this->m_recent.begin(), this->m_recent.end(), [&](const Recent& value) {
return value.guildId == request.first && value.version == request.second;
});
this->m_pending.pop_front();
if (recent) {
continue;
}
if (request.first != 0) {
emblems.Download(request.first, request.second, accountId, accountName, token16, connection, manager);
this->m_recent.push_back({request.first, request.second, timeGetTime()});
}
return;
}
}

View file

@ -0,0 +1,36 @@
#ifndef RAGNAROK_SOURCE_CONTENTS_EMBLEMS_GUILDEMBLEMREQBUNDLE_H
#define RAGNAROK_SOURCE_CONTENTS_EMBLEMS_GUILDEMBLEMREQBUNDLE_H
#include <cstdint>
#include <deque>
#include <string>
#include <utility>
class CEmblemDataMgr;
class CConnection;
class CAsyncWorkMgr;
class CGuildEmblemReqBundle {
public:
CGuildEmblemReqBundle();
virtual ~CGuildEmblemReqBundle();
void Add(std::uint32_t guildId, std::uint32_t version);
void Update(
CEmblemDataMgr& emblems, std::uint32_t accountId, const std::string& accountName, const char* token16, CConnection& connection, CAsyncWorkMgr& manager
);
protected:
struct Recent {
std::uint32_t guildId;
std::uint32_t version;
std::uint32_t tick;
};
/* 0004 */ std::deque<std::pair<std::uint32_t, std::uint32_t>> m_pending;
/* 0018 */ std::deque<Recent> m_recent;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(CGuildEmblemReqBundle) == 44);
#endif
#endif