2021-06-11 19:24:52 +02:00
|
|
|
// MassBuilderSaveTool
|
2022-01-30 11:36:56 +01:00
|
|
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
2021-06-11 19:24:52 +02:00
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
#include <Corrade/Utility/Format.h>
|
|
|
|
#include <Corrade/Utility/Path.h>
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2022-11-21 18:12:42 +01:00
|
|
|
#include "../Logger/Logger.h"
|
|
|
|
|
2021-06-11 19:24:52 +02:00
|
|
|
#include "MassManager.h"
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
using namespace Containers::Literals;
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2022-11-21 18:12:42 +01:00
|
|
|
MassManager::MassManager(Containers::StringView save_path, Containers::StringView account, bool demo,
|
|
|
|
Containers::StringView staging_dir):
|
2022-03-31 17:58:47 +02:00
|
|
|
_saveDirectory{save_path}, _account{account}, _demo{demo}, _stagingAreaDirectory{staging_dir}
|
2021-06-11 19:24:52 +02:00
|
|
|
{
|
2022-03-04 21:18:55 +01:00
|
|
|
Containers::String mass_filename = "";
|
2022-12-05 11:32:18 +01:00
|
|
|
for(std::uint32_t i = 0; i < _hangars.size(); i++) {
|
2022-11-21 18:12:42 +01:00
|
|
|
mass_filename = Utility::Path::join(_saveDirectory,
|
|
|
|
Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
|
2022-03-30 20:34:37 +02:00
|
|
|
new(&_hangars[i]) Mass{mass_filename};
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
refreshStagedMasses();
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
Containers::StringView
|
|
|
|
MassManager::lastError() {
|
2021-06-11 19:24:52 +02:00
|
|
|
return _lastError;
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
Mass&
|
2022-12-05 11:32:18 +01:00
|
|
|
MassManager::hangar(std::int32_t hangar) {
|
2021-08-19 20:33:59 +02:00
|
|
|
return _hangars[hangar];
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
void
|
2022-12-05 11:32:18 +01:00
|
|
|
MassManager::refreshHangar(std::int32_t hangar) {
|
2021-06-11 19:24:52 +02:00
|
|
|
if(hangar < 0 || hangar >= 32) {
|
2022-11-21 18:12:42 +01:00
|
|
|
_lastError = "Hangar index out of range.";
|
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
Containers::String mass_filename =
|
2022-03-09 11:04:19 +01:00
|
|
|
Utility::Path::join(_saveDirectory,
|
|
|
|
Utility::format("{}Unit{:.2d}{}.sav", _demo ? "Demo" : "", hangar, _account));
|
2021-06-11 19:24:52 +02:00
|
|
|
_hangars[hangar] = Mass{mass_filename};
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
bool
|
2022-12-05 11:32:18 +01:00
|
|
|
MassManager::importMass(Containers::StringView staged_fn, std::int32_t hangar) {
|
2021-06-11 19:24:52 +02:00
|
|
|
if(hangar < 0 || hangar >= 32) {
|
2022-11-21 18:12:42 +01:00
|
|
|
_lastError = "Hangar index out of range.";
|
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-21 16:31:29 +01:00
|
|
|
auto it = _stagedMasses.find(Containers::String::nullTerminatedView(staged_fn));
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
if(it == _stagedMasses.end()) {
|
2022-03-04 21:18:55 +01:00
|
|
|
_lastError = "Couldn't find "_s + staged_fn + " in the staged M.A.S.S.es."_s;
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
Containers::String source = Utility::Path::join(_stagingAreaDirectory, staged_fn);
|
|
|
|
Utility::Path::copy(source, source + ".tmp"_s);
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
{
|
2022-03-04 21:18:55 +01:00
|
|
|
Mass mass{source + ".tmp"_s};
|
|
|
|
if(!mass.updateAccount(_account)) {
|
2022-02-26 14:48:45 +01:00
|
|
|
_lastError = mass.lastError();
|
2022-03-09 11:04:19 +01:00
|
|
|
Utility::Path::remove(source + ".tmp"_s);
|
2022-02-26 14:48:45 +01:00
|
|
|
return false;
|
|
|
|
}
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
Containers::String dest = Utility::Path::join(_saveDirectory, _hangars[hangar].filename());
|
2022-02-26 14:48:45 +01:00
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
if(Utility::Path::exists(dest)) {
|
|
|
|
Utility::Path::remove(dest);
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
if(!Utility::Path::move(source + ".tmp"_s, dest)) {
|
|
|
|
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
bool
|
2022-12-05 11:32:18 +01:00
|
|
|
MassManager::exportMass(std::int32_t hangar) {
|
2021-06-11 19:24:52 +02:00
|
|
|
if(hangar < 0 || hangar >= 32) {
|
2022-11-21 18:12:42 +01:00
|
|
|
_lastError = "Hangar index out of range."_s;
|
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-08-28 20:20:09 +02:00
|
|
|
if(_hangars[hangar].state() != Mass::State::Valid) {
|
2022-03-09 11:04:19 +01:00
|
|
|
_lastError = Utility::format("There is no valid data to export in hangar {:.2d}", hangar + 1);
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
Containers::String source = Utility::Path::join(_saveDirectory, _hangars[hangar].filename());
|
2022-04-04 10:37:09 +02:00
|
|
|
Containers::String dest = Utility::Path::join(_stagingAreaDirectory,
|
|
|
|
Utility::format("{}_{}.sav", _hangars[hangar].name(), _account));
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
if(!Utility::Path::copy(source, dest)) {
|
|
|
|
_lastError = Utility::format("Couldn't export data from hangar {:.2d} to {}", hangar, dest);
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
bool
|
2022-12-05 11:32:18 +01:00
|
|
|
MassManager::moveMass(std::int32_t source, std::int32_t destination) {
|
2021-06-11 19:24:52 +02:00
|
|
|
if(source < 0 || source >= 32) {
|
2022-11-21 18:12:42 +01:00
|
|
|
_lastError = "Source hangar index out of range."_s;
|
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(destination < 0 || destination >= 32) {
|
2022-11-21 18:12:42 +01:00
|
|
|
_lastError = "Destination hangar index out of range."_s;
|
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
Containers::String source_file = Utility::Path::join(_saveDirectory, _hangars[source].filename());
|
|
|
|
Containers::String dest_file = Utility::Path::join(_saveDirectory, _hangars[destination].filename());
|
2021-08-28 20:20:09 +02:00
|
|
|
Mass::State dest_state = _hangars[destination].state();
|
2021-06-11 19:24:52 +02:00
|
|
|
|
|
|
|
switch(dest_state) {
|
2021-08-28 20:20:09 +02:00
|
|
|
case Mass::State::Empty:
|
2021-06-11 19:24:52 +02:00
|
|
|
break;
|
2021-08-28 20:20:09 +02:00
|
|
|
case Mass::State::Invalid:
|
2022-03-09 11:04:19 +01:00
|
|
|
Utility::Path::remove(dest_file);
|
2021-06-11 19:24:52 +02:00
|
|
|
break;
|
2021-08-28 20:20:09 +02:00
|
|
|
case Mass::State::Valid:
|
2022-03-09 11:04:19 +01:00
|
|
|
Utility::Path::move(dest_file, dest_file + ".tmp"_s);
|
2021-06-11 19:24:52 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
Utility::Path::move(source_file, dest_file);
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2021-08-28 20:20:09 +02:00
|
|
|
if(dest_state == Mass::State::Valid) {
|
2022-03-09 11:04:19 +01:00
|
|
|
Utility::Path::move(dest_file + ".tmp"_s, source_file);
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
bool
|
2022-12-05 11:32:18 +01:00
|
|
|
MassManager::deleteMass(std::int32_t hangar) {
|
2021-06-11 19:24:52 +02:00
|
|
|
if(hangar < 0 || hangar >= 32) {
|
2022-11-21 18:12:42 +01:00
|
|
|
_lastError = "Hangar index out of range."_s;
|
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
if(!Utility::Path::remove(Utility::Path::join(_saveDirectory, _hangars[hangar].filename()))) {
|
|
|
|
_lastError = Utility::format("Deletion failed: {}", std::strerror(errno));
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
const std::map<Containers::String, Containers::String>&
|
|
|
|
MassManager::stagedMasses() {
|
2021-06-11 19:24:52 +02:00
|
|
|
return _stagedMasses;
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
void
|
|
|
|
MassManager::refreshStagedMasses() {
|
2021-06-11 19:24:52 +02:00
|
|
|
_stagedMasses.clear();
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
using Utility::Path::ListFlag;
|
2022-11-21 18:12:42 +01:00
|
|
|
auto file_list = Utility::Path::list(_stagingAreaDirectory,
|
|
|
|
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
if(!file_list) {
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR_FORMAT("{} couldn't be opened.", _stagingAreaDirectory);
|
2022-03-09 11:04:19 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto iter = std::remove_if(file_list->begin(), file_list->end(), [](Containers::StringView file){
|
2022-03-09 14:03:08 +01:00
|
|
|
return !file.hasSuffix(".sav"_s);
|
2021-06-11 19:24:52 +02:00
|
|
|
});
|
|
|
|
|
2022-07-06 17:22:40 +02:00
|
|
|
auto list_view = file_list->exceptSuffix(file_list->end() - iter);
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2022-11-22 10:06:22 +01:00
|
|
|
LOG_INFO("Scanning for staged M.A.S.S.es...");
|
2022-03-09 11:04:19 +01:00
|
|
|
for(Containers::StringView file : list_view) {
|
|
|
|
auto name = Mass::getNameFromFile(Utility::Path::join(_stagingAreaDirectory, file));
|
2021-06-11 19:24:52 +02:00
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
if(name) {
|
2022-11-22 10:06:22 +01:00
|
|
|
LOG_INFO_FORMAT("Found staged M.A.S.S.: {}", *name);
|
2022-03-04 21:18:55 +01:00
|
|
|
_stagedMasses[file] = *name;
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
2022-03-09 14:03:08 +01:00
|
|
|
else {
|
2022-11-22 10:06:22 +01:00
|
|
|
LOG_WARNING_FORMAT("Skipped {}.", file);
|
2022-03-09 14:03:08 +01:00
|
|
|
}
|
2021-06-11 19:24:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
void
|
|
|
|
MassManager::refreshStagedMass(Containers::StringView filename) {
|
2022-11-22 10:35:05 +01:00
|
|
|
LOG_INFO_FORMAT("Refreshing staged unit with filename {}.", filename);
|
2022-04-04 10:37:09 +02:00
|
|
|
|
|
|
|
bool file_exists = Utility::Path::exists(Utility::Path::join(_stagingAreaDirectory, filename));
|
|
|
|
auto it = _stagedMasses.find(filename);
|
|
|
|
|
|
|
|
if(file_exists) {
|
|
|
|
auto name = Mass::getNameFromFile(Utility::Path::join(_stagingAreaDirectory, filename));
|
|
|
|
if(name) {
|
|
|
|
_stagedMasses[filename] = *name;
|
|
|
|
}
|
|
|
|
else if(it != _stagedMasses.cend()) {
|
|
|
|
_stagedMasses.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(it != _stagedMasses.cend()) {
|
|
|
|
_stagedMasses.erase(it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-03 16:49:39 +01:00
|
|
|
bool
|
|
|
|
MassManager::deleteStagedMass(Containers::StringView filename) {
|
2021-06-11 19:24:52 +02:00
|
|
|
if(_stagedMasses.find(filename) == _stagedMasses.cend()) {
|
2022-03-04 21:18:55 +01:00
|
|
|
_lastError = "The file "_s + filename + " couldn't be found in the list of staged M.A.S.S.es."_s;
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-09 11:04:19 +01:00
|
|
|
if(!Utility::Path::remove(Utility::Path::join(_stagingAreaDirectory, filename))) {
|
2022-03-04 21:18:55 +01:00
|
|
|
_lastError = filename + " couldn't be deleted: " + std::strerror(errno);
|
2022-11-21 18:12:42 +01:00
|
|
|
LOG_ERROR(_lastError);
|
2021-06-11 19:24:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|