From d0ee8971357e4b71e61e56d79fc55c453a2dbfbf Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 18 Aug 2019 17:05:44 +0100 Subject: [PATCH] Unreserve and re-reserve reservations to bidi bridge/tunnel entrances when reversing train inside --- src/train_cmd.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 0a5b3f8c10..0dbbbc616a 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2176,6 +2176,32 @@ void ReverseTrainDirection(Train *v) /* Clear path reservation in front if train is not stuck. */ if (!HasBit(v->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v); + std::vector re_reserve_trains; + { + /* 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) { + 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); + } + } + }; + 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)); + } + } + 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)); @@ -2236,6 +2262,10 @@ 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 we are inside a depot after reversing, don't bother with path reserving. */ if (v->track == TRACK_BIT_DEPOT) { /* Can't be stuck here as inside a depot is always a safe tile. */