Compare commits
10 commits
44656b32d5
...
fa81d2428e
Author | SHA1 | Date | |
---|---|---|---|
fa81d2428e | |||
79c97733db | |||
060daebe17 | |||
8cf5351f0b | |||
e795e276da | |||
bf820f65ec | |||
fb6246cff7 | |||
7257b9865c | |||
45bc2b97d9 | |||
9de62db449 |
9 changed files with 158 additions and 124 deletions
|
@ -143,6 +143,7 @@ add_executable(MassBuilderSaveTool WIN32
|
||||||
ProfileManager/ProfileManager.cpp
|
ProfileManager/ProfileManager.cpp
|
||||||
Profile/Profile.h
|
Profile/Profile.h
|
||||||
Profile/Profile.cpp
|
Profile/Profile.cpp
|
||||||
|
Profile/PropertyNames.h
|
||||||
Profile/ResourceIDs.h
|
Profile/ResourceIDs.h
|
||||||
MassManager/MassManager.h
|
MassManager/MassManager.h
|
||||||
MassManager/MassManager.cpp
|
MassManager/MassManager.cpp
|
||||||
|
|
|
@ -19,16 +19,20 @@
|
||||||
#include <Corrade/Utility/Format.h>
|
#include <Corrade/Utility/Format.h>
|
||||||
#include <Corrade/Utility/Path.h>
|
#include <Corrade/Utility/Path.h>
|
||||||
|
|
||||||
|
#include "../Logger/Logger.h"
|
||||||
|
|
||||||
#include "MassManager.h"
|
#include "MassManager.h"
|
||||||
|
|
||||||
using namespace Containers::Literals;
|
using namespace Containers::Literals;
|
||||||
|
|
||||||
MassManager::MassManager(Containers::StringView save_path, Containers::StringView account, bool demo, Containers::StringView staging_dir):
|
MassManager::MassManager(Containers::StringView save_path, Containers::StringView account, bool demo,
|
||||||
|
Containers::StringView staging_dir):
|
||||||
_saveDirectory{save_path}, _account{account}, _demo{demo}, _stagingAreaDirectory{staging_dir}
|
_saveDirectory{save_path}, _account{account}, _demo{demo}, _stagingAreaDirectory{staging_dir}
|
||||||
{
|
{
|
||||||
Containers::String mass_filename = "";
|
Containers::String mass_filename = "";
|
||||||
for(UnsignedInt i = 0; i < _hangars.size(); i++) {
|
for(UnsignedInt i = 0; i < _hangars.size(); i++) {
|
||||||
mass_filename = Utility::Path::join(_saveDirectory, Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
|
mass_filename = Utility::Path::join(_saveDirectory,
|
||||||
|
Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
|
||||||
new(&_hangars[i]) Mass{mass_filename};
|
new(&_hangars[i]) Mass{mass_filename};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +49,8 @@ auto MassManager::hangar(Int hangar) -> Mass& {
|
||||||
|
|
||||||
void MassManager::refreshHangar(Int hangar) {
|
void MassManager::refreshHangar(Int hangar) {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
|
_lastError = "Hangar index out of range.";
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +62,8 @@ void MassManager::refreshHangar(Int hangar) {
|
||||||
|
|
||||||
auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bool {
|
auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bool {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
_lastError = "Hangar out of range in MassManager::importMass()"_s;
|
_lastError = "Hangar index out of range.";
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +71,7 @@ auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bo
|
||||||
|
|
||||||
if(it == _stagedMasses.end()) {
|
if(it == _stagedMasses.end()) {
|
||||||
_lastError = "Couldn't find "_s + staged_fn + " in the staged M.A.S.S.es."_s;
|
_lastError = "Couldn't find "_s + staged_fn + " in the staged M.A.S.S.es."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +95,7 @@ auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bo
|
||||||
|
|
||||||
if(!Utility::Path::move(source + ".tmp"_s, dest)) {
|
if(!Utility::Path::move(source + ".tmp"_s, dest)) {
|
||||||
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,12 +104,14 @@ auto MassManager::importMass(Containers::StringView staged_fn, Int hangar) -> bo
|
||||||
|
|
||||||
auto MassManager::exportMass(Int hangar) -> bool {
|
auto MassManager::exportMass(Int hangar) -> bool {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
_lastError = "Hangar out of range in MassManager::exportMass()"_s;
|
_lastError = "Hangar index out of range."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_hangars[hangar].state() != Mass::State::Valid) {
|
if(_hangars[hangar].state() != Mass::State::Valid) {
|
||||||
_lastError = Utility::format("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
_lastError = Utility::format("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +121,7 @@ auto MassManager::exportMass(Int hangar) -> bool {
|
||||||
|
|
||||||
if(!Utility::Path::copy(source, dest)) {
|
if(!Utility::Path::copy(source, dest)) {
|
||||||
_lastError = Utility::format("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
_lastError = Utility::format("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,12 +130,14 @@ auto MassManager::exportMass(Int hangar) -> bool {
|
||||||
|
|
||||||
auto MassManager::moveMass(Int source, Int destination) -> bool {
|
auto MassManager::moveMass(Int source, Int destination) -> bool {
|
||||||
if(source < 0 || source >= 32) {
|
if(source < 0 || source >= 32) {
|
||||||
_lastError = "Source hangar out of range."_s;
|
_lastError = "Source hangar index out of range."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(destination < 0 || destination >= 32) {
|
if(destination < 0 || destination >= 32) {
|
||||||
_lastError = "Destination hangar out of range."_s;
|
_lastError = "Destination hangar index out of range."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,12 +167,14 @@ auto MassManager::moveMass(Int source, Int destination) -> bool {
|
||||||
|
|
||||||
auto MassManager::deleteMass(Int hangar) -> bool {
|
auto MassManager::deleteMass(Int hangar) -> bool {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
_lastError = "Hangar out of range."_s;
|
_lastError = "Hangar index out of range."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _hangars[hangar].filename()))) {
|
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _hangars[hangar].filename()))) {
|
||||||
_lastError = Utility::format("Deletion failed: {}", std::strerror(errno));
|
_lastError = Utility::format("Deletion failed: {}", std::strerror(errno));
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,10 +189,11 @@ void MassManager::refreshStagedMasses() {
|
||||||
_stagedMasses.clear();
|
_stagedMasses.clear();
|
||||||
|
|
||||||
using Utility::Path::ListFlag;
|
using Utility::Path::ListFlag;
|
||||||
auto file_list = Utility::Path::list(_stagingAreaDirectory, ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
auto file_list = Utility::Path::list(_stagingAreaDirectory,
|
||||||
|
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
||||||
|
|
||||||
if(!file_list) {
|
if(!file_list) {
|
||||||
Utility::Error{} << _stagingAreaDirectory << "couldn't be opened";
|
LOG_ERROR_FORMAT("{} couldn't be opened.", _stagingAreaDirectory);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,11 +240,13 @@ void MassManager::refreshStagedMass(Containers::StringView filename) {
|
||||||
auto MassManager::deleteStagedMass(Containers::StringView filename) -> bool {
|
auto MassManager::deleteStagedMass(Containers::StringView filename) -> bool {
|
||||||
if(_stagedMasses.find(filename) == _stagedMasses.cend()) {
|
if(_stagedMasses.find(filename) == _stagedMasses.cend()) {
|
||||||
_lastError = "The file "_s + filename + " couldn't be found in the list of staged M.A.S.S.es."_s;
|
_lastError = "The file "_s + filename + " couldn't be found in the list of staged M.A.S.S.es."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Utility::Path::remove(Utility::Path::join(_stagingAreaDirectory, filename))) {
|
if(!Utility::Path::remove(Utility::Path::join(_stagingAreaDirectory, filename))) {
|
||||||
_lastError = filename + " couldn't be deleted: " + std::strerror(errno);
|
_lastError = filename + " couldn't be deleted: " + std::strerror(errno);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,11 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <Corrade/Containers/Array.h>
|
|
||||||
#include <Corrade/Containers/Pair.h>
|
#include <Corrade/Containers/Pair.h>
|
||||||
#include <Corrade/Containers/StaticArray.h>
|
|
||||||
#include <Corrade/Utility/Path.h>
|
#include <Corrade/Utility/Path.h>
|
||||||
#include <Corrade/Utility/Format.h>
|
|
||||||
|
|
||||||
|
#include "PropertyNames.h"
|
||||||
|
#include "../Logger/Logger.h"
|
||||||
#include "../UESaveFile/Types/ArrayProperty.h"
|
#include "../UESaveFile/Types/ArrayProperty.h"
|
||||||
#include "../UESaveFile/Types/ResourceItemValue.h"
|
#include "../UESaveFile/Types/ResourceItemValue.h"
|
||||||
#include "../UESaveFile/Types/IntProperty.h"
|
#include "../UESaveFile/Types/IntProperty.h"
|
||||||
|
@ -35,8 +34,11 @@ using namespace Containers::Literals;
|
||||||
Profile::Profile(Containers::StringView path):
|
Profile::Profile(Containers::StringView path):
|
||||||
_profile(path)
|
_profile(path)
|
||||||
{
|
{
|
||||||
|
LOG_INFO_FORMAT("Reading profile at {}.", path);
|
||||||
|
|
||||||
if(!_profile.valid()) {
|
if(!_profile.valid()) {
|
||||||
_lastError = _profile.lastError();
|
_lastError = _profile.lastError();
|
||||||
|
_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +51,7 @@ Profile::Profile(Containers::StringView path):
|
||||||
_type = ProfileType::FullGame;
|
_type = ProfileType::FullGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto account_prop = _profile.at<StringProperty>("Account"_s);
|
auto account_prop = _profile.at<StringProperty>(PROFILE_ACCOUNT);
|
||||||
if(!account_prop) {
|
if(!account_prop) {
|
||||||
_lastError = "Couldn't find an account ID in "_s + _filename;
|
_lastError = "Couldn't find an account ID in "_s + _filename;
|
||||||
_valid = false;
|
_valid = false;
|
||||||
|
@ -57,13 +59,6 @@ Profile::Profile(Containers::StringView path):
|
||||||
}
|
}
|
||||||
_account = account_prop->value;
|
_account = account_prop->value;
|
||||||
|
|
||||||
if(_account.hasPrefix("PMCSlot"_s)) {
|
|
||||||
_version = ProfileVersion::Normal;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_version = ProfileVersion::Legacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshValues();
|
refreshValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,72 +82,73 @@ auto Profile::isDemo() const -> bool {
|
||||||
return _type == ProfileType::Demo;
|
return _type == ProfileType::Demo;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::version() const -> ProfileVersion {
|
|
||||||
return _version;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Profile::isLegacy() const -> bool {
|
|
||||||
return _version == ProfileVersion::Legacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Profile::account() const -> Containers::StringView {
|
auto Profile::account() const -> Containers::StringView {
|
||||||
return _account;
|
return _account;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profile::refreshValues() {
|
void Profile::refreshValues() {
|
||||||
if(!_profile.reloadData()) {
|
if(!_profile.reloadData()) {
|
||||||
_lastError = _profile.lastError();
|
LOG_ERROR(_profile.lastError());
|
||||||
_valid = false;
|
_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_profile.saveType() != "/Game/Core/Save/bpSaveGameProfile.bpSaveGameProfile_C"_s) {
|
if(_profile.saveType() != "/Game/Core/Save/bpSaveGameProfile.bpSaveGameProfile_C"_s) {
|
||||||
Utility::Error{} << _filename << "is not a valid profile save.";
|
LOG_ERROR_FORMAT("{} is not a valid profile save.", _filename);
|
||||||
|
_valid = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name_prop = _profile.at<StringProperty>("CompanyName"_s);
|
LOG_INFO("Getting the company name.");
|
||||||
|
auto name_prop = _profile.at<StringProperty>(PROFILE_NAME);
|
||||||
if(!name_prop) {
|
if(!name_prop) {
|
||||||
_lastError = "No company name in "_s + _filename;
|
_lastError = "No company name in "_s + _filename;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
_valid = false;
|
_valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_name = name_prop->value;
|
_name = name_prop->value;
|
||||||
|
|
||||||
auto prop = _profile.at<IntProperty>("ActiveFrameSlot"_s);
|
LOG_INFO("Getting the active frame slot.");
|
||||||
|
auto prop = _profile.at<IntProperty>(PROFILE_ACTIVE_FRAME_SLOT);
|
||||||
_activeFrameSlot = prop ? prop->value : 0;
|
_activeFrameSlot = prop ? prop->value : 0;
|
||||||
|
|
||||||
prop = _profile.at<IntProperty>("Credit"_s);
|
LOG_INFO("Getting the credits.");
|
||||||
|
prop = _profile.at<IntProperty>(PROFILE_CREDITS);
|
||||||
_credits = prop ? prop->value : 0;
|
_credits = prop ? prop->value : 0;
|
||||||
|
|
||||||
prop = _profile.at<IntProperty>("StoryProgress"_s);
|
LOG_INFO("Getting the story progress.");
|
||||||
|
prop = _profile.at<IntProperty>(PROFILE_STORY_PROGRESS);
|
||||||
_storyProgress = prop ? prop->value : 0;
|
_storyProgress = prop ? prop->value : 0;
|
||||||
|
|
||||||
prop = _profile.at<IntProperty>("LastMissionID"_s);
|
LOG_INFO("Getting the last mission ID.");
|
||||||
|
prop = _profile.at<IntProperty>(PROFILE_LAST_MISSION_ID);
|
||||||
_lastMissionId = prop ? prop->value : 0;
|
_lastMissionId = prop ? prop->value : 0;
|
||||||
|
|
||||||
_verseSteel = getResource("ResourceMaterial"_s, VerseSteel);
|
LOG_INFO("Getting the materials.");
|
||||||
_undinium = getResource("ResourceMaterial"_s, Undinium);
|
_verseSteel = getResource(PROFILE_MATERIAL, VerseSteel);
|
||||||
_necriumAlloy = getResource("ResourceMaterial"_s, NecriumAlloy);
|
_undinium = getResource(PROFILE_MATERIAL, Undinium);
|
||||||
_lunarite = getResource("ResourceMaterial"_s, Lunarite);
|
_necriumAlloy = getResource(PROFILE_MATERIAL, NecriumAlloy);
|
||||||
_asterite = getResource("ResourceMaterial"_s, Asterite);
|
_lunarite = getResource(PROFILE_MATERIAL, Lunarite);
|
||||||
|
_asterite = getResource(PROFILE_MATERIAL, Asterite);
|
||||||
|
|
||||||
_ednil = getResource("ResourceMaterial"_s, Ednil);
|
_ednil = getResource(PROFILE_MATERIAL, Ednil);
|
||||||
_nuflalt = getResource("ResourceMaterial"_s, Nuflalt);
|
_nuflalt = getResource(PROFILE_MATERIAL, Nuflalt);
|
||||||
_aurelene = getResource("ResourceMaterial"_s, Aurelene);
|
_aurelene = getResource(PROFILE_MATERIAL, Aurelene);
|
||||||
_soldus = getResource("ResourceMaterial"_s, Soldus);
|
_soldus = getResource(PROFILE_MATERIAL, Soldus);
|
||||||
_synthesisedN = getResource("ResourceMaterial"_s, SynthesisedN);
|
_synthesisedN = getResource(PROFILE_MATERIAL, SynthesisedN);
|
||||||
|
|
||||||
_alcarbonite = getResource("ResourceMaterial"_s, Alcarbonite);
|
_alcarbonite = getResource(PROFILE_MATERIAL, Alcarbonite);
|
||||||
_keriphene = getResource("ResourceMaterial"_s, Keriphene);
|
_keriphene = getResource(PROFILE_MATERIAL, Keriphene);
|
||||||
_nitinolCM = getResource("ResourceMaterial"_s, NitinolCM);
|
_nitinolCM = getResource(PROFILE_MATERIAL, NitinolCM);
|
||||||
_quarkium = getResource("ResourceMaterial"_s, Quarkium);
|
_quarkium = getResource(PROFILE_MATERIAL, Quarkium);
|
||||||
_alterene = getResource("ResourceMaterial"_s, Alterene);
|
_alterene = getResource(PROFILE_MATERIAL, Alterene);
|
||||||
|
|
||||||
_mixedComposition = getResource("ResourceQuarkData"_s, MixedComposition);
|
_mixedComposition = getResource(PROFILE_QUARK_DATA, MixedComposition);
|
||||||
_voidResidue = getResource("ResourceQuarkData"_s, VoidResidue);
|
_voidResidue = getResource(PROFILE_QUARK_DATA, VoidResidue);
|
||||||
_muscularConstruction = getResource("ResourceQuarkData"_s, MuscularConstruction);
|
_muscularConstruction = getResource(PROFILE_QUARK_DATA, MuscularConstruction);
|
||||||
_mineralExoskeletology = getResource("ResourceQuarkData"_s, MineralExoskeletology);
|
_mineralExoskeletology = getResource(PROFILE_QUARK_DATA, MineralExoskeletology);
|
||||||
_carbonisedSkin = getResource("ResourceQuarkData"_s, CarbonisedSkin);
|
_carbonisedSkin = getResource(PROFILE_QUARK_DATA, CarbonisedSkin);
|
||||||
|
|
||||||
_valid = true;
|
_valid = true;
|
||||||
}
|
}
|
||||||
|
@ -162,9 +158,10 @@ auto Profile::companyName() const -> Containers::StringView {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::renameCompany(Containers::StringView new_name) -> bool {
|
auto Profile::renameCompany(Containers::StringView new_name) -> bool {
|
||||||
auto name_prop = _profile.at<StringProperty>("CompanyName"_s);
|
auto name_prop = _profile.at<StringProperty>(PROFILE_NAME);
|
||||||
if(!name_prop) {
|
if(!name_prop) {
|
||||||
_lastError = "No company name in "_s + _filename;
|
_lastError = "No company name in "_s + _filename;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
_valid = false;
|
_valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -188,11 +185,12 @@ auto Profile::credits() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setCredits(Int amount) -> bool {
|
auto Profile::setCredits(Int amount) -> bool {
|
||||||
auto credits_prop = _profile.at<IntProperty>("Credit"_s);
|
auto credits_prop = _profile.at<IntProperty>(PROFILE_CREDITS);
|
||||||
|
|
||||||
if(!credits_prop) {
|
if(!credits_prop) {
|
||||||
credits_prop = new IntProperty;
|
credits_prop = new IntProperty;
|
||||||
credits_prop->name.emplace("Credit"_s);
|
credits_prop->name.emplace("Credit"_s);
|
||||||
|
credits_prop->valueLength = sizeof(Int);
|
||||||
_profile.appendProperty(IntProperty::ptr{credits_prop});
|
_profile.appendProperty(IntProperty::ptr{credits_prop});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +214,7 @@ auto Profile::setStoryProgress(Int progress) -> bool {
|
||||||
if(!story_progress_prop) {
|
if(!story_progress_prop) {
|
||||||
story_progress_prop = new IntProperty;
|
story_progress_prop = new IntProperty;
|
||||||
story_progress_prop->name.emplace("StoryProgress"_s);
|
story_progress_prop->name.emplace("StoryProgress"_s);
|
||||||
|
story_progress_prop->valueLength = sizeof(Int);
|
||||||
_profile.appendProperty(IntProperty::ptr{story_progress_prop});
|
_profile.appendProperty(IntProperty::ptr{story_progress_prop});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +237,7 @@ auto Profile::verseSteel() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setVerseSteel(Int amount) -> bool {
|
auto Profile::setVerseSteel(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, VerseSteel, amount);
|
return setResource(PROFILE_MATERIAL, VerseSteel, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::undinium() const -> Int {
|
auto Profile::undinium() const -> Int {
|
||||||
|
@ -246,7 +245,7 @@ auto Profile::undinium() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setUndinium(Int amount) -> bool {
|
auto Profile::setUndinium(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Undinium, amount);
|
return setResource(PROFILE_MATERIAL, Undinium, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::necriumAlloy() const -> Int {
|
auto Profile::necriumAlloy() const -> Int {
|
||||||
|
@ -254,7 +253,7 @@ auto Profile::necriumAlloy() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setNecriumAlloy(Int amount) -> bool {
|
auto Profile::setNecriumAlloy(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, NecriumAlloy, amount);
|
return setResource(PROFILE_MATERIAL, NecriumAlloy, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::lunarite() const -> Int {
|
auto Profile::lunarite() const -> Int {
|
||||||
|
@ -262,7 +261,7 @@ auto Profile::lunarite() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setLunarite(Int amount) -> bool {
|
auto Profile::setLunarite(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Lunarite, amount);
|
return setResource(PROFILE_MATERIAL, Lunarite, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::asterite() const -> Int {
|
auto Profile::asterite() const -> Int {
|
||||||
|
@ -270,7 +269,7 @@ auto Profile::asterite() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setAsterite(Int amount) -> bool {
|
auto Profile::setAsterite(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Asterite, amount);
|
return setResource(PROFILE_MATERIAL, Asterite, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::ednil() const -> Int {
|
auto Profile::ednil() const -> Int {
|
||||||
|
@ -278,7 +277,7 @@ auto Profile::ednil() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setEdnil(Int amount) -> bool {
|
auto Profile::setEdnil(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Ednil, amount);
|
return setResource(PROFILE_MATERIAL, Ednil, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::nuflalt() const -> Int {
|
auto Profile::nuflalt() const -> Int {
|
||||||
|
@ -286,7 +285,7 @@ auto Profile::nuflalt() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setNuflalt(Int amount) -> bool {
|
auto Profile::setNuflalt(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Nuflalt, amount);
|
return setResource(PROFILE_MATERIAL, Nuflalt, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::aurelene() const -> Int {
|
auto Profile::aurelene() const -> Int {
|
||||||
|
@ -294,7 +293,7 @@ auto Profile::aurelene() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setAurelene(Int amount) -> bool {
|
auto Profile::setAurelene(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Aurelene, amount);
|
return setResource(PROFILE_MATERIAL, Aurelene, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::soldus() const -> Int {
|
auto Profile::soldus() const -> Int {
|
||||||
|
@ -302,7 +301,7 @@ auto Profile::soldus() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setSoldus(Int amount) -> bool {
|
auto Profile::setSoldus(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Soldus, amount);
|
return setResource(PROFILE_MATERIAL, Soldus, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::synthesisedN() const -> Int {
|
auto Profile::synthesisedN() const -> Int {
|
||||||
|
@ -310,7 +309,7 @@ auto Profile::synthesisedN() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setSynthesisedN(Int amount) -> bool {
|
auto Profile::setSynthesisedN(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, SynthesisedN, amount);
|
return setResource(PROFILE_MATERIAL, SynthesisedN, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::alcarbonite() const -> Int {
|
auto Profile::alcarbonite() const -> Int {
|
||||||
|
@ -318,7 +317,7 @@ auto Profile::alcarbonite() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setAlcarbonite(Int amount) -> bool {
|
auto Profile::setAlcarbonite(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Alcarbonite, amount);
|
return setResource(PROFILE_MATERIAL, Alcarbonite, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::keriphene() const -> Int {
|
auto Profile::keriphene() const -> Int {
|
||||||
|
@ -326,7 +325,7 @@ auto Profile::keriphene() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setKeriphene(Int amount) -> bool {
|
auto Profile::setKeriphene(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Keriphene, amount);
|
return setResource(PROFILE_MATERIAL, Keriphene, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::nitinolCM() const -> Int {
|
auto Profile::nitinolCM() const -> Int {
|
||||||
|
@ -334,7 +333,7 @@ auto Profile::nitinolCM() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setNitinolCM(Int amount) -> bool {
|
auto Profile::setNitinolCM(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, NitinolCM, amount);
|
return setResource(PROFILE_MATERIAL, NitinolCM, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::quarkium() const -> Int {
|
auto Profile::quarkium() const -> Int {
|
||||||
|
@ -342,7 +341,7 @@ auto Profile::quarkium() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setQuarkium(Int amount) -> bool {
|
auto Profile::setQuarkium(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Quarkium, amount);
|
return setResource(PROFILE_MATERIAL, Quarkium, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::alterene() const -> Int {
|
auto Profile::alterene() const -> Int {
|
||||||
|
@ -350,7 +349,7 @@ auto Profile::alterene() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setAlterene(Int amount) -> bool {
|
auto Profile::setAlterene(Int amount) -> bool {
|
||||||
return setResource("ResourceMaterial"_s, Alterene, amount);
|
return setResource(PROFILE_MATERIAL, Alterene, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::mixedComposition() const -> Int {
|
auto Profile::mixedComposition() const -> Int {
|
||||||
|
@ -358,7 +357,7 @@ auto Profile::mixedComposition() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setMixedComposition(Int amount) -> bool {
|
auto Profile::setMixedComposition(Int amount) -> bool {
|
||||||
return setResource("ResourceQuarkData"_s, MixedComposition, amount);
|
return setResource(PROFILE_QUARK_DATA, MixedComposition, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::voidResidue() const -> Int {
|
auto Profile::voidResidue() const -> Int {
|
||||||
|
@ -366,7 +365,7 @@ auto Profile::voidResidue() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setVoidResidue(Int amount) -> bool {
|
auto Profile::setVoidResidue(Int amount) -> bool {
|
||||||
return setResource("ResourceQuarkData"_s, VoidResidue, amount);
|
return setResource(PROFILE_QUARK_DATA, VoidResidue, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::muscularConstruction() const -> Int {
|
auto Profile::muscularConstruction() const -> Int {
|
||||||
|
@ -374,7 +373,7 @@ auto Profile::muscularConstruction() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setMuscularConstruction(Int amount) -> bool {
|
auto Profile::setMuscularConstruction(Int amount) -> bool {
|
||||||
return setResource("ResourceQuarkData"_s, MuscularConstruction, amount);
|
return setResource(PROFILE_QUARK_DATA, MuscularConstruction, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::mineralExoskeletology() const -> Int {
|
auto Profile::mineralExoskeletology() const -> Int {
|
||||||
|
@ -382,7 +381,7 @@ auto Profile::mineralExoskeletology() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setMineralExoskeletology(Int amount) -> bool {
|
auto Profile::setMineralExoskeletology(Int amount) -> bool {
|
||||||
return setResource("ResourceQuarkData"_s, MineralExoskeletology, amount);
|
return setResource(PROFILE_QUARK_DATA, MineralExoskeletology, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::carbonisedSkin() const -> Int {
|
auto Profile::carbonisedSkin() const -> Int {
|
||||||
|
@ -390,7 +389,7 @@ auto Profile::carbonisedSkin() const -> Int {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::setCarbonisedSkin(Int amount) -> bool {
|
auto Profile::setCarbonisedSkin(Int amount) -> bool {
|
||||||
return setResource("ResourceQuarkData"_s, CarbonisedSkin, amount);
|
return setResource(PROFILE_QUARK_DATA, CarbonisedSkin, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Profile::getResource(Containers::StringView container, MaterialID id) -> Int {
|
auto Profile::getResource(Containers::StringView container, MaterialID id) -> Int {
|
||||||
|
@ -413,9 +412,9 @@ auto Profile::setResource(Containers::StringView container, MaterialID id, Int a
|
||||||
auto mats_prop = _profile.at<ArrayProperty>(container);
|
auto mats_prop = _profile.at<ArrayProperty>(container);
|
||||||
|
|
||||||
if(!mats_prop) {
|
if(!mats_prop) {
|
||||||
_lastError = "Couldn't find "_s + container + " in "_s + _filename;
|
mats_prop = new ArrayProperty;
|
||||||
_valid = false;
|
mats_prop->name.emplace(container);
|
||||||
return false;
|
_profile.appendProperty(ArrayProperty::ptr{mats_prop});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto predicate = [&id](UnrealPropertyBase::ptr& prop){
|
auto predicate = [&id](UnrealPropertyBase::ptr& prop){
|
||||||
|
|
|
@ -33,11 +33,6 @@ enum class ProfileType : UnsignedByte {
|
||||||
FullGame
|
FullGame
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ProfileVersion : UnsignedByte {
|
|
||||||
Legacy, // pre-0.8
|
|
||||||
Normal // 0.8 and later
|
|
||||||
};
|
|
||||||
|
|
||||||
class Profile {
|
class Profile {
|
||||||
public:
|
public:
|
||||||
explicit Profile(Containers::StringView path);
|
explicit Profile(Containers::StringView path);
|
||||||
|
@ -51,9 +46,6 @@ class Profile {
|
||||||
auto type() const -> ProfileType;
|
auto type() const -> ProfileType;
|
||||||
auto isDemo() const -> bool;
|
auto isDemo() const -> bool;
|
||||||
|
|
||||||
auto version() const -> ProfileVersion;
|
|
||||||
auto isLegacy() const -> bool;
|
|
||||||
|
|
||||||
auto account() const -> Containers::StringView;
|
auto account() const -> Containers::StringView;
|
||||||
|
|
||||||
void refreshValues();
|
void refreshValues();
|
||||||
|
@ -138,7 +130,6 @@ class Profile {
|
||||||
Containers::String _filename;
|
Containers::String _filename;
|
||||||
|
|
||||||
ProfileType _type;
|
ProfileType _type;
|
||||||
ProfileVersion _version;
|
|
||||||
|
|
||||||
UESaveFile _profile;
|
UESaveFile _profile;
|
||||||
|
|
||||||
|
|
10
src/Profile/PropertyNames.h
Normal file
10
src/Profile/PropertyNames.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define PROFILE_NAME "CompanyName"
|
||||||
|
#define PROFILE_ACTIVE_FRAME_SLOT "ActiveFrameSlot"
|
||||||
|
#define PROFILE_CREDITS "Credit"
|
||||||
|
#define PROFILE_STORY_PROGRESS "StoryProgress"
|
||||||
|
#define PROFILE_LAST_MISSION_ID "LastMissionID"
|
||||||
|
#define PROFILE_MATERIAL "ResourceMaterial"
|
||||||
|
#define PROFILE_QUARK_DATA "ResourceQuarkData"
|
||||||
|
#define PROFILE_ACCOUNT "Account"
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iomanip>
|
|
||||||
#include <regex>
|
|
||||||
|
|
||||||
#include <Corrade/Containers/ScopeGuard.h>
|
#include <Corrade/Containers/ScopeGuard.h>
|
||||||
#include <Corrade/Containers/StaticArray.h>
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
|
@ -29,6 +27,8 @@
|
||||||
|
|
||||||
#include <zip.h>
|
#include <zip.h>
|
||||||
|
|
||||||
|
#include "../Logger/Logger.h"
|
||||||
|
|
||||||
#include "ProfileManager.h"
|
#include "ProfileManager.h"
|
||||||
|
|
||||||
using namespace Containers::Literals;
|
using namespace Containers::Literals;
|
||||||
|
@ -53,6 +53,8 @@ auto ProfileManager::profiles() -> Containers::ArrayView<Profile> {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ProfileManager::refreshProfiles() -> bool {
|
auto ProfileManager::refreshProfiles() -> bool {
|
||||||
|
LOG_INFO("Refreshing profiles.");
|
||||||
|
|
||||||
_profiles = Containers::Array<Profile>{};
|
_profiles = Containers::Array<Profile>{};
|
||||||
|
|
||||||
using Utility::Path::ListFlag;
|
using Utility::Path::ListFlag;
|
||||||
|
@ -61,14 +63,12 @@ auto ProfileManager::refreshProfiles() -> bool {
|
||||||
|
|
||||||
if(!files) {
|
if(!files) {
|
||||||
_lastError = _saveDirectory + " can't be opened.";
|
_lastError = _saveDirectory + " can't be opened.";
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto predicate = [](Containers::StringView file)->bool{
|
auto predicate = [](Containers::StringView file)->bool{
|
||||||
std::regex legacy_regex("(Demo)?Profile[0-9]{17}\\.sav", std::regex::nosubs);
|
return !((file.hasPrefix("DemoProfile") || file.hasPrefix("Profile")) && file.hasSuffix(".sav"));
|
||||||
std::regex new_regex("(Demo)?ProfilePMCSlot[0-9]{3}\\.sav", std::regex::nosubs);
|
|
||||||
std::cmatch m;
|
|
||||||
return !std::regex_match(file.data(), m, legacy_regex) && !std::regex_match(file.data(), m, new_regex);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
|
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
|
||||||
|
@ -77,7 +77,7 @@ auto ProfileManager::refreshProfiles() -> bool {
|
||||||
Profile profile{Utility::Path::join(_saveDirectory, file)};
|
Profile profile{Utility::Path::join(_saveDirectory, file)};
|
||||||
|
|
||||||
if(!profile.valid()) {
|
if(!profile.valid()) {
|
||||||
Utility::Warning{} << "Profile"_s << file << "is invalid:"_s << profile.lastError();
|
LOG_WARNING_FORMAT("Profile {} is invalid: {}", file, profile.lastError());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ auto ProfileManager::refreshProfiles() -> bool {
|
||||||
|
|
||||||
if(_profiles.isEmpty()) {
|
if(_profiles.isEmpty()) {
|
||||||
_lastError = "No valid profiles were found."_s;
|
_lastError = "No valid profiles were found."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +102,7 @@ auto ProfileManager::deleteProfile(std::size_t index, bool delete_builds) -> boo
|
||||||
_lastError = Utility::format("Couldn't delete {} (filename: {}).",
|
_lastError = Utility::format("Couldn't delete {} (filename: {}).",
|
||||||
_profiles[index].companyName(),
|
_profiles[index].companyName(),
|
||||||
_profiles[index].filename());
|
_profiles[index].filename());
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
refreshProfiles();
|
refreshProfiles();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +131,7 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
std::tm* time = std::localtime(×tamp);
|
std::tm* time = std::localtime(×tamp);
|
||||||
auto& profile = _profiles[index];
|
auto& profile = _profiles[index];
|
||||||
|
|
||||||
auto filename = Utility::format("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.mbprofbackup",
|
auto filename = Utility::format("{}_{}{:.2d}{:.2d}_{:.2d}{:.2d}{:.2d}.backup.mbst",
|
||||||
Utility::String::replaceAll(profile.companyName().data(), " ", "_").c_str(),
|
Utility::String::replaceAll(profile.companyName().data(), " ", "_").c_str(),
|
||||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||||
time->tm_hour, time->tm_min, time->tm_sec);
|
time->tm_hour, time->tm_min, time->tm_sec);
|
||||||
|
@ -140,26 +142,28 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
if(zip == nullptr) {
|
if(zip == nullptr) {
|
||||||
zip_error_init_with_code(&error, error_code);
|
zip_error_init_with_code(&error, error_code);
|
||||||
_lastError = zip_error_strerror(&error);
|
_lastError = zip_error_strerror(&error);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zip_source_t* profile_source = zip_source_file(zip, Utility::Path::toNativeSeparators(Utility::Path::join(_saveDirectory, profile.filename())).data(), 0, 0);
|
zip_source_t* profile_source = zip_source_file(zip, Utility::Path::toNativeSeparators(Utility::Path::join(_saveDirectory, profile.filename())).data(), 0, 0);
|
||||||
if(profile_source == nullptr) {
|
if(profile_source == nullptr) {
|
||||||
_lastError = zip_strerror(zip);
|
_lastError = zip_strerror(zip);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
zip_source_free(profile_source);
|
zip_source_free(profile_source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(zip_file_add(zip, profile.filename().data(), profile_source, ZIP_FL_ENC_UTF_8) == -1) {
|
if(zip_file_add(zip, profile.filename().data(), profile_source, ZIP_FL_ENC_UTF_8) == -1) {
|
||||||
_lastError = zip_strerror(zip);
|
_lastError = zip_strerror(zip);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
zip_source_free(profile_source);
|
zip_source_free(profile_source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto comment = Utility::format("{}|{}{}|{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}",
|
auto comment = Utility::format("{}|{}|{}-{:.2d}-{:.2d}-{:.2d}-{:.2d}-{:.2d}",
|
||||||
profile.companyName(),
|
profile.companyName(),
|
||||||
profile.isDemo() ? "demo"_s : "full"_s,
|
profile.isDemo() ? "demo"_s : "full"_s,
|
||||||
profile.isLegacy() ? ""_s : "_new"_s,
|
|
||||||
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
|
||||||
time->tm_hour, time->tm_min, time->tm_sec);
|
time->tm_hour, time->tm_min, time->tm_sec);
|
||||||
zip_set_archive_comment(zip, comment.data(), comment.size());
|
zip_set_archive_comment(zip, comment.data(), comment.size());
|
||||||
|
@ -189,6 +193,7 @@ auto ProfileManager::backupProfile(std::size_t index, bool backup_builds) -> boo
|
||||||
|
|
||||||
if(zip_close(zip) == -1) {
|
if(zip_close(zip) == -1) {
|
||||||
_lastError = zip_strerror(zip);
|
_lastError = zip_strerror(zip);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,11 +215,12 @@ void ProfileManager::refreshBackups() {
|
||||||
|
|
||||||
if(!files) {
|
if(!files) {
|
||||||
_lastError = _backupsDirectory + " can't be opened.";
|
_lastError = _backupsDirectory + " can't be opened.";
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto predicate = [](Containers::StringView file)->bool{
|
auto predicate = [](Containers::StringView file)->bool{
|
||||||
return !file.hasSuffix(".mbprofbackup"_s);
|
return !(file.hasSuffix(".mbprofbackup"_s) || file.hasSuffix(".backup.mbst"));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
|
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
|
||||||
|
@ -252,21 +258,11 @@ void ProfileManager::refreshBackups() {
|
||||||
|
|
||||||
backup.company = info[0];
|
backup.company = info[0];
|
||||||
|
|
||||||
if(info[1] == "full") {
|
if(info[1].hasPrefix("full")) {
|
||||||
backup.type = ProfileType::FullGame;
|
backup.type = ProfileType::FullGame;
|
||||||
backup.version = ProfileVersion::Legacy;
|
|
||||||
}
|
}
|
||||||
else if(info[1] == "demo") {
|
else if(info[1].hasPrefix("demo")) {
|
||||||
backup.type = ProfileType::Demo;
|
backup.type = ProfileType::Demo;
|
||||||
backup.version = ProfileVersion::Legacy;
|
|
||||||
}
|
|
||||||
else if(info[1] == "full_new") {
|
|
||||||
backup.type = ProfileType::FullGame;
|
|
||||||
backup.version = ProfileVersion::Normal;
|
|
||||||
}
|
|
||||||
else if(info[1] == "demo_new") {
|
|
||||||
backup.type = ProfileType::Demo;
|
|
||||||
backup.version = ProfileVersion::Normal;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -297,6 +293,7 @@ void ProfileManager::refreshBackups() {
|
||||||
auto ProfileManager::deleteBackup(std::size_t index) -> bool {
|
auto ProfileManager::deleteBackup(std::size_t index) -> bool {
|
||||||
if(!Utility::Path::remove(Utility::Path::join(_backupsDirectory, _backups[index].filename))) {
|
if(!Utility::Path::remove(Utility::Path::join(_backupsDirectory, _backups[index].filename))) {
|
||||||
_lastError = "Couldn't delete " + _backups[index].filename;
|
_lastError = "Couldn't delete " + _backups[index].filename;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,6 +320,7 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
||||||
zip_error_t error;
|
zip_error_t error;
|
||||||
zip_error_init_with_code(&error, error_code);
|
zip_error_init_with_code(&error, error_code);
|
||||||
_lastError = zip_error_strerror(&error);
|
_lastError = zip_error_strerror(&error);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +330,7 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
||||||
FILE* out = std::fopen(Utility::Path::join(_saveDirectory, file).data(), "wb");
|
FILE* out = std::fopen(Utility::Path::join(_saveDirectory, file).data(), "wb");
|
||||||
if(out == nullptr) {
|
if(out == nullptr) {
|
||||||
_lastError = Utility::format(error_format.data(), file, std::strerror(errno));
|
_lastError = Utility::format(error_format.data(), file, std::strerror(errno));
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,6 +339,7 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
||||||
zip_file_t* zf = zip_fopen(zip, file.data(), ZIP_FL_ENC_GUESS);
|
zip_file_t* zf = zip_fopen(zip, file.data(), ZIP_FL_ENC_GUESS);
|
||||||
if(zf == nullptr) {
|
if(zf == nullptr) {
|
||||||
_lastError = Utility::format(error_format.data(), file, zip_strerror(zip));
|
_lastError = Utility::format(error_format.data(), file, zip_strerror(zip));
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,12 +351,14 @@ auto ProfileManager::restoreBackup(std::size_t index) -> bool {
|
||||||
while((bytes_read = zip_fread(zf, buf.data(), buf.size())) > 0) {
|
while((bytes_read = zip_fread(zf, buf.data(), buf.size())) > 0) {
|
||||||
if(std::fwrite(buf.data(), sizeof(char), bytes_read, out) < static_cast<std::size_t>(bytes_read)) {
|
if(std::fwrite(buf.data(), sizeof(char), bytes_read, out) < static_cast<std::size_t>(bytes_read)) {
|
||||||
_lastError = Utility::format(error_format.data(), file, "not enough bytes written.");
|
_lastError = Utility::format(error_format.data(), file, "not enough bytes written.");
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bytes_read == -1) {
|
if(bytes_read == -1) {
|
||||||
_lastError = Utility::format(error_format.data(), file, "couldn't read bytes from archive.");
|
_lastError = Utility::format(error_format.data(), file, "couldn't read bytes from archive.");
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ struct Backup {
|
||||||
Containers::String filename;
|
Containers::String filename;
|
||||||
Containers::String company;
|
Containers::String company;
|
||||||
ProfileType type;
|
ProfileType type;
|
||||||
ProfileVersion version;
|
|
||||||
struct {
|
struct {
|
||||||
int year;
|
int year;
|
||||||
int month;
|
int month;
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <Corrade/Utility/Format.h>
|
||||||
#include <Corrade/Utility/String.h>
|
#include <Corrade/Utility/String.h>
|
||||||
#include <Corrade/Utility/Unicode.h>
|
#include <Corrade/Utility/Unicode.h>
|
||||||
|
|
||||||
#include <SDL_events.h>
|
#include <SDL_events.h>
|
||||||
|
#include <SDL_messagebox.h>
|
||||||
|
|
||||||
#include <fileapi.h>
|
#include <fileapi.h>
|
||||||
#include <handleapi.h>
|
#include <handleapi.h>
|
||||||
|
@ -98,7 +100,11 @@ void SaveTool::fileUpdateEvent(SDL_Event& event) {
|
||||||
if(is_current_profile) {
|
if(is_current_profile) {
|
||||||
_currentProfile = nullptr;
|
_currentProfile = nullptr;
|
||||||
_uiState = UiState::ProfileManager;
|
_uiState = UiState::ProfileManager;
|
||||||
_profileManager->refreshProfiles();
|
if(!_profileManager->refreshProfiles()) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(is_unit) {
|
else if(is_unit) {
|
||||||
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
|
||||||
|
|
|
@ -52,7 +52,8 @@ void SaveTool::drawProfileManager() {
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::SmallButton("Refresh")) {
|
if(ImGui::SmallButton("Refresh")) {
|
||||||
if(!_profileManager->refreshProfiles()) {
|
if(!_profileManager->refreshProfiles()) {
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error in ProfileManager", _profileManager->lastError().data(), window());
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,9 +96,7 @@ void SaveTool::drawProfileManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::Text("%s%s",
|
ImGui::TextUnformatted(profile.isDemo() ? "Demo" : "Full");
|
||||||
profile.isDemo() ? "Demo" : "Full",
|
|
||||||
profile.isLegacy() ? " (legacy)" : "");
|
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {
|
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {
|
||||||
|
@ -161,7 +160,11 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
if(!_profileManager->restoreBackup(backup_index)) {
|
if(!_profileManager->restoreBackup(backup_index)) {
|
||||||
_queue.addToast(Toast::Type::Error, _profileManager->lastError());
|
_queue.addToast(Toast::Type::Error, _profileManager->lastError());
|
||||||
}
|
}
|
||||||
_profileManager->refreshProfiles();
|
if(!_profileManager->refreshProfiles()) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -278,9 +281,7 @@ auto SaveTool::drawBackupListPopup() -> ImGuiID {
|
||||||
backup.timestamp.second);
|
backup.timestamp.second);
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
ImGui::Text("%s%s",
|
ImGui::TextUnformatted(backup.type == ProfileType::Demo ? "Demo" : "Full");
|
||||||
backup.type == ProfileType::Demo ? "Demo" : "Full",
|
|
||||||
backup.version == ProfileVersion::Legacy ? " (legacy)" : "");
|
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
ImGui::PushID(i);
|
ImGui::PushID(i);
|
||||||
|
@ -340,12 +341,18 @@ auto SaveTool::drawBackupProfilePopup(std::size_t profile_index) -> ImGuiID {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
_profileManager->backupProfile(profile_index, true);
|
if(!_profileManager->backupProfile(profile_index, true)) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if(ImGui::Button("No", ImGui::GetItemRectSize())) {
|
if(ImGui::Button("No", ImGui::GetItemRectSize())) {
|
||||||
_profileManager->backupProfile(profile_index, false);
|
if(!_profileManager->backupProfile(profile_index, false)) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error",
|
||||||
|
_profileManager->lastError().data(), window());
|
||||||
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
Loading…
Reference in a new issue