mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-02 12:45:46 -06:00
Implement trophy migration (#4501)
* Implement trophy migration * Respect user choice from save migration * yet another nested subfolder iterator * refactoring and remove original hardcoded forced migration code
This commit is contained in:
parent
0e23d468ca
commit
4ac417b74f
@ -6,6 +6,7 @@
|
||||
#include <SDL3/SDL_messagebox.h>
|
||||
#include <common/assert.h>
|
||||
#include <common/path_util.h>
|
||||
#include <pugixml.hpp>
|
||||
#include "emulator_settings.h"
|
||||
#include "libraries/system/userservice.h"
|
||||
#include "user_manager.h"
|
||||
@ -89,6 +90,156 @@ const std::vector<User>& UserManager::GetAllUsers() const {
|
||||
return m_users.user;
|
||||
}
|
||||
|
||||
enum class TransferOption : s32 {
|
||||
Copy = 0,
|
||||
Move,
|
||||
MoveAndLinkBack,
|
||||
Nothing,
|
||||
SdlCancelled = -1,
|
||||
};
|
||||
TransferOption AskMigrationOption() {
|
||||
TransferOption user_choice = TransferOption::Nothing;
|
||||
#ifndef _WIN32
|
||||
SDL_MessageBoxButtonData btns[4]
|
||||
#else
|
||||
SDL_MessageBoxButtonData btns[3]
|
||||
#endif
|
||||
{
|
||||
{0, 0, "Copy"},
|
||||
{0, 1, "Move"},
|
||||
#ifndef _WIN32
|
||||
{0, 2, "Move and link back"},
|
||||
#endif
|
||||
{0, 3, "Do nothing"},
|
||||
};
|
||||
SDL_MessageBoxData msg_box{
|
||||
0,
|
||||
nullptr,
|
||||
"Save Migration",
|
||||
"The shadPS4 save and trophy locations have been updated, and save/trophy "
|
||||
"files have been detected in the old location.\n"
|
||||
"Do you wish to copy them over, move them over, "
|
||||
#ifndef _WIN32
|
||||
"move and link back to the original the original location, "
|
||||
#endif
|
||||
"or continue without doing anything?",
|
||||
|
||||
#ifndef _WIN32
|
||||
4,
|
||||
#else
|
||||
3,
|
||||
#endif
|
||||
btns,
|
||||
nullptr,
|
||||
};
|
||||
SDL_ShowMessageBox(&msg_box, reinterpret_cast<s32*>(&user_choice));
|
||||
return user_choice;
|
||||
}
|
||||
|
||||
static void MoveFolder(fs::path const& _from, fs::path const& _to) {
|
||||
try {
|
||||
fs::rename(_from, _to);
|
||||
} catch (...) {
|
||||
fs::copy(_from, _to, fs::copy_options::recursive);
|
||||
fs::remove_all(_from);
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckAndMigrateSaves(TransferOption option) {
|
||||
auto const new_save_dir = EmulatorSettings.GetHomeDir() / "1000" / "savedata";
|
||||
auto const old_save_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "savedata" / "1";
|
||||
if (fs::exists(old_save_dir) && !fs::is_empty(old_save_dir)) {
|
||||
try {
|
||||
switch (option) {
|
||||
case TransferOption::Copy:
|
||||
fs::copy(old_save_dir, new_save_dir, fs::copy_options::recursive);
|
||||
break;
|
||||
case TransferOption::Move:
|
||||
MoveFolder(old_save_dir, new_save_dir);
|
||||
break;
|
||||
case TransferOption::MoveAndLinkBack:
|
||||
MoveFolder(old_save_dir, new_save_dir);
|
||||
fs::create_directory_symlink(new_save_dir, old_save_dir);
|
||||
break;
|
||||
case TransferOption::SdlCancelled:
|
||||
case TransferOption::Nothing:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
UNREACHABLE_MSG("Error while migrating saves: {}", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckAndMigrateTrophies(TransferOption option) {
|
||||
auto const user_dir = EmulatorSettings.GetHomeDir() / "1000";
|
||||
auto const old_trophy_base_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "game_data";
|
||||
auto const new_trophy_global_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "trophy";
|
||||
try {
|
||||
for (auto const& entry : fs::directory_iterator(old_trophy_base_dir)) {
|
||||
if (!entry.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
if (!fs::exists(entry.path() / "TrophyFiles")) {
|
||||
continue;
|
||||
}
|
||||
for (auto const& subentry : fs::directory_iterator(entry.path() / "TrophyFiles")) {
|
||||
if (!subentry.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
auto const old_trophy_dir = subentry.path();
|
||||
if (fs::exists(old_trophy_dir / "Xml")) {
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_parse_result result =
|
||||
doc.load_file((old_trophy_dir / "Xml" / "TROP.XML").native().c_str());
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
std::string npcommid =
|
||||
doc.child("trophyconf").child("npcommid").text().as_string();
|
||||
if (npcommid.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (fs::exists(user_dir / "trophy" / (npcommid + ".xml"))) {
|
||||
continue;
|
||||
}
|
||||
if (!fs::exists(new_trophy_global_dir / npcommid)) {
|
||||
fs::create_directories(new_trophy_global_dir / npcommid);
|
||||
fs::copy(old_trophy_dir, new_trophy_global_dir / npcommid,
|
||||
fs::copy_options::recursive);
|
||||
}
|
||||
auto const old_trophy_file = old_trophy_dir / "Xml" / "TROP.XML";
|
||||
auto const new_trophy_file = user_dir / "trophy" / (npcommid + ".xml");
|
||||
switch (option) {
|
||||
case TransferOption::Copy:
|
||||
fs::copy_file(old_trophy_file, new_trophy_file);
|
||||
break;
|
||||
case TransferOption::Move:
|
||||
MoveFolder(old_trophy_file, new_trophy_file);
|
||||
break;
|
||||
case TransferOption::MoveAndLinkBack:
|
||||
MoveFolder(old_trophy_file, new_trophy_file);
|
||||
fs::create_symlink(new_trophy_file, old_trophy_file);
|
||||
break;
|
||||
case TransferOption::Nothing:
|
||||
case TransferOption::SdlCancelled:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
UNREACHABLE_MSG("Error while migrating trophies: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
Users UserManager::CreateDefaultUsers() {
|
||||
Users default_users;
|
||||
default_users.user = {
|
||||
@ -146,79 +297,10 @@ Users UserManager::CreateDefaultUsers() {
|
||||
std::filesystem::create_directory(user_dir / "savedata");
|
||||
std::filesystem::create_directory(user_dir / "trophy");
|
||||
std::filesystem::create_directory(user_dir / "inputs");
|
||||
auto const old_save_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "savedata" / "1";
|
||||
if (u.user_id == 1000 && std::filesystem::exists(old_save_dir) &&
|
||||
!std::filesystem::is_empty(old_save_dir)) {
|
||||
auto const new_save_dir = user_dir / "savedata";
|
||||
#ifndef _WIN32
|
||||
SDL_MessageBoxButtonData btns[4]
|
||||
#else
|
||||
SDL_MessageBoxButtonData btns[3]
|
||||
#endif
|
||||
{
|
||||
{0, 0, "Copy"},
|
||||
{0, 1, "Move"},
|
||||
#ifndef _WIN32
|
||||
{0, 2, "Move and link back"},
|
||||
#endif
|
||||
{0, 3, "Do nothing"},
|
||||
};
|
||||
SDL_MessageBoxData msg_box{
|
||||
0,
|
||||
nullptr,
|
||||
"Save Migration",
|
||||
"The shadPS4 save location has been updated, and save files have been detected "
|
||||
"in the old location.\nDo you wish to copy them over, move them over, "
|
||||
#ifndef _WIN32
|
||||
"move and link back to the original the original location, "
|
||||
#endif
|
||||
"or continue without doing anything?",
|
||||
|
||||
#ifndef _WIN32
|
||||
4,
|
||||
#else
|
||||
3,
|
||||
#endif
|
||||
btns,
|
||||
nullptr,
|
||||
};
|
||||
int result = 3;
|
||||
SDL_ShowMessageBox(&msg_box, &result);
|
||||
try {
|
||||
switch (result) {
|
||||
case 0:
|
||||
std::filesystem::copy(old_save_dir, new_save_dir,
|
||||
std::filesystem::copy_options::recursive);
|
||||
break;
|
||||
case 1:
|
||||
try {
|
||||
std::filesystem::rename(old_save_dir, new_save_dir);
|
||||
} catch (...) {
|
||||
std::filesystem::copy(old_save_dir, new_save_dir,
|
||||
std::filesystem::copy_options::recursive);
|
||||
std::filesystem::remove_all(old_save_dir);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
try {
|
||||
std::filesystem::rename(old_save_dir, new_save_dir);
|
||||
} catch (...) {
|
||||
std::filesystem::copy(old_save_dir, new_save_dir,
|
||||
std::filesystem::copy_options::recursive);
|
||||
std::filesystem::remove_all(old_save_dir);
|
||||
}
|
||||
std::filesystem::create_directory_symlink(new_save_dir, old_save_dir);
|
||||
break;
|
||||
case -1:
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
} catch (std::exception const& e) {
|
||||
UNREACHABLE_MSG("Error while migrating saves: {}", e.what());
|
||||
}
|
||||
if (u.user_id == 1000) {
|
||||
TransferOption user_choice = AskMigrationOption();
|
||||
CheckAndMigrateSaves(user_choice);
|
||||
CheckAndMigrateTrophies(user_choice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user