No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
9 changed files with 212 additions and 4 deletions
-
3src/frontend_common/CMakeLists.txt
-
66src/frontend_common/mod_manager.cpp
-
12src/frontend_common/mod_manager.h
-
6src/qt_common/CMakeLists.txt
-
25src/qt_common/abstract/frontend.cpp
-
6src/qt_common/abstract/frontend.h
-
84src/qt_common/util/mod.cpp
-
12src/qt_common/util/mod.h
-
2src/yuzu/main_window.cpp
@ -0,0 +1,66 @@ |
|||
#include <algorithm>
|
|||
#include <filesystem>
|
|||
#include <iostream>
|
|||
#include <fmt/format.h>
|
|||
#include "common/fs/fs.h"
|
|||
#include "common/fs/fs_types.h"
|
|||
#include "common/logging/backend.h"
|
|||
#include "frontend_common/data_manager.h"
|
|||
#include "mod_manager.h"
|
|||
|
|||
namespace FrontendCommon { |
|||
|
|||
// TODO: Handle cases where the folder appears to contain multiple mods.
|
|||
std::optional<std::filesystem::path> GetModFolder(const std::string& root) { |
|||
std::filesystem::path path; |
|||
bool found; |
|||
|
|||
auto callback = [&path, &found](const std::filesystem::directory_entry& entry) -> bool { |
|||
const auto name = entry.path().filename().string(); |
|||
static constexpr const std::array<std::string, 5> valid_names = {"exefs", |
|||
"romfs" |
|||
"romfs_ext", |
|||
"cheats", "romfslite"}; |
|||
|
|||
if (std::ranges::find(valid_names, name) != valid_names.end()) { |
|||
path = entry.path().parent_path(); |
|||
found = true; |
|||
} |
|||
|
|||
return true; |
|||
}; |
|||
|
|||
Common::FS::IterateDirEntriesRecursively(root, callback, Common::FS::DirEntryFilter::Directory); |
|||
|
|||
if (found) |
|||
return path; |
|||
|
|||
return std::nullopt; |
|||
} |
|||
|
|||
bool InstallMod(const std::filesystem::path& path, const u64 program_id, const bool copy) { |
|||
const auto program_id_string = fmt::format("{:016X}", program_id); |
|||
const auto mod_name = path.filename(); |
|||
const auto mod_dir = |
|||
DataManager::GetDataDir(DataManager::DataDir::Mods) / program_id_string / mod_name; |
|||
|
|||
// pre-emptively remove any existing mod here
|
|||
std::filesystem::remove_all(mod_dir); |
|||
|
|||
// now copy
|
|||
try { |
|||
if (copy) |
|||
std::filesystem::copy(path, mod_dir, std::filesystem::copy_options::recursive); |
|||
else |
|||
std::filesystem::rename(path, mod_dir); |
|||
} catch (std::exception& e) { |
|||
LOG_ERROR(Frontend, "Mod install failed with message {}", e.what()); |
|||
return false; |
|||
} |
|||
|
|||
LOG_INFO(Frontend, "Copied mod from {} to {}", path.string(), mod_dir.string()); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
} // namespace FrontendCommon
|
|||
@ -0,0 +1,12 @@ |
|||
#pragma once |
|||
|
|||
#include <filesystem> |
|||
#include <optional> |
|||
#include "common/common_types.h" |
|||
|
|||
namespace FrontendCommon { |
|||
|
|||
std::optional<std::filesystem::path> GetModFolder(const std::string& root); |
|||
|
|||
bool InstallMod(const std::filesystem::path &path, const u64 program_id, const bool copy = true); |
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
#include <filesystem>
|
|||
#include "frontend_common/mod_manager.h"
|
|||
#include "mod.h"
|
|||
#include "qt_common/abstract/frontend.h"
|
|||
|
|||
namespace QtCommon::Mod { |
|||
QString GetModFolder(const QString& root, const QString& fallbackName) { |
|||
namespace fs = std::filesystem; |
|||
|
|||
const auto std_root = root.toStdString(); |
|||
auto std_path = FrontendCommon::GetModFolder(std_root); |
|||
|
|||
QString default_name; |
|||
if (std_path) |
|||
default_name = QString::fromStdString(std_path->filename()); |
|||
else if (fallbackName.isEmpty()) |
|||
default_name = root.split(QLatin1Char('/')).last(); |
|||
else |
|||
default_name = fallbackName; |
|||
|
|||
QString name = QtCommon::Frontend::GetTextInput( |
|||
tr("Mod Name"), tr("What should this mod be called?"), default_name); |
|||
|
|||
// if std_path is empty, frontend_common could not determine mod type and/or name.
|
|||
// so we have to prompt the user and set up the structure ourselves
|
|||
if (!std_path) { |
|||
// TODO: Carboxyl impl.
|
|||
const QStringList choices = { |
|||
tr("RomFS"), |
|||
tr("ExeFS/Patch"), |
|||
tr("Cheat"), |
|||
}; |
|||
|
|||
int choice = QtCommon::Frontend::Choice( |
|||
tr("Mod Type"), |
|||
tr("Could not detect mod type automatically. Please manually " |
|||
"specify the type of mod you downloaded.\n\nMost mods are RomFS mods, but patches " |
|||
"(.pchtxt) are typically ExeFS mods."), |
|||
choices); |
|||
|
|||
std::string to_make; |
|||
|
|||
switch (choice) { |
|||
case 0: |
|||
to_make = "romfs"; |
|||
break; |
|||
case 1: |
|||
to_make = "exefs"; |
|||
break; |
|||
case 2: |
|||
to_make = "cheats"; |
|||
break; |
|||
default: |
|||
return QString(); |
|||
} |
|||
|
|||
// now make a temp directory...
|
|||
const auto mod_dir = fs::temp_directory_path() / "eden" / "mod" / name.toStdString(); |
|||
const auto tmp = mod_dir / to_make; |
|||
fs::remove_all(mod_dir); |
|||
if (!fs::create_directories(tmp)) |
|||
return QString(); |
|||
|
|||
std_path = mod_dir; |
|||
|
|||
// ... and copy everything from the root to the temp dir
|
|||
for (const auto& entry : fs::directory_iterator(root.toStdString())) { |
|||
const auto target = tmp / entry.path().filename(); |
|||
|
|||
fs::copy(entry.path(), target, |
|||
fs::copy_options::recursive | fs::copy_options::overwrite_existing); |
|||
} |
|||
} |
|||
|
|||
return QString::fromStdString(std_path->string()); |
|||
} |
|||
|
|||
bool InstallMod(const QString& path, const QString& fallbackName, const u64 program_id, |
|||
const bool copy) { |
|||
const auto target = GetModFolder(path, fallbackName); |
|||
return FrontendCommon::InstallMod(target.toStdString(), program_id, copy); |
|||
} |
|||
|
|||
} // namespace QtCommon::Mod
|
|||
@ -0,0 +1,12 @@ |
|||
#pragma once |
|||
|
|||
#include <QString> |
|||
#include "common/common_types.h" |
|||
|
|||
namespace QtCommon::Mod { |
|||
|
|||
QString GetModFolder(const QString &root, const QString &fallbackName); |
|||
|
|||
bool InstallMod(const QString &path, const QString &fallbackName, const u64 program_id, const bool copy); |
|||
|
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue