From fa3f2ae035a2ad1bcb83b6bbc1e05b21911b5844 Mon Sep 17 00:00:00 2001 From: michi_cc Date: Tue, 9 Sep 2008 19:02:47 +0000 Subject: [PATCH] (svn r14285) -Fix [FS#2263]: A train inside a wormhole could free the reservation of another train inside the wormhole. --- src/train_cmd.cpp | 21 ++++++++++++--------- src/vehicle.cpp | 8 +++++--- src/vehicle_func.h | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 3c01f435a6..f03e1a06b4 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -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. */ -static void ClearPathReservation(TileIndex tile, Trackdir track_dir) +static void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir) { DiagDirection dir = TrackdirToExitdir(track_dir); @@ -2433,12 +2433,15 @@ static void ClearPathReservation(TileIndex tile, Trackdir track_dir) if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { TileIndex end = GetOtherTunnelBridgeEnd(tile); - SetTunnelBridgeReservation(tile, false); - SetTunnelBridgeReservation(end, false); + if (!HasVehicleOnTunnelBridge(tile, end, v)) { + /* 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) { - MarkTileDirtyByTile(tile); - MarkTileDirtyByTile(end); + if (_settings_client.gui.show_track_reservation) { + MarkTileDirtyByTile(tile); + MarkTileDirtyByTile(end); + } } } } 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. */ - 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; } @@ -3402,7 +3405,7 @@ static void SetVehicleCrashed(Vehicle *v) * and any railway station paltform reservation. */ FreeTrainTrackReservation(v); 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)) { /* ClearPathReservation will not free the wormhole exit * 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 */ - if (v->Next() == NULL) ClearPathReservation(v->tile, GetVehicleTrackdir(v)); + if (v->Next() == NULL) ClearPathReservation(v, v->tile, GetVehicleTrackdir(v)); v->tile = gp.new_tile; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a3886c7057..ce757c470c 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -178,6 +178,7 @@ bool EnsureNoVehicleOnGround(TileIndex tile) static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data) { 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); return v; @@ -187,12 +188,13 @@ static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data) * Finds vehicle in tunnel / bridge * @param tile first end * @param endtile second end + * @param ignore Ignore this vehicle when searching * @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) || - HasVehicleOnPos(endtile, NULL, &GetVehicleTunnelBridgeProc); + return HasVehicleOnPos(tile, (void *)ignore, &GetVehicleTunnelBridgeProc) || + HasVehicleOnPos(endtile, (void *)ignore, &GetVehicleTunnelBridgeProc); } diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 754004d59b..ec679776d0 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -51,7 +51,7 @@ SpriteID GetRotorImage(const Vehicle *v); uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y); 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 CheckVehicleBreakdown(Vehicle *v);