Merge pull request #17212 from Broxzier/bugfix/17205-terrain-mapgen-crash

This commit is contained in:
Hielke Morsink 2022-05-15 15:52:42 +02:00 committed by GitHub
commit aac14f6ef3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 21 deletions

View File

@ -19,6 +19,7 @@
- Fix: [#17099] Object selection thumbnail box is one pixel too tall.
- Fix: [#17104] Changing map size does not invalidate park size.
- Fix: [#17197] Segfault when extracting files from the GOG installer.
- Fix: [#17205] Map generator sometimes crashes when not all standard terrain objects are available.
0.4.0 (2022-04-25)
------------------------------------------------------------------------

View File

@ -64,6 +64,6 @@ void TerrainEdgeObject::ReadJson(IReadObjectContext* context, json_t& root)
TerrainEdgeObject* TerrainEdgeObject::GetById(ObjectEntryIndex entryIndex)
{
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objMgr.GetLoadedObject(ObjectType::TerrainSurface, entryIndex);
return obj != nullptr ? static_cast<TerrainEdgeObject*>(obj) : nullptr;
auto* obj = objMgr.GetLoadedObject(ObjectType::TerrainEdge, entryIndex);
return static_cast<TerrainEdgeObject*>(obj);
}

View File

@ -160,6 +160,6 @@ uint32_t TerrainSurfaceObject::GetImageId(
TerrainSurfaceObject* TerrainSurfaceObject::GetById(ObjectEntryIndex entryIndex)
{
auto& objMgr = OpenRCT2::GetContext()->GetObjectManager();
auto obj = objMgr.GetLoadedObject(ObjectType::TerrainSurface, entryIndex);
return obj != nullptr ? static_cast<TerrainSurfaceObject*>(obj) : nullptr;
auto* obj = objMgr.GetLoadedObject(ObjectType::TerrainSurface, entryIndex);
return static_cast<TerrainSurfaceObject*>(obj);
}

View File

@ -144,12 +144,24 @@ void mapgen_generate(mapgen_settings* settings)
auto mapSize = settings->mapSize;
auto waterLevel = settings->water_level;
const auto selectedFloor = TerrainSurfaceObject::GetById(settings->floor);
std::string floorTexture = selectedFloor != nullptr ? std::string(selectedFloor->GetIdentifier()) : "";
std::string_view floorTexture = selectedFloor != nullptr ? selectedFloor->GetIdentifier() : "";
const auto selectedEdge = TerrainEdgeObject::GetById(settings->wall);
std::string edgeTexture = selectedFloor != nullptr ? std::string(selectedEdge->GetIdentifier()) : "";
std::string_view edgeTexture = selectedFloor != nullptr ? selectedEdge->GetIdentifier() : "";
auto& objectManager = OpenRCT2::GetContext()->GetObjectManager();
if (floorTexture.empty())
floorTexture = BaseTerrain[util_rand() % std::size(BaseTerrain)];
{
std::vector<std::string_view> availableTerrains;
std::copy_if(std::begin(BaseTerrain), std::end(BaseTerrain), std::back_inserter(availableTerrains), [&](auto terrain) {
return objectManager.GetLoadedObject(ObjectEntryDescriptor(terrain)) != nullptr;
});
if (availableTerrains.empty())
// Fall back to the first available surface texture that is available in the park
floorTexture = TerrainSurfaceObject::GetById(0)->GetIdentifier();
else
floorTexture = availableTerrains[util_rand() % availableTerrains.size()];
}
if (edgeTexture.empty())
{
@ -160,10 +172,14 @@ void mapgen_generate(mapgen_settings* settings)
edgeTexture = "rct2.terrain_edge.ice";
else
edgeTexture = "rct2.terrain_edge.rock";
// Fall back to the first available edge texture that is available in the park
if (objectManager.GetLoadedObject(ObjectEntryDescriptor(edgeTexture)) == nullptr)
edgeTexture = TerrainEdgeObject::GetById(0)->GetIdentifier();
}
auto floorTextureId = object_manager_get_loaded_object_entry_index(ObjectEntryDescriptor(floorTexture));
auto edgeTextureId = object_manager_get_loaded_object_entry_index(ObjectEntryDescriptor(edgeTexture));
auto floorTextureId = objectManager.GetLoadedObjectEntryIndex(ObjectEntryDescriptor(floorTexture));
auto edgeTextureId = objectManager.GetLoadedObjectEntryIndex(ObjectEntryDescriptor(edgeTexture));
map_clear_all_elements();
@ -205,20 +221,19 @@ void mapgen_generate(mapgen_settings* settings)
mapgen_set_water_level(waterLevel);
// Add sandy beaches
std::string beachTexture = std::string(floorTexture);
if (settings->floor == -1 && floorTexture == "rct2.terrain_surface.grass")
std::string_view beachTexture = floorTexture;
if (settings->floor == -1 && floorTexture == "rct2.terrain_surface.grass" && (util_rand() & 1))
{
switch (util_rand() % 4)
{
case 0:
beachTexture = "rct2.terrain_surface.sand";
break;
case 1:
beachTexture = "rct2.terrain_surface.sand_brown";
break;
}
std::vector<std::string_view> availableBeachTextures;
if (objectManager.GetLoadedObject(ObjectEntryDescriptor("rct2.terrain_surface.sand")) != nullptr)
availableBeachTextures.push_back("rct2.terrain_surface.sand");
if (objectManager.GetLoadedObject(ObjectEntryDescriptor("rct2.terrain_surface.sand_brown")) != nullptr)
availableBeachTextures.push_back("rct2.terrain_surface.sand_brown");
if (!availableBeachTextures.empty())
beachTexture = availableBeachTextures[util_rand() % availableBeachTextures.size()];
}
auto beachTextureId = object_manager_get_loaded_object_entry_index(ObjectEntryDescriptor(beachTexture));
auto beachTextureId = objectManager.GetLoadedObjectEntryIndex(ObjectEntryDescriptor(beachTexture));
for (auto y = 1; y < mapSize - 1; y++)
{