Merge branch 'openttd'
This commit is contained in:
+142
-126
@@ -8,6 +8,11 @@
|
||||
/** @file town_sl.cpp Code handling saving and loading of towns and houses */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/town_sl_compat.h"
|
||||
|
||||
#include "newgrf_sl.h"
|
||||
#include "../newgrf_house.h"
|
||||
#include "../town.h"
|
||||
#include "../landscape.h"
|
||||
@@ -15,9 +20,6 @@
|
||||
#include "../strings_func.h"
|
||||
#include "../tilematrix_type.hpp"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../citymania/cm_main.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
@@ -116,15 +118,97 @@ void UpdateHousesAndTowns()
|
||||
RebuildTownCaches();
|
||||
}
|
||||
|
||||
/** Save and load of towns. */
|
||||
class SlTownSupplied : public DefaultSaveLoadHandler<SlTownSupplied, Town> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _town_supplied_sl_compat;
|
||||
|
||||
/**
|
||||
* Get the number of cargoes used by this savegame version.
|
||||
* @return The number of cargoes used by this savegame version.
|
||||
*/
|
||||
size_t GetNumCargo() const
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES)) return 32;
|
||||
if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return NUM_CARGO;
|
||||
/* Read from the savegame how long the list is. */
|
||||
return SlGetStructListLength(NUM_CARGO);
|
||||
}
|
||||
|
||||
void Save(Town *t) const override
|
||||
{
|
||||
SlSetStructListLength(NUM_CARGO);
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
SlObject(&t->supplied[i], this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(Town *t) const override
|
||||
{
|
||||
size_t num_cargo = this->GetNumCargo();
|
||||
for (CargoID i = 0; i < num_cargo; i++) {
|
||||
SlObject(&t->supplied[i], this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlTownReceived : public DefaultSaveLoadHandler<SlTownReceived, Town> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _town_received_sl_compat;
|
||||
|
||||
void Save(Town *t) const override
|
||||
{
|
||||
SlSetStructListLength(NUM_TE);
|
||||
for (size_t i = TE_BEGIN; i < TE_END; i++) {
|
||||
SlObject(&t->received[i], this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(Town *t) const override
|
||||
{
|
||||
size_t length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? (size_t)TE_END : SlGetStructListLength(TE_END);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
SlObject(&t->received[i], this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlTownAcceptanceMatrix : public DefaultSaveLoadHandler<SlTownAcceptanceMatrix, Town> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
|
||||
SLE_VAR(AcceptanceMatrix, area.w, SLE_UINT16),
|
||||
SLE_VAR(AcceptanceMatrix, area.h, SLE_UINT16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _town_acceptance_matrix_sl_compat;
|
||||
|
||||
void Load(Town *t) const override
|
||||
{
|
||||
/* Discard now unused acceptance matrix. */
|
||||
AcceptanceMatrix dummy;
|
||||
SlObject(&dummy, this->GetLoadDescription());
|
||||
if (dummy.area.w != 0) {
|
||||
uint arr_len = dummy.area.w / AcceptanceMatrix::GRID * dummy.area.h / AcceptanceMatrix::GRID;
|
||||
SlSkipBytes(4 * arr_len);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDVAR(Town, xy, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDVAR(Town, xy, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_3), ///< population, no longer in use
|
||||
SLE_CONDNULL(4, SLV_3, SLV_85), ///< population, no longer in use
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_92), ///< num_houses, no longer in use
|
||||
|
||||
SLE_CONDVAR(Town, townnamegrfid, SLE_UINT32, SLV_66, SL_MAX_VERSION),
|
||||
SLE_VAR(Town, townnametype, SLE_UINT16),
|
||||
SLE_VAR(Town, townnameparts, SLE_UINT32),
|
||||
@@ -134,36 +218,30 @@ static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDVAR(Town, statues, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDVAR(Town, statues, SLE_UINT16, SLV_104, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_2), ///< sort_index, no longer in use
|
||||
|
||||
SLE_CONDVAR(Town, have_ratings, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDVAR(Town, have_ratings, SLE_UINT16, SLV_104, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Town, ratings, SLE_INT16, 8, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
|
||||
/* failed bribe attempts are stored since savegame format 4 */
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104),
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_164), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
|
||||
|
||||
SLE_CONDVAR(Town, received[TE_FOOD].old_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDVAR(Town, received[TE_WATER].old_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDVAR(Town, received[TE_FOOD].new_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
@@ -174,12 +252,10 @@ static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDSSTR(Town, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_168, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, time_until_rebuild, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, grow_counter, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_FILE_U8 | SLE_VAR_I16, SL_MIN_VERSION, SLV_54),
|
||||
|
||||
SLE_CONDVAR(Town, time_until_rebuild, SLE_UINT16, SLV_54, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Town, grow_counter, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, grow_counter, SLE_UINT16, SLV_54, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_FILE_U8 | SLE_VAR_I16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_FILE_I16 | SLE_VAR_U16, SLV_54, SLV_165),
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
|
||||
@@ -192,121 +268,61 @@ static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDVAR(Town, larger_town, SLE_BOOL, SLV_56, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Town, layout, SLE_UINT8, SLV_113, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDLST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION),
|
||||
SLE_CONDREFLIST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use
|
||||
SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use
|
||||
SLE_CONDNULL(30, SLV_2, SLV_REMOVE_TOWN_CARGO_CACHE), ///< old reserved space
|
||||
|
||||
SLE_END()
|
||||
SLEG_CONDSTRUCTLIST("supplied", SlTownSupplied, SLV_165, SL_MAX_VERSION),
|
||||
SLEG_CONDSTRUCTLIST("received", SlTownReceived, SLV_165, SL_MAX_VERSION),
|
||||
SLEG_CONDSTRUCTLIST("acceptance_matrix", SlTownAcceptanceMatrix, SLV_166, SLV_REMOVE_TOWN_CARGO_CACHE),
|
||||
};
|
||||
|
||||
static const SaveLoad _town_supplied_desc[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
|
||||
SLE_END()
|
||||
struct HIDSChunkHandler : NewGRFMappingChunkHandler {
|
||||
HIDSChunkHandler() : NewGRFMappingChunkHandler('HIDS', _house_mngr) {}
|
||||
};
|
||||
|
||||
static const SaveLoad _town_received_desc[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
struct CITYChunkHandler : ChunkHandler {
|
||||
CITYChunkHandler() : ChunkHandler('CITY', CH_TABLE) {}
|
||||
|
||||
SLE_END()
|
||||
};
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_town_desc);
|
||||
|
||||
static void Save_HIDS()
|
||||
{
|
||||
Save_NewGRFMapping(_house_mngr);
|
||||
}
|
||||
|
||||
static void Load_HIDS()
|
||||
{
|
||||
Load_NewGRFMapping(_house_mngr);
|
||||
}
|
||||
|
||||
const SaveLoad *GetTileMatrixDesc()
|
||||
{
|
||||
/* Here due to private member vars. */
|
||||
static const SaveLoad _tilematrix_desc[] = {
|
||||
SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
|
||||
SLE_VAR(AcceptanceMatrix, area.w, SLE_UINT16),
|
||||
SLE_VAR(AcceptanceMatrix, area.h, SLE_UINT16),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
return _tilematrix_desc;
|
||||
}
|
||||
|
||||
static void RealSave_Town(Town *t)
|
||||
{
|
||||
SlObject(t, _town_desc);
|
||||
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
SlObject(&t->supplied[i], _town_supplied_desc);
|
||||
}
|
||||
for (int i = TE_BEGIN; i < NUM_TE; i++) {
|
||||
SlObject(&t->received[i], _town_received_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_TOWN()
|
||||
{
|
||||
for (Town *t : Town::Iterate()) {
|
||||
SlSetArrayIndex(t->index);
|
||||
SlAutolength((AutolengthProc*)RealSave_Town, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_TOWN()
|
||||
{
|
||||
int index;
|
||||
uint num_cargo = IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Town *t = new (index) Town();
|
||||
SlObject(t, _town_desc);
|
||||
|
||||
for (CargoID i = 0; i < num_cargo; i++) {
|
||||
SlObject(&t->supplied[i], _town_supplied_desc);
|
||||
}
|
||||
for (int i = TE_BEGIN; i < TE_END; i++) {
|
||||
SlObject(&t->received[i], _town_received_desc);
|
||||
for (Town *t : Town::Iterate()) {
|
||||
SlSetArrayIndex(t->index);
|
||||
SlObject(t, _town_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
|
||||
SlErrorCorrupt("Invalid town name generator");
|
||||
}
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_town_desc, _town_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_166) && IsSavegameVersionBefore(SLV_REMOVE_TOWN_CARGO_CACHE)) {
|
||||
/* Discard now unused acceptance matrix. */
|
||||
AcceptanceMatrix dummy;
|
||||
SlObject(&dummy, GetTileMatrixDesc());
|
||||
if (dummy.area.w != 0) {
|
||||
uint arr_len = dummy.area.w / AcceptanceMatrix::GRID * dummy.area.h / AcceptanceMatrix::GRID;
|
||||
SlSkipBytes(4 * arr_len);
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Town *t = new (index) Town();
|
||||
SlObject(t, slt);
|
||||
|
||||
if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
|
||||
SlErrorCorrupt("Invalid town name generator");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fix pointers when loading town data. */
|
||||
static void Ptrs_TOWN()
|
||||
{
|
||||
/* Don't run when savegame version lower than 161. */
|
||||
if (IsSavegameVersionBefore(SLV_161)) return;
|
||||
void FixPointers() const override
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_161)) return;
|
||||
|
||||
for (Town *t : Town::Iterate()) {
|
||||
SlObject(t, _town_desc);
|
||||
for (Town *t : Town::Iterate()) {
|
||||
SlObject(t, _town_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Chunk handler for towns. */
|
||||
extern const ChunkHandler _town_chunk_handlers[] = {
|
||||
{ 'HIDS', Save_HIDS, Load_HIDS, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, nullptr, CH_ARRAY | CH_LAST},
|
||||
};
|
||||
|
||||
static const HIDSChunkHandler HIDS;
|
||||
static const CITYChunkHandler CITY;
|
||||
static const ChunkHandlerRef town_chunk_handlers[] = {
|
||||
HIDS,
|
||||
CITY,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _town_chunk_handlers(town_chunk_handlers);
|
||||
|
||||
Reference in New Issue
Block a user