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:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user