4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file vehiclelist.cpp Lists of vehicles. */
14 #include "vehiclelist.h"
16 #include "tracerestrict.h"
18 #include "safeguards.h"
21 * Pack a VehicleListIdentifier in a single uint32.
22 * @return The packed identifier.
24 uint32
VehicleListIdentifier::Pack() const
26 byte c
= this->company
== OWNER_NONE
? 0xF : (byte
)this->company
;
28 assert(this->vtype
< (1 << 2));
29 assert(this->index
< (1 << 20));
30 assert(this->type
< VLT_END
);
31 assert_compile(VLT_END
<= (1 << 3));
33 return c
<< 28 | this->type
<< 23 | this->vtype
<< 26 | this->index
;
37 * Unpack a VehicleListIdentifier from a single uint32.
38 * @param data The data to unpack.
39 * @return true iff the data was valid (enough).
41 bool VehicleListIdentifier::UnpackIfValid(uint32 data
)
43 byte c
= GB(data
, 28, 4);
44 this->company
= c
== 0xF ? OWNER_NONE
: (CompanyID
)c
;
45 this->type
= (VehicleListType
)GB(data
, 23, 3);
46 this->vtype
= (VehicleType
)GB(data
, 26, 2);
47 this->index
= GB(data
, 0, 20);
49 return this->type
< VLT_END
;
53 * Decode a packed vehicle list identifier into a new one.
54 * @param data The data to unpack.
56 /* static */ VehicleListIdentifier
VehicleListIdentifier::UnPack(uint32 data
)
58 VehicleListIdentifier result
;
59 bool ret
= result
.UnpackIfValid(data
);
65 * Generate a list of vehicles inside a depot.
66 * @param type Type of vehicle
67 * @param tile The tile the depot is located on
68 * @param engines Pointer to list to add vehicles to
69 * @param wagons Pointer to list to add wagons to (can be nullptr)
70 * @param individual_wagons If true add every wagon to \a wagons which is not attached to an engine. If false only add the first wagon of every row.
72 void BuildDepotVehicleList(VehicleType type
, TileIndex tile
, VehicleList
*engines
, VehicleList
*wagons
, bool individual_wagons
)
75 if (wagons
!= nullptr && wagons
!= engines
) wagons
->Clear();
79 /* General tests for all vehicle types */
80 if (v
->type
!= type
) continue;
81 if (v
->tile
!= tile
) continue;
85 const Train
*t
= Train::From(v
);
86 if (t
->IsArticulatedPart() || t
->IsRearDualheaded()) continue;
87 if (t
->track
!= TRACK_BIT_DEPOT
) continue;
88 if (wagons
!= nullptr && t
->First()->IsFreeWagon()) {
89 if (individual_wagons
|| t
->IsFreeWagon()) *wagons
->Append() = t
;
96 if (!v
->IsInDepot()) continue;
100 if (!v
->IsPrimaryVehicle()) continue;
102 *engines
->Append() = v
;
105 /* Ensure the lists are not wasting too much space. If the lists are fresh
106 * (i.e. built within a command) then this will actually do nothing. */
108 if (wagons
!= nullptr && wagons
!= engines
) wagons
->Compact();
112 * Generate a list of vehicles based on window type.
113 * @param list Pointer to list to add vehicles to
114 * @param vli The identifier of this vehicle list.
115 * @return false if invalid list is requested
117 bool GenerateVehicleSortList(VehicleList
*list
, const VehicleListIdentifier
&vli
)
123 auto fill_all_vehicles
= [&]() {
124 FOR_ALL_VEHICLES(v
) {
125 if (!HasBit(v
->subtype
, GVSF_VIRTUAL
) && v
->type
== vli
.vtype
&& v
->owner
== vli
.company
&& v
->IsPrimaryVehicle()) {
132 case VL_STATION_LIST
:
133 FOR_ALL_VEHICLES(v
) {
134 if (v
->type
== vli
.vtype
&& v
->IsPrimaryVehicle()) {
137 FOR_VEHICLE_ORDERS(v
, order
) {
138 if ((order
->IsType(OT_GOTO_STATION
) || order
->IsType(OT_GOTO_WAYPOINT
) || order
->IsType(OT_IMPLICIT
))
139 && order
->GetDestination() == vli
.index
) {
148 case VL_SHARED_ORDERS
:
149 /* Add all vehicles from this vehicle's shared order list */
150 v
= Vehicle::GetIfValid(vli
.index
);
151 if (v
== nullptr || v
->type
!= vli
.vtype
|| !v
->IsPrimaryVehicle()) return false;
153 for (; v
!= nullptr; v
= v
->NextShared()) {
159 if (vli
.index
!= ALL_GROUP
) {
160 FOR_ALL_VEHICLES(v
) {
161 if (!HasBit(v
->subtype
, GVSF_VIRTUAL
) && v
->type
== vli
.vtype
&& v
->IsPrimaryVehicle() &&
162 v
->owner
== vli
.company
&& GroupIsInGroup(v
->group_id
, vli
.index
)) {
176 FOR_ALL_VEHICLES(v
) {
177 if (v
->type
== vli
.vtype
&& v
->IsPrimaryVehicle()) {
180 FOR_VEHICLE_ORDERS(v
, order
) {
181 if (order
->IsType(OT_GOTO_DEPOT
) && !(order
->GetDepotActionType() & ODATFB_NEAREST_DEPOT
) && order
->GetDestination() == vli
.index
) {
191 if (vli
.index
== ALL_TRAINS_TRACE_RESTRICT_SLOT_ID
) {
194 const TraceRestrictSlot
*slot
= TraceRestrictSlot::GetIfValid(vli
.index
);
195 if (slot
== nullptr) return false;
196 for (VehicleID id
: slot
->occupants
) {
197 *list
->Append() = Vehicle::Get(id
);
203 default: return false;