(svn r14285) -Fix [FS#2263]: A train inside a wormhole could free the reservation of another train inside the wormhole.

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
michi_cc 16 years ago
parent a7a7e2d3cc
commit fa3f2ae035

@ -2424,7 +2424,7 @@ static bool CheckTrainStayInDepot(Vehicle *v)
} }
/** Clear the reservation of a tile that was just left by a wagon on track_dir. */ /** Clear the reservation of a tile that was just left by a wagon on track_dir. */
static void ClearPathReservation(TileIndex tile, Trackdir track_dir) static void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir)
{ {
DiagDirection dir = TrackdirToExitdir(track_dir); DiagDirection dir = TrackdirToExitdir(track_dir);
@ -2433,12 +2433,15 @@ static void ClearPathReservation(TileIndex tile, Trackdir track_dir)
if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
TileIndex end = GetOtherTunnelBridgeEnd(tile); TileIndex end = GetOtherTunnelBridgeEnd(tile);
SetTunnelBridgeReservation(tile, false); if (!HasVehicleOnTunnelBridge(tile, end, v)) {
SetTunnelBridgeReservation(end, false); /* Free the reservation only if no other train is on the tiles. */
SetTunnelBridgeReservation(tile, false);
SetTunnelBridgeReservation(end, false);
if (_settings_client.gui.show_track_reservation) { if (_settings_client.gui.show_track_reservation) {
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(end); MarkTileDirtyByTile(end);
}
} }
} }
} else if (IsRailwayStationTile(tile)) { } else if (IsRailwayStationTile(tile)) {
@ -2497,7 +2500,7 @@ void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin, Trackdir orig
} }
/* Don't free first station/bridge/tunnel if we are on it. */ /* Don't free first station/bridge/tunnel if we are on it. */
if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(tile, td); if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td);
free_tile = true; free_tile = true;
} }
@ -3402,7 +3405,7 @@ static void SetVehicleCrashed(Vehicle *v)
* and any railway station paltform reservation. */ * and any railway station paltform reservation. */
FreeTrainTrackReservation(v); FreeTrainTrackReservation(v);
for (const Vehicle *u = v; u != NULL; u = u->Next()) { for (const Vehicle *u = v; u != NULL; u = u->Next()) {
ClearPathReservation(u->tile, GetVehicleTrackdir(u)); ClearPathReservation(u, u->tile, GetVehicleTrackdir(u));
if (IsTileType(u->tile, MP_TUNNELBRIDGE)) { if (IsTileType(u->tile, MP_TUNNELBRIDGE)) {
/* ClearPathReservation will not free the wormhole exit /* ClearPathReservation will not free the wormhole exit
* if the train has just entered the wormhole. */ * if the train has just entered the wormhole. */
@ -3703,7 +3706,7 @@ static void TrainController(Vehicle *v, Vehicle *nomove, bool update_image)
} }
/* Clear any track reservation when the last vehicle leaves the tile */ /* Clear any track reservation when the last vehicle leaves the tile */
if (v->Next() == NULL) ClearPathReservation(v->tile, GetVehicleTrackdir(v)); if (v->Next() == NULL) ClearPathReservation(v, v->tile, GetVehicleTrackdir(v));
v->tile = gp.new_tile; v->tile = gp.new_tile;

@ -178,6 +178,7 @@ bool EnsureNoVehicleOnGround(TileIndex tile)
static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data) static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
{ {
if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return NULL; if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return NULL;
if (v == (const Vehicle *)data) return NULL;
_error_message = VehicleInTheWayErrMsg(v); _error_message = VehicleInTheWayErrMsg(v);
return v; return v;
@ -187,12 +188,13 @@ static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
* Finds vehicle in tunnel / bridge * Finds vehicle in tunnel / bridge
* @param tile first end * @param tile first end
* @param endtile second end * @param endtile second end
* @param ignore Ignore this vehicle when searching
* @return true if the bridge has a vehicle * @return true if the bridge has a vehicle
*/ */
bool HasVehicleOnTunnelBridge(TileIndex tile, TileIndex endtile) bool HasVehicleOnTunnelBridge(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
{ {
return HasVehicleOnPos(tile, NULL, &GetVehicleTunnelBridgeProc) || return HasVehicleOnPos(tile, (void *)ignore, &GetVehicleTunnelBridgeProc) ||
HasVehicleOnPos(endtile, NULL, &GetVehicleTunnelBridgeProc); HasVehicleOnPos(endtile, (void *)ignore, &GetVehicleTunnelBridgeProc);
} }

@ -51,7 +51,7 @@ SpriteID GetRotorImage(const Vehicle *v);
uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y); uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y);
StringID VehicleInTheWayErrMsg(const Vehicle* v); StringID VehicleInTheWayErrMsg(const Vehicle* v);
bool HasVehicleOnTunnelBridge(TileIndex tile, TileIndex endtile); bool HasVehicleOnTunnelBridge(TileIndex tile, TileIndex endtile, const Vehicle *ignore = NULL);
void DecreaseVehicleValue(Vehicle *v); void DecreaseVehicleValue(Vehicle *v);
void CheckVehicleBreakdown(Vehicle *v); void CheckVehicleBreakdown(Vehicle *v);

Loading…
Cancel
Save