diff --git a/r5dev/vpklib/packedstore.cpp b/r5dev/vpklib/packedstore.cpp index ff14ad45..7feb59cd 100644 --- a/r5dev/vpklib/packedstore.cpp +++ b/r5dev/vpklib/packedstore.cpp @@ -43,41 +43,68 @@ void CPackedStore::InitLzDecompParams(void) } //----------------------------------------------------------------------------- -// Purpose: gets a directory structure for specified file +// Purpose: gets a directory structure for specified file. // Input : svPackDirFile - +// bSanitizeName - retrieve the directory file name from block name // Output : VPKDir_t //----------------------------------------------------------------------------- -VPKDir_t CPackedStore::GetDirectoryFile(string svPackDirFile) const +VPKDir_t CPackedStore::GetDirectoryFile(string svPackDirFile, bool bSanitizeName) const { /*| PACKDIRFILE |||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/ - std::regex rgArchiveRegex("pak000_([0-9]{3})"); std::smatch smRegexMatches; - std::regex_search(svPackDirFile, smRegexMatches, rgArchiveRegex); + if (!bSanitizeName) + return VPKDir_t(svPackDirFile); - if (smRegexMatches.size() != 0) + std::regex_search(svPackDirFile, smRegexMatches, BLOCK_REGEX); + if (smRegexMatches.empty()) + return VPKDir_t(svPackDirFile); + + StringReplace(svPackDirFile, smRegexMatches[0], "pak000_dir"); + + bool bHasLocale = false; + bool bHasContext = false; + string svPackDirPrefix; + + size_t nLocaleIndex = 0; // Default to ENGLISH; + size_t nContextIndex = 0; // Default to SERVER; + + for (size_t i = 0, nl = DIR_LOCALE.size(); i < nl; i++) { - StringReplace(svPackDirFile, smRegexMatches[0], "pak000_dir"); - - for (const string& svLocale : DIR_LOCALE) + const string& svLocale = DIR_LOCALE[i]; + if (svPackDirFile.find(svLocale) != string::npos) { - if (svPackDirFile.find(svLocale) != string::npos) - { - for (const string& svContext : DIR_CONTEXT) - { - if (svPackDirFile.find(svContext) != string::npos) - { - const string svPackDirPrefix = svContext + svContext; - StringReplace(svPackDirFile, svContext, svPackDirPrefix); - goto escape; - } - } - } - }escape:; + svPackDirPrefix.append(svLocale); + nLocaleIndex = i; + bHasLocale = true; + } } - VPKDir_t vDir(svPackDirFile); - return vDir; + if (svPackDirPrefix.empty()) // No locale found. + { + svPackDirPrefix.append(DIR_LOCALE[0]); + } + + if (!bHasLocale) + { + for (size_t i = 0, nc = DIR_CONTEXT.size(); i < nc; i++) + { + const string& svContext = DIR_CONTEXT[i]; + if (svPackDirFile.find(svContext) != string::npos) + { + svPackDirPrefix.append(svContext); + nContextIndex = i; + bHasContext = true; + } + } + } + + if (bHasContext) // Context is required for this to work. + { + StringReplace(svPackDirFile, DIR_CONTEXT[nContextIndex], svPackDirPrefix); + } + + return VPKDir_t(svPackDirFile); } //----------------------------------------------------------------------------- @@ -148,7 +175,7 @@ vector CPackedStore::GetEntryBlocks(CIOStream* pReader) const //----------------------------------------------------------------------------- // Purpose: scans the input directory and returns the paths to the vector // Input : &svPathIn - -// Output : vector +// Output : a string vector of all included entry paths //----------------------------------------------------------------------------- vector CPackedStore::GetEntryPaths(const string& svPathIn) const { @@ -181,7 +208,7 @@ vector CPackedStore::GetEntryPaths(const string& svPathIn) const // Purpose: scans the input directory and returns the paths to the vector if path exists in manifest // Input : &svPathIn - // &jManifest - -// Output : vector +// Output : a string vector of all included entry paths //----------------------------------------------------------------------------- vector CPackedStore::GetEntryPaths(const string& svPathIn, const nlohmann::json& jManifest) const { @@ -225,15 +252,15 @@ vector CPackedStore::GetEntryPaths(const string& svPathIn, const nlohman } //----------------------------------------------------------------------------- -// Purpose: gets the parts of the directory file name (1 = locale + context, 2 = levelname) +// Purpose: gets the parts of the directory file name // Input : &svDirectoryName - -// nCaptureGroup - -// Output : string +// nCaptureGroup - (1 = locale + context, 2 = levelname) +// Output : part of directory file name as string //----------------------------------------------------------------------------- string CPackedStore::GetNameParts(const string& svDirectoryName, int nCaptureGroup) const { std::smatch smRegexMatches; - std::regex_search(svDirectoryName, smRegexMatches, BLOCK_REGEX); + std::regex_search(svDirectoryName, smRegexMatches, DIR_REGEX); return smRegexMatches[nCaptureGroup].str(); } @@ -241,12 +268,12 @@ string CPackedStore::GetNameParts(const string& svDirectoryName, int nCaptureGro //----------------------------------------------------------------------------- // Purpose: gets the source of the directory file name // Input : &svDirectoryName - -// Output : string +// Output : source name as string (e.g. "mp_rr_box") //----------------------------------------------------------------------------- string CPackedStore::GetSourceName(const string& svDirectoryName) const { std::smatch smRegexMatches; - std::regex_search(svDirectoryName, smRegexMatches, BLOCK_REGEX); + std::regex_search(svDirectoryName, smRegexMatches, DIR_REGEX); return smRegexMatches[1].str() + smRegexMatches[2].str(); } @@ -285,7 +312,7 @@ nlohmann::json CPackedStore::GetManifest(const string& svWorkSpace, const string //----------------------------------------------------------------------------- // Purpose: gets the contents from the global ignore list (.vpkignore) // Input : &svWorkSpace - -// Output : vector +// Output : a string vector of ignored directories/files //----------------------------------------------------------------------------- vector CPackedStore::GetIgnoreList(const string& svWorkSpace) const { @@ -317,7 +344,7 @@ vector CPackedStore::GetIgnoreList(const string& svWorkSpace) const // Input : svPath - // &svName - // &svExtension - -// Output : string +// Output : formatted entry path //----------------------------------------------------------------------------- string CPackedStore::FormatEntryPath(string svPath, const string& svName, const string& svExtension) const { @@ -331,7 +358,7 @@ string CPackedStore::FormatEntryPath(string svPath, const string& svName, const //----------------------------------------------------------------------------- // Purpose: strips locale prefix from file path // Input : &svDirectoryFile - -// Output : string +// Output : directory filename without locale prefix //----------------------------------------------------------------------------- string CPackedStore::StripLocalePrefix(const string& svDirectoryFile) const { @@ -355,7 +382,7 @@ string CPackedStore::StripLocalePrefix(const string& svDirectoryFile) const // svContext - // &svPakName - // nPatch - -// Output : VPKPair_t +// Output : a vpk file pair (block and directory file names) //----------------------------------------------------------------------------- VPKPair_t CPackedStore::BuildFileName(string svLanguage, string svContext, const string& svPakName, int nPatch) const { diff --git a/r5dev/vpklib/packedstore.h b/r5dev/vpklib/packedstore.h index 1ce83c11..9a0bf57d 100644 --- a/r5dev/vpklib/packedstore.h +++ b/r5dev/vpklib/packedstore.h @@ -8,7 +8,8 @@ constexpr unsigned int VPK_MINOR_VERSION = 3; constexpr unsigned int VPK_DICT_SIZE = 20; constexpr int ENTRY_MAX_LEN = 1024 * 1024; -static const std::regex BLOCK_REGEX{ R"((?:.*\/)?([^_]*_)(.*)(.bsp.pak000_dir).*)" }; +static const std::regex BLOCK_REGEX{ R"(pak000_([0-9]{3}))" }; +static const std::regex DIR_REGEX{ R"((?:.*\/)?([^_]*_)(.*)(.bsp.pak000_dir).*)" }; static const vector DIR_CONTEXT = { @@ -142,7 +143,7 @@ public: void InitLzCompParams(void); void InitLzDecompParams(void); - VPKDir_t GetDirectoryFile(string svDirectoryFile) const; + VPKDir_t GetDirectoryFile(string svDirectoryFile, bool bSanitizeName) const; string GetPackFile(const string& svPackDirFile, uint16_t iArchiveIndex) const; lzham_compress_level GetCompressionLevel(void) const; diff --git a/r5dev/vstdlib/callback.cpp b/r5dev/vstdlib/callback.cpp index 1847783a..eb5d980e 100644 --- a/r5dev/vstdlib/callback.cpp +++ b/r5dev/vstdlib/callback.cpp @@ -261,20 +261,20 @@ void Pak_RequestUnload_f(const CCommand& args) { if (args.HasOnlyDigits(1)) { - RPakHandle_t pakHandle = std::stoi(args.Arg(1)); - RPakLoadedInfo_t* pakInfo = g_pRTech->GetPakLoadedInfo(pakHandle); + const RPakHandle_t pakHandle = std::stoi(args.Arg(1)); + const RPakLoadedInfo_t* pakInfo = g_pRTech->GetPakLoadedInfo(pakHandle); if (!pakInfo) { throw std::exception("Found no pak entry for specified handle."); } - string pakName = pakInfo->m_pszFileName; + const string pakName = pakInfo->m_pszFileName; !pakName.empty() ? DevMsg(eDLL_T::RTECH, "Requested pak unload for file '%s'\n", pakName.c_str()) : DevMsg(eDLL_T::RTECH, "Requested pak unload for handle '%d'\n", pakHandle); g_pakLoadApi->UnloadPak(pakHandle); } else { - RPakLoadedInfo_t* pakInfo = g_pRTech->GetPakLoadedInfo(args.Arg(1)); + const RPakLoadedInfo_t* pakInfo = g_pRTech->GetPakLoadedInfo(args.Arg(1)); if (!pakInfo) { throw std::exception("Found no pak entry for specified name."); @@ -537,7 +537,7 @@ void VPK_Unpack_f(const CCommand& args) DevMsg(eDLL_T::FS, "*** Starting VPK extraction command for: '%s'\n", pArg); - VPKDir_t vpk = g_pPackedStore->GetDirectoryFile(pArg); + VPKDir_t vpk = g_pPackedStore->GetDirectoryFile(pArg, (args.ArgC() > 2)); g_pPackedStore->InitLzDecompParams(); std::thread th([&] { g_pPackedStore->UnpackAll(vpk, ConvertToWinPath(fs_packedstore_workspace->GetString())); });