Compare commits
No commits in common. "57f6364b7f48446ee9b60222946bb5ff004d4c4b" and "07832e6a89022aed6044d4576a02bb43b655ee29" have entirely different histories.
57f6364b7f
...
07832e6a89
12 changed files with 143 additions and 346 deletions
|
@ -40,7 +40,6 @@
|
||||||
#include "../Managers/BackupManager.h"
|
#include "../Managers/BackupManager.h"
|
||||||
#include "../Managers/MassManager.h"
|
#include "../Managers/MassManager.h"
|
||||||
#include "../Managers/ProfileManager.h"
|
#include "../Managers/ProfileManager.h"
|
||||||
#include "../Managers/StagedMassManager.h"
|
|
||||||
#include "../ToastQueue/ToastQueue.h"
|
#include "../ToastQueue/ToastQueue.h"
|
||||||
#include "../UpdateChecker/UpdateChecker.h"
|
#include "../UpdateChecker/UpdateChecker.h"
|
||||||
|
|
||||||
|
@ -261,8 +260,6 @@ class Application: public Platform::Sdl2Application, public efsw::FileWatchListe
|
||||||
Containers::Pointer<Managers::MassManager> _massManager;
|
Containers::Pointer<Managers::MassManager> _massManager;
|
||||||
GameObjects::Mass* _currentMass = nullptr;
|
GameObjects::Mass* _currentMass = nullptr;
|
||||||
|
|
||||||
Containers::Pointer<Managers::StagedMassManager> _stagedMassManager;
|
|
||||||
|
|
||||||
GameObjects::Weapon* _currentWeapon = nullptr;
|
GameObjects::Weapon* _currentWeapon = nullptr;
|
||||||
|
|
||||||
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
Containers::Pointer<efsw::FileWatcher> _fileWatcher;
|
||||||
|
|
|
@ -68,7 +68,7 @@ Application::fileUpdateEvent(SDL_Event& event) {
|
||||||
std::strlen(static_cast<char*>(event.user.data1)), nullptr};
|
std::strlen(static_cast<char*>(event.user.data1)), nullptr};
|
||||||
|
|
||||||
if((event.user.code & StagedUpdate) == StagedUpdate) {
|
if((event.user.code & StagedUpdate) == StagedUpdate) {
|
||||||
_stagedMassManager->refreshMass(filename);
|
_massManager->refreshStagedMass(filename);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,6 @@ Application::initialiseManager() {
|
||||||
|
|
||||||
_backupManager.emplace();
|
_backupManager.emplace();
|
||||||
|
|
||||||
_stagedMassManager.emplace();
|
|
||||||
|
|
||||||
event.user.code = InitSuccess;
|
event.user.code = InitSuccess;
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -438,7 +438,7 @@ Application::drawMassManager() {
|
||||||
|
|
||||||
Containers::StringView file = *static_cast<Containers::String*>(payload->Data);
|
Containers::StringView file = *static_cast<Containers::String*>(payload->Data);
|
||||||
|
|
||||||
if(!_stagedMassManager->import(file, i, _currentProfile->account(), _currentProfile->isDemo())) {
|
if(!_massManager->importMass(file, i)) {
|
||||||
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,26 +530,26 @@ Application::drawMassManager() {
|
||||||
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
openUri(Utility::Path::toNativeSeparators(conf().directories().staging));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto& mass : _stagedMassManager->stagedMasses()) {
|
for(const auto& pair : _massManager->stagedMasses()) {
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
Containers::String staged_formatted = Utility::format("{} ({})", mass.name, mass.filename);
|
Containers::String staged_formatted = Utility::format("{} ({})", pair.second, pair.first);
|
||||||
ImGui::Selectable(staged_formatted.data());
|
ImGui::Selectable(staged_formatted.data());
|
||||||
if((ImGui::CalcTextSize(staged_formatted.data()).x + ImGui::GetStyle().FramePadding.x) > ImGui::GetContentRegionAvail().x) {
|
if((ImGui::CalcTextSize(staged_formatted.data()).x + ImGui::GetStyle().FramePadding.x) > ImGui::GetContentRegionAvail().x) {
|
||||||
drawTooltip(staged_formatted.data());
|
drawTooltip(staged_formatted.data());
|
||||||
}
|
}
|
||||||
if(ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) {
|
if(ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) {
|
||||||
ImGui::SetDragDropPayload("StagedMass", &(mass.filename), sizeof(Containers::String));
|
ImGui::SetDragDropPayload("StagedMass", &(pair.first), sizeof(Containers::String));
|
||||||
|
|
||||||
ImGui::Text("%s - Staged", mass.name.cbegin());
|
ImGui::Text("%s - Staged", pair.second.data());
|
||||||
|
|
||||||
ImGui::EndDragDropSource();
|
ImGui::EndDragDropSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::PushID(mass.filename.data());
|
ImGui::PushID(pair.first.data());
|
||||||
if(ImGui::SmallButton(ICON_FA_TRASH_ALT)) {
|
if(ImGui::SmallButton(ICON_FA_TRASH_ALT)) {
|
||||||
staged_mass_to_delete = mass.filename;
|
staged_mass_to_delete = pair.first;
|
||||||
ImGui::OpenPopup("Confirmation##DeleteStagedMassConfirmation");
|
ImGui::OpenPopup("Confirmation##DeleteStagedMassConfirmation");
|
||||||
}
|
}
|
||||||
drawTooltip("Delete");
|
drawTooltip("Delete");
|
||||||
|
@ -644,7 +644,7 @@ Application::drawDeleteStagedMassPopup(Containers::StringView filename) {
|
||||||
|
|
||||||
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f);
|
ImGui::PushTextWrapPos(float(windowSize().x()) * 0.40f);
|
||||||
ImGui::Text("Are you sure you want to delete the staged M.A.S.S. named %s ? This operation is irreversible.",
|
ImGui::Text("Are you sure you want to delete the staged M.A.S.S. named %s ? This operation is irreversible.",
|
||||||
_stagedMassManager->at(filename).filename.cbegin());
|
_massManager->stagedMasses().at(filename).data());
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
|
|
||||||
if(ImGui::BeginTable("##DeleteStagedMassLayout", 2)) {
|
if(ImGui::BeginTable("##DeleteStagedMassLayout", 2)) {
|
||||||
|
@ -655,9 +655,8 @@ Application::drawDeleteStagedMassPopup(Containers::StringView filename) {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
if(ImGui::Button("Yes")) {
|
if(ImGui::Button("Yes")) {
|
||||||
if(!_stagedMassManager->remove(filename)) {
|
if(!_massManager->deleteStagedMass(filename)) {
|
||||||
_queue.addToast(Toast::Type::Error,
|
_queue.addToast(Toast::Type::Error, _massManager->lastError());
|
||||||
"Couldn't delete the staged M.A.S.S. at " + filename + ": " + _stagedMassManager->lastError());
|
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,9 +199,6 @@ add_executable(MassBuilderSaveTool
|
||||||
Managers/MassManager.cpp
|
Managers/MassManager.cpp
|
||||||
Managers/ProfileManager.h
|
Managers/ProfileManager.h
|
||||||
Managers/ProfileManager.cpp
|
Managers/ProfileManager.cpp
|
||||||
Managers/StagedMass.h
|
|
||||||
Managers/StagedMassManager.h
|
|
||||||
Managers/StagedMassManager.cpp
|
|
||||||
Managers/Vfs/Directory.h
|
Managers/Vfs/Directory.h
|
||||||
Maps/ArmourSlots.hpp
|
Maps/ArmourSlots.hpp
|
||||||
Maps/BulletLauncherAttachmentStyles.hpp
|
Maps/BulletLauncherAttachmentStyles.hpp
|
||||||
|
@ -237,7 +234,7 @@ target_compile_definitions(MassBuilderSaveTool PRIVATE
|
||||||
SAVETOOL_VERSION_MINOR=5
|
SAVETOOL_VERSION_MINOR=5
|
||||||
SAVETOOL_VERSION_PATCH=0
|
SAVETOOL_VERSION_PATCH=0
|
||||||
SAVETOOL_VERSION_PRERELEASE=true
|
SAVETOOL_VERSION_PRERELEASE=true
|
||||||
SAVETOOL_CODENAME="Fuckin' UE5..."
|
SAVETOOL_CODENAME="Friendly Valkyrie"
|
||||||
SAVETOOL_SUPPORTED_GAME_VERSION="0.11.x"
|
SAVETOOL_SUPPORTED_GAME_VERSION="0.11.x"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,6 @@ static const std::map<std::int32_t, Containers::StringView> mission_id_map {{
|
||||||
{114, "Mission 15 - Outposts Line of Defense"_s},
|
{114, "Mission 15 - Outposts Line of Defense"_s},
|
||||||
{115, "Mission 16 - Hidden in the Pass"_s},
|
{115, "Mission 16 - Hidden in the Pass"_s},
|
||||||
{116, "Mission 17 - Homebase Security"_s},
|
{116, "Mission 17 - Homebase Security"_s},
|
||||||
{117, "Mission 18 - Molewarp Protection Deal"_s},
|
|
||||||
{118, "Mission 19 - Behind the Walls of Ice"_s},
|
|
||||||
{119, "Mission 20 - Odin in the Sea of Flames"_s},
|
|
||||||
{120, "Mission 21 - Retracing Ruined Shelter"_s},
|
|
||||||
{121, "Mission 22 - The Traitor"_s},
|
|
||||||
{122, "Mission 23 - Duel of Aces"_s},
|
|
||||||
|
|
||||||
// Hunting grounds
|
// Hunting grounds
|
||||||
{200, "Hunt 1 - Desert Pathway Safety"_s},
|
{200, "Hunt 1 - Desert Pathway Safety"_s},
|
||||||
|
@ -58,8 +52,6 @@ static const std::map<std::int32_t, Containers::StringView> mission_id_map {{
|
||||||
{203, "Hunt 4 - Depths of the Machineries"_s},
|
{203, "Hunt 4 - Depths of the Machineries"_s},
|
||||||
{204, "Hunt 5 - Crater Crashers"_s},
|
{204, "Hunt 5 - Crater Crashers"_s},
|
||||||
{205, "Hunt 6 - Prototype Performance Tests"_s},
|
{205, "Hunt 6 - Prototype Performance Tests"_s},
|
||||||
{206, "Hunt 7 - A Mess in Manufacturing"_s},
|
|
||||||
{207, "Hunt 8 - Visitors in Volcanic Fissures"_s},
|
|
||||||
|
|
||||||
// Challenges
|
// Challenges
|
||||||
{300, "Challenge 1 - Redline Battlefront"_s},
|
{300, "Challenge 1 - Redline Battlefront"_s},
|
||||||
|
|
|
@ -108,27 +108,7 @@ static const Corrade::Containers::Array<StoryProgressPoint> story_progress
|
||||||
{0x06A5, "Chapter 3"_s, "Returned to hangar"_s, "After mission 16"_s},
|
{0x06A5, "Chapter 3"_s, "Returned to hangar"_s, "After mission 16"_s},
|
||||||
{0x06A6, "Chapter 3"_s, "Got mission 17 briefing"_s, "After mission 16"_s},
|
{0x06A6, "Chapter 3"_s, "Got mission 17 briefing"_s, "After mission 16"_s},
|
||||||
{0x0708, "Chapter 3"_s, "Debriefing"_s, "After mission 17"_s},
|
{0x0708, "Chapter 3"_s, "Debriefing"_s, "After mission 17"_s},
|
||||||
{0x0709, "Chapter 3"_s, "Returned to hangar"_s, "After mission 17"_s},
|
|
||||||
{0x070A, "Chapter 3"_s, "Got hunt 6 briefing"_s, "After mission 17"_s},
|
{0x070A, "Chapter 3"_s, "Got hunt 6 briefing"_s, "After mission 17"_s},
|
||||||
{0x070B, "Chapter 3"_s, "Returned to hangar"_s, "After mission 17"_s},
|
|
||||||
{0x070C, "Chapter 3"_s, "Got mission 18 briefing"_s, "After mission 17"_s},
|
|
||||||
{0x076C, "Chapter 3"_s, "Debriefing"_s, "After mission 18"_s},
|
|
||||||
{0x076D, "Chapter 3"_s, "Returned to hangar"_s, "After mission 18"_s},
|
|
||||||
{0x076E, "Chapter 3"_s, "Got hunt 7 and mission 19 briefing"_s, "After mission 18"_s},
|
|
||||||
|
|
||||||
{0x07D0, "Chapter 4"_s, "Debriefing"_s, "After mission 19"_s},
|
|
||||||
{0x07D1, "Chapter 4"_s, "Returned to hangar"_s, "After mission 19"_s},
|
|
||||||
{0x07D2, "Chapter 4"_s, "Got mission 20 briefing"_s, "After mission 19"_s},
|
|
||||||
{0x0834, "Chapter 4"_s, "Debriefing"_s, "After mission 20"_s},
|
|
||||||
{0x0835, "Chapter 4"_s, "Returned to hangar"_s, "After mission 20"_s},
|
|
||||||
{0x0836, "Chapter 4"_s, "Got hunt 8 and mission 21 briefing"_s, "After mission 20"_s},
|
|
||||||
{0x0898, "Chapter 4"_s, "Debriefing"_s, "After mission 21"_s},
|
|
||||||
{0x0899, "Chapter 4"_s, "Returned to hangar"_s, "After mission 21"_s},
|
|
||||||
{0x089A, "Chapter 4"_s, "Got mission 22 briefing"_s, "After mission 21"_s},
|
|
||||||
{0x08FC, "Chapter 4"_s, "Debriefing"_s, "After mission 22"_s},
|
|
||||||
{0x08FD, "Chapter 4"_s, "Returned to hangar"_s, "After mission 22"_s},
|
|
||||||
{0x08FE, "Chapter 4"_s, "Got mission 23 briefing"_s, "After mission 22"_s},
|
|
||||||
{0x0960, "Chapter 4"_s, "Returned to hangar"_s, "After mission 23"_s},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ MassManager::MassManager(Containers::StringView account, bool demo):
|
||||||
Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
|
Utility::format("{}Unit{:.2d}{}.sav", demo ? "Demo"_s : ""_s, i, _account));
|
||||||
new(&_hangars[i]) GameObjects::Mass{mass_filename};
|
new(&_hangars[i]) GameObjects::Mass{mass_filename};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshStagedMasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
Containers::StringView
|
Containers::StringView
|
||||||
|
@ -63,6 +65,49 @@ MassManager::refreshHangar(std::int32_t hangar) {
|
||||||
_hangars[hangar] = GameObjects::Mass{mass_filename};
|
_hangars[hangar] = GameObjects::Mass{mass_filename};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MassManager::importMass(Containers::StringView staged_fn, std::int32_t hangar) {
|
||||||
|
if(hangar < 0 || hangar >= 32) {
|
||||||
|
_lastError = "Hangar index out of range.";
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = _stagedMasses.find(Containers::String::nullTerminatedView(staged_fn));
|
||||||
|
|
||||||
|
if(it == _stagedMasses.end()) {
|
||||||
|
_lastError = "Couldn't find "_s + staged_fn + " in the staged M.A.S.S.es."_s;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::String source = Utility::Path::join(conf().directories().staging, staged_fn);
|
||||||
|
Utility::Path::copy(source, source + ".tmp"_s);
|
||||||
|
|
||||||
|
{
|
||||||
|
GameObjects::Mass mass{source + ".tmp"_s};
|
||||||
|
if(!mass.updateAccount(_account)) {
|
||||||
|
_lastError = mass.lastError();
|
||||||
|
Utility::Path::remove(source + ".tmp"_s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Containers::String dest = Utility::Path::join(conf().directories().gameSaves, _hangars[hangar].filename());
|
||||||
|
|
||||||
|
if(Utility::Path::exists(dest)) {
|
||||||
|
Utility::Path::remove(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Utility::Path::move(source + ".tmp"_s, dest)) {
|
||||||
|
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", staged_fn, hangar + 1);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MassManager::exportMass(std::int32_t hangar) {
|
MassManager::exportMass(std::int32_t hangar) {
|
||||||
if(hangar < 0 || hangar >= 32) {
|
if(hangar < 0 || hangar >= 32) {
|
||||||
|
@ -147,4 +192,80 @@ MassManager::deleteMass(std::int32_t hangar) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::map<Containers::String, Containers::String>&
|
||||||
|
MassManager::stagedMasses() {
|
||||||
|
return _stagedMasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MassManager::refreshStagedMasses() {
|
||||||
|
_stagedMasses.clear();
|
||||||
|
|
||||||
|
using Utility::Path::ListFlag;
|
||||||
|
auto file_list = Utility::Path::list(conf().directories().staging,
|
||||||
|
ListFlag::SkipSpecial|ListFlag::SkipDirectories|ListFlag::SkipDotAndDotDot);
|
||||||
|
|
||||||
|
if(!file_list) {
|
||||||
|
LOG_ERROR_FORMAT("{} couldn't be opened.", conf().directories().staging);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = std::remove_if(file_list->begin(), file_list->end(), [](Containers::StringView file){
|
||||||
|
return !file.hasSuffix(".sav"_s);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto list_view = file_list->exceptSuffix(file_list->end() - iter);
|
||||||
|
|
||||||
|
LOG_INFO("Scanning for staged M.A.S.S.es...");
|
||||||
|
for(Containers::StringView file : list_view) {
|
||||||
|
auto name = GameObjects::Mass::getNameFromFile(Utility::Path::join(conf().directories().staging, file));
|
||||||
|
|
||||||
|
if(name) {
|
||||||
|
LOG_INFO_FORMAT("Found staged M.A.S.S.: {}", *name);
|
||||||
|
_stagedMasses[file] = *name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_WARNING_FORMAT("Skipped {}.", file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MassManager::refreshStagedMass(Containers::StringView filename) {
|
||||||
|
LOG_INFO_FORMAT("Refreshing staged unit with filename {}.", filename);
|
||||||
|
|
||||||
|
bool file_exists = Utility::Path::exists(Utility::Path::join(conf().directories().staging, filename));
|
||||||
|
auto it = _stagedMasses.find(filename);
|
||||||
|
|
||||||
|
if(file_exists) {
|
||||||
|
auto name = GameObjects::Mass::getNameFromFile(Utility::Path::join(conf().directories().staging, filename));
|
||||||
|
if(name) {
|
||||||
|
_stagedMasses[filename] = *name;
|
||||||
|
}
|
||||||
|
else if(it != _stagedMasses.cend()) {
|
||||||
|
_stagedMasses.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(it != _stagedMasses.cend()) {
|
||||||
|
_stagedMasses.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MassManager::deleteStagedMass(Containers::StringView filename) {
|
||||||
|
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;
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Utility::Path::remove(Utility::Path::join(conf().directories().staging, filename))) {
|
||||||
|
_lastError = filename + " couldn't be deleted: " + std::strerror(errno);
|
||||||
|
LOG_ERROR(_lastError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
// 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 <map>
|
||||||
|
|
||||||
#include <Corrade/Containers/StaticArray.h>
|
#include <Corrade/Containers/StaticArray.h>
|
||||||
#include <Corrade/Containers/String.h>
|
#include <Corrade/Containers/String.h>
|
||||||
#include <Corrade/Containers/StringView.h>
|
#include <Corrade/Containers/StringView.h>
|
||||||
|
@ -36,11 +38,17 @@ class MassManager {
|
||||||
|
|
||||||
void refreshHangar(int hangar);
|
void refreshHangar(int hangar);
|
||||||
|
|
||||||
|
bool importMass(Containers::StringView staged_fn, int hangar);
|
||||||
bool exportMass(int hangar);
|
bool exportMass(int hangar);
|
||||||
|
|
||||||
bool moveMass(int source, int destination);
|
bool moveMass(int source, int destination);
|
||||||
bool deleteMass(int hangar);
|
bool deleteMass(int hangar);
|
||||||
|
|
||||||
|
auto stagedMasses() -> std::map<Containers::String, Containers::String> const&;
|
||||||
|
void refreshStagedMasses();
|
||||||
|
void refreshStagedMass(Containers::StringView filename);
|
||||||
|
bool deleteStagedMass(Containers::StringView filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Containers::StringView _account;
|
Containers::StringView _account;
|
||||||
bool _demo;
|
bool _demo;
|
||||||
|
@ -48,6 +56,8 @@ class MassManager {
|
||||||
Containers::String _lastError;
|
Containers::String _lastError;
|
||||||
|
|
||||||
Containers::StaticArray<32, GameObjects::Mass> _hangars{NoInit};
|
Containers::StaticArray<32, GameObjects::Mass> _hangars{NoInit};
|
||||||
|
|
||||||
|
std::map<Containers::String, Containers::String> _stagedMasses;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// 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 <Corrade/Containers/String.h>
|
|
||||||
|
|
||||||
using namespace Corrade;
|
|
||||||
|
|
||||||
namespace mbst::Managers {
|
|
||||||
|
|
||||||
struct StagedMass {
|
|
||||||
Containers::String filename;
|
|
||||||
Containers::String name;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
// 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 <algorithm>
|
|
||||||
|
|
||||||
#include <Corrade/Containers/Optional.h>
|
|
||||||
#include <Corrade/Utility/Path.h>
|
|
||||||
|
|
||||||
#include "../Configuration/Configuration.h"
|
|
||||||
#include "../GameObjects/Mass.h"
|
|
||||||
#include "../Logger/Logger.h"
|
|
||||||
#include "../Utilities/Temp.h"
|
|
||||||
|
|
||||||
#include "StagedMassManager.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace mbst::Managers {
|
|
||||||
|
|
||||||
StagedMassManager::StagedMassManager() {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
Containers::StringView
|
|
||||||
StagedMassManager::lastError() {
|
|
||||||
return _lastError;
|
|
||||||
}
|
|
||||||
|
|
||||||
Containers::ArrayView<const StagedMass>
|
|
||||||
StagedMassManager::stagedMasses() const {
|
|
||||||
return _stagedMasses;
|
|
||||||
}
|
|
||||||
|
|
||||||
const StagedMass&
|
|
||||||
StagedMassManager::at(Containers::StringView filename) const {
|
|
||||||
for(const auto& mass : _stagedMasses) {
|
|
||||||
if(mass.filename == filename) {
|
|
||||||
return mass;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CORRADE_ASSERT_UNREACHABLE("Invalid staged M.A.S.S.!", StagedMass{});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StagedMassManager::refresh() {
|
|
||||||
_stagedMasses = Containers::Array<StagedMass>{};
|
|
||||||
|
|
||||||
LOG_INFO("Scanning for staged M.A.S.S.es...");
|
|
||||||
|
|
||||||
scanSubdir(""_s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StagedMassManager::refreshMass(Containers::StringView filename) {
|
|
||||||
LOG_INFO_FORMAT("Refreshing staged unit with filename {}.", filename);
|
|
||||||
|
|
||||||
bool file_exists = Utility::Path::exists(Utility::Path::join(conf().directories().staging, filename));
|
|
||||||
auto index = _stagedMasses.size();
|
|
||||||
for(std::size_t i = 0; i < _stagedMasses.size(); ++i) {
|
|
||||||
if(_stagedMasses[i].filename == filename) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(file_exists) {
|
|
||||||
if(auto name = GameObjects::Mass::getNameFromFile(Utility::Path::join(conf().directories().staging, filename))) {
|
|
||||||
arrayAppend(_stagedMasses, StagedMass{filename, *name});
|
|
||||||
std::sort(_stagedMasses.begin(), _stagedMasses.end(),
|
|
||||||
[](const StagedMass& a, const StagedMass& b)->bool{
|
|
||||||
if(a.filename.contains('/') && !b.filename.contains('/')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return a.filename < b.filename;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if(index != _stagedMasses.size()) {
|
|
||||||
arrayRemove(_stagedMasses, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(index != _stagedMasses.size()) {
|
|
||||||
arrayRemove(_stagedMasses, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
StagedMassManager::import(Containers::StringView filename, int index, Containers::StringView new_account, bool demo) {
|
|
||||||
if(index < 0 || index >= 32) {
|
|
||||||
LOG_ERROR(_lastError = "Hangar index out of range."_s);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
for(auto& mass : _stagedMasses) {
|
|
||||||
if(mass.filename == filename) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found) {
|
|
||||||
LOG_ERROR(_lastError = "Couldn't find "_s + filename + " in the staged M.A.S.S.es."_s);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto source = Utility::Path::join(conf().directories().staging, filename);
|
|
||||||
auto temp_path = Utilities::getTempPath(Utility::Path::split(filename).second());
|
|
||||||
Utility::Path::copy(source, temp_path);
|
|
||||||
|
|
||||||
{
|
|
||||||
GameObjects::Mass mass{temp_path};
|
|
||||||
if(!mass.updateAccount(new_account)) {
|
|
||||||
LOG_ERROR(_lastError = mass.lastError());
|
|
||||||
Utility::Path::remove(temp_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dest = Utility::Path::join(conf().directories().gameSaves,
|
|
||||||
Utility::format("{}Unit{}{}.sav", demo ? "Demo" : "", index, new_account));
|
|
||||||
|
|
||||||
if(Utility::Path::exists(dest)) {
|
|
||||||
Utility::Path::remove(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!Utility::Path::move(temp_path, dest)) {
|
|
||||||
_lastError = Utility::format("Couldn't move {} to hangar {:.2d}", filename, index + 1);
|
|
||||||
LOG_ERROR(_lastError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
StagedMassManager::remove(Containers::StringView filename) {
|
|
||||||
bool found = false;
|
|
||||||
for(auto& mass : _stagedMasses) {
|
|
||||||
if(mass.filename == filename) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!found || !Utility::Path::remove(Utility::Path::join(conf().directories().staging, filename))) {
|
|
||||||
LOG_ERROR(_lastError = Utility::format("{} couldn't be found.", filename));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StagedMassManager::scanSubdir(Containers::StringView subdir) {
|
|
||||||
static std::uint8_t depth = 0;
|
|
||||||
|
|
||||||
auto full_subdir = Utility::Path::join(conf().directories().staging, subdir);
|
|
||||||
|
|
||||||
using Flag = Utility::Path::ListFlag;
|
|
||||||
auto files = Utility::Path::list(full_subdir, Flag::SkipSpecial|Flag::SkipDirectories);
|
|
||||||
|
|
||||||
if(!files) {
|
|
||||||
LOG_ERROR_FORMAT("{} couldn't be opened.", full_subdir);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto iter = std::remove_if(files->begin(), files->end(), [](Containers::StringView file){
|
|
||||||
return !file.hasSuffix(".sav"_s);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto files_view = files->exceptSuffix(files->end() - iter);
|
|
||||||
|
|
||||||
for(Containers::StringView file : files_view) {
|
|
||||||
if(auto name = GameObjects::Mass::getNameFromFile(Utility::Path::join(full_subdir, file))) {
|
|
||||||
LOG_INFO_FORMAT("Found staged M.A.S.S.: {}", *name);
|
|
||||||
arrayAppend(_stagedMasses, InPlaceInit, file, *name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOG_WARNING_FORMAT("Skipped {}.", file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(depth == 5) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto subdirs = Utility::Path::list(full_subdir, Flag::SkipFiles|Flag::SkipSpecial|Flag::SkipDotAndDotDot);
|
|
||||||
if(!subdirs) {
|
|
||||||
LOG_ERROR_FORMAT("Couldn't list contents of {}.", full_subdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
for(auto& dir : *subdirs) {
|
|
||||||
scanSubdir(Utility::Path::join(subdir, dir));
|
|
||||||
}
|
|
||||||
|
|
||||||
depth--;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// 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 <Corrade/Containers/Array.h>
|
|
||||||
#include <Corrade/Containers/ArrayView.h>
|
|
||||||
#include <Corrade/Containers/String.h>
|
|
||||||
#include <Corrade/Containers/StringView.h>
|
|
||||||
|
|
||||||
#include "StagedMass.h"
|
|
||||||
|
|
||||||
using namespace Corrade;
|
|
||||||
|
|
||||||
namespace mbst::Managers {
|
|
||||||
|
|
||||||
class StagedMassManager {
|
|
||||||
public:
|
|
||||||
explicit StagedMassManager();
|
|
||||||
|
|
||||||
auto lastError() -> Containers::StringView;
|
|
||||||
|
|
||||||
auto stagedMasses() const -> Containers::ArrayView<const StagedMass>;
|
|
||||||
auto at(Containers::StringView filename) const -> const StagedMass&;
|
|
||||||
|
|
||||||
void refresh();
|
|
||||||
void refreshMass(Containers::StringView filename);
|
|
||||||
bool import(Containers::StringView filename, int index, Containers::StringView new_account, bool demo);
|
|
||||||
bool remove(Containers::StringView filename);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void scanSubdir(Containers::StringView subdir);
|
|
||||||
|
|
||||||
Containers::String _lastError;
|
|
||||||
|
|
||||||
Containers::Array<StagedMass> _stagedMasses;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue