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 newgrf_class_func.h Implementation of the NewGRF class' functions. */
10 #include "newgrf_class.h"
12 #include "table/strings.h"
14 /** Reset the classes, i.e. clear everything. */
15 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
16 void NewGRFClass
<Tspec
, Tindex
, Tmax
>::Reset()
18 NewGRFClass::classes
.clear();
19 NewGRFClass::classes
.shrink_to_fit();
21 NewGRFClass::InsertDefaults();
25 * Allocate a class with a given global class ID.
26 * @param global_id The global class id, such as 'DFLT'.
27 * @return The (non global!) class ID for the class.
28 * @note Upon allocating the same global class ID for a
29 * second time, this first allocation will be given.
31 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
32 Tindex NewGRFClass
<Tspec
, Tindex
, Tmax
>::Allocate(uint32_t global_id
)
34 auto found
= std::find_if(std::begin(NewGRFClass::classes
), std::end(NewGRFClass::classes
), [global_id
](const auto &cls
) { return cls
.global_id
== global_id
; });
36 /* Id is already allocated, so reuse it. */
37 if (found
!= std::end(NewGRFClass::classes
)) return found
->Index();
39 /* More slots available, allocate a slot to the global id. */
40 if (NewGRFClass::classes
.size() < Tmax
) {
41 auto it
= NewGRFClass::classes
.emplace(std::end(NewGRFClass::classes
), global_id
, STR_EMPTY
);
42 it
->index
= static_cast<Tindex
>(std::distance(std::begin(NewGRFClass::classes
), it
));
46 GrfMsg(2, "ClassAllocate: already allocated {} classes, using default", Tmax
);
47 return static_cast<Tindex
>(0);
51 * Insert a spec into the class, and update its index.
52 * @param spec The spec to insert.
54 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
55 void NewGRFClass
<Tspec
, Tindex
, Tmax
>::Insert(Tspec
*spec
)
57 auto it
= this->spec
.insert(std::end(this->spec
), spec
);
58 uint16_t index
= static_cast<uint16_t>(std::distance(std::begin(this->spec
), it
));
59 if (spec
!= nullptr) (*it
)->index
= index
;
61 if (this->IsUIAvailable(index
)) this->ui_count
++;
65 * Assign a spec to one of the classes.
66 * @param spec The spec to assign.
67 * @note The spec must have a valid class index set.
69 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
70 void NewGRFClass
<Tspec
, Tindex
, Tmax
>::Assign(Tspec
*spec
)
72 assert(static_cast<size_t>(spec
->class_index
) < NewGRFClass::classes
.size());
73 Get(spec
->class_index
)->Insert(spec
);
77 * Get a particular class.
78 * @param class_index The index of the class.
79 * @pre class_index < Tmax
81 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
82 NewGRFClass
<Tspec
, Tindex
, Tmax
> *NewGRFClass
<Tspec
, Tindex
, Tmax
>::Get(Tindex class_index
)
84 assert(static_cast<size_t>(class_index
) < NewGRFClass::classes
.size());
85 return &NewGRFClass::classes
[class_index
];
89 * Get the number of allocated classes.
90 * @return The number of classes.
92 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
93 uint NewGRFClass
<Tspec
, Tindex
, Tmax
>::GetClassCount()
95 return static_cast<uint
>(NewGRFClass::classes
.size());
99 * Get the number of classes available to the user.
100 * @return The number of classes.
102 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
103 uint NewGRFClass
<Tspec
, Tindex
, Tmax
>::GetUIClassCount()
105 return std::count_if(std::begin(NewGRFClass::classes
), std::end(NewGRFClass::classes
), [](const auto &cls
) { return cls
.GetUISpecCount() > 0; });
109 * Get a spec from the class at a given index.
110 * @param index The index where to find the spec.
111 * @return The spec at given location.
113 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
114 const Tspec
*NewGRFClass
<Tspec
, Tindex
, Tmax
>::GetSpec(uint index
) const
116 /* If the custom spec isn't defined any more, then the GRF file probably was not loaded. */
117 return index
< this->GetSpecCount() ? this->spec
[index
] : nullptr;
121 * Retrieve a spec by GRF location.
122 * @param grfid GRF ID of spec.
123 * @param local_id Index within GRF file of spec.
124 * @param index Pointer to return the index of the spec in its class. If nullptr then not used.
127 template <typename Tspec
, typename Tindex
, Tindex Tmax
>
128 const Tspec
*NewGRFClass
<Tspec
, Tindex
, Tmax
>::GetByGrf(uint32_t grfid
, uint16_t local_id
)
130 for (const auto &cls
: NewGRFClass::classes
) {
131 for (const auto &spec
: cls
.spec
) {
132 if (spec
== nullptr) continue;
133 if (spec
->grf_prop
.local_id
!= local_id
) continue;
134 if ((spec
->grf_prop
.grffile
== nullptr ? 0 : spec
->grf_prop
.grffile
->grfid
) == grfid
) return spec
;