diff --git a/Source/Contents/ActorNameCard.h b/Source/Contents/ActorNameCard.h index 6424b22..c1f2982 100644 --- a/Source/Contents/ActorNameCard.h +++ b/Source/Contents/ActorNameCard.h @@ -63,6 +63,7 @@ public: std::size_t Erase(std::uint32_t id); bool Contains(std::uint32_t id) const; void Clear(); + void ProcessRequests(); struct Request { /* 0000 */ std::uint32_t id; diff --git a/Source/Contents/ActorNameRequests.cpp b/Source/Contents/ActorNameRequests.cpp index b9cf1a1..a396b80 100644 --- a/Source/Contents/ActorNameRequests.cpp +++ b/Source/Contents/ActorNameRequests.cpp @@ -1,6 +1,22 @@ #include "Contents/ActorNameCard.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketId.h" #include +#include +#include +#include + +#pragma pack(push, 1) +struct PACKET_CZ_REQNAME2 { + /* 0000 */ std::int16_t packetType; + /* 0002 */ std::uint32_t gid; +}; +#pragma pack(pop) + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(PACKET_CZ_REQNAME2) == 6); +#endif // OFFSET: 0x005BFD10 // FUNCTION: fn_03500 @@ -18,3 +34,36 @@ const CActorNameCard& CActorNameCardHolder::Lookup(std::uint32_t id) { static CActorNameCard empty; return empty; } + +// OFFSET: 0x005C01D0 +// FUNCTION: fn_03504 +void CActorNameCardHolder::ProcessRequests() { + while (!this->requests.empty()) { + const Request request = this->requests.front(); + if (timeGetTime() < request.tick + 10000) { + break; + } + this->requests.pop_front(); + } + + while (!this->pending.empty()) { + const std::uint32_t id = this->pending.front(); + const auto found = this->cards.find(id); + if (found == this->cards.end() || found->second.received != 1) { + const auto requested = std::find_if(this->requests.begin(), this->requests.end(), [id](const Request& request) { return request.id == id; }); + if (requested == this->requests.end()) { + this->pending.pop_front(); + if (id != 0) { + PACKET_CZ_REQNAME2 packet; + packet.packetType = ID_CZ_REQNAME2; + packet.gid = id; + GetRagConnection().Send(sizeof(packet), &packet); + this->requests.push_back({ id, timeGetTime() }); + } + return; + } + } + + this->pending.pop_front(); + } +} diff --git a/Source/Contents/MessageTable.cpp b/Source/Contents/MessageTable.cpp index ed6a0f1..c20d7d2 100644 --- a/Source/Contents/MessageTable.cpp +++ b/Source/Contents/MessageTable.cpp @@ -4855,6 +4855,35 @@ bool CCommonObject::LoadCsv(const char* name, std::vector (*transfo return true; } +// OFFSET: 0x005B7FE0 +// FUNCTION: fn_03419 +bool CCommonObject::LoadCsv(const char* name, std::function(std::vector&)> transform, + std::function&, std::any)> insert, std::any context) { + CFile file; + if (!this->OpenCsv(name, file)) { + return false; + } + + while (!file.IsEOF()) { + std::vector row = this->ReadCsvRow(file, ','); + if (transform) { + row = transform(row); + } + + if (insert) { + std::vector fields; + fields.reserve(row.size()); + for (const std::string& field : row) { + fields.push_back(field.c_str()); + } + insert(fields, context); + } + } + + file.Close(); + return true; +} + // OFFSET: 0x00B00360 // FUNCTION: fn_18368 int FillMessageBuckets(int* first, std::uintptr_t last, int* value) { diff --git a/Source/File/CommonObject.h b/Source/File/CommonObject.h index 1e51e23..d3206a3 100644 --- a/Source/File/CommonObject.h +++ b/Source/File/CommonObject.h @@ -1,6 +1,8 @@ #ifndef RAGNAROK_SOURCE_FILE_COMMONOBJECT_H #define RAGNAROK_SOURCE_FILE_COMMONOBJECT_H +#include +#include #include #include @@ -17,6 +19,8 @@ public: void Clear(); bool LoadTokens(std::vector& tokens, const char* name, int mode, ResourceBytes& file); bool LoadCsv(const char* name, std::vector (*transform)(const std::vector&), void (*insert)(std::vector&)); + bool LoadCsv(const char* name, std::function(std::vector&)> transform, + std::function&, std::any)> insert, std::any context); private: bool OpenCsv(const char* name, CFile& file);