diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index aa82b7f493..7243b96e5a 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -257,7 +257,7 @@ public: case WC_OBJECT_LOAD_ERROR: { std::string path = intent->GetStringExtra(INTENT_EXTRA_PATH); - const rct_object_entry* objects = static_cast(intent->GetPointerExtra(INTENT_EXTRA_LIST)); + auto objects = static_cast(intent->GetPointerExtra(INTENT_EXTRA_LIST)); size_t count = intent->GetUIntExtra(INTENT_EXTRA_LIST_COUNT); window_object_load_error_open(const_cast(path.c_str()), count, objects); diff --git a/src/openrct2-ui/scripting/ScTitleSequence.hpp b/src/openrct2-ui/scripting/ScTitleSequence.hpp index 4e5d889015..0a83ea11e7 100644 --- a/src/openrct2-ui/scripting/ScTitleSequence.hpp +++ b/src/openrct2-ui/scripting/ScTitleSequence.hpp @@ -211,7 +211,7 @@ namespace OpenRCT2::Scripting auto& objectMgr = GetContext()->GetObjectManager(); auto parkImporter = std::unique_ptr(ParkImporter::Create(handle->HintPath)); auto result = parkImporter->LoadFromStream(handle->Stream.get(), isScenario); - objectMgr.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectMgr.LoadObjects(result.RequiredObjects); parkImporter->Import(); auto old = gLoadKeepWindowsOpen; diff --git a/src/openrct2-ui/title/TitleSequencePlayer.cpp b/src/openrct2-ui/title/TitleSequencePlayer.cpp index 8a624e6bd1..e9271b8212 100644 --- a/src/openrct2-ui/title/TitleSequencePlayer.cpp +++ b/src/openrct2-ui/title/TitleSequencePlayer.cpp @@ -374,7 +374,7 @@ private: auto result = parkImporter->Load(path); auto& objectManager = GetContext()->GetObjectManager(); - objectManager.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectManager.LoadObjects(result.RequiredObjects); parkImporter->Import(); } @@ -413,7 +413,7 @@ private: auto result = parkImporter->LoadFromStream(stream, isScenario); auto& objectManager = GetContext()->GetObjectManager(); - objectManager.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectManager.LoadObjects(result.RequiredObjects); parkImporter->Import(); } diff --git a/src/openrct2-ui/windows/ObjectLoadError.cpp b/src/openrct2-ui/windows/ObjectLoadError.cpp index eb75214192..b9e3dc9061 100644 --- a/src/openrct2-ui/windows/ObjectLoadError.cpp +++ b/src/openrct2-ui/windows/ObjectLoadError.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -48,8 +49,8 @@ private: } }; - std::vector _entries; - std::vector _downloadedEntries; + std::vector _entries; + std::vector _downloadedEntries; size_t _currentDownloadIndex{}; std::mutex _downloadedEntriesMutex; std::mutex _queueMutex; @@ -64,7 +65,7 @@ private: inline static bool _downloadingObjects; public: - void Begin(const std::vector& entries) + void Begin(const std::vector& entries) { _lastDownloadStatusInfo = {}; _downloadStatusInfo = {}; @@ -80,7 +81,7 @@ public: return _downloadingObjects; } - std::vector GetDownloadedEntries() + std::vector GetDownloadedEntries() { std::lock_guard guard(_downloadedEntriesMutex); return _downloadedEntries; @@ -150,7 +151,7 @@ private: _nextDownloadQueued = true; } - void DownloadObject(const rct_object_entry& entry, const std::string name, const std::string url) + void DownloadObject(const ObjectEntryDescriptor& entry, const std::string name, const std::string url) { try { @@ -199,7 +200,7 @@ private: } auto& entry = _entries[_currentDownloadIndex]; - auto name = String::Trim(std::string(entry.name, sizeof(entry.name))); + auto name = String::Trim(std::string(entry.GetName())); log_verbose("Downloading object: [%s]:", name.c_str()); _currentDownloadIndex++; UpdateProgress({ name, _lastDownloadSource, _currentDownloadIndex, _entries.size() }); @@ -283,7 +284,6 @@ static rct_widget window_object_load_error_widgets[] = { { WIDGETS_END }, }; -static rct_string_id get_object_type_string(const rct_object_entry *entry); static void window_object_load_error_close(rct_window *w); static void window_object_load_error_update(rct_window *w); static void window_object_load_error_mouseup(rct_window *w, rct_widgetindex widgetIndex); @@ -310,7 +310,7 @@ static rct_window_event_list window_object_load_error_events([](auto& events) }); // clang-format on -static std::vector _invalid_entries; +static std::vector _invalid_entries; static int32_t highlighted_index = -1; static std::string file_path; #ifndef DISABLE_HTTP @@ -324,10 +324,10 @@ static bool _updatedListAfterDownload; * Could possibly be moved out of the window file if other * uses exist and a suitable location is found. */ -static rct_string_id get_object_type_string(const rct_object_entry* entry) +static rct_string_id get_object_type_string(ObjectType type) { rct_string_id result; - switch (entry->GetType()) + switch (type) { case ObjectType::Ride: result = STR_OBJECT_SELECTION_RIDE_VEHICLES_ATTRACTIONS; @@ -371,39 +371,21 @@ static rct_string_id get_object_type_string(const rct_object_entry* entry) */ static void copy_object_names_to_clipboard(rct_window* w) { - // Something has gone wrong, this shouldn't happen. - // We don't want to allocate stupidly large amounts of memory for no reason - assert(w->no_list_items > 0 && w->no_list_items <= OBJECT_ENTRY_COUNT); - - // No system has a newline over 2 characters - size_t line_sep_len = strnlen(PLATFORM_NEWLINE, 2); - size_t buffer_len = (w->no_list_items * (8 + line_sep_len)) + 1; - utf8* buffer = new utf8[buffer_len]{}; - - size_t cur_len = 0; + std::stringstream ss; for (uint16_t i = 0; i < w->no_list_items; i++) { - cur_len += (8 + line_sep_len); - assert(cur_len < buffer_len); - - uint16_t nameLength = 8; - for (; nameLength > 0; nameLength--) - { - if (_invalid_entries[i].name[nameLength - 1] != ' ') - break; - } - - strncat(buffer, _invalid_entries[i].name, nameLength); - strncat(buffer, PLATFORM_NEWLINE, buffer_len - strlen(buffer) - 1); + const auto& entry = _invalid_entries[i]; + ss << entry.GetName(); + ss << PLATFORM_NEWLINE; } - platform_place_string_on_clipboard(buffer); - delete[] buffer; + auto clip = ss.str(); + OpenRCT2::GetContext()->GetUiContext()->SetClipboardText(clip.c_str()); } -rct_window* window_object_load_error_open(utf8* path, size_t numMissingObjects, const rct_object_entry* missingObjects) +rct_window* window_object_load_error_open(utf8* path, size_t numMissingObjects, const ObjectEntryDescriptor* missingObjects) { - _invalid_entries = std::vector(missingObjects, missingObjects + numMissingObjects); + _invalid_entries = std::vector(missingObjects, missingObjects + numMissingObjects); // Check if window is already open rct_window* window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR); @@ -476,13 +458,8 @@ static void window_object_load_error_mouseup(rct_window* w, rct_widgetindex widg case WIDX_COPY_CURRENT: if (w->selected_list_item > -1 && w->selected_list_item < w->no_list_items) { - utf8* selected_name = strndup(_invalid_entries[w->selected_list_item].name, 8); - utf8* strp = strchr(selected_name, ' '); - if (strp != nullptr) - *strp = '\0'; - - platform_place_string_on_clipboard(selected_name); - SafeFree(selected_name); + auto name = std::string(_invalid_entries[w->selected_list_item].GetName()); + OpenRCT2::GetContext()->GetUiContext()->SetClipboardText(name.c_str()); } break; case WIDX_COPY_ALL: @@ -578,14 +555,23 @@ static void window_object_load_error_scrollpaint(rct_window* w, rct_drawpixelinf // Draw the actual object entry's name... screenCoords.x = NAME_COL_LEFT - 3; - gfx_draw_string(dpi, screenCoords, strndup(_invalid_entries[i].name, 8), { COLOUR_DARK_GREEN }); - // ... source game ... - rct_string_id sourceStringId = object_manager_get_source_game_string(_invalid_entries[i].GetSourceGame()); - DrawTextBasic(dpi, { SOURCE_COL_LEFT - 3, screenCoords.y }, sourceStringId, {}, { COLOUR_DARK_GREEN }); + const auto& entry = _invalid_entries[i]; + + auto name = entry.GetName(); + char buffer[256]; + String::Set(buffer, sizeof(buffer), name.data(), name.size()); + gfx_draw_string(dpi, screenCoords, buffer, { COLOUR_DARK_GREEN }); + + if (entry.Generation == ObjectGeneration::DAT) + { + // ... source game ... + rct_string_id sourceStringId = object_manager_get_source_game_string(entry.Entry.GetSourceGame()); + DrawTextBasic(dpi, { SOURCE_COL_LEFT - 3, screenCoords.y }, sourceStringId, {}, { COLOUR_DARK_GREEN }); + } // ... and type - rct_string_id type = get_object_type_string(&_invalid_entries[i]); + rct_string_id type = get_object_type_string(entry.GetType()); DrawTextBasic(dpi, { TYPE_COL_LEFT - 3, screenCoords.y }, type, {}, { COLOUR_DARK_GREEN }); } } @@ -609,7 +595,7 @@ static void window_object_load_error_update_list(rct_window* w) _invalid_entries.erase( std::remove_if( _invalid_entries.begin(), _invalid_entries.end(), - [de](const rct_object_entry& e) { return std::memcmp(de.name, e.name, sizeof(e.name)) == 0; }), + [de](const ObjectEntryDescriptor& e) { return de.GetName() == e.GetName(); }), _invalid_entries.end()); w->no_list_items = static_cast(_invalid_entries.size()); } diff --git a/src/openrct2-ui/windows/TitleEditor.cpp b/src/openrct2-ui/windows/TitleEditor.cpp index 813e0287da..5c3aa219c0 100644 --- a/src/openrct2-ui/windows/TitleEditor.cpp +++ b/src/openrct2-ui/windows/TitleEditor.cpp @@ -353,7 +353,7 @@ static void window_title_editor_mouseup(rct_window* w, rct_widgetindex widgetInd auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager(); auto parkImporter = std::unique_ptr(ParkImporter::Create(handle->HintPath)); auto result = parkImporter->LoadFromStream(handle->Stream.get(), isScenario); - objectMgr.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectMgr.LoadObjects(result.RequiredObjects); parkImporter->Import(); if (isScenario) diff --git a/src/openrct2-ui/windows/Window.h b/src/openrct2-ui/windows/Window.h index 2b727b62cd..439d6f1698 100644 --- a/src/openrct2-ui/windows/Window.h +++ b/src/openrct2-ui/windows/Window.h @@ -163,7 +163,7 @@ void window_text_input_open( std::string_view title, std::string_view description, std::string_view initialValue, size_t maxLength, std::function okCallback, std::function cancelCallback); -rct_window* window_object_load_error_open(utf8* path, size_t numMissingObjects, const rct_object_entry* missingObjects); +rct_window* window_object_load_error_open(utf8* path, size_t numMissingObjects, const ObjectEntryDescriptor* missingObjects); rct_window* window_ride_construction_open(); void window_ride_construction_update_active_elements_impl(); diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index bf9f70fc80..da7cce69c4 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -630,7 +630,7 @@ namespace OpenRCT2 // so reload the title screen if that happens. loadTitleScreenFirstOnFail = true; - _objectManager->LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + _objectManager->LoadObjects(result.RequiredObjects); parkImporter->Import(); gScenarioSavePath = path; gCurrentLoadedPath = path; @@ -692,7 +692,7 @@ namespace OpenRCT2 // which the window function doesn't like auto intent = Intent(WC_OBJECT_LOAD_ERROR); intent.putExtra(INTENT_EXTRA_PATH, path); - intent.putExtra(INTENT_EXTRA_LIST, const_cast(e.MissingObjects.data())); + intent.putExtra(INTENT_EXTRA_LIST, const_cast(e.MissingObjects.data())); intent.putExtra(INTENT_EXTRA_LIST_COUNT, static_cast(e.MissingObjects.size())); auto windowManager = _uiContext->GetWindowManager(); @@ -1509,11 +1509,6 @@ utf8* platform_open_directory_browser(const utf8* title) } } -bool platform_place_string_on_clipboard(utf8* target) -{ - return GetContext()->GetUiContext()->SetClipboardText(target); -} - /** * This function is deprecated. * Use IPlatformEnvironment instead. diff --git a/src/openrct2/ParkFile.cpp b/src/openrct2/ParkFile.cpp index 72b9db5597..0b27ea63a2 100644 --- a/src/openrct2/ParkFile.cpp +++ b/src/openrct2/ParkFile.cpp @@ -87,7 +87,7 @@ namespace OpenRCT2 class ParkFile { public: - std::vector RequiredObjects; + std::vector RequiredObjects; private: std::unique_ptr _os; @@ -168,20 +168,34 @@ namespace OpenRCT2 void ReadWriteObjectsChunk(OrcaStream& os) { + static constexpr uint8_t DESCRIPTOR_NONE = 0; + static constexpr uint8_t DESCRIPTOR_DAT = 1; + static constexpr uint8_t DESCRIPTOR_JSON = 2; + if (os.GetMode() == OrcaStream::Mode::READING) { - std::vector entries; - os.ReadWriteChunk(ParkFileChunkType::OBJECTS, [&entries](OrcaStream::ChunkStream& cs) { - cs.ReadWriteVector(entries, [&cs](rct_object_entry& entry) { - auto type = cs.Read(); - auto id = cs.Read(); - auto version = cs.Read(); - - entry.flags = type & 0x7FFF; - strncpy(entry.name, id.c_str(), 8); + std::vector requiredObjects; + os.ReadWriteChunk(ParkFileChunkType::OBJECTS, [&requiredObjects](OrcaStream::ChunkStream& cs) { + cs.ReadWriteVector(requiredObjects, [&cs](ObjectEntryDescriptor& objectDesc) { + auto kind = cs.Read(); + switch (kind) + { + case DESCRIPTOR_NONE: + break; + case DESCRIPTOR_DAT: + objectDesc.Entry = cs.Read(); + break; + case DESCRIPTOR_JSON: + objectDesc.Type = static_cast(cs.Read()); + objectDesc.Identifier = cs.Read(); + objectDesc.Version = cs.Read(); + break; + default: + throw std::runtime_error("Unknown object descriptor kind."); + } }); }); - RequiredObjects = entries; + RequiredObjects = requiredObjects; } else { @@ -193,18 +207,24 @@ namespace OpenRCT2 auto obj = objManager.GetLoadedObject(i); if (obj != nullptr) { - auto entry = obj->GetObjectEntry(); - auto type = static_cast(entry->flags & 0x0F); - type |= 0x8000; // Make as legacy object - cs.Write(type); - cs.Write(std::string_view(entry->name, 8)); - cs.Write(""); + if (obj->IsJsonObject()) + { + cs.Write(DESCRIPTOR_JSON); + cs.Write(static_cast(obj->GetObjectType())); + cs.Write(obj->GetIdentifier()); + cs.Write(""); // reserved for version + } + else + { + auto entry = obj->GetObjectEntry(); + assert(entry != nullptr); + cs.Write(DESCRIPTOR_DAT); + cs.Write(entry); + } } else { - cs.Write(0); - cs.Write(""); - cs.Write(""); + cs.Write(DESCRIPTOR_NONE); } }); }); diff --git a/src/openrct2/ParkImporter.h b/src/openrct2/ParkImporter.h index 6cf8f61795..89bc30dcdb 100644 --- a/src/openrct2/ParkImporter.h +++ b/src/openrct2/ParkImporter.h @@ -29,9 +29,9 @@ struct scenario_index_entry; struct ParkLoadResult final { public: - std::vector RequiredObjects; + std::vector RequiredObjects; - explicit ParkLoadResult(std::vector&& requiredObjects) + explicit ParkLoadResult(std::vector&& requiredObjects) : RequiredObjects(std::move(requiredObjects)) { } @@ -69,9 +69,9 @@ namespace ParkImporter class ObjectLoadException : public std::exception { public: - std::vector const MissingObjects; + std::vector const MissingObjects; - explicit ObjectLoadException(std::vector&& missingObjects) + explicit ObjectLoadException(std::vector&& missingObjects) : MissingObjects(std::move(missingObjects)) { } diff --git a/src/openrct2/ReplayManager.cpp b/src/openrct2/ReplayManager.cpp index 81c6746bd8..f400000acd 100644 --- a/src/openrct2/ReplayManager.cpp +++ b/src/openrct2/ReplayManager.cpp @@ -523,7 +523,7 @@ namespace OpenRCT2 auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadFromStream(&data.parkData, false); - objManager.LoadObjects(loadResult.RequiredObjects.data(), loadResult.RequiredObjects.size()); + objManager.LoadObjects(loadResult.RequiredObjects); importer->Import(); diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 2358beb336..a54af25786 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -2718,7 +2718,7 @@ bool NetworkBase::LoadMap(IStream* stream) auto& objManager = context->GetObjectManager(); auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadFromStream(stream, false); - objManager.LoadObjects(loadResult.RequiredObjects.data(), loadResult.RequiredObjects.size()); + objManager.LoadObjects(loadResult.RequiredObjects); importer->Import(); EntityTweener::Get().Reset(); diff --git a/src/openrct2/object/Object.cpp b/src/openrct2/object/Object.cpp index 0d221293e5..7a4c4f156b 100644 --- a/src/openrct2/object/Object.cpp +++ b/src/openrct2/object/Object.cpp @@ -33,6 +33,50 @@ ObjectType& operator++(ObjectType& d, int) return d = (d == ObjectType::Count) ? ObjectType::Ride : static_cast(static_cast(d) + 1); } +ObjectEntryDescriptor::ObjectEntryDescriptor(const rct_object_entry& newEntry) +{ + if (!object_entry_is_empty(&newEntry)) + { + Generation = ObjectGeneration::DAT; + Entry = newEntry; + } +} + +ObjectEntryDescriptor::ObjectEntryDescriptor(std::string_view newIdentifier) +{ + Generation = ObjectGeneration::JSON; + Identifier = std::string(newIdentifier); +} + +ObjectEntryDescriptor::ObjectEntryDescriptor(const ObjectRepositoryItem& ori) +{ + if (!ori.Identifier.empty()) + { + Generation = ObjectGeneration::JSON; + Identifier = std::string(ori.Identifier); + } + else + { + Generation = ObjectGeneration::DAT; + Entry = ori.ObjectEntry; + } +} + +bool ObjectEntryDescriptor::HasValue() const +{ + return Generation != ObjectGeneration::JSON || !Identifier.empty(); +}; + +ObjectType ObjectEntryDescriptor::GetType() const +{ + return Generation == ObjectGeneration::JSON ? Type : Entry.GetType(); +} + +std::string_view ObjectEntryDescriptor::GetName() const +{ + return Generation == ObjectGeneration::JSON ? Identifier : Entry.GetName(); +} + Object::Object(const rct_object_entry& entry) { _objectEntry = entry; @@ -302,20 +346,6 @@ std::unique_ptr ObjectAsset::GetStream() const return {}; } -ObjectEntryDescriptor::ObjectEntryDescriptor(const ObjectRepositoryItem& ori) -{ - if (!ori.Identifier.empty()) - { - Generation = ObjectGeneration::JSON; - Identifier = std::string(ori.Identifier); - } - else - { - Generation = ObjectGeneration::DAT; - Entry = ori.ObjectEntry; - } -} - #ifdef __WARN_SUGGEST_FINAL_METHODS__ # pragma GCC diagnostic pop #endif diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index 47e9ee87d5..0057bf3874 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -159,30 +159,23 @@ enum class ObjectGeneration : uint8_t struct ObjectEntryDescriptor { - ObjectGeneration Generation; - std::string Identifier; // For JSON objects - rct_object_entry Entry; // For DAT objects + ObjectGeneration Generation = ObjectGeneration::JSON; - ObjectEntryDescriptor() - : Generation(ObjectGeneration::JSON) - , Identifier() - , Entry() - { - } + // DAT + rct_object_entry Entry; - explicit ObjectEntryDescriptor(const rct_object_entry& newEntry) - { - Generation = ObjectGeneration::DAT; - Entry = newEntry; - } - - explicit ObjectEntryDescriptor(std::string_view newIdentifier) - { - Generation = ObjectGeneration::JSON; - Identifier = std::string(newIdentifier); - } + // JSON + ObjectType Type{}; + std::string Identifier; + std::string Version; + ObjectEntryDescriptor() = default; + explicit ObjectEntryDescriptor(const rct_object_entry& newEntry); + explicit ObjectEntryDescriptor(std::string_view newIdentifier); explicit ObjectEntryDescriptor(const ObjectRepositoryItem& ori); + bool HasValue() const; + ObjectType GetType() const; + std::string_view GetName() const; }; struct IObjectRepository; diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index 0ca24b767e..1ce486e517 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -114,10 +114,10 @@ public: return RepositoryItemToObject(ori); } - void LoadObjects(const rct_object_entry* entries, size_t count) override + void LoadObjects(const std::vector& entries) override { // Find all the required objects - auto requiredObjects = GetRequiredObjects(entries, count); + auto requiredObjects = GetRequiredObjects(entries); // Load the required objects size_t numNewLoadedObjects = 0; @@ -554,66 +554,21 @@ private: return duplicate; } - std::vector GetInvalidObjects(const rct_object_entry* entries) override - { - std::vector invalidEntries; - invalidEntries.reserve(OBJECT_ENTRY_COUNT); - for (int32_t i = 0; i < OBJECT_ENTRY_COUNT; i++) - { - auto entry = entries[i]; - const ObjectRepositoryItem* ori = nullptr; - if (object_entry_is_empty(&entry)) - { - entry = {}; - continue; - } - - ori = _objectRepository.FindObject(&entry); - if (ori == nullptr) - { - if (entry.GetType() != ObjectType::ScenarioText) - { - invalidEntries.push_back(entry); - ReportMissingObject(&entry); - } - else - { - entry = {}; - continue; - } - } - else - { - auto loadedObject = ori->LoadedObject; - if (loadedObject == nullptr) - { - auto object = _objectRepository.LoadObject(ori); - if (object == nullptr) - { - invalidEntries.push_back(entry); - ReportObjectLoadProblem(&entry); - } - } - } - } - return invalidEntries; - } - - std::vector GetRequiredObjects(const rct_object_entry* entries, size_t count) + std::vector GetRequiredObjects(const std::vector& objectList) { std::vector requiredObjects; - std::vector missingObjects; + std::vector missingObjects; - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < objectList.size(); i++) { - const rct_object_entry* entry = &entries[i]; + const auto& entry = objectList[i]; const ObjectRepositoryItem* ori = nullptr; - if (!object_entry_is_empty(entry)) + if (entry.HasValue()) { ori = _objectRepository.FindObject(entry); - if (ori == nullptr && entry->GetType() != ObjectType::ScenarioText) + if (ori == nullptr && entry.GetType() != ObjectType::ScenarioText) { - missingObjects.push_back(*entry); + missingObjects.push_back(entry); ReportMissingObject(entry); } } @@ -657,7 +612,7 @@ private: { std::vector> objects; std::vector loadedObjects; - std::vector badObjects; + std::vector badObjects; objects.resize(OBJECT_ENTRY_COUNT); loadedObjects.reserve(OBJECT_ENTRY_COUNT); @@ -677,7 +632,7 @@ private: std::lock_guard guard(commonMutex); if (object == nullptr) { - badObjects.push_back(requiredObject->ObjectEntry); + badObjects.push_back(ObjectEntryDescriptor(requiredObject->ObjectEntry)); ReportObjectLoadProblem(&requiredObject->ObjectEntry); } else @@ -778,11 +733,10 @@ private: } } - static void ReportMissingObject(const rct_object_entry* entry) + static void ReportMissingObject(const ObjectEntryDescriptor& entry) { - utf8 objName[DAT_NAME_LENGTH + 1] = { 0 }; - std::copy_n(entry->name, DAT_NAME_LENGTH, objName); - Console::Error::WriteLine("[%s] Object not found.", objName); + std::string name(entry.GetName()); + Console::Error::WriteLine("[%s] Object not found.", name.c_str()); } void ReportObjectLoadProblem(const rct_object_entry* entry) diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index 37f54cfb05..85f1e399c4 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -28,11 +28,10 @@ struct IObjectManager virtual Object* GetLoadedObject(ObjectType objectType, size_t index) abstract; virtual Object* GetLoadedObject(const ObjectEntryDescriptor& entry) abstract; virtual ObjectEntryIndex GetLoadedObjectEntryIndex(const Object* object) abstract; - virtual std::vector GetInvalidObjects(const rct_object_entry* entries) abstract; virtual Object* LoadObject(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 LoadObjects(const std::vector& entries) abstract; virtual void LoadDefaultObjects() abstract; virtual void UnloadObjects(const std::vector& entries) abstract; virtual void UnloadAll() abstract; diff --git a/src/openrct2/platform/platform.h b/src/openrct2/platform/platform.h index e0fb88d3fe..6ea82fa875 100644 --- a/src/openrct2/platform/platform.h +++ b/src/openrct2/platform/platform.h @@ -97,7 +97,6 @@ bool platform_ensure_directory_exists(const utf8* path); bool platform_directory_delete(const utf8* path); std::string platform_get_absolute_path(const utf8* relative_path, const utf8* base_path); bool platform_lock_single_instance(); -bool platform_place_string_on_clipboard(utf8* target); // Returns the bitmask of the GetLogicalDrives function for windows, 0 for other systems int32_t platform_get_drives(); diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index f8b60a8d72..f6645744da 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -1543,26 +1543,26 @@ private: } } - void AppendRequiredObjects(std::vector& entries, ObjectType objectType, const EntryList& entryList) + void AppendRequiredObjects(std::vector& entries, ObjectType objectType, const EntryList& entryList) { AppendRequiredObjects(entries, objectType, entryList.GetEntries()); } void AppendRequiredObjects( - std::vector& entries, ObjectType objectType, const std::vector& objectNames) + std::vector& entries, ObjectType objectType, const std::vector& objectNames) { for (const auto objectName : objectNames) { rct_object_entry entry{}; entry.flags = ((static_cast(ObjectSourceGame::RCT2) << 4) & 0xF0) | (EnumValue(objectType) & 0x0F); entry.SetName(objectName); - entries.push_back(entry); + entries.push_back(ObjectEntryDescriptor(entry)); } } - std::vector GetRequiredObjects() + std::vector GetRequiredObjects() { - std::vector result; + std::vector result; AppendRequiredObjects(result, ObjectType::Ride, _rideEntries); AppendRequiredObjects(result, ObjectType::SmallScenery, _smallSceneryEntries); AppendRequiredObjects(result, ObjectType::LargeScenery, _largeSceneryEntries); @@ -3051,7 +3051,7 @@ void load_from_sv4(const utf8* path) auto& objectMgr = GetContext()->GetObjectManager(); auto s4Importer = std::make_unique(); auto result = s4Importer->LoadSavedGame(path); - objectMgr.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectMgr.LoadObjects(result.RequiredObjects); s4Importer->Import(); } @@ -3060,6 +3060,6 @@ void load_from_sc4(const utf8* path) auto& objectMgr = GetContext()->GetObjectManager(); auto s4Importer = std::make_unique(); auto result = s4Importer->LoadScenario(path); - objectMgr.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectMgr.LoadObjects(result.RequiredObjects); s4Importer->Import(); } diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 7f6210b877..d7f6bacaee 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1549,22 +1549,19 @@ public: return justText.data(); } - std::vector GetRequiredObjects() + std::vector GetRequiredObjects() { - std::vector result; - rct_object_entry nullEntry = {}; - std::memset(&nullEntry, 0xFF, sizeof(nullEntry)); - + std::vector result; int objectIt = 0; for (int16_t objectType = EnumValue(ObjectType::Ride); objectType <= EnumValue(ObjectType::Water); objectType++) { for (int16_t i = 0; i < rct2_object_entry_group_counts[objectType]; i++, objectIt++) { - result.push_back(_s6.objects[objectIt]); + result.push_back(ObjectEntryDescriptor(_s6.objects[objectIt])); } for (int16_t i = rct2_object_entry_group_counts[objectType]; i < object_entry_group_counts[objectType]; i++) { - result.push_back(nullEntry); + result.push_back({}); } } @@ -1876,7 +1873,7 @@ void load_from_sv6(const char* path) { auto& objectMgr = context->GetObjectManager(); auto result = s6Importer->LoadSavedGame(path); - objectMgr.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objectMgr.LoadObjects(result.RequiredObjects); s6Importer->Import(); game_fix_save_vars(); AutoCreateMapAnimations(); @@ -1916,7 +1913,7 @@ void load_from_sc6(const char* path) try { auto result = s6Importer->LoadScenario(path); - objManager.LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size()); + objManager.LoadObjects(result.RequiredObjects); s6Importer->Import(); game_fix_save_vars(); AutoCreateMapAnimations(); diff --git a/test/tests/PlayTests.cpp b/test/tests/PlayTests.cpp index bc203938d5..b3b6fdefe3 100644 --- a/test/tests/PlayTests.cpp +++ b/test/tests/PlayTests.cpp @@ -45,7 +45,7 @@ static std::unique_ptr localStartGame(const std::string& parkPath) auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadSavedGame(parkPath.c_str(), false); - context->GetObjectManager().LoadObjects(loadResult.RequiredObjects.data(), loadResult.RequiredObjects.size()); + context->GetObjectManager().LoadObjects(loadResult.RequiredObjects); importer->Import(); reset_sprite_spatial_index(); diff --git a/test/tests/S6ImportExportTests.cpp b/test/tests/S6ImportExportTests.cpp index f3ee073f7d..d40661651e 100644 --- a/test/tests/S6ImportExportTests.cpp +++ b/test/tests/S6ImportExportTests.cpp @@ -83,7 +83,7 @@ static bool ImportSave(MemoryStream& stream, std::unique_ptr& context, auto importer = ParkImporter::CreateS6(context->GetObjectRepository()); auto loadResult = importer->LoadFromStream(&stream, false); - objManager.LoadObjects(loadResult.RequiredObjects.data(), loadResult.RequiredObjects.size()); + objManager.LoadObjects(loadResult.RequiredObjects); importer->Import(); GameInit(retainSpatialIndices);