mirror of https://github.com/OpenTTD/OpenTTD
(svn r13974) -Fix [YAPP]: A train crash could lead to stale reservations. (michi_cc)
parent
9a1958be91
commit
983e297ff0
24
src/pbs.cpp
24
src/pbs.cpp
|
@ -204,13 +204,24 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
||||||
return PBSTileInfo(tile, trackdir, false);
|
return PBSTileInfo(tile, trackdir, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Callback for VehicleFromPos to find a train on a specific track. */
|
||||||
|
static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
|
||||||
|
{
|
||||||
|
PBSTileInfo info = *(PBSTileInfo *)data;
|
||||||
|
|
||||||
|
if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info.trackdir))) return v;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Follow a train reservation to the last tile.
|
* Follow a train reservation to the last tile.
|
||||||
*
|
*
|
||||||
* @param v the vehicle
|
* @param v the vehicle
|
||||||
|
* @param train_on_res Is set to a train we might encounter
|
||||||
* @returns The last tile of the reservation or the current train tile if no reservation present.
|
* @returns The last tile of the reservation or the current train tile if no reservation present.
|
||||||
*/
|
*/
|
||||||
PBSTileInfo FollowTrainReservation(const Vehicle *v)
|
PBSTileInfo FollowTrainReservation(const Vehicle *v, Vehicle **train_on_res)
|
||||||
{
|
{
|
||||||
assert(v->type == VEH_TRAIN);
|
assert(v->type == VEH_TRAIN);
|
||||||
|
|
||||||
|
@ -221,19 +232,10 @@ PBSTileInfo FollowTrainReservation(const Vehicle *v)
|
||||||
|
|
||||||
PBSTileInfo res = FollowReservation(v->owner, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes, tile, trackdir);
|
PBSTileInfo res = FollowReservation(v->owner, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes, tile, trackdir);
|
||||||
res.okay = IsSafeWaitingPosition(v, res.tile, res.trackdir, true, _settings_game.pf.forbid_90_deg);
|
res.okay = IsSafeWaitingPosition(v, res.tile, res.trackdir, true, _settings_game.pf.forbid_90_deg);
|
||||||
|
if (train_on_res != NULL) *train_on_res = VehicleFromPos(res.tile, &res, FindTrainOnTrackEnum);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Callback for VehicleFromPos to find a train on a specific track. */
|
|
||||||
static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
|
|
||||||
{
|
|
||||||
PBSTileInfo info = *(PBSTileInfo *)data;
|
|
||||||
|
|
||||||
if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info.trackdir))) return v;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the train which has reserved a specific path.
|
* Find the train which has reserved a specific path.
|
||||||
*
|
*
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct PBSTileInfo {
|
||||||
PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {}
|
PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
PBSTileInfo FollowTrainReservation(const Vehicle *v);
|
PBSTileInfo FollowTrainReservation(const Vehicle *v, Vehicle **train_on_res = NULL);
|
||||||
bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false);
|
bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false);
|
||||||
bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false);
|
bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false);
|
||||||
|
|
||||||
|
|
|
@ -3059,7 +3059,8 @@ bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PBSTileInfo origin = FollowTrainReservation(v);
|
Vehicle *other_train = NULL;
|
||||||
|
PBSTileInfo origin = FollowTrainReservation(v, &other_train);
|
||||||
/* If we have a reserved path and the path ends at a safe tile, we are finished already. */
|
/* If we have a reserved path and the path ends at a safe tile, we are finished already. */
|
||||||
if (origin.okay && (v->tile != origin.tile || first_tile_okay)) {
|
if (origin.okay && (v->tile != origin.tile || first_tile_okay)) {
|
||||||
/* Can't be stuck then. */
|
/* Can't be stuck then. */
|
||||||
|
@ -3067,6 +3068,14 @@ bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay)
|
||||||
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
|
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/* The path we are driving on is alread blocked by some other train.
|
||||||
|
* This can only happen when tracks and signals are changed. A crash
|
||||||
|
* is probably imminent, don't do any further reservation because
|
||||||
|
* it might cause stale reservations. */
|
||||||
|
if (other_train != NULL && v->tile != origin.tile) {
|
||||||
|
if (mark_as_stuck) MarkTrainAsStuck(v);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we are in a depot, tentativly reserve the depot. */
|
/* If we are in a depot, tentativly reserve the depot. */
|
||||||
if (v->u.rail.track & TRACK_BIT_DEPOT) {
|
if (v->u.rail.track & TRACK_BIT_DEPOT) {
|
||||||
|
|
Loading…
Reference in New Issue