mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
Fix ObjectEntryDescriptor (#13506)
This commit is contained in:
@@ -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<rct_vehicle_colour>
|
||||
stream->Write(msg, strlen(msg));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct DataSerializerTraits_t<ObjectEntryDescriptor>
|
||||
{
|
||||
static void encode(OpenRCT2::IStream* stream, const ObjectEntryDescriptor& val)
|
||||
{
|
||||
stream->Write(&val.Generation);
|
||||
if (val.Generation == ObjectGeneration::DAT)
|
||||
{
|
||||
DataSerializerTraits<rct_object_entry> s;
|
||||
s.encode(stream, val.Entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
DataSerializerTraits<std::string> 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<rct_object_entry> s;
|
||||
s.decode(stream, obj);
|
||||
val = ObjectEntryDescriptor(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string id;
|
||||
DataSerializerTraits<std::string> 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<int32_t>(val.Generation));
|
||||
stream->Write(msg, strlen(msg));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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<TItem>& items) const
|
||||
|
||||
@@ -61,23 +61,4 @@ namespace OpenRCT2
|
||||
{
|
||||
WriteString(str.c_str());
|
||||
}
|
||||
|
||||
ObjectEntryDescriptor IStream::ReadObjectEntryDescriptor()
|
||||
{
|
||||
auto generation = ReadValue<ObjectGeneration>();
|
||||
if (generation == ObjectGeneration::DAT)
|
||||
return ObjectEntryDescriptor(ReadValue<rct_object_entry>());
|
||||
|
||||
return ObjectEntryDescriptor(ReadStdString());
|
||||
}
|
||||
|
||||
void IStream::WriteObjectEntryDescriptor(const ObjectEntryDescriptor& oed)
|
||||
{
|
||||
WriteValue<ObjectGeneration>(oed.Generation);
|
||||
if (oed.Generation == ObjectGeneration::DAT)
|
||||
WriteValue<rct_object_entry>(oed.Entry);
|
||||
else
|
||||
WriteString(oed.Identifier);
|
||||
}
|
||||
|
||||
} // namespace OpenRCT2
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include "ImageTable.h"
|
||||
#include "StringTable.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@@ -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<char*>(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<char*>(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
|
||||
{
|
||||
|
||||
@@ -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<ObjectRepositoryItem>
|
||||
{
|
||||
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<uint16_t>(static_cast<uint16_t>(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<uint16_t>();
|
||||
item.SceneryGroupInfo.Entries = std::vector<ObjectEntryDescriptor>(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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user