summaryrefslogtreecommitdiff
path: root/src/saveload
diff options
context:
space:
mode:
authorCharles Pigott <charlespigott@googlemail.com>2020-01-03 12:14:06 +0000
committerCharles Pigott <charlespigott@googlemail.com>2020-01-05 20:51:26 +0000
commitcddb8a4605570666e076ab0e0f7b1f986f393e17 (patch)
treefa11a2be2737998ac42bdc96ea36fff0deef5c3f /src/saveload
parent12380fc1bb952d5b8a368249082cd85291a78e82 (diff)
downloadopenttd-cddb8a4605570666e076ab0e0f7b1f986f393e17.tar.xz
Fix #7587: Crash when loading saves with waypoints with invalid locations
Diffstat (limited to 'src/saveload')
-rw-r--r--src/saveload/waypoint_sl.cpp45
1 files changed, 29 insertions, 16 deletions
diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp
index c0570f81d..0cba4b8d0 100644
--- a/src/saveload/waypoint_sl.cpp
+++ b/src/saveload/waypoint_sl.cpp
@@ -9,6 +9,7 @@
#include "../stdafx.h"
#include "../waypoint_base.h"
+#include "../debug.h"
#include "../newgrf_station.h"
#include "../vehicle_base.h"
#include "../town.h"
@@ -98,33 +99,45 @@ void MoveWaypointsToBaseStations()
/* All saveload conversions have been done. Create the new waypoints! */
for (OldWaypoint &wp : _old_waypoints) {
- Waypoint *new_wp = new Waypoint(wp.xy);
+ TileIndex t = wp.xy;
+ /* Sometimes waypoint (sign) locations became disconnected from their actual location in
+ * the map array. If this is the case, try to locate the actual location in the map array */
+ if (!IsTileType(t, MP_RAILWAY) || GetRailTileType(t) != 2 /* RAIL_TILE_WAYPOINT */ || _m[t].m2 != wp.index) {
+ DEBUG(sl, 0, "Found waypoint tile %u with invalid position", t);
+ for (t = 0; t < MapSize(); t++) {
+ if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp.index) {
+ DEBUG(sl, 0, "Found actual waypoint position at %u", t);
+ break;
+ }
+ }
+ }
+ if (t == MapSize()) {
+ SlErrorCorrupt("Waypoint with invalid tile");
+ }
+
+ Waypoint *new_wp = new Waypoint(t);
new_wp->town = wp.town;
new_wp->town_cn = wp.town_cn;
new_wp->name = wp.name;
new_wp->delete_ctr = 0; // Just reset delete counter for once.
new_wp->build_date = wp.build_date;
new_wp->owner = wp.owner;
+ new_wp->string_id = STR_SV_STNAME_WAYPOINT;
- new_wp->string_id = STR_SV_STNAME_WAYPOINT;
+ /* The tile might've been reserved! */
+ bool reserved = !IsSavegameVersionBefore(SLV_100) && HasBit(_m[t].m5, 4);
- TileIndex t = wp.xy;
- if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp.index) {
- /* The tile might've been reserved! */
- bool reserved = !IsSavegameVersionBefore(SLV_100) && HasBit(_m[t].m5, 4);
+ /* The tile really has our waypoint, so reassign the map array */
+ MakeRailWaypoint(t, GetTileOwner(t), new_wp->index, (Axis)GB(_m[t].m5, 0, 1), 0, GetRailType(t));
+ new_wp->facilities |= FACIL_TRAIN;
+ new_wp->owner = GetTileOwner(t);
- /* The tile really has our waypoint, so reassign the map array */
- MakeRailWaypoint(t, GetTileOwner(t), new_wp->index, (Axis)GB(_m[t].m5, 0, 1), 0, GetRailType(t));
- new_wp->facilities |= FACIL_TRAIN;
- new_wp->owner = GetTileOwner(t);
+ SetRailStationReservation(t, reserved);
- SetRailStationReservation(t, reserved);
-
- if (wp.spec != nullptr) {
- SetCustomStationSpecIndex(t, AllocateSpecToStation(wp.spec, new_wp, true));
- }
- new_wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
+ if (wp.spec != nullptr) {
+ SetCustomStationSpecIndex(t, AllocateSpecToStation(wp.spec, new_wp, true));
}
+ new_wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
wp.new_index = new_wp->index;
}