Changeset - r25693:311303f64840
[Not reviewed]
master
0 7 0
Patric Stout - 3 years ago 2021-06-06 21:23:12
truebrain@openttd.org
Change: store length of SL_STRUCTLIST in the savegame

This wasn't consistently done, and often variables were used that
were read by an earlier blob. By moving it next to the struct
itself, the code becomes a bit more self-contained and easier to
read.

Additionally, this allows for external tooling to know how many
structs to expect, instead of having to know where to find the
length-field or a hard-coded value that can change at any moment.
7 files changed with 156 insertions and 42 deletions:
0 comments (0 inline, 0 general)
src/saveload/company_sl.cpp
Show inline comments
 
@@ -369,41 +369,70 @@ public:
 
	void LoadCheck(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void FixPointers(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
};
 

	
 
class SlCompanyOldEconomy : public SlCompanyEconomy {
 
public:
 
	void GenericSaveLoad(CompanyProperties *c) const
 
	void Save(CompanyProperties *c) const override
 
	{
 
		SlSetStructListLength(c->num_valid_stat_ent);
 
		for (int i = 0; i < c->num_valid_stat_ent; i++) {
 
			SlObject(&c->old_economy[i], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(CompanyProperties *c) const override
 
	{
 
		if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) {
 
			c->num_valid_stat_ent = (uint8)SlGetStructListLength(UINT8_MAX);
 
		}
 
		if (c->num_valid_stat_ent > lengthof(c->old_economy)) SlErrorCorrupt("Too many old economy entries");
 

	
 
		for (int i = 0; i < c->num_valid_stat_ent; i++) {
 
			SlObject(&c->old_economy[i], this->GetDescription());
 
		}
 
	}
 

	
 
	void Save(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void Load(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void LoadCheck(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void FixPointers(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
 
};
 

	
 
class SlCompanyLiveries : public DefaultSaveLoadHandler<SlCompanyLiveries, CompanyProperties> {
 
public:
 
	inline static const SaveLoad description[] = {
 
		SLE_CONDVAR(Livery, in_use,  SLE_UINT8, SLV_34, SL_MAX_VERSION),
 
		SLE_CONDVAR(Livery, colour1, SLE_UINT8, SLV_34, SL_MAX_VERSION),
 
		SLE_CONDVAR(Livery, colour2, SLE_UINT8, SLV_34, SL_MAX_VERSION),
 
	};
 

	
 
	void GenericSaveLoad(CompanyProperties *c) const
 
	/**
 
	 * Get the number of liveries used by this savegame version.
 
	 * @return The number of liveries used by this savegame version.
 
	 */
 
	size_t GetNumLiveries() const
 
	{
 
		int num_liveries = IsSavegameVersionBefore(SLV_63) ? LS_END - 4 : (IsSavegameVersionBefore(SLV_85) ? LS_END - 2: LS_END);
 
		if (IsSavegameVersionBefore(SLV_63)) return LS_END - 4;
 
		if (IsSavegameVersionBefore(SLV_85)) return LS_END - 2;
 
		if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return LS_END;
 
		/* Read from the savegame how long the list is. */
 
		return SlGetStructListLength(LS_END);
 
	}
 

	
 
	void Save(CompanyProperties *c) const override
 
	{
 
		SlSetStructListLength(LS_END);
 
		for (int i = 0; i < LS_END; i++) {
 
			SlObject(&c->livery[i], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(CompanyProperties *c) const override
 
	{
 
		size_t num_liveries = this->GetNumLiveries();
 
		bool update_in_use = IsSavegameVersionBefore(SLV_GROUP_LIVERIES);
 

	
 
		for (int i = 0; i < num_liveries; i++) {
 
		for (size_t i = 0; i < num_liveries; i++) {
 
			SlObject(&c->livery[i], this->GetDescription());
 
			if (update_in_use && i != LS_DEFAULT) {
 
				if (c->livery[i].in_use == 0) {
 
					c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1;
 
					c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2;
 
				} else {
 
@@ -423,16 +452,13 @@ public:
 
			/* Copy bus/truck liveries over to trams */
 
			c->livery[LS_PASSENGER_TRAM] = c->livery[LS_BUS];
 
			c->livery[LS_FREIGHT_TRAM]   = c->livery[LS_TRUCK];
 
		}
 
	}
 

	
 
	void Save(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void Load(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void LoadCheck(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void FixPointers(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
 
	void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
 
};
 

	
 
/* Save/load of companies */
 
static const SaveLoad _company_desc[] = {
 
	    SLE_VAR(CompanyProperties, name_2,          SLE_UINT32),
 
	    SLE_VAR(CompanyProperties, name_1,          SLE_STRINGID),
 
@@ -464,13 +490,13 @@ static const SaveLoad _company_desc[] = 
 
	SLE_CONDVAR(CompanyProperties, last_build_coordinate, SLE_UINT32,                  SLV_6, SL_MAX_VERSION),
 
	SLE_CONDVAR(CompanyProperties, inaugurated_year,      SLE_FILE_U8  | SLE_VAR_I32,  SL_MIN_VERSION, SLV_31),
 
	SLE_CONDVAR(CompanyProperties, inaugurated_year,      SLE_INT32,                  SLV_31, SL_MAX_VERSION),
 

	
 
	    SLE_ARR(CompanyProperties, share_owners,          SLE_UINT8, 4),
 

	
 
	    SLE_VAR(CompanyProperties, num_valid_stat_ent,    SLE_UINT8),
 
	SLE_CONDVAR(CompanyProperties, num_valid_stat_ent,    SLE_UINT8,                   SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
 

	
 
	    SLE_VAR(CompanyProperties, months_of_bankruptcy,  SLE_UINT8),
 
	SLE_CONDVAR(CompanyProperties, bankrupt_asked,        SLE_FILE_U8  | SLE_VAR_U16,  SL_MIN_VERSION, SLV_104),
 
	SLE_CONDVAR(CompanyProperties, bankrupt_asked,        SLE_UINT16,                SLV_104, SL_MAX_VERSION),
 
	    SLE_VAR(CompanyProperties, bankrupt_timeout,      SLE_INT16),
 
	SLE_CONDVAR(CompanyProperties, bankrupt_value,        SLE_VAR_I64 | SLE_FILE_I32,  SL_MIN_VERSION, SLV_65),
src/saveload/game_sl.cpp
Show inline comments
 
@@ -118,30 +118,34 @@ public:
 
	inline static const SaveLoad description[] = {
 
		SLEG_SSTR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
 
	};
 

	
 
	void Save(LanguageStrings *ls) const override
 
	{
 
		SlSetStructListLength(ls->lines.size());
 

	
 
		for (const auto &string : ls->lines) {
 
			_game_saveload_string = string;
 
			SlObject(nullptr, this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(LanguageStrings *ls) const override
 
	{
 
		for (uint32 i = 0; i < _game_saveload_strings; i++) {
 
		uint32 length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _game_saveload_strings : (uint32)SlGetStructListLength(UINT32_MAX);
 

	
 
		for (uint32 i = 0; i < length; i++) {
 
			SlObject(nullptr, this->GetDescription());
 
			ls->lines.emplace_back(_game_saveload_string);
 
		}
 
	}
 
};
 

	
 
static const SaveLoad _game_language_desc[] = {
 
	SLE_SSTR(LanguageStrings, language, SLE_STR),
 
	SLEG_VAR(_game_saveload_strings, SLE_UINT32),
 
	SLEG_CONDVAR(_game_saveload_strings, SLE_UINT32, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
 
	SLEG_STRUCTLIST(SlGameLanguageString),
 
};
 

	
 
static void Load_GSTR()
 
{
 
	delete _current_data;
 
@@ -167,15 +171,13 @@ static void Load_GSTR()
 
static void Save_GSTR()
 
{
 
	if (_current_data == nullptr) return;
 

	
 
	for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
 
		SlSetArrayIndex(i);
 
		LanguageStrings *ls = &_current_data->raw_strings[i];
 
		_game_saveload_strings = (uint32)ls->lines.size();
 
		SlObject(ls, _game_language_desc);
 
		SlObject(&_current_data->raw_strings[i], _game_language_desc);
 
	}
 
}
 

	
 
static const ChunkHandler game_chunk_handlers[] = {
 
	{ 'GSTR', Save_GSTR, Load_GSTR, nullptr, nullptr, CH_ARRAY },
 
	{ 'GSDT', Save_GSDT, Load_GSDT, nullptr, nullptr, CH_ARRAY },
src/saveload/linkgraph_sl.cpp
Show inline comments
 
@@ -34,12 +34,18 @@ public:
 
		SLE_CONDVAR(Edge, last_restricted_update,   SLE_INT32, SLV_187, SL_MAX_VERSION),
 
		    SLE_VAR(Edge, next_edge,                SLE_UINT16),
 
	};
 

	
 
	void Save(Node *bn) const override
 
	{
 
		uint16 size = 0;
 
		for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
 
			size++;
 
		}
 

	
 
		SlSetStructListLength(size);
 
		for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
 
			SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(Node *bn) const override
 
@@ -51,17 +57,24 @@ public:
 
			for (NodeID to = 0; to < max_size; ++to) {
 
				SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
 
			}
 
			return;
 
		}
 

	
 
		size_t used_size = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? max_size : SlGetStructListLength(UINT16_MAX);
 

	
 
		/* ... but as that wasted a lot of space we save a sparse matrix now. */
 
		for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
 
			if (used_size == 0) SlErrorCorrupt("Link graph structure overflow");
 
			used_size--;
 

	
 
			if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
 
			SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
 
		}
 

	
 
		if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");
 
	}
 
};
 

	
 
class SlLinkgraphNode : public DefaultSaveLoadHandler<SlLinkgraphNode, LinkGraph> {
 
public:
 
	inline static const SaveLoad description[] = {
 
@@ -74,24 +87,26 @@ public:
 
	};
 

	
 
	void Save(LinkGraph *lg) const override
 
	{
 
		_linkgraph = lg;
 

	
 
		SlSetStructListLength(lg->Size());
 
		for (NodeID from = 0; from < lg->Size(); ++from) {
 
			_linkgraph_from = from;
 
			SlObject(&lg->nodes[from], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(LinkGraph *lg) const override
 
	{
 
		_linkgraph = lg;
 

	
 
		lg->Init(_num_nodes);
 
		for (NodeID from = 0; from < _num_nodes; ++from) {
 
		uint16 length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _num_nodes : (uint16)SlGetStructListLength(UINT16_MAX);
 
		lg->Init(length);
 
		for (NodeID from = 0; from < length; ++from) {
 
			_linkgraph_from = from;
 
			SlObject(&lg->nodes[from], this->GetDescription());
 
		}
 
	}
 
};
 

	
 
@@ -100,13 +115,13 @@ public:
 
 * @return SaveLoad array for link graph.
 
 */
 
SaveLoadTable GetLinkGraphDesc()
 
{
 
	static const SaveLoad link_graph_desc[] = {
 
		 SLE_VAR(LinkGraph, last_compression, SLE_INT32),
 
		SLEG_VAR(_num_nodes,                  SLE_UINT16),
 
		SLEG_CONDVAR(_num_nodes,              SLE_UINT16, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
 
		 SLE_VAR(LinkGraph, cargo,            SLE_UINT8),
 
		SLEG_STRUCTLIST(SlLinkgraphNode),
 
	};
 
	return link_graph_desc;
 
}
 

	
 
@@ -224,14 +239,12 @@ void AfterLoadLinkGraphs()
 
/**
 
 * Save all link graphs.
 
 */
 
static void Save_LGRP()
 
{
 
	for (LinkGraph *lg : LinkGraph::Iterate()) {
 
		_num_nodes = lg->Size();
 

	
 
		SlSetArrayIndex(lg->index);
 
		SlObject(lg, GetLinkGraphDesc());
 
	}
 
}
 

	
 
/**
 
@@ -249,14 +262,12 @@ static void Load_LGRP()
 
/**
 
 * Save all link graph jobs.
 
 */
 
static void Save_LGRJ()
 
{
 
	for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
 
		_num_nodes = lgj->Size();
 

	
 
		SlSetArrayIndex(lgj->index);
 
		SlObject(lgj, GetLinkGraphJobDesc());
 
	}
 
}
 

	
 
/**
src/saveload/saveload.cpp
Show inline comments
 
@@ -1587,12 +1587,40 @@ static bool SlObjectMember(void *object,
 
		default: NOT_REACHED();
 
	}
 
	return true;
 
}
 

	
 
/**
 
 * Set the length of this list.
 
 * @param The length of the list.
 
 */
 
void SlSetStructListLength(size_t length)
 
{
 
	/* Automatically calculate the length? */
 
	if (_sl.need_length != NL_NONE) {
 
		SlSetLength(SlGetArrayLength(length));
 
		if (_sl.need_length == NL_CALCLENGTH) return;
 
	}
 

	
 
	SlWriteArrayLength(length);
 
}
 

	
 
/**
 
 * Get the length of this list; if it exceeds the limit, error out.
 
 * @param limit The maximum size the list can be.
 
 * @return The length of the list.
 
 */
 
size_t SlGetStructListLength(size_t limit)
 
{
 
	size_t length = SlReadArrayLength();
 
	if (length > limit) SlErrorCorrupt("List exceeds storage size");
 

	
 
	return length;
 
}
 

	
 
/**
 
 * Main SaveLoad function.
 
 * @param object The object that is being saved or loaded.
 
 * @param slt The SaveLoad table with objects to save/load.
 
 */
 
void SlObject(void *object, const SaveLoadTable &slt)
 
{
src/saveload/saveload.h
Show inline comments
 
@@ -323,15 +323,17 @@ enum SaveLoadVersion : uint16 {
 
	SLV_START_PATCHPACKS,                   ///< 220  First known patchpack to use a version just above ours.
 
	SLV_END_PATCHPACKS = 286,               ///< 286  Last known patchpack to use a version just above ours.
 

	
 
	SLV_GS_INDUSTRY_CONTROL,                ///< 287  PR#7912 and PR#8115 GS industry control.
 
	SLV_VEH_MOTION_COUNTER,                 ///< 288  PR#8591 Desync safe motion counter
 
	SLV_INDUSTRY_TEXT,                      ///< 289  PR#8576 v1.11.0-RC1  Additional GS text for industries.
 

	
 
	SLV_MAPGEN_SETTINGS_REVAMP,             ///< 290  PR#8891 v1.11  Revamp of some mapgen settings (snow coverage, desert coverage, heightmap height, custom terrain type).
 
	SLV_GROUP_REPLACE_WAGON_REMOVAL,        ///< 291  PR#7441 Per-group wagon removal flag.
 
	SLV_CUSTOM_SUBSIDY_DURATION,            ///< 292  PR#9081 Configurable subsidy duration.
 
	SLV_SAVELOAD_LIST_LENGTH,               ///< 293  PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
 

	
 
/** Save or load result codes. */
 
enum SaveOrLoadResult {
 
@@ -989,12 +991,15 @@ static inline void *GetVariableAddress(c
 
int64 ReadValue(const void *ptr, VarType conv);
 
void WriteValue(void *ptr, VarType conv, int64 val);
 

	
 
void SlSetArrayIndex(uint index);
 
int SlIterateArray();
 

	
 
void SlSetStructListLength(size_t length);
 
size_t SlGetStructListLength(size_t limit);
 

	
 
void SlAutolength(AutolengthProc *proc, void *arg);
 
size_t SlGetFieldLength();
 
void SlSetLength(size_t length);
 
size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld);
 
size_t SlCalcObjLength(const void *object, const SaveLoadTable &slt);
 

	
src/saveload/station_sl.cpp
Show inline comments
 
@@ -154,20 +154,20 @@ static const SaveLoad _roadstop_desc[] =
 

	
 
	SLE_CONDNULL(4, SL_MIN_VERSION, SLV_25),
 
	SLE_CONDNULL(1, SLV_25, SLV_26),
 
};
 

	
 
static uint16 _waiting_acceptance;
 
static uint32 _num_flows;
 
static uint32 _old_num_flows;
 
static uint16 _cargo_source;
 
static uint32 _cargo_source_xy;
 
static uint8  _cargo_days;
 
static Money  _cargo_feeder_share;
 

	
 
std::list<CargoPacket *> _packets;
 
uint32 _num_dests;
 
uint32 _old_num_dests;
 

	
 
struct FlowSaveLoad {
 
	FlowSaveLoad() : source(0), via(0), share(0), restricted(false) {}
 
	StationID source;
 
	StationID via;
 
	uint32 share;
 
@@ -206,19 +206,24 @@ public:
 
		SLE_CONDVAR(StationSpecList, grfid,    SLE_UINT32, SLV_27, SL_MAX_VERSION),
 
		SLE_CONDVAR(StationSpecList, localidx, SLE_UINT8,  SLV_27, SL_MAX_VERSION),
 
	};
 

	
 
	void Save(BaseStation *bst) const override
 
	{
 
		SlSetStructListLength(bst->num_specs);
 
		for (uint i = 0; i < bst->num_specs; i++) {
 
			SlObject(&bst->speclist[i], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(BaseStation *bst) const override
 
	{
 
		if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) {
 
			bst->num_specs = (uint8)SlGetStructListLength(UINT8_MAX);
 
		}
 

	
 
		if (bst->num_specs != 0) {
 
			/* Allocate speclist memory when loading a game */
 
			bst->speclist = CallocT<StationSpecList>(bst->num_specs);
 
			for (uint i = 0; i < bst->num_specs; i++) {
 
				SlObject(&bst->speclist[i], this->GetDescription());
 
			}
 
@@ -232,21 +237,24 @@ public:
 
		    SLE_VAR(StationCargoPair, first,  SLE_UINT16),
 
		SLE_REFLIST(StationCargoPair, second, REF_CARGO_PACKET),
 
	};
 

	
 
	void Save(GoodsEntry *ge) const override
 
	{
 
		SlSetStructListLength(ge->cargo.Packets()->MapSize());
 
		for (StationCargoPacketMap::ConstMapIterator it(ge->cargo.Packets()->begin()); it != ge->cargo.Packets()->end(); ++it) {
 
			SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(GoodsEntry *ge) const override
 
	{
 
		size_t num_dests = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _old_num_dests : SlGetStructListLength(UINT32_MAX);
 

	
 
		StationCargoPair pair;
 
		for (uint j = 0; j < _num_dests; ++j) {
 
		for (uint j = 0; j < num_dests; ++j) {
 
			SlObject(&pair, this->GetDescription());
 
			const_cast<StationCargoPacketMap &>(*(ge->cargo.Packets()))[pair.first].swap(pair.second);
 
			assert(pair.second.empty());
 
		}
 
	}
 

	
 
@@ -266,12 +274,18 @@ public:
 
		    SLE_VAR(FlowSaveLoad, share,      SLE_UINT32),
 
		SLE_CONDVAR(FlowSaveLoad, restricted, SLE_BOOL, SLV_187, SL_MAX_VERSION),
 
	};
 

	
 
	void Save(GoodsEntry *ge) const override
 
	{
 
		uint32 num_flows = 0;
 
		for (FlowStatMap::const_iterator it(ge->flows.begin()); it != ge->flows.end(); ++it) {
 
			num_flows += (uint32)it->second.GetShares()->size();
 
		}
 
		SlSetStructListLength(num_flows);
 

	
 
		for (FlowStatMap::const_iterator outer_it(ge->flows.begin()); outer_it != ge->flows.end(); ++outer_it) {
 
			const FlowStat::SharesMap *shares = outer_it->second.GetShares();
 
			uint32 sum_shares = 0;
 
			FlowSaveLoad flow;
 
			flow.source = outer_it->first;
 
			for (FlowStat::SharesMap::const_iterator inner_it(shares->begin()); inner_it != shares->end(); ++inner_it) {
 
@@ -284,16 +298,18 @@ public:
 
			}
 
		}
 
	}
 

	
 
	void Load(GoodsEntry *ge) const override
 
	{
 
		size_t num_flows = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _old_num_flows : SlGetStructListLength(UINT32_MAX);
 

	
 
		FlowSaveLoad flow;
 
		FlowStat *fs = nullptr;
 
		StationID prev_source = INVALID_STATION;
 
		for (uint32 j = 0; j < _num_flows; ++j) {
 
		for (uint32 j = 0; j < num_flows; ++j) {
 
			SlObject(&flow, this->GetDescription());
 
			if (fs == nullptr || prev_source != flow.source) {
 
				fs = &(ge->flows.insert(std::make_pair(flow.source, FlowStat(flow.via, flow.share, flow.restricted))).first->second);
 
			} else {
 
				fs->AppendShare(flow.via, flow.share, flow.restricted);
 
			}
 
@@ -327,35 +343,46 @@ public:
 
		     SLE_VAR(GoodsEntry, last_speed,           SLE_UINT8),
 
		     SLE_VAR(GoodsEntry, last_age,             SLE_UINT8),
 
		SLEG_CONDVAR(            _cargo_feeder_share,  SLE_FILE_U32 | SLE_VAR_I64, SLV_14, SLV_65),
 
		SLEG_CONDVAR(            _cargo_feeder_share,  SLE_INT64,                  SLV_65, SLV_68),
 
		 SLE_CONDVAR(GoodsEntry, amount_fract,         SLE_UINT8,                 SLV_150, SL_MAX_VERSION),
 
		SLEG_CONDREFLIST(        _packets,             REF_CARGO_PACKET,           SLV_68, SLV_183),
 
		SLEG_CONDVAR(            _num_dests,           SLE_UINT32,                SLV_183, SL_MAX_VERSION),
 
		SLEG_CONDVAR(            _old_num_dests,       SLE_UINT32,                SLV_183, SLV_SAVELOAD_LIST_LENGTH),
 
		 SLE_CONDVAR(GoodsEntry, cargo.reserved_count, SLE_UINT,                  SLV_181, SL_MAX_VERSION),
 
		 SLE_CONDVAR(GoodsEntry, link_graph,           SLE_UINT16,                SLV_183, SL_MAX_VERSION),
 
		 SLE_CONDVAR(GoodsEntry, node,                 SLE_UINT16,                SLV_183, SL_MAX_VERSION),
 
		SLEG_CONDVAR(            _num_flows,           SLE_UINT32,                SLV_183, SL_MAX_VERSION),
 
		SLEG_CONDVAR(            _old_num_flows,       SLE_UINT32,                SLV_183, SLV_SAVELOAD_LIST_LENGTH),
 
		 SLE_CONDVAR(GoodsEntry, max_waiting_cargo,    SLE_UINT32,                SLV_183, SL_MAX_VERSION),
 
		SLEG_CONDSTRUCTLIST(SlStationFlow,                                        SLV_183, SL_MAX_VERSION),
 
		SLEG_CONDSTRUCTLIST(SlStationCargo,                                       SLV_183, SL_MAX_VERSION),
 
	};
 
#if defined(_MSC_VER) && (_MSC_VER == 1915 || _MSC_VER == 1916)
 
		return description;
 
	}
 
#endif
 

	
 
	/**
 
	 * 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_55)) return 12;
 
		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(BaseStation *bst) const override
 
	{
 
		Station *st = Station::From(bst);
 

	
 
		SlSetStructListLength(NUM_CARGO);
 

	
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			_num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize();
 
			_num_flows = 0;
 
			for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) {
 
				_num_flows += (uint32)it->second.GetShares()->size();
 
			}
 
			SlObject(&st->goods[i], this->GetDescription());
 
		}
 
	}
 

	
 
	void Load(BaseStation *bst) const override
 
	{
 
@@ -366,13 +393,13 @@ public:
 
			/* Store the old persistent storage. The GRFID will be added later. */
 
			assert(PersistentStorage::CanAllocateItem());
 
			st->airport.psa = new PersistentStorage(0, 0, 0);
 
			memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(_old_st_persistent_storage.storage));
 
		}
 

	
 
		uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
 
		size_t num_cargo = this->GetNumCargo();
 
		for (CargoID i = 0; i < num_cargo; i++) {
 
			GoodsEntry *ge = &st->goods[i];
 
			SlObject(ge, this->GetDescription());
 
			if (IsSavegameVersionBefore(SLV_183)) {
 
				SwapPackets(ge);
 
			}
 
@@ -517,13 +544,13 @@ public:
 
		    SLE_VAR(BaseStation, facilities,             SLE_UINT8),
 
		    SLE_VAR(BaseStation, build_date,             SLE_INT32),
 

	
 
		/* Used by newstations for graphic variations */
 
		    SLE_VAR(BaseStation, random_bits,            SLE_UINT16),
 
		    SLE_VAR(BaseStation, waiting_triggers,       SLE_UINT8),
 
		    SLE_VAR(BaseStation, num_specs,              SLE_UINT8),
 
		SLE_CONDVAR(BaseStation, num_specs,              SLE_UINT8,                   SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
 
	};
 

	
 
	void GenericSaveLoad(BaseStation *bst) const
 
	{
 
		SlObject(bst, this->GetDescription());
 
	}
 
@@ -623,13 +650,13 @@ static void Save_STNN()
 
		SlObject(st, _station_desc);
 
	}
 
}
 

	
 
static void Load_STNN()
 
{
 
	_num_flows = 0;
 
	_old_num_flows = 0;
 

	
 
	int index;
 
	while ((index = SlIterateArray()) != -1) {
 
		bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
 

	
 
		BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
src/saveload/town_sl.cpp
Show inline comments
 
@@ -119,22 +119,35 @@ public:
 
		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),
 
	};
 

	
 
	/**
 
	 * 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
 
	{
 
		uint num_cargo = IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
 
		size_t num_cargo = this->GetNumCargo();
 
		for (CargoID i = 0; i < num_cargo; i++) {
 
			SlObject(&t->supplied[i], this->GetDescription());
 
		}
 
	}
 
};
 

	
 
@@ -146,20 +159,22 @@ public:
 
		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),
 
	};
 

	
 
	void Save(Town *t) const override
 
	{
 
		for (int i = TE_BEGIN; i < TE_END; i++) {
 
		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
 
	{
 
		for (int i = TE_BEGIN; i < TE_END; i++) {
 
		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->GetDescription());
 
		}
 
	}
 
};
 

	
 
class SlTownAcceptanceMatrix : public DefaultSaveLoadHandler<SlTownAcceptanceMatrix, Town> {
0 comments (0 inline, 0 general)