diff --git a/CMakeLists.txt b/CMakeLists.txt
index 37810899e0..d1318d8d7e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,8 +41,8 @@ set(CMAKE_MACOSX_RPATH 1)
set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2c/title-sequences.zip")
set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d")
-set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.18/objects.zip")
-set(OBJECTS_SHA1 "4a3c32a0251c3babe014844f2c683fc32138b3f2")
+set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip")
+set(OBJECTS_SHA1 "151424d24b1d49a167932b58319bedaa6ec368e9")
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.22/replays.zip")
set(REPLAYS_SHA1 "7591db0a3842a7ac44fcbfbff9a573c9cb3ddc56")
diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj
index 2875a0204f..88435687e0 100644
--- a/OpenRCT2.xcodeproj/project.pbxproj
+++ b/OpenRCT2.xcodeproj/project.pbxproj
@@ -3908,7 +3908,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "version=\"1.0.18\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi";
+ shellScript = "version=\"1.0.20\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi";
};
C68B2D471EC790710020651C /* Download Libraries */ = {
isa = PBXShellScriptBuildPhase;
diff --git a/openrct2.proj b/openrct2.proj
index 8ddc9c7e6a..099197a8fa 100644
--- a/openrct2.proj
+++ b/openrct2.proj
@@ -46,8 +46,8 @@
058b9df80244c03f1633cb06e9f70471a29ebb8e
https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2c/title-sequences.zip
304d13a126c15bf2c86ff13b81a2f2cc1856ac8d
- https://github.com/OpenRCT2/objects/releases/download/v1.0.18/objects.zip
- 4a3c32a0251c3babe014844f2c683fc32138b3f2
+ https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip
+ 151424d24b1d49a167932b58319bedaa6ec368e9
https://github.com/OpenRCT2/replays/releases/download/v0.0.22/replays.zip
7591db0a3842a7ac44fcbfbff9a573c9cb3ddc56
diff --git a/shell.nix b/shell.nix
index b8e64d8b20..d28e07e766 100644
--- a/shell.nix
+++ b/shell.nix
@@ -15,8 +15,8 @@ let
objects-src = pkgs.fetchFromGitHub {
owner = "OpenRCT2";
repo = "objects";
- rev = "v1.0.18";
- sha256 = "bf8a28b7ccebaf58e4e9eb2540534632830534cf0b3f73677521dc555878c682";
+ rev = "v1.0.20";
+ sha256 = "bc266ef589c60302105473499ac142dbf951847be15e65b692d165ce261aeae0";
};
title-sequences-src = pkgs.fetchFromGitHub {
diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp
index e9001e8356..3fe7a5db7d 100644
--- a/src/openrct2/EditorObjectSelectionSession.cpp
+++ b/src/openrct2/EditorObjectSelectionSession.cpp
@@ -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(object_repository_get_items_count());
diff --git a/src/openrct2/EditorObjectSelectionSession.h b/src/openrct2/EditorObjectSelectionSession.h
index c93b940cd9..45f4f8b482 100644
--- a/src/openrct2/EditorObjectSelectionSession.h
+++ b/src/openrct2/EditorObjectSelectionSession.h
@@ -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.
diff --git a/src/openrct2/core/IStream.cpp b/src/openrct2/core/IStream.cpp
index 85dace3ecb..7f355d1413 100644
--- a/src/openrct2/core/IStream.cpp
+++ b/src/openrct2/core/IStream.cpp
@@ -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();
+ 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 b3d729c4d6..fc71319dc3 100644
--- a/src/openrct2/core/IStream.hpp
+++ b/src/openrct2/core/IStream.hpp
@@ -10,6 +10,7 @@
#pragma once
#include "../common.h"
+#include "../object/Object.h"
#include "Memory.hpp"
#include
@@ -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
diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h
index 1fc6a2e712..dccb485d0b 100644
--- a/src/openrct2/object/Object.h
+++ b/src/openrct2/object/Object.h
@@ -11,10 +11,12 @@
#include "../common.h"
#include "../core/JsonFwd.hpp"
+#include "../util/Util.h"
#include "ImageTable.h"
#include "StringTable.h"
#include
+#include
#include
#include
#include
@@ -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(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];
diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp
index b7f893213c..e9cb36ef1c 100644
--- a/src/openrct2/object/ObjectRepository.cpp
+++ b/src/openrct2/object/ObjectRepository.cpp
@@ -75,7 +75,7 @@ class ObjectFileIndex final : public FileIndex
{
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(static_cast(item.SceneryGroupInfo.Entries.size()));
for (const auto& entry : item.SceneryGroupInfo.Entries)
{
- stream->WriteValue(entry);
+ stream->WriteObjectEntryDescriptor(entry);
}
break;
default:
@@ -211,10 +211,10 @@ protected:
case ObjectType::SceneryGroup:
{
auto numEntries = stream->ReadValue();
- item.SceneryGroupInfo.Entries = std::vector(numEntries);
+ item.SceneryGroupInfo.Entries = std::vector(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
- item.SceneryGroupInfo.Entries[i] = stream->ReadValue();
+ 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