Create ObjectEntryDescriptor to properly handle mixed DAT and JSON

This commit is contained in:
Gymnasiast 2020-12-02 16:50:21 +01:00
parent aa8a08987f
commit 596aa71093
No known key found for this signature in database
GPG key ID: DBFFF47AB2CA3EDD
9 changed files with 99 additions and 17 deletions

View file

@ -455,7 +455,7 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_
{
for (const auto& sgEntry : item->SceneryGroupInfo.Entries)
{
window_editor_object_selection_select_object(++isMasterObject, flags, &sgEntry);
window_editor_object_selection_select_object(++isMasterObject, flags, sgEntry);
}
}
@ -494,7 +494,7 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_
{
for (const auto& sgEntry : item->SceneryGroupInfo.Entries)
{
if (!window_editor_object_selection_select_object(++isMasterObject, flags, &sgEntry))
if (!window_editor_object_selection_select_object(++isMasterObject, flags, sgEntry))
{
_maxObjectsWasHit = true;
}
@ -537,6 +537,14 @@ bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_
return window_editor_object_selection_select_object(isMasterObject, flags, item);
}
bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const ObjectEntryDescriptor& entry)
{
if (entry.Generation == ObjectGeneration::DAT)
return window_editor_object_selection_select_object(isMasterObject, flags, &entry.Entry);
return window_editor_object_selection_select_object(isMasterObject, flags, entry.Identifier);
}
bool editor_check_object_group_at_least_one_selected(ObjectType checkObjectType)
{
int32_t numObjects = static_cast<int32_t>(object_repository_get_items_count());

View file

@ -36,6 +36,7 @@ void finish_object_selection();
bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const ObjectRepositoryItem* item);
bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, std::string_view identifier);
bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const rct_object_entry* entry);
bool window_editor_object_selection_select_object(uint8_t isMasterObject, int32_t flags, const ObjectEntryDescriptor& entry);
/**
* Removes all unused objects from the object selection.

View file

@ -9,6 +9,7 @@
#include "IStream.hpp"
#include "../object/Object.h"
#include "Memory.hpp"
#include "String.hpp"
@ -61,4 +62,22 @@ 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

View file

@ -10,6 +10,7 @@
#pragma once
#include "../common.h"
#include "../object/Object.h"
#include "Memory.hpp"
#include <istream>
@ -206,6 +207,8 @@ 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

View file

@ -11,10 +11,12 @@
#include "../common.h"
#include "../core/JsonFwd.hpp"
#include "../util/Util.h"
#include "ImageTable.h"
#include "StringTable.h"
#include <algorithm>
#include <cstring>
#include <optional>
#include <string_view>
#include <vector>
@ -126,6 +128,46 @@ 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;
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];

View file

@ -75,7 +75,7 @@ class ObjectFileIndex final : public FileIndex<ObjectRepositoryItem>
{
private:
static constexpr uint32_t MAGIC_NUMBER = 0x5844494F; // OIDX
static constexpr uint16_t VERSION = 23;
static constexpr uint16_t VERSION = 24;
static constexpr auto PATTERN = "*.dat;*.pob;*.json;*.parkobj";
IObjectRepository& _objectRepository;
@ -163,7 +163,7 @@ protected:
stream->WriteValue<uint16_t>(static_cast<uint16_t>(item.SceneryGroupInfo.Entries.size()));
for (const auto& entry : item.SceneryGroupInfo.Entries)
{
stream->WriteValue<rct_object_entry>(entry);
stream->WriteObjectEntryDescriptor(entry);
}
break;
default:
@ -211,10 +211,10 @@ protected:
case ObjectType::SceneryGroup:
{
auto numEntries = stream->ReadValue<uint16_t>();
item.SceneryGroupInfo.Entries = std::vector<rct_object_entry>(numEntries);
item.SceneryGroupInfo.Entries = std::vector<ObjectEntryDescriptor>(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
item.SceneryGroupInfo.Entries[i] = stream->ReadValue<rct_object_entry>();
item.SceneryGroupInfo.Entries[i] = stream->ReadObjectEntryDescriptor();
}
break;
}
@ -310,6 +310,14 @@ public:
return nullptr;
}
const ObjectRepositoryItem* FindObject(const ObjectEntryDescriptor& entry) const override final
{
if (entry.Generation == ObjectGeneration::DAT)
return FindObject(&entry.Entry);
return FindObject(entry.Identifier);
}
std::unique_ptr<Object> LoadObject(const ObjectRepositoryItem* ori) override
{
Guard::ArgumentNotNull(ori, GUARD_LINE);

View file

@ -52,7 +52,7 @@ struct ObjectRepositoryItem
} RideInfo;
struct
{
std::vector<rct_object_entry> Entries;
std::vector<ObjectEntryDescriptor> Entries;
} SceneryGroupInfo;
ObjectSourceGame GetFirstSourceGame() const
@ -75,6 +75,7 @@ struct IObjectRepository
virtual const ObjectRepositoryItem* FindObjectLegacy(const std::string_view& legacyIdentifier) const abstract;
virtual const ObjectRepositoryItem* FindObject(std::string_view identifier) const abstract;
virtual const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const abstract;
virtual const ObjectRepositoryItem* FindObject(const ObjectEntryDescriptor& oed) const abstract;
virtual std::unique_ptr<Object> LoadObject(const ObjectRepositoryItem* ori) abstract;
virtual void RegisterLoadedObject(const ObjectRepositoryItem* ori, Object* object) abstract;

View file

@ -75,7 +75,7 @@ void SceneryGroupObject::UpdateEntryIndexes()
_legacyType.entry_count = 0;
for (const auto& objectEntry : _items)
{
auto ori = objectRepository.FindObject(&objectEntry);
auto ori = objectRepository.FindObject(objectEntry);
if (ori == nullptr)
continue;
if (ori->LoadedObject == nullptr)
@ -98,14 +98,14 @@ void SceneryGroupObject::SetRepositoryItem(ObjectRepositoryItem* item) const
item->SceneryGroupInfo.Entries = _items;
}
std::vector<rct_object_entry> SceneryGroupObject::ReadItems(IStream* stream)
std::vector<ObjectEntryDescriptor> SceneryGroupObject::ReadItems(IStream* stream)
{
auto items = std::vector<rct_object_entry>();
auto items = std::vector<ObjectEntryDescriptor>();
while (stream->ReadValue<uint8_t>() != 0xFF)
{
stream->Seek(-1, STREAM_SEEK_CURRENT);
auto entry = stream->ReadValue<rct_object_entry>();
items.push_back(entry);
items.push_back(ObjectEntryDescriptor(entry));
}
return items;
}
@ -166,13 +166,13 @@ EntertainerCostume SceneryGroupObject::ParseEntertainerCostume(const std::string
return EntertainerCostume::Panda;
}
std::vector<rct_object_entry> SceneryGroupObject::ReadJsonEntries(json_t& jEntries)
std::vector<ObjectEntryDescriptor> SceneryGroupObject::ReadJsonEntries(json_t& jEntries)
{
std::vector<rct_object_entry> entries;
std::vector<ObjectEntryDescriptor> entries;
for (auto& jEntry : jEntries)
{
auto entry = ParseObjectEntry(Json::GetString(jEntry));
auto entry = ObjectEntryDescriptor(Json::GetString(jEntry));
entries.push_back(entry);
}
return entries;

View file

@ -22,7 +22,7 @@ class SceneryGroupObject final : public Object
{
private:
rct_scenery_group_entry _legacyType = {};
std::vector<rct_object_entry> _items;
std::vector<ObjectEntryDescriptor> _items;
public:
explicit SceneryGroupObject(const rct_object_entry& entry)
@ -46,8 +46,8 @@ public:
void SetRepositoryItem(ObjectRepositoryItem* item) const override;
private:
static std::vector<rct_object_entry> ReadItems(OpenRCT2::IStream* stream);
static std::vector<ObjectEntryDescriptor> ReadItems(OpenRCT2::IStream* stream);
static uint32_t ReadJsonEntertainerCostumes(json_t& jCostumes);
static EntertainerCostume ParseEntertainerCostume(const std::string& s);
static std::vector<rct_object_entry> ReadJsonEntries(json_t& jEntries);
static std::vector<ObjectEntryDescriptor> ReadJsonEntries(json_t& jEntries);
};