2021-09-22 17:37:50 +02:00
|
|
|
// MassBuilderSaveTool
|
2022-01-30 11:36:56 +01:00
|
|
|
// Copyright (C) 2021-2022 Guillaume Jacquemin
|
2021-09-22 17:37:50 +02:00
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#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"
|
2021-09-23 15:09:02 +02:00
|
|
|
#include "Serialisers/ResourcePropertySerialiser.h"
|
2021-09-22 17:37:50 +02:00
|
|
|
#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"
|
|
|
|
|
2022-11-22 11:03:45 +01:00
|
|
|
#include "../Logger/Logger.h"
|
|
|
|
|
2021-09-22 17:37:50 +02:00
|
|
|
#include "PropertySerialiser.h"
|
|
|
|
|
|
|
|
PropertySerialiser::PropertySerialiser() {
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<ArrayPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<BoolPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<BytePropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<ColourPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<DateTimePropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<EnumPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<FloatPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<GuidPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<IntPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<MapPropertySerialiser>());
|
2021-09-23 15:09:02 +02:00
|
|
|
arrayAppend(_serialisers, Containers::pointer<ResourcePropertySerialiser>());
|
2021-09-22 17:37:50 +02:00
|
|
|
arrayAppend(_serialisers, Containers::pointer<RotatorPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<StringPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<SetPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<TextPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<VectorPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<Vector2DPropertySerialiser>());
|
|
|
|
arrayAppend(_serialisers, Containers::pointer<StructSerialiser>());
|
|
|
|
|
|
|
|
arrayAppend(_collectionSerialisers, Containers::pointer<StructSerialiser>());
|
|
|
|
}
|
|
|
|
|
2022-03-06 13:21:56 +01:00
|
|
|
auto PropertySerialiser::instance() -> PropertySerialiser& {
|
|
|
|
static PropertySerialiser serialiser;
|
|
|
|
return serialiser;
|
|
|
|
}
|
|
|
|
|
2021-09-22 17:37:50 +02:00
|
|
|
auto PropertySerialiser::read(BinaryReader& reader) -> UnrealPropertyBase::ptr {
|
|
|
|
if(reader.peekChar() < 0 || reader.eof()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
Containers::String name;
|
2021-09-22 17:37:50 +02:00
|
|
|
if(!reader.readUEString(name)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(name == "None") {
|
|
|
|
return Containers::pointer<NoneProperty>();
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
Containers::String type;
|
2021-09-22 17:37:50 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::readItem(BinaryReader& reader, Containers::String type, UnsignedLong value_length,
|
|
|
|
Containers::String name) -> UnrealPropertyBase::ptr {
|
2021-09-22 17:37:50 +02:00
|
|
|
if(reader.peekChar() < 0 || reader.eof()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return deserialise(std::move(name), std::move(type), value_length, reader);
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::readSet(BinaryReader& reader, Containers::StringView item_type,
|
|
|
|
UnsignedInt count) -> Containers::Array<UnrealPropertyBase::ptr>
|
|
|
|
{
|
2021-09-22 17:37:50 +02:00
|
|
|
if(reader.peekChar() < 0 || reader.eof()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto serialiser = getCollectionSerialiser(item_type);
|
|
|
|
|
|
|
|
Containers::Array<UnrealPropertyBase::ptr> array;
|
|
|
|
|
|
|
|
if(serialiser) {
|
2022-03-04 21:18:55 +01:00
|
|
|
Containers::String name;
|
2021-09-22 17:37:50 +02:00
|
|
|
if(!reader.readUEString(name)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
Containers::String type;
|
2021-09-22 17:37:50 +02:00
|
|
|
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++) {
|
2021-09-22 18:25:15 +02:00
|
|
|
auto item = readItem(reader, item_type, UnsignedLong(-1), "");
|
2021-09-22 17:37:50 +02:00
|
|
|
arrayAppend(array, std::move(item));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::deserialise(Containers::String name, Containers::String type, UnsignedLong value_length,
|
2021-09-22 17:37:50 +02:00
|
|
|
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) {
|
2022-11-22 11:03:45 +01:00
|
|
|
LOG_ERROR("No property.");
|
2021-09-22 17:37:50 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
prop->name = std::move(name);
|
|
|
|
prop->propertyType = std::move(type);
|
|
|
|
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::serialise(UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
|
|
|
|
UnsignedLong& bytes_written, BinaryWriter& writer) -> bool
|
2021-09-22 17:37:50 +02:00
|
|
|
{
|
|
|
|
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<NoneProperty*>(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<UnsignedLong>(value_length);
|
|
|
|
|
|
|
|
bool ret = serialise(prop, prop->propertyType, value_length, writer);
|
|
|
|
|
|
|
|
writer.writeValueToArrayAt(value_length, vl_position);
|
|
|
|
|
|
|
|
bytes_written += value_length;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::writeItem(UnrealPropertyBase::ptr& prop, Containers::StringView item_type,
|
2021-09-22 17:37:50 +02:00
|
|
|
UnsignedLong& bytes_written, BinaryWriter& writer) -> bool
|
|
|
|
{
|
|
|
|
if(prop->name == "None" && prop->propertyType == "NoneProperty" && dynamic_cast<NoneProperty*>(prop.get())) {
|
|
|
|
bytes_written += writer.writeUEStringToArray(*prop->name);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return serialise(prop, item_type, bytes_written, writer);
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::writeSet(Containers::ArrayView<UnrealPropertyBase::ptr> props,
|
|
|
|
Containers::StringView item_type, UnsignedLong& bytes_written,
|
|
|
|
BinaryWriter& writer) -> bool
|
2021-09-22 17:37:50 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::getSerialiser(Containers::StringView item_type) -> AbstractUnrealPropertySerialiser* {
|
2021-09-22 17:37:50 +02:00
|
|
|
for(auto& item : _serialisers) {
|
2022-03-06 13:21:56 +01:00
|
|
|
for(auto serialiser_type : item->types()) {
|
2021-09-22 17:37:50 +02:00
|
|
|
if(item_type == serialiser_type) {
|
|
|
|
return item.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-03-04 21:18:55 +01:00
|
|
|
auto PropertySerialiser::getCollectionSerialiser(Containers::StringView item_type) -> AbstractUnrealCollectionPropertySerialiser* {
|
2021-09-22 17:37:50 +02:00
|
|
|
for(auto& item : _collectionSerialisers) {
|
2022-03-04 21:18:55 +01:00
|
|
|
for(Containers::StringView serialiser_type : item->types()) {
|
2021-09-22 17:37:50 +02:00
|
|
|
if(item_type == serialiser_type) {
|
|
|
|
return item.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|