2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
8 /** @file vehiclelist.cpp Lists of vehicles. */
12 #include "vehicle_func.h"
13 #include "vehiclelist.h"
14 #include "vehiclelist_func.h"
17 #include "safeguards.h"
20 * Pack a VehicleListIdentifier in a single uint32.
21 * @return The packed identifier.
23 uint32_t VehicleListIdentifier::Pack() const
25 uint8_t c
= this->company
== OWNER_NONE
? 0xF : (uint8_t)this->company
;
27 assert(this->vtype
< (1 << 2));
28 assert(this->index
< (1 << 20));
29 assert(this->type
< VLT_END
);
30 static_assert(VLT_END
<= (1 << 3));
32 return c
<< 28 | this->type
<< 23 | this->vtype
<< 26 | this->index
;
36 * Unpack a VehicleListIdentifier from a single uint32.
37 * @param data The data to unpack.
38 * @return true iff the data was valid (enough).
40 bool VehicleListIdentifier::UnpackIfValid(uint32_t data
)
42 uint8_t c
= GB(data
, 28, 4);
43 this->company
= c
== 0xF ? OWNER_NONE
: (CompanyID
)c
;
44 this->type
= (VehicleListType
)GB(data
, 23, 3);
45 this->vtype
= (VehicleType
)GB(data
, 26, 2);
46 this->index
= GB(data
, 0, 20);
48 return this->type
< VLT_END
;
52 * Decode a packed vehicle list identifier into a new one.
53 * @param data The data to unpack.
55 /* static */ VehicleListIdentifier
VehicleListIdentifier::UnPack(uint32_t data
)
57 VehicleListIdentifier result
;
58 [[maybe_unused
]] bool ret
= result
.UnpackIfValid(data
);
63 /** Data for building a depot vehicle list. */
64 struct BuildDepotVehicleListData
66 VehicleList
*engines
; ///< Pointer to list to add vehicles to.
67 VehicleList
*wagons
; ///< Pointer to list to add wagons to (can be nullptr).
68 VehicleType type
; ///< Type of vehicle.
69 bool 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.
73 * Add vehicles to a depot vehicle list.
74 * @param v The found vehicle.
75 * @param data The depot vehicle list data.
76 * @return Always nullptr.
78 static Vehicle
*BuildDepotVehicleListProc(Vehicle
*v
, void *data
)
80 auto bdvld
= static_cast<BuildDepotVehicleListData
*>(data
);
81 if (v
->type
!= bdvld
->type
|| !v
->IsInDepot()) return nullptr;
83 if (bdvld
->type
== VEH_TRAIN
) {
84 const Train
*t
= Train::From(v
);
85 if (t
->IsArticulatedPart() || t
->IsRearDualheaded()) return nullptr;
86 if (bdvld
->wagons
!= nullptr && t
->First()->IsFreeWagon()) {
87 if (bdvld
->individual_wagons
|| t
->IsFreeWagon()) bdvld
->wagons
->push_back(t
);
92 if (v
->IsPrimaryVehicle()) bdvld
->engines
->push_back(v
);
97 * Generate a list of vehicles inside a depot.
98 * @param type Type of vehicle
99 * @param tile The tile the depot is located on
100 * @param engines Pointer to list to add vehicles to
101 * @param wagons Pointer to list to add wagons to (can be nullptr)
102 * @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.
104 void BuildDepotVehicleList(VehicleType type
, TileIndex tile
, VehicleList
*engines
, VehicleList
*wagons
, bool individual_wagons
)
107 if (wagons
!= nullptr && wagons
!= engines
) wagons
->clear();
109 BuildDepotVehicleListData bdvld
{engines
, wagons
, type
, individual_wagons
};
110 FindVehicleOnPos(tile
, &bdvld
, BuildDepotVehicleListProc
);
114 * Generate a list of vehicles based on window type.
115 * @param list Pointer to list to add vehicles to
116 * @param vli The identifier of this vehicle list.
117 * @return false if invalid list is requested
119 bool GenerateVehicleSortList(VehicleList
*list
, const VehicleListIdentifier
&vli
)
124 case VL_STATION_LIST
:
125 FindVehiclesWithOrder(
126 [&vli
](const Vehicle
*v
) { return v
->type
== vli
.vtype
; },
127 [&vli
](const Order
*order
) { return (order
->IsType(OT_GOTO_STATION
) || order
->IsType(OT_GOTO_WAYPOINT
) || order
->IsType(OT_IMPLICIT
)) && order
->GetDestination() == vli
.index
; },
128 [&list
](const Vehicle
*v
) { list
->push_back(v
); }
132 case VL_SHARED_ORDERS
: {
133 /* Add all vehicles from this vehicle's shared order list */
134 const Vehicle
*v
= Vehicle::GetIfValid(vli
.index
);
135 if (v
== nullptr || v
->type
!= vli
.vtype
|| !v
->IsPrimaryVehicle()) return false;
137 for (; v
!= nullptr; v
= v
->NextShared()) {
144 if (vli
.index
!= ALL_GROUP
) {
145 for (const Vehicle
*v
: Vehicle::Iterate()) {
146 if (v
->type
== vli
.vtype
&& v
->IsPrimaryVehicle() &&
147 v
->owner
== vli
.company
&& GroupIsInGroup(v
->group_id
, vli
.index
)) {
156 for (const Vehicle
*v
: Vehicle::Iterate()) {
157 if (v
->type
== vli
.vtype
&& v
->owner
== vli
.company
&& v
->IsPrimaryVehicle()) {
164 FindVehiclesWithOrder(
165 [&vli
](const Vehicle
*v
) { return v
->type
== vli
.vtype
; },
166 [&vli
](const Order
*order
) { return order
->IsType(OT_GOTO_DEPOT
) && !(order
->GetDepotActionType() & ODATFB_NEAREST_DEPOT
) && order
->GetDestination() == vli
.index
; },
167 [&list
](const Vehicle
*v
) { list
->push_back(v
); }
171 default: return false;