From a1f360ab7d822158a9140700d042c1a5a3479ca1 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 4 Dec 2017 21:56:06 +0000 Subject: [PATCH] Spike 1: Add RCT1 toilets JSON --- src/openrct2/object/ImageTable.cpp | 13 +++++++ src/openrct2/object/ImageTable.h | 1 + src/openrct2/object/Object.h | 2 + src/openrct2/object/ObjectFactory.cpp | 39 +++++++++++++++++++ src/openrct2/object/ObjectFactory.h | 2 + src/openrct2/object/ObjectRepository.cpp | 48 +++++++++++++++++------- src/openrct2/object/RideObject.cpp | 21 +++++++++++ src/openrct2/object/RideObject.h | 1 + 8 files changed, 114 insertions(+), 13 deletions(-) diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index d80bf172ae..17a25ff01c 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -97,3 +97,16 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) throw; } } + +void ImageTable::AddImage(const rct_g1_element * g1, size_t length) +{ + auto dstOffset = _dataSize; + _dataSize += length; + _data = Memory::Reallocate(_data, _dataSize); + auto dst = (uint8 *)((size_t)_data + dstOffset); + Memory::Copy(dst, g1->offset, length); + + rct_g1_element newg1 = *g1; + newg1.offset = dst; + _entries.push_back(newg1); +} diff --git a/src/openrct2/object/ImageTable.h b/src/openrct2/object/ImageTable.h index 9edfa20391..080533d91b 100644 --- a/src/openrct2/object/ImageTable.h +++ b/src/openrct2/object/ImageTable.h @@ -37,4 +37,5 @@ public: void Read(IReadObjectContext * context, IStream * stream); const rct_g1_element * GetImages() const { return _entries.data(); } uint32 GetCount() const { return (uint32)_entries.size(); } + void AddImage(const rct_g1_element * g1, size_t length); }; diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index aa361cdf33..c02c2c95a0 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -17,6 +17,7 @@ #pragma once #include "../common.h" +#include "../core/Json.hpp" #include "ImageTable.h" #include "StringTable.h" @@ -168,6 +169,7 @@ public: const rct_object_entry * GetObjectEntry() const { return &_objectEntry; } virtual void * GetLegacyData() abstract; + virtual void ReadJson(IReadObjectContext * context, const json_t * root) { } virtual void ReadLegacy(IReadObjectContext * context, IStream * stream) abstract; virtual void Load() abstract; virtual void Unload() abstract; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 163be81b37..fd3fbc3466 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -16,6 +16,7 @@ #include "../core/Console.hpp" #include "../core/FileStream.hpp" +#include "../core/Json.hpp" #include "../core/Memory.hpp" #include "../core/MemoryStream.h" #include "../core/String.hpp" @@ -203,4 +204,42 @@ namespace ObjectFactory } return result; } + + Object * CreateObjectFromJsonFile(const std::string &path) + { + log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str()); + + Object * result = nullptr; + try + { + auto jRoot = Json::ReadFromFile(path.c_str()); + auto jObjectType = json_object_get(jRoot, "objectType"); + if (json_is_string(jObjectType)) + { + auto objectType = std::string(json_string_value(jObjectType)); + if (objectType == "ride") + { + std::string objectName = "#RCT1TOI"; + rct_object_entry entry = { 0 }; + memcpy(entry.name, objectName.c_str(), 8); + result = new RideObject(entry); + auto readContext = ReadObjectContext(objectName.c_str()); + result->ReadJson(&readContext, jRoot); + if (readContext.WasError()) + { + throw Exception("Object has errors"); + } + } + } + json_decref(jRoot); + } + catch (Exception) + { + Console::Error::WriteLine("Unable to open or read '%s'", path); + + delete result; + result = nullptr; + } + return result; + } } diff --git a/src/openrct2/object/ObjectFactory.h b/src/openrct2/object/ObjectFactory.h index c8b1793f1d..e6173ff61d 100644 --- a/src/openrct2/object/ObjectFactory.h +++ b/src/openrct2/object/ObjectFactory.h @@ -25,4 +25,6 @@ namespace ObjectFactory Object * CreateObjectFromLegacyFile(const utf8 * path); Object * CreateObjectFromLegacyData(const rct_object_entry * entry, const void * data, size_t dataSize); Object * CreateObject(const rct_object_entry &entry); + + Object * CreateObjectFromJsonFile(const std::string &path); } diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index 0b423d38ac..94b4fd37d3 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -80,7 +80,7 @@ class ObjectFileIndex final : public FileIndex private: static constexpr uint32 MAGIC_NUMBER = 0x5844494F; // OIDX static constexpr uint16 VERSION = 17; - static constexpr auto PATTERN = "*.dat;*.pob"; + static constexpr auto PATTERN = "*.dat;*.pob;*.json"; public: explicit ObjectFileIndex(IPlatformEnvironment * env) : @@ -98,21 +98,36 @@ public: public: std::tuple Create(const std::string &path) const override { - auto object = ObjectFactory::CreateObjectFromLegacyFile(path.c_str()); - if (object != nullptr) + auto extension = Path::GetExtension(path); + if (String::Equals(extension, ".json", true)) { - ObjectRepositoryItem item = { 0 }; - item.ObjectEntry = *object->GetObjectEntry(); - item.Path = String::Duplicate(path); - item.Name = String::Duplicate(object->GetName()); - object->SetRepositoryItem(&item); - delete object; - return std::make_tuple(true, item); + auto object = ObjectFactory::CreateObjectFromJsonFile(path); + if (object != nullptr) + { + ObjectRepositoryItem item = { 0 }; + item.ObjectEntry = *object->GetObjectEntry(); + item.Path = String::Duplicate(path); + item.Name = String::Duplicate(object->GetName()); + object->SetRepositoryItem(&item); + delete object; + return std::make_tuple(true, item); + } } else { - return std::make_tuple(false, ObjectRepositoryItem()); + auto object = ObjectFactory::CreateObjectFromLegacyFile(path.c_str()); + if (object != nullptr) + { + ObjectRepositoryItem item = { 0 }; + item.ObjectEntry = *object->GetObjectEntry(); + item.Path = String::Duplicate(path); + item.Name = String::Duplicate(object->GetName()); + object->SetRepositoryItem(&item); + delete object; + return std::make_tuple(true, item); + } } + return std::make_tuple(false, ObjectRepositoryItem()); } protected: @@ -260,8 +275,15 @@ public: { Guard::ArgumentNotNull(ori, GUARD_LINE); - Object * object = ObjectFactory::CreateObjectFromLegacyFile(ori->Path); - return object; + auto extension = Path::GetExtension(ori->Path); + if (String::Equals(extension, ".json", true)) + { + return ObjectFactory::CreateObjectFromJsonFile(ori->Path); + } + else + { + return ObjectFactory::CreateObjectFromLegacyFile(ori->Path); + } } void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index f194ce4ed9..840ea94f72 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -532,3 +532,24 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve return numHorizontalFrames; } + +void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + printf("RideObject::ReadJson(context, root)\n"); + _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; + _legacyType.category[0] = RIDE_CATEGORY_SHOP; + + auto stringTable = GetStringTable(); + stringTable->SetString(0, 0, "RCT1 toilets"); + stringTable->SetString(1, 0, "Desc"); + stringTable->SetString(2, 0, "Capacity"); + stringTable->SetString(3, 0, "Vehicle"); + + auto imageTable = GetImageTable(); + auto g1 = *(gfx_get_g1_element(0x60000 + 64231)); + // auto g12 = gfx_get_g1_element(0x60000 + 64322); + // imageTable->AddImage(g1, (size_t)(g12->offset - g1->offset)); + g1.x_offset = 0; + g1.y_offset = 0; + imageTable->AddImage(&g1, 0x4000); +} diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index 27c467667f..b84f586838 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -34,6 +34,7 @@ public: void * GetLegacyData() override { return &_legacyType; } + void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override;