Fix clearing of train reservations in tunnels and on bridges.

(cherry picked from commit e2c4fb517d1064b163d8f2b0627506d785ffb3ed)

See: #46
This commit is contained in:
keldorkatarn
2018-04-20 23:02:51 +02:00
committed by Jonathan G Rennison
parent c92a28a072
commit c2678b896e

View File

@@ -2287,44 +2287,30 @@ static void UnreserveBridgeTunnelTile(TileIndex tile)
* @param v %Train owning the reservation. * @param v %Train owning the reservation.
* @param tile Tile with reservation to clear. * @param tile Tile with reservation to clear.
* @param track_dir Track direction to clear. * @param track_dir Track direction to clear.
* @param tunbridge_clear_unsignaled_other_end Whether to clear the far end of unsignalled tunnels/bridges.
*/ */
static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir) static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir, bool tunbridge_clear_unsignaled_other_end = false)
{ {
DiagDirection dir = TrackdirToExitdir(track_dir); DiagDirection dir = TrackdirToExitdir(track_dir);
if (IsTileType(tile, MP_TUNNELBRIDGE)) { if (IsTileType(tile, MP_TUNNELBRIDGE)) {
TileIndex end = GetOtherTunnelBridgeEnd(tile);
UnreserveBridgeTunnelTile(tile);
if (IsTunnelBridgeWithSignalSimulation(tile)) {
/* Are we just leaving a tunnel/bridge? */ /* Are we just leaving a tunnel/bridge? */
if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
TileIndex end = GetOtherTunnelBridgeEnd(tile);
bool free = TunnelBridgeIsFree(tile, end, v).Succeeded(); bool free = TunnelBridgeIsFree(tile, end, v).Succeeded();
if (IsTunnelBridgeWithSignalSimulation(tile)) {
UnreserveBridgeTunnelTile(tile);
HandleLastTunnelBridgeSignals(tile, end, dir, free); HandleLastTunnelBridgeSignals(tile, end, dir, free);
if (_settings_client.gui.show_track_reservation) {
MarkTileDirtyByTile(tile);
} }
} else if (free) { } else if (tunbridge_clear_unsignaled_other_end) {
/* Free the reservation only if no other train is on the tiles. */
UnreserveBridgeTunnelTile(tile);
UnreserveBridgeTunnelTile(end); UnreserveBridgeTunnelTile(end);
}
if (_settings_client.gui.show_track_reservation) { if (_settings_client.gui.show_track_reservation) {
if (IsBridge(tile)) {
MarkBridgeDirty(tile);
} else {
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);
MarkTileDirtyByTile(end); MarkTileDirtyByTile(end);
} }
}
}
} else if (GetTunnelBridgeDirection(tile) == dir && IsTunnelBridgeWithSignalSimulation(tile)) {
/* cancelling reservation of entry ramp, due to reverse */
UnreserveBridgeTunnelTile(tile);
if (_settings_client.gui.show_track_reservation) {
MarkTileDirtyByTile(tile);
}
}
} else if (IsRailStationTile(tile)) { } else if (IsRailStationTile(tile)) {
TileIndex new_tile = TileAddByDiagDir(tile, dir); TileIndex new_tile = TileAddByDiagDir(tile, dir);
/* If the new tile is not a further tile of the same station, we /* If the new tile is not a further tile of the same station, we
@@ -2391,6 +2377,11 @@ void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_t
} else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) { } else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
break; break;
} }
} else if (IsTunnelBridgeWithSignalSimulation(tile)) {
TileIndex end = GetOtherTunnelBridgeEnd(tile);
bool free = TunnelBridgeIsFree(tile, end, v).Succeeded();
if (!free && GetTunnelBridgeDirection(tile) == ReverseDiagDir(TrackdirToExitdir(td))) break;
} }
/* Don't free first station/bridge/tunnel if we are on it. */ /* Don't free first station/bridge/tunnel if we are on it. */
@@ -3052,12 +3043,7 @@ uint Train::Crash(bool flooded)
* Also clear all reserved tracks the train is currently on. */ * Also clear all reserved tracks the train is currently on. */
if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this); if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this);
for (const Train *v = this; v != NULL; v = v->Next()) { for (const Train *v = this; v != NULL; v = v->Next()) {
ClearPathReservation(v, v->tile, v->GetVehicleTrackdir()); ClearPathReservation(v, v->tile, v->GetVehicleTrackdir(), true);
if (IsTileType(v->tile, MP_TUNNELBRIDGE)) {
/* ClearPathReservation will not free the wormhole exit
* if the train has just entered the wormhole. */
UnreserveBridgeTunnelTile(GetOtherTunnelBridgeEnd(v->tile));
}
} }
/* we may need to update crossing we were approaching, /* we may need to update crossing we were approaching,
@@ -3553,7 +3539,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
} }
/* 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, v->tile, v->GetVehicleTrackdir()); if (v->Next() == NULL) ClearPathReservation(v, v->tile, v->GetVehicleTrackdir(), true);
v->tile = gp.new_tile; v->tile = gp.new_tile;