/* * 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 . */ /** @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 #include 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 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 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 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 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 veh_temporarily_added; std::vector veh_temporarily_removed; private: bool is_active = false; static std::vector 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(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 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(this)->GetRefIdsPtr(); } void IncrementRefCount(TraceRestrictRefId ref_id); void DecrementRefCount(TraceRestrictRefId ref_id); static CommandCost Validate(const std::vector &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags); static size_t InstructionOffsetToArrayOffset(const std::vector &items, size_t offset); static size_t ArrayOffsetToInstructionOffset(const std::vector &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 &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::iterator InstructionAt(std::vector &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::const_iterator InstructionAt(const std::vector &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(GB(item, TRIFA_TYPE_OFFSET, TRIFA_TYPE_COUNT)); } /** Get TraceRestrictItem condition flags field */ inline TraceRestrictCondFlags GetTraceRestrictCondFlags(TraceRestrictItem item) { return static_cast(GB(item, TRIFA_COND_FLAGS_OFFSET, TRIFA_COND_FLAGS_COUNT)); } /** Get TraceRestrictItem condition operator field */ inline TraceRestrictCondOp GetTraceRestrictCondOp(TraceRestrictItem item) { return static_cast(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(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(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(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(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(ref >> 3); } /** Get track from mapping ref ID */ inline Track GetTraceRestrictRefIdTrack(TraceRestrictRefId ref) { return static_cast(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(0), static_cast(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 &items, uint32_t offset, bool shallow_mode); CommandCost TraceRestrictProgramMoveItemAt(std::vector &items, uint32_t &offset, bool up, bool shallow_mode); CommandCost TraceRestrictProgramDuplicateItemAt(std::vector &items, uint32_t offset); bool TraceRestrictProgramDuplicateItemAtDryRun(const std::vector &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 &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 occupants; std::vector progsig_dependants; static void RebuildVehicleIndex(); static bool ValidateVehicleIndex(); static void ValidateSlotOccupants(std::function 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 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 */