diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a0aa25a..a1c8e24 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,83 @@ set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON) corrade_add_resource(Assets assets.conf) +add_library(UESaveFile STATIC EXCLUDE_FROM_ALL + UESaveFile/Serialisers/AbstractUnrealCollectionPropertySerialiser.h + UESaveFile/Serialisers/AbstractUnrealPropertySerialiser.h + UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h + UESaveFile/Serialisers/ArrayPropertySerialiser.h + UESaveFile/Serialisers/ArrayPropertySerialiser.cpp + UESaveFile/Serialisers/BoolPropertySerialiser.h + UESaveFile/Serialisers/BoolPropertySerialiser.cpp + UESaveFile/Serialisers/BytePropertySerialiser.h + UESaveFile/Serialisers/BytePropertySerialiser.cpp + UESaveFile/Serialisers/ColourPropertySerialiser.h + UESaveFile/Serialisers/ColourPropertySerialiser.cpp + UESaveFile/Serialisers/DateTimePropertySerialiser.h + UESaveFile/Serialisers/DateTimePropertySerialiser.cpp + UESaveFile/Serialisers/EnumPropertySerialiser.h + UESaveFile/Serialisers/EnumPropertySerialiser.cpp + UESaveFile/Serialisers/FloatPropertySerialiser.h + UESaveFile/Serialisers/FloatPropertySerialiser.cpp + UESaveFile/Serialisers/GuidPropertySerialiser.h + UESaveFile/Serialisers/GuidPropertySerialiser.cpp + UESaveFile/Serialisers/IntPropertySerialiser.h + UESaveFile/Serialisers/IntPropertySerialiser.cpp + UESaveFile/Serialisers/MapPropertySerialiser.h + UESaveFile/Serialisers/MapPropertySerialiser.cpp + UESaveFile/Serialisers/RotatorPropertySerialiser.h + UESaveFile/Serialisers/RotatorPropertySerialiser.cpp + UESaveFile/Serialisers/StringPropertySerialiser.h + UESaveFile/Serialisers/StringPropertySerialiser.cpp + UESaveFile/Serialisers/SetPropertySerialiser.h + UESaveFile/Serialisers/SetPropertySerialiser.cpp + UESaveFile/Serialisers/StructSerialiser.h + UESaveFile/Serialisers/StructSerialiser.cpp + UESaveFile/Serialisers/TextPropertySerialiser.h + UESaveFile/Serialisers/TextPropertySerialiser.cpp + UESaveFile/Serialisers/UnrealPropertySerialiser.h + UESaveFile/Serialisers/VectorPropertySerialiser.h + UESaveFile/Serialisers/VectorPropertySerialiser.cpp + UESaveFile/Serialisers/Vector2DPropertySerialiser.h + UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp + + UESaveFile/Types/ArrayProperty.h + UESaveFile/Types/BoolProperty.h + UESaveFile/Types/ByteProperty.h + UESaveFile/Types/ColourStructProperty.h + UESaveFile/Types/DateTimeStructProperty.h + UESaveFile/Types/EnumProperty.h + UESaveFile/Types/FloatProperty.h + UESaveFile/Types/GenericStructProperty.h + UESaveFile/Types/GuidStructProperty.h + UESaveFile/Types/IntProperty.h + UESaveFile/Types/MapProperty.h + UESaveFile/Types/NoneProperty.h + UESaveFile/Types/RotatorStructProperty.h + UESaveFile/Types/SetProperty.h + UESaveFile/Types/StringProperty.h + UESaveFile/Types/StructProperty.h + UESaveFile/Types/TextProperty.h + UESaveFile/Types/UnrealProperty.h + UESaveFile/Types/UnrealPropertyBase.h + UESaveFile/Types/VectorStructProperty.h + + UESaveFile/Debug.h + UESaveFile/Debug.cpp + UESaveFile/UESaveFile.h + UESaveFile/UESaveFile.cpp + UESaveFile/BinaryReader.h + UESaveFile/BinaryReader.cpp + UESaveFile/BinaryWriter.h + UESaveFile/BinaryWriter.cpp + UESaveFile/PropertySerialiser.h + UESaveFile/PropertySerialiser.cpp) + +target_link_libraries(UESaveFile PRIVATE + Corrade::Containers + Corrade::Utility + Magnum::Magnum) + add_executable(MassBuilderSaveTool WIN32 main.cpp SaveTool/SaveTool.h @@ -78,6 +155,7 @@ target_link_libraries(MassBuilderSaveTool PRIVATE Magnum::GL Magnum::Sdl2Application MagnumIntegration::ImGui + UESaveFile efsw zip cpr::cpr diff --git a/src/UESaveFile/BinaryReader.cpp b/src/UESaveFile/BinaryReader.cpp new file mode 100644 index 0000000..6a9b942 --- /dev/null +++ b/src/UESaveFile/BinaryReader.cpp @@ -0,0 +1,122 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include + +#include "BinaryReader.h" + +BinaryReader::BinaryReader(const std::string& filename) { + _file = std::fopen(filename.c_str(), "rb"); + + if(!_file) { + Utility::Error{} << "Couldn't open" << filename.c_str() << "for reading:\n" + << std::strerror(errno); + } +} + +BinaryReader::~BinaryReader() { + closeFile(); +} + +auto BinaryReader::open() -> bool { + return _file; +} + +auto BinaryReader::eof() -> bool { + return std::feof(_file) != 0; +} + +auto BinaryReader::position() -> Long { + return _ftelli64(_file); +} + +void BinaryReader::closeFile() { + std::fclose(_file); + _file = nullptr; +} + +auto BinaryReader::readChar(char& value) -> bool { + return std::fread(&value, sizeof(char), 1, _file) == 1; +} + +auto BinaryReader::readByte(Byte& value) -> bool { + return std::fread(&value, sizeof(Byte), 1, _file) == 1; +} + +auto BinaryReader::readUnsignedByte(UnsignedByte& value) -> bool { + return std::fread(&value, sizeof(UnsignedByte), 1, _file) == 1; +} + +auto BinaryReader::readShort(Short& value) -> bool { + return std::fread(&value, sizeof(Short), 1, _file) == 1; +} + +auto BinaryReader::readUnsignedShort(UnsignedShort& value) -> bool { + return std::fread(&value, sizeof(UnsignedShort), 1, _file) == 1; +} + +auto BinaryReader::readInt(Int& value) -> bool { + return std::fread(&value, sizeof(Int), 1, _file) == 1; +} + +auto BinaryReader::readUnsignedInt(UnsignedInt& value) -> bool { + return std::fread(&value, sizeof(UnsignedInt), 1, _file) == 1; +} + +auto BinaryReader::readLong(Long& value) -> bool { + return std::fread(&value, sizeof(Long), 1, _file) == 1; +} + +auto BinaryReader::readUnsignedLong(UnsignedLong& value) -> bool { + return std::fread(&value, sizeof(UnsignedLong), 1, _file) == 1; +} + +auto BinaryReader::readFloat(Float& value) -> bool { + return std::fread(&value, sizeof(Float), 1, _file) == 1; +} + +auto BinaryReader::readDouble(Double& value) -> bool { + return std::fread(&value, sizeof(Double), 1, _file) == 1; +} + +auto BinaryReader::readArray(Containers::Array& array, std::size_t count) -> bool { + if(array.size() < count) { + array = Containers::Array{ValueInit, count}; + } + + return std::fread(array.data(), sizeof(char), count, _file) == count; +} + +auto BinaryReader::readUEString(std::string& str) -> bool { + UnsignedInt length = 0; + if(!readUnsignedInt(length) || length == 0) { + return false; + } + + str = std::string{}; + str.resize(length - 1); + + return std::fread(&str[0], sizeof(char), length, _file) == length; +} + +auto BinaryReader::peekChar() -> Int { + Int c; + c = std::fgetc(_file); + std::ungetc(c, _file); + return c; +} diff --git a/src/UESaveFile/BinaryReader.h b/src/UESaveFile/BinaryReader.h new file mode 100644 index 0000000..c2a52b5 --- /dev/null +++ b/src/UESaveFile/BinaryReader.h @@ -0,0 +1,65 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include +#include + +#include + +using namespace Corrade; +using namespace Magnum; + +class BinaryReader { + public: + explicit BinaryReader(const std::string& filename); + ~BinaryReader(); + + auto open() -> bool; + auto eof() -> bool; + auto position() -> Long; + + void closeFile(); + + auto readChar(char& value) -> bool; + auto readByte(Byte& value) -> bool; + auto readUnsignedByte(UnsignedByte& value) -> bool; + auto readShort(Short& value) -> bool; + auto readUnsignedShort(UnsignedShort& value) -> bool; + auto readInt(Int& value) -> bool; + auto readUnsignedInt(UnsignedInt& value) -> bool; + auto readLong(Long& value) -> bool; + auto readUnsignedLong(UnsignedLong& value) -> bool; + auto readFloat(Float& value) -> bool; + auto readDouble(Double& value) -> bool; + auto readArray(Containers::Array& array, std::size_t count) -> bool; + + template + auto readStaticArray(Containers::StaticArray& array) -> bool { + return std::fread(array.data(), sizeof(char), S, _file) == S; + } + + auto readUEString(std::string& str) -> bool; + + auto peekChar() -> Int; + + private: + std::FILE* _file = nullptr; +}; diff --git a/src/UESaveFile/BinaryWriter.cpp b/src/UESaveFile/BinaryWriter.cpp new file mode 100644 index 0000000..76c2b03 --- /dev/null +++ b/src/UESaveFile/BinaryWriter.cpp @@ -0,0 +1,133 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include + +#include "BinaryWriter.h" + +BinaryWriter::BinaryWriter(const std::string& filename) { + _file = std::fopen(filename.c_str(), "wb"); + if(!_file) { + Utility::Error{} << "Couldn't open" << filename.c_str() << "for reading:\n" + << std::strerror(errno); + } +} + +BinaryWriter::~BinaryWriter() { + closeFile(); +} + +auto BinaryWriter::open() -> bool { + return _file; +} + +void BinaryWriter::closeFile() { + std::fflush(_file); + std::fclose(_file); + _file = nullptr; +} + +auto BinaryWriter::position() -> Long { + return _ftelli64(_file); +} + +auto BinaryWriter::arrayPosition() const -> UnsignedLong { + return _index; +} + +auto BinaryWriter::flushToFile() -> bool { + bool ret = writeArray(_data); + std::fflush(_file); + _data = Containers::Array{}; + _index = 0; + return ret; +} + +auto BinaryWriter::writeChar(char value) -> bool { + return std::fwrite(&value, sizeof(char), 1, _file) == 1; +} + +auto BinaryWriter::writeByte(Byte value) -> bool { + return std::fwrite(&value, sizeof(Byte), 1, _file) == 1; +} + +auto BinaryWriter::writeUnsignedByte(UnsignedByte value) -> bool { + return std::fwrite(&value, sizeof(UnsignedByte), 1, _file) == 1; +} + +auto BinaryWriter::writeShort(Short value) -> bool { + return std::fwrite(&value, sizeof(Short), 1, _file) == 1; +} + +auto BinaryWriter::writeUnsignedShort(UnsignedShort value) -> bool { + return std::fwrite(&value, sizeof(UnsignedShort), 1, _file) == 1; +} + +auto BinaryWriter::writeInt(Int value) -> bool { + return std::fwrite(&value, sizeof(Int), 1, _file) == 1; +} + +auto BinaryWriter::writeUnsignedInt(UnsignedInt value) -> bool { + return std::fwrite(&value, sizeof(UnsignedInt), 1, _file) == 1; +} + +auto BinaryWriter::writeLong(Long value) -> bool { + return std::fwrite(&value, sizeof(Long), 1, _file) == 1; +} + +auto BinaryWriter::writeUnsignedLong(UnsignedLong value) -> bool { + return std::fwrite(&value, sizeof(UnsignedLong), 1, _file) == 1; +} + +auto BinaryWriter::writeFloat(Float value) -> bool { + return std::fwrite(&value, sizeof(Float), 1, _file) == 1; +} + +auto BinaryWriter::writeDouble(Double value) -> bool { + return std::fwrite(&value, sizeof(Double), 1, _file) == 1; +} + +auto BinaryWriter::writeArray(Containers::ArrayView array) -> bool { + if(array.size() == 0) { + return false; + } + + return std::fwrite(array.data(), sizeof(char), array.size(), _file) == array.size(); +} + +auto BinaryWriter::writeUEString(const std::string& str) -> bool { + if(str.length() > UINT32_MAX) { + Utility::Error{} << "BinaryWriter::writeUEString(): string is too big."; + return false; + } + + writeUnsignedInt(static_cast(str.length()) + 1); + + if(str.length() > 0) { + std::size_t count = std::fwrite(&str[0], sizeof(char), str.length(), _file); + if(count != str.length()) { + return false; + } + } + return writeChar('\0'); +} + +auto BinaryWriter::writeUEStringToArray(const std::string& value) -> UnsignedLong { + Containers::ArrayView view{value.c_str(), value.length()}; + return writeValueToArray(UnsignedInt(value.length()) + 1u) + writeDataToArray(view) + writeValueToArray('\0'); +} diff --git a/src/UESaveFile/BinaryWriter.h b/src/UESaveFile/BinaryWriter.h new file mode 100644 index 0000000..50ea2b7 --- /dev/null +++ b/src/UESaveFile/BinaryWriter.h @@ -0,0 +1,99 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include +#include +#include + +#include + +using namespace Corrade; +using namespace Magnum; + +class BinaryWriter { + public: + explicit BinaryWriter(const std::string& filename); + ~BinaryWriter(); + + auto open() -> bool; + + void closeFile(); + + auto position() -> Long; + + auto arrayPosition() const -> UnsignedLong; + auto flushToFile() -> bool; + + auto writeByte(Byte value) -> bool; + auto writeChar(char value) -> bool; + auto writeUnsignedByte(UnsignedByte value) -> bool; + auto writeShort(Short value) -> bool; + auto writeUnsignedShort(UnsignedShort value) -> bool; + auto writeInt(Int value) -> bool; + auto writeUnsignedInt(UnsignedInt value) -> bool; + auto writeLong(Long value) -> bool; + auto writeUnsignedLong(UnsignedLong value) -> bool; + auto writeFloat(Float value) -> bool; + auto writeDouble(Double value) -> bool; + auto writeArray(Containers::ArrayView array) -> bool; + + template + auto writeStaticArray(Containers::StaticArrayView array) -> bool { + return std::fwrite(array.data(), sizeof(char), S, _file) == S; + } + + auto writeUEString(const std::string& str) -> bool; + + template::value, T, T&>> + auto writeValueToArray(U value) -> UnsignedLong { + Containers::ArrayView view{&value, 1}; + return writeDataToArray(view); + } + + auto writeUEStringToArray(const std::string& value) -> UnsignedLong; + + template + void writeValueToArrayAt(T& value, UnsignedLong position) { + Containers::ArrayView view{&value, 1}; + writeDataToArrayAt(view, position); + } + + template + auto writeDataToArray(Containers::ArrayView view) -> UnsignedLong { + arrayAppend(_data, Containers::arrayCast(view)); + _index += sizeof(T) * view.size(); + return sizeof(T) * view.size(); + } + + template + void writeDataToArrayAt(Containers::ArrayView view, UnsignedLong position) { + auto casted_view = Containers::arrayCast(view); + for(UnsignedLong i = 0; i < casted_view.size(); i++) { + _data[position + i] = casted_view[i]; + } + } + + private: + FILE* _file = nullptr; + + Containers::Array _data; + UnsignedLong _index = 0; +}; diff --git a/src/UESaveFile/Debug.cpp b/src/UESaveFile/Debug.cpp new file mode 100644 index 0000000..6d60d35 --- /dev/null +++ b/src/UESaveFile/Debug.cpp @@ -0,0 +1,76 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "Types/UnrealPropertyBase.h" +#include "Types/ArrayProperty.h" +#include "Types/SetProperty.h" +#include "Types/StructProperty.h" +#include "Types/GenericStructProperty.h" + +#include "Debug.h" + +Utility::Debug& operator<<(Utility::Debug& debug, const ArrayProperty* prop) { + return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << + prop->propertyType.c_str() << "of" << prop->items.size() << prop->itemType.c_str(); +} + +Utility::Debug& operator<<(Utility::Debug& debug, const SetProperty* prop) { + return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << + prop->propertyType.c_str() << "of" << prop->items.size() << prop->itemType.c_str(); +} + +Utility::Debug& operator<<(Utility::Debug& debug, const GenericStructProperty* prop) { + debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << + prop->structType.c_str() << "(" << Utility::Debug::nospace << prop->propertyType.c_str() << Utility::Debug::nospace << + ") Contents:"; + for(const auto& item : prop->properties) { + debug << "\n " << Utility::Debug::nospace << item.get(); + } + return debug; +} + +Utility::Debug& operator<<(Utility::Debug& debug, const StructProperty* prop) { + auto cast = dynamic_cast(prop); + if(cast) { + return debug << cast; + } + + return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << + prop->structType.c_str() << "(" << Utility::Debug::nospace << prop->propertyType.c_str() << Utility::Debug::nospace << ")"; +} + +Utility::Debug& operator<<(Utility::Debug& debug, const UnrealPropertyBase* prop) { + if(prop->propertyType == "ArrayProperty") { + auto array_prop = dynamic_cast(prop); + if(array_prop) { + return debug << array_prop; + } + } + else if(prop->propertyType == "SetProperty") { + auto set_prop = dynamic_cast(prop); + if(set_prop) { + return debug << set_prop; + } + } + else if(prop->propertyType == "StructProperty") { + auto struct_prop = dynamic_cast(prop); + if(struct_prop) { + return debug << struct_prop; + } + } + + return debug << (*prop->name).c_str() << Utility::Debug::nospace << ":" << prop->propertyType.c_str(); +} diff --git a/src/UESaveFile/Debug.h b/src/UESaveFile/Debug.h new file mode 100644 index 0000000..016d7e0 --- /dev/null +++ b/src/UESaveFile/Debug.h @@ -0,0 +1,33 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +struct ArrayProperty; +struct SetProperty; +struct GenericStructProperty; +struct StructProperty; +struct UnrealPropertyBase; + +using namespace Corrade; + +Utility::Debug& operator<<(Utility::Debug& debug, const ArrayProperty* prop); +Utility::Debug& operator<<(Utility::Debug& debug, const SetProperty* prop); +Utility::Debug& operator<<(Utility::Debug& debug, const GenericStructProperty* prop); +Utility::Debug& operator<<(Utility::Debug& debug, const StructProperty* prop); +Utility::Debug& operator<<(Utility::Debug& debug, const UnrealPropertyBase* prop); diff --git a/src/UESaveFile/PropertySerialiser.cpp b/src/UESaveFile/PropertySerialiser.cpp new file mode 100644 index 0000000..4c64756 --- /dev/null +++ b/src/UESaveFile/PropertySerialiser.cpp @@ -0,0 +1,252 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "Serialisers/ArrayPropertySerialiser.h" +#include "Serialisers/BoolPropertySerialiser.h" +#include "Serialisers/BytePropertySerialiser.h" +#include "Serialisers/ColourPropertySerialiser.h" +#include "Serialisers/DateTimePropertySerialiser.h" +#include "Serialisers/EnumPropertySerialiser.h" +#include "Serialisers/FloatPropertySerialiser.h" +#include "Serialisers/GuidPropertySerialiser.h" +#include "Serialisers/IntPropertySerialiser.h" +#include "Serialisers/MapPropertySerialiser.h" +#include "Serialisers/RotatorPropertySerialiser.h" +#include "Serialisers/StringPropertySerialiser.h" +#include "Serialisers/SetPropertySerialiser.h" +#include "Serialisers/StructSerialiser.h" +#include "Serialisers/TextPropertySerialiser.h" +#include "Serialisers/VectorPropertySerialiser.h" +#include "Serialisers/Vector2DPropertySerialiser.h" + +#include "Types/NoneProperty.h" + +#include "BinaryReader.h" +#include "BinaryWriter.h" + +#include "PropertySerialiser.h" + + +PropertySerialiser::PropertySerialiser() { + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + arrayAppend(_serialisers, Containers::pointer()); + + arrayAppend(_collectionSerialisers, Containers::pointer()); +} + +auto PropertySerialiser::read(BinaryReader& reader) -> UnrealPropertyBase::ptr { + if(reader.peekChar() < 0 || reader.eof()) { + return nullptr; + } + + std::string name; + if(!reader.readUEString(name)) { + return nullptr; + } + + if(name == "None") { + return Containers::pointer(); + } + + std::string type; + if(!reader.readUEString(type)) { + return nullptr; + } + + UnsignedLong value_length; + if(!reader.readUnsignedLong(value_length)) { + return nullptr; + } + + return deserialise(std::move(name), std::move(type), value_length, reader); +} + +auto PropertySerialiser::readItem(BinaryReader& reader, std::string type, UnsignedLong value_length, std::string name) -> UnrealPropertyBase::ptr { + if(reader.peekChar() < 0 || reader.eof()) { + return nullptr; + } + + return deserialise(std::move(name), std::move(type), value_length, reader); +} + +auto PropertySerialiser::readSet(BinaryReader& reader, const std::string& item_type, UnsignedInt count) -> Containers::Array { + if(reader.peekChar() < 0 || reader.eof()) { + return nullptr; + } + + auto serialiser = getCollectionSerialiser(item_type); + + Containers::Array array; + + if(serialiser) { + std::string name; + if(!reader.readUEString(name)) { + return nullptr; + } + + std::string type; + if(!reader.readUEString(type)) { + return nullptr; + } + + UnsignedLong value_length; + if(!reader.readUnsignedLong(value_length)) { + return nullptr; + } + + array = serialiser->deserialise(name, type, value_length, count, reader, *this); + + for(auto& item : array) { + if(item->name == Containers::NullOpt) { + item->name.emplace(name); + } + } + } + else { + for(UnsignedInt i = 0; i < count; i++) { + auto item = readItem(reader, item_type, -1, ""); + arrayAppend(array, std::move(item)); + } + } + + return array; +} + +auto PropertySerialiser::deserialise(std::string name, std::string type, UnsignedLong value_length, + BinaryReader& reader) -> UnrealPropertyBase::ptr +{ + UnrealPropertyBase::ptr prop; + auto serialiser = getSerialiser(type); + + if(serialiser == nullptr) { + return nullptr; + } + + prop = serialiser->deserialise(name, type, value_length, reader, *this); + + if(!prop) { + !Utility::Error{} << "No prop in" << __func__; + return nullptr; + } + + prop->name = std::move(name); + prop->propertyType = std::move(type); + + return prop; +} + +auto PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written, + BinaryWriter& writer) -> bool +{ + auto serialiser = getSerialiser(item_type); + if(!serialiser) { + return false; + } + return serialiser->serialise(prop, bytes_written, writer, *this); +} + +auto PropertySerialiser::write(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool { + if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast(prop.get())) { + bytes_written += writer.writeUEStringToArray(*prop->name); + return true; + } + + bytes_written += writer.writeUEStringToArray(*prop->name); + bytes_written += writer.writeUEStringToArray(prop->propertyType); + + UnsignedLong value_length = 0; + UnsignedLong vl_position = writer.arrayPosition(); + + bytes_written += writer.writeValueToArray(value_length); + + bool ret = serialise(prop, prop->propertyType, value_length, writer); + + writer.writeValueToArrayAt(value_length, vl_position); + + bytes_written += value_length; + + return ret; +} + +auto PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, const std::string& item_type, + UnsignedLong& bytes_written, BinaryWriter& writer) -> bool +{ + if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast(prop.get())) { + bytes_written += writer.writeUEStringToArray(*prop->name); + return true; + } + + return serialise(prop, item_type, bytes_written, writer); +} + +auto PropertySerialiser::writeSet(Containers::ArrayView props, const std::string& item_type, + UnsignedLong& bytes_written, BinaryWriter& writer) -> bool +{ + auto serialiser = getCollectionSerialiser(item_type); + if(serialiser) { + return serialiser->serialise(props, item_type, bytes_written, writer, *this); + } + else { + for(auto& prop : props) { + if(!writeItem(prop, item_type, bytes_written, writer)) { + return false; + } + } + + return true; + } +} + +auto PropertySerialiser::getSerialiser(const std::string& item_type) -> AbstractUnrealPropertySerialiser* { + for(auto& item : _serialisers) { + for(const std::string& serialiser_type : item->types()) { + if(item_type == serialiser_type) { + return item.get(); + } + } + } + + return nullptr; +} + +auto PropertySerialiser::getCollectionSerialiser(const std::string& item_type) -> AbstractUnrealCollectionPropertySerialiser* { + for(auto& item : _collectionSerialisers) { + for(const std::string& serialiser_type : item->types()) { + if(item_type == serialiser_type) { + return item.get(); + } + } + } + + return nullptr; +} diff --git a/src/UESaveFile/PropertySerialiser.h b/src/UESaveFile/PropertySerialiser.h new file mode 100644 index 0000000..8757aea --- /dev/null +++ b/src/UESaveFile/PropertySerialiser.h @@ -0,0 +1,51 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "Serialisers/AbstractUnrealPropertySerialiser.h" +#include "Serialisers/AbstractUnrealCollectionPropertySerialiser.h" + +#include "Types/UnrealPropertyBase.h" + +using namespace Corrade; + +class BinaryReader; +class BinaryWriter; + +class PropertySerialiser { + public: + PropertySerialiser(); + + auto read(BinaryReader& reader) -> UnrealPropertyBase::ptr; + auto readItem(BinaryReader& reader, std::string type, UnsignedLong value_length, std::string name) -> UnrealPropertyBase::ptr; + auto readSet(BinaryReader& reader, const std::string& item_type, UnsignedInt count) -> Containers::Array; + auto deserialise(std::string name, std::string type, UnsignedLong value_length, BinaryReader& reader) -> UnrealPropertyBase::ptr; + + auto serialise(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool; + auto write(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool; + auto writeItem(UnrealPropertyBase::ptr& prop, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool; + auto writeSet(Containers::ArrayView props, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer) -> bool; + + private: + auto getSerialiser(const std::string& item_type) -> AbstractUnrealPropertySerialiser*; + auto getCollectionSerialiser(const std::string& item_type) -> AbstractUnrealCollectionPropertySerialiser*; + + Containers::Array _serialisers; + Containers::Array _collectionSerialisers; +}; diff --git a/src/UESaveFile/Serialisers/AbstractUnrealCollectionPropertySerialiser.h b/src/UESaveFile/Serialisers/AbstractUnrealCollectionPropertySerialiser.h new file mode 100644 index 0000000..df004d4 --- /dev/null +++ b/src/UESaveFile/Serialisers/AbstractUnrealCollectionPropertySerialiser.h @@ -0,0 +1,47 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include +#include + +#include + +#include "../Types/UnrealPropertyBase.h" + +using namespace Corrade; +using namespace Magnum; + +class BinaryReader; +class BinaryWriter; +class PropertySerialiser; + +class AbstractUnrealCollectionPropertySerialiser { + public: + using ptr = Containers::Pointer; + + virtual ~AbstractUnrealCollectionPropertySerialiser() = default; + + virtual auto types() -> Containers::ArrayView = 0; + + virtual auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, UnsignedInt count, BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array = 0; + + virtual auto serialise(Containers::ArrayView props, const std::string& item_type, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0; +}; diff --git a/src/UESaveFile/Serialisers/AbstractUnrealPropertySerialiser.h b/src/UESaveFile/Serialisers/AbstractUnrealPropertySerialiser.h new file mode 100644 index 0000000..6605550 --- /dev/null +++ b/src/UESaveFile/Serialisers/AbstractUnrealPropertySerialiser.h @@ -0,0 +1,46 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include + +#include + +#include "../Types/UnrealPropertyBase.h" + +using namespace Corrade; +using namespace Magnum; + +class BinaryReader; +class BinaryWriter; +class PropertySerialiser; + +class AbstractUnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + virtual ~AbstractUnrealPropertySerialiser() = default; + + virtual auto types() -> Containers::ArrayView = 0; + + virtual auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr = 0; + + virtual auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0; +}; diff --git a/src/UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h b/src/UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h new file mode 100644 index 0000000..e52175b --- /dev/null +++ b/src/UESaveFile/Serialisers/AbstractUnrealStructSerialiser.h @@ -0,0 +1,46 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include +#include + +#include + +#include "../Types/UnrealPropertyBase.h" + +using namespace Corrade; +using namespace Magnum; + +class BinaryReader; +class BinaryWriter; + +class AbstractUnrealStructSerialiser { + public: + using ptr = Containers::Pointer; + + virtual ~AbstractUnrealStructSerialiser() = default; + + virtual auto supportsType(const std::string& type) -> bool = 0; + + virtual auto deserialise(BinaryReader& reader) -> UnrealPropertyBase::ptr = 0; + + virtual auto serialise(UnrealPropertyBase::ptr& structProp, BinaryWriter& writer, UnsignedLong& bytes_written) -> bool = 0; +}; diff --git a/src/UESaveFile/Serialisers/ArrayPropertySerialiser.cpp b/src/UESaveFile/Serialisers/ArrayPropertySerialiser.cpp new file mode 100644 index 0000000..70cff56 --- /dev/null +++ b/src/UESaveFile/Serialisers/ArrayPropertySerialiser.cpp @@ -0,0 +1,66 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" +#include "../PropertySerialiser.h" + +#include "ArrayPropertySerialiser.h" + +auto ArrayPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + std::string item_type; + if(!reader.readUEString(item_type)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + UnsignedInt item_count; + if(!reader.readUnsignedInt(item_count)) { + return nullptr; + } + + auto prop = Containers::pointer(); + prop->itemType = std::move(item_type); + prop->items = serialiser.readSet(reader, prop->itemType, item_count); + + return prop; +} + +auto ArrayPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto array_prop = dynamic_cast(prop.get()); + if(!array_prop) { + return false; + } + + writer.writeUEStringToArray(array_prop->itemType); + writer.writeValueToArray('\0'); + bytes_written += writer.writeValueToArray(UnsignedInt(array_prop->items.size())); + + UnsignedLong start_pos = writer.arrayPosition(); + UnsignedLong dummy_bytes_written = 0; + bool ret = serialiser.writeSet(array_prop->items, array_prop->itemType, dummy_bytes_written, writer); + bytes_written += writer.arrayPosition() - start_pos; + + return ret; +} diff --git a/src/UESaveFile/Serialisers/ArrayPropertySerialiser.h b/src/UESaveFile/Serialisers/ArrayPropertySerialiser.h new file mode 100644 index 0000000..f05db71 --- /dev/null +++ b/src/UESaveFile/Serialisers/ArrayPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/ArrayProperty.h" + +class ArrayPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/BoolPropertySerialiser.cpp b/src/UESaveFile/Serialisers/BoolPropertySerialiser.cpp new file mode 100644 index 0000000..10e761f --- /dev/null +++ b/src/UESaveFile/Serialisers/BoolPropertySerialiser.cpp @@ -0,0 +1,61 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "BoolPropertySerialiser.h" + +auto BoolPropertySerialiser::types() -> Containers::ArrayView { + static const Containers::Array types{InPlaceInit, {"BoolProperty"}}; + return types; +} + +auto BoolPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + if(value_length != 0) { + return nullptr; + } + + Short value; + if(!reader.readShort(value)) { + return nullptr; + } + + if(value > 1 || value < 0) { + return nullptr; + } + + auto prop = Containers::pointer(); + prop->value = value; + + return prop; +} + +auto BoolPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto bool_prop = dynamic_cast(prop.get()); + + if(!bool_prop) { + return false; + } + + writer.writeValueToArray(Short(bool_prop->value)); + + return true; +} diff --git a/src/UESaveFile/Serialisers/BoolPropertySerialiser.h b/src/UESaveFile/Serialisers/BoolPropertySerialiser.h new file mode 100644 index 0000000..1b0bb3d --- /dev/null +++ b/src/UESaveFile/Serialisers/BoolPropertySerialiser.h @@ -0,0 +1,32 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "AbstractUnrealPropertySerialiser.h" + +#include "../Types/BoolProperty.h" + +class BoolPropertySerialiser : public AbstractUnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + auto types() -> Containers::ArrayView override; + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/BytePropertySerialiser.cpp b/src/UESaveFile/Serialisers/BytePropertySerialiser.cpp new file mode 100644 index 0000000..4cc597f --- /dev/null +++ b/src/UESaveFile/Serialisers/BytePropertySerialiser.cpp @@ -0,0 +1,75 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "BytePropertySerialiser.h" + +auto BytePropertySerialiser::types() -> Containers::ArrayView { + static const Containers::Array types{InPlaceInit, {"ByteProperty"}}; + return types; +} + +auto BytePropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readUEString(prop->enumType)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + if(!reader.readUEString(prop->enumValue)) { + return nullptr; + } + + //UnsignedInt count = 0; + //if(!reader.readUnsignedInt(count)) { + // return nullptr; + //} + + //if(!reader.readArray(prop->value, count)) { + // return nullptr; + //} + + return prop; +} + +auto BytePropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto byte_prop = dynamic_cast(prop.get()); + + if(!byte_prop) { + return false; + } + + //writer.writeValueToArray('\0'); + //bytes_written += writer.writeValueToArray(byte_prop->value.size()); + //bytes_written += writer.writeDataToArray(byte_prop->value); + + writer.writeUEStringToArray(byte_prop->enumType); + writer.writeValueToArray('\0'); + bytes_written += writer.writeUEStringToArray(byte_prop->enumValue); + + return true; +} diff --git a/src/UESaveFile/Serialisers/BytePropertySerialiser.h b/src/UESaveFile/Serialisers/BytePropertySerialiser.h new file mode 100644 index 0000000..3fd882d --- /dev/null +++ b/src/UESaveFile/Serialisers/BytePropertySerialiser.h @@ -0,0 +1,32 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "AbstractUnrealPropertySerialiser.h" + +#include "../Types/ByteProperty.h" + +class BytePropertySerialiser : public AbstractUnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + auto types() -> Containers::ArrayView override; + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/ColourPropertySerialiser.cpp b/src/UESaveFile/Serialisers/ColourPropertySerialiser.cpp new file mode 100644 index 0000000..befd069 --- /dev/null +++ b/src/UESaveFile/Serialisers/ColourPropertySerialiser.cpp @@ -0,0 +1,49 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "ColourPropertySerialiser.h" + +auto ColourPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readFloat(prop->r) || !reader.readFloat(prop->g) || + !reader.readFloat(prop->b) || !reader.readFloat(prop->a)) + { + return nullptr; + } + + return prop; +} + +auto ColourPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto colour_prop = dynamic_cast(prop.get()); + + if(!colour_prop) { + return false; + } + + bytes_written += writer.writeValueToArray(colour_prop->r) + writer.writeValueToArray(colour_prop->g) + + writer.writeValueToArray(colour_prop->b) + writer.writeValueToArray(colour_prop->a); + + return true; +} diff --git a/src/UESaveFile/Serialisers/ColourPropertySerialiser.h b/src/UESaveFile/Serialisers/ColourPropertySerialiser.h new file mode 100644 index 0000000..f858739 --- /dev/null +++ b/src/UESaveFile/Serialisers/ColourPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/ColourStructProperty.h" + +class ColourPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/DateTimePropertySerialiser.cpp b/src/UESaveFile/Serialisers/DateTimePropertySerialiser.cpp new file mode 100644 index 0000000..615449e --- /dev/null +++ b/src/UESaveFile/Serialisers/DateTimePropertySerialiser.cpp @@ -0,0 +1,46 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "DateTimePropertySerialiser.h" + +auto DateTimePropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readUnsignedLong(prop->timestamp)) { + return nullptr; + } + + return prop; +} + +auto DateTimePropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto dt_prop = dynamic_cast(prop.get()); + + if(!dt_prop) { + return false; + } + + bytes_written += writer.writeValueToArray(dt_prop->timestamp); + + return true; +} diff --git a/src/UESaveFile/Serialisers/DateTimePropertySerialiser.h b/src/UESaveFile/Serialisers/DateTimePropertySerialiser.h new file mode 100644 index 0000000..b0e43ac --- /dev/null +++ b/src/UESaveFile/Serialisers/DateTimePropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/DateTimeStructProperty.h" + +class DateTimePropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/EnumPropertySerialiser.cpp b/src/UESaveFile/Serialisers/EnumPropertySerialiser.cpp new file mode 100644 index 0000000..cd7364c --- /dev/null +++ b/src/UESaveFile/Serialisers/EnumPropertySerialiser.cpp @@ -0,0 +1,62 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "EnumPropertySerialiser.h" + +auto EnumPropertySerialiser::types() -> Containers::ArrayView { + static const Containers::Array types{InPlaceInit, {"EnumProperty"}}; + return types; +} + +auto EnumPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readUEString(prop->enumType)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + if(!reader.readUEString(prop->value)) { + return nullptr; + } + + return prop; +} + +auto EnumPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto enum_prop = dynamic_cast(prop.get()); + + if(!enum_prop) { + return false; + } + + writer.writeUEStringToArray(enum_prop->enumType); + writer.writeValueToArray('\0'); + bytes_written += writer.writeUEStringToArray(enum_prop->value); + + return true; +} diff --git a/src/UESaveFile/Serialisers/EnumPropertySerialiser.h b/src/UESaveFile/Serialisers/EnumPropertySerialiser.h new file mode 100644 index 0000000..ab4335f --- /dev/null +++ b/src/UESaveFile/Serialisers/EnumPropertySerialiser.h @@ -0,0 +1,32 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "AbstractUnrealPropertySerialiser.h" + +#include "../Types/EnumProperty.h" + +class EnumPropertySerialiser : public AbstractUnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + auto types() -> Containers::ArrayView override; + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/FloatPropertySerialiser.cpp b/src/UESaveFile/Serialisers/FloatPropertySerialiser.cpp new file mode 100644 index 0000000..c13a72e --- /dev/null +++ b/src/UESaveFile/Serialisers/FloatPropertySerialiser.cpp @@ -0,0 +1,57 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "FloatPropertySerialiser.h" + +auto FloatPropertySerialiser::types() -> Containers::ArrayView { + static const Containers::Array types{InPlaceInit, {"FloatProperty"}}; + return types; +} + +auto FloatPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + if(!reader.readFloat(prop->value)) { + return nullptr; + } + + return prop; +} + +auto FloatPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto float_prop = dynamic_cast(prop.get()); + + if(!float_prop) { + return false; + } + + writer.writeValueToArray('\0'); + bytes_written += writer.writeValueToArray(float_prop->value); + + return true; +} diff --git a/src/UESaveFile/Serialisers/FloatPropertySerialiser.h b/src/UESaveFile/Serialisers/FloatPropertySerialiser.h new file mode 100644 index 0000000..c4e45ab --- /dev/null +++ b/src/UESaveFile/Serialisers/FloatPropertySerialiser.h @@ -0,0 +1,32 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "AbstractUnrealPropertySerialiser.h" + +#include "../Types/FloatProperty.h" + +class FloatPropertySerialiser : public AbstractUnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + auto types() -> Containers::ArrayView override; + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/GuidPropertySerialiser.cpp b/src/UESaveFile/Serialisers/GuidPropertySerialiser.cpp new file mode 100644 index 0000000..9fe235b --- /dev/null +++ b/src/UESaveFile/Serialisers/GuidPropertySerialiser.cpp @@ -0,0 +1,47 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "GuidPropertySerialiser.h" + +auto GuidPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readStaticArray(prop->guid)) { + Utility::Error{} << "Couldn't read guid in" << __func__; + return nullptr; + } + + return prop; +} + +auto GuidPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto guid_prop = dynamic_cast(prop.get()); + + if(!guid_prop) { + return false; + } + + bytes_written += writer.writeDataToArray({guid_prop->guid.data(), guid_prop->guid.size()}); + + return true; +} diff --git a/src/UESaveFile/Serialisers/GuidPropertySerialiser.h b/src/UESaveFile/Serialisers/GuidPropertySerialiser.h new file mode 100644 index 0000000..7dd1d67 --- /dev/null +++ b/src/UESaveFile/Serialisers/GuidPropertySerialiser.h @@ -0,0 +1,31 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/GuidStructProperty.h" + +class GuidPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/IntPropertySerialiser.cpp b/src/UESaveFile/Serialisers/IntPropertySerialiser.cpp new file mode 100644 index 0000000..5c70d45 --- /dev/null +++ b/src/UESaveFile/Serialisers/IntPropertySerialiser.cpp @@ -0,0 +1,66 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "IntPropertySerialiser.h" + +auto IntPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(value_length == UnsignedLong(-1)) { + if(!reader.readInt(prop->value)) { + return nullptr; + } + + prop->valueLength = UnsignedLong(-1); + return prop; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + if(!reader.readInt(prop->value)) { + return nullptr; + } + + prop->name.emplace(name); + + return prop; +} + +auto IntPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto int_prop = dynamic_cast(prop.get()); + + if(!int_prop) { + return false; + } + + if(prop->valueLength != UnsignedLong(-1)) { + writer.writeValueToArray('\0'); + } + + bytes_written += writer.writeValueToArray(int_prop->value); + + return true; +} diff --git a/src/UESaveFile/Serialisers/IntPropertySerialiser.h b/src/UESaveFile/Serialisers/IntPropertySerialiser.h new file mode 100644 index 0000000..8274299 --- /dev/null +++ b/src/UESaveFile/Serialisers/IntPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/IntProperty.h" + +class IntPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/MapPropertySerialiser.cpp b/src/UESaveFile/Serialisers/MapPropertySerialiser.cpp new file mode 100644 index 0000000..27b721d --- /dev/null +++ b/src/UESaveFile/Serialisers/MapPropertySerialiser.cpp @@ -0,0 +1,124 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" +#include "../PropertySerialiser.h" + +#include "../Types/NoneProperty.h" + +#include "MapPropertySerialiser.h" + +auto MapPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readUEString(prop->keyType)) { + return nullptr; + } + + if(!reader.readUEString(prop->valueType)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + UnsignedInt null; + if(!reader.readUnsignedInt(null) || null != 0u) { + return nullptr; + } + + UnsignedInt count; + if(!reader.readUnsignedInt(count)) { + return nullptr; + } + + // Begin dirty code because the MapProperty format doesn't seem to match any of the GVAS reading stuff I've found, + // so I'm just gonna write stuff that matches the only MapProperty I can find in MB's save files. + + arrayReserve(prop->map, count); + + for(UnsignedInt i = 0; i < count; i++) { + MapProperty::KeyValuePair pair; + + if(prop->keyType == "IntProperty") { + pair.key = serialiser.readItem(reader, prop->keyType, -1, name); + if(pair.key == nullptr) { + return nullptr; + } + } + else { // Add other branches depending on key type, should more maps appear in the future. + return nullptr; + } + + UnrealPropertyBase::ptr value_item; + while((value_item = serialiser.read(reader)) != nullptr) { + arrayAppend(pair.values, std::move(value_item)); + + if(pair.values.back()->name == "None" && + pair.values.back()->propertyType == "NoneProperty" && + dynamic_cast(pair.values.back().get()) != nullptr) + { + break; + } + } + + arrayAppend(prop->map, std::move(pair)); + } + + // End dirty code + + return prop; +} + +auto MapPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto map_prop = dynamic_cast(prop.get()); + if(!map_prop) { + return false; + } + + writer.writeUEStringToArray(map_prop->keyType); + writer.writeUEStringToArray(map_prop->valueType); + writer.writeValueToArray('\0'); + + UnsignedLong value_start = writer.arrayPosition(); + writer.writeValueToArray(0u); + + writer.writeValueToArray(UnsignedInt(map_prop->map.size())); + + UnsignedLong dummy_bytes_written = 0; + for(auto& pair : map_prop->map) { + if(!serialiser.writeItem(pair.key, map_prop->keyType, dummy_bytes_written, writer)) { + return false; + } + + for(auto& value : pair.values) { + if(!serialiser.write(value, dummy_bytes_written, writer)) { + return false; + } + } + } + + bytes_written += (writer.arrayPosition() - value_start); + + return true; +} diff --git a/src/UESaveFile/Serialisers/MapPropertySerialiser.h b/src/UESaveFile/Serialisers/MapPropertySerialiser.h new file mode 100644 index 0000000..aba537b --- /dev/null +++ b/src/UESaveFile/Serialisers/MapPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/MapProperty.h" + +class MapPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/RotatorPropertySerialiser.cpp b/src/UESaveFile/Serialisers/RotatorPropertySerialiser.cpp new file mode 100644 index 0000000..4be77bf --- /dev/null +++ b/src/UESaveFile/Serialisers/RotatorPropertySerialiser.cpp @@ -0,0 +1,47 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "RotatorPropertySerialiser.h" + +auto RotatorPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) { + return nullptr; + } + + return prop; +} + +auto RotatorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto rotator = dynamic_cast(prop.get()); + + if(!rotator) { + return false; + } + + bytes_written += writer.writeValueToArray(rotator->x) + writer.writeValueToArray(rotator->y) + + writer.writeValueToArray(rotator->z); + + return true; +} diff --git a/src/UESaveFile/Serialisers/RotatorPropertySerialiser.h b/src/UESaveFile/Serialisers/RotatorPropertySerialiser.h new file mode 100644 index 0000000..9a7192e --- /dev/null +++ b/src/UESaveFile/Serialisers/RotatorPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/RotatorStructProperty.h" + +class RotatorPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/SetPropertySerialiser.cpp b/src/UESaveFile/Serialisers/SetPropertySerialiser.cpp new file mode 100644 index 0000000..7b81683 --- /dev/null +++ b/src/UESaveFile/Serialisers/SetPropertySerialiser.cpp @@ -0,0 +1,73 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" +#include "../PropertySerialiser.h" + +#include "SetPropertySerialiser.h" + +auto SetPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + std::string item_type; + if(!reader.readUEString(item_type)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + UnsignedInt four_bytes; + if(!reader.readUnsignedInt(four_bytes) || four_bytes != 0u) { + return nullptr; + } + + UnsignedInt item_count; + if(!reader.readUnsignedInt(item_count)) { + return nullptr; + } + + auto prop = Containers::pointer(); + prop->itemType = std::move(item_type); + prop->items = serialiser.readSet(reader, prop->itemType, item_count); + + return prop; +} + +auto SetPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto set_prop = dynamic_cast(prop.get()); + if(!set_prop) { + return false; + } + + writer.writeUEStringToArray(set_prop->itemType); + writer.writeValueToArray('\0'); + + bytes_written += writer.writeValueToArray(0u); + bytes_written += writer.writeValueToArray(UnsignedInt(set_prop->items.size())); + + UnsignedLong start_pos = writer.arrayPosition(); + UnsignedLong dummy_bytes_written = 0; + serialiser.writeSet(set_prop->items, set_prop->itemType, dummy_bytes_written, writer); + bytes_written += writer.arrayPosition() - start_pos; + + return true; +} diff --git a/src/UESaveFile/Serialisers/SetPropertySerialiser.h b/src/UESaveFile/Serialisers/SetPropertySerialiser.h new file mode 100644 index 0000000..a19f560 --- /dev/null +++ b/src/UESaveFile/Serialisers/SetPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/SetProperty.h" + +class SetPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/StringPropertySerialiser.cpp b/src/UESaveFile/Serialisers/StringPropertySerialiser.cpp new file mode 100644 index 0000000..c455fd5 --- /dev/null +++ b/src/UESaveFile/Serialisers/StringPropertySerialiser.cpp @@ -0,0 +1,64 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "StringPropertySerialiser.h" + +auto StringPropertySerialiser::types() -> Containers::ArrayView { + static const Containers::Array types{InPlaceInit, {"NameProperty", "StrProperty", "SoftObjectProperty", "ObjectProperty"}}; + return types; +} + +auto StringPropertySerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(type); + + if(value_length != UnsignedLong(-1)) { + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + } + + if(!reader.readUEString(prop->value)) { + return nullptr; + } + + prop->valueLength = value_length; + + return prop; +} + +auto StringPropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto str_prop = dynamic_cast(prop.get()); + + if(!str_prop) { + return false; + } + + if(str_prop->valueLength != UnsignedLong(-1)) { + writer.writeValueToArray('\0'); + } + + bytes_written += writer.writeUEStringToArray(str_prop->value); + + return true; +} diff --git a/src/UESaveFile/Serialisers/StringPropertySerialiser.h b/src/UESaveFile/Serialisers/StringPropertySerialiser.h new file mode 100644 index 0000000..0c9e69b --- /dev/null +++ b/src/UESaveFile/Serialisers/StringPropertySerialiser.h @@ -0,0 +1,32 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "AbstractUnrealPropertySerialiser.h" + +#include "../Types/StringProperty.h" + +class StringPropertySerialiser : public AbstractUnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + auto types() -> Containers::ArrayView override; + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/StructSerialiser.cpp b/src/UESaveFile/Serialisers/StructSerialiser.cpp new file mode 100644 index 0000000..58d08d4 --- /dev/null +++ b/src/UESaveFile/Serialisers/StructSerialiser.cpp @@ -0,0 +1,210 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" +#include "../PropertySerialiser.h" + +#include "../Types/GenericStructProperty.h" +#include "../Types/NoneProperty.h" + +#include "StructSerialiser.h" + +auto StructSerialiser::types() -> Containers::ArrayView { + static const Containers::Array types{InPlaceInit, {"StructProperty"}}; + return types; +} + +auto StructSerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + UnsignedInt count, BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array +{ + std::string item_type; + if(!reader.readUEString(item_type)) { + return nullptr; + } + + Containers::StaticArray<16, char> guid{ValueInit}; + if(!reader.readStaticArray(guid)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + Containers::Array array; + + if(count == 0) { + auto prop = Containers::pointer(); + prop->structType = std::move(item_type); + prop->structGuid = std::move(guid); + } + else { + for(UnsignedInt i = 0; i < count; i++) { + auto prop = readStructValue(name, item_type, value_length, reader, serialiser); + + if(!prop) { + return nullptr; + } + + prop->structGuid = guid; + + arrayAppend(array, std::move(prop)); + } + } + + return array; +} + +auto StructSerialiser::deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + std::string item_type; + if(!reader.readUEString(item_type)) { + return nullptr; + } + + if(item_type == "None") { + return Containers::pointer(); + } + + Containers::StaticArray<16, char> guid{ValueInit}; + if(!reader.readStaticArray(guid)) { + return nullptr; + } + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + UnrealPropertyBase::ptr prop = serialiser.readItem(reader, item_type, value_length, name); + + if(!prop) { + prop = readStructValue(name, item_type, value_length, reader, serialiser); + if(prop) { + dynamic_cast(prop.get())->structGuid = std::move(guid); + } + } + + return prop; +} + +auto StructSerialiser::serialise(Containers::ArrayView props, const std::string& item_type, + UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + bytes_written += writer.writeUEStringToArray(*(props.front()->name)); + bytes_written += writer.writeUEStringToArray(item_type); + UnsignedLong vl_pos = writer.arrayPosition(); + bytes_written += writer.writeValueToArray(0ull); + + auto struct_prop = dynamic_cast(props.front().get()); + if(!struct_prop) { + return false; + } + + bytes_written += writer.writeUEStringToArray(struct_prop->structType); + bytes_written += writer.writeDataToArray(arrayView(struct_prop->structGuid)); + bytes_written += writer.writeValueToArray('\0'); + + UnsignedLong vl_start = writer.arrayPosition(); + + UnsignedLong bytes_written_here = 0; + for(auto& prop : props) { + struct_prop = dynamic_cast(prop.get()); + + if(!struct_prop) { + return false; + } + + if(!writeStructValue(struct_prop, bytes_written_here, writer, serialiser)) { + return false; + } + } + + UnsignedLong vl_stop = writer.arrayPosition() - vl_start; + writer.writeValueToArrayAt(vl_stop, vl_pos); + bytes_written += vl_stop; + + return true; +} + +auto StructSerialiser::serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto struct_prop = dynamic_cast(prop.get()); + + if(!struct_prop) { + return false; + } + + writer.writeUEStringToArray(struct_prop->structType); + writer.writeDataToArray(arrayView(struct_prop->structGuid)); + writer.writeValueToArray('\0'); + + if(!serialiser.writeItem(prop, struct_prop->structType, bytes_written, writer)) { + UnsignedLong dummy_bytes_written = 0; + UnsignedLong vl_start = writer.arrayPosition(); + if(!writeStructValue(struct_prop, dummy_bytes_written, writer, serialiser)) { + return false; + } + bytes_written += writer.arrayPosition() - vl_start; + } + + return true; +} + +auto StructSerialiser::readStructValue(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> StructProperty::ptr +{ + auto st_prop = Containers::pointer(); + st_prop->structType = type; + + UnrealPropertyBase::ptr prop; + while((prop = serialiser.read(reader)) != nullptr) { + arrayAppend(st_prop->properties, std::move(prop)); + + if(st_prop->properties.back()->name == "None" && + st_prop->properties.back()->propertyType == "NoneProperty" && + dynamic_cast(st_prop->properties.back().get()) != nullptr) + { + break; + } + } + + st_prop->name.emplace(name); + + return st_prop; +} + +auto StructSerialiser::writeStructValue(StructProperty* prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto struct_prop = dynamic_cast(prop); + + if(!struct_prop) { + return false; + } + + for(auto& item : struct_prop->properties) { + if(!serialiser.write(item, bytes_written, writer)) { + return false; + } + } + + return true; +} diff --git a/src/UESaveFile/Serialisers/StructSerialiser.h b/src/UESaveFile/Serialisers/StructSerialiser.h new file mode 100644 index 0000000..e219360 --- /dev/null +++ b/src/UESaveFile/Serialisers/StructSerialiser.h @@ -0,0 +1,45 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "AbstractUnrealCollectionPropertySerialiser.h" +#include "AbstractUnrealPropertySerialiser.h" +#include "AbstractUnrealStructSerialiser.h" + +#include "../Types/StructProperty.h" + +class StructSerialiser : public AbstractUnrealPropertySerialiser, public AbstractUnrealCollectionPropertySerialiser { + public: + using ptr = Containers::Pointer; + + auto types() -> Containers::ArrayView override; + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, UnsignedInt count, + BinaryReader& reader, PropertySerialiser& serialiser) -> Containers::Array override; + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + + auto serialise(Containers::ArrayView props, const std::string& item_type, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; + + private: + auto readStructValue(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> StructProperty::ptr; + auto writeStructValue(StructProperty* prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool; +}; diff --git a/src/UESaveFile/Serialisers/TextPropertySerialiser.cpp b/src/UESaveFile/Serialisers/TextPropertySerialiser.cpp new file mode 100644 index 0000000..72a0f54 --- /dev/null +++ b/src/UESaveFile/Serialisers/TextPropertySerialiser.cpp @@ -0,0 +1,84 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "TextPropertySerialiser.h" + +auto TextPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + Long start_position = reader.position(); + + char terminator; + if(!reader.readChar(terminator) || terminator != '\0') { + return nullptr; + } + + if(reader.peekChar() > 0) { + if(!reader.readArray(prop->flags, 8)) { + return nullptr; + } + } + else { + if(!reader.readArray(prop->flags, 4)) { + return nullptr; + } + } + + if(!reader.readChar(prop->id)) { + return nullptr; + } + + auto interval = reader.position() - start_position; + + do { + std::string str; + + if(!reader.readUEString(str)) { + return nullptr; + } + + arrayAppend(prop->data, std::move(str)); + + interval = reader.position() - start_position; + } while(UnsignedLong(interval) < value_length); + + prop->value = prop->data.back(); + + return prop; +} + +auto TextPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto text_prop = dynamic_cast(prop.get()); + + if(!text_prop) { + return false; + } + + writer.writeValueToArray('\0'); + bytes_written += writer.writeDataToArray(text_prop->flags); + for(const auto& str : text_prop->data) { + bytes_written += writer.writeUEStringToArray(str); + } + + return true; +} diff --git a/src/UESaveFile/Serialisers/TextPropertySerialiser.h b/src/UESaveFile/Serialisers/TextPropertySerialiser.h new file mode 100644 index 0000000..3b99676 --- /dev/null +++ b/src/UESaveFile/Serialisers/TextPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/TextProperty.h" + +class TextPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/UnrealPropertySerialiser.h b/src/UESaveFile/Serialisers/UnrealPropertySerialiser.h new file mode 100644 index 0000000..0364908 --- /dev/null +++ b/src/UESaveFile/Serialisers/UnrealPropertySerialiser.h @@ -0,0 +1,58 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "AbstractUnrealPropertySerialiser.h" +#include "../Types/StructProperty.h" + +template +class UnrealPropertySerialiser : public AbstractUnrealPropertySerialiser { + static_assert(std::is_base_of::value, "T must be derived from UnrealPropertyBase."); + + public: + using ptr = Containers::Pointer>; + + auto types() -> Containers::ArrayView override { + static const Containers::Array types = []{ + Containers::Array array; + Containers::Pointer p(new T); + if(std::is_base_of::value) { + array = Containers::Array{InPlaceInit, {dynamic_cast(p.get())->structType}}; + } + else { + array = Containers::Array{InPlaceInit, {p->propertyType}}; + } + return array; + }(); + return types; + } + + auto deserialise(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override { + return deserialiseProperty(name, type, value_length, reader, serialiser); + } + + auto serialise(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override { + return serialiseProperty(prop, bytes_written, writer, serialiser); + } + + private: + virtual auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> typename UnrealPropertyBase::ptr = 0; + + virtual auto serialiseProperty(typename UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool = 0; +}; diff --git a/src/UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp b/src/UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp new file mode 100644 index 0000000..f272d6f --- /dev/null +++ b/src/UESaveFile/Serialisers/Vector2DPropertySerialiser.cpp @@ -0,0 +1,46 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "Vector2DPropertySerialiser.h" + +auto Vector2DPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y)) { + return nullptr; + } + + return prop; +} + +auto Vector2DPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto vector = dynamic_cast(prop.get()); + + if(!vector) { + return false; + } + + bytes_written += writer.writeValueToArray(vector->x) + writer.writeValueToArray(vector->y); + + return true; +} diff --git a/src/UESaveFile/Serialisers/Vector2DPropertySerialiser.h b/src/UESaveFile/Serialisers/Vector2DPropertySerialiser.h new file mode 100644 index 0000000..c754bda --- /dev/null +++ b/src/UESaveFile/Serialisers/Vector2DPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/Vector2DStructProperty.h" + +class Vector2DPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Serialisers/VectorPropertySerialiser.cpp b/src/UESaveFile/Serialisers/VectorPropertySerialiser.cpp new file mode 100644 index 0000000..feaa803 --- /dev/null +++ b/src/UESaveFile/Serialisers/VectorPropertySerialiser.cpp @@ -0,0 +1,47 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "../BinaryReader.h" +#include "../BinaryWriter.h" + +#include "VectorPropertySerialiser.h" + +auto VectorPropertySerialiser::deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, + BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr +{ + auto prop = Containers::pointer(); + + if(!reader.readFloat(prop->x) || !reader.readFloat(prop->y) || !reader.readFloat(prop->z)) { + return nullptr; + } + + return prop; +} + +auto VectorPropertySerialiser::serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, + BinaryWriter& writer, PropertySerialiser& serialiser) -> bool +{ + auto vector = dynamic_cast(prop.get()); + + if(!vector) { + return false; + } + + bytes_written += writer.writeValueToArray(vector->x) + writer.writeValueToArray(vector->y) + + writer.writeValueToArray(vector->z); + + return true; +} diff --git a/src/UESaveFile/Serialisers/VectorPropertySerialiser.h b/src/UESaveFile/Serialisers/VectorPropertySerialiser.h new file mode 100644 index 0000000..3afb0dc --- /dev/null +++ b/src/UESaveFile/Serialisers/VectorPropertySerialiser.h @@ -0,0 +1,30 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertySerialiser.h" + +#include "../Types/VectorStructProperty.h" + +class VectorPropertySerialiser : public UnrealPropertySerialiser { + public: + using ptr = Containers::Pointer; + + private: + auto deserialiseProperty(const std::string& name, const std::string& type, UnsignedLong value_length, BinaryReader& reader, PropertySerialiser& serialiser) -> UnrealPropertyBase::ptr override; + auto serialiseProperty(UnrealPropertyBase::ptr& prop, UnsignedLong& bytes_written, BinaryWriter& writer, PropertySerialiser& serialiser) -> bool override; +}; diff --git a/src/UESaveFile/Types/ArrayProperty.h b/src/UESaveFile/Types/ArrayProperty.h new file mode 100644 index 0000000..b01a9ba --- /dev/null +++ b/src/UESaveFile/Types/ArrayProperty.h @@ -0,0 +1,40 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "UnrealPropertyBase.h" + +struct ArrayProperty : public UnrealPropertyBase { + using ptr = Containers::Pointer; + + ArrayProperty() { + propertyType = "ArrayProperty"; + } + + auto at(std::size_t index) -> UnrealPropertyBase* { + if(index >= items.size()) { + return nullptr; + } + + return items[index].get(); + } + + std::string itemType; + Containers::Array items; +}; diff --git a/src/UESaveFile/Types/BoolProperty.h b/src/UESaveFile/Types/BoolProperty.h new file mode 100644 index 0000000..f80a3b9 --- /dev/null +++ b/src/UESaveFile/Types/BoolProperty.h @@ -0,0 +1,27 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealProperty.h" + +struct BoolProperty : public UnrealProperty { + using ptr = Containers::Pointer; + + BoolProperty() { + propertyType = "BoolProperty"; + } +}; diff --git a/src/UESaveFile/Types/ByteProperty.h b/src/UESaveFile/Types/ByteProperty.h new file mode 100644 index 0000000..8587d2e --- /dev/null +++ b/src/UESaveFile/Types/ByteProperty.h @@ -0,0 +1,33 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "UnrealProperty.h" + +struct ByteProperty : public UnrealProperty> { + using ptr = Containers::Pointer; + + ByteProperty() { + propertyType = "ByteProperty"; + } + + // For some reason, M.A.S.S. Builder stores EnumProperties as ByteProperties. Ugh... + std::string enumType; + std::string enumValue; +}; diff --git a/src/UESaveFile/Types/ColourStructProperty.h b/src/UESaveFile/Types/ColourStructProperty.h new file mode 100644 index 0000000..6df355d --- /dev/null +++ b/src/UESaveFile/Types/ColourStructProperty.h @@ -0,0 +1,27 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "StructProperty.h" + +struct ColourStructProperty : public StructProperty { + using ptr = Containers::Pointer; + ColourStructProperty() { + structType = "LinearColor"; + } + Float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f; +}; diff --git a/src/UESaveFile/Types/DateTimeStructProperty.h b/src/UESaveFile/Types/DateTimeStructProperty.h new file mode 100644 index 0000000..86da227 --- /dev/null +++ b/src/UESaveFile/Types/DateTimeStructProperty.h @@ -0,0 +1,29 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "StructProperty.h" + +struct DateTimeStructProperty : public StructProperty { + using ptr = Containers::Pointer; + + DateTimeStructProperty() { + structType = "DateTime"; + } + + UnsignedLong timestamp = 0; +}; diff --git a/src/UESaveFile/Types/EnumProperty.h b/src/UESaveFile/Types/EnumProperty.h new file mode 100644 index 0000000..e9418af --- /dev/null +++ b/src/UESaveFile/Types/EnumProperty.h @@ -0,0 +1,29 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealProperty.h" + +struct EnumProperty : public UnrealProperty { + using ptr = Containers::Pointer; + + EnumProperty() { + propertyType = "EnumProperty"; + } + + std::string enumType; +}; diff --git a/src/UESaveFile/Types/FloatProperty.h b/src/UESaveFile/Types/FloatProperty.h new file mode 100644 index 0000000..1594959 --- /dev/null +++ b/src/UESaveFile/Types/FloatProperty.h @@ -0,0 +1,27 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealProperty.h" + +struct FloatProperty : public UnrealProperty { + using ptr = Containers::Pointer; + + FloatProperty() { + propertyType = "FloatProperty"; + } +}; diff --git a/src/UESaveFile/Types/GenericStructProperty.h b/src/UESaveFile/Types/GenericStructProperty.h new file mode 100644 index 0000000..93b6b88 --- /dev/null +++ b/src/UESaveFile/Types/GenericStructProperty.h @@ -0,0 +1,43 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include + +#include "StructProperty.h" + +struct GenericStructProperty : public StructProperty { + using ptr = Containers::Pointer; + + template + auto at(const std::string& name) -> T* { + for(auto& item : properties) { + if(item->name == name) { + return static_cast(item.get()); + } + } + return nullptr; + } + + auto props() -> Containers::ArrayView { + return properties; + } + + Containers::Array properties; +}; diff --git a/src/UESaveFile/Types/GuidStructProperty.h b/src/UESaveFile/Types/GuidStructProperty.h new file mode 100644 index 0000000..e5a88dc --- /dev/null +++ b/src/UESaveFile/Types/GuidStructProperty.h @@ -0,0 +1,31 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "StructProperty.h" + +struct GuidStructProperty : public StructProperty { + using ptr = Containers::Pointer; + + GuidStructProperty() { + structType = "Guid"; + } + + Containers::StaticArray<16, char> guid{ValueInit}; +}; diff --git a/src/UESaveFile/Types/IntProperty.h b/src/UESaveFile/Types/IntProperty.h new file mode 100644 index 0000000..d03f77b --- /dev/null +++ b/src/UESaveFile/Types/IntProperty.h @@ -0,0 +1,27 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealProperty.h" + +struct IntProperty : public UnrealProperty { + using ptr = Containers::Pointer; + + IntProperty() { + propertyType = "IntProperty"; + } +}; diff --git a/src/UESaveFile/Types/MapProperty.h b/src/UESaveFile/Types/MapProperty.h new file mode 100644 index 0000000..3f8768b --- /dev/null +++ b/src/UESaveFile/Types/MapProperty.h @@ -0,0 +1,37 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertyBase.h" + +struct MapProperty : public UnrealPropertyBase { + using ptr = Containers::Pointer; + + MapProperty() { + propertyType = "MapProperty"; + } + + std::string keyType; + std::string valueType; + + struct KeyValuePair { + UnrealPropertyBase::ptr key; + Containers::Array values; + }; + + Containers::Array map; +}; diff --git a/src/UESaveFile/Types/NoneProperty.h b/src/UESaveFile/Types/NoneProperty.h new file mode 100644 index 0000000..e52ec61 --- /dev/null +++ b/src/UESaveFile/Types/NoneProperty.h @@ -0,0 +1,28 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertyBase.h" + +struct NoneProperty : UnrealPropertyBase { + using ptr = Containers::Pointer; + + NoneProperty() { + name.emplace("None"); + propertyType = "NoneProperty"; + } +}; diff --git a/src/UESaveFile/Types/RotatorStructProperty.h b/src/UESaveFile/Types/RotatorStructProperty.h new file mode 100644 index 0000000..89add8b --- /dev/null +++ b/src/UESaveFile/Types/RotatorStructProperty.h @@ -0,0 +1,29 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "StructProperty.h" + +struct RotatorStructProperty : public StructProperty { + using ptr = Containers::Pointer; + + RotatorStructProperty() { + structType = "Rotator"; + } + + Float x = 0.0f, y = 0.0f, z = 0.0f; +}; diff --git a/src/UESaveFile/Types/SetProperty.h b/src/UESaveFile/Types/SetProperty.h new file mode 100644 index 0000000..b426dc6 --- /dev/null +++ b/src/UESaveFile/Types/SetProperty.h @@ -0,0 +1,40 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "UnrealPropertyBase.h" + +struct SetProperty : public UnrealPropertyBase { + using ptr = Containers::Pointer; + + SetProperty() { + propertyType = "SetProperty"; + } + + auto at(std::size_t index) -> UnrealPropertyBase* { + if(index >= items.size()) { + return nullptr; + } + + return items[index].get(); + } + + std::string itemType; + Containers::Array items; +}; diff --git a/src/UESaveFile/Types/StringProperty.h b/src/UESaveFile/Types/StringProperty.h new file mode 100644 index 0000000..07463ac --- /dev/null +++ b/src/UESaveFile/Types/StringProperty.h @@ -0,0 +1,27 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealProperty.h" + +struct StringProperty : public UnrealProperty { + using ptr = Containers::Pointer; + + explicit StringProperty(const std::string& type = "StrProperty") { + propertyType = type; + } +}; diff --git a/src/UESaveFile/Types/StructProperty.h b/src/UESaveFile/Types/StructProperty.h new file mode 100644 index 0000000..80b9efc --- /dev/null +++ b/src/UESaveFile/Types/StructProperty.h @@ -0,0 +1,32 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include "UnrealPropertyBase.h" + +struct StructProperty : public UnrealPropertyBase { + using ptr = Containers::Pointer; + + StructProperty() { + std::string propertyType = "StructProperty"; + } + + Containers::StaticArray<16, char> structGuid{ValueInit}; + std::string structType; +}; diff --git a/src/UESaveFile/Types/TextProperty.h b/src/UESaveFile/Types/TextProperty.h new file mode 100644 index 0000000..46bd99e --- /dev/null +++ b/src/UESaveFile/Types/TextProperty.h @@ -0,0 +1,31 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealProperty.h" + +struct TextProperty : public UnrealProperty { + using ptr = Containers::Pointer; + + TextProperty() { + propertyType = "TextProperty"; + } + + Containers::Array flags; + char id = 0; + Containers::Array data; +}; diff --git a/src/UESaveFile/Types/UnrealProperty.h b/src/UESaveFile/Types/UnrealProperty.h new file mode 100644 index 0000000..08290fe --- /dev/null +++ b/src/UESaveFile/Types/UnrealProperty.h @@ -0,0 +1,26 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "UnrealPropertyBase.h" + +template +struct UnrealProperty : public UnrealPropertyBase { + using ptr = Containers::Pointer>; + + T value; +}; diff --git a/src/UESaveFile/Types/UnrealPropertyBase.h b/src/UESaveFile/Types/UnrealPropertyBase.h new file mode 100644 index 0000000..9165e5f --- /dev/null +++ b/src/UESaveFile/Types/UnrealPropertyBase.h @@ -0,0 +1,37 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include + +#include + +using namespace Corrade; +using namespace Magnum; + +struct UnrealPropertyBase { + using ptr = Containers::Pointer; + + virtual ~UnrealPropertyBase() = default; + + Containers::Optional name = Containers::NullOpt; + std::string propertyType; + UnsignedLong valueLength; +}; diff --git a/src/UESaveFile/Types/Vector2DStructProperty.h b/src/UESaveFile/Types/Vector2DStructProperty.h new file mode 100644 index 0000000..1795b05 --- /dev/null +++ b/src/UESaveFile/Types/Vector2DStructProperty.h @@ -0,0 +1,29 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "StructProperty.h" + +struct Vector2DStructProperty : public StructProperty { + using ptr = Containers::Pointer; + + Vector2DStructProperty() { + structType = "Vector2D"; + } + + Float x = 0.0f, y = 0.0f; +}; diff --git a/src/UESaveFile/Types/VectorStructProperty.h b/src/UESaveFile/Types/VectorStructProperty.h new file mode 100644 index 0000000..529522e --- /dev/null +++ b/src/UESaveFile/Types/VectorStructProperty.h @@ -0,0 +1,29 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include "StructProperty.h" + +struct VectorStructProperty : public StructProperty { + using ptr = Containers::Pointer; + + VectorStructProperty() { + structType = "Vector"; + } + + Float x = 0.0f, y = 0.0f, z = 0.0f; +}; diff --git a/src/UESaveFile/UESaveFile.cpp b/src/UESaveFile/UESaveFile.cpp new file mode 100644 index 0000000..e1c4790 --- /dev/null +++ b/src/UESaveFile/UESaveFile.cpp @@ -0,0 +1,189 @@ +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include +#include +#include + +#include "BinaryReader.h" +#include "BinaryWriter.h" + +#include "UESaveFile.h" + +UESaveFile::UESaveFile(std::string filepath) +{ + _filepath = std::move(filepath); + + loadData(); +} + +auto UESaveFile::valid() const -> bool { + return _valid; +} + +auto UESaveFile::lastError() const -> const std::string& { + return _lastError; +} + +auto UESaveFile::reloadData() -> bool { + loadData(); + return valid(); +} + +auto UESaveFile::at(const std::string& name) -> UnrealPropertyBase* { + for(auto& prop : _properties) { + if(*(prop->name) == name) { + return prop.get(); + } + } + return nullptr; +} + +auto UESaveFile::props() -> Containers::ArrayView { + return _properties; +} + +auto UESaveFile::saveToFile() -> bool { + BinaryWriter writer{_filepath + ".other"}; + + if(!writer.open()) { + return false; + } + + if(!writer.writeStaticArray(staticArrayView(_magicBytes)) || + !writer.writeUnsignedInt(_saveVersion) || + !writer.writeUnsignedInt(_packageVersion) || + !writer.writeUnsignedShort(_engineVersion.major) || + !writer.writeUnsignedShort(_engineVersion.minor) || + !writer.writeUnsignedShort(_engineVersion.patch) || + !writer.writeUnsignedInt(_engineVersion.build) || + !writer.writeUEString(_engineVersion.buildId)) + { + return false; + } + + if(!writer.writeUnsignedInt(_customFormatVersion) || + !writer.writeUnsignedInt(_customFormatData.size())) + { + return false; + } + + for(UnsignedLong i = 0; i < _customFormatData.size(); i++) { + if(!writer.writeStaticArray(Containers::StaticArrayView<16, const char>{_customFormatData[i].id}) || + !writer.writeUnsignedInt(_customFormatData[i].value)) + { + return false; + } + } + + if(!writer.writeUEString(_saveType)) { + return false; + } + + for(auto& prop : _properties) { + UnsignedLong bytes_written = 0; + if(!_propSerialiser.write(prop, bytes_written, writer)) { + return false; + } + + if(!writer.flushToFile()) { + return false; + } + } + + writer.writeUnsignedInt(0); + + return true; +} + +void UESaveFile::loadData() { + _valid = false; + + if(!Utility::Directory::exists(_filepath)) { + return; + } + + BinaryReader reader{_filepath}; + + if(!reader.open()) { + _lastError = _filepath + " couldn't be opened."; + return; + } + + Containers::Array magic; + if(!reader.readArray(magic, 4)) { + _lastError = "Couldn't read magic bytes in " + _filepath; + return; + } + + std::string invalid = _filepath + " isn't a valid UE4 save."; + + if(std::strncmp(magic.data(), _magicBytes.data(), 4) != 0) { + _lastError = std::move(invalid); + return; + } + + if(!reader.readUnsignedInt(_saveVersion) || + !reader.readUnsignedInt(_packageVersion) || + !reader.readUnsignedShort(_engineVersion.major) || + !reader.readUnsignedShort(_engineVersion.minor) || + !reader.readUnsignedShort(_engineVersion.patch) || + !reader.readUnsignedInt(_engineVersion.build) || + !reader.readUEString(_engineVersion.buildId)) + { + _lastError = std::move(invalid); + return; + } + + if(!reader.readUnsignedInt(_customFormatVersion)) { + _lastError = std::move(invalid); + return; + } + + UnsignedInt custom_format_data_size = 0; + + if(!reader.readUnsignedInt(custom_format_data_size)) { + _lastError = std::move(invalid); + return; + } + + arrayReserve(_customFormatData, custom_format_data_size); + + for(UnsignedInt i = 0; i < custom_format_data_size; i++) { + CustomFormatDataEntry entry; + + if(!reader.readStaticArray(entry.id) || + !reader.readInt(entry.value)) + { + _lastError = std::move(invalid); + return; + } + + arrayAppend(_customFormatData, entry); + } + + if(!reader.readUEString(_saveType)) { + _lastError = std::move(invalid); + return; + } + + UnrealPropertyBase::ptr prop; + while((prop = _propSerialiser.read(reader)) != nullptr) { + arrayAppend(_properties, std::move(prop)); + } + + _valid = true; +} diff --git a/src/UESaveFile/UESaveFile.h b/src/UESaveFile/UESaveFile.h new file mode 100644 index 0000000..88e87cd --- /dev/null +++ b/src/UESaveFile/UESaveFile.h @@ -0,0 +1,81 @@ +#pragma once + +// MassBuilderSaveTool +// Copyright (C) 2021 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 . + +#include + +#include +#include +#include + +#include + +#include "Types/UnrealPropertyBase.h" + +#include "PropertySerialiser.h" + +using namespace Corrade; +using namespace Magnum; + +class UESaveFile { + public: + explicit UESaveFile(std::string filepath); + + auto valid() const -> bool; + auto lastError() const -> std::string const&; + + auto reloadData() -> bool; + + auto at(const std::string& name) -> UnrealPropertyBase*; + + auto props() -> Containers::ArrayView; + + auto saveToFile() -> bool; + + private: + void loadData(); + + bool _valid{false}; + std::string _lastError; + + std::string _filepath; + + const Containers::StaticArray<4, char> _magicBytes{'G', 'V', 'A', 'S'}; + + UnsignedInt _saveVersion = 0; + UnsignedInt _packageVersion = 0; + struct { + UnsignedShort major = 0; + UnsignedShort minor = 0; + UnsignedShort patch = 0; + UnsignedInt build = 0; + std::string buildId; + } _engineVersion; + + UnsignedInt _customFormatVersion = 0; + struct CustomFormatDataEntry { + Containers::StaticArray<16, char> id; + Int value = 0; + }; + Containers::Array _customFormatData; + + std::string _saveType; + + Containers::Array _properties; + + PropertySerialiser _propSerialiser; +};