Save/load: Pre-filter SaveLoad descriptor arrays for current version/mode, for chunks with many objects
This commit is contained in:
@@ -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.
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user