Update: Translations from eints
[openttd-github.git] / src / saveload / town_sl.cpp
blobdce806121e01d3f7d61bcf6e5ccf3dfab41e5b29
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 town_sl.cpp Code handling saving and loading of towns and houses */
10 #include "../stdafx.h"
12 #include "saveload.h"
13 #include "compat/town_sl_compat.h"
15 #include "newgrf_sl.h"
16 #include "../newgrf_house.h"
17 #include "../town.h"
18 #include "../landscape.h"
19 #include "../subsidy_func.h"
20 #include "../strings_func.h"
22 #include "../safeguards.h"
24 /**
25 * Rebuild all the cached variables of towns.
27 void RebuildTownCaches()
29 InitializeBuildingCounts();
30 RebuildTownKdtree();
32 /* Reset town population and num_houses */
33 for (Town *town : Town::Iterate()) {
34 town->cache.population = 0;
35 town->cache.num_houses = 0;
38 for (TileIndex t = 0; t < Map::Size(); t++) {
39 if (!IsTileType(t, MP_HOUSE)) continue;
41 HouseID house_id = GetHouseType(t);
42 Town *town = Town::GetByTile(t);
43 IncreaseBuildingCount(town, house_id);
44 if (IsHouseCompleted(t)) town->cache.population += HouseSpec::Get(house_id)->population;
46 /* Increase the number of houses for every house, but only once. */
47 if (GetHouseNorthPart(house_id) == TileDiffXY(0, 0)) town->cache.num_houses++;
50 /* Update the population and num_house dependent values */
51 for (Town *town : Town::Iterate()) {
52 UpdateTownRadius(town);
56 /**
57 * Check and update town and house values.
59 * Checked are the HouseIDs. Updated are the
60 * town population the number of houses per
61 * town, the town radius and the max passengers
62 * of the town.
64 void UpdateHousesAndTowns()
66 for (TileIndex t = 0; t < Map::Size(); t++) {
67 if (!IsTileType(t, MP_HOUSE)) continue;
69 HouseID house_id = GetCleanHouseType(t);
70 if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
71 /* The specs for this type of house are not available any more, so
72 * replace it with the substitute original house type. */
73 house_id = _house_mngr.GetSubstituteID(house_id);
74 SetHouseType(t, house_id);
78 /* Check for cases when a NewGRF has set a wrong house substitute type. */
79 for (TileIndex t = 0; t < Map::Size(); t++) {
80 if (!IsTileType(t, MP_HOUSE)) continue;
82 HouseID house_type = GetCleanHouseType(t);
83 TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'!
84 if (t == north_tile) {
85 const HouseSpec *hs = HouseSpec::Get(house_type);
86 bool valid_house = true;
87 if (hs->building_flags & TILE_SIZE_2x1) {
88 TileIndex tile = t + TileDiffXY(1, 0);
89 if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
90 } else if (hs->building_flags & TILE_SIZE_1x2) {
91 TileIndex tile = t + TileDiffXY(0, 1);
92 if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
93 } else if (hs->building_flags & TILE_SIZE_2x2) {
94 TileIndex tile = t + TileDiffXY(0, 1);
95 if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false;
96 tile = t + TileDiffXY(1, 0);
97 if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 2) valid_house = false;
98 tile = t + TileDiffXY(1, 1);
99 if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 3) valid_house = false;
101 /* If not all tiles of this house are present remove the house.
102 * The other tiles will get removed later in this loop because
103 * their north tile is not the correct type anymore. */
104 if (!valid_house) DoClearSquare(t);
105 } else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) {
106 /* This tile should be part of a multi-tile building but the
107 * north tile of this house isn't on the map. */
108 DoClearSquare(t);
112 RebuildTownCaches();
115 class SlTownSupplied : public DefaultSaveLoadHandler<SlTownSupplied, Town> {
116 public:
117 inline static const SaveLoad description[] = {
118 SLE_CONDVAR(TransportedCargoStat<uint32_t>, old_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
119 SLE_CONDVAR(TransportedCargoStat<uint32_t>, new_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
120 SLE_CONDVAR(TransportedCargoStat<uint32_t>, old_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
121 SLE_CONDVAR(TransportedCargoStat<uint32_t>, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
123 inline const static SaveLoadCompatTable compat_description = _town_supplied_sl_compat;
126 * Get the number of cargoes used by this savegame version.
127 * @return The number of cargoes used by this savegame version.
129 size_t GetNumCargo() const
131 if (IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES)) return 32;
132 if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return NUM_CARGO;
133 /* Read from the savegame how long the list is. */
134 return SlGetStructListLength(NUM_CARGO);
137 void Save(Town *t) const override
139 SlSetStructListLength(std::size(t->supplied));
140 for (auto &supplied : t->supplied) {
141 SlObject(&supplied, this->GetDescription());
145 void Load(Town *t) const override
147 size_t num_cargo = this->GetNumCargo();
148 for (size_t i = 0; i < num_cargo; i++) {
149 SlObject(&t->supplied[i], this->GetLoadDescription());
154 class SlTownReceived : public DefaultSaveLoadHandler<SlTownReceived, Town> {
155 public:
156 inline static const SaveLoad description[] = {
157 SLE_CONDVAR(TransportedCargoStat<uint16_t>, old_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
158 SLE_CONDVAR(TransportedCargoStat<uint16_t>, new_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
159 SLE_CONDVAR(TransportedCargoStat<uint16_t>, old_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
160 SLE_CONDVAR(TransportedCargoStat<uint16_t>, new_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
162 inline const static SaveLoadCompatTable compat_description = _town_received_sl_compat;
164 void Save(Town *t) const override
166 SlSetStructListLength(std::size(t->received));
167 for (auto &received : t->received) {
168 SlObject(&received, this->GetDescription());
172 void Load(Town *t) const override
174 size_t length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? static_cast<size_t>(TAE_END) : SlGetStructListLength(TAE_END);
175 for (size_t i = 0; i < length; i++) {
176 SlObject(&t->received[i], this->GetLoadDescription());
181 class SlTownAcceptanceMatrix : public DefaultSaveLoadHandler<SlTownAcceptanceMatrix, Town> {
182 private:
183 /** Compatibility struct with just enough of TileMatrix to facilitate loading. */
184 struct AcceptanceMatrix {
185 TileArea area;
186 static const uint GRID = 4;
188 public:
189 inline static const SaveLoad description[] = {
190 SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
191 SLE_VAR(AcceptanceMatrix, area.w, SLE_UINT16),
192 SLE_VAR(AcceptanceMatrix, area.h, SLE_UINT16),
194 inline const static SaveLoadCompatTable compat_description = _town_acceptance_matrix_sl_compat;
196 void Load(Town *) const override
198 /* Discard now unused acceptance matrix. */
199 AcceptanceMatrix dummy;
200 SlObject(&dummy, this->GetLoadDescription());
201 if (dummy.area.w != 0) {
202 uint arr_len = dummy.area.w / AcceptanceMatrix::GRID * dummy.area.h / AcceptanceMatrix::GRID;
203 SlSkipBytes(4 * arr_len);
208 static const SaveLoad _town_desc[] = {
209 SLE_CONDVAR(Town, xy, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
210 SLE_CONDVAR(Town, xy, SLE_UINT32, SLV_6, SL_MAX_VERSION),
212 SLE_CONDVAR(Town, townnamegrfid, SLE_UINT32, SLV_66, SL_MAX_VERSION),
213 SLE_VAR(Town, townnametype, SLE_UINT16),
214 SLE_VAR(Town, townnameparts, SLE_UINT32),
215 SLE_CONDSSTR(Town, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
217 SLE_VAR(Town, flags, SLE_UINT8),
218 SLE_CONDVAR(Town, statues, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
219 SLE_CONDVAR(Town, statues, SLE_UINT16, SLV_104, SL_MAX_VERSION),
221 SLE_CONDVAR(Town, have_ratings, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
222 SLE_CONDVAR(Town, have_ratings, SLE_UINT16, SLV_104, SL_MAX_VERSION),
223 SLE_CONDARR(Town, ratings, SLE_INT16, 8, SL_MIN_VERSION, SLV_104),
224 SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
225 SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104),
226 SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
228 /* Slots 0 and 2 are passengers and mail respectively for old saves. */
229 SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
230 SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_UINT32, SLV_9, SLV_165),
231 SLE_CONDVARNAME(Town, supplied[2].old_max, "supplied[CT_MAIL].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
232 SLE_CONDVARNAME(Town, supplied[2].old_max, "supplied[CT_MAIL].old_max", SLE_UINT32, SLV_9, SLV_165),
233 SLE_CONDVARNAME(Town, supplied[0].new_max, "supplied[CT_PASSENGERS].new_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
234 SLE_CONDVARNAME(Town, supplied[0].new_max, "supplied[CT_PASSENGERS].new_max", SLE_UINT32, SLV_9, SLV_165),
235 SLE_CONDVARNAME(Town, supplied[2].new_max, "supplied[CT_MAIL].new_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
236 SLE_CONDVARNAME(Town, supplied[2].new_max, "supplied[CT_MAIL].new_max", SLE_UINT32, SLV_9, SLV_165),
237 SLE_CONDVARNAME(Town, supplied[0].old_act, "supplied[CT_PASSENGERS].old_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
238 SLE_CONDVARNAME(Town, supplied[0].old_act, "supplied[CT_PASSENGERS].old_act", SLE_UINT32, SLV_9, SLV_165),
239 SLE_CONDVARNAME(Town, supplied[2].old_act, "supplied[CT_MAIL].old_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
240 SLE_CONDVARNAME(Town, supplied[2].old_act, "supplied[CT_MAIL].old_act", SLE_UINT32, SLV_9, SLV_165),
241 SLE_CONDVARNAME(Town, supplied[0].new_act, "supplied[CT_PASSENGERS].new_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
242 SLE_CONDVARNAME(Town, supplied[0].new_act, "supplied[CT_PASSENGERS].new_act", SLE_UINT32, SLV_9, SLV_165),
243 SLE_CONDVARNAME(Town, supplied[2].new_act, "supplied[CT_MAIL].new_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
244 SLE_CONDVARNAME(Town, supplied[2].new_act, "supplied[CT_MAIL].new_act", SLE_UINT32, SLV_9, SLV_165),
246 SLE_CONDVARNAME(Town, received[TAE_FOOD].old_act, "received[TE_FOOD].old_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
247 SLE_CONDVARNAME(Town, received[TAE_WATER].old_act, "received[TE_WATER].old_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
248 SLE_CONDVARNAME(Town, received[TAE_FOOD].new_act, "received[TE_FOOD].new_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
249 SLE_CONDVARNAME(Town, received[TAE_WATER].new_act, "received[TE_WATER].new_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
251 SLE_CONDARR(Town, goal, SLE_UINT32, NUM_TAE, SLV_165, SL_MAX_VERSION),
253 SLE_CONDSSTR(Town, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_168, SL_MAX_VERSION),
255 SLE_CONDVAR(Town, time_until_rebuild, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
256 SLE_CONDVAR(Town, time_until_rebuild, SLE_UINT16, SLV_54, SL_MAX_VERSION),
257 SLE_CONDVAR(Town, grow_counter, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
258 SLE_CONDVAR(Town, grow_counter, SLE_UINT16, SLV_54, SL_MAX_VERSION),
259 SLE_CONDVAR(Town, growth_rate, SLE_FILE_U8 | SLE_VAR_I16, SL_MIN_VERSION, SLV_54),
260 SLE_CONDVAR(Town, growth_rate, SLE_FILE_I16 | SLE_VAR_U16, SLV_54, SLV_165),
261 SLE_CONDVAR(Town, growth_rate, SLE_UINT16, SLV_165, SL_MAX_VERSION),
263 SLE_VAR(Town, fund_buildings_months, SLE_UINT8),
264 SLE_VAR(Town, road_build_months, SLE_UINT8),
266 SLE_CONDVAR(Town, exclusivity, SLE_UINT8, SLV_2, SL_MAX_VERSION),
267 SLE_CONDVAR(Town, exclusive_counter, SLE_UINT8, SLV_2, SL_MAX_VERSION),
269 SLE_CONDVAR(Town, larger_town, SLE_BOOL, SLV_56, SL_MAX_VERSION),
270 SLE_CONDVAR(Town, layout, SLE_UINT8, SLV_113, SL_MAX_VERSION),
272 SLE_CONDREFLIST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION),
274 SLEG_CONDSTRUCTLIST("supplied", SlTownSupplied, SLV_165, SL_MAX_VERSION),
275 SLEG_CONDSTRUCTLIST("received", SlTownReceived, SLV_165, SL_MAX_VERSION),
276 SLEG_CONDSTRUCTLIST("acceptance_matrix", SlTownAcceptanceMatrix, SLV_166, SLV_REMOVE_TOWN_CARGO_CACHE),
279 struct HIDSChunkHandler : NewGRFMappingChunkHandler {
280 HIDSChunkHandler() : NewGRFMappingChunkHandler('HIDS', _house_mngr) {}
283 struct CITYChunkHandler : ChunkHandler {
284 CITYChunkHandler() : ChunkHandler('CITY', CH_TABLE) {}
286 void Save() const override
288 SlTableHeader(_town_desc);
290 for (Town *t : Town::Iterate()) {
291 SlSetArrayIndex(t->index);
292 SlObject(t, _town_desc);
296 void Load() const override
298 const std::vector<SaveLoad> slt = SlCompatTableHeader(_town_desc, _town_sl_compat);
300 int index;
302 while ((index = SlIterateArray()) != -1) {
303 Town *t = new (index) Town();
304 SlObject(t, slt);
306 if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
307 SlErrorCorrupt("Invalid town name generator");
312 void FixPointers() const override
314 if (IsSavegameVersionBefore(SLV_161)) return;
316 for (Town *t : Town::Iterate()) {
317 SlObject(t, _town_desc);
322 static const HIDSChunkHandler HIDS;
323 static const CITYChunkHandler CITY;
324 static const ChunkHandlerRef town_chunk_handlers[] = {
325 HIDS,
326 CITY,
329 extern const ChunkHandlerTable _town_chunk_handlers(town_chunk_handlers);