mirror of
https://github.com/tswow/tswow
synced 2026-08-14 20:29:06 -04:00
133 lines
No EOL
4 KiB
C++
133 lines
No EOL
4 KiB
C++
/*
|
|
* This file is part of tswow (https://github.com/tswow)
|
|
*
|
|
* Copyright (C) 2020 tswow <https://github.com/tswow/>
|
|
* This program is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation, version 3.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include <boost/filesystem.hpp>
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
#include <StormLib.h>
|
|
#include <stdexcept>
|
|
#include <iostream>
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
|
|
std::vector<std::string> special_files = {
|
|
"interface\\glues\\charactercreate\\ui-charactercreate-classes.blp"
|
|
, "interface\\targetingframe\\ui-classes-circles.blp"
|
|
, "interface\\worldstateframe\\icons-classes.blp"
|
|
, "textures\\minimap\\md5translate.trs"
|
|
};
|
|
|
|
HANDLE handle = NULL;
|
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
fs::path findClientLang(fs::path directory) {
|
|
fs::directory_iterator end;
|
|
for(fs::directory_iterator itr(directory); itr != end; ++itr)
|
|
{
|
|
if(fs::is_directory(itr->path()))
|
|
{
|
|
return itr->path();
|
|
}
|
|
}
|
|
throw std::runtime_error("No lang directory found in "+directory.string());
|
|
}
|
|
|
|
int counter = 0;
|
|
void handleFile(HANDLE hMpq, std::string const& file,std::string const& outputDir) {
|
|
std::string fileLower = file;
|
|
std::transform(fileLower.begin(), fileLower.end(), fileLower.begin(),
|
|
[](unsigned char c){ return std::tolower(c); });
|
|
|
|
if(
|
|
boost::algorithm::ends_with(file,".xml")
|
|
|| boost::algorithm::ends_with(file,".lua")
|
|
|| boost::algorithm::ends_with(file,".toc")
|
|
|| std::find(special_files.begin(),special_files.end(),fileLower) != special_files.end())
|
|
{
|
|
auto f = file;
|
|
std::replace(f.begin(),f.end(),'\\','/');
|
|
fs::path outfile = outputDir / fs::path(f);
|
|
fs::create_directories(outfile.parent_path());
|
|
SFileExtractFile(hMpq,file.c_str(),outfile.string().c_str(),0);
|
|
++counter;
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
if (argc < 2) {
|
|
std::cout << "Usage: luaxmlreader outputDir clientPath inputDir1";
|
|
return -1;
|
|
}
|
|
|
|
std::string outputDir = argv[1];
|
|
fs::path langdir = findClientLang(fs::path(argv[2]));
|
|
fs::path mainfile;
|
|
std::vector<fs::path> patches;
|
|
|
|
// todo: hack for md5translate.trs, do this properly!
|
|
fs::directory_iterator end;
|
|
|
|
for(fs::directory_iterator itr(langdir); itr != end; ++itr)
|
|
{
|
|
if (itr->path().filename().string().find("locale-", 0) == 0) {
|
|
mainfile = itr->path();
|
|
}
|
|
|
|
else if (itr->path().filename().string().find("patch") == 0) {
|
|
auto fullstr = itr->path();
|
|
if(!fs::is_directory(fullstr))
|
|
{
|
|
patches.push_back(fullstr);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::sort(patches.begin(), patches.end(), [](fs::path const& a, fs::path const& b) {
|
|
if (b.string().length() != a.string().length()) return b.string().length() > a.string().length();
|
|
return b.string() > a.string();
|
|
});
|
|
|
|
// md5translate.trs hack
|
|
patches.push_back(fs::path(argv[2]) / "patch-3.MPQ");
|
|
|
|
HANDLE mpq = NULL;
|
|
if (!SFileOpenArchive(mainfile.string().c_str(), 0, STREAM_FLAG_READ_ONLY, &mpq)) {
|
|
std::cout << "Failed to open main MPQ file " << mainfile.string() << " with error " << GetLastError() << "\n";
|
|
return GetLastError();
|
|
}
|
|
|
|
for (auto& patch : patches) {
|
|
if (!SFileOpenPatchArchive(mpq, patch.string().c_str(), NULL, 0)) {
|
|
std::cout << "Failed to apply patch " << patch << " with error " << GetLastError() << "\n";
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
HANDLE find_handle = NULL;
|
|
SFILE_FIND_DATA* f = new SFILE_FIND_DATA;
|
|
if ((find_handle = SFileFindFirstFile(mpq, "*", f, 0))) {
|
|
handleFile(mpq, std::string(f->cFileName), outputDir);
|
|
}
|
|
|
|
while (SFileFindNextFile(find_handle, f)) {
|
|
handleFile(mpq, std::string(f->cFileName), outputDir);
|
|
}
|
|
|
|
SFileFindClose(find_handle);
|
|
SFileCloseArchive(mpq);
|
|
return 0;
|
|
} |