Follow a reservation starting from a specific tile to the end. */
| 189 | |
| 190 | /** Follow a reservation starting from a specific tile to the end. */ |
| 191 | static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, bool ignore_oneway = false) |
| 192 | { |
| 193 | TileIndex start_tile = tile; |
| 194 | Trackdir start_trackdir = trackdir; |
| 195 | bool first_loop = true; |
| 196 | |
| 197 | /* Start track not reserved? This can happen if two trains |
| 198 | * are on the same tile. The reservation on the next tile |
| 199 | * is not ours in this case, so exit. */ |
| 200 | if (!HasReservedTracks(tile, TrackToTrackBits(TrackdirToTrack(trackdir)))) return PBSTileInfo(tile, trackdir, false); |
| 201 | |
| 202 | /* Do not disallow 90 deg turns as the setting might have changed between reserving and now. */ |
| 203 | CFollowTrackRail ft(o, rts); |
| 204 | while (ft.Follow(tile, trackdir)) { |
| 205 | TrackdirBits reserved = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.new_tile)); |
| 206 | |
| 207 | /* No reservation --> path end found */ |
| 208 | if (reserved == TRACKDIR_BIT_NONE) { |
| 209 | if (ft.is_station) { |
| 210 | /* Check skipped station tiles as well, maybe our reservation ends inside the station. */ |
| 211 | TileIndexDiff diff = TileOffsByDiagDir(ft.exitdir); |
| 212 | while (ft.tiles_skipped-- > 0) { |
| 213 | ft.new_tile -= diff; |
| 214 | if (HasStationReservation(ft.new_tile)) { |
| 215 | tile = ft.new_tile; |
| 216 | trackdir = DiagDirToDiagTrackdir(ft.exitdir); |
| 217 | break; |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | break; |
| 222 | } |
| 223 | |
| 224 | /* Can't have more than one reserved trackdir */ |
| 225 | Trackdir new_trackdir = FindFirstTrackdir(reserved); |
| 226 | |
| 227 | /* One-way signal against us. The reservation can't be ours as it is not |
| 228 | * a safe position from our direction and we can never pass the signal. */ |
| 229 | if (!ignore_oneway && HasOnewaySignalBlockingTrackdir(ft.new_tile, new_trackdir)) break; |
| 230 | |
| 231 | tile = ft.new_tile; |
| 232 | trackdir = new_trackdir; |
| 233 | |
| 234 | if (first_loop) { |
| 235 | /* Update the start tile after we followed the track the first |
| 236 | * time. This is necessary because the track follower can skip |
| 237 | * tiles (in stations for example) which means that we might |
| 238 | * never visit our original starting tile again. */ |
| 239 | start_tile = tile; |
| 240 | start_trackdir = trackdir; |
| 241 | first_loop = false; |
| 242 | } else { |
| 243 | /* Loop encountered? */ |
| 244 | if (tile == start_tile && trackdir == start_trackdir) break; |
| 245 | } |
| 246 | /* Depot tile? Can't continue. */ |
| 247 | if (IsRailDepotTile(tile)) break; |
| 248 | /* Non-pbs signal? Reservation can't continue. */ |
no test coverage detected