Validate lookahead reservation end OK before calling FollowTrainReservation

This commit is contained in:
Jonathan G Rennison
2021-04-01 00:36:13 +01:00
parent 5b5e068e52
commit 8fd4f65a85
3 changed files with 40 additions and 6 deletions

View File

@@ -657,6 +657,23 @@ static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
return nullptr; return nullptr;
} }
bool ValidateLookAhead(const Train *v)
{
TileIndex tile = v->lookahead->reservation_end_tile;
Trackdir trackdir = v->lookahead->reservation_end_trackdir;
if (HasBit(v->lookahead->flags, TRLF_TB_EXIT_FREE)) {
if (!likely(IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && TrackdirEntersTunnelBridge(tile, trackdir))) {
return false;
}
}
if (HasBit(v->lookahead->flags, TRLF_DEPOT_END) && !IsRailDepotTile(tile)) return false;
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
if (!HasTrackdir(trackdirbits, trackdir)) return false;
return true;
}
/** /**
* Follow a train reservation to the last tile. * Follow a train reservation to the last tile.

View File

@@ -141,6 +141,7 @@ enum FollowTrainReservationFlags {
}; };
DECLARE_ENUM_AS_BIT_SET(FollowTrainReservationFlags) DECLARE_ENUM_AS_BIT_SET(FollowTrainReservationFlags)
bool ValidateLookAhead(const Train *v);
PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = nullptr, FollowTrainReservationFlags flags = FTRF_NONE); PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = nullptr, FollowTrainReservationFlags flags = FTRF_NONE);
void ApplyAvailableFreeTunnelBridgeTiles(TrainReservationLookAhead *lookahead, int free_tiles, TileIndex tile, TileIndex end); void ApplyAvailableFreeTunnelBridgeTiles(TrainReservationLookAhead *lookahead, int free_tiles, TileIndex tile, TileIndex end);
void TryCreateLookAheadForTrainInTunnelBridge(Train *t); void TryCreateLookAheadForTrainInTunnelBridge(Train *t);

View File

@@ -67,10 +67,11 @@ struct ChooseTrainTrackLookAheadState {
/** Flags for ChooseTrainTrack */ /** Flags for ChooseTrainTrack */
enum ChooseTrainTrackFlags { enum ChooseTrainTrackFlags {
CTTF_NONE = 0, ///< No flags CTTF_NONE = 0, ///< No flags
CTTF_FORCE_RES = 0x01, ///< Force a reservation to be made CTTF_FORCE_RES = 0x01, ///< Force a reservation to be made
CTTF_MARK_STUCK = 0x02, ///< The train has to be marked as stuck when needed CTTF_MARK_STUCK = 0x02, ///< The train has to be marked as stuck when needed
CTTF_NON_LOOKAHEAD = 0x04, ///< Any lookahead should not be used, if necessary reset the lookahead state CTTF_NON_LOOKAHEAD = 0x04, ///< Any lookahead should not be used, if necessary reset the lookahead state
CTTF_NO_LOOKAHEAD_VALIDATE = 0x08, ///< Don't validate the lookahead state as it has already been done
}; };
DECLARE_ENUM_AS_BIT_SET(ChooseTrainTrackFlags) DECLARE_ENUM_AS_BIT_SET(ChooseTrainTrackFlags)
@@ -90,6 +91,11 @@ static void TrainEnterStation(Train *v, StationID station);
static void UnreserveBridgeTunnelTile(TileIndex tile); static void UnreserveBridgeTunnelTile(TileIndex tile);
static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile); static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile);
inline void ClearLookAheadIfInvalid(Train *v)
{
if (v->lookahead != nullptr && !ValidateLookAhead(v)) v->lookahead.reset();
}
static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8}; static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8};
static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10}; static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
@@ -2984,6 +2990,8 @@ static FindDepotData FindClosestTrainDepot(Train *v, int max_distance)
if (IsRailDepotTile(v->tile)) return FindDepotData(v->tile, 0); if (IsRailDepotTile(v->tile)) return FindDepotData(v->tile, 0);
if (v->lookahead != nullptr && !ValidateLookAhead(v)) return FindDepotData();
PBSTileInfo origin = FollowTrainReservation(v, nullptr, FTRF_OKAY_UNUSED); PBSTileInfo origin = FollowTrainReservation(v, nullptr, FTRF_OKAY_UNUSED);
if (IsRailDepotTile(origin.tile)) return FindDepotData(origin.tile, 0); if (IsRailDepotTile(origin.tile)) return FindDepotData(origin.tile, 0);
@@ -3900,7 +3908,7 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
} }
SetTunnelBridgeExitSignalState(exit_tile, SIGNAL_STATE_GREEN); SetTunnelBridgeExitSignalState(exit_tile, SIGNAL_STATE_GREEN);
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, TrackdirBitsToTrackBits(ft.m_new_td_bits), force_res ? CTTF_FORCE_RES : CTTF_NONE, nullptr, lookahead_state); ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, TrackdirBitsToTrackBits(ft.m_new_td_bits), CTTF_NO_LOOKAHEAD_VALIDATE | (force_res ? CTTF_FORCE_RES : CTTF_NONE), nullptr, lookahead_state);
if (reserved_bits == GetReservedTrackbits(ft.m_new_tile)) { if (reserved_bits == GetReservedTrackbits(ft.m_new_tile)) {
/* next tile is still not reserved, so unreserve exit and restore signal state */ /* next tile is still not reserved, so unreserve exit and restore signal state */
@@ -3921,12 +3929,14 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
CFollowTrackRail ft(v); CFollowTrackRail ft(v);
if (ft.Follow(tile, td) && HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits), !long_enough)) { if (ft.Follow(tile, td) && HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits), !long_enough)) {
// We reserved up to a LR signal, reserve past it as well. recursion // We reserved up to a LR signal, reserve past it as well. recursion
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, TrackdirBitsToTrackBits(ft.m_new_td_bits), force_res ? CTTF_FORCE_RES : CTTF_NONE, nullptr, lookahead_state); ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, TrackdirBitsToTrackBits(ft.m_new_td_bits), CTTF_NO_LOOKAHEAD_VALIDATE | (force_res ? CTTF_FORCE_RES : CTTF_NONE), nullptr, lookahead_state);
} }
} }
static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile) static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile)
{ {
ClearLookAheadIfInvalid(v);
PBSTileInfo origin = FollowTrainReservation(v, nullptr, FTRF_OKAY_UNUSED); PBSTileInfo origin = FollowTrainReservation(v, nullptr, FTRF_OKAY_UNUSED);
if (IsRailDepotTile(origin.tile)) return; if (IsRailDepotTile(origin.tile)) return;
@@ -4012,6 +4022,10 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
v->lookahead.reset(); v->lookahead.reset();
} }
if (!(flags & CTTF_NO_LOOKAHEAD_VALIDATE)) {
ClearLookAheadIfInvalid(v);
}
PBSTileInfo origin = FollowTrainReservation(v, nullptr, FTRF_OKAY_UNUSED); PBSTileInfo origin = FollowTrainReservation(v, nullptr, FTRF_OKAY_UNUSED);
PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false); PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false);
DiagDirection dest_enterdir = enterdir; DiagDirection dest_enterdir = enterdir;
@@ -4186,6 +4200,8 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
{ {
assert(v->IsFrontEngine()); assert(v->IsFrontEngine());
ClearLookAheadIfInvalid(v);
if (v->lookahead != nullptr && HasBit(v->lookahead->flags, TRLF_DEPOT_END)) return true; if (v->lookahead != nullptr && HasBit(v->lookahead->flags, TRLF_DEPOT_END)) return true;
/* We have to handle depots specially as the track follower won't look /* We have to handle depots specially as the track follower won't look