Fix #14893: Crash in MapCheckCapacityAndReorganise()

This commit is contained in:
Duncan 2021-06-13 12:34:54 +01:00 committed by GitHub
parent 474e00d48b
commit 7e84e0ef3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 42 additions and 68 deletions

View File

@ -55,17 +55,17 @@ GameActions::Result::Ptr BannerPlaceAction::Query() const
res->Expenditure = ExpenditureType::Landscaping;
res->ErrorTitle = STR_CANT_POSITION_THIS_HERE;
if (!LocationValid(_loc))
{
return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE);
}
if (!MapCheckCapacityAndReorganise(_loc))
{
log_error("No free map elements.");
return MakeResult(GameActions::Status::NoFreeElements, STR_CANT_POSITION_THIS_HERE);
}
if (!LocationValid(_loc))
{
return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE);
}
auto pathElement = GetValidPathElement();
if (pathElement == nullptr)

View File

@ -142,12 +142,6 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Query() const
}
}
if (!CheckMapCapacity(sceneryEntry->tiles, totalNumTiles))
{
log_error("No free map elements available");
return std::make_unique<LargeSceneryPlaceActionResult>(GameActions::Status::NoFreeElements);
}
uint8_t tileNum = 0;
for (rct_large_scenery_tile* tile = sceneryEntry->tiles; tile->x_offset != -1; tile++, tileNum++)
{
@ -200,6 +194,12 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Query() const
}
}
if (!CheckMapCapacity(sceneryEntry->tiles, totalNumTiles))
{
log_error("No free map elements available");
return std::make_unique<LargeSceneryPlaceActionResult>(GameActions::Status::NoFreeElements);
}
// Force ride construction to recheck area
_currentTrackSelectionFlags |= TRACK_SELECTION_FLAG_RECHECK;
@ -234,7 +234,6 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const
return std::make_unique<LargeSceneryPlaceActionResult>(GameActions::Status::InvalidParameters);
}
uint32_t totalNumTiles = GetTotalNumTiles(sceneryEntry->tiles);
int16_t maxHeight = GetMaxSurfaceHeight(sceneryEntry->tiles);
if (_loc.z != 0)
@ -244,12 +243,6 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const
res->Position.z = maxHeight;
if (!CheckMapCapacity(sceneryEntry->tiles, totalNumTiles))
{
log_error("No free map elements available");
return std::make_unique<LargeSceneryPlaceActionResult>(GameActions::Status::NoFreeElements);
}
uint8_t tileNum = 0;
for (rct_large_scenery_tile* tile = sceneryEntry->tiles; tile->x_offset != -1; tile++, tileNum++)
{

View File

@ -39,12 +39,6 @@ GameActions::Result::Ptr MazePlaceTrackAction::Query() const
res->Position = _loc + CoordsXYZ{ 8, 8, 0 };
res->Expenditure = ExpenditureType::RideConstruction;
res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
if (!MapCheckCapacityAndReorganise(_loc))
{
res->Error = GameActions::Status::NoFreeElements;
res->ErrorMessage = STR_TILE_ELEMENT_LIMIT_REACHED;
return res;
}
if ((_loc.z & 0xF) != 0)
{
res->Error = GameActions::Status::Unknown;
@ -59,6 +53,12 @@ GameActions::Result::Ptr MazePlaceTrackAction::Query() const
return res;
}
if (!MapCheckCapacityAndReorganise(_loc))
{
res->Error = GameActions::Status::NoFreeElements;
res->ErrorMessage = STR_TILE_ELEMENT_LIMIT_REACHED;
return res;
}
auto surfaceElement = map_get_surface_element_at(_loc);
if (surfaceElement == nullptr)
{
@ -135,13 +135,6 @@ GameActions::Result::Ptr MazePlaceTrackAction::Execute() const
return res;
}
if (!MapCheckCapacityAndReorganise(_loc))
{
res->Error = GameActions::Status::NoFreeElements;
res->ErrorMessage = STR_NONE;
return res;
}
uint32_t flags = GetFlags();
if (!(flags & GAME_COMMAND_FLAG_GHOST))
{

View File

@ -51,12 +51,6 @@ GameActions::Result::Ptr MazeSetTrackAction::Query() const
res->Position = _loc + CoordsXYZ{ 8, 8, 0 };
res->Expenditure = ExpenditureType::RideConstruction;
res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE;
if (!MapCheckCapacityAndReorganise(_loc))
{
res->Error = GameActions::Status::NoFreeElements;
res->ErrorMessage = STR_TILE_ELEMENT_LIMIT_REACHED;
return res;
}
if ((_loc.z & 0xF) != 0 && _mode == GC_SET_MAZE_TRACK_BUILD)
{
res->Error = GameActions::Status::Unknown;
@ -71,6 +65,12 @@ GameActions::Result::Ptr MazeSetTrackAction::Query() const
return res;
}
if (!MapCheckCapacityAndReorganise(_loc))
{
res->Error = GameActions::Status::NoFreeElements;
res->ErrorMessage = STR_TILE_ELEMENT_LIMIT_REACHED;
return res;
}
auto surfaceElement = map_get_surface_element_at(_loc);
if (surfaceElement == nullptr)
{
@ -159,13 +159,6 @@ GameActions::Result::Ptr MazeSetTrackAction::Execute() const
return res;
}
if (!MapCheckCapacityAndReorganise(_loc))
{
res->Error = GameActions::Status::NoFreeElements;
res->ErrorMessage = STR_NONE;
return res;
}
uint32_t flags = GetFlags();
if (!(flags & GAME_COMMAND_FLAG_GHOST))
{

View File

@ -51,12 +51,6 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Query() const
res->Expenditure = ExpenditureType::LandPurchase;
res->Position = { _loc.x, _loc.y, _loc.z };
if (!CheckMapCapacity(3))
{
return std::make_unique<GameActions::Result>(
GameActions::Status::NoFreeElements, STR_CANT_BUILD_PARK_ENTRANCE_HERE, STR_NONE);
}
if (!LocationValid(_loc) || _loc.x <= 32 || _loc.y <= 32 || _loc.x >= (gMapSizeUnits - 32)
|| _loc.y >= (gMapSizeUnits - 32))
{
@ -64,6 +58,12 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Query() const
GameActions::Status::InvalidParameters, STR_CANT_BUILD_PARK_ENTRANCE_HERE, STR_TOO_CLOSE_TO_EDGE_OF_MAP);
}
if (!CheckMapCapacity(3))
{
return std::make_unique<GameActions::Result>(
GameActions::Status::NoFreeElements, STR_CANT_BUILD_PARK_ENTRANCE_HERE, STR_NONE);
}
if (gParkEntrances.size() >= MAX_PARK_ENTRANCES)
{
return std::make_unique<GameActions::Result>(

View File

@ -50,10 +50,6 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Query() const
{
auto errorTitle = _isExit ? STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION
: STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION;
if (!MapCheckCapacityAndReorganise(_loc))
{
return MakeResult(GameActions::Status::NoFreeElements, errorTitle);
}
auto ride = get_ride(_rideIndex);
if (ride == nullptr)
@ -98,6 +94,10 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Query() const
return MakeResult(GameActions::Status::NotOwned, errorTitle);
}
if (!MapCheckCapacityAndReorganise(_loc))
{
return MakeResult(GameActions::Status::NoFreeElements, errorTitle);
}
auto clear_z = z + (_isExit ? RideExitHeight : RideEntranceHeight);
auto canBuild = MapCanConstructWithClearAt(
{ _loc, z, clear_z }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, GetFlags());
@ -217,16 +217,16 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::TrackPlaceQuery(const Coor
{
auto errorTitle = isExit ? STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION
: STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION;
if (!MapCheckCapacityAndReorganise(loc))
{
return MakeResult(GameActions::Status::NoFreeElements, errorTitle);
}
if (!gCheatsSandboxMode && !map_is_location_owned(loc))
{
return MakeResult(GameActions::Status::NotOwned, errorTitle);
}
if (!MapCheckCapacityAndReorganise(loc))
{
return MakeResult(GameActions::Status::NoFreeElements, errorTitle);
}
int16_t baseZ = loc.z;
int16_t clearZ = baseZ + (isExit ? RideExitHeight : RideEntranceHeight);
auto canBuild = MapCanConstructWithClearAt({ loc, baseZ, clearZ }, &map_place_non_scenery_clear_func, { 0b1111, 0 }, 0);

View File

@ -111,16 +111,16 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Query() const
res->Position.z = surfaceHeight;
}
if (!MapCheckCapacityAndReorganise(_loc))
{
return std::make_unique<SmallSceneryPlaceActionResult>(GameActions::Status::NoFreeElements);
}
if (!LocationValid(_loc))
{
return MakeResult(GameActions::Status::InvalidParameters);
}
if (!MapCheckCapacityAndReorganise(_loc))
{
return std::make_unique<SmallSceneryPlaceActionResult>(GameActions::Status::NoFreeElements);
}
if (!byte_9D8150 && (_loc.x > gMapSizeMaxXY || _loc.y > gMapSizeMaxXY))
{
return std::make_unique<SmallSceneryPlaceActionResult>(GameActions::Status::InvalidParameters);

View File

@ -361,11 +361,6 @@ GameActions::Result::Ptr WallPlaceAction::Execute() const
}
}
if (!MapCheckCapacityAndReorganise(_loc))
{
return MakeResult(GameActions::Status::NoFreeElements, STR_TILE_ELEMENT_LIMIT_REACHED);
}
if (wallEntry->scrolling_mode != SCROLLING_MODE_NONE)
{
if (_bannerId == BANNER_INDEX_NULL)