You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OpenTTD-patches/src/tracerestrict.h

1261 lines
49 KiB
C++

/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file tracerestrict.h Header file for Trace Restrict */
#ifndef TRACERESTRICT_H
#define TRACERESTRICT_H
#include "stdafx.h"
#include "core/bitmath_func.hpp"
#include "core/enum_type.hpp"
#include "core/pool_type.hpp"
#include "core/container_func.hpp"
#include "command_func.h"
#include "rail_map.h"
#include "tile_type.h"
#include "group_type.h"
#include "vehicle_type.h"
#include "signal_type.h"
#include "3rdparty/cpp-btree/btree_map.h"
#include <map>
#include <vector>
struct Train;
/** Program pool ID type. */
typedef uint32_t TraceRestrictProgramID;
struct TraceRestrictProgram;
/** Tile/track mapping type. */
typedef uint32_t TraceRestrictRefId;
/** Type of the pool for trace restrict programs. */
typedef Pool<TraceRestrictProgram, TraceRestrictProgramID, 16, 256000> TraceRestrictProgramPool;
/** The actual pool for trace restrict nodes. */
extern TraceRestrictProgramPool _tracerestrictprogram_pool;
/** Slot pool ID type. */
typedef uint16_t TraceRestrictSlotID;
struct TraceRestrictSlot;
/** Type of the pool for trace restrict slots. */
typedef Pool<TraceRestrictSlot, TraceRestrictSlotID, 16, 0xFFF0> TraceRestrictSlotPool;
/** The actual pool for trace restrict slots. */
extern TraceRestrictSlotPool _tracerestrictslot_pool;
static const TraceRestrictSlotID NEW_TRACE_RESTRICT_SLOT_ID = 0xFFFD; // for GUI use only
static const TraceRestrictSlotID ALL_TRAINS_TRACE_RESTRICT_SLOT_ID = 0xFFFE; // for GUI use only
static const TraceRestrictSlotID INVALID_TRACE_RESTRICT_SLOT_ID = 0xFFFF;
/** Counter pool ID type. */
typedef uint16_t TraceRestrictCounterID;
struct TraceRestrictCounter;
/** Type of the pool for trace restrict counters. */
typedef Pool<TraceRestrictCounter, TraceRestrictCounterID, 16, 0xFFF0> TraceRestrictCounterPool;
/** The actual pool for trace restrict counters. */
extern TraceRestrictCounterPool _tracerestrictcounter_pool;
static const TraceRestrictCounterID NEW_TRACE_RESTRICT_COUNTER_ID = 0xFFFE; // for GUI use only
static const TraceRestrictCounterID INVALID_TRACE_RESTRICT_COUNTER_ID = 0xFFFF;
extern const uint16_t _tracerestrict_pathfinder_penalty_preset_values[];
/** Type used for the TraceRestrictRefId -> TraceRestrictProgramID mapping */
struct TraceRestrictMappingItem {
TraceRestrictProgramID program_id;
TraceRestrictMappingItem() { }
TraceRestrictMappingItem(TraceRestrictProgramID program_id_)
: program_id(program_id_) { }
};
typedef btree::btree_map<TraceRestrictRefId, TraceRestrictMappingItem> TraceRestrictMapping;
/** The actual mapping from TraceRestrictRefId to TraceRestrictProgramID. */
extern TraceRestrictMapping _tracerestrictprogram_mapping;
void ClearTraceRestrictMapping();
/** Type of a single instruction, this is bit-packed as per TraceRestrictItemFlagAllocation */
typedef uint32_t TraceRestrictItem;
/**
* Describes the allocation of bits to fields in TraceRestrictItem.
* Of the fields below, the type seems the most likely
* to need future expansion, hence the reserved bits are placed
* immediately after them.
*
* This only applies to the first item of dual-item instructions.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | |Cond |Aux|Cond | Value |
* | | |Flags| | Op | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | |
* Free Combined wider field (TRIFA_CMB_AUX_COND)
*
* COUNT values describe the field bit width
* OFFSET values describe the field bit offset
*/
enum TraceRestrictItemFlagAllocation {
TRIFA_TYPE_COUNT = 6,
TRIFA_TYPE_OFFSET = 0,
/* 2 bits reserved for future use */
TRIFA_COND_FLAGS_COUNT = 3,
TRIFA_COND_FLAGS_OFFSET = 8,
TRIFA_AUX_FIELD_COUNT = 2,
TRIFA_AUX_FIELD_OFFSET = 11,
TRIFA_COND_OP_COUNT = 3,
TRIFA_COND_OP_OFFSET = 13,
TRIFA_CMB_AUX_COND_COUNT = 5, ///< This aliases the AUX_FIELD and COND_OP fields as a single wider field
TRIFA_CMB_AUX_COND_OFFSET = 11,
TRIFA_VALUE_COUNT = 16,
TRIFA_VALUE_OFFSET = 16,
};
/**
* Enumeration of TraceRestrictItem type field.
* This has a width of 6 bits (0 - 63).
* This is split into three sections:
* * non-conditionals: 0 <= type < TRIT_COND_BEGIN
* * conditionals: TRIT_COND_BEGIN <= type < TRIT_COND_END
* * non-conditionals: TRIT_COND_END <= type < max (63)
*
* This was previously 5 bits (0 - 31), which is why it's in three sections, not two.
*/
enum TraceRestrictItemType : uint8_t {
TRIT_NULL = 0, ///< Null-type, not in programs and not valid for execution, mainly used with TraceRestrictNullTypeSpecialValue for start/end
TRIT_PF_DENY = 1, ///< Pathfinder deny/allow
TRIT_PF_PENALTY = 2, ///< Add to pathfinder penalty
TRIT_RESERVE_THROUGH = 3, ///< Reserve through PBS signal
TRIT_LONG_RESERVE = 4, ///< Long reserve PBS signal
TRIT_WAIT_AT_PBS = 5, ///< Wait at PBS signal
TRIT_SLOT = 6, ///< Slot operation
TRIT_COND_BEGIN = 8, ///< Start of conditional item types, note that this has the same value as TRIT_COND_ENDIF
TRIT_COND_ENDIF = 8, ///< This is an endif block or an else block
TRIT_COND_UNDEFINED = 9, ///< This condition has no type defined (evaluate as false)
TRIT_COND_TRAIN_LENGTH = 10, ///< Test train length
TRIT_COND_MAX_SPEED = 11, ///< Test train max speed
TRIT_COND_CURRENT_ORDER = 12, ///< Test train current order (station, waypoint or depot)
TRIT_COND_NEXT_ORDER = 13, ///< Test train next order (station, waypoint or depot)
TRIT_COND_LAST_STATION = 14, ///< Test train last visited station
TRIT_COND_CARGO = 15, ///< Test if train can carry cargo type
TRIT_COND_ENTRY_DIRECTION = 16, ///< Test which side of signal/signal tile is being entered from
TRIT_COND_PBS_ENTRY_SIGNAL = 17, ///< Test tile and PBS-state of previous signal
TRIT_COND_TRAIN_GROUP = 18, ///< Test train group membership
TRIT_COND_PHYS_PROP = 19, ///< Test train physical property
TRIT_COND_PHYS_RATIO = 20, ///< Test train physical property ratio
TRIT_COND_TRAIN_IN_SLOT = 21, ///< Test train slot membership
TRIT_COND_SLOT_OCCUPANCY = 22, ///< Test train slot occupancy state
TRIT_COND_TRAIN_OWNER = 24, ///< Test train owner
TRIT_COND_TRAIN_STATUS = 25, ///< Test train status
TRIT_COND_LOAD_PERCENT = 26, ///< Test train load percentage
TRIT_COND_COUNTER_VALUE = 27, ///< Test counter value
TRIT_COND_TIME_DATE_VALUE = 28, ///< Test time/date value
TRIT_COND_RESERVED_TILES = 29, ///< Test reserved tiles ahead of train
TRIT_COND_CATEGORY = 30, ///< Test train category
TRIT_COND_TARGET_DIRECTION = 31, ///< Test direction of order target tile relative to this signal tile
TRIT_COND_RESERVATION_THROUGH = 32, ///< Test if train reservation passes through tile
TRIT_COND_END = 48, ///< End (exclusive) of conditional item types, note that this has the same value as TRIT_REVERSE
TRIT_REVERSE = 48, ///< Reverse behind signal
TRIT_SPEED_RESTRICTION = 49, ///< Speed restriction
TRIT_NEWS_CONTROL = 50, ///< News control
TRIT_COUNTER = 51, ///< Change counter value
TRIT_PF_PENALTY_CONTROL = 52, ///< Control base signal penalties
TRIT_SPEED_ADAPTATION_CONTROL = 53, ///< Control speed adaptation
TRIT_SIGNAL_MODE_CONTROL = 54, ///< Control signal modes
/* space up to 63 */
};
/**
* TraceRestrictItem condition flags field, only valid with conditional types (IsTraceRestrictTypeConditional() is true)
*/
enum TraceRestrictCondFlags : uint8_t {
TRCF_DEFAULT = 0, ///< indicates end if for type: TRIT_COND_ENDIF, if otherwise
TRCF_ELSE = 1 << 0, ///< indicates an else block for type: TRIT_COND_ENDIF, elif otherwise
TRCF_OR = 1 << 1, ///< indicates an orif block, not valid with type: TRIT_COND_ENDIF
/* 1 bit spare */
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictCondFlags)
/**
* Enumeration of TraceRestrictItemvalue type field when type is TRIT_NULL
*/
enum TraceRestrictNullTypeSpecialValue : uint8_t {
TRNTSV_NULL = 0, ///< null, what you get when you zero-init a TraceRestrictItemvalue
TRNTSV_START = 1, ///< start tag, generated within GUI
TRNTSV_END = 2, ///< end tag, generated within GUI
};
/**
* Enumeration of TraceRestrictItemvalue type field when value type is TRVT_DIRECTION
*/
enum TraceRestrictDirectionTypeSpecialValue : uint8_t {
TRNTSV_NE = 0, ///< DIAGDIR_NE: entering at NE tile edge
TRNTSV_SE = 1, ///< DIAGDIR_SE: entering at SE tile edge
TRNTSV_SW = 2, ///< DIAGDIR_SW: entering at SW tile edge
TRNTSV_NW = 3, ///< DIAGDIR_NW: entering at NW tile edge
TRDTSV_FRONT = 4, ///< entering at front face of signal
TRDTSV_BACK = 5, ///< entering at rear face of signal
TRDTSV_TUNBRIDGE_ENTER = 32, ///< signal is a tunnel/bridge entrance
TRDTSV_TUNBRIDGE_EXIT = 33, ///< signal is a tunnel/bridge exit
};
/**
* TraceRestrictItem condition operator field, only valid with conditional types (IsTraceRestrictTypeConditional() is true)
*/
enum TraceRestrictCondOp : uint8_t {
TRCO_IS = 0, ///< equality test, or can carry test for cargo
TRCO_ISNOT = 1, ///< inequality test, or can't carry test for cargo
TRCO_LT = 2, ///< less than test
TRCO_LTE = 3, ///< less than or equal test
TRCO_GT = 4, ///< greater than test
TRCO_GTE = 5, ///< greater than or equal test
/* space up to 7 */
};
/**
* TraceRestrictItem auxiliary type field, for order type conditionals
*/
enum TraceRestrictOrderCondAuxField : uint8_t {
TROCAF_STATION = 0, ///< value field is a station StationID
TROCAF_WAYPOINT = 1, ///< value field is a waypoint StationID
TROCAF_DEPOT = 2, ///< value field is a depot DepotID
/* space up to 3 */
};
/**
* TraceRestrictItem auxiliary type field, for physical property type conditionals
*/
enum TraceRestrictPhysPropCondAuxField : uint8_t {
TRPPCAF_WEIGHT = 0, ///< value field is a weight
TRPPCAF_POWER = 1, ///< value field is a power
TRPPCAF_MAX_TE = 2, ///< value field is a tractive effort
/* space up to 3 */
};
/**
* TraceRestrictItem auxiliary type field, for physical property ratio type conditionals
*/
enum TraceRestrictPhysPropRatioCondAuxField : uint8_t {
TRPPRCAF_POWER_WEIGHT = 0, ///< value field is a 100 * power / weight ratio
TRPPRCAF_MAX_TE_WEIGHT = 1, ///< value field is a 100 * tractive effort / weight ratio
/* space up to 3 */
};
/**
* TraceRestrictItem auxiliary type field, for category type conditionals
*/
enum TraceRestrictCatgeoryCondAuxField : uint8_t {
TRCCAF_ENGINE_CLASS = 0, ///< value field is an EngineClass type
/* space up to 3 */
};
/**
* TraceRestrictItem auxiliary type field, for TRIT_PF_PENALTY
*/
enum TraceRestrictPathfinderPenaltyAuxField : uint8_t {
TRPPAF_VALUE = 0, ///< value field is a the pathfinder penalty to use
TRPPAF_PRESET = 1, ///< value field is a pathfinder penalty prefix index: TraceRestrictPathfinderPenaltyPresetIndex
/* space up to 3 */
};
/**
* TraceRestrictItem auxiliary type field, for TRIT_COND_TARGET_DIRECTION
*/
enum TraceRestrictTargetDirectionCondAuxField : uint8_t {
TRTDCAF_CURRENT_ORDER = 0, ///< Current order
TRTDCAF_NEXT_ORDER = 1, ///< Next order
/* space up to 3 */
};
/**
* TraceRestrictItem value field, for TRIT_LONG_RESERVE
*/
enum TraceRestrictLongReserveValueField : uint8_t {
TRLRVF_LONG_RESERVE = 0, ///< Long reserve
TRLRVF_CANCEL_LONG_RESERVE = 1, ///< Cancel long reserve
TRLRVF_LONG_RESERVE_UNLESS_STOPPING = 2, ///< Long reserve (unless passed stop)
};
/**
* TraceRestrictItem value field, for TRIT_WAIT_AT_PBS
*/
enum TraceRestrictWaitAtPbsValueField : uint8_t {
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 value field, for TRIT_REVERSE
*/
enum TraceRestrictReverseValueField : uint8_t {
TRRVF_REVERSE = 0, ///< Reverse
TRRVF_CANCEL_REVERSE = 1, ///< Cancel reverse
};
/**
* TraceRestrictItem value field, for TRIT_NEWS_CONTROL
*/
enum TraceRestrictNewsControlField : uint8_t {
TRNCF_TRAIN_NOT_STUCK = 0, ///< Train is not stuck
TRNCF_CANCEL_TRAIN_NOT_STUCK = 1, ///< Cancel train is not stuck
};
/**
* TraceRestrictItem value field, for TRIT_PF_PENALTY_CONTROL
*/
enum TraceRestrictPfPenaltyControlField : uint8_t {
TRPPCF_NO_PBS_BACK_PENALTY = 0, ///< Do not apply PBS signal back penalty
TRPPCF_CANCEL_NO_PBS_BACK_PENALTY = 1, ///< Cancel do not apply PBS signal back penalty
};
/**
* TraceRestrictItem value field, for TRIT_SPEED_ADAPTATION_CONTROL
*/
enum TraceRestrictSpeedAdaptationControlField : uint8_t {
TRSACF_SPEED_ADAPT_EXEMPT = 0, ///< Make train exempt from speed adaptation
TRSACF_REMOVE_SPEED_ADAPT_EXEMPT = 1, ///< Remove train exempt from speed adaptation
};
/**
* TraceRestrictItem value field, for TRIT_SIGNAL_MODE_CONTROL
*/
enum TraceRestrictSignalModeControlField : uint8_t {
TRSMCF_NORMAL_ASPECT = 0, ///< Combined normal/shunt aspect signals: use normal mode
TRSMCF_SHUNT_ASPECT = 1, ///< Combined normal/shunt aspect signals: use shunt mode
};
/**
* TraceRestrictItem value field, for TRIT_COND_TRAIN_STATUS
*/
enum TraceRestrictTrainStatusValueField : uint8_t {
TRTSVF_EMPTY = 0, ///< Train is empty
TRTSVF_FULL = 1, ///< Train is full
TRTSVF_BROKEN_DOWN = 2, ///< Train is broken down
TRTSVF_NEEDS_REPAIR = 3, ///< Train needs repair
TRTSVF_REVERSING = 4, ///< Train is reversing
TRTSVF_HEADING_TO_STATION_WAYPOINT = 5, ///< Train is en-route to a station or waypoint
TRTSVF_HEADING_TO_DEPOT = 6, ///< Train is en-route to a depot
TRTSVF_LOADING = 7, ///< Train is loading
TRTSVF_WAITING = 8, ///< Train is waiting
TRTSVF_LOST = 9, ///< Train is lost
TRTSVF_REQUIRES_SERVICE = 10, ///< Train requires service
TRTSVF_STOPPING_AT_STATION_WAYPOINT= 11, ///< Train stops at destination station/waypoint
};
/**
* TraceRestrictItem value field, for TRIT_COND_TIME_DATE_VALUE
*/
enum TraceRestrictTimeDateValueField : uint8_t {
TRTDVF_MINUTE = 0, ///< Minute
TRTDVF_HOUR = 1, ///< Hour
TRTDVF_HOUR_MINUTE = 2, ///< Hour and minute
TRTDVF_DAY = 3, ///< Day
TRTDVF_MONTH = 4, ///< Month
TRTDVF_END = 5, ///< End tag
};
/**
* TraceRestrictItem subtype field, using the combined auxiliary and cond op bits, for slot operation type actions
*/
enum TraceRestrictSlotSubtypeField : uint8_t {
TRSCOF_ACQUIRE_WAIT = 0, ///< acquire a slot, or wait at the current signal
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
TRSCOF_RELEASE_ON_RESERVE = 7, ///< release a slot (on reserve)
/* space up to 31 */
};
/**
* TraceRestrictItem auxiliary type field, for TRIT_COND_SLOT_OCCUPANCY
*/
enum TraceRestrictSlotOccupancyCondAuxField : uint8_t {
TRSOCAF_OCCUPANTS = 0, ///< value field is the occupancy count of the slot
TRSOCAF_REMAINING = 1, ///< value field is the remaining occupancy of the slot
/* space up to 3 */
};
/**
* TraceRestrictItem repurposed condition operator field, for counter operation type actions
*/
enum TraceRestrictCounterCondOpField : uint8_t {
TRCCOF_INCREASE = 0, ///< increase counter by value
TRCCOF_DECREASE = 1, ///< decrease counter by value
TRCCOF_SET = 2, ///< set counter to value
/* space up to 7 */
};
/**
* TraceRestrictItem auxiliary type field, for TRIT_COND_PBS_ENTRY_SIGNAL
*/
enum TraceRestrictPBSEntrySignalAuxField : uint8_t {
TRPESAF_VEH_POS = 0, ///< vehicle position signal
TRPESAF_RES_END = 1, ///< reservation end signal
TRPESAF_RES_END_TILE = 2, ///< reservation end tile
/* space up to 3 */
};
/**
* TraceRestrictItem pathfinder penalty preset index
* This may not be shortened, only lengthened, as preset indexes are stored in save games
*/
enum TraceRestrictPathfinderPenaltyPresetIndex : uint8_t {
TRPPPI_SMALL = 0, ///< small preset value
TRPPPI_MEDIUM = 1, ///< medium preset value
TRPPPI_LARGE = 2, ///< large preset value
TRPPPI_END, ///< end value
};
/**
* Enumeration for TraceRestrictProgramResult::flags
*/
enum TraceRestrictProgramResultFlags : uint16_t {
TRPRF_DENY = 1 << 0, ///< Pathfinder deny is set
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
TRPRF_REVERSE = 1 << 5, ///< Reverse behind signal
TRPRF_SPEED_RESTRICTION_SET = 1 << 6, ///< Speed restriction field set
TRPRF_TRAIN_NOT_STUCK = 1 << 7, ///< Train is not stuck
TRPRF_NO_PBS_BACK_PENALTY = 1 << 8, ///< Do not apply PBS back penalty
TRPRF_SPEED_ADAPT_EXEMPT = 1 << 9, ///< Make speed adaptation exempt
TRPRF_RM_SPEED_ADAPT_EXEMPT = 1 << 10, ///< Remove speed adaptation exemption
TRPRF_SIGNAL_MODE_NORMAL = 1 << 11, ///< Combined normal/shunt signal mode control: normal
TRPRF_SIGNAL_MODE_SHUNT = 1 << 12, ///< Combined normal/shunt signal mode control: shunt
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags)
/**
* Enumeration for TraceRestrictProgram::actions_used_flags
*/
enum TraceRestrictProgramActionsUsedFlags : uint32_t {
TRPAUF_NONE = 0, ///< No flags set
TRPAUF_PF = 1 << 0, ///< Pathfinder deny or penalty are present
TRPAUF_RESERVE_THROUGH = 1 << 1, ///< Reserve through action is present
TRPAUF_LONG_RESERVE = 1 << 2, ///< Long reserve action is present
TRPAUF_WAIT_AT_PBS = 1 << 3, ///< Wait at PBS signal action is present
TRPAUF_SLOT_ACQUIRE = 1 << 4, ///< Slot acquire and/or release (on reserve) actions are 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
TRPAUF_REVERSE = 1 << 9, ///< Reverse behind signal
TRPAUF_SPEED_RESTRICTION = 1 << 10, ///< Speed restriction
TRPAUF_TRAIN_NOT_STUCK = 1 << 11, ///< Train is not stuck
TRPAUF_CHANGE_COUNTER = 1 << 12, ///< Change counter value is present
TRPAUF_NO_PBS_BACK_PENALTY = 1 << 13, ///< No PBS back penalty is present
TRPAUF_SLOT_CONDITIONALS = 1 << 14, ///< Slot conditionals are present
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
TRPAUF_RESERVE_THROUGH_ALWAYS = 1 << 17, ///< Reserve through action is unconditionally set
TRPAUF_CMB_SIGNAL_MODE_CTRL = 1 << 18, ///< Combined normal/shunt signal mode control
TRPAUF_ORDER_CONDITIONALS = 1 << 19, ///< Order conditionals are present
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags)
/**
* Enumeration for TraceRestrictProgramInput::permitted_slot_operations
*/
enum TraceRestrictProgramInputSlotPermissions : uint8_t {
TRPISP_NONE = 0, ///< No permissions
TRPISP_ACQUIRE = 1 << 0, ///< Slot acquire and release (on reserve) are 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/release (PBS reservations ending at this signal) is permitted
TRPISP_PBS_RES_END_ACQ_DRY = 1 << 4, ///< Dry-run slot acquire/release (PBS reservations ending at this signal) is permitted
TRPISP_ACQUIRE_TEMP_STATE = 1 << 5, ///< Slot acquire/release is permitted, using temporary state, TraceRestrictSlotTemporaryState::change_stack must be non-empty
TRPISP_CHANGE_COUNTER = 1 << 6, ///< Change counter value is permitted
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputSlotPermissions)
/**
* Enumeration for TraceRestrictProgramInput::input_flags
*/
enum TraceRestrictProgramInputFlags : uint8_t {
TRPIF_NONE = 0, ///< No flags set
TRPIF_PASSED_STOP = 1 << 0, ///< Train has passed stop
};
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramInputFlags)
struct TraceRestrictSlotTemporaryState {
std::vector<TraceRestrictSlotID> veh_temporarily_added;
std::vector<TraceRestrictSlotID> veh_temporarily_removed;
private:
bool is_active = false;
static std::vector<TraceRestrictSlotTemporaryState *> change_stack;
void ApplyTemporaryChanges(const Vehicle *v);
void ApplyTemporaryChangesToParent(VehicleID veh, TraceRestrictSlotTemporaryState *parent);
public:
static TraceRestrictSlotTemporaryState *GetCurrent() { return change_stack.back(); }
static void ClearChangeStackApplyAllTemporaryChanges(const Vehicle *v)
{
while (!change_stack.empty()) {
change_stack.back()->PopFromChangeStackApplyTemporaryChanges(v);
}
}
bool IsActive() const { return this->is_active; }
void RevertTemporaryChanges(VehicleID veh);
void PushToChangeStack()
{
assert(!this->is_active);
this->is_active = true;
this->change_stack.push_back(this);
}
void PopFromChangeStackRevertTemporaryChanges(VehicleID veh)
{
assert(this->change_stack.back() == this);
this->change_stack.pop_back();
this->RevertTemporaryChanges(veh);
this->is_active = false;
}
void PopFromChangeStackApplyTemporaryChanges(const Vehicle *v);
bool IsEmpty() const
{
return this->veh_temporarily_added.empty() && this->veh_temporarily_removed.empty();
}
};
/**
* Execution input of a TraceRestrictProgram
*/
struct TraceRestrictProgramInput {
typedef TileIndex PreviousSignalProc(const Train *v, const void *ptr, TraceRestrictPBSEntrySignalAuxField mode);
TileIndex tile; ///< Tile of restrict signal, for direction testing
Trackdir trackdir; ///< Track direction on tile of restrict signal, for direction testing
TraceRestrictProgramInputFlags input_flags; ///< Input flags
TraceRestrictProgramInputSlotPermissions permitted_slot_operations; ///< Permitted slot operations
PreviousSignalProc *previous_signal_callback; ///< Callback to retrieve tile and direction of previous signal, may be nullptr
const void *previous_signal_ptr; ///< Opaque pointer suitable to be passed to previous_signal_callback
TraceRestrictProgramInput(TileIndex tile_, Trackdir trackdir_, PreviousSignalProc *previous_signal_callback_, const void *previous_signal_ptr_)
: tile(tile_), trackdir(trackdir_), input_flags(TRPIF_NONE), permitted_slot_operations(TRPISP_NONE),
previous_signal_callback(previous_signal_callback_), previous_signal_ptr(previous_signal_ptr_) { }
};
/**
* Execution result of a TraceRestrictProgram
*/
struct TraceRestrictProgramResult {
uint32_t penalty; ///< Total additional pathfinder penalty
TraceRestrictProgramResultFlags flags; ///< Flags of other actions to take
uint16_t speed_restriction; ///< Speed restriction to apply (if TRPRF_SPEED_RESTRICTION_SET flag present)
TraceRestrictProgramResult()
: penalty(0), flags(static_cast<TraceRestrictProgramResultFlags>(0)) { }
};
/**
* Program type, this stores the instruction list
* This is refcounted, see info at top of tracerestrict.cpp
*/
struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrictprogram_pool> {
uint32_t refcount;
std::vector<TraceRestrictItem> items;
TraceRestrictProgramActionsUsedFlags actions_used_flags;
private:
struct ptr_buffer {
TraceRestrictRefId *buffer;
uint32_t elem_capacity;
};
union refid_list_union {
TraceRestrictRefId inline_ref_ids[4];
ptr_buffer ptr_ref_ids;
// Actual construction/destruction done by struct TraceRestrictProgram
refid_list_union() {}
~refid_list_union() {}
};
refid_list_union ref_ids;
void ClearRefIds();
inline TraceRestrictRefId *GetRefIdsPtr() { return this->refcount <= 4 ? this->ref_ids.inline_ref_ids : this->ref_ids.ptr_ref_ids.buffer; };
public:
TraceRestrictProgram()
: refcount(0), actions_used_flags(TRPAUF_NONE) { }
~TraceRestrictProgram()
{
this->ClearRefIds();
}
void Execute(const Train *v, const TraceRestrictProgramInput &input, TraceRestrictProgramResult &out) const;
inline const TraceRestrictRefId *GetRefIdsPtr() const { return const_cast<TraceRestrictProgram *>(this)->GetRefIdsPtr(); }
void IncrementRefCount(TraceRestrictRefId ref_id);
void DecrementRefCount(TraceRestrictRefId ref_id);
static CommandCost Validate(const std::vector<TraceRestrictItem> &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags);
static size_t InstructionOffsetToArrayOffset(const std::vector<TraceRestrictItem> &items, size_t offset);
static size_t ArrayOffsetToInstructionOffset(const std::vector<TraceRestrictItem> &items, size_t offset);
/** Call InstructionOffsetToArrayOffset on current program instruction list */
size_t InstructionOffsetToArrayOffset(size_t offset) const
{
return TraceRestrictProgram::InstructionOffsetToArrayOffset(this->items, offset);
}
/** Call ArrayOffsetToInstructionOffset on current program instruction list */
size_t ArrayOffsetToInstructionOffset(size_t offset) const
{
return TraceRestrictProgram::ArrayOffsetToInstructionOffset(this->items, offset);
}
/** Get number of instructions in @p items */
static size_t GetInstructionCount(const std::vector<TraceRestrictItem> &items)
{
return ArrayOffsetToInstructionOffset(items, items.size());
}
/** Call GetInstructionCount on current program instruction list */
size_t GetInstructionCount() const
{
return TraceRestrictProgram::GetInstructionCount(this->items);
}
/** Get an iterator to the instruction at a given @p instruction_offset in @p items */
static std::vector<TraceRestrictItem>::iterator InstructionAt(std::vector<TraceRestrictItem> &items, size_t instruction_offset)
{
return items.begin() + TraceRestrictProgram::InstructionOffsetToArrayOffset(items, instruction_offset);
}
/** Get a const_iterator to the instruction at a given @p instruction_offset in @p items */
static std::vector<TraceRestrictItem>::const_iterator InstructionAt(const std::vector<TraceRestrictItem> &items, size_t instruction_offset)
{
return items.begin() + TraceRestrictProgram::InstructionOffsetToArrayOffset(items, instruction_offset);
}
/** Call validation function on current program instruction list and set actions_used_flags */
CommandCost Validate()
{
return TraceRestrictProgram::Validate(items, actions_used_flags);
}
};
/** Get TraceRestrictItem type field */
inline TraceRestrictItemType GetTraceRestrictType(TraceRestrictItem item)
{
return static_cast<TraceRestrictItemType>(GB(item, TRIFA_TYPE_OFFSET, TRIFA_TYPE_COUNT));
}
/** Get TraceRestrictItem condition flags field */
inline TraceRestrictCondFlags GetTraceRestrictCondFlags(TraceRestrictItem item)
{
return static_cast<TraceRestrictCondFlags>(GB(item, TRIFA_COND_FLAGS_OFFSET, TRIFA_COND_FLAGS_COUNT));
}
/** Get TraceRestrictItem condition operator field */
inline TraceRestrictCondOp GetTraceRestrictCondOp(TraceRestrictItem item)
{
return static_cast<TraceRestrictCondOp>(GB(item, TRIFA_COND_OP_OFFSET, TRIFA_COND_OP_COUNT));
}
/** Get TraceRestrictItem auxiliary field */
inline uint8_t GetTraceRestrictAuxField(TraceRestrictItem item)
{
return GB(item, TRIFA_AUX_FIELD_OFFSET, TRIFA_AUX_FIELD_COUNT);
}
/** Get TraceRestrictItem combined condition operator and auxiliary fields */
inline uint8_t GetTraceRestrictCombinedAuxCondOpField(TraceRestrictItem item)
{
return GB(item, TRIFA_CMB_AUX_COND_OFFSET, TRIFA_CMB_AUX_COND_COUNT);
}
/** Get TraceRestrictItem value field */
inline uint16_t GetTraceRestrictValue(TraceRestrictItem item)
{
return static_cast<uint16_t>(GB(item, TRIFA_VALUE_OFFSET, TRIFA_VALUE_COUNT));
}
/** Set TraceRestrictItem type field */
inline void SetTraceRestrictType(TraceRestrictItem &item, TraceRestrictItemType type)
{
SB(item, TRIFA_TYPE_OFFSET, TRIFA_TYPE_COUNT, type);
}
/** Set TraceRestrictItem condition operator field */
inline void SetTraceRestrictCondOp(TraceRestrictItem &item, TraceRestrictCondOp condop)
{
SB(item, TRIFA_COND_OP_OFFSET, TRIFA_COND_OP_COUNT, condop);
}
/** Set TraceRestrictItem condition flags field */
inline void SetTraceRestrictCondFlags(TraceRestrictItem &item, TraceRestrictCondFlags condflags)
{
SB(item, TRIFA_COND_FLAGS_OFFSET, TRIFA_COND_FLAGS_COUNT, condflags);
}
/** Set TraceRestrictItem auxiliary field */
inline void SetTraceRestrictAuxField(TraceRestrictItem &item, uint8_t data)
{
SB(item, TRIFA_AUX_FIELD_OFFSET, TRIFA_AUX_FIELD_COUNT, data);
}
/** Set TraceRestrictItem combined condition operator and auxiliary fields */
inline void SetTraceRestrictCombinedAuxCondOpField(TraceRestrictItem &item, uint8_t data)
{
SB(item, TRIFA_CMB_AUX_COND_OFFSET, TRIFA_CMB_AUX_COND_COUNT, data);
}
/** Set TraceRestrictItem value field */
inline void SetTraceRestrictValue(TraceRestrictItem &item, uint16_t value)
{
SB(item, TRIFA_VALUE_OFFSET, TRIFA_VALUE_COUNT, value);
}
/** Is TraceRestrictItemType a conditional type? */
inline bool IsTraceRestrictTypeConditional(TraceRestrictItemType type)
{
return type >= TRIT_COND_BEGIN && type < TRIT_COND_END;
}
/** Is TraceRestrictItem type field a conditional type? */
inline bool IsTraceRestrictConditional(TraceRestrictItem item)
{
return IsTraceRestrictTypeConditional(GetTraceRestrictType(item));
}
/** Is TraceRestrictItem a double-item type? */
inline bool IsTraceRestrictDoubleItem(TraceRestrictItem item)
{
const TraceRestrictItemType type = GetTraceRestrictType(item);
return type == TRIT_COND_PBS_ENTRY_SIGNAL || type == TRIT_COND_SLOT_OCCUPANCY || type == TRIT_COUNTER ||
type == TRIT_COND_COUNTER_VALUE || type == TRIT_COND_TIME_DATE_VALUE || type == TRIT_COND_RESERVATION_THROUGH;
}
/**
* Categorisation of what is allowed in the TraceRestrictItem condition op field
* see TraceRestrictTypePropertySet
*/
enum TraceRestrictConditionOpType : uint8_t {
TRCOT_NONE = 0, ///< takes no condition op
TRCOT_BINARY = 1, ///< takes "is" and "is not" condition ops
TRCOT_ALL = 2, ///< takes all condition ops (i.e. all relational ops)
};
/**
* Categorisation of what is in the TraceRestrictItem value field
* see TraceRestrictTypePropertySet
*/
enum TraceRestrictValueType : uint8_t {
TRVT_NONE = 0, ///< value field not used (set to 0)
TRVT_SPECIAL = 1, ///< special handling of value field
TRVT_INT = 2, ///< takes an unsigned integer value
TRVT_DENY = 3, ///< takes a value 0 = deny, 1 = allow (cancel previous deny)
TRVT_SPEED = 4, ///< takes an integer speed value
TRVT_ORDER = 5, ///< takes an order target ID, as per the auxiliary field as type: TraceRestrictOrderCondAuxField
TRVT_CARGO_ID = 6, ///< takes a CargoID
TRVT_DIRECTION = 7, ///< takes a TraceRestrictDirectionTypeSpecialValue
TRVT_TILE_INDEX = 8, ///< takes a TileIndex in the next item slot
TRVT_PF_PENALTY = 9, ///< takes a pathfinder penalty value or preset index, as per the auxiliary field as type: TraceRestrictPathfinderPenaltyAuxField
TRVT_RESERVE_THROUGH = 10,///< takes a value 0 = reserve through, 1 = cancel previous reserve through
TRVT_LONG_RESERVE = 11,///< takes a TraceRestrictLongReserveValueField
TRVT_GROUP_INDEX = 12,///< takes a GroupID
TRVT_WEIGHT = 13,///< takes a weight
TRVT_POWER = 14,///< takes a power
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 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_PERCENT = 21,///> takes a unsigned integer percentage value between 0 and 100
TRVT_OWNER = 40,///< takes a CompanyID
TRVT_TRAIN_STATUS = 41,///< takes a TraceRestrictTrainStatusValueField
TRVT_REVERSE = 42,///< takes a TraceRestrictReverseValueField
TRVT_NEWS_CONTROL = 43,///< takes a TraceRestrictNewsControlField
TRVT_COUNTER_INDEX_INT = 44,///< takes a TraceRestrictCounterID, and an integer in the next item slot
TRVT_TIME_DATE_INT = 45,///< takes a TraceRestrictTimeDateValueField, and an integer in the next item slot
TRVT_ENGINE_CLASS = 46,///< takes a EngineClass
TRVT_PF_PENALTY_CONTROL = 47,///< takes a TraceRestrictPfPenaltyControlField
TRVT_SPEED_ADAPTATION_CONTROL = 48,///< takes a TraceRestrictSpeedAdaptationControlField
TRVT_SIGNAL_MODE_CONTROL = 49,///< takes a TraceRestrictSignalModeControlField
TRVT_ORDER_TARGET_DIAGDIR = 50,///< takes a DiagDirection, and the order type in the auxiliary field
TRVT_TILE_INDEX_THROUGH = 51,///< takes a TileIndex in the next item slot (passes through)
};
/**
* Describes formats of TraceRestrictItem condition op and value fields
*/
struct TraceRestrictTypePropertySet {
TraceRestrictConditionOpType cond_type;
TraceRestrictValueType value_type;
};
void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueType value_type);
void SetTraceRestrictTypeAndNormalise(TraceRestrictItem &item, TraceRestrictItemType type, uint8_t aux_data = 0);
/**
* Get TraceRestrictTypePropertySet for a given instruction, only looks at value field
*/
inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceRestrictItem item)
{
TraceRestrictTypePropertySet out;
if (GetTraceRestrictType(item) == TRIT_NULL) {
out.cond_type = TRCOT_NONE;
out.value_type = TRVT_SPECIAL;
} else if (GetTraceRestrictType(item) == TRIT_COND_ENDIF ||
GetTraceRestrictType(item) == TRIT_COND_UNDEFINED) {
out.cond_type = TRCOT_NONE;
out.value_type = TRVT_NONE;
} else if (IsTraceRestrictConditional(item)) {
out.cond_type = TRCOT_ALL;
switch (GetTraceRestrictType(item)) {
case TRIT_COND_TRAIN_LENGTH:
out.value_type = TRVT_INT;
break;
case TRIT_COND_MAX_SPEED:
out.value_type = TRVT_SPEED;
break;
case TRIT_COND_CURRENT_ORDER:
case TRIT_COND_NEXT_ORDER:
case TRIT_COND_LAST_STATION:
out.value_type = TRVT_ORDER;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_CARGO:
out.value_type = TRVT_CARGO_ID;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_ENTRY_DIRECTION:
out.value_type = TRVT_DIRECTION;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_PBS_ENTRY_SIGNAL:
out.value_type = TRVT_TILE_INDEX;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_TRAIN_GROUP:
out.value_type = TRVT_GROUP_INDEX;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_TRAIN_IN_SLOT:
out.value_type = TRVT_SLOT_INDEX;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_SLOT_OCCUPANCY:
out.value_type = TRVT_SLOT_INDEX_INT;
break;
case TRIT_COND_PHYS_PROP:
switch (static_cast<TraceRestrictPhysPropCondAuxField>(GetTraceRestrictAuxField(item))) {
case TRPPCAF_WEIGHT:
out.value_type = TRVT_WEIGHT;
break;
case TRPPCAF_POWER:
out.value_type = TRVT_POWER;
break;
case TRPPCAF_MAX_TE:
out.value_type = TRVT_FORCE;
break;
default:
NOT_REACHED();
break;
}
break;
case TRIT_COND_PHYS_RATIO:
switch (static_cast<TraceRestrictPhysPropRatioCondAuxField>(GetTraceRestrictAuxField(item))) {
case TRPPRCAF_POWER_WEIGHT:
out.value_type = TRVT_POWER_WEIGHT_RATIO;
break;
case TRPPRCAF_MAX_TE_WEIGHT:
out.value_type = TRVT_FORCE_WEIGHT_RATIO;
break;
default:
NOT_REACHED();
break;
}
break;
case TRIT_COND_TRAIN_OWNER:
out.value_type = TRVT_OWNER;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_TRAIN_STATUS:
out.value_type = TRVT_TRAIN_STATUS;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_LOAD_PERCENT:
out.value_type = TRVT_PERCENT;
break;
case TRIT_COND_COUNTER_VALUE:
out.value_type = TRVT_COUNTER_INDEX_INT;
break;
case TRIT_COND_TIME_DATE_VALUE:
out.value_type = TRVT_TIME_DATE_INT;
break;
case TRIT_COND_RESERVED_TILES:
out.value_type = TRVT_INT;
break;
case TRIT_COND_CATEGORY:
switch (static_cast<TraceRestrictCatgeoryCondAuxField>(GetTraceRestrictAuxField(item))) {
case TRCCAF_ENGINE_CLASS:
out.value_type = TRVT_ENGINE_CLASS;
break;
default:
NOT_REACHED();
break;
}
break;
case TRIT_COND_TARGET_DIRECTION:
out.value_type = TRVT_ORDER_TARGET_DIAGDIR;
out.cond_type = TRCOT_BINARY;
break;
case TRIT_COND_RESERVATION_THROUGH:
out.value_type = TRVT_TILE_INDEX_THROUGH;
out.cond_type = TRCOT_BINARY;
break;
default:
NOT_REACHED();
break;
}
} else {
out.cond_type = TRCOT_NONE;
switch (GetTraceRestrictType(item)) {
case TRIT_PF_PENALTY:
out.value_type = TRVT_PF_PENALTY;
break;
case TRIT_PF_DENY:
out.value_type = TRVT_DENY;
break;
case TRIT_RESERVE_THROUGH:
out.value_type = TRVT_RESERVE_THROUGH;
break;
case TRIT_LONG_RESERVE:
out.value_type = TRVT_LONG_RESERVE;
break;
case TRIT_WAIT_AT_PBS:
out.value_type = TRVT_WAIT_AT_PBS;
break;
case TRIT_SLOT:
out.value_type = TRVT_SLOT_INDEX;
break;
case TRIT_REVERSE:
out.value_type = TRVT_REVERSE;
break;
case TRIT_SPEED_RESTRICTION:
out.value_type = TRVT_SPEED;
break;
case TRIT_NEWS_CONTROL:
out.value_type = TRVT_NEWS_CONTROL;
break;
case TRIT_COUNTER:
out.value_type = TRVT_COUNTER_INDEX_INT;
break;
case TRIT_PF_PENALTY_CONTROL:
out.value_type = TRVT_PF_PENALTY_CONTROL;
break;
case TRIT_SPEED_ADAPTATION_CONTROL:
out.value_type = TRVT_SPEED_ADAPTATION_CONTROL;
break;
case TRIT_SIGNAL_MODE_CONTROL:
out.value_type = TRVT_SIGNAL_MODE_CONTROL;
break;
default:
out.value_type = TRVT_NONE;
break;
}
}
return out;
}
/** Is the aux field for this TraceRestrictItemType used as a subtype which changes the type of the value field? */
inline bool IsTraceRestrictTypeAuxSubtype(TraceRestrictItemType type)
{
switch (type) {
case TRIT_COND_PHYS_PROP:
case TRIT_COND_PHYS_RATIO:
case TRIT_COND_SLOT_OCCUPANCY:
case TRIT_COND_PBS_ENTRY_SIGNAL:
case TRIT_COND_CATEGORY:
return true;
default:
return false;
}
}
/** May this TraceRestrictItemType take a slot of a different (non-train) vehicle type */
inline bool IsTraceRestrictTypeNonMatchingVehicleTypeSlot(TraceRestrictItemType type)
{
switch (type) {
case TRIT_COND_SLOT_OCCUPANCY:
return true;
default:
return false;
}
}
/** Get mapping ref ID from tile and track */
inline TraceRestrictRefId MakeTraceRestrictRefId(TileIndex t, Track track)
{
return (t << 3) | track;
}
/** Get tile from mapping ref ID */
inline TileIndex GetTraceRestrictRefIdTileIndex(TraceRestrictRefId ref)
{
return static_cast<TileIndex>(ref >> 3);
}
/** Get track from mapping ref ID */
inline Track GetTraceRestrictRefIdTrack(TraceRestrictRefId ref)
{
return static_cast<Track>(ref & 7);
}
void TraceRestrictSetIsSignalRestrictedBit(TileIndex t);
void TraceRestrictCreateProgramMapping(TraceRestrictRefId ref, TraceRestrictProgram *prog);
bool TraceRestrictRemoveProgramMapping(TraceRestrictRefId ref);
TraceRestrictProgram *GetTraceRestrictProgram(TraceRestrictRefId ref, bool create_new);
void TraceRestrictNotifySignalRemoval(TileIndex tile, Track track);
inline bool IsRestrictedSignalTile(TileIndex t)
{
switch (GetTileType(t)) {
case MP_RAILWAY:
return IsRestrictedSignal(t);
case MP_TUNNELBRIDGE:
return IsTunnelBridgeRestrictedSignal(t);
default:
return false;
}
}
/**
* Gets the existing signal program for the tile identified by @p t and @p track, or nullptr
*/
inline const TraceRestrictProgram *GetExistingTraceRestrictProgram(TileIndex t, Track track)
{
if (IsRestrictedSignalTile(t)) {
return GetTraceRestrictProgram(MakeTraceRestrictRefId(t, track), false);
} else {
return nullptr;
}
}
/**
* Enumeration for command action type field, indicates what command to do
*/
enum TraceRestrictDoCommandType : uint8_t {
TRDCT_INSERT_ITEM, ///< insert new instruction before offset field as given value
TRDCT_MODIFY_ITEM, ///< modify instruction at offset field to given value
TRDCT_MODIFY_DUAL_ITEM, ///< modify second item of dual-part instruction at offset field to given value
TRDCT_REMOVE_ITEM, ///< remove instruction at offset field
TRDCT_SHALLOW_REMOVE_ITEM, ///< shallow remove instruction at offset field, does not delete contents of block
TRDCT_MOVE_ITEM, ///< move instruction or block at offset field
TRDCT_DUPLICATE_ITEM, ///< duplicate instruction/block at offset field
TRDCT_PROG_COPY, ///< copy program operation. Do not re-order this with respect to other values
TRDCT_PROG_COPY_APPEND, ///< copy and append program operation
TRDCT_PROG_SHARE, ///< share program operation
TRDCT_PROG_SHARE_IF_UNMAPPED, ///< share program operation (if unmapped)
TRDCT_PROG_UNSHARE, ///< unshare program (copy as a new program)
TRDCT_PROG_RESET, ///< reset program state of signal
};
void TraceRestrictDoCommandP(TileIndex tile, Track track, TraceRestrictDoCommandType type, uint32_t offset, uint32_t value, StringID error_msg);
void TraceRestrictProgMgmtWithSourceDoCommandP(TileIndex tile, Track track, TraceRestrictDoCommandType type,
TileIndex source_tile, Track source_track, StringID error_msg);
/**
* Short-hand to call TraceRestrictProgMgmtWithSourceDoCommandP with 0 for source tile/track
*/
inline void TraceRestrictProgMgmtDoCommandP(TileIndex tile, Track track, TraceRestrictDoCommandType type, StringID error_msg)
{
TraceRestrictProgMgmtWithSourceDoCommandP(tile, track, type, static_cast<TileIndex>(0), static_cast<Track>(0), error_msg);
}
CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, uint32_t p1, uint32_t p2, const char *text);
CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag flags, uint32_t p1, uint32_t p2, const char *text);
CommandCost TraceRestrictProgramRemoveItemAt(std::vector<TraceRestrictItem> &items, uint32_t offset, bool shallow_mode);
CommandCost TraceRestrictProgramMoveItemAt(std::vector<TraceRestrictItem> &items, uint32_t &offset, bool up, bool shallow_mode);
CommandCost TraceRestrictProgramDuplicateItemAt(std::vector<TraceRestrictItem> &items, uint32_t offset);
bool TraceRestrictProgramDuplicateItemAtDryRun(const std::vector<TraceRestrictItem> &items, uint32_t offset);
void ShowTraceRestrictProgramWindow(TileIndex tile, Track track);
int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type);
int GetTraceRestrictTimeDateValueFromStateTicks(TraceRestrictTimeDateValueField type, StateTicks state_ticks);
void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint16_t index);
void TraceRestrictRemoveGroupID(GroupID index);
void TraceRestrictUpdateCompanyID(CompanyID old_company, CompanyID new_company);
void TraceRestrictRemoveSlotID(TraceRestrictSlotID index);
void TraceRestrictRemoveCounterID(TraceRestrictCounterID index);
void TraceRestrictRemoveVehicleFromAllSlots(VehicleID id);
void TraceRestrictTransferVehicleOccupantInAllSlots(VehicleID from, VehicleID to);
void TraceRestrictGetVehicleSlots(VehicleID id, std::vector<TraceRestrictSlotID> &out);
static const uint MAX_LENGTH_TRACE_RESTRICT_SLOT_NAME_CHARS = 128; ///< The maximum length of a slot name in characters including '\0'
/**
* Slot type, used for slot operations
*/
struct TraceRestrictSlot : TraceRestrictSlotPool::PoolItem<&_tracerestrictslot_pool> {
friend TraceRestrictSlotTemporaryState;
Owner owner;
VehicleType vehicle_type;
uint32_t max_occupancy = 1;
std::string name;
std::vector<VehicleID> occupants;
std::vector<SignalReference> progsig_dependants;
static void RebuildVehicleIndex();
static bool ValidateVehicleIndex();
static void ValidateSlotOccupants(std::function<void(const char *)> log);
static void PreCleanPool();
TraceRestrictSlot(CompanyID owner = INVALID_COMPANY, VehicleType type = VEH_TRAIN)
{
this->owner = owner;
this->vehicle_type = type;
}
~TraceRestrictSlot()
{
if (!CleaningPool()) this->Clear();
}
/** Test whether vehicle ID is already an occupant */
bool IsOccupant(VehicleID id) const {
for (size_t i = 0; i < occupants.size(); i++) {
if (occupants[i] == id) return true;
}
return false;
}
bool Occupy(const Vehicle *v, bool force = false);
bool OccupyDryRun(VehicleID ids);
bool OccupyUsingTemporaryState(VehicleID id, TraceRestrictSlotTemporaryState *state);
void Vacate(const Vehicle *v);
void VacateUsingTemporaryState(VehicleID id, TraceRestrictSlotTemporaryState *state);
void Clear();
void UpdateSignals();
private:
void AddIndex(const Vehicle *v);
void DeIndex(VehicleID id, const Vehicle *v);
};
/**
* Counter type
*/
struct TraceRestrictCounter : TraceRestrictCounterPool::PoolItem<&_tracerestrictcounter_pool> {
Owner owner;
int32_t value = 0;
std::string name;
std::vector<SignalReference> progsig_dependants;
TraceRestrictCounter(CompanyID owner = INVALID_COMPANY)
{
this->owner = owner;
}
void UpdateValue(int32_t new_value);
static int32_t ApplyValue(int32_t current, TraceRestrictCounterCondOpField op, int32_t value);
void ApplyUpdate(TraceRestrictCounterCondOpField op, int32_t value)
{
this->UpdateValue(TraceRestrictCounter::ApplyValue(this->value, op, value));
}
};
#endif /* TRACERESTRICT_H */