Fully simulate slot occupancy changes in PBS res end dry-run mode
This commit is contained in:
@@ -73,6 +73,9 @@ INSTANTIATE_POOL_METHODS(TraceRestrictSlot)
|
|||||||
TraceRestrictCounterPool _tracerestrictcounter_pool("TraceRestrictCounter");
|
TraceRestrictCounterPool _tracerestrictcounter_pool("TraceRestrictCounter");
|
||||||
INSTANTIATE_POOL_METHODS(TraceRestrictCounter)
|
INSTANTIATE_POOL_METHODS(TraceRestrictCounter)
|
||||||
|
|
||||||
|
std::vector<TraceRestrictSlotID> TraceRestrictSlot::veh_temporarily_added;
|
||||||
|
std::vector<TraceRestrictSlotID> TraceRestrictSlot::veh_temporarily_removed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TraceRestrictRefId --> TraceRestrictProgramID (Pool ID) mapping
|
* TraceRestrictRefId --> TraceRestrictProgramID (Pool ID) mapping
|
||||||
* The indirection is mainly to enable shared programs
|
* The indirection is mainly to enable shared programs
|
||||||
@@ -667,16 +670,28 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
|
|||||||
if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) {
|
if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) {
|
||||||
if (!slot->Occupy(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT;
|
if (!slot->Occupy(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT;
|
||||||
} else if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) {
|
} else if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) {
|
||||||
if (!slot->OccupyDryRun(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT;
|
if (this->actions_used_flags & TRPAUF_PBS_RES_END_SIMULATE) {
|
||||||
|
if (!slot->OccupyDryRunUsingTemporaryState(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT;
|
||||||
|
} else {
|
||||||
|
if (!slot->OccupyDryRun(v->index)) out.flags |= TRPRF_PBS_RES_END_WAIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRSCOF_PBS_RES_END_ACQ_TRY:
|
case TRSCOF_PBS_RES_END_ACQ_TRY:
|
||||||
if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) slot->Occupy(v->index);
|
if (input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQUIRE) {
|
||||||
|
slot->Occupy(v->index);
|
||||||
|
} else if ((input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) && (this->actions_used_flags & TRPAUF_PBS_RES_END_SIMULATE)) {
|
||||||
|
slot->OccupyDryRunUsingTemporaryState(v->index);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRSCOF_PBS_RES_END_RELEASE:
|
case TRSCOF_PBS_RES_END_RELEASE:
|
||||||
if (input.permitted_slot_operations & TRPISP_PBS_RES_END_RELEASE) slot->Vacate(v->index);
|
if (input.permitted_slot_operations & TRPISP_PBS_RES_END_RELEASE) {
|
||||||
|
slot->Vacate(v->index);
|
||||||
|
} else if ((input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) && (this->actions_used_flags & TRPAUF_PBS_RES_END_SIMULATE)) {
|
||||||
|
slot->VacateUsingTemporaryState(v->index);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRSCOF_ACQUIRE_TRY_ON_RESERVE:
|
case TRSCOF_ACQUIRE_TRY_ON_RESERVE:
|
||||||
@@ -797,6 +812,9 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((input.permitted_slot_operations & TRPISP_PBS_RES_END_ACQ_DRY) && (this->actions_used_flags & TRPAUF_PBS_RES_END_SIMULATE)) {
|
||||||
|
TraceRestrictSlot::RevertTemporaryChanges(v->index);
|
||||||
|
}
|
||||||
assert(condstack.empty());
|
assert(condstack.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,6 +841,11 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
|||||||
condstack.clear();
|
condstack.clear();
|
||||||
actions_used_flags = static_cast<TraceRestrictProgramActionsUsedFlags>(0);
|
actions_used_flags = static_cast<TraceRestrictProgramActionsUsedFlags>(0);
|
||||||
|
|
||||||
|
static std::vector<TraceRestrictSlotID> pbs_res_end_released_slots;
|
||||||
|
pbs_res_end_released_slots.clear();
|
||||||
|
static std::vector<TraceRestrictSlotID> pbs_res_end_acquired_slots;
|
||||||
|
pbs_res_end_acquired_slots.clear();
|
||||||
|
|
||||||
size_t size = items.size();
|
size_t size = items.size();
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
TraceRestrictItem item = items[i];
|
TraceRestrictItem item = items[i];
|
||||||
@@ -878,8 +901,6 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
|||||||
case TRIT_COND_ENTRY_DIRECTION:
|
case TRIT_COND_ENTRY_DIRECTION:
|
||||||
case TRIT_COND_PBS_ENTRY_SIGNAL:
|
case TRIT_COND_PBS_ENTRY_SIGNAL:
|
||||||
case TRIT_COND_TRAIN_GROUP:
|
case TRIT_COND_TRAIN_GROUP:
|
||||||
case TRIT_COND_TRAIN_IN_SLOT:
|
|
||||||
case TRIT_COND_SLOT_OCCUPANCY:
|
|
||||||
case TRIT_COND_PHYS_PROP:
|
case TRIT_COND_PHYS_PROP:
|
||||||
case TRIT_COND_PHYS_RATIO:
|
case TRIT_COND_PHYS_RATIO:
|
||||||
case TRIT_COND_TRAIN_OWNER:
|
case TRIT_COND_TRAIN_OWNER:
|
||||||
@@ -891,6 +912,13 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
|||||||
case TRIT_COND_CATEGORY:
|
case TRIT_COND_CATEGORY:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TRIT_COND_TRAIN_IN_SLOT:
|
||||||
|
case TRIT_COND_SLOT_OCCUPANCY:
|
||||||
|
if (find_index(pbs_res_end_released_slots, GetTraceRestrictValue(item)) >= 0 || find_index(pbs_res_end_acquired_slots, GetTraceRestrictValue(item)) >= 0) {
|
||||||
|
actions_used_flags |= TRPAUF_PBS_RES_END_SIMULATE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION);
|
return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION);
|
||||||
}
|
}
|
||||||
@@ -947,11 +975,19 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
|||||||
|
|
||||||
case TRSCOF_PBS_RES_END_ACQ_WAIT:
|
case TRSCOF_PBS_RES_END_ACQ_WAIT:
|
||||||
actions_used_flags |= TRPAUF_PBS_RES_END_SLOT | TRPAUF_PBS_RES_END_WAIT;
|
actions_used_flags |= TRPAUF_PBS_RES_END_SLOT | TRPAUF_PBS_RES_END_WAIT;
|
||||||
|
if (find_index(pbs_res_end_released_slots, GetTraceRestrictValue(item)) >= 0) actions_used_flags |= TRPAUF_PBS_RES_END_SIMULATE;
|
||||||
|
include(pbs_res_end_acquired_slots, GetTraceRestrictValue(item));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRSCOF_PBS_RES_END_ACQ_TRY:
|
case TRSCOF_PBS_RES_END_ACQ_TRY:
|
||||||
|
actions_used_flags |= TRPAUF_PBS_RES_END_SLOT;
|
||||||
|
if (find_index(pbs_res_end_released_slots, GetTraceRestrictValue(item)) >= 0) actions_used_flags |= TRPAUF_PBS_RES_END_SIMULATE;
|
||||||
|
include(pbs_res_end_acquired_slots, GetTraceRestrictValue(item));
|
||||||
|
break;
|
||||||
|
|
||||||
case TRSCOF_PBS_RES_END_RELEASE:
|
case TRSCOF_PBS_RES_END_RELEASE:
|
||||||
actions_used_flags |= TRPAUF_PBS_RES_END_SLOT;
|
actions_used_flags |= TRPAUF_PBS_RES_END_SLOT;
|
||||||
|
include(pbs_res_end_released_slots, GetTraceRestrictValue(item));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRSCOF_ACQUIRE_TRY_ON_RESERVE:
|
case TRSCOF_ACQUIRE_TRY_ON_RESERVE:
|
||||||
@@ -1932,7 +1968,7 @@ bool TraceRestrictSlot::Occupy(VehicleID id, bool force)
|
|||||||
/**
|
/**
|
||||||
* Dry-run adding vehicle ID to occupants if possible and not already an occupant
|
* Dry-run adding vehicle ID to occupants if possible and not already an occupant
|
||||||
* @param id Vehicle ID
|
* @param id Vehicle ID
|
||||||
* @return whether vehicle IDwould be an occupant
|
* @return whether vehicle ID would be an occupant
|
||||||
*/
|
*/
|
||||||
bool TraceRestrictSlot::OccupyDryRun(VehicleID id)
|
bool TraceRestrictSlot::OccupyDryRun(VehicleID id)
|
||||||
{
|
{
|
||||||
@@ -1941,6 +1977,25 @@ bool TraceRestrictSlot::OccupyDryRun(VehicleID id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dry-run adding vehicle ID to occupants if possible and not already an occupant, record any changes in the temporary state to be reverted later
|
||||||
|
* @param id Vehicle ID
|
||||||
|
* @return whether vehicle ID is now an occupant
|
||||||
|
*/
|
||||||
|
bool TraceRestrictSlot::OccupyDryRunUsingTemporaryState(VehicleID id)
|
||||||
|
{
|
||||||
|
if (this->IsOccupant(id)) return true;
|
||||||
|
if (this->occupants.size() >= this->max_occupancy) return false;
|
||||||
|
|
||||||
|
this->occupants.push_back(id);
|
||||||
|
|
||||||
|
if (find_index(veh_temporarily_removed, this->index) < 0) {
|
||||||
|
include(veh_temporarily_added, this->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove vehicle ID from occupants
|
* Remove vehicle ID from occupants
|
||||||
* @param id Vehicle ID
|
* @param id Vehicle ID
|
||||||
@@ -1953,6 +2008,19 @@ void TraceRestrictSlot::Vacate(VehicleID id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove vehicle ID from occupants, record any changes in the temporary state to be reverted later
|
||||||
|
* @param id Vehicle ID
|
||||||
|
*/
|
||||||
|
void TraceRestrictSlot::VacateUsingTemporaryState(VehicleID id)
|
||||||
|
{
|
||||||
|
if (container_unordered_remove(this->occupants, id)) {
|
||||||
|
if (find_index(veh_temporarily_added, this->index) < 0) {
|
||||||
|
include(veh_temporarily_removed, this->index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove all occupants */
|
/** Remove all occupants */
|
||||||
void TraceRestrictSlot::Clear()
|
void TraceRestrictSlot::Clear()
|
||||||
{
|
{
|
||||||
@@ -2039,6 +2107,21 @@ void TraceRestrictSlot::PreCleanPool()
|
|||||||
slot_vehicle_index.clear();
|
slot_vehicle_index.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Revert any temporary changes */
|
||||||
|
void TraceRestrictSlot::RevertTemporaryChanges(VehicleID veh)
|
||||||
|
{
|
||||||
|
for (TraceRestrictSlotID id : veh_temporarily_added) {
|
||||||
|
TraceRestrictSlot *slot = TraceRestrictSlot::Get(id);
|
||||||
|
container_unordered_remove(slot->occupants, veh);
|
||||||
|
}
|
||||||
|
for (TraceRestrictSlotID id : veh_temporarily_removed) {
|
||||||
|
TraceRestrictSlot *slot = TraceRestrictSlot::Get(id);
|
||||||
|
include(slot->occupants, veh);
|
||||||
|
}
|
||||||
|
veh_temporarily_added.clear();
|
||||||
|
veh_temporarily_removed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove vehicle ID from all slot occupants */
|
/** Remove vehicle ID from all slot occupants */
|
||||||
void TraceRestrictRemoveVehicleFromAllSlots(VehicleID vehicle_id)
|
void TraceRestrictRemoveVehicleFromAllSlots(VehicleID vehicle_id)
|
||||||
{
|
{
|
||||||
|
@@ -421,6 +421,7 @@ enum TraceRestrictProgramActionsUsedFlags {
|
|||||||
TRPAUF_NO_PBS_BACK_PENALTY = 1 << 13, ///< No PBS back penalty is present
|
TRPAUF_NO_PBS_BACK_PENALTY = 1 << 13, ///< No PBS back penalty is present
|
||||||
TRPAUF_SLOT_ACQUIRE_ON_RES = 1 << 14, ///< Slot acquire (on reserve) action is present
|
TRPAUF_SLOT_ACQUIRE_ON_RES = 1 << 14, ///< Slot acquire (on reserve) action is present
|
||||||
TRPAUF_SPEED_ADAPTATION = 1 << 15, ///< Speed adaptation control
|
TRPAUF_SPEED_ADAPTATION = 1 << 15, ///< Speed adaptation control
|
||||||
|
TRPAUF_PBS_RES_END_SIMULATE = 1 << 16, ///< PBS reservations ending at this signal slot changes must be fully simulated in dry run mode
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags)
|
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags)
|
||||||
|
|
||||||
@@ -994,10 +995,14 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p
|
|||||||
|
|
||||||
std::vector<SignalReference> progsig_dependants;
|
std::vector<SignalReference> progsig_dependants;
|
||||||
|
|
||||||
|
static std::vector<TraceRestrictSlotID> veh_temporarily_added;
|
||||||
|
static std::vector<TraceRestrictSlotID> veh_temporarily_removed;
|
||||||
|
|
||||||
static void RebuildVehicleIndex();
|
static void RebuildVehicleIndex();
|
||||||
static bool ValidateVehicleIndex();
|
static bool ValidateVehicleIndex();
|
||||||
static void ValidateSlotOccupants(std::function<void(const char *)> log);
|
static void ValidateSlotOccupants(std::function<void(const char *)> log);
|
||||||
static void PreCleanPool();
|
static void PreCleanPool();
|
||||||
|
static void RevertTemporaryChanges(VehicleID veh);
|
||||||
|
|
||||||
TraceRestrictSlot(CompanyID owner = INVALID_COMPANY, VehicleType type = VEH_TRAIN)
|
TraceRestrictSlot(CompanyID owner = INVALID_COMPANY, VehicleType type = VEH_TRAIN)
|
||||||
{
|
{
|
||||||
@@ -1020,7 +1025,9 @@ struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_p
|
|||||||
|
|
||||||
bool Occupy(VehicleID id, bool force = false);
|
bool Occupy(VehicleID id, bool force = false);
|
||||||
bool OccupyDryRun(VehicleID ids);
|
bool OccupyDryRun(VehicleID ids);
|
||||||
|
bool OccupyDryRunUsingTemporaryState(VehicleID id);
|
||||||
void Vacate(VehicleID id);
|
void Vacate(VehicleID id);
|
||||||
|
void VacateUsingTemporaryState(VehicleID id);
|
||||||
void Clear();
|
void Clear();
|
||||||
void UpdateSignals();
|
void UpdateSignals();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user