diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 89ba75849f..008aaebf9e 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -14,6 +14,7 @@ #include "../localisation/Localisation.h" #include "../network/NetworkTypes.h" #include "../network/network.h" +#include "../object/Object.h" #include "../ride/Ride.h" #include "../ride/TrackDesign.h" #include "../world/Location.hpp" @@ -730,3 +731,46 @@ template<> struct DataSerializerTraits_t stream->Write(msg, strlen(msg)); } }; + +template<> struct DataSerializerTraits_t +{ + static void encode(OpenRCT2::IStream* stream, const ObjectEntryDescriptor& val) + { + stream->Write(&val.Generation); + if (val.Generation == ObjectGeneration::DAT) + { + DataSerializerTraits s; + s.encode(stream, val.Entry); + } + else + { + DataSerializerTraits s; + s.encode(stream, val.Identifier); + } + } + static void decode(OpenRCT2::IStream* stream, ObjectEntryDescriptor& val) + { + ObjectGeneration generation; + stream->Read(&generation); + if (generation == ObjectGeneration::DAT) + { + rct_object_entry obj; + DataSerializerTraits s; + s.decode(stream, obj); + val = ObjectEntryDescriptor(obj); + } + else + { + std::string id; + DataSerializerTraits s; + s.decode(stream, id); + val = ObjectEntryDescriptor(id); + } + } + static void log(OpenRCT2::IStream* stream, const ObjectEntryDescriptor& val) + { + char msg[128] = {}; + snprintf(msg, sizeof(msg), "ObjectEntryDescriptor (Generation = %d)", static_cast(val.Generation)); + stream->Write(msg, strlen(msg)); + } +}; diff --git a/src/openrct2/core/FileIndex.hpp b/src/openrct2/core/FileIndex.hpp index 25e244d749..6a6fab1fd8 100644 --- a/src/openrct2/core/FileIndex.hpp +++ b/src/openrct2/core/FileIndex.hpp @@ -276,7 +276,7 @@ private: for (uint32_t i = 0; i < header.NumItems; i++) { auto item = Deserialise(&fs); - items.push_back(item); + items.emplace_back(std::move(item)); } loadedItems = true; } @@ -291,7 +291,7 @@ private: Console::Error::WriteLine("%s", e.what()); } } - return std::make_tuple(loadedItems, items); + return std::make_tuple(loadedItems, std::move(items)); } void WriteIndexFile(int32_t language, const DirectoryStats& stats, const std::vector& items) const diff --git a/src/openrct2/core/IStream.cpp b/src/openrct2/core/IStream.cpp index 7f355d1413..88bf74d02e 100644 --- a/src/openrct2/core/IStream.cpp +++ b/src/openrct2/core/IStream.cpp @@ -61,23 +61,4 @@ namespace OpenRCT2 { WriteString(str.c_str()); } - - ObjectEntryDescriptor IStream::ReadObjectEntryDescriptor() - { - auto generation = ReadValue(); - if (generation == ObjectGeneration::DAT) - return ObjectEntryDescriptor(ReadValue()); - - return ObjectEntryDescriptor(ReadStdString()); - } - - void IStream::WriteObjectEntryDescriptor(const ObjectEntryDescriptor& oed) - { - WriteValue(oed.Generation); - if (oed.Generation == ObjectGeneration::DAT) - WriteValue(oed.Entry); - else - WriteString(oed.Identifier); - } - } // namespace OpenRCT2 diff --git a/src/openrct2/core/IStream.hpp b/src/openrct2/core/IStream.hpp index fc71319dc3..9cf5016fb2 100644 --- a/src/openrct2/core/IStream.hpp +++ b/src/openrct2/core/IStream.hpp @@ -207,8 +207,6 @@ namespace OpenRCT2 std::string ReadStdString(); void WriteString(const utf8* str); void WriteString(const std::string& string); - ObjectEntryDescriptor ReadObjectEntryDescriptor(); - void WriteObjectEntryDescriptor(const ObjectEntryDescriptor& oed); }; } // namespace OpenRCT2 diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index 47d5a48ab8..da2c60df47 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -15,8 +15,6 @@ #include "ImageTable.h" #include "StringTable.h" -#include -#include #include #include #include @@ -128,52 +126,6 @@ struct rct_object_entry_group assert_struct_size(rct_object_entry_group, 8); #endif -enum class ObjectGeneration : uint8_t -{ - DAT, - JSON, -}; - -struct ObjectEntryDescriptor -{ - ObjectGeneration Generation; - union - { - rct_object_entry Entry; // For DAT objects - char Identifier[64]; // For JSON objects - }; - - ObjectEntryDescriptor() = default; - - ObjectEntryDescriptor(const ObjectEntryDescriptor& entry) - { - *this = entry; - } - - explicit ObjectEntryDescriptor(const rct_object_entry& newEntry) - { - Generation = ObjectGeneration::DAT; - Entry = newEntry; - } - - explicit ObjectEntryDescriptor(std::string_view newIdentifier) - { - Generation = ObjectGeneration::JSON; - safe_strcpy(const_cast(Identifier), std::string(newIdentifier).c_str(), 64); - } - - ObjectEntryDescriptor& operator=(const ObjectEntryDescriptor& newEntry) - { - Generation = newEntry.Generation; - if (newEntry.Generation == ObjectGeneration::DAT) - Entry = newEntry.Entry; - else - safe_strcpy(const_cast(Identifier), std::string(newEntry.Identifier).c_str(), 64); - - return *this; - } -}; - struct rct_ride_filters { uint8_t category[2]; @@ -191,6 +143,38 @@ struct rct_object_filters assert_struct_size(rct_object_filters, 3); #pragma pack(pop) +enum class ObjectGeneration : uint8_t +{ + DAT, + JSON, +}; + +struct ObjectEntryDescriptor +{ + ObjectGeneration Generation; + std::string Identifier; // For JSON objects + rct_object_entry Entry; // For DAT objects + + ObjectEntryDescriptor() + : Generation(ObjectGeneration::JSON) + , Identifier() + , Entry() + { + } + + explicit ObjectEntryDescriptor(const rct_object_entry& newEntry) + { + Generation = ObjectGeneration::DAT; + Entry = newEntry; + } + + explicit ObjectEntryDescriptor(std::string_view newIdentifier) + { + Generation = ObjectGeneration::JSON; + Identifier = std::string(newIdentifier); + } +}; + struct IObjectRepository; namespace OpenRCT2 { diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index e9cb36ef1c..f79e16edd0 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -14,6 +14,7 @@ #include "../common.h" #include "../config/Config.h" #include "../core/Console.hpp" +#include "../core/DataSerialiser.h" #include "../core/FileIndex.hpp" #include "../core/FileStream.h" #include "../core/Guard.hpp" @@ -75,7 +76,7 @@ class ObjectFileIndex final : public FileIndex { private: static constexpr uint32_t MAGIC_NUMBER = 0x5844494F; // OIDX - static constexpr uint16_t VERSION = 24; + static constexpr uint16_t VERSION = 25; static constexpr auto PATTERN = "*.dat;*.pob;*.json;*.parkobj"; IObjectRepository& _objectRepository; @@ -160,12 +161,15 @@ protected: } break; case ObjectType::SceneryGroup: + { stream->WriteValue(static_cast(item.SceneryGroupInfo.Entries.size())); + DataSerialiser serialiser(true, *stream); for (const auto& entry : item.SceneryGroupInfo.Entries) { - stream->WriteObjectEntryDescriptor(entry); + serialiser << entry; } break; + } default: // Switch processes only ObjectType::Ride and ObjectType::SceneryGroup break; @@ -212,9 +216,10 @@ protected: { auto numEntries = stream->ReadValue(); item.SceneryGroupInfo.Entries = std::vector(numEntries); + DataSerialiser serialiser(false, *stream); for (size_t i = 0; i < numEntries; i++) { - item.SceneryGroupInfo.Entries[i] = stream->ReadObjectEntryDescriptor(); + serialiser << item.SceneryGroupInfo.Entries[i]; } break; }