Allow placing routing restrictions on tunnel/bridge entrance/exit signals
No reserve through support
This commit is contained in:
@@ -4001,11 +4001,12 @@ static bool HasLongReservePbsSignalOnTrackdir(Train* v, TileIndex tile, Trackdir
|
||||
return false;
|
||||
}
|
||||
|
||||
static TileIndex CheckLongReservePbsTunnelBridgeOnTrackdir(Train* v, TileIndex tile, Trackdir trackdir)
|
||||
static TileIndex CheckLongReservePbsTunnelBridgeOnTrackdir(Train* v, TileIndex tile, Trackdir trackdir, bool restricted_only = false)
|
||||
{
|
||||
if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC && IsTunnelBridgeSignalSimulationEntranceTile(tile) && TrackdirEntersTunnelBridge(tile, trackdir)) {
|
||||
|
||||
TileIndex end = GetOtherTunnelBridgeEnd(tile);
|
||||
if (restricted_only && !IsTunnelBridgeRestrictedSignal(end)) return INVALID_TILE;
|
||||
int raw_free_tiles;
|
||||
if (v->lookahead != nullptr && v->lookahead->reservation_end_tile == tile && v->lookahead->reservation_end_trackdir == trackdir) { // TODO fix loop case
|
||||
if (HasBit(v->lookahead->flags, TRLF_TB_EXIT_FREE)) {
|
||||
@@ -4033,7 +4034,7 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
|
||||
const bool long_enough = IsReservationLookAheadLongEnough(v, lookahead_state);
|
||||
|
||||
// We reserved up to a unoccupied signalled tunnel/bridge, reserve past it as well. recursion
|
||||
TileIndex exit_tile = long_enough ? INVALID_TILE : CheckLongReservePbsTunnelBridgeOnTrackdir(v, tile, td);
|
||||
TileIndex exit_tile = CheckLongReservePbsTunnelBridgeOnTrackdir(v, tile, td, long_enough);
|
||||
if (exit_tile != INVALID_TILE) {
|
||||
CFollowTrackRail ft(v);
|
||||
Trackdir exit_td = GetTunnelBridgeExitTrackdir(exit_tile);
|
||||
@@ -4042,6 +4043,23 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
|
||||
if ((ft.m_new_td_bits & TrackBitsToTrackdirBits(reserved_bits)) == TRACKDIR_BIT_NONE) {
|
||||
/* next tile is not reserved */
|
||||
|
||||
bool long_reserve = !long_enough;
|
||||
if (IsTunnelBridgeRestrictedSignal(exit_tile)) {
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(exit_tile, TrackdirToTrack(exit_td));
|
||||
if (prog && prog->actions_used_flags & (TRPAUF_WAIT_AT_PBS | TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_ACQUIRE_ON_RES | TRPAUF_LONG_RESERVE)) {
|
||||
TraceRestrictProgramResult out;
|
||||
if (long_reserve) out.flags |= TRPRF_LONG_RESERVE;
|
||||
TraceRestrictProgramInput input(exit_tile, exit_td, nullptr, nullptr);
|
||||
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_ACQUIRE_ON_RES;
|
||||
prog->Execute(v, input, out);
|
||||
if (out.flags & TRPRF_WAIT_AT_PBS) {
|
||||
return;
|
||||
}
|
||||
long_reserve = (out.flags & TRPRF_LONG_RESERVE);
|
||||
}
|
||||
}
|
||||
if (!long_reserve) return;
|
||||
|
||||
SignalState exit_state = GetTunnelBridgeExitSignalState(exit_tile);
|
||||
|
||||
/* reserve exit to make contiguous reservation */
|
||||
@@ -4051,10 +4069,6 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
|
||||
SetTunnelReservation(exit_tile, true);
|
||||
}
|
||||
SetTunnelBridgeExitSignalState(exit_tile, SIGNAL_STATE_GREEN);
|
||||
if (_extra_aspects > 0) {
|
||||
SetTunnelBridgeExitSignalAspect(exit_tile, 0);
|
||||
UpdateAspectDeferred(exit_tile, GetTunnelBridgeExitTrackdir(exit_tile));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -4067,6 +4081,10 @@ static void TryLongReserveChooseTrainTrack(Train *v, TileIndex tile, Trackdir td
|
||||
}
|
||||
SetTunnelBridgeExitSignalState(exit_tile, exit_state);
|
||||
} else {
|
||||
if (_extra_aspects > 0) {
|
||||
SetTunnelBridgeExitSignalAspect(exit_tile, 0);
|
||||
UpdateAspectDeferred(exit_tile, GetTunnelBridgeExitTrackdir(exit_tile));
|
||||
}
|
||||
MarkTileDirtyByTile(exit_tile, VMDF_NOT_MAP_MODE);
|
||||
}
|
||||
}
|
||||
@@ -4995,6 +5013,23 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
|
||||
}
|
||||
}
|
||||
|
||||
auto try_exit_reservation = [&]() -> bool {
|
||||
if (IsTunnelBridgeRestrictedSignal(tile)) {
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(td));
|
||||
if (prog && prog->actions_used_flags & (TRPAUF_WAIT_AT_PBS | TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_ACQUIRE_ON_RES)) {
|
||||
TraceRestrictProgramResult out;
|
||||
TraceRestrictProgramInput input(tile, td, nullptr, nullptr);
|
||||
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_ACQUIRE_ON_RES;
|
||||
prog->Execute(t, input, out);
|
||||
if (out.flags & TRPRF_WAIT_AT_PBS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TryPathReserve(t);
|
||||
};
|
||||
|
||||
if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
|
||||
if (unlikely(t->lookahead == nullptr)) {
|
||||
FillTrainReservationLookAhead(t);
|
||||
@@ -5004,10 +5039,6 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
|
||||
if (t->lookahead->reservation_end_tile == t->tile && t->lookahead->reservation_end_position - t->lookahead->current_position <= (int)TILE_SIZE && !HasBit(t->lookahead->flags, TRLF_TB_EXIT_FREE)) return false;
|
||||
SignalState exit_state = GetTunnelBridgeExitSignalState(tile);
|
||||
SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_GREEN);
|
||||
if (_extra_aspects > 0) {
|
||||
SetTunnelBridgeExitSignalAspect(tile, 0);
|
||||
UpdateAspectDeferred(tile, GetTunnelBridgeExitTrackdir(tile));
|
||||
}
|
||||
|
||||
/* Get tile margin before changing vehicle direction */
|
||||
const int tile_margin = GetTileMarginInFrontOfTrain(t);
|
||||
@@ -5018,7 +5049,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
|
||||
t->tile = tile;
|
||||
t->track = TRACK_BIT_WORMHOLE;
|
||||
t->direction = TrackdirToDirection(td);
|
||||
bool ok = TryPathReserve(t);
|
||||
bool ok = try_exit_reservation();
|
||||
if (!ok && (t->lookahead->reservation_end_position >= t->lookahead->current_position && t->lookahead->reservation_end_position > t->lookahead->current_position + tile_margin)) {
|
||||
/* Reservation was made previously and was valid then.
|
||||
* To avoid unexpected braking due to stopping short of the lookahead end,
|
||||
@@ -5026,6 +5057,10 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
|
||||
ok = true;
|
||||
}
|
||||
if (ok) {
|
||||
if (_extra_aspects > 0) {
|
||||
SetTunnelBridgeExitSignalAspect(tile, 0);
|
||||
UpdateAspectDeferred(tile, GetTunnelBridgeExitTrackdir(tile));
|
||||
}
|
||||
mark_dirty = true;
|
||||
if (t->lookahead->reservation_end_tile == veh_orig_tile && t->lookahead->reservation_end_position - t->lookahead->current_position <= (int)TILE_SIZE) {
|
||||
/* Less than a tile of lookahead, advance tile */
|
||||
@@ -5057,7 +5092,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile)
|
||||
t->tile = tile;
|
||||
t->track = TRACK_BIT_WORMHOLE;
|
||||
t->direction = TrackdirToDirection(td);
|
||||
bool ok = TryPathReserve(t);
|
||||
bool ok = try_exit_reservation();
|
||||
t->tile = veh_orig_tile;
|
||||
t->track = veh_orig_track;
|
||||
t->direction = veh_orig_direction;
|
||||
@@ -5170,6 +5205,21 @@ void DecrementPendingSpeedRestrictions(Train *v)
|
||||
}
|
||||
}
|
||||
|
||||
void HandleTraceRestrictSpeedRestrictionAction(const TraceRestrictProgramResult &out, Train *v, Trackdir signal_td)
|
||||
{
|
||||
if (out.flags & TRPRF_SPEED_RESTRICTION_SET) {
|
||||
SetBit(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; ++it) {
|
||||
if ((uint16) (out.speed_restriction + 0xFFFF) < (uint16) (it->second.new_speed + 0xFFFF)) it->second.new_speed = out.speed_restriction;
|
||||
}
|
||||
uint16 flags = 0;
|
||||
if (IsDiagonalTrack(TrackdirToTrack(signal_td))) SetBit(flags, PSRCF_DIAGONAL);
|
||||
pending_speed_restriction_change_map.insert({ v->index, { (uint16) (v->gcache.cached_total_length + (HasBit(flags, PSRCF_DIAGONAL) ? 8 : 4)), out.speed_restriction, v->speed_restriction, flags } });
|
||||
if ((uint16) (out.speed_restriction + 0xFFFF) < (uint16) (v->speed_restriction + 0xFFFF)) v->speed_restriction = out.speed_restriction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a vehicle chain one movement stop forwards.
|
||||
* @param v First vehicle to move.
|
||||
@@ -5366,17 +5416,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
v->reverse_distance = v->gcache.cached_total_length + (IsDiagonalTrack(TrackdirToTrack(dir)) ? 16 : 8);
|
||||
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
||||
}
|
||||
if (out.flags & TRPRF_SPEED_RESTRICTION_SET) {
|
||||
SetBit(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; ++it) {
|
||||
if ((uint16) (out.speed_restriction + 0xFFFF) < (uint16) (it->second.new_speed + 0xFFFF)) it->second.new_speed = out.speed_restriction;
|
||||
}
|
||||
uint16 flags = 0;
|
||||
if (IsDiagonalTrack(TrackdirToTrack(dir))) SetBit(flags, PSRCF_DIAGONAL);
|
||||
pending_speed_restriction_change_map.insert({ v->index, { (uint16) (v->gcache.cached_total_length + (HasBit(flags, PSRCF_DIAGONAL) ? 8 : 4)), out.speed_restriction, v->speed_restriction, flags } });
|
||||
if ((uint16) (out.speed_restriction + 0xFFFF) < (uint16) (v->speed_restriction + 0xFFFF)) v->speed_restriction = out.speed_restriction;
|
||||
}
|
||||
HandleTraceRestrictSpeedRestrictionAction(out, v, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5519,6 +5559,31 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
/* Entered wormhole set counters. */
|
||||
v->wait_counter = (TILE_SIZE * simulated_wormhole_signals) - TILE_SIZE;
|
||||
v->tunnel_bridge_signal_num = 0;
|
||||
|
||||
if (v->IsFrontEngine() && IsTunnelBridgeSignalSimulationEntrance(old_tile) && IsTunnelBridgeRestrictedSignal(old_tile)) {
|
||||
const Trackdir trackdir = GetTunnelBridgeEntranceTrackdir(old_tile);
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(old_tile, TrackdirToTrack(trackdir));
|
||||
if (prog && prog->actions_used_flags & (TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_SPEED_RESTRICTION | TRPAUF_CHANGE_COUNTER)) {
|
||||
TraceRestrictProgramResult out;
|
||||
TraceRestrictProgramInput input(old_tile, trackdir, nullptr, nullptr);
|
||||
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_RELEASE_FRONT | TRPISP_CHANGE_COUNTER;
|
||||
prog->Execute(v, input, out);
|
||||
HandleTraceRestrictSpeedRestrictionAction(out, v, trackdir);
|
||||
}
|
||||
}
|
||||
|
||||
if (v->Next() == nullptr && IsTunnelBridgeSignalSimulationEntrance(old_tile) && IsTunnelBridgeRestrictedSignal(old_tile)) {
|
||||
const Trackdir trackdir = GetTunnelBridgeEntranceTrackdir(old_tile);
|
||||
const Track track = TrackdirToTrack(trackdir);
|
||||
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(old_tile, track);
|
||||
if (prog && prog->actions_used_flags & TRPAUF_SLOT_RELEASE_BACK) {
|
||||
TraceRestrictProgramResult out;
|
||||
TraceRestrictProgramInput input(old_tile, trackdir, nullptr, nullptr);
|
||||
input.permitted_slot_operations = TRPISP_RELEASE_BACK;
|
||||
prog->Execute(first, input, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint distance = v->wait_counter;
|
||||
@@ -5534,6 +5599,17 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
return false;
|
||||
}
|
||||
leaving = true;
|
||||
if (IsTunnelBridgeRestrictedSignal(gp.new_tile) && IsTunnelBridgeSignalSimulationExit(gp.new_tile)) {
|
||||
const Trackdir trackdir = GetTunnelBridgeExitTrackdir(gp.new_tile);
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(gp.new_tile, TrackdirToTrack(trackdir));
|
||||
if (prog && prog->actions_used_flags & (TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_SPEED_RESTRICTION | TRPAUF_CHANGE_COUNTER)) {
|
||||
TraceRestrictProgramResult out;
|
||||
TraceRestrictProgramInput input(gp.new_tile, trackdir, nullptr, nullptr);
|
||||
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_RELEASE_FRONT | TRPISP_CHANGE_COUNTER;
|
||||
prog->Execute(v, input, out);
|
||||
HandleTraceRestrictSpeedRestrictionAction(out, v, trackdir);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (IsTooCloseBehindTrain(v, gp.new_tile, v->wait_counter, distance == 0)) {
|
||||
if (distance == 0) v->wait_counter = 0;
|
||||
@@ -5765,6 +5841,22 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsTileType(gp.old_tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(gp.old_tile) && IsTunnelBridgeRestrictedSignal(gp.old_tile)) {
|
||||
const TrackdirBits rev_tracks = TrackBitsToTrackdirBits(GetTunnelBridgeTrackBits(gp.old_tile)) & DiagdirReachesTrackdirs(ReverseDiagDir(enterdir));
|
||||
const Trackdir rev_trackdir = FindFirstTrackdir(rev_tracks);
|
||||
const Track track = TrackdirToTrack(rev_trackdir);
|
||||
|
||||
if (TrackdirEntersTunnelBridge(gp.old_tile, rev_trackdir)) {
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(gp.old_tile, track);
|
||||
if (prog && prog->actions_used_flags & TRPAUF_SLOT_RELEASE_BACK) {
|
||||
TraceRestrictProgramResult out;
|
||||
TraceRestrictProgramInput input(gp.old_tile, ReverseTrackdir(rev_trackdir), nullptr, nullptr);
|
||||
input.permitted_slot_operations = TRPISP_RELEASE_BACK;
|
||||
prog->Execute(first, input, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user