diff --git a/distribution/changelog.txt b/distribution/changelog.txt index c1c79aaa31..059b1b227b 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Feature: [#25286] Footpath area dragging tool. - Feature: [#25379] Add an option to the command line screenshot function to draw debug segment heights. +- Improved: [#21375] The `load_object` console command now allows loading JSON objects. - Improved: [#25297] Paths on the ground in SV4/SC4 no longer block supports of the paths above. - Improved: [#25349] ‘Recent Messages’ window can now be fully themed. - Change: [#25089] Peep actions and animations that cause them to stop moving no longer trigger when they are on a level crossing. diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index e24fe91d41..1b8a96615d 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1051,78 +1051,92 @@ static void ConsoleCommandSet(InteractiveConsole& console, const arguments_t& ar static void ConsoleCommandLoadObject(InteractiveConsole& console, const arguments_t& argv) { - if (!argv.empty()) + if (argv.empty()) + { + console.WriteLineError("Please specify an object name."); + return; + } + + auto& objectRepository = GetContext()->GetObjectRepository(); + auto objectName = argv[0]; + + // First, try and find a JSON object by this name + const ObjectRepositoryItem* ori = objectRepository.FindObject(objectName); + + // If this fails, try loading by DAT name + if (ori == nullptr) { char name[9] = { 0 }; std::fill_n(name, 8, ' '); std::size_t i = 0; - for (const char* ch = argv[0].c_str(); *ch != '\0' && i < std::size(name) - 1; ch++) + for (const char* ch = objectName.c_str(); *ch != '\0' && i < std::size(name) - 1; ch++) { name[i++] = *ch; } - const ObjectRepositoryItem* ori = ObjectRepositoryFindObjectByName(name); - if (ori == nullptr) - { - console.WriteLineError("Could not find the object."); - return; - } - - const auto* entry = &ori->ObjectEntry; - const auto* loadedObject = ObjectManagerGetLoadedObject(ObjectEntryDescriptor(*ori)); - if (loadedObject != nullptr) - { - console.WriteLineError("Object is already in scenario."); - return; - } - - loadedObject = ObjectManagerLoadObject(entry); - if (loadedObject == nullptr) - { - console.WriteLineError("Unable to load object."); - return; - } - auto groupIndex = ObjectManagerGetLoadedObjectEntryIndex(loadedObject); - - ObjectType objectType = entry->GetType(); - if (objectType == ObjectType::ride) - { - // Automatically research the ride so it's supported by the game. - const auto* rideEntry = GetRideEntryByIndex(groupIndex); - - for (int32_t j = 0; j < RCT2::ObjectLimits::kMaxRideTypesPerRideEntry; j++) - { - auto rideType = rideEntry->ride_type[j]; - if (rideType != kRideTypeNull) - { - ResearchCategory category = GetRideTypeDescriptor(rideType).GetResearchCategory(); - ResearchInsertRideEntry(rideType, groupIndex, category, true); - } - } - - gSilentResearch = true; - ResearchResetCurrentItem(); - gSilentResearch = false; - } - else if (objectType == ObjectType::sceneryGroup) - { - ResearchInsertSceneryGroupEntry(groupIndex, true); - - gSilentResearch = true; - ResearchResetCurrentItem(); - gSilentResearch = false; - } - - auto sceneryIntent = Intent(INTENT_ACTION_SET_DEFAULT_SCENERY_CONFIG); - ContextBroadcastIntent(&sceneryIntent); - - auto ridesIntent = Intent(INTENT_ACTION_REFRESH_NEW_RIDES); - ContextBroadcastIntent(&ridesIntent); - - gWindowUpdateTicks = 0; - GfxInvalidateScreen(); - console.WriteLine("Object file loaded."); + ori = objectRepository.FindObjectLegacy(name); } + + if (ori == nullptr) + { + console.WriteLineError("Could not find the object."); + return; + } + + const auto* loadedObject = ObjectManagerGetLoadedObject(ObjectEntryDescriptor(*ori)); + if (loadedObject != nullptr) + { + console.WriteLineError("Object is already in scenario."); + return; + } + + auto& objectManager = OpenRCT2::GetContext()->GetObjectManager(); + loadedObject = objectManager.LoadRepositoryItem(*ori); + if (loadedObject == nullptr) + { + console.WriteLineError("Unable to load object."); + return; + } + auto groupIndex = ObjectManagerGetLoadedObjectEntryIndex(loadedObject); + + ObjectType objectType = loadedObject->GetObjectType(); + if (objectType == ObjectType::ride) + { + // Automatically research the ride so it's supported by the game. + const auto* rideEntry = GetRideEntryByIndex(groupIndex); + + for (int32_t j = 0; j < RCT2::ObjectLimits::kMaxRideTypesPerRideEntry; j++) + { + auto rideType = rideEntry->ride_type[j]; + if (rideType != kRideTypeNull) + { + ResearchCategory category = GetRideTypeDescriptor(rideType).GetResearchCategory(); + ResearchInsertRideEntry(rideType, groupIndex, category, true); + } + } + + gSilentResearch = true; + ResearchResetCurrentItem(); + gSilentResearch = false; + } + else if (objectType == ObjectType::sceneryGroup) + { + ResearchInsertSceneryGroupEntry(groupIndex, true); + + gSilentResearch = true; + ResearchResetCurrentItem(); + gSilentResearch = false; + } + + auto sceneryIntent = Intent(INTENT_ACTION_SET_DEFAULT_SCENERY_CONFIG); + ContextBroadcastIntent(&sceneryIntent); + + auto ridesIntent = Intent(INTENT_ACTION_REFRESH_NEW_RIDES); + ContextBroadcastIntent(&ridesIntent); + + gWindowUpdateTicks = 0; + GfxInvalidateScreen(); + console.WriteLine("Object file loaded."); } constexpr auto _objectTypeNames = std::to_array({ diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index b0fe705aa2..714d1290cc 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -202,6 +202,11 @@ namespace OpenRCT2 return RepositoryItemToObject(ori, slot); } + Object* LoadRepositoryItem(const ObjectRepositoryItem& ori) override + { + return RepositoryItemToObject(&ori); + } + void LoadObjects(const ObjectList& objectList, const bool reportProgress) override { // Find all the required objects diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index 3e1420e0c2..ebd128a314 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -44,6 +44,7 @@ namespace OpenRCT2 virtual Object* LoadObject(const RCTObjectEntry* entry) = 0; virtual Object* LoadObject(const ObjectEntryDescriptor& descriptor) = 0; virtual Object* LoadObject(const ObjectEntryDescriptor& descriptor, ObjectEntryIndex slot) = 0; + virtual Object* LoadRepositoryItem(const ObjectRepositoryItem& ori) = 0; virtual void LoadObjects(const ObjectList& entries, const bool reportProgress = false) = 0; virtual void UnloadObjects(const std::vector& entries) = 0; virtual void UnloadAllTransient() = 0;