new client utils, start wow and patch game
This commit is contained in:
2
src/external/blizzard-archive-library
vendored
2
src/external/blizzard-archive-library
vendored
Submodule src/external/blizzard-archive-library updated: cb73a80bc6...25c98a8fbd
@@ -15,6 +15,11 @@
|
|||||||
#include <noggit/ui/FramelessWindow.hpp>
|
#include <noggit/ui/FramelessWindow.hpp>
|
||||||
#include <noggit/ui/tools/UiCommon/StackedWidget.hpp>
|
#include <noggit/ui/tools/UiCommon/StackedWidget.hpp>
|
||||||
#include <noggit/project/ApplicationProject.h>
|
#include <noggit/project/ApplicationProject.h>
|
||||||
|
#include <noggit/ui/windows/noggitWindow/widgets/MapListItem.hpp>
|
||||||
|
#include <noggit/ui/windows/noggitWindow/widgets/MapBookmarkListItem.hpp>
|
||||||
|
#include <noggit/ui/windows/noggitWindow/components/BuildMapListComponent.hpp>
|
||||||
|
#include <noggit/application/Utils.hpp>
|
||||||
|
#include <noggit/application/NoggitApplication.hpp>
|
||||||
#include <BlizzardDatabase.h>
|
#include <BlizzardDatabase.h>
|
||||||
#include <QtGui/QCloseEvent>
|
#include <QtGui/QCloseEvent>
|
||||||
#include <QtWidgets/QHBoxLayout>
|
#include <QtWidgets/QHBoxLayout>
|
||||||
@@ -27,16 +32,14 @@
|
|||||||
#include <QtWidgets/QWidget>
|
#include <QtWidgets/QWidget>
|
||||||
#include <QtWidgets/QStackedWidget>
|
#include <QtWidgets/QStackedWidget>
|
||||||
#include <QtWidgets/QComboBox>
|
#include <QtWidgets/QComboBox>
|
||||||
#include <noggit/ui/windows/noggitWindow/widgets/MapListItem.hpp>
|
|
||||||
#include <noggit/ui/windows/noggitWindow/widgets/MapBookmarkListItem.hpp>
|
|
||||||
#include <QtNetwork/QTcpSocket>
|
#include <QtNetwork/QTcpSocket>
|
||||||
#include <sstream>
|
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <noggit/ui/windows/noggitWindow/components/BuildMapListComponent.hpp>
|
|
||||||
#include <noggit/application/Utils.hpp>
|
#include <sstream>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#ifdef USE_MYSQL_UID_STORAGE
|
#ifdef USE_MYSQL_UID_STORAGE
|
||||||
#include <mysql/mysql.h>
|
#include <mysql/mysql.h>
|
||||||
@@ -567,4 +570,217 @@ namespace Noggit::Ui::Windows
|
|||||||
"The models are listed in the log file.", QMessageBox::Ok
|
"The models are listed in the log file.", QMessageBox::Ok
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
void NoggitWindow::startWowClient()
|
||||||
|
{
|
||||||
|
// TODO auto login
|
||||||
|
|
||||||
|
// TODO attach to process to allow memory edits
|
||||||
|
|
||||||
|
// std::filesystem::path WoW_path = std::filesystem::path(Noggit::Project::CurrentProject::get()->ClientPath) / "Wow.exe";
|
||||||
|
std::filesystem::path WoW_path = std::filesystem::path(_project->ClientPath) / "Wow.exe";
|
||||||
|
|
||||||
|
QString program_path = WoW_path.string().c_str();
|
||||||
|
QFileInfo checkFile(program_path);
|
||||||
|
|
||||||
|
QStringList arguments;
|
||||||
|
// arguments << "-console"; // deosn't seem to work
|
||||||
|
arguments << "-windowed";
|
||||||
|
// auto login using https://github.com/FrostAtom/awesome_wotlk, requires patched Wow.exe
|
||||||
|
// arguments << "-login \"LOGIN\" -password \"PASSWORD\" -realmlist \"REALMLIST\" -realmname \"REALMNAME\"";
|
||||||
|
|
||||||
|
|
||||||
|
if (checkFile.exists() && checkFile.isFile())
|
||||||
|
{
|
||||||
|
QProcess* process = new QProcess(this); // this parent?
|
||||||
|
process->start(program_path, arguments);
|
||||||
|
|
||||||
|
//Noggit::Application::NoggitApplication::instance().
|
||||||
|
if (!process->waitForStarted()) {
|
||||||
|
// qWarning("Failed to start process");
|
||||||
|
QMessageBox::information(this, "Error", "Failed to start process Wow.exe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// qWarning("File does not exist");
|
||||||
|
QMessageBox::information(this, "Error", std::format("File {} does not exist", WoW_path.string()).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NoggitWindow::patchWowClient()
|
||||||
|
{
|
||||||
|
// Option to make folder patch ?
|
||||||
|
|
||||||
|
QDialog* mpq_patch_params = new QDialog(this);
|
||||||
|
mpq_patch_params->setWindowFlags(Qt::Dialog);
|
||||||
|
mpq_patch_params->setWindowTitle("Patch Export Settings");
|
||||||
|
QVBoxLayout* mpq_patch_params_layout = new QVBoxLayout(mpq_patch_params);
|
||||||
|
|
||||||
|
mpq_patch_params_layout->addWidget(new QLabel("<font color=orange><h4> Warning :\
|
||||||
|
\nErrors can cause MPQ Corruption, make sure to have backup.</h4></font>\
|
||||||
|
\nWhile Noggit is writting the archive, files are not accessible by the client, please wait.", mpq_patch_params));
|
||||||
|
|
||||||
|
mpq_patch_params_layout->addWidget(new QLabel("MPQ Name:", mpq_patch_params));
|
||||||
|
|
||||||
|
QLineEdit* mpq_patch_params_ledit = new QLineEdit("patch-A.MPQ", mpq_patch_params);
|
||||||
|
QSettings settings;
|
||||||
|
// saved last set patch name
|
||||||
|
mpq_patch_params_ledit->setText(settings.value("noggit_window/mpq_name", "patch-A.MPQ").toString());
|
||||||
|
mpq_patch_params_layout->addWidget(mpq_patch_params_ledit);
|
||||||
|
|
||||||
|
|
||||||
|
QCheckBox* mpq_patch_params_locale_chk = new QCheckBox("Save DBC to Locale:", mpq_patch_params);
|
||||||
|
mpq_patch_params_locale_chk->setToolTip("This is recommended for non English clients");
|
||||||
|
//auto set locale mode if client isn't english.
|
||||||
|
bool non_english = false;
|
||||||
|
BlizzardArchive::Locale locale_mode = Noggit::Application::NoggitApplication::instance()->clientData()->locale_mode();
|
||||||
|
if (!(locale_mode != BlizzardArchive::Locale::AUTO) && !(locale_mode != BlizzardArchive::Locale::enGB)
|
||||||
|
&& !(locale_mode != BlizzardArchive::Locale::enUS))
|
||||||
|
{
|
||||||
|
non_english = true;
|
||||||
|
}
|
||||||
|
mpq_patch_params_locale_chk->setChecked(non_english);
|
||||||
|
// Unimplemented
|
||||||
|
mpq_patch_params_locale_chk->setHidden(true);
|
||||||
|
mpq_patch_params_locale_chk->setDisabled(true);
|
||||||
|
mpq_patch_params_layout->addWidget(mpq_patch_params_locale_chk);
|
||||||
|
|
||||||
|
|
||||||
|
// mode choice between replace archive and add files to archive
|
||||||
|
QCheckBox* mpq_overwrite_chk = new QCheckBox("Overwrite Archive", mpq_patch_params);
|
||||||
|
mpq_overwrite_chk->setToolTip("If there is already an archive with this name, it will be deleted and replaced by a new one.");
|
||||||
|
mpq_overwrite_chk->setChecked(false);
|
||||||
|
// Unimplemented
|
||||||
|
mpq_overwrite_chk->setHidden(true);
|
||||||
|
mpq_overwrite_chk->setDisabled(true);
|
||||||
|
mpq_patch_params_layout->addWidget(mpq_overwrite_chk);
|
||||||
|
|
||||||
|
|
||||||
|
QCheckBox* mpq_compact_chk = new QCheckBox("Compact Archive", mpq_patch_params);
|
||||||
|
mpq_compact_chk->setToolTip("Adding and removing files creates empty space in the MPQ, making it grow in size.\
|
||||||
|
\nCompacting takes a few seconds depending on patch size, it is recommended to compact when many files have been added.");
|
||||||
|
mpq_compact_chk->setChecked(false);
|
||||||
|
mpq_patch_params_layout->addWidget(mpq_compact_chk);
|
||||||
|
|
||||||
|
QCheckBox* mpq_compress_files_chk = new QCheckBox("Compress Files (slow)", mpq_patch_params);
|
||||||
|
mpq_compress_files_chk->setToolTip("Files will be compressed in the MPQ, but writting becomes much slower(about 3x slower).\
|
||||||
|
\nRecommended for distribution.");
|
||||||
|
mpq_compress_files_chk->setChecked(true);
|
||||||
|
mpq_patch_params_layout->addWidget(mpq_compress_files_chk);
|
||||||
|
|
||||||
|
|
||||||
|
QPushButton* mpq_patch_params_okay = new QPushButton("Save Project to Client MPQ", mpq_patch_params);
|
||||||
|
mpq_patch_params_layout->addWidget(mpq_patch_params_okay);
|
||||||
|
|
||||||
|
connect(mpq_patch_params_okay, &QPushButton::clicked
|
||||||
|
, [=]()
|
||||||
|
{
|
||||||
|
// check if mpq name is allowed
|
||||||
|
if (!Noggit::Application::NoggitApplication::instance()->clientData()->isMPQNameValid(mpq_patch_params_ledit->text().toLower().toStdString(), true))
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, "Name Error", "MPQ Name is not allowed.\This name is already used by base client patches, or the client can't load it.\
|
||||||
|
\nYour patch must be named \"patch-[4-9].MPQ\" or \"patch-[A-Z].MPQ\".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue("noggit_window/mpq_name", mpq_patch_params_ledit->text());
|
||||||
|
settings.sync();
|
||||||
|
|
||||||
|
mpq_patch_params->accept();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// execute dialog, and run code when Mpq_patch_params_okay calls Mpq_patch_params->accept();
|
||||||
|
if (mpq_patch_params->exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
// OK button was pressed, do stuff.
|
||||||
|
|
||||||
|
auto archive_name = mpq_patch_params_ledit->text().toStdString();
|
||||||
|
auto clientData = Noggit::Application::NoggitApplication::instance()->clientData();
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
// progress bar, count maximum files
|
||||||
|
// ignore directories, only count files
|
||||||
|
auto regular_file = [](const fs::path& path) {
|
||||||
|
std::string const extension = path.extension().string();
|
||||||
|
// filter noggit files
|
||||||
|
if (extension == ".noggitproj" || extension == ".json" || extension == ".ini")
|
||||||
|
return false;
|
||||||
|
return fs::is_regular_file(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
int totalItems = std::count_if(fs::recursive_directory_iterator(clientData->projectPath()), {}, regular_file);
|
||||||
|
|
||||||
|
if (!totalItems)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, "Error", std::format("No files found in project {}", clientData->projectPath()).c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!clientData->mpqArchiveExistsOnDisk(archive_name))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto archive = clientData->tryCreateMPQArchive(archive_name);
|
||||||
|
}
|
||||||
|
catch (BlizzardArchive::Exceptions::Archive::ArchiveOpenError& e)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(nullptr, "Error", e.what());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(nullptr, "Error", "Failed to create MPQ Archive. Unhandled exception.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto archive = clientData->getMPQArchive(archive_name);
|
||||||
|
if (archive.has_value())
|
||||||
|
{
|
||||||
|
auto progress_box = new QMessageBox(QMessageBox::Information, "Working...", std::format("Saving {} files to patch {}...\
|
||||||
|
\nClosing the program now can corrupt the MPQ.", std::to_string(totalItems), archive_name ).c_str(), QMessageBox::StandardButton::NoButton, this);
|
||||||
|
progress_box->setStandardButtons(QMessageBox::NoButton);
|
||||||
|
progress_box->setWindowFlags(progress_box->windowFlags() & ~Qt::WindowCloseButtonHint);
|
||||||
|
// progress_box->exec(); // this stops code execution
|
||||||
|
progress_box->repaint();
|
||||||
|
qApp->processEvents();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
std::array<int, 2> result = clientData->saveLocalFilesToArchive(archive.value(), mpq_compress_files_chk->isChecked(), mpq_compact_chk->isChecked());
|
||||||
|
int processed_files = result[0];
|
||||||
|
int files_failed = processed_files - result[1];
|
||||||
|
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
std::chrono::duration<double> duration = end - start;
|
||||||
|
std::ostringstream oss; // duration in seconds with 1 digit
|
||||||
|
oss << std::fixed << std::setprecision(1) << duration.count();
|
||||||
|
|
||||||
|
// if no file was processed, archive was most likely opened and not accessible
|
||||||
|
// TODO : we can throw an error message in saveLocalFilesToArchive if (!archive->openForWritting()) instead
|
||||||
|
if (!processed_files)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, "Error", "Project Folder is not a valid directory or client MPQ is not accessible.\
|
||||||
|
\nMake sure it isn't opened by Wow or MPQ editor");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QMessageBox::information(this, "Archive Updated", std::format("Added {} files to existing Archive {} in {} seconds.\
|
||||||
|
\n{} Files failed.", std::to_string(processed_files), archive_name, oss.str(), std::to_string(files_failed)).c_str());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(nullptr, "Error", "unhandled exception");
|
||||||
|
}
|
||||||
|
|
||||||
|
progress_box->close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QMessageBox::warning(this, "Error", std::format("Error accessing archive {}", archive_name).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ namespace Noggit::Ui::Windows
|
|||||||
void promptExit(QCloseEvent* event);
|
void promptExit(QCloseEvent* event);
|
||||||
void promptUidFixFailure();
|
void promptUidFixFailure();
|
||||||
|
|
||||||
|
// TODO, better location for those utils that need to be above mapview?
|
||||||
|
void startWowClient();
|
||||||
|
|
||||||
|
void patchWowClient();
|
||||||
|
|
||||||
|
|
||||||
QMenuBar* _menuBar;
|
QMenuBar* _menuBar;
|
||||||
|
|
||||||
QToolBar* _app_toolbar;
|
QToolBar* _app_toolbar;
|
||||||
|
|||||||
Reference in New Issue
Block a user