From 8d54e8ad0b109b44953b54defabcc2642d546ed5 Mon Sep 17 00:00:00 2001 From: VDm Date: Sat, 29 Mar 2025 22:58:53 +0400 Subject: [PATCH] feat(client): add PatchFiles class --- src/client/Client.cpp | 11 ++++---- src/client/Client.hpp | 2 ++ src/client/Patch.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++ src/client/Patch.hpp | 33 ++++++++++++++++++++++ src/util/SFile.cpp | 19 +++++++++++-- src/util/SFile.hpp | 2 ++ 6 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 src/client/Patch.cpp create mode 100644 src/client/Patch.hpp diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 4dcee3e..aefcb3f 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -376,18 +376,17 @@ int32_t InitializeGlobal() { CheckAvailableLocales(existingLocale); locale->Set(existingLocale, true, false, false, true); + char path[STORM_MAX_PATH]; + SStrPrintf(path, sizeof(path), "%s%s", "Data\\", locale->GetString()); + SFile::SetDataPathAlternate(path); + SFile::RebuildHash(); + OpenArchives(); // TODO: This method should be placed inside OpenArchives ClientServices::InitLoginServerCVars(1, locale->GetString()); - // SStrPrintf(dest, 260, "%s%s", *(_DWORD *)off_AB6158, v2->m_stringValue.m_str); - - // sub_421B50(dest); - - // sub_423D70(); - // sub_405DD0(); // CVar* v3 = CVar::Register( diff --git a/src/client/Client.hpp b/src/client/Client.hpp index ca6ea88..3ad8056 100644 --- a/src/client/Client.hpp +++ b/src/client/Client.hpp @@ -14,6 +14,8 @@ namespace Client { void ClientPostClose(int32_t a1); +const char* UpdateInstallLocation(); + void CommonMain(); void StormInitialize(); diff --git a/src/client/Patch.cpp b/src/client/Patch.cpp new file mode 100644 index 0000000..0e63151 --- /dev/null +++ b/src/client/Patch.cpp @@ -0,0 +1,65 @@ +#include "client/Patch.hpp" + +#include + +#include "client/Client.hpp" + + +PatchFiles::PatchFiles() { + this->path = nullptr; +} + +void PatchFiles::SearchArchives(const char* locale, int32_t a3) { + char fullPath[256] = {}; + char pattern[256] = {}; + char path[256] = {}; + + const size_t listSize = 12; + + ListEntry list[listSize] = { + { 0, 0, false, "Data\\", "patch-?.MPQ" }, + { 0, 0, false, "Data\\%s\\", "patch-%s-?.MPQ" }, + { 1, 0, false, "Data\\", "patch.MPQ" }, + { 1, 0, false, "Data\\%s\\", "patch-%s.MPQ" }, + { 1, 1, false, "Data\\", "patch-4.MPQ" }, + { 1, 1, false, "Data\\%s\\", "patch-%s-4.MPQ" }, + { 1, 1, false, "Data\\", "patch-3.MPQ" }, + { 1, 1, false, "Data\\%s\\", "patch-%s-3.MPQ" }, + { 1, 1, false, "..\\Data\\", "patch-2.MPQ" }, + { 1, 1, false, "..\\Data\\%s\\", "patch-%s-2.MPQ" }, + { 1, 1, false, "..\\Data\\", "patch.MPQ" }, + { 1, 1, false, "..\\Data\\%s\\", "patch-%s.MPQ" }, + }; + + const char* installRoot = UpdateInstallLocation(); + + // Warning: assigning pointer to a temporary variable + // Need this for OsFileList's callback + this->path = path; + + for (size_t i = 0; i <= 2; ++i) { + for (size_t j = 0; j < listSize; ++j) { + auto entry = &list[j]; + if (entry->num1 != i || entry->num2 != (a3 != 0)) { + continue; + } + + SStrPrintf(path, sizeof(path), entry->dataDir, locale); + SStrPrintf(pattern, sizeof(pattern), entry->pattern, locale); + if (entry->absolute && installRoot && installRoot[0]) { + SStrPrintf(fullPath, sizeof(fullPath), "%s%s", installRoot, path); + SStrCopy(path, fullPath, sizeof(path)); + + } + // TODO: OsFileList(this->path, pattern, PatchFiles::EnumPatchArchives, this, 0); + } + + if (i == 0) { + std::qsort(this->files.Ptr(), this->files.Count(), sizeof(char*), &PatchFiles::qsortpatchfiles); + } + } +} + +int PatchFiles::qsortpatchfiles(const void* a1, const void* a2) { + return -SStrCmpI(*((const char**) a1), *((const char**) a2), STORM_MAX_STR); +} diff --git a/src/client/Patch.hpp b/src/client/Patch.hpp new file mode 100644 index 0000000..443c879 --- /dev/null +++ b/src/client/Patch.hpp @@ -0,0 +1,33 @@ +#ifndef CLIENT_PATCH_HPP +#define CLIENT_PATCH_HPP + + +#include + + +class PatchFiles { + public: + PatchFiles(); + + void SearchArchives(const char* locale, int32_t a3); + + public: + char* path; + TSGrowableArray files; + + private: + static int qsortpatchfiles(const void* a1, const void* a2); + + private: + struct ListEntry { + uint32_t num1; + uint32_t num2; + bool absolute; + const char* dataDir; + const char* pattern; + }; +}; + + + +#endif diff --git a/src/util/SFile.cpp b/src/util/SFile.cpp index 84a29f6..5cc0d76 100644 --- a/src/util/SFile.cpp +++ b/src/util/SFile.cpp @@ -8,8 +8,9 @@ #include #include "util/Filesystem.hpp" -static char s_basepath[STORM_MAX_PATH] = {0}; -static char s_datapath[STORM_MAX_PATH] = {0}; +static char s_basepath[STORM_MAX_PATH] = { 0 }; +static char s_datapath[STORM_MAX_PATH] = { 0 }; +static char s_datapath2[STORM_MAX_PATH] = { 0 }; // TODO Proper implementation int32_t SFile::Close(SFile* file) { @@ -279,3 +280,17 @@ int32_t SFile::GetDataPath(char* buffer, size_t bufferchars) { SStrCopy(buffer, s_datapath, bufferchars); return 1; } + +int32_t SFile::SetDataPathAlternate(const char* path) { + SStrCopy(s_datapath2, path, STORM_MAX_PATH); + size_t length = SStrLen(s_datapath2); + if (length && s_datapath2[length - 1] != '\\' && s_datapath2[length - 1] != '/') { + SStrPack(s_datapath2, "\\", STORM_MAX_PATH); + } + return 1; +} + +int32_t SFile::RebuildHash() { + // TODO + return 1; +} diff --git a/src/util/SFile.hpp b/src/util/SFile.hpp index 1e3db95..350859d 100644 --- a/src/util/SFile.hpp +++ b/src/util/SFile.hpp @@ -39,6 +39,8 @@ class SFile { static int32_t SetDataPath(const char* path); static int32_t GetBasePath(char* path, size_t capacity); static int32_t GetDataPath(char* path, size_t capacity); + static int32_t SetDataPathAlternate(const char* path); + static int32_t RebuildHash(); // Member variables SFILE_TYPE m_type;