From ede51ded86363944dd853cdc1fae3319cf706729 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 14 Dec 2017 18:43:59 +0000 Subject: [PATCH] Add JSON loading for scenery groups --- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/ObjectJsonHelpers.cpp | 9 ++ src/openrct2/object/ObjectJsonHelpers.h | 2 + src/openrct2/object/SceneryGroupObject.cpp | 102 ++++++++++++++++++--- src/openrct2/object/SceneryGroupObject.h | 4 + src/openrct2/object/SceneryObject.cpp | 27 ++++++ src/openrct2/object/SceneryObject.h | 10 +- 7 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 src/openrct2/object/SceneryObject.cpp diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index d16cc7af3e..ca5b6b8b89 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,7 @@ namespace ObjectFactory if (s == "footpath") return OBJECT_TYPE_PATHS; if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; if (s == "water") return OBJECT_TYPE_WATER; return 0xFF; diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index a47bf77b4d..cb7286f3a6 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -66,6 +66,15 @@ namespace ObjectJsonHelpers return result; } + rct_object_entry ParseObjectEntry(const std::string & s) + { + rct_object_entry entry = { 0 }; + std::fill_n(entry.name, sizeof(entry.name), ' '); + auto copyLen = std::min(8, s.size()); + std::copy_n(s.c_str(), copyLen, entry.name); + return entry; + } + static std::vector ParseRange(std::string s) { // Currently only supports [###] or [###..###] diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index c2edea2741..7cc3c11cb7 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -23,6 +23,7 @@ #include "../common.h" #include "../core/Json.hpp" #include "../drawing/drawing.h" +#include "../object.h" #include "ImageTable.h" #include "StringTable.h" @@ -31,6 +32,7 @@ namespace ObjectJsonHelpers bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); std::vector GetJsonStringArray(const json_t * arr); + rct_object_entry ParseObjectEntry(const std::string & s); void LoadStrings(const json_t * root, StringTable &stringTable); void LoadImages(const json_t * root, ImageTable &imageTable); diff --git a/src/openrct2/object/SceneryGroupObject.cpp b/src/openrct2/object/SceneryGroupObject.cpp index e137461e21..e43827704f 100644 --- a/src/openrct2/object/SceneryGroupObject.cpp +++ b/src/openrct2/object/SceneryGroupObject.cpp @@ -14,15 +14,20 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + +#include #include "../core/IStream.hpp" #include "../core/Memory.hpp" +#include "../core/String.hpp" +#include "../drawing/Drawing.h" +#include "../localisation/Language.h" +#include "../peep/Staff.h" +#include "ObjectJsonHelpers.h" #include "ObjectManager.h" #include "ObjectRepository.h" #include "SceneryGroupObject.h" -#include "../drawing/Drawing.h" -#include "../localisation/Language.h" - void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { stream->Seek(6, STREAM_SEEK_CURRENT); @@ -79,17 +84,20 @@ void SceneryGroupObject::UpdateEntryIndexes() uint16 sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject); Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE); - uint8 objectType = objectEntry.flags & 0x0F; + auto objectType = ori->ObjectEntry.flags & 0x0F; switch (objectType) { case OBJECT_TYPE_SMALL_SCENERY: break; - case OBJECT_TYPE_LARGE_SCENERY: sceneryEntry |= 0x300; break; - case OBJECT_TYPE_WALLS: sceneryEntry |= 0x200; break; case OBJECT_TYPE_PATH_BITS: sceneryEntry |= 0x100; break; - default: sceneryEntry |= 0x400; break; + case OBJECT_TYPE_WALLS: sceneryEntry |= 0x200; break; + case OBJECT_TYPE_LARGE_SCENERY: sceneryEntry |= 0x300; break; + case OBJECT_TYPE_BANNERS: sceneryEntry |= 0x400; break; + default: sceneryEntry = 0xFFFF; break; + } + if (sceneryEntry != 0xFFFF) + { + _legacyType.scenery_entries[_legacyType.entry_count] = sceneryEntry; + _legacyType.entry_count++; } - - _legacyType.scenery_entries[_legacyType.entry_count] = sceneryEntry; - _legacyType.entry_count++; } } @@ -111,8 +119,80 @@ std::vector SceneryGroupObject::ReadItems(IStream * stream) while (stream->ReadValue() != 0xFF) { stream->Seek(-1, STREAM_SEEK_CURRENT); - rct_object_entry entry = stream->ReadValue(); + auto entry = stream->ReadValue(); items.push_back(entry); } return items; } + +void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + _legacyType.priority = json_integer_value(json_object_get(properties, "priority")); + + // Entertainer cosumes + auto jCostumes = json_object_get(properties, "entertainerCostumes"); + if (jCostumes != nullptr) + { + _legacyType.entertainer_costumes = ReadJsonEntertainerCostumes(jCostumes); + } + + auto jEntries = json_object_get(properties, "entries"); + if (jEntries != nullptr) + { + _items = ReadJsonEntries(jEntries); + } + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} + +uint32 SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostumes) +{ + uint32 costumes = 0; + size_t index; + json_t * jCostume; + json_array_foreach(jCostumes, index, jCostume) + { + auto costume = ObjectJsonHelpers::GetString(jCostume); + auto entertainer = ParseEntertainerCostume(costume); + + // For some reason the flags are +4 from the actual costume IDs + // See staff_get_available_entertainer_costumes + costumes |= 1 << (entertainer + 4); + } + return costumes; +} + +uint32 SceneryGroupObject::ParseEntertainerCostume(const std::string &s) +{ + if (s == "panda") return ENTERTAINER_COSTUME_PANDA; + if (s == "tiger") return ENTERTAINER_COSTUME_TIGER; + if (s == "elephant") return ENTERTAINER_COSTUME_ELEPHANT; + if (s == "roman") return ENTERTAINER_COSTUME_ROMAN; + if (s == "gorilla") return ENTERTAINER_COSTUME_GORILLA; + if (s == "snowman") return ENTERTAINER_COSTUME_SNOWMAN; + if (s == "knight") return ENTERTAINER_COSTUME_KNIGHT; + if (s == "astronaut") return ENTERTAINER_COSTUME_ASTRONAUT; + if (s == "bandit") return ENTERTAINER_COSTUME_BANDIT; + if (s == "sheriff") return ENTERTAINER_COSTUME_SHERIFF; + if (s == "pirate") return ENTERTAINER_COSTUME_PIRATE; + return ENTERTAINER_COSTUME_PANDA; +} + +std::vector SceneryGroupObject::ReadJsonEntries(const json_t * jEntries) +{ + std::vector entries; + size_t index; + json_t * jEntry; + json_array_foreach(jEntries, index, jEntry) + { + auto entryId = json_string_value(jEntry); + if (entryId != nullptr) + { + auto entry = ObjectJsonHelpers::ParseObjectEntry(entryId); + entries.push_back(entry); + } + } + return entries; +} diff --git a/src/openrct2/object/SceneryGroupObject.h b/src/openrct2/object/SceneryGroupObject.h index a4e6b9c5de..6c6cb47f75 100644 --- a/src/openrct2/object/SceneryGroupObject.h +++ b/src/openrct2/object/SceneryGroupObject.h @@ -32,6 +32,7 @@ public: explicit SceneryGroupObject(const rct_object_entry &entry) : Object(entry) { } void * GetLegacyData() override { return &_legacyType; } + void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; @@ -44,4 +45,7 @@ public: private: static std::vector ReadItems(IStream * stream); + static uint32 ReadJsonEntertainerCostumes(const json_t * jCostumes); + static uint32 ParseEntertainerCostume(const std::string &s); + static std::vector ReadJsonEntries(const json_t * jEntries); }; diff --git a/src/openrct2/object/SceneryObject.cpp b/src/openrct2/object/SceneryObject.cpp new file mode 100644 index 0000000000..140239a8a6 --- /dev/null +++ b/src/openrct2/object/SceneryObject.cpp @@ -0,0 +1,27 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* OpenRCT2 is the work of many authors, a full list can be found in contributors.md +* For more information, visit https://github.com/OpenRCT2/OpenRCT2 +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* A full copy of the GNU General Public License can be found in licence.txt +*****************************************************************************/ +#pragma endregion + +#include "ObjectJsonHelpers.h" +#include "SceneryObject.h" + +void SceneryObject::SetPrimarySceneryGroup(const std::string &s) +{ + if (!s.empty()) + { + auto sgEntry = ObjectJsonHelpers::ParseObjectEntry(s); + SetPrimarySceneryGroup(&sgEntry); + } +} diff --git a/src/openrct2/object/SceneryObject.h b/src/openrct2/object/SceneryObject.h index 4d3cb9d693..98ce7256c8 100644 --- a/src/openrct2/object/SceneryObject.h +++ b/src/openrct2/object/SceneryObject.h @@ -32,13 +32,5 @@ public: protected: void SetPrimarySceneryGroup(const rct_object_entry * entry) { _primarySceneryGroupEntry = *entry; } - void SetPrimarySceneryGroup(const std::string &s) - { - if (!s.empty()) - { - rct_object_entry sgEntry = { 0 }; - std::strncpy(sgEntry.name, s.c_str(), 8); - SetPrimarySceneryGroup(&sgEntry); - } - } + void SetPrimarySceneryGroup(const std::string &s); };