MassBuilderSaveTool/src/Managers/ProfileManager.cpp

136 lines
4.1 KiB
C++

// MassBuilderSaveTool
// Copyright (C) 2021-2024 Guillaume Jacquemin
//
// 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 <cstdio>
#include <algorithm>
#include <chrono>
#include <Corrade/Containers/ScopeGuard.h>
#include <Corrade/Containers/StaticArray.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/Path.h>
#include <Corrade/Utility/String.h>
#include <zip.h>
#include "../Configuration/Configuration.h"
#include "../Logger/Logger.h"
#include "ProfileManager.h"
using namespace Containers::Literals;
namespace mbst { namespace Managers {
ProfileManager::ProfileManager() {
_ready = refreshProfiles();
}
bool
ProfileManager::ready() const {
return _ready;
}
Containers::StringView
ProfileManager::lastError() {
return _lastError;
}
Containers::ArrayView<GameObjects::Profile>
ProfileManager::profiles() {
return _profiles;
}
bool
ProfileManager::refreshProfiles() {
LOG_INFO("Refreshing profiles.");
_profiles = Containers::Array<GameObjects::Profile>{};
using Utility::Path::ListFlag;
auto files = Utility::Path::list(conf().directories().gameSaves,
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
if(!files) {
LOG_ERROR(_lastError = conf().directories().gameSaves + " can't be opened.");
return false;
}
auto predicate = [](Containers::StringView file)->bool{
return !((file.hasPrefix("DemoProfile") || file.hasPrefix("Profile")) && file.hasSuffix(".sav"));
};
auto files_view = files->exceptSuffix(files->end() - std::remove_if(files->begin(), files->end(), predicate));
for(const auto& file : files_view) {
GameObjects::Profile profile{Utility::Path::join(conf().directories().gameSaves, file)};
if(!profile.valid()) {
LOG_WARNING_FORMAT("Profile {} is invalid: {}", file, profile.lastError());
continue;
}
arrayAppend(_profiles, Utility::move(profile));
}
if(_profiles.isEmpty()) {
_lastError = "No valid profiles were found."_s;
LOG_ERROR(_lastError);
return false;
}
return true;
}
GameObjects::Profile*
ProfileManager::getProfile(std::size_t index) {
return index <= _profiles.size() ? &(_profiles[index]) : nullptr;
}
bool
ProfileManager::deleteProfile(std::size_t index, bool delete_builds) {
if(!Utility::Path::remove(Utility::Path::join(conf().directories().gameSaves, _profiles[index].filename()))) {
_lastError = Utility::format("Couldn't delete {} (filename: {}).",
_profiles[index].companyName(),
_profiles[index].filename());
LOG_ERROR(_lastError);
refreshProfiles();
return false;
}
if(delete_builds) {
for(std::uint8_t i = 0; i < 32; ++i) {
auto filename = Utility::format("{}Unit{:.2d}{}.sav",
_profiles[index].type() == GameObjects::Profile::Type::Demo ? "Demo": "",
i, _profiles[index].account());
Utility::Path::remove(Utility::Path::join(conf().directories().gameSaves, filename));
}
}
auto file = _profiles[index].filename();
auto it = std::remove_if(_profiles.begin(), _profiles.end(),
[&file](GameObjects::Profile& profile){ return profile.filename() == file; });
if(it != _profiles.end()) {
arrayRemoveSuffix(_profiles, 1);
}
return true;
}
}}