diff --git a/src/lang/english.txt b/src/lang/english.txt index 7a65d73fa6..e450f7d1d2 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2641,6 +2641,10 @@ STR_TRACE_RESTRICT_LONG_RESERVE :Long reserve STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL :Cancel long reserve STR_TRACE_RESTRICT_WAIT_AT_PBS :Wait at PBS signal STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL :Cancel wait at PBS signal +STR_TRACE_RESTRICT_PBS_RES_END_WAIT :Wait at start PBS signal for reservation ending here +STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL :Cancel wait at start PBS signal for reservation ending here +STR_TRACE_RESTRICT_PBS_RES_END_WAIT_SHORT :Wait at start PBS... +STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL_SHORT :Cancel wait at start PBS... STR_TRACE_RESTRICT_PF_PENALTY :Penalty STR_TRACE_RESTRICT_PF_VALUE_SMALL :small STR_TRACE_RESTRICT_PF_VALUE_MEDIUM :medium @@ -2659,10 +2663,16 @@ STR_TRACE_RESTRICT_SLOT_ACQUIRE_WAIT :Acquire or wait STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE :Try to acquire STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT :Release (front) STR_TRACE_RESTRICT_SLOT_RELEASE_BACK :Release (back) +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT :PBS end: Acquire or wait +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE :PBS end: Try to acquire +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE :PBS end: Release STR_TRACE_RESTRICT_SLOT_ACQUIRE_WAIT_ITEM :Acquire slot: {STRING1}{BLACK}{STRING}, or wait at PBS signal STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE_ITEM :Try to acquire slot: {STRING1}{BLACK}{STRING}, or continue anyway STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT_ITEM :Release slot: {STRING1}{BLACK}{STRING} (front of train) STR_TRACE_RESTRICT_SLOT_RELEASE_BACK_ITEM :Release slot: {STRING1}{BLACK}{STRING} (back of train) +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT_ITEM :PBS reservation ending here: Acquire slot: {STRING1}{BLACK}{STRING}, or wait at start +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE_ITEM :PBS reservation ending here: Acquire slot: {STRING1}{BLACK}{STRING}, or continue anyway +STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE_ITEM :PBS reservation ending here: Release slot: {STRING1}{BLACK}{STRING} STR_TRACE_RESTRICT_SLOT_NAME :{TRSLOT} STR_TRACE_RESTRICT_SLOT_LIST_HEADER :{BLACK}Slot{CONSUME_ARG}{P "" s}: {LTBLUE} STR_TRACE_RESTRICT_SLOT_LIST_SEPARATOR :{BLACK}, {LTBLUE} diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index b6c11cb414..caa6cb032d 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -18,6 +18,7 @@ #include "yapf_destrail.hpp" #include "../../viewport_func.h" #include "../../newgrf_station.h" +#include "../../tracerestrict.h" #include "../../safeguards.h" @@ -189,7 +190,8 @@ public: } /* Don't bother if the target is reserved. */ - if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false; + PBSWaitingPositionRestrictedSignalInfo restricted_signal_info; + if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td, false, &restricted_signal_info)) return false; for (Node *node = m_res_node; node->m_parent != NULL; node = node->m_parent) { node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack::ReserveSingleTrack); @@ -207,6 +209,18 @@ public: } } + if (restricted_signal_info.tile != INVALID_TILE) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir)); + if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_SLOT) { + extern TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *); + + TraceRestrictProgramResult out; + TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, NULL); + input.permitted_slot_operations = TRPISP_PBS_RES_END_ACQUIRE | TRPISP_PBS_RES_END_RELEASE; + prog->Execute(Yapf().GetVehicle(), input, out); + } + } + if (target != NULL) target->okay = true; if (Yapf().CanUseGlobalCache(*m_res_node)) { diff --git a/src/pbs.cpp b/src/pbs.cpp index fcbb24c04f..f83cd78b7b 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -550,7 +550,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo * @param forbid_90deg Don't allow trains to make 90 degree turns * @return True if the position is free */ -bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg) +bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg, PBSWaitingPositionRestrictedSignalInfo *restricted_signal_info) { Track track = TrackdirToTrack(trackdir); TrackBits reserved = GetReservedTrackbits(tile); @@ -560,7 +560,31 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo /* Not reserved and depot or not a pbs signal -> free. */ if (IsRailDepotTile(tile)) return true; - if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) return true; + + auto pbs_res_end_wait_test = [v, restricted_signal_info](TileIndex t, Trackdir td) -> bool { + if (IsRestrictedSignal(t)) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(t, TrackdirToTrack(td)); + if (restricted_signal_info && prog) { + restricted_signal_info->tile = t; + restricted_signal_info->trackdir = td; + } + if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_WAIT) { + TraceRestrictProgramInput input(t, td, &VehiclePosTraceRestrictPreviousSignalCallback, NULL); + input.permitted_slot_operations = TRPISP_PBS_RES_END_ACQ_DRY; + TraceRestrictProgramResult out; + prog->Execute(v, input, out); + if (out.flags & TRPRF_PBS_RES_END_WAIT) { + return false; + } + } + } + return true; + }; + + if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) { + return pbs_res_end_wait_test(tile, trackdir); + } + if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && IsTunnelBridgeSignalSimulationEntrance(tile)) { if (IsTunnelBridgeSignalSimulationBidirectional(tile)) { TileIndex other_end = GetOtherTunnelBridgeEnd(tile); @@ -584,5 +608,15 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir); if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir); - return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits)); + if (HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits))) return false; + + if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) { + Trackdir td = FindFirstTrackdir(ft.m_new_td_bits); + /* PBS signal on next trackdir? */ + if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) { + return pbs_res_end_wait_test(ft.m_new_tile, td); + } + } + + return true; } diff --git a/src/pbs.h b/src/pbs.h index 223aeccacf..38f386e7bb 100644 --- a/src/pbs.h +++ b/src/pbs.h @@ -46,9 +46,14 @@ struct PBSTileInfo { PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {} }; +struct PBSWaitingPositionRestrictedSignalInfo { + TileIndex tile = INVALID_TILE; + Trackdir trackdir = INVALID_TRACKDIR; +}; + PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res = NULL); bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false); -bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false); +bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false, PBSWaitingPositionRestrictedSignalInfo *restricted_signal_info = nullptr); Train *GetTrainForReservation(TileIndex tile, Track track); diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index b0eb8692ae..50fe4fae63 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -47,7 +47,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_TRACE_RESTRICT, XSCF_NULL, 8, 8, "tracerestrict", NULL, NULL, "TRRM,TRRP,TRRS" }, + { XSLFI_TRACE_RESTRICT, XSCF_NULL, 9, 9, "tracerestrict", NULL, NULL, "TRRM,TRRP,TRRS" }, { XSLFI_TRACE_RESTRICT_OWNER, XSCF_NULL, 1, 1, "tracerestrict_owner", NULL, NULL, NULL }, { XSLFI_TRACE_RESTRICT_ORDRCND, XSCF_NULL, 1, 1, "tracerestrict_order_cond", NULL, NULL, NULL }, { XSLFI_PROG_SIGS, XSCF_NULL, 1, 1, "programmable_signals", NULL, NULL, "SPRG" }, diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 0be2859123..1d1a004236 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -22,11 +22,11 @@ #include "string_func.h" #include "pathfinder/yapf/yapf_cache.h" -#include "safeguards.h" - #include #include +#include "safeguards.h" + /** @file * * Trace Restrict Data Storage Model Notes: @@ -479,10 +479,26 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp break; case TRIT_WAIT_AT_PBS: - if (GetTraceRestrictValue(item)) { - out.flags &= ~TRPRF_WAIT_AT_PBS; - } else { - out.flags |= TRPRF_WAIT_AT_PBS; + switch (static_cast(GetTraceRestrictValue(item))) { + case TRWAPVF_WAIT_AT_PBS: + out.flags |= TRPRF_WAIT_AT_PBS; + break; + + case TRWAPVF_CANCEL_WAIT_AT_PBS: + out.flags &= ~TRPRF_WAIT_AT_PBS; + break; + + case TRWAPVF_PBS_RES_END_WAIT: + out.flags |= TRPRF_PBS_RES_END_WAIT; + break; + + case TRWAPVF_CANCEL_PBS_RES_END_WAIT: + out.flags &= ~TRPRF_PBS_RES_END_WAIT; + break; + + default: + NOT_REACHED(); + break; } break; @@ -509,6 +525,22 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp if (input.permitted_slot_operations & TRPISP_RELEASE_FRONT) slot->Vacate(v->index); break; + case TRSCOF_PBS_RES_END_ACQ_WAIT: + if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) { + if (!slot->Occupy(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT; + } else if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) { + if (!slot->OccupyDryRun(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT; + } + break; + + case TRSCOF_PBS_RES_END_ACQ_TRY: + if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) slot->Occupy(v->index); + break; + + case TRSCOF_PBS_RES_END_RELEASE: + if (input.permitted_slot_operations & TRPISP_PBS_RES_END_RELEASE) slot->Vacate(v->index); + break; + default: NOT_REACHED(); break; @@ -629,7 +661,21 @@ CommandCost TraceRestrictProgram::Validate(const std::vector break; case TRIT_WAIT_AT_PBS: - actions_used_flags |= TRPAUF_WAIT_AT_PBS; + switch (static_cast(GetTraceRestrictValue(item))) { + case TRWAPVF_WAIT_AT_PBS: + case TRWAPVF_CANCEL_WAIT_AT_PBS: + actions_used_flags |= TRPAUF_WAIT_AT_PBS; + break; + + case TRWAPVF_PBS_RES_END_WAIT: + case TRWAPVF_CANCEL_PBS_RES_END_WAIT: + actions_used_flags |= TRPAUF_PBS_RES_END_WAIT; + break; + + default: + NOT_REACHED(); + break; + } break; case TRIT_SLOT: @@ -650,6 +696,15 @@ CommandCost TraceRestrictProgram::Validate(const std::vector actions_used_flags |= TRPAUF_SLOT_RELEASE_FRONT; break; + case TRSCOF_PBS_RES_END_ACQ_WAIT: + actions_used_flags |= TRPAUF_PBS_RES_END_SLOT | TRPAUF_PBS_RES_END_WAIT; + break; + + case TRSCOF_PBS_RES_END_ACQ_TRY: + case TRSCOF_PBS_RES_END_RELEASE: + actions_used_flags |= TRPAUF_PBS_RES_END_SLOT; + break; + default: NOT_REACHED(); break; @@ -1473,6 +1528,18 @@ bool TraceRestrictSlot::Occupy(VehicleID id, bool force) return true; } +/** + * Dry-run adding vehicle ID to occupants if possible and not already an occupant + * @param id Vehicle ID + * @return whether vehicle IDwould be an occupant + */ +bool TraceRestrictSlot::OccupyDryRun(VehicleID id) +{ + if (this->IsOccupant(id)) return true; + if (this->occupants.size() >= this->max_occupancy) return false; + return true; +} + /** * Remove vehicle ID from occupants * @param id Vehicle ID diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 02fba9117d..42ace7a086 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -223,6 +223,16 @@ enum TraceRestrictPathfinderPenaltyAuxField { /* space up to 3 */ }; +/** + * TraceRestrictItem value field, for TRIT_WAIT_AT_PBS + */ +enum TraceRestrictWaitAtPbsValueField { + TRWAPVF_WAIT_AT_PBS = 0, ///< Wait at PBS + TRWAPVF_CANCEL_WAIT_AT_PBS = 1, ///< Cancel wait at PBS + TRWAPVF_PBS_RES_END_WAIT = 2, ///< PBS reservations ending at this signal wait + TRWAPVF_CANCEL_PBS_RES_END_WAIT = 3, ///< Cancel PBS reservations ending at this signal wait +}; + /** * TraceRestrictItem repurposed condition operator field, for slot operation type actions */ @@ -231,6 +241,9 @@ enum TraceRestrictSlotCondOpField { TRSCOF_ACQUIRE_TRY = 1, ///< try to acquire a slot, or carry on otherwise TRSCOF_RELEASE_BACK = 2, ///< release a slot (back of train) TRSCOF_RELEASE_FRONT = 3, ///< release a slot (front of train) + TRSCOF_PBS_RES_END_ACQ_WAIT = 4, ///< PBS reservations ending at this signal: acquire a slot, or wait + TRSCOF_PBS_RES_END_ACQ_TRY = 5, ///< PBS reservations ending at this signal: acquire a slot, or carry on otherwise + TRSCOF_PBS_RES_END_RELEASE = 6, ///< PBS reservations ending at this signal: release a slot /* space up to 8 */ }; @@ -262,6 +275,7 @@ enum TraceRestrictProgramResultFlags { TRPRF_RESERVE_THROUGH = 1 << 1, ///< Reserve through is set TRPRF_LONG_RESERVE = 1 << 2, ///< Long reserve is set TRPRF_WAIT_AT_PBS = 1 << 3, ///< Wait at PBS signal is set + TRPRF_PBS_RES_END_WAIT = 1 << 4, ///< PBS reservations ending at this signal wait is set }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) @@ -276,6 +290,8 @@ enum TraceRestrictProgramActionsUsedFlags { TRPAUF_SLOT_ACQUIRE = 1 << 4, ///< Slot acquire action is present TRPAUF_SLOT_RELEASE_BACK = 1 << 5, ///< Slot release (back) action is present TRPAUF_SLOT_RELEASE_FRONT = 1 << 6, ///< Slot release (front) action is present + TRPAUF_PBS_RES_END_WAIT = 1 << 7, ///< PBS reservations ending at this signal wait action is present + TRPAUF_PBS_RES_END_SLOT = 1 << 8, ///< PBS reservations ending at this signal slot action is present }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) @@ -286,6 +302,9 @@ enum TraceRestrictProgramInputSlotPermissions { TRPISP_ACQUIRE = 1 << 0, ///< Slot acquire is permitted TRPISP_RELEASE_BACK = 1 << 1, ///< Slot release (back) is permitted TRPISP_RELEASE_FRONT = 1 << 2, ///< Slot release (front) is permitted + TRPISP_PBS_RES_END_ACQUIRE = 1 << 3, ///< Slot acquire (PBS reservations ending at this signal) is permitted + TRPISP_PBS_RES_END_ACQ_DRY = 1 << 4, ///< Dry-run slot acquire (PBS reservations ending at this signal) is permitted + TRPISP_PBS_RES_END_RELEASE = 1 << 5, ///< Slot release (PBS reservations ending at this signal) is permitted }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputSlotPermissions) @@ -499,7 +518,7 @@ enum TraceRestrictValueType { TRVT_FORCE = 15,///< takes a force TRVT_POWER_WEIGHT_RATIO = 16,///< takes a power / weight ratio, * 100 TRVT_FORCE_WEIGHT_RATIO = 17,///< takes a force / weight ratio, * 100 - TRVT_WAIT_AT_PBS = 18,///< takes a value 0 = wait at PBS signal, 1 = cancel wait at PBS signal + TRVT_WAIT_AT_PBS = 18,///< takes a TraceRestrictWaitAtPbsValueField value TRVT_SLOT_INDEX = 19,///< takes a TraceRestrictSlotID TRVT_SLOT_INDEX_INT = 20,///< takes a TraceRestrictSlotID, and an integer in the next item slot TRVT_OWNER = 40,///< takes a CompanyID @@ -778,6 +797,7 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p } bool Occupy(VehicleID id, bool force = false); + bool OccupyDryRun(VehicleID ids); void Vacate(VehicleID id); void Clear(); diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 0f6924214d..9b721220fb 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -225,11 +225,15 @@ static const TraceRestrictDropDownListSet _long_reserve_value = { static const StringID _wait_at_pbs_value_str[] = { STR_TRACE_RESTRICT_WAIT_AT_PBS, STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL, + STR_TRACE_RESTRICT_PBS_RES_END_WAIT_SHORT, + STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL_SHORT, INVALID_STRING_ID }; static const uint _wait_at_pbs_value_val[] = { - 0, - 1, + TRWAPVF_WAIT_AT_PBS, + TRWAPVF_CANCEL_WAIT_AT_PBS, + TRWAPVF_PBS_RES_END_WAIT, + TRWAPVF_CANCEL_PBS_RES_END_WAIT, }; /** value drop down list for wait at PBS types strings and values */ @@ -506,6 +510,9 @@ static const StringID _slot_op_cond_ops_str[] = { STR_TRACE_RESTRICT_SLOT_TRY_ACQUIRE, STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT, STR_TRACE_RESTRICT_SLOT_RELEASE_BACK, + STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT, + STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE, + STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE, INVALID_STRING_ID, }; static const uint _slot_op_cond_ops_val[] = { @@ -513,6 +520,9 @@ static const uint _slot_op_cond_ops_val[] = { TRSCOF_ACQUIRE_TRY, TRSCOF_RELEASE_FRONT, TRSCOF_RELEASE_BACK, + TRSCOF_PBS_RES_END_ACQ_WAIT, + TRSCOF_PBS_RES_END_ACQ_TRY, + TRSCOF_PBS_RES_END_RELEASE, }; /** cargo conditional operators dropdown list set */ static const TraceRestrictDropDownListSet _slot_op_cond_ops = { @@ -1054,7 +1064,27 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric break; case TRIT_WAIT_AT_PBS: - instruction_string = GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL : STR_TRACE_RESTRICT_WAIT_AT_PBS; + switch (static_cast(GetTraceRestrictValue(item))) { + case TRWAPVF_WAIT_AT_PBS: + instruction_string = STR_TRACE_RESTRICT_WAIT_AT_PBS; + break; + + case TRWAPVF_CANCEL_WAIT_AT_PBS: + instruction_string = STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL; + break; + + case TRWAPVF_PBS_RES_END_WAIT: + instruction_string = STR_TRACE_RESTRICT_PBS_RES_END_WAIT; + break; + + case TRWAPVF_CANCEL_PBS_RES_END_WAIT: + instruction_string = STR_TRACE_RESTRICT_PBS_RES_END_WAIT_CANCEL; + break; + + default: + NOT_REACHED(); + break; + } break; case TRIT_SLOT: @@ -1075,6 +1105,18 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric instruction_string = STR_TRACE_RESTRICT_SLOT_RELEASE_FRONT_ITEM; break; + case TRSCOF_PBS_RES_END_ACQ_WAIT: + instruction_string = STR_TRACE_RESTRICT_SLOT_PBS_RES_END_ACQUIRE_WAIT_ITEM; + break; + + case TRSCOF_PBS_RES_END_ACQ_TRY: + instruction_string = STR_TRACE_RESTRICT_SLOT_PBS_RES_END_TRY_ACQUIRE_ITEM; + break; + + case TRSCOF_PBS_RES_END_RELEASE: + instruction_string = STR_TRACE_RESTRICT_SLOT_PBS_RES_END_RELEASE_ITEM; + break; + default: NOT_REACHED(); break; @@ -2272,7 +2314,7 @@ private: right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = - GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_WAIT_AT_PBS_CANCEL : STR_TRACE_RESTRICT_WAIT_AT_PBS; + GetDropDownStringByValue(&_wait_at_pbs_value, GetTraceRestrictValue(item)); break; case TRVT_GROUP_INDEX: diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index cc3518153e..bf4d8be7fb 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2813,9 +2813,19 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, const PBSTileInfo &ori cur_td = FindFirstTrackdir(ft.m_new_td_bits); if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) { - bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg); + PBSWaitingPositionRestrictedSignalInfo restricted_signal_info; + bool wp_free = IsWaitingPositionFree(v, tile, cur_td, _settings_game.pf.forbid_90_deg, &restricted_signal_info); if (!(wp_free && TryReserveRailTrack(tile, TrackdirToTrack(cur_td)))) break; /* Safe position is all good, path valid and okay. */ + if (restricted_signal_info.tile != INVALID_TILE) { + const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(restricted_signal_info.tile, TrackdirToTrack(restricted_signal_info.trackdir)); + if (prog && prog->actions_used_flags & TRPAUF_PBS_RES_END_SLOT) { + TraceRestrictProgramResult out; + TraceRestrictProgramInput input(restricted_signal_info.tile, restricted_signal_info.trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, NULL); + input.permitted_slot_operations = TRPISP_PBS_RES_END_ACQUIRE | TRPISP_PBS_RES_END_RELEASE; + prog->Execute(v, input, out); + } + } return PBSTileInfo(tile, cur_td, true); }