diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 05b8ae8c47..8ccd5ce67f 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -731,11 +731,18 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp case TRSCOF_ACQUIRE_WAIT: if (input.permitted_slot_operations & TRPISP_ACQUIRE) { if (!slot->Occupy(v->index)) out.flags |= TRPRF_WAIT_AT_PBS; + } else if (input.permitted_slot_operations & TRPISP_ACQUIRE_TEMP_STATE) { + if (!slot->OccupyUsingTemporaryState(v->index, input.slot_temporary_state)) out.flags |= TRPRF_WAIT_AT_PBS; } break; case TRSCOF_ACQUIRE_TRY: - if (input.permitted_slot_operations & TRPISP_ACQUIRE) slot->Occupy(v->index); + case TRSCOF_ACQUIRE_TRY_ON_RESERVE: + if (input.permitted_slot_operations & TRPISP_ACQUIRE) { + slot->Occupy(v->index); + } else if (input.permitted_slot_operations & TRPISP_ACQUIRE_TEMP_STATE) { + slot->OccupyUsingTemporaryState(v->index, input.slot_temporary_state); + } break; case TRSCOF_RELEASE_BACK: @@ -774,10 +781,6 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp } break; - case TRSCOF_ACQUIRE_TRY_ON_RESERVE: - if (input.permitted_slot_operations & TRPISP_ACQUIRE_ON_RES) slot->Occupy(v->index); - break; - default: NOT_REACHED(); break; @@ -1351,6 +1354,7 @@ CommandCost TraceRestrictProgram::Validate(const std::vector break; case TRSCOF_ACQUIRE_TRY: + case TRSCOF_ACQUIRE_TRY_ON_RESERVE: actions_used_flags |= TRPAUF_SLOT_ACQUIRE; break; @@ -1379,10 +1383,6 @@ CommandCost TraceRestrictProgram::Validate(const std::vector include(pbs_res_end_released_slots, GetTraceRestrictValue(item)); break; - case TRSCOF_ACQUIRE_TRY_ON_RESERVE: - actions_used_flags |= TRPAUF_SLOT_ACQUIRE_ON_RES; - break; - default: return unknown_instruction(); } @@ -2537,10 +2537,7 @@ bool TraceRestrictSlot::Occupy(VehicleID id, bool force) if (this->IsOccupant(id)) return true; if (this->occupants.size() >= this->max_occupancy && !force) return false; this->occupants.push_back(id); - slot_vehicle_index.insert({ id, this->index }); - SetBit(Vehicle::Get(id)->vehicle_flags, VF_HAVE_SLOT); - SetWindowDirty(WC_VEHICLE_DETAILS, id); - InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS); + this->AddIndex(id); this->UpdateSignals(); return true; } @@ -2619,6 +2616,15 @@ void TraceRestrictSlot::UpdateSignals() { } } +void TraceRestrictSlot::AddIndex(VehicleID id) +{ + slot_vehicle_index.insert({ id, this->index }); + SetBit(Vehicle::Get(id)->vehicle_flags, VF_HAVE_SLOT); + SetWindowDirty(WC_VEHICLE_DETAILS, id); + InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS); + +} + void TraceRestrictSlot::DeIndex(VehicleID id) { auto start = slot_vehicle_index.lower_bound(id); @@ -2704,6 +2710,28 @@ void TraceRestrictSlotTemporaryState::RevertTemporaryChanges(VehicleID veh) this->veh_temporarily_removed.clear(); } +/** Apply any temporary changes */ +void TraceRestrictSlotTemporaryState::ApplyTemporaryChanges(VehicleID veh) +{ + for (TraceRestrictSlotID id : this->veh_temporarily_added) { + TraceRestrictSlot *slot = TraceRestrictSlot::Get(id); + if (slot->IsOccupant(veh)) { + slot->AddIndex(veh); + slot->UpdateSignals(); + } + } + for (TraceRestrictSlotID id : this->veh_temporarily_removed) { + TraceRestrictSlot *slot = TraceRestrictSlot::Get(id); + if (!slot->IsOccupant(veh)) { + slot->DeIndex(veh); + slot->UpdateSignals(); + } + } + + this->veh_temporarily_added.clear(); + this->veh_temporarily_removed.clear(); +} + /** Remove vehicle ID from all slot occupants */ void TraceRestrictRemoveVehicleFromAllSlots(VehicleID vehicle_id) { diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 9bed9a83b0..eb794b9c3a 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -489,6 +489,7 @@ enum TraceRestrictProgramInputSlotPermissions : uint8_t { 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 TRPISP_CHANGE_COUNTER = 1 << 6, ///< Change counter value is permitted + TRPISP_ACQUIRE_TEMP_STATE = 1 << 7, ///< Slot acquire is permitted, using temporary state, TraceRestrictProgramInput::slot_temporary_state must be set }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputSlotPermissions) @@ -505,6 +506,12 @@ struct TraceRestrictSlotTemporaryState { std::vector veh_temporarily_removed; void RevertTemporaryChanges(VehicleID veh); + void ApplyTemporaryChanges(VehicleID veh); + + bool IsEmpty() const + { + return this->veh_temporarily_added.empty() && this->veh_temporarily_removed.empty(); + } }; /** @@ -519,6 +526,7 @@ struct TraceRestrictProgramInput { const void *previous_signal_ptr; ///< Opaque pointer suitable to be passed to previous_signal_callback TraceRestrictProgramInputSlotPermissions permitted_slot_operations; ///< Permitted slot operations TraceRestrictProgramInputFlags input_flags; ///< Input flags + TraceRestrictSlotTemporaryState *slot_temporary_state = nullptr; ///< Slot temporary state, must be set when permitted_slot_operations includes TRPISP_ACQUIRE_TEMP_STATE TraceRestrictProgramInput(TileIndex tile_, Trackdir trackdir_, PreviousSignalProc *previous_signal_callback_, const void *previous_signal_ptr_) : tile(tile_), trackdir(trackdir_), previous_signal_callback(previous_signal_callback_), previous_signal_ptr(previous_signal_ptr_), @@ -1143,6 +1151,8 @@ static const uint MAX_LENGTH_TRACE_RESTRICT_SLOT_NAME_CHARS = 128; ///< The maxi * Slot type, used for slot operations */ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_pool> { + friend TraceRestrictSlotTemporaryState; + std::vector occupants; uint32_t max_occupancy = 1; std::string name; @@ -1184,6 +1194,7 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p void UpdateSignals(); private: + void AddIndex(VehicleID id); void DeIndex(VehicleID id); };