diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 99184df9b3..6198b575d4 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2287,43 +2287,29 @@ static void UnreserveBridgeTunnelTile(TileIndex tile) * @param v %Train owning the reservation. * @param tile Tile with reservation 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); if (IsTileType(tile, MP_TUNNELBRIDGE)) { - /* Are we just leaving a tunnel/bridge? */ - if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { - TileIndex end = GetOtherTunnelBridgeEnd(tile); + TileIndex end = GetOtherTunnelBridgeEnd(tile); + UnreserveBridgeTunnelTile(tile); - bool free = TunnelBridgeIsFree(tile, end, v).Succeeded(); - if (IsTunnelBridgeWithSignalSimulation(tile)) { - UnreserveBridgeTunnelTile(tile); + if (IsTunnelBridgeWithSignalSimulation(tile)) { + /* Are we just leaving a tunnel/bridge? */ + if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) { + bool free = TunnelBridgeIsFree(tile, end, v).Succeeded(); HandleLastTunnelBridgeSignals(tile, end, dir, free); - if (_settings_client.gui.show_track_reservation) { - MarkTileDirtyByTile(tile); - } - } else if (free) { - /* Free the reservation only if no other train is on the tiles. */ - UnreserveBridgeTunnelTile(tile); - UnreserveBridgeTunnelTile(end); - - if (_settings_client.gui.show_track_reservation) { - if (IsBridge(tile)) { - MarkBridgeDirty(tile); - } else { - MarkTileDirtyByTile(tile); - 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 (tunbridge_clear_unsignaled_other_end) { + UnreserveBridgeTunnelTile(end); + } + + if (_settings_client.gui.show_track_reservation) { + MarkTileDirtyByTile(tile); + MarkTileDirtyByTile(end); } } else if (IsRailStationTile(tile)) { TileIndex new_tile = TileAddByDiagDir(tile, dir); @@ -2391,6 +2377,11 @@ void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_t } else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) { 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. */ @@ -3052,12 +3043,7 @@ uint Train::Crash(bool flooded) * Also clear all reserved tracks the train is currently on. */ if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this); for (const Train *v = this; v != NULL; v = v->Next()) { - ClearPathReservation(v, v->tile, v->GetVehicleTrackdir()); - 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)); - } + ClearPathReservation(v, v->tile, v->GetVehicleTrackdir(), true); } /* 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 */ - 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;