diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index f47ad4a005..50694280d7 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2200,41 +2200,38 @@ void ReverseTrainDirection(Train *v) v->reverse_distance = 0; - /* Clear path reservation in front if train is not stuck. */ - if (!HasBit(v->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v); - - std::vector re_reserve_trains; + bool no_near_end_unreserve = false; + bool no_far_end_unreserve = false; { /* Temporarily clear and restore reservations to bidi tunnel/bridge entrances when reversing train inside, * to avoid outgoing and incoming reservations becoming merged */ - auto find_train_reservations = [&re_reserve_trains, &v](TileIndex tile) { + auto find_train_reservations = [&v](TileIndex tile, bool &found_reservation) { TrackBits reserved = GetAcrossTunnelBridgeReservationTrackBits(tile); Track track; while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) { Train *res_train = GetTrainForReservation(tile, track); if (res_train != nullptr && res_train != v) { - FreeTrainTrackReservation(res_train); - re_reserve_trains.push_back(res_train); + found_reservation = true; } } }; if (IsTunnelBridgeWithSignalSimulation(v->tile) && IsTunnelBridgeSignalSimulationBidirectional(v->tile)) { - find_train_reservations(v->tile); - find_train_reservations(GetOtherTunnelBridgeEnd(v->tile)); - } - Train *last = v->Last(); - if (IsTunnelBridgeWithSignalSimulation(last->tile) && IsTunnelBridgeSignalSimulationBidirectional(last->tile)) { - find_train_reservations(last->tile); - find_train_reservations(GetOtherTunnelBridgeEnd(last->tile)); + find_train_reservations(v->tile, no_near_end_unreserve); + find_train_reservations(GetOtherTunnelBridgeEnd(v->tile), no_far_end_unreserve); } } + /* Clear path reservation in front if train is not stuck. */ + if (!HasBit(v->flags, VRF_TRAIN_STUCK) && !no_near_end_unreserve && !no_far_end_unreserve) { + FreeTrainTrackReservation(v); + } + if ((v->track & TRACK_BIT_WORMHOLE) && IsTunnelBridgeWithSignalSimulation(v->tile)) { /* Clear exit tile reservation if train was on approach to exit and had reserved it */ Axis axis = DiagDirToAxis(GetTunnelBridgeDirection(v->tile)); DiagDirection axial_dir = DirToDiagDirAlongAxis(v->direction, axis); TileIndex next_tile = TileVirtXY(v->x_pos, v->y_pos) + TileOffsByDiagDir(axial_dir); - if (next_tile == v->tile || next_tile == GetOtherTunnelBridgeEnd(v->tile)) { + if ((!no_near_end_unreserve && next_tile == v->tile) || (!no_far_end_unreserve && next_tile == GetOtherTunnelBridgeEnd(v->tile))) { Trackdir exit_td = TrackEnterdirToTrackdir(FindFirstTrack(GetAcrossTunnelBridgeTrackBits(next_tile)), ReverseDiagDir(GetTunnelBridgeDirection(next_tile))); CFollowTrackRail ft(GetTileOwner(next_tile), GetRailTypeInfo(v->railtype)->all_compatible_railtypes); if (ft.Follow(next_tile, exit_td)) { @@ -2289,10 +2286,6 @@ void ReverseTrainDirection(Train *v) crossing = TrainApproachingCrossingTile(v); if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing); - for (uint i = 0; i < re_reserve_trains.size(); ++i) { - TryPathReserve(re_reserve_trains[i], true); - } - if (HasBit(v->flags, VRF_PENDING_SPEED_RESTRICTION)) { auto range = pending_speed_restriction_change_map.equal_range(v->index); for (auto it = range.first; it != range.second;) {