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