From fdfd9b47601830534e694aa08443bf2c45a65dce Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 6 Dec 2021 16:58:50 +0000 Subject: [PATCH] Make track designs NSF map size safe (#16116) * Make track designs NSF map size safe * Increment network version --- src/openrct2/core/DataSerialiserTraits.h | 10 ++--- src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/rct2/T6Exporter.cpp | 6 +-- src/openrct2/rct2/T6Importer.cpp | 6 +-- src/openrct2/ride/TrackDesign.cpp | 57 ++++++++++-------------- src/openrct2/ride/TrackDesign.h | 4 +- src/openrct2/ride/TrackDesignSave.cpp | 12 +---- 7 files changed, 36 insertions(+), 61 deletions(-) diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index 8ef60287ba..e4855f5068 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -716,9 +716,7 @@ template<> struct DataSerializerTraits_t { 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 } 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 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(); diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index a734c8c401..d210eac02d 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -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; diff --git a/src/openrct2/rct2/T6Exporter.cpp b/src/openrct2/rct2/T6Exporter.cpp index 276e84ddb2..57014a011d 100644 --- a/src/openrct2/rct2/T6Exporter.cpp +++ b/src/openrct2/rct2/T6Exporter.cpp @@ -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(sceneryElement.x); - tempStream.WriteValue(sceneryElement.y); - tempStream.WriteValue(sceneryElement.z); + tempStream.WriteValue(sceneryElement.loc.x / COORDS_XY_STEP); + tempStream.WriteValue(sceneryElement.loc.y / COORDS_XY_STEP); + tempStream.WriteValue(sceneryElement.loc.z / COORDS_Z_STEP); tempStream.WriteValue(sceneryElement.flags); tempStream.WriteValue(sceneryElement.primary_colour); tempStream.WriteValue(sceneryElement.secondary_colour); diff --git a/src/openrct2/rct2/T6Importer.cpp b/src/openrct2/rct2/T6Importer.cpp index 6df127d463..173da798d3 100644 --- a/src/openrct2/rct2/T6Importer.cpp +++ b/src/openrct2/rct2/T6Importer.cpp @@ -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; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 2b0b3cfaf9..849dc28507 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -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(scenery.x), static_cast(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(sceneryTilePos.x); - scenery.y = static_cast(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(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); diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index e032db9daa..e5bee7c288 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -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; diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 67d1896348..150e9a4d00 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -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;