From bafafa6805ae62ad0845be43d129155a68a0d11a Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Thu, 5 Nov 2020 21:19:43 +0100 Subject: [PATCH] Create functions to load objects by JSON id --- src/openrct2/network/NetworkBase.cpp | 4 +- src/openrct2/object/BannerObject.cpp | 2 +- src/openrct2/object/FootpathItemObject.cpp | 2 +- src/openrct2/object/ObjectManager.cpp | 101 +++++++++++--------- src/openrct2/object/ObjectManager.h | 1 + src/openrct2/object/ObjectRepository.cpp | 48 +++++++++- src/openrct2/object/ObjectRepository.h | 3 +- src/openrct2/rct1/S4Importer.cpp | 2 +- src/openrct2/ride/TrackDesignRepository.cpp | 4 +- 9 files changed, 112 insertions(+), 55 deletions(-) diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 4be3980077..843d4aeee2 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -2340,7 +2340,7 @@ void NetworkBase::Client_Handle_OBJECTS_LIST(NetworkConnection& connection, Netw uint32_t flags = 0; packet >> checksum >> flags; - const auto* object = repo.FindObject(objectName); + const auto* object = repo.FindObjectLegacy(objectName); // This could potentially request the object if checksums don't match, but since client // won't replace its version with server-provided one, we don't do that. if (object == nullptr) @@ -2482,7 +2482,7 @@ void NetworkBase::Server_Handle_MAPREQUEST(NetworkConnection& connection, Networ // This is required, as packet does not have null terminator std::string s(name, name + 8); log_verbose("Client requested object %s", s.c_str()); - const ObjectRepositoryItem* item = repo.FindObject(s.c_str()); + const ObjectRepositoryItem* item = repo.FindObjectLegacy(s.c_str()); if (item == nullptr) { log_warning("Client tried getting non-existent object %s from us.", s.c_str()); diff --git a/src/openrct2/object/BannerObject.cpp b/src/openrct2/object/BannerObject.cpp index eb1493b48c..e81b172aa1 100644 --- a/src/openrct2/object/BannerObject.cpp +++ b/src/openrct2/object/BannerObject.cpp @@ -44,7 +44,7 @@ void BannerObject::ReadLegacy(IReadObjectContext* context, OpenRCT2::IStream* st auto identifier = GetLegacyIdentifier(); auto& objectRepository = context->GetObjectRepository(); - auto item = objectRepository.FindObject(identifier); + auto item = objectRepository.FindObjectLegacy(identifier); if (item != nullptr) { auto sourceGame = item->GetFirstSourceGame(); diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index ee076b2f48..970f9d0806 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -48,7 +48,7 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext* context, OpenRCT2::IStre auto identifier = GetLegacyIdentifier(); auto& objectRepository = context->GetObjectRepository(); - auto item = objectRepository.FindObject(identifier); + auto item = objectRepository.FindObjectLegacy(identifier); if (item != nullptr) { auto sourceGame = item->GetFirstSourceGame(); diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index ba93821ce9..5a6edc0a6e 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -101,10 +101,9 @@ public: return result; } - Object* LoadObject(const rct_object_entry* entry) override + Object* RepositoryItemToObject(const ObjectRepositoryItem* ori) { Object* loadedObject = nullptr; - const ObjectRepositoryItem* ori = _objectRepository.FindObject(entry); if (ori != nullptr) { loadedObject = ori->LoadedObject; @@ -132,6 +131,18 @@ public: return loadedObject; } + Object* LoadObject(const std::string_view& identifier) override + { + const ObjectRepositoryItem* ori = _objectRepository.FindObject(identifier); + return RepositoryItemToObject(ori); + } + + Object* LoadObject(const rct_object_entry* entry) override + { + const ObjectRepositoryItem* ori = _objectRepository.FindObject(entry); + return RepositoryItemToObject(ori); + } + void LoadObjects(const rct_object_entry* entries, size_t count) override { // Find all the required objects @@ -222,52 +233,52 @@ public: // loaded RCT1 and RCT2 save files. // Surfaces - LoadObject("#RCT2SGR"); - LoadObject("#RCT2SSY"); - LoadObject("#RCT2SDI"); - LoadObject("#RCT2SRO"); - LoadObject("#RCT2SMA"); - LoadObject("#RCT2SCH"); - LoadObject("#RCT2SGC"); - LoadObject("#RCT2SIC"); - LoadObject("#RCT2SIR"); - LoadObject("#RCT2SIY"); - LoadObject("#RCT2SIP"); - LoadObject("#RCT2SIG"); - LoadObject("#RCT2SSR"); - LoadObject("#RCT2SSA"); + LoadObjectLegacy("#RCT2SGR"); + LoadObjectLegacy("#RCT2SSY"); + LoadObjectLegacy("#RCT2SDI"); + LoadObjectLegacy("#RCT2SRO"); + LoadObjectLegacy("#RCT2SMA"); + LoadObjectLegacy("#RCT2SCH"); + LoadObjectLegacy("#RCT2SGC"); + LoadObjectLegacy("#RCT2SIC"); + LoadObjectLegacy("#RCT2SIR"); + LoadObjectLegacy("#RCT2SIY"); + LoadObjectLegacy("#RCT2SIP"); + LoadObjectLegacy("#RCT2SIG"); + LoadObjectLegacy("#RCT2SSR"); + LoadObjectLegacy("#RCT2SSA"); // Edges - LoadObject("#RCT2ERO"); - LoadObject("#RCT2EWR"); - LoadObject("#RCT2EWB"); - LoadObject("#RCT2EIC"); - LoadObject("#RCT1EBR"); - LoadObject("#RCT1EIR"); - LoadObject("#RCT1EGY"); - LoadObject("#RCT1EYE"); - LoadObject("#RCT1ERE"); - LoadObject("#RCT1EPU"); - LoadObject("#RCT1EGR"); - LoadObject("#RCT1ESN"); - LoadObject("#RCT1ESG"); - LoadObject("#RCT1ESA"); - LoadObject("#RCT1ESB"); + LoadObjectLegacy("#RCT2ERO"); + LoadObjectLegacy("#RCT2EWR"); + LoadObjectLegacy("#RCT2EWB"); + LoadObjectLegacy("#RCT2EIC"); + LoadObjectLegacy("#RCT1EBR"); + LoadObjectLegacy("#RCT1EIR"); + LoadObjectLegacy("#RCT1EGY"); + LoadObjectLegacy("#RCT1EYE"); + LoadObjectLegacy("#RCT1ERE"); + LoadObjectLegacy("#RCT1EPU"); + LoadObjectLegacy("#RCT1EGR"); + LoadObjectLegacy("#RCT1ESN"); + LoadObjectLegacy("#RCT1ESG"); + LoadObjectLegacy("#RCT1ESA"); + LoadObjectLegacy("#RCT1ESB"); // Stations - LoadObject("#RCT2STN"); - LoadObject("#RCT2STW"); - LoadObject("#RCT2STV"); - LoadObject("#RCT2ST3"); - LoadObject("#RCT2ST4"); - LoadObject("#RCT2STJ"); - LoadObject("#RCT2STL"); - LoadObject("#RCT2STC"); - LoadObject("#RCT2STA"); - LoadObject("#RCT2STS"); - LoadObject("#RCT2STP"); - LoadObject("#RCT2STE"); - LoadObject("#ORCT2SN"); + LoadObjectLegacy("#RCT2STN"); + LoadObjectLegacy("#RCT2STW"); + LoadObjectLegacy("#RCT2STV"); + LoadObjectLegacy("#RCT2ST3"); + LoadObjectLegacy("#RCT2ST4"); + LoadObjectLegacy("#RCT2STJ"); + LoadObjectLegacy("#RCT2STL"); + LoadObjectLegacy("#RCT2STC"); + LoadObjectLegacy("#RCT2STA"); + LoadObjectLegacy("#RCT2STS"); + LoadObjectLegacy("#RCT2STP"); + LoadObjectLegacy("#RCT2STE"); + LoadObjectLegacy("#ORCT2SN"); } static rct_string_id GetObjectSourceGameString(const ObjectSourceGame sourceGame) @@ -304,7 +315,7 @@ public: } private: - Object* LoadObject(const std::string& name) + Object* LoadObjectLegacy(const std::string& name) { rct_object_entry entry{}; std::copy_n(name.c_str(), 8, entry.name); diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index dda14a4172..ea5f7145e5 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -30,6 +30,7 @@ struct IObjectManager virtual ObjectEntryIndex GetLoadedObjectEntryIndex(const Object* object) abstract; virtual std::vector GetInvalidObjects(const rct_object_entry* entries) abstract; + virtual Object* LoadObject(const std::string_view& identifier) abstract; virtual Object* LoadObject(const rct_object_entry* entry) abstract; virtual void LoadObjects(const rct_object_entry* entries, size_t count) abstract; virtual void LoadDefaultObjects() abstract; diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index 6cfbdce0d3..4c9503b3dd 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -47,6 +47,28 @@ using namespace OpenRCT2; +struct ObjectIdentifierHash +{ + size_t operator()(const std::string_view& identifier) const + { + std::string copy = identifier.data(); + uint32_t hash = 5381; + for (auto i : copy) + { + hash = ((hash << 5) + hash) + i; + } + return hash; + } +}; + +struct ObjectIdentifierEqual +{ + bool operator()(const std::string_view& lhs, const std::string_view& rhs) const + { + return lhs == rhs; + } +}; + struct ObjectEntryHash { size_t operator()(const rct_object_entry& entry) const @@ -68,6 +90,7 @@ struct ObjectEntryEqual } }; +using ObjectIdentifierMap = std::unordered_map; using ObjectEntryMap = std::unordered_map; class ObjectFileIndex final : public FileIndex @@ -230,6 +253,7 @@ class ObjectRepository final : public IObjectRepository std::shared_ptr const _env; ObjectFileIndex const _fileIndex; std::vector _items; + ObjectIdentifierMap _newItemMap; ObjectEntryMap _itemMap; public: @@ -269,7 +293,7 @@ public: return _items.data(); } - const ObjectRepositoryItem* FindObject(const std::string_view& legacyIdentifier) const override + const ObjectRepositoryItem* FindObjectLegacy(const std::string_view& legacyIdentifier) const override { rct_object_entry entry = {}; entry.SetName(legacyIdentifier); @@ -282,6 +306,16 @@ public: return nullptr; } + const ObjectRepositoryItem* FindObject(const std::string_view& identifier) const override final + { + auto kvp = _newItemMap.find(identifier.data()); + if (kvp != _newItemMap.end()) + { + return &_items[kvp->second]; + } + return nullptr; + } + const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const override final { auto kvp = _itemMap.find(*objectEntry); @@ -411,6 +445,7 @@ private: void ClearItems() { _items.clear(); + _newItemMap.clear(); _itemMap.clear(); } @@ -428,10 +463,15 @@ private: // Rebuild item map _itemMap.clear(); + _newItemMap.clear(); for (size_t i = 0; i < _items.size(); i++) { rct_object_entry entry = _items[i].ObjectEntry; _itemMap[entry] = i; + if (_items[i].Identifier != "") + { + _newItemMap[_items[i].Identifier] = i; + } } } @@ -460,6 +500,10 @@ private: auto copy = item; copy.Id = index; _items.push_back(copy); + if (item.Identifier != "") + { + _newItemMap[item.Identifier] = index; + } _itemMap[item.ObjectEntry] = index; return true; } @@ -749,7 +793,7 @@ const ObjectRepositoryItem* object_repository_find_object_by_entry(const rct_obj const ObjectRepositoryItem* object_repository_find_object_by_name(const char* name) { auto& objectRepository = GetContext()->GetObjectRepository(); - return objectRepository.FindObject(name); + return objectRepository.FindObjectLegacy(name); } bool object_entry_compare(const rct_object_entry* a, const rct_object_entry* b) diff --git a/src/openrct2/object/ObjectRepository.h b/src/openrct2/object/ObjectRepository.h index 6670395e24..838c95f2df 100644 --- a/src/openrct2/object/ObjectRepository.h +++ b/src/openrct2/object/ObjectRepository.h @@ -72,7 +72,8 @@ struct IObjectRepository virtual void Construct(int32_t language) abstract; virtual size_t GetNumObjects() const abstract; virtual const ObjectRepositoryItem* GetObjects() const abstract; - virtual const ObjectRepositoryItem* FindObject(const std::string_view& legacyIdentifier) const abstract; + virtual const ObjectRepositoryItem* FindObjectLegacy(const std::string_view& legacyIdentifier) const abstract; + virtual const ObjectRepositoryItem* FindObject(const std::string_view& identifier) const abstract; virtual const ObjectRepositoryItem* FindObject(const rct_object_entry* objectEntry) const abstract; virtual std::unique_ptr LoadObject(const ObjectRepositoryItem* ori) abstract; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index a052ec05d0..362df7c920 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -526,7 +526,7 @@ private: for (const char* objectName : objects) { auto& objectRepository = OpenRCT2::GetContext()->GetObjectRepository(); - auto foundObject = objectRepository.FindObject(objectName); + auto foundObject = objectRepository.FindObjectLegacy(objectName); if (foundObject != nullptr) { uint8_t objectType = foundObject->ObjectEntry.GetType(); diff --git a/src/openrct2/ride/TrackDesignRepository.cpp b/src/openrct2/ride/TrackDesignRepository.cpp index 3f676e4e3c..a032ad6f9d 100644 --- a/src/openrct2/ride/TrackDesignRepository.cpp +++ b/src/openrct2/ride/TrackDesignRepository.cpp @@ -164,7 +164,7 @@ public: bool entryIsNotSeparate = false; if (entry.empty()) { - const ObjectRepositoryItem* ori = repo.FindObject(item.ObjectEntry.c_str()); + const ObjectRepositoryItem* ori = repo.FindObjectLegacy(item.ObjectEntry.c_str()); if (ori == nullptr || !RideTypeDescriptors[rideType].HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) entryIsNotSeparate = true; @@ -198,7 +198,7 @@ public: bool entryIsNotSeparate = false; if (entry.empty()) { - const ObjectRepositoryItem* ori = repo.FindObject(item.ObjectEntry.c_str()); + const ObjectRepositoryItem* ori = repo.FindObjectLegacy(item.ObjectEntry.c_str()); if (ori == nullptr || !RideTypeDescriptors[rideType].HasFlag(RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY)) entryIsNotSeparate = true;