rodecomp/Source/Contents/Store/MCStoreInfoBackup.cpp
ragnarok-clanker e168b4e4a6 Restore translation-unit ownership and publish verified source corrections
Owner-authorized source migration: 31 helper-only translation units were merged into their callers or existing inline headers; both build manifests updated. Includes the preserved source payload, Lua configuration matching wowdecomp, and exact malloca expansion without diagnostic pragmas.

449 native units compiled locally and 449 staged units compiled by the pinned server toolchain. No previously byte-matched function regressed. Compiler mapping diagnostics remain recorded as needs_cleanup, not accepted or peer-confirmed. Existing independent review records are preserved. README.md is intentionally unchanged.
2026-10-25 15:42:21 +00:00

213 lines
5.9 KiB
C++

#include "Contents/UserData/AccountService.h"
#include "Contents/Async/AsyncWorkMgr.h"
#include "Contents/Store/MCStoreInfoBackup.h"
#include "Contents/MessageTable.h"
#include "Contents/Store/StoreBackupData.h"
#include "Utility/Async/AsyncDiagnostic.h"
#include <algorithm>
#include <cstring>
#include <json/reader.h>
#include <json/value.h>
#include <json/writer.h>
// OFFSET: 0x00605BF0
// FUNCTION: fn_04226
CMCStoreInfoBackup::CMCStoreInfoBackup() : enabled(true), loaded(false), pendingSaves(0), type(0) {
}
// OFFSET: 0x00605D70
// OFFSET: 0x00605DF0
// FUNCTION: fn_04227
CMCStoreInfoBackup::~CMCStoreInfoBackup() = default;
// OFFSET: 0x00605EC0
// FUNCTION: fn_04229
void CMCStoreInfoBackup::Clear() {
this->items.clear();
}
// OFFSET: 0x00606BB0
// FUNCTION: fn_04234
int CMCStoreInfoBackup::Restore(unsigned char wholeItem, int maximum, std::list<ItemInfo>& inventory, std::list<ItemInfo>& storeItems) {
auto saved = this->items.begin();
int examined = 0;
while (saved != this->items.end() && examined < maximum) {
const auto found = std::find_if(inventory.begin(), inventory.end(), [&](const ItemInfo& item) {
if (item.itemId != saved->itemId || std::memcmp(item.unknown_001C, saved->unknown_001C, sizeof(item.unknown_001C)) != 0 ||
item.identified != saved->identified || item.unknown_0060 != saved->unknown_0060 || item.unknown_0088 != saved->unknown_0088 ||
item.unknown_0098 != saved->unknown_0098) {
return false;
}
const int count = item.unknown_0098;
if (count >= 5) {
return false;
}
return count <= 0 || std::memcmp(item.unknown_009C, saved->unknown_009C, static_cast<std::size_t>(count) * 5) == 0;
});
if (found == inventory.end()) {
saved = this->items.erase(saved);
} else {
ItemInfo item(*found);
if (wholeItem == 0) {
item.quantity = std::min(item.quantity, saved->quantity);
}
if (item.unknown_0000[0] != 0) {
const auto offered =
std::find_if(storeItems.begin(), storeItems.end(), [&](const ItemInfo& value) { return value.unknown_0000[1] == item.unknown_0000[1]; });
if (offered == storeItems.end()) {
storeItems.push_back(item);
} else if (wholeItem == 0) {
offered->quantity += item.quantity;
}
if (wholeItem != 0) {
inventory.erase(found);
} else {
found->quantity -= item.quantity;
if (found->quantity <= 0) {
inventory.erase(found);
}
}
}
++saved;
}
++examined;
}
return examined;
}
// OFFSET: 0x00605EE0
// FUNCTION: fn_04230
std::string CMCStoreInfoBackup::LoadUrl() const {
return this->loadUrl;
}
// OFFSET: 0x00605F40
// FUNCTION: fn_04231
std::string CMCStoreInfoBackup::SaveUrl() const {
return this->saveUrl;
}
// OFFSET: 0x006070E0
// FUNCTION: fn_04237
void CMCStoreInfoBackup::Reset(LuaScript& settings, LuaScript& tables, const char* host, const char* port, const char* overrideKey) {
this->loaded = false;
this->title.clear();
this->items.clear();
const std::string base = ResolveAccountServiceBase(settings, tables, host, port, overrideKey);
if (!base.empty()) {
this->saveUrl = base + "/MerchantStore/save";
this->loadUrl = base + "/MerchantStore/load";
}
}
// OFFSET: 0x00605FA0
// FUNCTION: fn_04232
void CMCStoreInfoBackup::CompleteLoad(
AsyncDiagnostic diagnostic, std::uint32_t, std::uint32_t, std::string, std::string response, StoreBackupContext& 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;
}
const int type = root["Type"].asInt();
if (type == 1) {
Json::Value& data = root["data"];
StoreBackupData{this->title, this->items}.Import(data);
if (!data["Item"].isNull() || !this->title.empty()) {
context.RefreshShop();
}
}
if (type == 1 || type == 4) {
this->loaded = true;
}
}
// OFFSET: 0x00607810
// FUNCTION: fn_04239
void CMCStoreInfoBackup::CompleteSave(AsyncDiagnostic diagnostic, std::string response, StoreBackupContext& context) {
--this->pendingSaves;
if (!diagnostic.success) {
return;
}
Json::Value root;
Json::Reader reader;
const std::string document(response.c_str());
if (!reader.parse(document, root, true) || root["Type"].asInt() != 1) {
return;
}
context.ui.Notify(3, nullptr, 0);
if (this->type == 0 || this->type == 1) {
const char* message = LookupMessage(this->type == 0 ? 3685 : 3686, context.languagePrefix, context.serviceType, context.language);
context.ui.Notify(1, message, 0xFFFF);
}
}
// OFFSET: 0x00606DE0
// FUNCTION: fn_04235
void CMCStoreInfoBackup::Load(
std::uint32_t accountId, std::uint32_t characterId, std::string accountName, const char* token16, int type, CAsyncWorkMgr& workManager,
StoreBackupContext& context
) {
if (accountId == 0 || characterId == 0) {
return;
}
const std::string token(token16, 16);
const std::string url = this->LoadUrl();
workManager.LoadStore(accountId, characterId, accountName, url, token, type, *this, context);
}
// OFFSET: 0x00606EB0
// FUNCTION: fn_04236
void CMCStoreInfoBackup::Save(
int type, std::uint32_t accountId, std::uint32_t characterId, const char* accountName, const char* token16, const std::list<ItemInfo>& storeItems,
CAsyncWorkMgr& workManager, StoreBackupContext& context
) {
this->type = type;
Json::Value root;
Json::Value data;
StoreBackupData{this->title, this->items}.Export(data, storeItems);
if (!data.isNull()) {
root["data"] = data;
Json::StyledWriter writer;
const std::string response = writer.write(root);
const std::string token(token16, 16);
const std::string url = this->SaveUrl();
const std::string name(accountName);
workManager.SaveStore(accountId, characterId, name, url, token, response, this->type, *this, context);
++this->pendingSaves;
}
}