Save/load: Pre-filter SaveLoad descriptor arrays for current version/mode, for chunks with many objects

This commit is contained in:
Jonathan G Rennison
2019-09-23 17:30:09 +01:00
parent 02bd91477d
commit 0a1c1809ab
9 changed files with 344 additions and 69 deletions

View File

@@ -534,7 +534,8 @@ protected:
friend class LinkGraph::Node;
friend const SaveLoad *GetLinkGraphDesc();
friend const SaveLoad *GetLinkGraphJobDesc();
friend void SaveLoad_LinkGraph(LinkGraph &lg);
friend void Save_LinkGraph(LinkGraph &lg);
friend void Load_LinkGraph(LinkGraph &lg);
CargoID cargo; ///< Cargo of this component's link graph.
Date last_compression; ///< Last time the capacities and supplies were compressed.

View File

@@ -119,11 +119,11 @@ const SaveLoad *GetCargoPacketDesc()
*/
static void Save_CAPA()
{
std::vector<SaveLoad> filtered_packet_desc = SlFilterObject(GetCargoPacketDesc());
CargoPacket *cp;
FOR_ALL_CARGOPACKETS(cp) {
SlSetArrayIndex(cp->index);
SlObject(cp, GetCargoPacketDesc());
SlObjectSaveFiltered(cp, filtered_packet_desc.data());
}
}
@@ -132,11 +132,11 @@ static void Save_CAPA()
*/
static void Load_CAPA()
{
std::vector<SaveLoad> filtered_packet_desc = SlFilterObject(GetCargoPacketDesc());
int index;
while ((index = SlIterateArray()) != -1) {
CargoPacket *cp = new (index) CargoPacket();
SlObject(cp, GetCargoPacketDesc());
SlObjectLoadFiltered(cp, filtered_packet_desc.data());
}
}

View File

@@ -138,25 +138,53 @@ static const SaveLoad _edge_desc[] = {
SLE_END()
};
std::vector<SaveLoad> _filtered_node_desc;
std::vector<SaveLoad> _filtered_edge_desc;
std::vector<SaveLoad> _filtered_job_desc;
static void FilterDescs()
{
_filtered_node_desc = SlFilterObject(_node_desc);
_filtered_edge_desc = SlFilterObject(_edge_desc);
_filtered_job_desc = SlFilterObject(GetLinkGraphJobDesc());
}
/**
* Save/load a link graph.
* Save a link graph.
* @param lg Link graph to be saved or loaded.
*/
void SaveLoad_LinkGraph(LinkGraph &lg)
void Save_LinkGraph(LinkGraph &lg)
{
uint size = lg.Size();
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg.nodes[from];
SlObject(node, _node_desc);
SlObjectSaveFiltered(node, _filtered_node_desc.data());
/* ... but as that wasted a lot of space we save a sparse matrix now. */
for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
SlObjectSaveFiltered(&lg.edges[from][to], _filtered_edge_desc.data());
}
}
}
/**
* Load a link graph.
* @param lg Link graph to be saved or loaded.
*/
void Load_LinkGraph(LinkGraph &lg)
{
uint size = lg.Size();
for (NodeID from = 0; from < size; ++from) {
Node *node = &lg.nodes[from];
SlObjectLoadFiltered(node, _filtered_node_desc.data());
if (IsSavegameVersionBefore(SLV_191)) {
/* We used to save the full matrix ... */
for (NodeID to = 0; to < size; ++to) {
SlObject(&lg.edges[from][to], _edge_desc);
SlObjectLoadFiltered(&lg.edges[from][to], _filtered_edge_desc.data());
}
} else {
/* ... but as that wasted a lot of space we save a sparse matrix now. */
for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
SlObject(&lg.edges[from][to], _edge_desc);
SlObjectLoadFiltered(&lg.edges[from][to], _filtered_edge_desc.data());
}
}
}
@@ -168,10 +196,10 @@ void SaveLoad_LinkGraph(LinkGraph &lg)
*/
static void DoSave_LGRJ(LinkGraphJob *lgj)
{
SlObject(lgj, GetLinkGraphJobDesc());
SlObjectSaveFiltered(lgj, _filtered_job_desc.data());
_num_nodes = lgj->Size();
SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
SlObjectSaveFiltered(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
Save_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
}
/**
@@ -181,8 +209,8 @@ static void DoSave_LGRJ(LinkGraphJob *lgj)
static void DoSave_LGRP(LinkGraph *lg)
{
_num_nodes = lg->Size();
SlObject(lg, GetLinkGraphDesc());
SaveLoad_LinkGraph(*lg);
SlObjectSaveFiltered(lg, GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
Save_LinkGraph(*lg);
}
/**
@@ -190,6 +218,7 @@ static void DoSave_LGRP(LinkGraph *lg)
*/
static void Load_LGRP()
{
FilterDescs();
int index;
while ((index = SlIterateArray()) != -1) {
if (!LinkGraph::CanAllocateItem()) {
@@ -197,9 +226,9 @@ static void Load_LGRP()
NOT_REACHED();
}
LinkGraph *lg = new (index) LinkGraph();
SlObject(lg, GetLinkGraphDesc());
SlObjectLoadFiltered(lg, GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
lg->Init(_num_nodes);
SaveLoad_LinkGraph(*lg);
Load_LinkGraph(*lg);
}
}
@@ -208,6 +237,7 @@ static void Load_LGRP()
*/
static void Load_LGRJ()
{
FilterDescs();
int index;
while ((index = SlIterateArray()) != -1) {
if (!LinkGraphJob::CanAllocateItem()) {
@@ -215,14 +245,14 @@ static void Load_LGRJ()
NOT_REACHED();
}
LinkGraphJob *lgj = new (index) LinkGraphJob();
SlObject(lgj, GetLinkGraphJobDesc());
SlObjectLoadFiltered(lgj, _filtered_job_desc.data());
if (SlXvIsFeatureMissing(XSLFI_LINKGRAPH_DAY_SCALE)) {
GetLinkGraphJobDayLengthScaleAfterLoad(lgj);
}
LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
SlObject(&lg, GetLinkGraphDesc());
SlObjectLoadFiltered(&lg, GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
lg.Init(_num_nodes);
SaveLoad_LinkGraph(lg);
Load_LinkGraph(lg);
}
}
@@ -267,6 +297,7 @@ void AfterLoadLinkGraphs()
*/
static void Save_LGRP()
{
FilterDescs();
LinkGraph *lg;
FOR_ALL_LINK_GRAPHS(lg) {
SlSetArrayIndex(lg->index);
@@ -279,6 +310,7 @@ static void Save_LGRP()
*/
static void Save_LGRJ()
{
FilterDescs();
LinkGraphJob *lgj;
FOR_ALL_LINK_GRAPH_JOBS(lgj) {
SlSetArrayIndex(lgj->index);

View File

@@ -33,7 +33,8 @@ void Save_NewGRFMapping(const OverrideManagerBase &mapping)
{
for (uint i = 0; i < mapping.GetMaxMapping(); i++) {
SlSetArrayIndex(i);
SlObject(&mapping.mapping_ID[i], _newgrf_mapping_desc);
SlSetLength(4 + 1 + 1);
SlObjectSaveFiltered(&mapping.mapping_ID[i], _newgrf_mapping_desc); // _newgrf_mapping_desc has no conditionals
}
}
@@ -51,8 +52,8 @@ void Load_NewGRFMapping(OverrideManagerBase &mapping)
int index;
while ((index = SlIterateArray()) != -1) {
if ((uint)index >= max_id) SlErrorCorrupt("Too many NewGRF entity mappings");
SlObject(&mapping.mapping_ID[index], _newgrf_mapping_desc);
if (unlikely((uint)index >= max_id)) SlErrorCorrupt("Too many NewGRF entity mappings");
SlObjectLoadFiltered(&mapping.mapping_ID[index], _newgrf_mapping_desc); // _newgrf_mapping_desc has no conditionals
}
}

View File

@@ -889,9 +889,10 @@ void WriteValue(void *ptr, VarType conv, int64 val)
* @param ptr The object being filled/read
* @param conv VarType type of the current element of the struct
*/
static void SlSaveLoadConv(void *ptr, VarType conv)
template <SaveLoadAction action>
static void SlSaveLoadConvGeneric(void *ptr, VarType conv)
{
switch (_sl.action) {
switch (action) {
case SLA_SAVE: {
int64 x = ReadValue(ptr, conv);
@@ -937,6 +938,23 @@ static void SlSaveLoadConv(void *ptr, VarType conv)
}
}
void SlSaveLoadConv(void *ptr, VarType conv)
{
switch (_sl.action) {
case SLA_SAVE:
SlSaveLoadConvGeneric<SLA_SAVE>(ptr, conv);
return;
case SLA_LOAD_CHECK:
case SLA_LOAD:
SlSaveLoadConvGeneric<SLA_LOAD>(ptr, conv);
return;
case SLA_PTRS:
case SLA_NULL:
return;
default: NOT_REACHED();
}
}
/**
* Calculate the net length of a string. This is in almost all cases
* just strlen(), but if the string is not properly terminated, we'll
@@ -1679,12 +1697,96 @@ static bool IsVariableSizeRight(const SaveLoad *sld)
#endif /* OTTD_ASSERT */
bool SlObjectMember(void *ptr, const SaveLoad *sld)
void SlFilterObject(const SaveLoad *sld, std::vector<SaveLoad> &save);
static void SlFilterObjectMember(const SaveLoad *sld, std::vector<SaveLoad> &save)
{
#ifdef OTTD_ASSERT
assert(IsVariableSizeRight(sld));
#endif
switch (sld->cmd) {
case SL_VAR:
case SL_REF:
case SL_ARR:
case SL_STR:
case SL_LST:
case SL_PTRDEQ:
case SL_VEC:
case SL_DEQUE:
case SL_STDSTR:
case SL_VARVEC:
/* CONDITIONAL saveload types depend on the savegame version */
if (!SlIsObjectValidInSavegame(sld)) return;
if (SlSkipVariableOnLoad(sld)) return;
switch (_sl.action) {
case SLA_SAVE:
case SLA_LOAD_CHECK:
case SLA_LOAD:
break;
case SLA_PTRS:
case SLA_NULL:
switch (sld->cmd) {
case SL_REF:
case SL_LST:
case SL_PTRDEQ:
case SL_VEC:
break;
/* non-ptr types do not require SLA_PTRS or SLA_NULL actions */
default:
return;
}
break;
default: NOT_REACHED();
}
save.push_back(*sld);
break;
/* SL_WRITEBYTE writes a value to the savegame to identify the type of an object.
* When loading, the value is read explictly with SlReadByte() to determine which
* object description to use. */
case SL_WRITEBYTE:
if (_sl.action == SLA_SAVE) save.push_back(*sld);
break;
/* SL_VEH_INCLUDE loads common code for vehicles */
case SL_VEH_INCLUDE:
SlFilterObject(GetVehicleDescription(VEH_END), save);
break;
case SL_ST_INCLUDE:
SlFilterObject(GetBaseStationDescription(), save);
break;
default: NOT_REACHED();
}
}
void SlFilterObject(const SaveLoad *sld, std::vector<SaveLoad> &save)
{
for (; sld->cmd != SL_END; sld++) {
SlFilterObjectMember(sld, save);
}
}
std::vector<SaveLoad> SlFilterObject(const SaveLoad *sld)
{
std::vector<SaveLoad> save;
SlFilterObject(sld, save);
save.push_back(SLE_END());
return save;
}
template <SaveLoadAction action, bool check_version>
bool SlObjectMemberGeneric(void *ptr, const SaveLoad *sld)
{
#ifdef OTTD_ASSERT
if (check_version) assert(IsVariableSizeRight(sld));
#endif
VarType conv = GB(sld->conv, 0, 8);
switch (sld->cmd) {
case SL_VAR:
@@ -1698,13 +1800,15 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
case SL_STDSTR:
case SL_VARVEC:
/* CONDITIONAL saveload types depend on the savegame version */
if (check_version) {
if (!SlIsObjectValidInSavegame(sld)) return false;
if (SlSkipVariableOnLoad(sld)) return false;
}
switch (sld->cmd) {
case SL_VAR: SlSaveLoadConv(ptr, conv); break;
case SL_VAR: SlSaveLoadConvGeneric<action>(ptr, conv); break;
case SL_REF: // Reference variable, translate
switch (_sl.action) {
switch (action) {
case SLA_SAVE:
SlWriteUint32((uint32)ReferenceToInt(*(void **)ptr, (SLRefType)conv));
break;
@@ -1747,7 +1851,7 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
* When loading, the value is read explictly with SlReadByte() to determine which
* object description to use. */
case SL_WRITEBYTE:
switch (_sl.action) {
switch (action) {
case SLA_SAVE: SlWriteByte(*(uint8 *)ptr); break;
case SLA_LOAD_CHECK:
case SLA_LOAD:
@@ -1771,6 +1875,22 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
return true;
}
bool SlObjectMember(void *ptr, const SaveLoad *sld)
{
switch (_sl.action) {
case SLA_SAVE:
return SlObjectMemberGeneric<SLA_SAVE, true>(ptr, sld);
case SLA_LOAD_CHECK:
case SLA_LOAD:
return SlObjectMemberGeneric<SLA_LOAD, true>(ptr, sld);
case SLA_PTRS:
return SlObjectMemberGeneric<SLA_PTRS, true>(ptr, sld);
case SLA_NULL:
return SlObjectMemberGeneric<SLA_NULL, true>(ptr, sld);
default: NOT_REACHED();
}
}
/**
* Main SaveLoad function.
* @param object The object that is being saved or loaded
@@ -1789,6 +1909,48 @@ void SlObject(void *object, const SaveLoad *sld)
}
}
template <SaveLoadAction action, bool check_version>
void SlObjectIterateBase(void *object, const SaveLoad *sld)
{
for (; sld->cmd != SL_END; sld++) {
void *ptr = sld->global ? sld->address : GetVariableAddress(object, sld);
SlObjectMemberGeneric<action, check_version>(ptr, sld);
}
}
void SlObjectSaveFiltered(void *object, const SaveLoad *sld)
{
if (_sl.need_length != NL_NONE) {
_sl.need_length = NL_NONE;
_sl.dumper->StartAutoLength();
SlObjectIterateBase<SLA_SAVE, false>(object, sld);
auto result = _sl.dumper->StopAutoLength();
_sl.need_length = NL_WANTLENGTH;
SlSetLength(result.second);
_sl.dumper->CopyBytes(result.first, result.second);
} else {
SlObjectIterateBase<SLA_SAVE, false>(object, sld);
}
}
void SlObjectLoadFiltered(void *object, const SaveLoad *sld)
{
SlObjectIterateBase<SLA_LOAD, false>(object, sld);
}
void SlObjectPtrOrNullFiltered(void *object, const SaveLoad *sld)
{
switch (_sl.action) {
case SLA_PTRS:
SlObjectIterateBase<SLA_PTRS, false>(object, sld);
return;
case SLA_NULL:
SlObjectIterateBase<SLA_NULL, false>(object, sld);
return;
default: NOT_REACHED();
}
}
/**
* Save or Load (a list of) global variables
* @param sldg The global variable that is being loaded or saved

View File

@@ -17,6 +17,7 @@
#include "extended_ver_sl.h"
#include <stdarg.h>
#include <vector>
/** SaveLoad versions
* Previous savegame versions, the trunk revision where they were
@@ -1024,6 +1025,12 @@ void SlGlobList(const SaveLoadGlobVarList *sldg);
void SlArray(void *array, size_t length, VarType conv);
void SlObject(void *object, const SaveLoad *sld);
bool SlObjectMember(void *object, const SaveLoad *sld);
std::vector<SaveLoad> SlFilterObject(const SaveLoad *sld);
void SlObjectSaveFiltered(void *object, const SaveLoad *sld);
void SlObjectLoadFiltered(void *object, const SaveLoad *sld);
void SlObjectPtrOrNullFiltered(void *object, const SaveLoad *sld);
void NORETURN SlError(StringID string, const char *extra_msg = nullptr, bool already_malloced = false);
void NORETURN SlErrorCorrupt(const char *msg, bool already_malloced = false);
void NORETURN CDECL SlErrorFmt(StringID string, const char *msg, ...) WARN_FORMAT(2, 3);

View File

@@ -489,10 +489,31 @@ const SaveLoad *GetBaseStationDescription()
return _base_station_desc;
}
std::vector<SaveLoad> _filtered_station_desc;
std::vector<SaveLoad> _filtered_waypoint_desc;
std::vector<SaveLoad> _filtered_goods_desc;
std::vector<SaveLoad> _filtered_station_speclist_desc;
static void SetupDescs_STNN()
{
_filtered_station_desc = SlFilterObject(_station_desc);
_filtered_waypoint_desc = SlFilterObject(_waypoint_desc);
_filtered_goods_desc = SlFilterObject(GetGoodsDesc());
_filtered_station_speclist_desc = SlFilterObject(_station_speclist_desc);
}
std::vector<SaveLoad> _filtered_roadstop_desc;
static void SetupDescs_ROADSTOP()
{
_filtered_roadstop_desc = SlFilterObject(_roadstop_desc);
}
static void RealSave_STNN(BaseStation *bst)
{
bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0;
SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
SlObjectSaveFiltered(bst, waypoint ? _filtered_waypoint_desc.data() : _filtered_station_desc.data());
MemoryDumper *dumper = MemoryDumper::GetCurrent();
@@ -504,7 +525,7 @@ static void RealSave_STNN(BaseStation *bst)
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], GetGoodsDesc());
SlObjectSaveFiltered(&st->goods[i], _filtered_goods_desc.data());
for (FlowStatMap::const_iterator outer_it(st->goods[i].flows.begin()); outer_it != st->goods[i].flows.end(); ++outer_it) {
const FlowStat::SharesMap *shares = outer_it->second.GetShares();
uint32 sum_shares = 0;
@@ -526,18 +547,20 @@ static void RealSave_STNN(BaseStation *bst)
}
}
for (StationCargoPacketMap::ConstMapIterator it(st->goods[i].cargo.Packets()->begin()); it != st->goods[i].cargo.Packets()->end(); ++it) {
SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc);
SlObjectSaveFiltered(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc); // _cargo_list_desc has no conditionals
}
}
}
for (uint i = 0; i < bst->num_specs; i++) {
SlObject(&bst->speclist[i], _station_speclist_desc);
SlObjectSaveFiltered(&bst->speclist[i], _filtered_station_speclist_desc.data());
}
}
static void Save_STNN()
{
SetupDescs_STNN();
BaseStation *st;
/* Write the stations */
FOR_ALL_BASE_STATIONS(st) {
@@ -548,6 +571,8 @@ static void Save_STNN()
static void Load_STNN()
{
SetupDescs_STNN();
_num_flows = 0;
const uint num_cargo = IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
@@ -558,7 +583,7 @@ static void Load_STNN()
bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
SlObjectLoadFiltered(bst, waypoint ? _filtered_waypoint_desc.data() : _filtered_station_desc.data());
if (!waypoint) {
Station *st = Station::From(bst);
@@ -572,7 +597,7 @@ static void Load_STNN()
}
for (CargoID i = 0; i < num_cargo; i++) {
SlObject(&st->goods[i], GetGoodsDesc());
SlObjectLoadFiltered(&st->goods[i], _filtered_goods_desc.data());
FlowSaveLoad flow;
FlowStat *fs = nullptr;
StationID prev_source = INVALID_STATION;
@@ -596,7 +621,7 @@ static void Load_STNN()
} else {
StationCargoPair pair;
for (uint j = 0; j < _num_dests; ++j) {
SlObject(&pair, _cargo_list_desc);
SlObjectLoadFiltered(&pair, _cargo_list_desc); // _cargo_list_desc has no conditionals
const_cast<StationCargoPacketMap &>(*(st->goods[i].cargo.Packets()))[pair.first].swap(pair.second);
assert(pair.second.empty());
}
@@ -609,7 +634,7 @@ static void Load_STNN()
/* 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], _station_speclist_desc);
SlObjectLoadFiltered(&bst->speclist[i], _filtered_station_speclist_desc.data());
}
}
}
@@ -620,6 +645,12 @@ static void Ptrs_STNN()
/* Don't run when savegame version lower than 123. */
if (IsSavegameVersionBefore(SLV_123)) return;
SetupDescs_STNN();
if (!IsSavegameVersionBefore(SLV_183)) {
assert(_filtered_goods_desc[0].cmd == SL_END);
}
uint num_cargo = IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
Station *st;
FOR_ALL_STATIONS(st) {
@@ -627,50 +658,51 @@ static void Ptrs_STNN()
GoodsEntry *ge = &st->goods[i];
if (IsSavegameVersionBefore(SLV_183)) {
SwapPackets(ge);
SlObject(ge, GetGoodsDesc());
SlObjectPtrOrNullFiltered(ge, _filtered_goods_desc.data());
SwapPackets(ge);
} else {
SlObject(ge, GetGoodsDesc());
//SlObject(ge, GetGoodsDesc());
for (StationCargoPacketMap::ConstMapIterator it = ge->cargo.Packets()->begin(); it != ge->cargo.Packets()->end(); ++it) {
SlObject(const_cast<StationCargoPair *>(&(*it)), _cargo_list_desc);
SlObjectPtrOrNullFiltered(const_cast<StationCargoPair *>(&(*it)), _cargo_list_desc); // _cargo_list_desc has no conditionals
}
}
}
SlObject(st, _station_desc);
SlObjectPtrOrNullFiltered(st, _filtered_station_desc.data());
}
Waypoint *wp;
FOR_ALL_WAYPOINTS(wp) {
SlObject(wp, _waypoint_desc);
SlObjectPtrOrNullFiltered(wp, _filtered_waypoint_desc.data());
}
}
static void Save_ROADSTOP()
{
SetupDescs_ROADSTOP();
RoadStop *rs;
FOR_ALL_ROADSTOPS(rs) {
SlSetArrayIndex(rs->index);
SlObject(rs, _roadstop_desc);
SlObjectSaveFiltered(rs, _filtered_roadstop_desc.data());
}
}
static void Load_ROADSTOP()
{
SetupDescs_ROADSTOP();
int index;
while ((index = SlIterateArray()) != -1) {
RoadStop *rs = new (index) RoadStop(INVALID_TILE);
SlObject(rs, _roadstop_desc);
SlObjectLoadFiltered(rs, _filtered_roadstop_desc.data());
}
}
static void Ptrs_ROADSTOP()
{
SetupDescs_ROADSTOP();
RoadStop *rs;
FOR_ALL_ROADSTOPS(rs) {
SlObject(rs, _roadstop_desc);
SlObjectPtrOrNullFiltered(rs, _filtered_roadstop_desc.data());
}
}

View File

@@ -239,6 +239,17 @@ static const SaveLoad _town_received_desc_spp[] = {
SLE_END()
};
std::vector<SaveLoad> _filtered_town_desc;
std::vector<SaveLoad> _filtered_town_supplied_desc;
std::vector<SaveLoad> _filtered_town_received_desc;
static void SetupDescs_TOWN()
{
_filtered_town_desc = SlFilterObject(_town_desc);
_filtered_town_supplied_desc = SlFilterObject(_town_supplied_desc);
_filtered_town_received_desc = SlFilterObject(_town_received_desc);
}
static void Save_HIDS()
{
Save_NewGRFMapping(_house_mngr);
@@ -264,22 +275,16 @@ const SaveLoad *GetTileMatrixDesc()
static void RealSave_Town(Town *t)
{
SlObject(t, _town_desc);
SlObjectSaveFiltered(t, _filtered_town_desc.data());
for (CargoID i = 0; i < NUM_CARGO; i++) {
SlObject(&t->supplied[i], _town_supplied_desc);
SlObjectSaveFiltered(&t->supplied[i], _filtered_town_supplied_desc.data());
}
if (SlXvIsFeaturePresent(XSLFI_SPRINGPP)) {
for (int i = TE_BEGIN; i < NUM_TE; i++) {
SlObject(&t->received[i], _town_received_desc_spp);
}
} else {
for (int i = TE_BEGIN; i < NUM_TE; i++) {
SlObject(&t->received[i], _town_received_desc);
}
SlObjectSaveFiltered(&t->received[i], _filtered_town_received_desc.data());
}
SlObject(&t->cargo_accepted, GetTileMatrixDesc());
SlObjectSaveFiltered(&t->cargo_accepted, GetTileMatrixDesc()); // GetTileMatrixDesc() has no conditionals
if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT64);
@@ -288,8 +293,8 @@ static void RealSave_Town(Town *t)
static void Save_TOWN()
{
SetupDescs_TOWN();
Town *t;
FOR_ALL_TOWNS(t) {
SlSetArrayIndex(t->index);
SlAutolength((AutolengthProc*)RealSave_Town, t);
@@ -298,15 +303,16 @@ static void Save_TOWN()
static void Load_TOWN()
{
SetupDescs_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);
SlObjectLoadFiltered(t, _filtered_town_desc.data());
for (CargoID i = 0; i < num_cargo; i++) {
SlObject(&t->supplied[i], _town_supplied_desc);
SlObjectLoadFiltered(&t->supplied[i], _filtered_town_supplied_desc.data());
}
if (SlXvIsFeaturePresent(XSLFI_SPRINGPP)) {
for (int i = TE_BEGIN; i < NUM_TE; i++) {
@@ -314,7 +320,7 @@ static void Load_TOWN()
}
} else {
for (int i = TE_BEGIN; i < NUM_TE; i++) {
SlObject(&t->received[i], _town_received_desc);
SlObjectLoadFiltered(&t->received[i], _filtered_town_received_desc.data());
}
}
@@ -331,7 +337,7 @@ static void Load_TOWN()
}
}
if (SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX)) {
SlObject(&t->cargo_accepted, GetTileMatrixDesc());
SlObjectLoadFiltered(&t->cargo_accepted, GetTileMatrixDesc()); // GetTileMatrixDesc() has no conditionals
if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
t->cargo_accepted.data = MallocT<CargoTypes>(arr_len);
@@ -349,9 +355,10 @@ static void Ptrs_TOWN()
/* Don't run when savegame version lower than 161. */
if (IsSavegameVersionBefore(SLV_161)) return;
SetupDescs_TOWN();
Town *t;
FOR_ALL_TOWNS(t) {
SlObject(t, _town_desc);
SlObjectPtrOrNullFiltered(t, _filtered_town_desc.data());
}
}

View File

@@ -951,20 +951,51 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
return _veh_descs[vt];
}
static std::vector<SaveLoad> _filtered_train_desc;
static std::vector<SaveLoad> _filtered_roadveh_desc;
static std::vector<SaveLoad> _filtered_ship_desc;
static std::vector<SaveLoad> _filtered_aircraft_desc;
static std::vector<SaveLoad> _filtered_special_desc;
static std::vector<SaveLoad> _filtered_disaster_desc;
static std::vector<SaveLoad> * const _filtered_veh_descs[] = {
&_filtered_train_desc,
&_filtered_roadveh_desc,
&_filtered_ship_desc,
&_filtered_aircraft_desc,
&_filtered_special_desc,
&_filtered_disaster_desc,
};
const SaveLoad *GetVehicleDescriptionFiltered(VehicleType vt)
{
return _filtered_veh_descs[vt]->data();
}
static void SetupDescs_VEHS()
{
for (size_t i = 0; i < lengthof(_filtered_veh_descs); i++) {
*(_filtered_veh_descs[i]) = SlFilterObject(GetVehicleDescription((VehicleType) i));
}
}
/** Will be called when the vehicles need to be saved. */
static void Save_VEHS()
{
SetupDescs_VEHS();
Vehicle *v;
/* Write the vehicles */
FOR_ALL_VEHICLES(v) {
SlSetArrayIndex(v->index);
SlObject(v, GetVehicleDescription(v->type));
SlObjectSaveFiltered(v, GetVehicleDescriptionFiltered(v->type));
}
}
/** Will be called when vehicles need to be loaded. */
void Load_VEHS()
{
SetupDescs_VEHS();
int index;
_cargo_count = 0;
@@ -984,7 +1015,7 @@ void Load_VEHS()
default: SlErrorCorrupt("Invalid vehicle type");
}
SlObject(v, GetVehicleDescription(vtype));
SlObjectLoadFiltered(v, GetVehicleDescriptionFiltered(vtype));
if (_cargo_count != 0 && IsCompanyBuildableVehicleType(v) && CargoPacket::CanAllocateItem()) {
/* Don't construct the packet with station here, because that'll fail with old savegames */
@@ -1013,9 +1044,11 @@ void Load_VEHS()
static void Ptrs_VEHS()
{
SetupDescs_VEHS();
Vehicle *v;
FOR_ALL_VEHICLES(v) {
SlObject(v, GetVehicleDescription(v->type));
SlObjectPtrOrNullFiltered(v, GetVehicleDescriptionFiltered(v->type));
}
}