(svn r14285) -Fix [FS#2263]: A train inside a wormhole could free the reservation of another train inside the wormhole.
authormichi_cc
Tue, 09 Sep 2008 19:02:47 +0000
changeset 10103 ad05ade1f2c4
parent 10102 dcd66d9d53af
child 10104 fb4346183ffe
(svn r14285) -Fix [FS#2263]: A train inside a wormhole could free the reservation of another train inside the wormhole.
src/train_cmd.cpp
src/vehicle.cpp
src/vehicle_func.h
--- a/src/train_cmd.cpp	Tue Sep 09 18:47:53 2008 +0000
+++ b/src/train_cmd.cpp	Tue Sep 09 19:02:47 2008 +0000
@@ -2424,7 +2424,7 @@
 }
 
 /** 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 @@
 		if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
 			TileIndex end = GetOtherTunnelBridgeEnd(tile);
 
-			SetTunnelBridgeReservation(tile, false);
-			SetTunnelBridgeReservation(end, false);
-
-			if (_settings_client.gui.show_track_reservation) {
-				MarkTileDirtyByTile(tile);
-				MarkTileDirtyByTile(end);
+			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);
+				}
 			}
 		}
 	} else if (IsRailwayStationTile(tile)) {
@@ -2497,7 +2500,7 @@
 		}
 
 		/* 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 @@
 		 * 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 @@
 					}
 
 					/* 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;
 
--- a/src/vehicle.cpp	Tue Sep 09 18:47:53 2008 +0000
+++ b/src/vehicle.cpp	Tue Sep 09 19:02:47 2008 +0000
@@ -178,6 +178,7 @@
 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 @@
  * 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);
 }
 
 
--- a/src/vehicle_func.h	Tue Sep 09 18:47:53 2008 +0000
+++ b/src/vehicle_func.h	Tue Sep 09 19:02:47 2008 +0000
@@ -51,7 +51,7 @@
 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);