1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 04:23:20 +01:00

Make track designs NSF map size safe (#16116)

* Make track designs NSF map size safe

* Increment network version
This commit is contained in:
Duncan
2021-12-06 16:58:50 +00:00
committed by GitHub
parent bd9f7d56c5
commit fdfd9b4760
7 changed files with 36 additions and 61 deletions

View File

@@ -520,27 +520,20 @@ rct_string_id TrackDesign::CreateTrackDesignScenery(TrackDesignState& tds)
}
}
// Cast the value into a uint8_t as this value is not signed yet.
auto sceneryPos = TileCoordsXY(static_cast<uint8_t>(scenery.x), static_cast<uint8_t>(scenery.y)).ToCoordsXY();
CoordsXY sceneryMapPos = sceneryPos - tds.Origin;
CoordsXY rotatedSceneryMapPos = sceneryMapPos.Rotate(0 - _saveDirection);
TileCoordsXY sceneryTilePos{ rotatedSceneryMapPos };
const auto relativeMapPosition = scenery.loc - tds.Origin;
const CoordsXY rotatedRelativeMapPos = relativeMapPosition.Rotate(0 - _saveDirection);
if (sceneryTilePos.x > 127 || sceneryTilePos.y > 127 || sceneryTilePos.x < -126 || sceneryTilePos.y < -126)
if (rotatedRelativeMapPos.x > 127 * COORDS_XY_STEP || rotatedRelativeMapPos.y > 127 * COORDS_XY_STEP
|| rotatedRelativeMapPos.x < -126 * COORDS_XY_STEP || rotatedRelativeMapPos.y < -126 * COORDS_XY_STEP)
{
return STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY;
}
scenery.x = static_cast<int8_t>(sceneryTilePos.x);
scenery.y = static_cast<int8_t>(sceneryTilePos.y);
int32_t z = scenery.z * COORDS_Z_STEP - tds.Origin.z;
z /= COORDS_Z_STEP;
if (z > 127 || z < -126)
if (relativeMapPosition.z > 127 * COORDS_Z_STEP || relativeMapPosition.z < -126 * COORDS_Z_STEP)
{
return STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY;
}
scenery.z = z;
scenery.loc = CoordsXYZ(rotatedRelativeMapPos, relativeMapPosition.z);
}
return STR_NONE;
@@ -789,19 +782,19 @@ static void TrackDesignMirrorScenery(TrackDesign* td6)
switch (scenery.flags & 3)
{
case 0:
scenery.y = (-(scenery.y * 32 + y1) - y2) / 32;
scenery.loc.y = -(scenery.loc.y + y1) - y2;
break;
case 1:
scenery.x = (scenery.x * 32 + y2 + y1) / 32;
scenery.y = (-(scenery.y * 32)) / 32;
scenery.loc.x = scenery.loc.x + y2 + y1;
scenery.loc.y = -scenery.loc.y;
scenery.flags ^= (1 << 1);
break;
case 2:
scenery.y = (-(scenery.y * 32 - y2) + y1) / 32;
scenery.loc.y = -(scenery.loc.y - y2) + y1;
break;
case 3:
scenery.x = (scenery.x * 32 - y2 - y1) / 32;
scenery.y = (-(scenery.y * 32)) / 32;
scenery.loc.x = scenery.loc.x - y2 - y1;
scenery.loc.y = -scenery.loc.y;
scenery.flags ^= (1 << 1);
break;
}
@@ -810,7 +803,7 @@ static void TrackDesignMirrorScenery(TrackDesign* td6)
case ObjectType::SmallScenery:
{
auto* sceneryEntry = reinterpret_cast<const SmallSceneryEntry*>(obj->GetLegacyData());
scenery.y = -scenery.y;
scenery.loc.y = -scenery.loc.y;
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_DIAGONAL))
{
@@ -831,7 +824,7 @@ static void TrackDesignMirrorScenery(TrackDesign* td6)
}
case ObjectType::Walls:
{
scenery.y = -scenery.y;
scenery.loc.y = -scenery.loc.y;
if (scenery.flags & (1 << 0))
{
scenery.flags ^= (1 << 1);
@@ -841,7 +834,7 @@ static void TrackDesignMirrorScenery(TrackDesign* td6)
case ObjectType::Paths:
case ObjectType::FootpathSurface:
{
scenery.y = -scenery.y;
scenery.loc.y = -scenery.loc.y;
if (scenery.flags & (1 << 5))
{
@@ -965,7 +958,7 @@ static GameActions::Result TrackDesignPlaceSceneryElementRemoveGhost(
return GameActions::Result();
}
int32_t z = (scenery.z * COORDS_Z_STEP) + originZ;
int32_t z = scenery.loc.z + originZ;
uint8_t sceneryRotation = (rotation + scenery.flags) & TILE_ELEMENT_DIRECTION_MASK;
const uint32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND
| GAME_COMMAND_FLAG_GHOST;
@@ -1008,7 +1001,7 @@ static GameActions::Result TrackDesignPlaceSceneryElementRemoveGhost(
static bool TrackDesignPlaceSceneryElementGetPlaceZ(TrackDesignState& tds, const TrackDesignSceneryElement& scenery)
{
int32_t z = scenery.z * COORDS_Z_STEP + tds.PlaceZ;
int32_t z = scenery.loc.z + tds.PlaceZ;
if (z < tds.PlaceSceneryZ)
{
tds.PlaceSceneryZ = z;
@@ -1068,7 +1061,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
rotation += scenery.flags;
rotation &= 3;
z = scenery.z * COORDS_Z_STEP + originZ;
z = scenery.loc.z + originZ;
quadrant = ((scenery.flags >> 2) + _currentTrackPieceDirection) & 3;
flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_PATH_SCENERY;
@@ -1112,7 +1105,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
rotation += scenery.flags;
rotation &= 3;
z = scenery.z * COORDS_Z_STEP + originZ;
z = scenery.loc.z + originZ;
flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_PATH_SCENERY;
if (tds.PlaceOperation == PTD_OPERATION_PLACE_TRACK_PREVIEW)
@@ -1149,7 +1142,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
return GameActions::Result();
}
z = scenery.z * COORDS_Z_STEP + originZ;
z = scenery.loc.z + originZ;
rotation += scenery.flags;
rotation &= 3;
@@ -1184,7 +1177,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
}
case ObjectType::Paths:
case ObjectType::FootpathSurface:
z = (scenery.z * COORDS_Z_STEP + originZ) / COORDS_Z_STEP;
z = scenery.loc.z + originZ;
if (mode == 0)
{
auto isQueue = scenery.IsQueue();
@@ -1223,8 +1216,7 @@ static GameActions::Result TrackDesignPlaceSceneryElement(
if (entryInfo->Type == ObjectType::Paths)
constructFlags |= PathConstructFlag::IsLegacyPathObject;
auto footpathPlaceAction = FootpathPlaceFromTrackAction(
{ mapCoord.x, mapCoord.y, z * COORDS_Z_STEP }, slope, entryInfo->Index, entryInfo->SecondaryIndex, edges,
constructFlags);
{ mapCoord.x, mapCoord.y, z }, slope, entryInfo->Index, entryInfo->SecondaryIndex, edges, constructFlags);
footpathPlaceAction.SetFlags(flags);
auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&footpathPlaceAction)
: GameActions::QueryNested(&footpathPlaceAction);
@@ -1303,11 +1295,8 @@ static GameActions::Result TrackDesignPlaceAllScenery(
for (const auto& scenery : sceneryList)
{
uint8_t rotation = _currentTrackPieceDirection;
TileCoordsXY tileCoords = TileCoordsXY(origin);
TileCoordsXY offsets = { scenery.x, scenery.y };
tileCoords += offsets.Rotate(rotation);
auto mapCoord = CoordsXYZ{ tileCoords.ToCoordsXY(), origin.z };
auto mapCoord = CoordsXYZ{ CoordsXY(origin) + scenery.loc.Rotate(rotation), origin.z };
TrackDesignUpdatePreviewBounds(tds, mapCoord);
auto placementRes = TrackDesignPlaceSceneryElement(tds, mapCoord, mode, scenery, rotation, origin.z);