Update: Translations from eints
[openttd-github.git] / src / saveload / industry_sl.cpp
blob6edea24e05d260ca37c68e4defa0c79138f12e17
1 /*
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/>.
6 */
8 /** @file industry_sl.cpp Code handling saving and loading of industries */
10 #include "../stdafx.h"
12 #include "saveload.h"
13 #include "compat/industry_sl_compat.h"
15 #include "../industry.h"
16 #include "newgrf_sl.h"
18 #include "../safeguards.h"
20 static OldPersistentStorage _old_ind_persistent_storage;
22 class SlIndustryAccepted : public DefaultSaveLoadHandler<SlIndustryAccepted, Industry> {
23 public:
24 inline static const SaveLoad description[] = {
25 SLE_VAR(Industry::AcceptedCargo, cargo, SLE_UINT8),
26 SLE_VAR(Industry::AcceptedCargo, waiting, SLE_UINT16),
27 SLE_VAR(Industry::AcceptedCargo, last_accepted, SLE_INT32),
29 inline const static SaveLoadCompatTable compat_description = _industry_accepts_sl_compat;
31 void Save(Industry *i) const override
33 SlSetStructListLength(i->accepted.size());
35 for (auto &a : i->accepted) {
36 SlObject(&a, this->GetDescription());
40 void Load(Industry *i) const override
42 size_t len = SlGetStructListLength(INDUSTRY_NUM_INPUTS);
44 i->accepted.reserve(len);
45 for (size_t index = 0; index < len; ++index) {
46 auto &a = i->accepted.emplace_back();
47 SlObject(&a, this->GetLoadDescription());
51 /* Old array structure used for savegames before SLV_INDUSTRY_CARGO_REORGANISE. */
52 static inline std::array<CargoID, INDUSTRY_NUM_INPUTS> old_cargo;
53 static inline std::array<uint16_t, INDUSTRY_NUM_INPUTS> old_waiting;
54 static inline std::array<TimerGameEconomy::Date, INDUSTRY_NUM_INPUTS> old_last_accepted;
56 static void ResetOldStructure()
58 SlIndustryAccepted::old_cargo.fill(INVALID_CARGO);
59 SlIndustryAccepted::old_waiting.fill(0);
60 SlIndustryAccepted::old_last_accepted.fill(0);
64 class SlIndustryProducedHistory : public DefaultSaveLoadHandler<SlIndustryProducedHistory, Industry::ProducedCargo> {
65 public:
66 inline static const SaveLoad description[] = {
67 SLE_VAR(Industry::ProducedHistory, production, SLE_UINT16),
68 SLE_VAR(Industry::ProducedHistory, transported, SLE_UINT16),
70 inline const static SaveLoadCompatTable compat_description = _industry_produced_history_sl_compat;
72 void Save(Industry::ProducedCargo *p) const override
74 if (!IsValidCargoID(p->cargo)) {
75 /* Don't save any history if cargo slot isn't used. */
76 SlSetStructListLength(0);
77 return;
80 SlSetStructListLength(p->history.size());
82 for (auto &h : p->history) {
83 SlObject(&h, this->GetDescription());
87 void Load(Industry::ProducedCargo *p) const override
89 size_t len = SlGetStructListLength(p->history.size());
91 for (auto &h : p->history) {
92 if (--len > p->history.size()) break; // unsigned so wraps after hitting zero.
93 SlObject(&h, this->GetDescription());
98 class SlIndustryProduced : public DefaultSaveLoadHandler<SlIndustryProduced, Industry> {
99 public:
100 inline static const SaveLoad description[] = {
101 SLE_VAR(Industry::ProducedCargo, cargo, SLE_UINT8),
102 SLE_VAR(Industry::ProducedCargo, waiting, SLE_UINT16),
103 SLE_VAR(Industry::ProducedCargo, rate, SLE_UINT8),
104 SLEG_STRUCTLIST("history", SlIndustryProducedHistory),
106 inline const static SaveLoadCompatTable compat_description = _industry_produced_sl_compat;
108 void Save(Industry *i) const override
110 SlSetStructListLength(i->produced.size());
112 for (auto &p : i->produced) {
113 SlObject(&p, this->GetDescription());
117 void Load(Industry *i) const override
119 size_t len = SlGetStructListLength(INDUSTRY_NUM_OUTPUTS);
121 i->produced.reserve(len);
122 for (size_t index = 0; index < len; ++index) {
123 auto &p = i->produced.emplace_back();
124 SlObject(&p, this->GetLoadDescription());
128 /* Old array structure used for savegames before SLV_INDUSTRY_CARGO_REORGANISE. */
129 static inline std::array<CargoID, INDUSTRY_NUM_OUTPUTS> old_cargo;
130 static inline std::array<uint16_t, INDUSTRY_NUM_OUTPUTS> old_waiting;
131 static inline std::array<uint8_t, INDUSTRY_NUM_OUTPUTS> old_rate;
132 static inline std::array<uint16_t, INDUSTRY_NUM_OUTPUTS> old_this_month_production;
133 static inline std::array<uint16_t, INDUSTRY_NUM_OUTPUTS> old_this_month_transported;
134 static inline std::array<uint16_t, INDUSTRY_NUM_OUTPUTS> old_last_month_production;
135 static inline std::array<uint16_t, INDUSTRY_NUM_OUTPUTS> old_last_month_transported;
137 static void ResetOldStructure()
139 SlIndustryProduced::old_cargo.fill(INVALID_CARGO);
140 SlIndustryProduced::old_waiting.fill(0);
141 SlIndustryProduced::old_rate.fill(0);
142 SlIndustryProduced::old_this_month_production.fill(0);
143 SlIndustryProduced::old_this_month_transported.fill(0);
144 SlIndustryProduced::old_last_month_production.fill(0);
145 SlIndustryProduced::old_this_month_production.fill(0);
149 static const SaveLoad _industry_desc[] = {
150 SLE_CONDVAR(Industry, location.tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
151 SLE_CONDVAR(Industry, location.tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
152 SLE_VAR(Industry, location.w, SLE_FILE_U8 | SLE_VAR_U16),
153 SLE_VAR(Industry, location.h, SLE_FILE_U8 | SLE_VAR_U16),
154 SLE_REF(Industry, town, REF_TOWN),
155 SLE_CONDREF(Industry, neutral_station, REF_STATION, SLV_SERVE_NEUTRAL_INDUSTRIES, SL_MAX_VERSION),
156 SLEG_CONDARR("produced_cargo", SlIndustryProduced::old_cargo, SLE_UINT8, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
157 SLEG_CONDARR("produced_cargo", SlIndustryProduced::old_cargo, SLE_UINT8, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
158 SLEG_CONDARR("incoming_cargo_waiting", SlIndustryAccepted::old_waiting, SLE_UINT16, INDUSTRY_ORIGINAL_NUM_INPUTS, SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
159 SLEG_CONDARR("incoming_cargo_waiting", SlIndustryAccepted::old_waiting, SLE_UINT16, INDUSTRY_NUM_INPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
160 SLEG_CONDARR("produced_cargo_waiting", SlIndustryProduced::old_waiting, SLE_UINT16, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
161 SLEG_CONDARR("produced_cargo_waiting", SlIndustryProduced::old_waiting, SLE_UINT16, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
162 SLEG_CONDARR("production_rate", SlIndustryProduced::old_rate, SLE_UINT8, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
163 SLEG_CONDARR("production_rate", SlIndustryProduced::old_rate, SLE_UINT8, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
164 SLEG_CONDARR("accepts_cargo", SlIndustryAccepted::old_cargo, SLE_UINT8, INDUSTRY_ORIGINAL_NUM_INPUTS, SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
165 SLEG_CONDARR("accepts_cargo", SlIndustryAccepted::old_cargo, SLE_UINT8, INDUSTRY_NUM_INPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
166 SLE_VAR(Industry, prod_level, SLE_UINT8),
167 SLEG_CONDARR("this_month_production", SlIndustryProduced::old_this_month_production, SLE_UINT16, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
168 SLEG_CONDARR("this_month_production", SlIndustryProduced::old_this_month_production, SLE_UINT16, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
169 SLEG_CONDARR("this_month_transported", SlIndustryProduced::old_this_month_transported, SLE_UINT16, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
170 SLEG_CONDARR("this_month_transported", SlIndustryProduced::old_this_month_transported, SLE_UINT16, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
171 SLEG_CONDARR("last_month_production", SlIndustryProduced::old_last_month_production, SLE_UINT16, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
172 SLEG_CONDARR("last_month_production", SlIndustryProduced::old_last_month_production, SLE_UINT16, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
173 SLEG_CONDARR("last_month_transported", SlIndustryProduced::old_last_month_transported, SLE_UINT16, INDUSTRY_ORIGINAL_NUM_OUTPUTS, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
174 SLEG_CONDARR("last_month_transported", SlIndustryProduced::old_last_month_transported, SLE_UINT16, INDUSTRY_NUM_OUTPUTS, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
176 SLE_VAR(Industry, counter, SLE_UINT16),
178 SLE_VAR(Industry, type, SLE_UINT8),
179 SLE_VAR(Industry, owner, SLE_UINT8),
180 SLE_VAR(Industry, random_colour, SLE_UINT8),
181 SLE_CONDVAR(Industry, last_prod_year, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
182 SLE_CONDVAR(Industry, last_prod_year, SLE_INT32, SLV_31, SL_MAX_VERSION),
183 SLE_VAR(Industry, was_cargo_delivered, SLE_UINT8),
184 SLE_CONDVAR(Industry, ctlflags, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
186 SLE_CONDVAR(Industry, founder, SLE_UINT8, SLV_70, SL_MAX_VERSION),
187 SLE_CONDVAR(Industry, construction_date, SLE_INT32, SLV_70, SL_MAX_VERSION),
188 SLE_CONDVAR(Industry, construction_type, SLE_UINT8, SLV_70, SL_MAX_VERSION),
189 SLEG_CONDVAR("last_cargo_accepted_at[0]", SlIndustryAccepted::old_last_accepted[0], SLE_INT32, SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
190 SLEG_CONDARR("last_cargo_accepted_at", SlIndustryAccepted::old_last_accepted, SLE_INT32, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
191 SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, SLV_73, SL_MAX_VERSION),
192 SLE_CONDVAR(Industry, exclusive_supplier, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
193 SLE_CONDVAR(Industry, exclusive_consumer, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
195 SLEG_CONDARR("storage", _old_ind_persistent_storage.storage, SLE_UINT32, 16, SLV_76, SLV_161),
196 SLE_CONDREF(Industry, psa, REF_STORAGE, SLV_161, SL_MAX_VERSION),
198 SLE_CONDVAR(Industry, random, SLE_UINT16, SLV_82, SL_MAX_VERSION),
199 SLE_CONDSSTR(Industry, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_INDUSTRY_TEXT, SL_MAX_VERSION),
201 SLEG_CONDSTRUCTLIST("accepted", SlIndustryAccepted, SLV_INDUSTRY_CARGO_REORGANISE, SL_MAX_VERSION),
202 SLEG_CONDSTRUCTLIST("produced", SlIndustryProduced, SLV_INDUSTRY_CARGO_REORGANISE, SL_MAX_VERSION),
205 struct INDYChunkHandler : ChunkHandler {
206 INDYChunkHandler() : ChunkHandler('INDY', CH_TABLE) {}
208 void Save() const override
210 SlTableHeader(_industry_desc);
212 /* Write the industries */
213 for (Industry *ind : Industry::Iterate()) {
214 SlSetArrayIndex(ind->index);
215 SlObject(ind, _industry_desc);
219 void LoadMoveAcceptsProduced(Industry *i, uint inputs, uint outputs) const
221 i->accepted.reserve(inputs);
222 for (uint j = 0; j != inputs; ++j) {
223 auto &a = i->accepted.emplace_back();
224 a.cargo = SlIndustryAccepted::old_cargo[j];
225 a.waiting = SlIndustryAccepted::old_waiting[j];
226 a.last_accepted = SlIndustryAccepted::old_last_accepted[j];
229 i->produced.reserve(outputs);
230 for (uint j = 0; j != outputs; ++j) {
231 auto &p = i->produced.emplace_back();
232 p.cargo = SlIndustryProduced::old_cargo[j];
233 p.waiting = SlIndustryProduced::old_waiting[j];
234 p.rate = SlIndustryProduced::old_rate[j];
235 p.history[THIS_MONTH].production = SlIndustryProduced::old_this_month_production[j];
236 p.history[THIS_MONTH].transported = SlIndustryProduced::old_this_month_transported[j];
237 p.history[LAST_MONTH].production = SlIndustryProduced::old_last_month_production[j];
238 p.history[LAST_MONTH].transported = SlIndustryProduced::old_last_month_transported[j];
242 void Load() const override
244 const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat);
246 int index;
248 SlIndustryAccepted::ResetOldStructure();
249 SlIndustryProduced::ResetOldStructure();
250 Industry::ResetIndustryCounts();
252 while ((index = SlIterateArray()) != -1) {
253 Industry *i = new (index) Industry();
254 SlObject(i, slt);
256 /* Before savegame version 161, persistent storages were not stored in a pool. */
257 if (IsSavegameVersionBefore(SLV_161) && !IsSavegameVersionBefore(SLV_76)) {
258 /* Store the old persistent storage. The GRFID will be added later. */
259 assert(PersistentStorage::CanAllocateItem());
260 i->psa = new PersistentStorage(0, 0, 0);
261 std::copy(std::begin(_old_ind_persistent_storage.storage), std::end(_old_ind_persistent_storage.storage), std::begin(i->psa->storage));
263 if (IsSavegameVersionBefore(SLV_EXTEND_INDUSTRY_CARGO_SLOTS)) {
264 LoadMoveAcceptsProduced(i, INDUSTRY_ORIGINAL_NUM_INPUTS, INDUSTRY_ORIGINAL_NUM_OUTPUTS);
265 } else if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) {
266 LoadMoveAcceptsProduced(i, INDUSTRY_NUM_INPUTS, INDUSTRY_NUM_OUTPUTS);
268 Industry::IncIndustryTypeCount(i->type);
272 void FixPointers() const override
274 for (Industry *i : Industry::Iterate()) {
275 SlObject(i, _industry_desc);
280 struct IIDSChunkHandler : NewGRFMappingChunkHandler {
281 IIDSChunkHandler() : NewGRFMappingChunkHandler('IIDS', _industry_mngr) {}
284 struct TIDSChunkHandler : NewGRFMappingChunkHandler {
285 TIDSChunkHandler() : NewGRFMappingChunkHandler('TIDS', _industile_mngr) {}
288 /** Description of the data to save and load in #IndustryBuildData. */
289 static const SaveLoad _industry_builder_desc[] = {
290 SLEG_VAR("wanted_inds", _industry_builder.wanted_inds, SLE_UINT32),
293 /** Industry builder. */
294 struct IBLDChunkHandler : ChunkHandler {
295 IBLDChunkHandler() : ChunkHandler('IBLD', CH_TABLE) {}
297 void Save() const override
299 SlTableHeader(_industry_builder_desc);
301 SlSetArrayIndex(0);
302 SlGlobList(_industry_builder_desc);
305 void Load() const override
307 const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_builder_desc, _industry_builder_sl_compat);
309 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
310 SlGlobList(slt);
311 if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many IBLD entries");
315 /** Description of the data to save and load in #IndustryTypeBuildData. */
316 static const SaveLoad _industrytype_builder_desc[] = {
317 SLE_VAR(IndustryTypeBuildData, probability, SLE_UINT32),
318 SLE_VAR(IndustryTypeBuildData, min_number, SLE_UINT8),
319 SLE_VAR(IndustryTypeBuildData, target_count, SLE_UINT16),
320 SLE_VAR(IndustryTypeBuildData, max_wait, SLE_UINT16),
321 SLE_VAR(IndustryTypeBuildData, wait_count, SLE_UINT16),
324 /** Industry-type build data. */
325 struct ITBLChunkHandler : ChunkHandler {
326 ITBLChunkHandler() : ChunkHandler('ITBL', CH_TABLE) {}
328 void Save() const override
330 SlTableHeader(_industrytype_builder_desc);
332 for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
333 SlSetArrayIndex(i);
334 SlObject(_industry_builder.builddata + i, _industrytype_builder_desc);
338 void Load() const override
340 const std::vector<SaveLoad> slt = SlCompatTableHeader(_industrytype_builder_desc, _industrytype_builder_sl_compat);
342 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
343 _industry_builder.builddata[it].Reset();
345 int index;
346 while ((index = SlIterateArray()) != -1) {
347 if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas");
348 SlObject(_industry_builder.builddata + index, slt);
353 static const INDYChunkHandler INDY;
354 static const IIDSChunkHandler IIDS;
355 static const TIDSChunkHandler TIDS;
356 static const IBLDChunkHandler IBLD;
357 static const ITBLChunkHandler ITBL;
358 static const ChunkHandlerRef industry_chunk_handlers[] = {
359 INDY,
360 IIDS,
361 TIDS,
362 IBLD,
363 ITBL,
366 extern const ChunkHandlerTable _industry_chunk_handlers(industry_chunk_handlers);