1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-24 00:03:11 +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

@@ -716,9 +716,7 @@ template<> struct DataSerializerTraits_t<TrackDesignSceneryElement>
{
static void encode(OpenRCT2::IStream* stream, const TrackDesignSceneryElement& val)
{
stream->Write(&val.x);
stream->Write(&val.y);
stream->Write(&val.z);
stream->Write(&val.loc);
stream->Write(&val.flags);
stream->Write(&val.primary_colour);
stream->Write(&val.secondary_colour);
@@ -727,9 +725,7 @@ template<> struct DataSerializerTraits_t<TrackDesignSceneryElement>
}
static void decode(OpenRCT2::IStream* stream, TrackDesignSceneryElement& val)
{
stream->Read(&val.x);
stream->Read(&val.y);
stream->Read(&val.z);
stream->Read(&val.loc);
stream->Read(&val.flags);
stream->Read(&val.primary_colour);
stream->Read(&val.secondary_colour);
@@ -741,7 +737,7 @@ template<> struct DataSerializerTraits_t<TrackDesignSceneryElement>
char msg[128] = {};
snprintf(
msg, sizeof(msg), "TrackDesignSceneryElement(x = %d, y = %d, z = %d, flags = %d, colour1 = %d, colour2 = %d)",
val.x, val.y, val.z, val.flags, val.primary_colour, val.secondary_colour);
val.loc.x, val.loc.y, val.loc.z, val.flags, val.primary_colour, val.secondary_colour);
stream->Write(msg, strlen(msg));
auto identifier = val.scenery_object.GetName();

View File

@@ -40,7 +40,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "3"
#define NETWORK_STREAM_VERSION "4"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static Peep* _pickup_peep = nullptr;

View File

@@ -127,9 +127,9 @@ namespace RCT2
for (const auto& sceneryElement : _trackDesign->scenery_elements)
{
tempStream.Write(&sceneryElement.scenery_object.Entry, sizeof(rct_object_entry));
tempStream.WriteValue<int8_t>(sceneryElement.x);
tempStream.WriteValue<int8_t>(sceneryElement.y);
tempStream.WriteValue<int8_t>(sceneryElement.z);
tempStream.WriteValue<int8_t>(sceneryElement.loc.x / COORDS_XY_STEP);
tempStream.WriteValue<int8_t>(sceneryElement.loc.y / COORDS_XY_STEP);
tempStream.WriteValue<int8_t>(sceneryElement.loc.z / COORDS_Z_STEP);
tempStream.WriteValue<uint8_t>(sceneryElement.flags);
tempStream.WriteValue<uint8_t>(sceneryElement.primary_colour);
tempStream.WriteValue<uint8_t>(sceneryElement.secondary_colour);

View File

@@ -203,9 +203,9 @@ namespace RCT2
_stream.Read(&t6SceneryElement, sizeof(TD6SceneryElement));
TrackDesignSceneryElement sceneryElement{};
sceneryElement.scenery_object = ObjectEntryDescriptor(t6SceneryElement.scenery_object);
sceneryElement.x = t6SceneryElement.x;
sceneryElement.y = t6SceneryElement.y;
sceneryElement.z = t6SceneryElement.z;
sceneryElement.loc.x = t6SceneryElement.x * COORDS_XY_STEP;
sceneryElement.loc.y = t6SceneryElement.y * COORDS_XY_STEP;
sceneryElement.loc.z = t6SceneryElement.z * COORDS_Z_STEP;
sceneryElement.flags = t6SceneryElement.flags;
sceneryElement.primary_colour = t6SceneryElement.primary_colour;
sceneryElement.secondary_colour = t6SceneryElement.secondary_colour;

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);

View File

@@ -47,9 +47,7 @@ struct TrackDesignEntranceElement
struct TrackDesignSceneryElement
{
ObjectEntryDescriptor scenery_object;
int8_t x;
int8_t y;
int8_t z;
CoordsXYZ loc;
uint8_t flags;
uint8_t primary_colour;
uint8_t secondary_colour;

View File

@@ -217,12 +217,9 @@ static bool track_design_is_supported_object(const Object* obj)
static void track_design_save_push_tile_element_desc(
const rct_object_entry& entry, const CoordsXYZ& loc, uint8_t flags, uint8_t primaryColour, uint8_t secondaryColour)
{
auto tileLoc = TileCoordsXYZ(loc);
TrackDesignSceneryElement item{};
item.scenery_object = ObjectEntryDescriptor(entry);
item.x = tileLoc.x;
item.y = tileLoc.y;
item.z = tileLoc.z;
item.loc = loc;
item.flags = flags;
item.primary_colour = primaryColour;
item.secondary_colour = secondaryColour;
@@ -442,15 +439,10 @@ static void track_design_save_pop_tile_element(const CoordsXY& loc, TileElement*
static void track_design_save_pop_tile_element_desc(const ObjectEntryDescriptor& entry, const CoordsXYZ& loc, uint8_t flags)
{
size_t removeIndex = SIZE_MAX;
auto tileLoc = TileCoordsXYZ(loc);
for (size_t i = 0; i < _trackSavedTileElementsDesc.size(); i++)
{
TrackDesignSceneryElement* item = &_trackSavedTileElementsDesc[i];
if (item->x != tileLoc.x)
continue;
if (item->y != tileLoc.y)
continue;
if (item->z != tileLoc.z)
if (item->loc != loc)
continue;
if (item->flags != flags)
continue;