Compare commits

..

3 commits

Author SHA1 Message Date
db6836ec33 Profile(Manager): add basic 0.8 profile support. 2022-03-06 14:42:24 +01:00
89bba618fb SaveTool: eliminate a few format warnings. 2022-03-06 14:30:04 +01:00
88afaaceec UESaveFile/Serialisers: make types() return an ArrayView of Strings.
It's the best way to avoid dangling views for now.
2022-03-06 14:29:09 +01:00
21 changed files with 48 additions and 41 deletions

View file

@ -36,16 +36,21 @@ using namespace Containers::Literals;
Profile::Profile(Containers::StringView path): Profile::Profile(Containers::StringView path):
_profile(path) _profile(path)
{ {
if(!_profile.valid()) {
_lastError = _profile.lastError();
return;
}
_filename = Utility::Directory::filename(path); _filename = Utility::Directory::filename(path);
if(Utility::String::beginsWith(_filename, "Demo"_s)) { if(_filename.hasPrefix("Demo"_s)) {
_type = ProfileType::Demo; _type = ProfileType::Demo;
} }
else { else {
_type = ProfileType::FullGame; _type = ProfileType::FullGame;
} }
auto account_prop = _profile.at<StringProperty>("Account"); auto account_prop = _profile.at<StringProperty>("Account"_s);
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;
@ -53,7 +58,7 @@ Profile::Profile(Containers::StringView path):
} }
_account = account_prop->value; _account = account_prop->value;
if(Utility::String::beginsWith(_account, "PMCSlot"_s)) { if(_account.hasPrefix("PMCSlot"_s)) {
_version = ProfileVersion::Normal; _version = ProfileVersion::Normal;
} }
else { else {

View file

@ -60,9 +60,10 @@ auto ProfileManager::refreshProfiles() -> bool {
auto files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot); auto files = Utility::Directory::list(_saveDirectory, Flag::SkipSpecial|Flag::SkipDirectories|Flag::SkipDotAndDotDot);
auto predicate = [](Containers::StringView file)->bool{ auto predicate = [](Containers::StringView file)->bool{
std::regex regex("(Demo)?Profile[0-9]{17}\\.sav", std::regex::nosubs); std::regex legacy_regex("(Demo)?Profile[0-9]{17}\\.sav", std::regex::nosubs);
std::regex new_regex("(Demo)?ProfilePMCSlot[0-9]{3}\\.sav", std::regex::nosubs);
std::cmatch m; std::cmatch m;
return !std::regex_match(file.data(), m, regex); return !std::regex_match(file.data(), m, legacy_regex) && !std::regex_match(file.data(), m, new_regex);
}; };
files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end()); files.erase(std::remove_if(files.begin(), files.end(), predicate), files.end());

View file

@ -188,10 +188,10 @@ void SaveTool::drawGeneralInfo() {
ImGui::TextUnformatted("Story progress:"); ImGui::TextUnformatted("Story progress:");
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.x / 4.0f); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.x / 4.0f);
if(!it->after) { if(!it->after) {
ImGui::TextWrapped("%s - %s", it->chapter, it->point); ImGui::TextWrapped("%s - %s", it->chapter.data(), it->point.data());
} }
else { else {
ImGui::TextWrapped("%s - %s - %s", it->chapter, it->after, it->point); ImGui::TextWrapped("%s - %s - %s", it->chapter.data(), it->after.data(), it->point.data());
} }
} }
else { else {
@ -199,7 +199,7 @@ void SaveTool::drawGeneralInfo() {
} }
if(mission_id_map.find(_currentProfile->lastMissionId()) != mission_id_map.cend()) { if(mission_id_map.find(_currentProfile->lastMissionId()) != mission_id_map.cend()) {
ImGui::Text("Last mission: %s", mission_id_map.at(_currentProfile->lastMissionId())); ImGui::Text("Last mission: %s", mission_id_map.at(_currentProfile->lastMissionId()).data());
} }
else if(_currentProfile->lastMissionId() == -1) { else if(_currentProfile->lastMissionId() == -1) {
ImGui::TextUnformatted("Last mission: none"); ImGui::TextUnformatted("Last mission: none");

View file

@ -491,7 +491,7 @@ void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<C
ImGui::TextUnformatted("Accessory: <none>"); ImGui::TextUnformatted("Accessory: <none>");
} }
else if(accessories.find(accessory.id) != accessories.cend()) { else if(accessories.find(accessory.id) != accessories.cend()) {
ImGui::Text("Accessory #%i - %s", accessory.id, accessories.at(accessory.id)); ImGui::Text("Accessory #%i - %s", accessory.id, accessories.at(accessory.id).data());
} }
else { else {
ImGui::Text("Accessory #%i", accessory.id); ImGui::Text("Accessory #%i", accessory.id);

View file

@ -77,11 +77,13 @@ void SaveTool::drawProfileManager() {
ImGui::TextUnformatted("Actions"); ImGui::TextUnformatted("Actions");
for(std::size_t i = 0; i < _profileManager->profiles().size(); ++i) { for(std::size_t i = 0; i < _profileManager->profiles().size(); ++i) {
Profile& profile = _profileManager->profiles()[i];
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
ImGui::PushID(i); ImGui::PushID(i);
if(ImGui::Selectable(_profileManager->profiles()[i].companyName().data(), false, if(ImGui::Selectable(profile.companyName().data(), false,
ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap)) ImGuiSelectableFlags_SpanAllColumns|ImGuiSelectableFlags_AllowItemOverlap))
{ {
_currentProfile = _profileManager->getProfile(i); _currentProfile = _profileManager->getProfile(i);
@ -90,7 +92,9 @@ void SaveTool::drawProfileManager() {
} }
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
ImGui::TextUnformatted(_profileManager->profiles()[i].type() == ProfileType::Demo ? "Demo (legacy)" : "Full (legacy)"); ImGui::Text("%s%s",
profile.type() == ProfileType::Demo ? "Demo" : "Full",
profile.version() == ProfileVersion::Legacy ? " (legacy)" : "");
ImGui::TableSetColumnIndex(2); ImGui::TableSetColumnIndex(2);
if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) { if(ImGui::SmallButton(ICON_FA_FILE_ARCHIVE)) {

View file

@ -238,10 +238,8 @@ auto PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr>
} }
auto PropertySerialiser::getSerialiser(Containers::StringView item_type) -> AbstractUnrealPropertySerialiser* { auto PropertySerialiser::getSerialiser(Containers::StringView item_type) -> AbstractUnrealPropertySerialiser* {
!Utility::Debug{};
for(auto& item : _serialisers) { for(auto& item : _serialisers) {
for(auto serialiser_type : item->types()) { for(auto serialiser_type : item->types()) {
Utility::Debug{} << serialiser_type;
if(item_type == serialiser_type) { if(item_type == serialiser_type) {
return item.get(); return item.get();
} }

View file

@ -38,7 +38,7 @@ class AbstractUnrealCollectionPropertySerialiser {
virtual ~AbstractUnrealCollectionPropertySerialiser() = default; virtual ~AbstractUnrealCollectionPropertySerialiser() = default;
virtual auto types() -> Containers::ArrayView<const Containers::StringView> = 0; virtual auto types() -> Containers::ArrayView<const Containers::String> = 0;
virtual auto deserialise(Containers::StringView name, Containers::StringView type, virtual auto deserialise(Containers::StringView name, Containers::StringView type,
UnsignedLong value_length, UnsignedInt count, BinaryReader& reader, UnsignedLong value_length, UnsignedInt count, BinaryReader& reader,

View file

@ -37,7 +37,7 @@ class AbstractUnrealPropertySerialiser {
virtual ~AbstractUnrealPropertySerialiser() = default; virtual ~AbstractUnrealPropertySerialiser() = default;
virtual auto types() -> Containers::ArrayView<const Containers::StringView> = 0; virtual auto types() -> Containers::ArrayView<const Containers::String> = 0;
virtual auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, virtual auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr = 0; BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr = 0;

View file

@ -19,9 +19,9 @@
#include "BoolPropertySerialiser.h" #include "BoolPropertySerialiser.h"
auto BoolPropertySerialiser::types() -> Containers::ArrayView<const Containers::StringView> { auto BoolPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::StringView> types{InPlaceInit, {"BoolProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"BoolProperty"_s}};
return types; return types;
} }

View file

@ -29,7 +29,7 @@ class BoolPropertySerialiser : public AbstractUnrealPropertySerialiser {
public: public:
using ptr = Containers::Pointer<BoolPropertySerialiser>; using ptr = Containers::Pointer<BoolPropertySerialiser>;
auto types() -> Containers::ArrayView<const Containers::StringView> override; auto types() -> Containers::ArrayView<const Containers::String> override;
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;

View file

@ -19,9 +19,9 @@
#include "BytePropertySerialiser.h" #include "BytePropertySerialiser.h"
auto BytePropertySerialiser::types() -> Containers::ArrayView<const Containers::StringView> { auto BytePropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::StringView> types{InPlaceInit, {"ByteProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"ByteProperty"_s}};
return types; return types;
} }

View file

@ -27,7 +27,7 @@ class BytePropertySerialiser : public AbstractUnrealPropertySerialiser {
public: public:
using ptr = Containers::Pointer<BytePropertySerialiser>; using ptr = Containers::Pointer<BytePropertySerialiser>;
auto types() -> Containers::ArrayView<const Containers::StringView> override; auto types() -> Containers::ArrayView<const Containers::String> override;
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;

View file

@ -19,9 +19,9 @@
#include "EnumPropertySerialiser.h" #include "EnumPropertySerialiser.h"
auto EnumPropertySerialiser::types() -> Containers::ArrayView<const Containers::StringView> { auto EnumPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::StringView> types{InPlaceInit, {"EnumProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"EnumProperty"_s}};
return types; return types;
} }

View file

@ -27,7 +27,7 @@ class EnumPropertySerialiser : public AbstractUnrealPropertySerialiser {
public: public:
using ptr = Containers::Pointer<EnumPropertySerialiser>; using ptr = Containers::Pointer<EnumPropertySerialiser>;
auto types() -> Containers::ArrayView<const Containers::StringView> override; auto types() -> Containers::ArrayView<const Containers::String> override;
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;

View file

@ -19,10 +19,9 @@
#include "FloatPropertySerialiser.h" #include "FloatPropertySerialiser.h"
auto FloatPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
auto FloatPropertySerialiser::types() -> Containers::ArrayView<const Containers::StringView> {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::StringView> types{InPlaceInit, {"FloatProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"FloatProperty"_s}};
return types; return types;
} }

View file

@ -27,7 +27,7 @@ class FloatPropertySerialiser : public AbstractUnrealPropertySerialiser {
public: public:
using ptr = Containers::Pointer<FloatPropertySerialiser>; using ptr = Containers::Pointer<FloatPropertySerialiser>;
auto types() -> Containers::ArrayView<const Containers::StringView> override; auto types() -> Containers::ArrayView<const Containers::String> override;
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;

View file

@ -19,11 +19,11 @@
#include "StringPropertySerialiser.h" #include "StringPropertySerialiser.h"
auto StringPropertySerialiser::types() -> Containers::ArrayView<const Containers::StringView> { auto StringPropertySerialiser::types() -> Containers::ArrayView<const Containers::String> {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::StringView> types{InPlaceInit, static const Containers::Array<Containers::String> types{InPlaceInit,
{"NameProperty"_s, "StrProperty"_s, {"NameProperty"_s, "StrProperty"_s,
"SoftObjectProperty"_s, "ObjectProperty"_s}}; "SoftObjectProperty"_s, "ObjectProperty"_s}};
return types; return types;
} }

View file

@ -27,7 +27,7 @@ class StringPropertySerialiser : public AbstractUnrealPropertySerialiser {
public: public:
using ptr = Containers::Pointer<StringPropertySerialiser>; using ptr = Containers::Pointer<StringPropertySerialiser>;
auto types() -> Containers::ArrayView<const Containers::StringView> override; auto types() -> Containers::ArrayView<const Containers::String> override;
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override;

View file

@ -25,9 +25,9 @@
#include "StructSerialiser.h" #include "StructSerialiser.h"
auto StructSerialiser::types() -> Containers::ArrayView<const Containers::StringView> { auto StructSerialiser::types() -> Containers::ArrayView<const Containers::String> {
using namespace Containers::Literals; using namespace Containers::Literals;
static const Containers::Array<Containers::StringView> types{InPlaceInit, {"StructProperty"_s}}; static const Containers::Array<Containers::String> types{InPlaceInit, {"StructProperty"_s}};
return types; return types;
} }

View file

@ -29,7 +29,7 @@ class StructSerialiser : public AbstractUnrealPropertySerialiser, public Abstrac
public: public:
using ptr = Containers::Pointer<StructSerialiser>; using ptr = Containers::Pointer<StructSerialiser>;
auto types() -> Containers::ArrayView<const Containers::StringView> override; auto types() -> Containers::ArrayView<const Containers::String> override;
auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length, auto deserialise(Containers::StringView name, Containers::StringView type, UnsignedLong value_length,
UnsignedInt count, BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array<UnrealPropertyBase::ptr> override; UnsignedInt count, BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array<UnrealPropertyBase::ptr> override;

View file

@ -32,15 +32,15 @@ class UnrealPropertySerialiser : public AbstractUnrealPropertySerialiser {
public: public:
using ptr = Containers::Pointer<UnrealPropertySerialiser<T>>; using ptr = Containers::Pointer<UnrealPropertySerialiser<T>>;
auto types() -> Containers::ArrayView<const Containers::StringView> override { auto types() -> Containers::ArrayView<const Containers::String> override {
static const Containers::Array<Containers::StringView> types = []{ static const Containers::Array<Containers::String> types = []{
Containers::Array<Containers::StringView> array; Containers::Array<Containers::String> array;
Containers::Pointer<T> p(new T); Containers::Pointer<T> p(new T);
if(std::is_base_of<StructProperty, T>::value) { if(std::is_base_of<StructProperty, T>::value) {
array = Containers::Array<Containers::StringView>{InPlaceInit, {dynamic_cast<StructProperty*>(p.get())->structType}}; array = Containers::Array<Containers::String>{InPlaceInit, {dynamic_cast<StructProperty*>(p.get())->structType}};
} }
else { else {
array = Containers::Array<Containers::StringView>{InPlaceInit, {p->propertyType}}; array = Containers::Array<Containers::String>{InPlaceInit, {p->propertyType}};
} }
return array; return array;
}(); }();