mirror of https://github.com/OpenTTD/OpenTTD
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.pull/9375/head
parent
d0bcb9839a
commit
a146bcfe93
|
@ -372,8 +372,19 @@ public:
|
||||||
|
|
||||||
class SlCompanyOldEconomy : public SlCompanyEconomy {
|
class SlCompanyOldEconomy : public SlCompanyEconomy {
|
||||||
public:
|
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");
|
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++) {
|
for (int i = 0; i < c->num_valid_stat_ent; i++) {
|
||||||
|
@ -381,10 +392,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Save(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
|
void LoadCheck(CompanyProperties *c) const override { this->Load(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); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SlCompanyLiveries : public DefaultSaveLoadHandler<SlCompanyLiveries, CompanyProperties> {
|
class SlCompanyLiveries : public DefaultSaveLoadHandler<SlCompanyLiveries, CompanyProperties> {
|
||||||
|
@ -395,12 +403,33 @@ public:
|
||||||
SLE_CONDVAR(Livery, colour2, 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);
|
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());
|
SlObject(&c->livery[i], this->GetDescription());
|
||||||
if (update_in_use && i != LS_DEFAULT) {
|
if (update_in_use && i != LS_DEFAULT) {
|
||||||
if (c->livery[i].in_use == 0) {
|
if (c->livery[i].in_use == 0) {
|
||||||
|
@ -426,10 +455,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Save(CompanyProperties *c) const override { this->GenericSaveLoad(c); }
|
void LoadCheck(CompanyProperties *c) const override { this->Load(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); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Save/load of companies */
|
/* Save/load of companies */
|
||||||
|
@ -467,7 +493,7 @@ static const SaveLoad _company_desc[] = {
|
||||||
|
|
||||||
SLE_ARR(CompanyProperties, share_owners, SLE_UINT8, 4),
|
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_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_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||||
|
|
|
@ -121,6 +121,8 @@ public:
|
||||||
|
|
||||||
void Save(LanguageStrings *ls) const override
|
void Save(LanguageStrings *ls) const override
|
||||||
{
|
{
|
||||||
|
SlSetStructListLength(ls->lines.size());
|
||||||
|
|
||||||
for (const auto &string : ls->lines) {
|
for (const auto &string : ls->lines) {
|
||||||
_game_saveload_string = string;
|
_game_saveload_string = string;
|
||||||
SlObject(nullptr, this->GetDescription());
|
SlObject(nullptr, this->GetDescription());
|
||||||
|
@ -129,7 +131,9 @@ public:
|
||||||
|
|
||||||
void Load(LanguageStrings *ls) const override
|
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());
|
SlObject(nullptr, this->GetDescription());
|
||||||
ls->lines.emplace_back(_game_saveload_string);
|
ls->lines.emplace_back(_game_saveload_string);
|
||||||
}
|
}
|
||||||
|
@ -138,7 +142,7 @@ public:
|
||||||
|
|
||||||
static const SaveLoad _game_language_desc[] = {
|
static const SaveLoad _game_language_desc[] = {
|
||||||
SLE_SSTR(LanguageStrings, language, SLE_STR),
|
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),
|
SLEG_STRUCTLIST(SlGameLanguageString),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,9 +174,7 @@ static void Save_GSTR()
|
||||||
|
|
||||||
for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
|
for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
|
||||||
SlSetArrayIndex(i);
|
SlSetArrayIndex(i);
|
||||||
LanguageStrings *ls = &_current_data->raw_strings[i];
|
SlObject(&_current_data->raw_strings[i], _game_language_desc);
|
||||||
_game_saveload_strings = (uint32)ls->lines.size();
|
|
||||||
SlObject(ls, _game_language_desc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,12 @@ public:
|
||||||
|
|
||||||
void Save(Node *bn) const override
|
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) {
|
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
|
||||||
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
|
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
|
||||||
}
|
}
|
||||||
|
@ -54,11 +60,18 @@ public:
|
||||||
return;
|
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. */
|
/* ... 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) {
|
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");
|
if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
|
||||||
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
|
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,6 +90,7 @@ public:
|
||||||
{
|
{
|
||||||
_linkgraph = lg;
|
_linkgraph = lg;
|
||||||
|
|
||||||
|
SlSetStructListLength(lg->Size());
|
||||||
for (NodeID from = 0; from < lg->Size(); ++from) {
|
for (NodeID from = 0; from < lg->Size(); ++from) {
|
||||||
_linkgraph_from = from;
|
_linkgraph_from = from;
|
||||||
SlObject(&lg->nodes[from], this->GetDescription());
|
SlObject(&lg->nodes[from], this->GetDescription());
|
||||||
|
@ -87,8 +101,9 @@ public:
|
||||||
{
|
{
|
||||||
_linkgraph = lg;
|
_linkgraph = lg;
|
||||||
|
|
||||||
lg->Init(_num_nodes);
|
uint16 length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _num_nodes : (uint16)SlGetStructListLength(UINT16_MAX);
|
||||||
for (NodeID from = 0; from < _num_nodes; ++from) {
|
lg->Init(length);
|
||||||
|
for (NodeID from = 0; from < length; ++from) {
|
||||||
_linkgraph_from = from;
|
_linkgraph_from = from;
|
||||||
SlObject(&lg->nodes[from], this->GetDescription());
|
SlObject(&lg->nodes[from], this->GetDescription());
|
||||||
}
|
}
|
||||||
|
@ -103,7 +118,7 @@ SaveLoadTable GetLinkGraphDesc()
|
||||||
{
|
{
|
||||||
static const SaveLoad link_graph_desc[] = {
|
static const SaveLoad link_graph_desc[] = {
|
||||||
SLE_VAR(LinkGraph, last_compression, SLE_INT32),
|
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),
|
SLE_VAR(LinkGraph, cargo, SLE_UINT8),
|
||||||
SLEG_STRUCTLIST(SlLinkgraphNode),
|
SLEG_STRUCTLIST(SlLinkgraphNode),
|
||||||
};
|
};
|
||||||
|
@ -227,8 +242,6 @@ void AfterLoadLinkGraphs()
|
||||||
static void Save_LGRP()
|
static void Save_LGRP()
|
||||||
{
|
{
|
||||||
for (LinkGraph *lg : LinkGraph::Iterate()) {
|
for (LinkGraph *lg : LinkGraph::Iterate()) {
|
||||||
_num_nodes = lg->Size();
|
|
||||||
|
|
||||||
SlSetArrayIndex(lg->index);
|
SlSetArrayIndex(lg->index);
|
||||||
SlObject(lg, GetLinkGraphDesc());
|
SlObject(lg, GetLinkGraphDesc());
|
||||||
}
|
}
|
||||||
|
@ -252,8 +265,6 @@ static void Load_LGRP()
|
||||||
static void Save_LGRJ()
|
static void Save_LGRJ()
|
||||||
{
|
{
|
||||||
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
||||||
_num_nodes = lgj->Size();
|
|
||||||
|
|
||||||
SlSetArrayIndex(lgj->index);
|
SlSetArrayIndex(lgj->index);
|
||||||
SlObject(lgj, GetLinkGraphJobDesc());
|
SlObject(lgj, GetLinkGraphJobDesc());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1589,6 +1589,34 @@ static bool SlObjectMember(void *object, const SaveLoad &sld)
|
||||||
return true;
|
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.
|
* Main SaveLoad function.
|
||||||
* @param object The object that is being saved or loaded.
|
* @param object The object that is being saved or loaded.
|
||||||
|
|
|
@ -326,9 +326,11 @@ enum SaveLoadVersion : uint16 {
|
||||||
SLV_GS_INDUSTRY_CONTROL, ///< 287 PR#7912 and PR#8115 GS industry control.
|
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_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_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_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_GROUP_REPLACE_WAGON_REMOVAL, ///< 291 PR#7441 Per-group wagon removal flag.
|
||||||
SLV_CUSTOM_SUBSIDY_DURATION, ///< 292 PR#9081 Configurable subsidy duration.
|
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
|
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||||
};
|
};
|
||||||
|
@ -992,6 +994,9 @@ void WriteValue(void *ptr, VarType conv, int64 val);
|
||||||
void SlSetArrayIndex(uint index);
|
void SlSetArrayIndex(uint index);
|
||||||
int SlIterateArray();
|
int SlIterateArray();
|
||||||
|
|
||||||
|
void SlSetStructListLength(size_t length);
|
||||||
|
size_t SlGetStructListLength(size_t limit);
|
||||||
|
|
||||||
void SlAutolength(AutolengthProc *proc, void *arg);
|
void SlAutolength(AutolengthProc *proc, void *arg);
|
||||||
size_t SlGetFieldLength();
|
size_t SlGetFieldLength();
|
||||||
void SlSetLength(size_t length);
|
void SlSetLength(size_t length);
|
||||||
|
|
|
@ -157,14 +157,14 @@ static const SaveLoad _roadstop_desc[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint16 _waiting_acceptance;
|
static uint16 _waiting_acceptance;
|
||||||
static uint32 _num_flows;
|
static uint32 _old_num_flows;
|
||||||
static uint16 _cargo_source;
|
static uint16 _cargo_source;
|
||||||
static uint32 _cargo_source_xy;
|
static uint32 _cargo_source_xy;
|
||||||
static uint8 _cargo_days;
|
static uint8 _cargo_days;
|
||||||
static Money _cargo_feeder_share;
|
static Money _cargo_feeder_share;
|
||||||
|
|
||||||
std::list<CargoPacket *> _packets;
|
std::list<CargoPacket *> _packets;
|
||||||
uint32 _num_dests;
|
uint32 _old_num_dests;
|
||||||
|
|
||||||
struct FlowSaveLoad {
|
struct FlowSaveLoad {
|
||||||
FlowSaveLoad() : source(0), via(0), share(0), restricted(false) {}
|
FlowSaveLoad() : source(0), via(0), share(0), restricted(false) {}
|
||||||
|
@ -209,6 +209,7 @@ public:
|
||||||
|
|
||||||
void Save(BaseStation *bst) const override
|
void Save(BaseStation *bst) const override
|
||||||
{
|
{
|
||||||
|
SlSetStructListLength(bst->num_specs);
|
||||||
for (uint i = 0; i < bst->num_specs; i++) {
|
for (uint i = 0; i < bst->num_specs; i++) {
|
||||||
SlObject(&bst->speclist[i], this->GetDescription());
|
SlObject(&bst->speclist[i], this->GetDescription());
|
||||||
}
|
}
|
||||||
|
@ -216,6 +217,10 @@ public:
|
||||||
|
|
||||||
void Load(BaseStation *bst) const override
|
void Load(BaseStation *bst) const override
|
||||||
{
|
{
|
||||||
|
if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) {
|
||||||
|
bst->num_specs = (uint8)SlGetStructListLength(UINT8_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
if (bst->num_specs != 0) {
|
if (bst->num_specs != 0) {
|
||||||
/* Allocate speclist memory when loading a game */
|
/* Allocate speclist memory when loading a game */
|
||||||
bst->speclist = CallocT<StationSpecList>(bst->num_specs);
|
bst->speclist = CallocT<StationSpecList>(bst->num_specs);
|
||||||
|
@ -235,6 +240,7 @@ public:
|
||||||
|
|
||||||
void Save(GoodsEntry *ge) const override
|
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) {
|
for (StationCargoPacketMap::ConstMapIterator it(ge->cargo.Packets()->begin()); it != ge->cargo.Packets()->end(); ++it) {
|
||||||
SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), this->GetDescription());
|
SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), this->GetDescription());
|
||||||
}
|
}
|
||||||
|
@ -242,8 +248,10 @@ public:
|
||||||
|
|
||||||
void Load(GoodsEntry *ge) const override
|
void Load(GoodsEntry *ge) const override
|
||||||
{
|
{
|
||||||
|
size_t num_dests = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _old_num_dests : SlGetStructListLength(UINT32_MAX);
|
||||||
|
|
||||||
StationCargoPair pair;
|
StationCargoPair pair;
|
||||||
for (uint j = 0; j < _num_dests; ++j) {
|
for (uint j = 0; j < num_dests; ++j) {
|
||||||
SlObject(&pair, this->GetDescription());
|
SlObject(&pair, this->GetDescription());
|
||||||
const_cast<StationCargoPacketMap &>(*(ge->cargo.Packets()))[pair.first].swap(pair.second);
|
const_cast<StationCargoPacketMap &>(*(ge->cargo.Packets()))[pair.first].swap(pair.second);
|
||||||
assert(pair.second.empty());
|
assert(pair.second.empty());
|
||||||
|
@ -269,6 +277,12 @@ public:
|
||||||
|
|
||||||
void Save(GoodsEntry *ge) const override
|
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) {
|
for (FlowStatMap::const_iterator outer_it(ge->flows.begin()); outer_it != ge->flows.end(); ++outer_it) {
|
||||||
const FlowStat::SharesMap *shares = outer_it->second.GetShares();
|
const FlowStat::SharesMap *shares = outer_it->second.GetShares();
|
||||||
uint32 sum_shares = 0;
|
uint32 sum_shares = 0;
|
||||||
|
@ -287,10 +301,12 @@ public:
|
||||||
|
|
||||||
void Load(GoodsEntry *ge) const override
|
void Load(GoodsEntry *ge) const override
|
||||||
{
|
{
|
||||||
|
size_t num_flows = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _old_num_flows : SlGetStructListLength(UINT32_MAX);
|
||||||
|
|
||||||
FlowSaveLoad flow;
|
FlowSaveLoad flow;
|
||||||
FlowStat *fs = nullptr;
|
FlowStat *fs = nullptr;
|
||||||
StationID prev_source = INVALID_STATION;
|
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());
|
SlObject(&flow, this->GetDescription());
|
||||||
if (fs == nullptr || prev_source != flow.source) {
|
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);
|
fs = &(ge->flows.insert(std::make_pair(flow.source, FlowStat(flow.via, flow.share, flow.restricted))).first->second);
|
||||||
|
@ -330,11 +346,11 @@ public:
|
||||||
SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, SLV_65, SLV_68),
|
SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, SLV_65, SLV_68),
|
||||||
SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, SLV_150, SL_MAX_VERSION),
|
SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, SLV_150, SL_MAX_VERSION),
|
||||||
SLEG_CONDREFLIST( _packets, REF_CARGO_PACKET, SLV_68, SLV_183),
|
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, 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, link_graph, SLE_UINT16, SLV_183, SL_MAX_VERSION),
|
||||||
SLE_CONDVAR(GoodsEntry, node, 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),
|
SLE_CONDVAR(GoodsEntry, max_waiting_cargo, SLE_UINT32, SLV_183, SL_MAX_VERSION),
|
||||||
SLEG_CONDSTRUCTLIST(SlStationFlow, SLV_183, SL_MAX_VERSION),
|
SLEG_CONDSTRUCTLIST(SlStationFlow, SLV_183, SL_MAX_VERSION),
|
||||||
SLEG_CONDSTRUCTLIST(SlStationCargo, SLV_183, SL_MAX_VERSION),
|
SLEG_CONDSTRUCTLIST(SlStationCargo, SLV_183, SL_MAX_VERSION),
|
||||||
|
@ -344,15 +360,26 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
void Save(BaseStation *bst) const override
|
||||||
{
|
{
|
||||||
Station *st = Station::From(bst);
|
Station *st = Station::From(bst);
|
||||||
|
|
||||||
|
SlSetStructListLength(NUM_CARGO);
|
||||||
|
|
||||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
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());
|
SlObject(&st->goods[i], this->GetDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,7 +396,7 @@ public:
|
||||||
memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(_old_st_persistent_storage.storage));
|
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++) {
|
for (CargoID i = 0; i < num_cargo; i++) {
|
||||||
GoodsEntry *ge = &st->goods[i];
|
GoodsEntry *ge = &st->goods[i];
|
||||||
SlObject(ge, this->GetDescription());
|
SlObject(ge, this->GetDescription());
|
||||||
|
@ -520,7 +547,7 @@ public:
|
||||||
/* Used by newstations for graphic variations */
|
/* Used by newstations for graphic variations */
|
||||||
SLE_VAR(BaseStation, random_bits, SLE_UINT16),
|
SLE_VAR(BaseStation, random_bits, SLE_UINT16),
|
||||||
SLE_VAR(BaseStation, waiting_triggers, SLE_UINT8),
|
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
|
void GenericSaveLoad(BaseStation *bst) const
|
||||||
|
@ -626,7 +653,7 @@ static void Save_STNN()
|
||||||
|
|
||||||
static void Load_STNN()
|
static void Load_STNN()
|
||||||
{
|
{
|
||||||
_num_flows = 0;
|
_old_num_flows = 0;
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
|
|
|
@ -122,8 +122,21 @@ public:
|
||||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_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
|
void Save(Town *t) const override
|
||||||
{
|
{
|
||||||
|
SlSetStructListLength(NUM_CARGO);
|
||||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||||
SlObject(&t->supplied[i], this->GetDescription());
|
SlObject(&t->supplied[i], this->GetDescription());
|
||||||
}
|
}
|
||||||
|
@ -131,7 +144,7 @@ public:
|
||||||
|
|
||||||
void Load(Town *t) const override
|
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++) {
|
for (CargoID i = 0; i < num_cargo; i++) {
|
||||||
SlObject(&t->supplied[i], this->GetDescription());
|
SlObject(&t->supplied[i], this->GetDescription());
|
||||||
}
|
}
|
||||||
|
@ -149,14 +162,16 @@ public:
|
||||||
|
|
||||||
void Save(Town *t) const override
|
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());
|
SlObject(&t->received[i], this->GetDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Load(Town *t) const override
|
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());
|
SlObject(&t->received[i], this->GetDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue