Move upstream saveload to src/saveload/, move jgrpp saveload to src/sl/
Leave afterload in src/saveload/
This commit is contained in:
@@ -20,6 +20,7 @@ add_subdirectory(network)
|
||||
add_subdirectory(os)
|
||||
add_subdirectory(pathfinder)
|
||||
add_subdirectory(saveload)
|
||||
add_subdirectory(sl)
|
||||
add_subdirectory(sound)
|
||||
add_subdirectory(spriteloader)
|
||||
add_subdirectory(table)
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include "vehicle_type.h"
|
||||
#include "company_type.h"
|
||||
#include "core/multimap.hpp"
|
||||
#include "saveload/saveload_common.h"
|
||||
#include "sl/saveload_common.h"
|
||||
#include <deque>
|
||||
|
||||
/** Unique identifier for a single cargo packet. */
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include "company_base.h"
|
||||
#include "company_func.h"
|
||||
#include "date_func.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "textbuf_gui.h"
|
||||
#include "window_gui.h"
|
||||
#include "string_func.h"
|
||||
|
@@ -12,7 +12,7 @@
|
||||
#include "debug.h"
|
||||
#include "engine_func.h"
|
||||
#include "landscape.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "network/core/game_info.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include "music/music_driver.hpp"
|
||||
#include "sound/sound_driver.hpp"
|
||||
#include "video/video_driver.hpp"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "screenshot.h"
|
||||
#include "gfx_func.h"
|
||||
#include "network/network.h"
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#include "vehicle_base.h"
|
||||
#include "rail_gui.h"
|
||||
#include "linkgraph/linkgraph.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "newgrf_profiling.h"
|
||||
#include "console_func.h"
|
||||
#include "debug.h"
|
||||
|
@@ -8,7 +8,7 @@
|
||||
/** @file fios_gui.cpp GUIs for loading/saving games, scenarios, heightmaps, ... */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "error.h"
|
||||
#include "gui.h"
|
||||
#include "gfx_func.h"
|
||||
|
@@ -8,7 +8,7 @@
|
||||
/** @file gamelog.cpp Definition of functions used for logging of important changes in the game */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "string_func.h"
|
||||
#include "settings_type.h"
|
||||
#include "gamelog_internal.h"
|
||||
|
@@ -21,7 +21,7 @@
|
||||
#include "water.h"
|
||||
#include "video/video_driver.hpp"
|
||||
#include "tilehighlight_func.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "void_map.h"
|
||||
#include "town.h"
|
||||
#include "newgrf.h"
|
||||
|
@@ -25,7 +25,7 @@
|
||||
#include "town.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "core/random_func.hpp"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "progress.h"
|
||||
#include "error.h"
|
||||
#include "newgrf_townname.h"
|
||||
|
@@ -12,7 +12,7 @@
|
||||
#include "clear_map.h"
|
||||
#include "void_map.h"
|
||||
#include "error.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "bmp.h"
|
||||
#include "gfx_func.h"
|
||||
#include "fios.h"
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "company_func.h"
|
||||
#include "tunnelbridge_map.h"
|
||||
#include "pathfinder/npf/aystar.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "framerate_type.h"
|
||||
#include "town.h"
|
||||
#include "3rdparty/cpp-btree/btree_set.h"
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#include "../station_base.h"
|
||||
#include "../cargotype.h"
|
||||
#include "../date_func.h"
|
||||
#include "../saveload/saveload_common.h"
|
||||
#include "../sl/saveload_common.h"
|
||||
#include "linkgraph_type.h"
|
||||
#include "../3rdparty/cpp-btree/btree_map.h"
|
||||
#include <utility>
|
||||
|
@@ -34,7 +34,7 @@
|
||||
#include "error.h"
|
||||
#include "news_gui.h"
|
||||
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
|
||||
#include "widgets/main_widget.h"
|
||||
|
||||
|
@@ -9,8 +9,8 @@
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "network_gui.h"
|
||||
#include "../saveload/saveload.h"
|
||||
#include "../saveload/saveload_filter.h"
|
||||
#include "../sl/saveload.h"
|
||||
#include "../sl/saveload_filter.h"
|
||||
#include "../command_func.h"
|
||||
#include "../console_func.h"
|
||||
#include "../strings_func.h"
|
||||
|
@@ -18,8 +18,8 @@
|
||||
#include "../console_func.h"
|
||||
#include "../company_base.h"
|
||||
#include "../command_func.h"
|
||||
#include "../saveload/saveload.h"
|
||||
#include "../saveload/saveload_filter.h"
|
||||
#include "../sl/saveload.h"
|
||||
#include "../sl/saveload_filter.h"
|
||||
#include "../station_base.h"
|
||||
#include "../genworld.h"
|
||||
#include "../company_func.h"
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include "gui.h"
|
||||
|
||||
#include "base_media_base.h"
|
||||
#include "saveload/saveload.h"
|
||||
#include "sl/saveload.h"
|
||||
#include "company_func.h"
|
||||
#include "command_func.h"
|
||||
#include "news_func.h"
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#include "vehicle_type.h"
|
||||
#include "base_consist.h"
|
||||
#include "order_base.h"
|
||||
#include "saveload/saveload_common.h"
|
||||
#include "sl/saveload_common.h"
|
||||
|
||||
/** Unique identifier for an order backup. */
|
||||
typedef uint8 OrderBackupID;
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include "date_type.h"
|
||||
#include "schdispatch.h"
|
||||
#include "gfx_type.h"
|
||||
#include "saveload/saveload_common.h"
|
||||
#include "sl/saveload_common.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include "../../crashlog.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../gamelog.h"
|
||||
#include "../../saveload/saveload.h"
|
||||
#include "../../sl/saveload.h"
|
||||
#include "../../thread.h"
|
||||
#include "../../screenshot.h"
|
||||
#include "../../debug.h"
|
||||
|
@@ -12,7 +12,7 @@
|
||||
#include "../../crashlog_bfd.h"
|
||||
#include "../../string_func.h"
|
||||
#include "../../gamelog.h"
|
||||
#include "../../saveload/saveload.h"
|
||||
#include "../../sl/saveload.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#include "../../fileio_func.h"
|
||||
#include "../../strings_func.h"
|
||||
#include "../../gamelog.h"
|
||||
#include "../../saveload/saveload.h"
|
||||
#include "../../sl/saveload.h"
|
||||
#include "../../video/video_driver.hpp"
|
||||
#include "../../screenshot.h"
|
||||
#include "../../debug.h"
|
||||
|
@@ -1,4 +1,4 @@
|
||||
add_subdirectory(upstream)
|
||||
add_subdirectory(compat)
|
||||
|
||||
add_files(
|
||||
afterload.cpp
|
||||
@@ -6,17 +6,13 @@ add_files(
|
||||
airport_sl.cpp
|
||||
animated_tile_sl.cpp
|
||||
autoreplace_sl.cpp
|
||||
bridge_signal_sl.cpp
|
||||
cargomonitor_sl.cpp
|
||||
cargopacket_sl.cpp
|
||||
cheat_sl.cpp
|
||||
company_sl.cpp
|
||||
debug_sl.cpp
|
||||
depot_sl.cpp
|
||||
economy_sl.cpp
|
||||
engine_sl.cpp
|
||||
extended_ver_sl.cpp
|
||||
extended_ver_sl.h
|
||||
game_sl.cpp
|
||||
gamelog_sl.cpp
|
||||
goal_sl.cpp
|
||||
@@ -29,33 +25,16 @@ add_files(
|
||||
misc_sl.cpp
|
||||
newgrf_sl.cpp
|
||||
newgrf_sl.h
|
||||
newsignals_sl.cpp
|
||||
object_sl.cpp
|
||||
oldloader.cpp
|
||||
oldloader.h
|
||||
oldloader_sl.cpp
|
||||
order_sl.cpp
|
||||
plans_sl.cpp
|
||||
saveload.cpp
|
||||
saveload.h
|
||||
saveload_buffer.h
|
||||
saveload_common.h
|
||||
saveload_filter.h
|
||||
saveload_internal.h
|
||||
saveload_types.h
|
||||
signal_sl.cpp
|
||||
settings_sl.cpp
|
||||
signs_sl.cpp
|
||||
station_sl.cpp
|
||||
storage_sl.cpp
|
||||
strings_sl.cpp
|
||||
story_sl.cpp
|
||||
subsidy_sl.cpp
|
||||
tbtr_template_replacement_sl.cpp
|
||||
tbtr_template_veh_sl.cpp
|
||||
town_sl.cpp
|
||||
tracerestrict_sl.cpp
|
||||
train_speed_adaptation.cpp
|
||||
tunnel_sl.cpp
|
||||
vehicle_sl.cpp
|
||||
waypoint_sl.cpp
|
||||
)
|
||||
|
@@ -75,7 +75,7 @@
|
||||
#include "../timer/timer_game_tick.h"
|
||||
|
||||
|
||||
#include "saveload_internal.h"
|
||||
#include "../sl/saveload_internal.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <algorithm>
|
||||
|
@@ -8,9 +8,12 @@
|
||||
/** @file ai_sl.cpp Handles the saveload part of the AIs */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../company_base.h"
|
||||
#include "../debug.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/ai_sl_compat.h"
|
||||
|
||||
#include "../company_base.h"
|
||||
#include "../string_func.h"
|
||||
|
||||
#include "../ai/ai.hpp"
|
||||
@@ -20,16 +23,18 @@
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static std::string _ai_saveload_name;
|
||||
static int _ai_saveload_version;
|
||||
static std::string _ai_saveload_settings;
|
||||
static bool _ai_saveload_is_random;
|
||||
|
||||
static const SaveLoad _ai_company[] = {
|
||||
SLEG_SSTR(_ai_saveload_name, SLE_STR),
|
||||
SLEG_SSTR(_ai_saveload_settings, SLE_STR),
|
||||
SLEG_CONDVAR(_ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR(_ai_saveload_is_random, SLE_BOOL, SLV_136, SL_MAX_VERSION),
|
||||
static const SaveLoad _ai_company_desc[] = {
|
||||
SLEG_SSTR("name", _ai_saveload_name, SLE_STR),
|
||||
SLEG_SSTR("settings", _ai_saveload_settings, SLE_STR),
|
||||
SLEG_CONDVAR("version", _ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("is_random", _ai_saveload_is_random, SLE_BOOL, SLV_136, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void SaveReal_AIPL(int *index_ptr)
|
||||
@@ -49,13 +54,18 @@ static void SaveReal_AIPL(int *index_ptr)
|
||||
_ai_saveload_is_random = config->IsRandom();
|
||||
_ai_saveload_settings = config->SettingsToString();
|
||||
|
||||
SlObject(nullptr, _ai_company);
|
||||
SlObject(nullptr, _ai_company_desc);
|
||||
/* If the AI was active, store its data too */
|
||||
if (Company::IsValidAiID(index)) AI::Save(index);
|
||||
}
|
||||
|
||||
static void Load_AIPL()
|
||||
{
|
||||
struct AIPLChunkHandler : ChunkHandler {
|
||||
AIPLChunkHandler() : ChunkHandler('AIPL', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_ai_company_desc, _ai_company_sl_compat);
|
||||
|
||||
/* Free all current data */
|
||||
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
|
||||
AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(nullptr);
|
||||
@@ -67,7 +77,7 @@ static void Load_AIPL()
|
||||
|
||||
_ai_saveload_is_random = false;
|
||||
_ai_saveload_version = -1;
|
||||
SlObject(nullptr, _ai_company);
|
||||
SlObject(nullptr, slt);
|
||||
|
||||
if (_game_mode == GM_MENU || (_networking && !_network_server)) {
|
||||
if (Company::IsValidAiID(index)) AIInstance::LoadEmpty();
|
||||
@@ -86,14 +96,14 @@ static void Load_AIPL()
|
||||
config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
if (_ai_saveload_name.compare("%_dummy") != 0) {
|
||||
DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version);
|
||||
DEBUG(script, 0, "The savegame has an AI by the name '%s', version %u which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version);
|
||||
DEBUG(script, 0, "A random other AI will be loaded in its place.");
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame had no AIs available at the time of saving.");
|
||||
DEBUG(script, 0, "A random available AI will be loaded now.");
|
||||
}
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version);
|
||||
DEBUG(script, 0, "The savegame has an AI by the name '%s', version %u which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version);
|
||||
DEBUG(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
|
||||
}
|
||||
/* Make sure the AI doesn't get the saveload data, as it was not the
|
||||
@@ -107,18 +117,24 @@ static void Load_AIPL()
|
||||
/* Load the AI saved data */
|
||||
if (Company::IsValidAiID(index)) config->SetToLoadData(AIInstance::Load(_ai_saveload_version));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_ai_company_desc);
|
||||
|
||||
static void Save_AIPL()
|
||||
{
|
||||
for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlAutolength((AutolengthProc *)SaveReal_AIPL, &i);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler ai_chunk_handlers[] = {
|
||||
{ 'AIPL', Save_AIPL, Load_AIPL, nullptr, nullptr, CH_ARRAY },
|
||||
static const AIPLChunkHandler AIPL;
|
||||
static const ChunkHandlerRef ai_chunk_handlers[] = {
|
||||
AIPL,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _ai_chunk_handlers(ai_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -14,29 +14,23 @@
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static void Save_APID()
|
||||
{
|
||||
Save_NewGRFMapping(_airport_mngr);
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
static void Load_APID()
|
||||
{
|
||||
Load_NewGRFMapping(_airport_mngr);
|
||||
}
|
||||
struct APIDChunkHandler : NewGRFMappingChunkHandler {
|
||||
APIDChunkHandler() : NewGRFMappingChunkHandler('APID', _airport_mngr) {}
|
||||
};
|
||||
|
||||
static void Save_ATID()
|
||||
{
|
||||
Save_NewGRFMapping(_airporttile_mngr);
|
||||
}
|
||||
struct ATIDChunkHandler : NewGRFMappingChunkHandler {
|
||||
ATIDChunkHandler() : NewGRFMappingChunkHandler('ATID', _airporttile_mngr) {}
|
||||
};
|
||||
|
||||
static void Load_ATID()
|
||||
{
|
||||
Load_NewGRFMapping(_airporttile_mngr);
|
||||
}
|
||||
|
||||
static const ChunkHandler airport_chunk_handlers[] = {
|
||||
{ 'ATID', Save_ATID, Load_ATID, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'APID', Save_APID, Load_APID, nullptr, nullptr, CH_ARRAY },
|
||||
static const ATIDChunkHandler ATID;
|
||||
static const APIDChunkHandler APID;
|
||||
static const ChunkHandlerRef airport_chunk_handlers[] = {
|
||||
ATID,
|
||||
APID,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _airport_chunk_handlers(airport_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,42 +8,41 @@
|
||||
/** @file animated_tile_sl.cpp Code handling saving and loading of animated tiles */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../animated_tile.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/animated_tile_sl_compat.h"
|
||||
|
||||
#include "../tile_type.h"
|
||||
#include "../animated_tile.h"
|
||||
#include "../core/alloc_func.hpp"
|
||||
#include "../core/smallvec_type.hpp"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Save the ANIT chunk.
|
||||
*/
|
||||
static void Save_ANIT()
|
||||
{
|
||||
uint count = 0;
|
||||
for (const auto &it : _animated_tiles) {
|
||||
if (!it.second.pending_deletion) count++;
|
||||
}
|
||||
SlSetLength(count * 5);
|
||||
for (const auto &it : _animated_tiles) {
|
||||
if (it.second.pending_deletion) continue;
|
||||
SlWriteUint32(it.first);
|
||||
SlWriteByte(it.second.speed);
|
||||
}
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
/**
|
||||
* Load the ANIT chunk; the chunk containing the animated tiles.
|
||||
*/
|
||||
static void Load_ANIT()
|
||||
{
|
||||
static std::vector <TileIndex> _tmp_animated_tiles;
|
||||
|
||||
static const SaveLoad _animated_tile_desc[] = {
|
||||
SLEG_VECTOR("tiles", _tmp_animated_tiles, SLE_UINT32),
|
||||
};
|
||||
|
||||
struct ANITChunkHandler : ChunkHandler {
|
||||
ANITChunkHandler() : ChunkHandler('ANIT', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
// removed
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
/* Before version 80 we did NOT have a variable length animated tile table */
|
||||
if (IsSavegameVersionBefore(SLV_80)) {
|
||||
/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
|
||||
TileIndex anim_list[256];
|
||||
SlArray(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
|
||||
SlCopy(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (anim_list[i] == 0) break;
|
||||
@@ -52,29 +51,34 @@ static void Load_ANIT()
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
|
||||
size_t count = SlGetFieldLength() / sizeof(uint32);
|
||||
_animated_tiles.clear();
|
||||
if (SlXvIsFeaturePresent(XSLFI_ANIMATED_TILE_EXTRA)) {
|
||||
uint count = (uint)SlGetFieldLength() / 5;
|
||||
for (uint i = 0; i < count; i++) {
|
||||
TileIndex tile = SlReadUint32();
|
||||
AnimatedTileInfo info = {};
|
||||
info.speed = SlReadByte();
|
||||
_animated_tiles[tile] = info;
|
||||
}
|
||||
} else {
|
||||
uint count = (uint)SlGetFieldLength() / 4;
|
||||
for (uint i = 0; i < count; i++) {
|
||||
_animated_tiles[SlReadUint32()] = {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Definition" imported by the saveload code to be able to load and save
|
||||
* the animated tile table.
|
||||
*/
|
||||
static const ChunkHandler animated_tile_chunk_handlers[] = {
|
||||
{ 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_RIFF },
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_animated_tile_desc, _animated_tile_sl_compat);
|
||||
|
||||
if (SlIterateArray() == -1) return;
|
||||
SlGlobList(slt);
|
||||
if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries");
|
||||
|
||||
for (TileIndex t : _tmp_animated_tiles) {
|
||||
_animated_tiles[t] = {};
|
||||
}
|
||||
_tmp_animated_tiles.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const ANITChunkHandler ANIT;
|
||||
static const ChunkHandlerRef animated_tile_chunk_handlers[] = {
|
||||
ANIT,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _animated_tile_chunk_handlers(animated_tile_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,12 +8,16 @@
|
||||
/** @file autoreplace_sl.cpp Code handling saving and loading of autoreplace rules */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../autoreplace_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/autoreplace_sl_compat.h"
|
||||
|
||||
#include "../autoreplace_base.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _engine_renew_desc[] = {
|
||||
SLE_VAR(EngineRenew, from, SLE_UINT16),
|
||||
SLE_VAR(EngineRenew, to, SLE_UINT16),
|
||||
@@ -23,21 +27,28 @@ static const SaveLoad _engine_renew_desc[] = {
|
||||
SLE_CONDVAR(EngineRenew, replace_when_old, SLE_BOOL, SLV_175, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_ERNW()
|
||||
{
|
||||
struct ERNWChunkHandler : ChunkHandler {
|
||||
ERNWChunkHandler() : ChunkHandler('ERNW', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_engine_renew_desc);
|
||||
|
||||
for (EngineRenew *er : EngineRenew::Iterate()) {
|
||||
SlSetArrayIndex(er->index);
|
||||
SlObject(er, _engine_renew_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_renew_desc, _engine_renew_sl_compat);
|
||||
|
||||
static void Load_ERNW()
|
||||
{
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
EngineRenew *er = new (index) EngineRenew();
|
||||
SlObject(er, _engine_renew_desc);
|
||||
SlObject(er, slt);
|
||||
|
||||
/* Advanced vehicle lists, ungrouped vehicles got added */
|
||||
if (IsSavegameVersionBefore(SLV_60)) {
|
||||
@@ -46,17 +57,21 @@ static void Load_ERNW()
|
||||
if (er->group_id == DEFAULT_GROUP) er->group_id = ALL_GROUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_ERNW()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (EngineRenew *er : EngineRenew::Iterate()) {
|
||||
SlObject(er, _engine_renew_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler autoreplace_chunk_handlers[] = {
|
||||
{ 'ERNW', Save_ERNW, Load_ERNW, Ptrs_ERNW, nullptr, CH_ARRAY },
|
||||
static const ERNWChunkHandler ERNW;
|
||||
static const ChunkHandlerRef autoreplace_chunk_handlers[] = {
|
||||
ERNW,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _autoreplace_chunk_handlers(autoreplace_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,12 +8,16 @@
|
||||
/** @file cargomonitor_sl.cpp Code handling saving and loading of Cargo monitoring. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../cargomonitor.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/cargomonitor_sl_compat.h"
|
||||
|
||||
#include "../cargomonitor.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/** Temporary storage of cargo monitoring data for loading or saving it. */
|
||||
struct TempStorage {
|
||||
CargoMonitorID number;
|
||||
@@ -41,9 +45,14 @@ static CargoMonitorID FixupCargoMonitor(CargoMonitorID number)
|
||||
return number;
|
||||
}
|
||||
|
||||
/** Save the #_cargo_deliveries monitoring map. */
|
||||
static void SaveDelivery()
|
||||
{
|
||||
/** #_cargo_deliveries monitoring map. */
|
||||
struct CMDLChunkHandler : ChunkHandler {
|
||||
CMDLChunkHandler() : ChunkHandler('CMDL', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cargomonitor_pair_desc);
|
||||
|
||||
TempStorage storage;
|
||||
|
||||
int i = 0;
|
||||
@@ -58,30 +67,36 @@ static void SaveDelivery()
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
|
||||
|
||||
/** Load the #_cargo_deliveries monitoring map. */
|
||||
static void LoadDelivery()
|
||||
{
|
||||
TempStorage storage;
|
||||
bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
|
||||
|
||||
ClearCargoDeliveryMonitoring();
|
||||
for (;;) {
|
||||
if (SlIterateArray() < 0) break;
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
SlObject(&storage, slt);
|
||||
|
||||
if (fix) storage.number = FixupCargoMonitor(storage.number);
|
||||
|
||||
std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
|
||||
_cargo_deliveries.insert(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** #_cargo_pickups monitoring map. */
|
||||
struct CMPUChunkHandler : ChunkHandler {
|
||||
CMPUChunkHandler() : ChunkHandler('CMPU', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cargomonitor_pair_desc);
|
||||
|
||||
/** Save the #_cargo_pickups monitoring map. */
|
||||
static void SavePickup()
|
||||
{
|
||||
TempStorage storage;
|
||||
|
||||
int i = 0;
|
||||
@@ -96,30 +111,36 @@ static void SavePickup()
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
|
||||
|
||||
/** Load the #_cargo_pickups monitoring map. */
|
||||
static void LoadPickup()
|
||||
{
|
||||
TempStorage storage;
|
||||
bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
|
||||
|
||||
ClearCargoPickupMonitoring();
|
||||
for (;;) {
|
||||
if (SlIterateArray() < 0) break;
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
SlObject(&storage, slt);
|
||||
|
||||
if (fix) storage.number = FixupCargoMonitor(storage.number);
|
||||
|
||||
std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
|
||||
_cargo_pickups.insert(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Chunk definition of the cargomonitoring maps. */
|
||||
static const ChunkHandler cargomonitor_chunk_handlers[] = {
|
||||
{ 'CMDL', SaveDelivery, LoadDelivery, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'CMPU', SavePickup, LoadPickup, nullptr, nullptr, CH_ARRAY },
|
||||
static const CMDLChunkHandler CMDL;
|
||||
static const CMPUChunkHandler CMPU;
|
||||
static const ChunkHandlerRef cargomonitor_chunk_handlers[] = {
|
||||
CMDL,
|
||||
CMPU,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _cargomonitor_chunk_handlers(cargomonitor_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,100 +8,16 @@
|
||||
/** @file cargopacket_sl.cpp Code handling saving and loading of cargo packets */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../vehicle_base.h"
|
||||
#include "../station_base.h"
|
||||
#include "../scope_info.h"
|
||||
#include "../3rdparty/cpp-btree/btree_map.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/cargopacket_sl_compat.h"
|
||||
|
||||
#include "../vehicle_base.h"
|
||||
#include "../station_base.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern btree::btree_map<uint64, Money> _cargo_packet_deferred_payments;
|
||||
|
||||
/**
|
||||
* Savegame conversion for cargopackets.
|
||||
*/
|
||||
/* static */ void CargoPacket::AfterLoad()
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_44)) {
|
||||
/* If we remove a station while cargo from it is still en route, payment calculation will assume
|
||||
* 0, 0 to be the source of the cargo, resulting in very high payments usually. v->source_xy
|
||||
* stores the coordinates, preserving them even if the station is removed. However, if a game is loaded
|
||||
* where this situation exists, the cargo-source information is lost. in this case, we set the source
|
||||
* to the current tile of the vehicle to prevent excessive profits
|
||||
*/
|
||||
for (const Vehicle *v : Vehicle::Iterate()) {
|
||||
const CargoPacketList *packets = v->cargo.Packets();
|
||||
for (VehicleCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
|
||||
CargoPacket *cp = *it;
|
||||
cp->source_xy = Station::IsValidID(cp->source) ? Station::Get(cp->source)->xy : v->tile;
|
||||
cp->loaded_at_xy = cp->source_xy;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store position of the station where the goods come from, so there
|
||||
* are no very high payments when stations get removed. However, if the
|
||||
* station where the goods came from is already removed, the source
|
||||
* information is lost. In that case we set it to the position of this
|
||||
* station */
|
||||
for (Station *st : Station::Iterate()) {
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
||||
GoodsEntry *ge = &st->goods[c];
|
||||
|
||||
const StationCargoPacketMap *packets = ge->cargo.Packets();
|
||||
for (StationCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
|
||||
CargoPacket *cp = *it;
|
||||
cp->source_xy = Station::IsValidID(cp->source) ? Station::Get(cp->source)->xy : st->xy;
|
||||
cp->loaded_at_xy = cp->source_xy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_120)) {
|
||||
/* CargoPacket's source should be either INVALID_STATION or a valid station */
|
||||
for (CargoPacket *cp : CargoPacket::Iterate()) {
|
||||
if (!Station::IsValidID(cp->source)) cp->source = INVALID_STATION;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_68)) {
|
||||
/* Only since version 68 we have cargo packets. Savegames from before used
|
||||
* 'new CargoPacket' + cargolist.Append so their caches are already
|
||||
* correct and do not need rebuilding. */
|
||||
for (Vehicle *v : Vehicle::Iterate()) v->cargo.InvalidateCache();
|
||||
|
||||
for (Station *st : Station::Iterate()) {
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_181)) {
|
||||
for (Vehicle *v : Vehicle::Iterate()) v->cargo.KeepAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Savegame conversion for cargopackets.
|
||||
*/
|
||||
/* static */ void CargoPacket::PostVehiclesAfterLoad()
|
||||
{
|
||||
if (SlXvIsFeaturePresent(XSLFI_CHILLPP)) {
|
||||
extern std::map<VehicleID, CargoPacketList> _veh_cpp_packets;
|
||||
for (auto &iter : _veh_cpp_packets) {
|
||||
if (iter.second.empty()) continue;
|
||||
Vehicle *v = Vehicle::Get(iter.first);
|
||||
Station *st = Station::Get(v->First()->last_station_visited);
|
||||
assert_msg(st != nullptr, "%s", scope_dumper().VehicleInfo(v));
|
||||
for (CargoPacket *cp : iter.second) {
|
||||
st->goods[v->cargo_type].cargo.AfterLoadIncreaseReservationCount(cp->count);
|
||||
v->cargo.Append(cp, VehicleCargoList::MTA_LOAD);
|
||||
}
|
||||
}
|
||||
_veh_cpp_packets.clear();
|
||||
}
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
/**
|
||||
* Wrapper function to get the CargoPacket's internal structure while
|
||||
@@ -115,81 +31,46 @@ SaveLoadTable GetCargoPacketDesc()
|
||||
SLE_VAR(CargoPacket, source_xy, SLE_UINT32),
|
||||
SLE_VAR(CargoPacket, loaded_at_xy, SLE_UINT32),
|
||||
SLE_VAR(CargoPacket, count, SLE_UINT16),
|
||||
SLE_CONDVAR_X(CargoPacket, days_in_transit, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_MORE_CARGO_AGE, 0, 0)),
|
||||
SLE_CONDVAR_X(CargoPacket, days_in_transit, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_MORE_CARGO_AGE)),
|
||||
SLE_CONDVAR(CargoPacket, days_in_transit, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_MORE_CARGO_AGE),
|
||||
SLE_CONDVAR(CargoPacket, days_in_transit, SLE_UINT16, SLV_MORE_CARGO_AGE, SL_MAX_VERSION),
|
||||
SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
|
||||
SLE_CONDVAR(CargoPacket, source_type, SLE_UINT8, SLV_125, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CargoPacket, source_id, SLE_UINT16, SLV_125, SL_MAX_VERSION),
|
||||
|
||||
/* Used to be paid_for, but that got changed. */
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_121),
|
||||
};
|
||||
return _cargopacket_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the cargo packets.
|
||||
*/
|
||||
static void Save_CAPA()
|
||||
{
|
||||
std::vector<SaveLoad> filtered_packet_desc = SlFilterObject(GetCargoPacketDesc());
|
||||
struct CAPAChunkHandler : ChunkHandler {
|
||||
CAPAChunkHandler() : ChunkHandler('CAPA', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(GetCargoPacketDesc());
|
||||
|
||||
for (CargoPacket *cp : CargoPacket::Iterate()) {
|
||||
SlSetArrayIndex(cp->index);
|
||||
SlObjectSaveFiltered(cp, filtered_packet_desc);
|
||||
SlObject(cp, GetCargoPacketDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the cargo packets.
|
||||
*/
|
||||
static void Load_CAPA()
|
||||
{
|
||||
std::vector<SaveLoad> filtered_packet_desc = SlFilterObject(GetCargoPacketDesc());
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
CargoPacket *cp = new (index) CargoPacket();
|
||||
SlObjectLoadFiltered(cp, filtered_packet_desc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save cargo packet deferred payments.
|
||||
*/
|
||||
void Save_CPDP()
|
||||
{
|
||||
SlSetLength(16 * _cargo_packet_deferred_payments.size());
|
||||
|
||||
for (auto &it : _cargo_packet_deferred_payments) {
|
||||
SlWriteUint64(it.first);
|
||||
SlWriteUint64(it.second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load cargo packet deferred payments.
|
||||
*/
|
||||
void Load_CPDP()
|
||||
{
|
||||
uint count = static_cast<uint>(SlGetFieldLength() / 16);
|
||||
uint last_cargo_packet_id = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
for (uint i = 0; i < count; i++) {
|
||||
uint64 k = SlReadUint64();
|
||||
uint64 v = SlReadUint64();
|
||||
_cargo_packet_deferred_payments[k] = v;
|
||||
if (k >> 32 != last_cargo_packet_id) {
|
||||
last_cargo_packet_id = k >> 32;
|
||||
CargoPacket::Get(last_cargo_packet_id)->flags |= CargoPacket::CPF_HAS_DEFERRED_PAYMENT;
|
||||
SlObject(cp, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Chunk handlers related to cargo packets. */
|
||||
static const ChunkHandler cargopacket_chunk_handlers[] = {
|
||||
{ 'CAPA', Save_CAPA, Load_CAPA, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'CPDP', Save_CPDP, Load_CPDP, nullptr, nullptr, CH_RIFF },
|
||||
static const CAPAChunkHandler CAPA;
|
||||
static const ChunkHandlerRef cargopacket_chunk_handlers[] = {
|
||||
CAPA,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _cargopacket_chunk_handlers(cargopacket_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,29 +8,15 @@
|
||||
/** @file cheat_sl.cpp Code handling saving and loading of cheats */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../cheat_type.h"
|
||||
#include "../debug.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/cheat_sl_compat.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "../cheat_type.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern std::map<std::string, Cheat> _unknown_cheats;
|
||||
|
||||
struct ExtraCheatNameDesc {
|
||||
const char *name;
|
||||
Cheat *cht;
|
||||
};
|
||||
|
||||
static ExtraCheatNameDesc _extra_cheat_descs[] = {
|
||||
{ "inflation_cost", &_extra_cheats.inflation_cost },
|
||||
{ "inflation_income", &_extra_cheats.inflation_income },
|
||||
{ "station_rating", &_extra_cheats.station_rating },
|
||||
{ "town_rating", &_extra_cheats.town_rating },
|
||||
};
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _cheats_desc[] = {
|
||||
SLE_VAR(Cheats, magic_bulldozer.been_used, SLE_BOOL),
|
||||
@@ -41,146 +27,60 @@ static const SaveLoad _cheats_desc[] = {
|
||||
SLE_VAR(Cheats, money.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, crossing_tunnels.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, crossing_tunnels.value, SLE_BOOL),
|
||||
SLE_NULL(1),
|
||||
SLE_NULL(1), // Needs to be two NULL fields. See Load_CHTS().
|
||||
SLE_VAR(Cheats, no_jetcrash.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, no_jetcrash.value, SLE_BOOL),
|
||||
SLE_NULL(1),
|
||||
SLE_NULL(1), // Needs to be two NULL fields. See Load_CHTS().
|
||||
SLE_VAR(Cheats, change_date.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, change_date.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, setup_prod.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, setup_prod.value, SLE_BOOL),
|
||||
SLE_NULL(1),
|
||||
SLE_NULL(1), // Needs to be two NULL fields. See Load_CHTS().
|
||||
SLE_VAR(Cheats, edit_max_hl.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, edit_max_hl.value, SLE_BOOL),
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the cheat values.
|
||||
*/
|
||||
static void Save_CHTS()
|
||||
{
|
||||
SlSetLength(std::size(_cheats_desc));
|
||||
SlObject(&_cheats, _cheats_desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the cheat values.
|
||||
*/
|
||||
static void Load_CHTS()
|
||||
{
|
||||
struct CHTSChunkHandler : ChunkHandler {
|
||||
CHTSChunkHandler() : ChunkHandler('CHTS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cheats_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlObject(&_cheats, _cheats_desc);
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::vector<SaveLoad> slt = SlCompatTableHeader(_cheats_desc, _cheats_sl_compat);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_TABLE_CHUNKS)) {
|
||||
size_t count = SlGetFieldLength();
|
||||
std::vector<SaveLoad> slt;
|
||||
std::vector<SaveLoad> oslt;
|
||||
|
||||
/* Cheats were added over the years without a savegame bump. They are
|
||||
* stored as 2 SLE_BOOLs per entry. "count" indicates how many SLE_BOOLs
|
||||
* are stored for this savegame. So read only "count" SLE_BOOLs (and in
|
||||
* result "count / 2" cheats). */
|
||||
for (auto &sld : _cheats_desc) {
|
||||
for (auto &sld : slt) {
|
||||
count--;
|
||||
slt.push_back(sld);
|
||||
oslt.push_back(sld);
|
||||
|
||||
if (count == 0) break;
|
||||
}
|
||||
slt = oslt;
|
||||
}
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlObject(&_cheats, slt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the extra cheat values.
|
||||
*/
|
||||
static void Load_CHTX()
|
||||
{
|
||||
struct CheatsExtLoad {
|
||||
char name[256];
|
||||
Cheat cht;
|
||||
};
|
||||
|
||||
static const SaveLoad _cheats_ext_load_desc[] = {
|
||||
SLE_STR(CheatsExtLoad, name, SLE_STRB, 256),
|
||||
SLE_VAR(CheatsExtLoad, cht.been_used, SLE_BOOL),
|
||||
SLE_VAR(CheatsExtLoad, cht.value, SLE_BOOL),
|
||||
};
|
||||
|
||||
CheatsExtLoad current_cheat;
|
||||
|
||||
uint32 chunk_flags = SlReadUint32();
|
||||
// flags are not in use yet, reserve for future expansion
|
||||
if (chunk_flags != 0) SlErrorCorruptFmt("CHTX chunk: unknown chunk header flags: 0x%X", chunk_flags);
|
||||
|
||||
uint32 cheat_count = SlReadUint32();
|
||||
for (uint32 i = 0; i < cheat_count; i++) {
|
||||
SlObject(¤t_cheat, _cheats_ext_load_desc);
|
||||
|
||||
bool found = false;
|
||||
for (uint j = 0; j < lengthof(_extra_cheat_descs); j++) {
|
||||
const ExtraCheatNameDesc &desc = _extra_cheat_descs[j];
|
||||
if (strcmp(desc.name, current_cheat.name) == 0) {
|
||||
*(desc.cht) = current_cheat.cht;
|
||||
found = true;
|
||||
break;
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many CHTS entries");
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
DEBUG(sl, 1, "CHTX chunk: Could not find cheat: '%s'", current_cheat.name);
|
||||
_unknown_cheats[current_cheat.name] = current_cheat.cht;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the extra cheat values.
|
||||
*/
|
||||
static void Save_CHTX()
|
||||
{
|
||||
struct CheatsExtSave {
|
||||
const char *name;
|
||||
Cheat cht;
|
||||
};
|
||||
|
||||
static const SaveLoad _cheats_ext_save_desc[] = {
|
||||
SLE_STR(CheatsExtSave, name, SLE_STR, 0),
|
||||
SLE_VAR(CheatsExtSave, cht.been_used, SLE_BOOL),
|
||||
SLE_VAR(CheatsExtSave, cht.value, SLE_BOOL),
|
||||
};
|
||||
|
||||
SlAutolength([](void *) {
|
||||
SlWriteUint32(0); // flags
|
||||
SlWriteUint32((uint32)(lengthof(_extra_cheat_descs) + _unknown_cheats.size())); // cheat count
|
||||
|
||||
for (uint j = 0; j < lengthof(_extra_cheat_descs); j++) {
|
||||
CheatsExtSave save = { _extra_cheat_descs[j].name, *(_extra_cheat_descs[j].cht) };
|
||||
SlObject(&save, _cheats_ext_save_desc);
|
||||
}
|
||||
for (const auto &iter : _unknown_cheats) {
|
||||
CheatsExtSave save = { iter.first.c_str(), iter.second };
|
||||
SlObject(&save, _cheats_ext_save_desc);
|
||||
}
|
||||
}, nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal structure used in SaveSettingsPatx() and SaveSettingsPlyx()
|
||||
*/
|
||||
struct SettingsExtSave {
|
||||
uint32 flags;
|
||||
const char *name;
|
||||
uint32 setting_length;
|
||||
};
|
||||
|
||||
static const SaveLoad _settings_ext_save_desc[] = {
|
||||
SLE_VAR(SettingsExtSave, flags, SLE_UINT32),
|
||||
SLE_STR(SettingsExtSave, name, SLE_STR, 0),
|
||||
SLE_VAR(SettingsExtSave, setting_length, SLE_UINT32),
|
||||
};
|
||||
|
||||
|
||||
/** Chunk handlers related to cheats. */
|
||||
static const ChunkHandler cheat_chunk_handlers[] = {
|
||||
{ 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_RIFF },
|
||||
{ 'CHTX', Save_CHTX, Load_CHTX, nullptr, nullptr, CH_RIFF },
|
||||
static const CHTSChunkHandler CHTS;
|
||||
static const ChunkHandlerRef cheat_chunk_handlers[] = {
|
||||
CHTS,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _cheat_chunk_handlers(cheat_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,241 +8,227 @@
|
||||
/** @file company_sl.cpp Code handling saving and loading of company data */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/company_sl_compat.h"
|
||||
|
||||
#include "../company_func.h"
|
||||
#include "../company_manager_face.h"
|
||||
#include "../fios.h"
|
||||
#include "../tunnelbridge_map.h"
|
||||
#include "../tunnelbridge.h"
|
||||
#include "../station_base.h"
|
||||
#include "../settings_func.h"
|
||||
#include "../strings_func.h"
|
||||
#include "../network/network.h"
|
||||
#include "../network/network_func.h"
|
||||
#include "../network/network_server.h"
|
||||
#include "../3rdparty/randombytes/randombytes.h"
|
||||
#include "../3rdparty/monocypher/monocypher.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "saveload_buffer.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/**
|
||||
* Converts an old company manager's face format to the new company manager's face format
|
||||
*
|
||||
* Meaning of the bits in the old face (some bits are used in several times):
|
||||
* - 4 and 5: chin
|
||||
* - 6 to 9: eyebrows
|
||||
* - 10 to 13: nose
|
||||
* - 13 to 15: lips (also moustache for males)
|
||||
* - 16 to 19: hair
|
||||
* - 20 to 22: eye colour
|
||||
* - 20 to 27: tie, ear rings etc.
|
||||
* - 28 to 30: glasses
|
||||
* - 19, 26 and 27: race (bit 27 set and bit 19 equal to bit 26 = black, otherwise white)
|
||||
* - 31: gender (0 = male, 1 = female)
|
||||
*
|
||||
* @param face the face in the old format
|
||||
* @return the face in the new format
|
||||
void SetDefaultCompanySettings(CompanyID cid);
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/* We do need to read this single value, as the bigger it gets, the more data is stored */
|
||||
struct CompanyOldAI {
|
||||
uint8 num_build_rec;
|
||||
};
|
||||
|
||||
class SlCompanyOldAIBuildRec : public DefaultSaveLoadHandler<SlCompanyOldAIBuildRec, CompanyOldAI> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {{}}; // Needed to keep DefaultSaveLoadHandler happy.
|
||||
inline const static SaveLoadCompatTable compat_description = _company_old_ai_buildrec_compat;
|
||||
|
||||
SaveLoadTable GetDescription() const override { return {}; }
|
||||
|
||||
void Load(CompanyOldAI *old_ai) const override
|
||||
{
|
||||
for (int i = 0; i != old_ai->num_build_rec; i++) {
|
||||
SlObject(nullptr, this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyOldAI *old_ai) const override { this->Load(old_ai); }
|
||||
};
|
||||
|
||||
class SlCompanyOldAI : public DefaultSaveLoadHandler<SlCompanyOldAI, CompanyProperties> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(CompanyOldAI, num_build_rec, SLE_UINT8, SL_MIN_VERSION, SLV_107),
|
||||
SLEG_STRUCTLIST("buildrec", SlCompanyOldAIBuildRec),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_old_ai_compat;
|
||||
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
if (!c->is_ai) return;
|
||||
|
||||
CompanyOldAI old_ai;
|
||||
SlObject(&old_ai, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
class SlCompanySettings : public DefaultSaveLoadHandler<SlCompanySettings, CompanyProperties> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
/* Engine renewal settings */
|
||||
SLE_CONDREF(CompanyProperties, engine_renew_list, REF_ENGINE_RENEWS, SLV_19, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.engine_renew, SLE_BOOL, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.engine_renew_months, SLE_INT16, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.engine_renew_money, SLE_UINT32, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.renew_keep_length, SLE_BOOL, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
/* Default vehicle settings */
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_ispercent, SLE_BOOL, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_trains, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_roadveh, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_aircraft, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_ships, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_settings_compat;
|
||||
|
||||
void Save(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(c, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(c, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void FixPointers(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(c, this->GetDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
class SlCompanyEconomy : public DefaultSaveLoadHandler<SlCompanyEconomy, CompanyProperties> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(CompanyEconomyEntry, income, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, income, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, SL_MIN_VERSION, SLV_170),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, SLV_170, SLV_EXTEND_CARGOTYPES),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||
SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_economy_compat;
|
||||
|
||||
void Save(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(&c->cur_economy, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(&c->cur_economy, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void FixPointers(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(&c->cur_economy, this->GetDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
class SlCompanyOldEconomy : public SlCompanyEconomy {
|
||||
public:
|
||||
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->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_liveries_compat;
|
||||
|
||||
/**
|
||||
* Get the number of liveries used by this savegame version.
|
||||
* @return The number of liveries used by this savegame version.
|
||||
*/
|
||||
CompanyManagerFace ConvertFromOldCompanyManagerFace(uint32 face)
|
||||
{
|
||||
CompanyManagerFace cmf = 0;
|
||||
GenderEthnicity ge = GE_WM;
|
||||
size_t GetNumLiveries() const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (HasBit(face, 31)) SetBit(ge, GENDER_FEMALE);
|
||||
if (HasBit(face, 27) && (HasBit(face, 26) == HasBit(face, 19))) SetBit(ge, ETHNICITY_BLACK);
|
||||
void Save(CompanyProperties *c) const override
|
||||
{
|
||||
SlSetStructListLength(LS_END);
|
||||
for (int i = 0; i < LS_END; i++) {
|
||||
SlObject(&c->livery[i], this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_GEN_ETHN, ge, ge);
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge, GB(face, 28, 3) <= 1);
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge, HasBit(ge, ETHNICITY_BLACK) ? 0 : ClampU(GB(face, 20, 3), 5, 7) - 5);
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_CHIN, ge, ScaleCompanyManagerFaceValue(CMFV_CHIN, ge, GB(face, 4, 2)));
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_EYEBROWS, ge, ScaleCompanyManagerFaceValue(CMFV_EYEBROWS, ge, GB(face, 6, 4)));
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_HAIR, ge, ScaleCompanyManagerFaceValue(CMFV_HAIR, ge, GB(face, 16, 4)));
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_JACKET, ge, ScaleCompanyManagerFaceValue(CMFV_JACKET, ge, GB(face, 20, 2)));
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_COLLAR, ge, ScaleCompanyManagerFaceValue(CMFV_COLLAR, ge, GB(face, 22, 2)));
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_GLASSES, ge, GB(face, 28, 1));
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
size_t num_liveries = this->GetNumLiveries();
|
||||
bool update_in_use = IsSavegameVersionBefore(SLV_GROUP_LIVERIES);
|
||||
|
||||
uint lips = GB(face, 10, 4);
|
||||
if (!HasBit(ge, GENDER_FEMALE) && lips < 4) {
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge, true);
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_MOUSTACHE, ge, std::max(lips, 1U) - 1);
|
||||
for (size_t i = 0; i < num_liveries; i++) {
|
||||
SlObject(&c->livery[i], this->GetLoadDescription());
|
||||
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 {
|
||||
if (!HasBit(ge, GENDER_FEMALE)) {
|
||||
lips = lips * 15 / 16;
|
||||
lips -= 3;
|
||||
if (HasBit(ge, ETHNICITY_BLACK) && lips > 8) lips = 0;
|
||||
} else {
|
||||
lips = ScaleCompanyManagerFaceValue(CMFV_LIPS, ge, lips);
|
||||
c->livery[i].in_use = 3;
|
||||
}
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_LIPS, ge, lips);
|
||||
|
||||
uint nose = GB(face, 13, 3);
|
||||
if (ge == GE_WF) {
|
||||
nose = (nose * 3 >> 3) * 3 >> 2; // There is 'hole' in the nose sprites for females
|
||||
} else {
|
||||
nose = ScaleCompanyManagerFaceValue(CMFV_NOSE, ge, nose);
|
||||
}
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_NOSE, ge, nose);
|
||||
}
|
||||
|
||||
uint tie_earring = GB(face, 24, 4);
|
||||
if (!HasBit(ge, GENDER_FEMALE) || tie_earring < 3) { // Not all females have an earring
|
||||
if (HasBit(ge, GENDER_FEMALE)) SetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge, true);
|
||||
SetCompanyManagerFaceBits(cmf, CMFV_TIE_EARRING, ge, HasBit(ge, GENDER_FEMALE) ? tie_earring : ScaleCompanyManagerFaceValue(CMFV_TIE_EARRING, ge, tie_earring / 2));
|
||||
}
|
||||
|
||||
return cmf;
|
||||
}
|
||||
|
||||
/** Rebuilding of company statistics after loading a savegame. */
|
||||
void AfterLoadCompanyStats()
|
||||
{
|
||||
/* Reset infrastructure statistics to zero. */
|
||||
for (Company *c : Company::Iterate()) MemSetT(&c->infrastructure, 0);
|
||||
|
||||
/* Collect airport count. */
|
||||
for (const Station *st : Station::Iterate()) {
|
||||
if ((st->facilities & FACIL_AIRPORT) && Company::IsValidID(st->owner)) {
|
||||
Company::Get(st->owner)->infrastructure.airport++;
|
||||
}
|
||||
}
|
||||
|
||||
Company *c;
|
||||
for (TileIndex tile = 0; tile < MapSize(); tile++) {
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_RAILWAY:
|
||||
c = Company::GetIfValid(GetTileOwner(tile));
|
||||
if (c != nullptr) {
|
||||
uint pieces = 1;
|
||||
if (IsPlainRail(tile)) {
|
||||
TrackBits bits = GetTrackBits(tile);
|
||||
if (bits == TRACK_BIT_HORZ || bits == TRACK_BIT_VERT) {
|
||||
c->infrastructure.rail[GetSecondaryRailType(tile)]++;
|
||||
} else {
|
||||
pieces = CountBits(bits);
|
||||
if (TracksOverlap(bits)) pieces *= pieces;
|
||||
}
|
||||
}
|
||||
c->infrastructure.rail[GetRailType(tile)] += pieces;
|
||||
|
||||
if (HasSignals(tile)) c->infrastructure.signal += CountBits(GetPresentSignals(tile));
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_ROAD: {
|
||||
if (IsLevelCrossing(tile)) {
|
||||
c = Company::GetIfValid(GetTileOwner(tile));
|
||||
if (c != nullptr) c->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR;
|
||||
if (IsSavegameVersionBefore(SLV_85)) {
|
||||
/* We want to insert some liveries somewhere in between. This means some have to be moved. */
|
||||
memmove(&c->livery[LS_FREIGHT_WAGON], &c->livery[LS_PASSENGER_WAGON_MONORAIL], (LS_END - LS_FREIGHT_WAGON) * sizeof(c->livery[0]));
|
||||
c->livery[LS_PASSENGER_WAGON_MONORAIL] = c->livery[LS_MONORAIL];
|
||||
c->livery[LS_PASSENGER_WAGON_MAGLEV] = c->livery[LS_MAGLEV];
|
||||
}
|
||||
|
||||
/* Iterate all present road types as each can have a different owner. */
|
||||
for (RoadTramType rtt : _roadtramtypes) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt == INVALID_ROADTYPE) continue;
|
||||
c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt));
|
||||
/* A level crossings and depots have two road bits. */
|
||||
if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rtt)) : 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_STATION:
|
||||
c = Company::GetIfValid(GetTileOwner(tile));
|
||||
if (c != nullptr && GetStationType(tile) != STATION_AIRPORT && !IsBuoy(tile)) c->infrastructure.station++;
|
||||
|
||||
switch (GetStationType(tile)) {
|
||||
case STATION_RAIL:
|
||||
case STATION_WAYPOINT:
|
||||
if (c != nullptr && !IsStationTileBlocked(tile)) c->infrastructure.rail[GetRailType(tile)]++;
|
||||
break;
|
||||
|
||||
case STATION_BUS:
|
||||
case STATION_TRUCK:
|
||||
case STATION_ROADWAYPOINT: {
|
||||
/* Iterate all present road types as each can have a different owner. */
|
||||
for (RoadTramType rtt : _roadtramtypes) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt == INVALID_ROADTYPE) continue;
|
||||
c = Company::GetIfValid(GetRoadOwner(tile, rtt));
|
||||
if (c != nullptr) c->infrastructure.road[rt] += 2; // A road stop has two road bits.
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case STATION_DOCK:
|
||||
case STATION_BUOY:
|
||||
if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
|
||||
if (c != nullptr) c->infrastructure.water++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_WATER:
|
||||
if (IsShipDepot(tile) || IsLock(tile)) {
|
||||
c = Company::GetIfValid(GetTileOwner(tile));
|
||||
if (c != nullptr) {
|
||||
if (IsShipDepot(tile)) c->infrastructure.water += LOCK_DEPOT_TILE_FACTOR;
|
||||
if (IsLock(tile) && GetLockPart(tile) == LOCK_PART_MIDDLE) {
|
||||
/* The middle tile specifies the owner of the lock. */
|
||||
c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // the middle tile specifies the owner of the
|
||||
break; // do not count the middle tile as canal
|
||||
if (IsSavegameVersionBefore(SLV_63)) {
|
||||
/* 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
FALLTHROUGH;
|
||||
|
||||
case MP_OBJECT:
|
||||
if (GetWaterClass(tile) == WATER_CLASS_CANAL) {
|
||||
c = Company::GetIfValid(GetTileOwner(tile));
|
||||
if (c != nullptr) c->infrastructure.water++;
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_TUNNELBRIDGE: {
|
||||
/* Only count the tunnel/bridge if we're on the western end tile. */
|
||||
if (GetTunnelBridgeDirection(tile) < DIAGDIR_SW) {
|
||||
TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
|
||||
|
||||
/* Count each tunnel/bridge TUNNELBRIDGE_TRACKBIT_FACTOR times to simulate
|
||||
* the higher structural maintenance needs, and don't forget the end tiles. */
|
||||
const uint middle_len = GetTunnelBridgeLength(tile, other_end) * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
|
||||
switch (GetTunnelBridgeTransportType(tile)) {
|
||||
case TRANSPORT_RAIL:
|
||||
AddRailTunnelBridgeInfrastructure(tile, other_end);
|
||||
break;
|
||||
|
||||
case TRANSPORT_ROAD: {
|
||||
AddRoadTunnelBridgeInfrastructure(tile, other_end);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_WATER:
|
||||
c = Company::GetIfValid(GetTileOwner(tile));
|
||||
if (c != nullptr) c->infrastructure.water += middle_len + (2 * TUNNELBRIDGE_TRACKBIT_FACTOR);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
/* Save/load of companies */
|
||||
static const SaveLoad _company_desc[] = {
|
||||
@@ -265,11 +251,8 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
SLE_VAR(CompanyProperties, colour, SLE_UINT8),
|
||||
SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_58), ///< avail_railtypes
|
||||
SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_94), ///< cargo_types
|
||||
SLE_CONDNULL(4, SLV_94, SLV_170), ///< cargo_types
|
||||
SLE_CONDVAR(CompanyProperties, location_of_HQ, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDVAR(CompanyProperties, location_of_HQ, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, last_build_coordinate, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
@@ -279,11 +262,9 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
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_X(CompanyProperties, bankrupt_last_asked, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BANKRUPTCY_EXTRA)),
|
||||
SLE_CONDVAR_X(CompanyProperties, bankrupt_flags, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BANKRUPTCY_EXTRA, 2)),
|
||||
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),
|
||||
@@ -292,232 +273,55 @@ static const SaveLoad _company_desc[] = {
|
||||
|
||||
/* yearly expenses was changed to 64-bit in savegame version 2. */
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDARR_X(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 13, SLV_2, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_INFRA_SHARING, 0, 0)),
|
||||
SLE_CONDARR_X(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 15, SLV_2, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_INFRA_SHARING)),
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 13, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, is_ai, SLE_BOOL, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(1, SLV_107, SLV_112), ///< is_noai
|
||||
SLE_CONDNULL(1, SLV_4, SLV_100),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, terraform_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, clear_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, tree_limit, SLE_UINT32, SLV_175, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(CompanyProperties, purchase_land_limit, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BUY_LAND_RATE_LIMIT)),
|
||||
SLE_CONDVAR_X(CompanyProperties, build_object_limit, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BUILD_OBJECT_RATE_LIMIT)),
|
||||
SLEG_STRUCT("settings", SlCompanySettings),
|
||||
SLEG_CONDSTRUCT("old_ai", SlCompanyOldAI, SL_MIN_VERSION, SLV_107),
|
||||
SLEG_STRUCT("cur_economy", SlCompanyEconomy),
|
||||
SLEG_STRUCTLIST("old_economy", SlCompanyOldEconomy),
|
||||
SLEG_CONDSTRUCTLIST("liveries", SlCompanyLiveries, SLV_34, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static const SaveLoad _company_settings_desc[] = {
|
||||
/* Engine renewal settings */
|
||||
SLE_CONDNULL(512, SLV_16, SLV_19),
|
||||
SLE_CONDREF(Company, engine_renew_list, REF_ENGINE_RENEWS, SLV_19, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.engine_renew, SLE_BOOL, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.engine_renew_months, SLE_INT16, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.engine_renew_money, SLE_UINT32, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.renew_keep_length, SLE_BOOL, SLV_2, SL_MAX_VERSION),
|
||||
struct PLYRChunkHandler : ChunkHandler {
|
||||
PLYRChunkHandler() : ChunkHandler('PLYR', CH_TABLE) {}
|
||||
|
||||
/* Default vehicle settings */
|
||||
SLE_CONDVAR(Company, settings.vehicle.servint_ispercent, SLE_BOOL, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.vehicle.servint_trains, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.vehicle.servint_roadveh, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.vehicle.servint_aircraft, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Company, settings.vehicle.servint_ships, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(Company, settings.vehicle.auto_timetable_by_default, SLE_BOOL, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AUTO_TIMETABLE, 2, 2)),
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_company_desc);
|
||||
|
||||
SLE_CONDNULL(63, SLV_2, SLV_144), // old reserved space
|
||||
};
|
||||
|
||||
static const SaveLoad _company_settings_skip_desc[] = {
|
||||
/* Engine renewal settings */
|
||||
SLE_CONDNULL(512, SLV_16, SLV_19),
|
||||
SLE_CONDNULL(2, SLV_19, SLV_69), // engine_renew_list
|
||||
SLE_CONDNULL(4, SLV_69, SL_MAX_VERSION), // engine_renew_list
|
||||
SLE_CONDNULL(1, SLV_16, SL_MAX_VERSION), // settings.engine_renew
|
||||
SLE_CONDNULL(2, SLV_16, SL_MAX_VERSION), // settings.engine_renew_months
|
||||
SLE_CONDNULL(4, SLV_16, SL_MAX_VERSION), // settings.engine_renew_money
|
||||
SLE_CONDNULL(1, SLV_2, SL_MAX_VERSION), // settings.renew_keep_length
|
||||
|
||||
/* Default vehicle settings */
|
||||
SLE_CONDNULL(1, SLV_120, SL_MAX_VERSION), // settings.vehicle.servint_ispercent
|
||||
SLE_CONDNULL(2, SLV_120, SL_MAX_VERSION), // settings.vehicle.servint_trains
|
||||
SLE_CONDNULL(2, SLV_120, SL_MAX_VERSION), // settings.vehicle.servint_roadveh
|
||||
SLE_CONDNULL(2, SLV_120, SL_MAX_VERSION), // settings.vehicle.servint_aircraft
|
||||
SLE_CONDNULL(2, SLV_120, SL_MAX_VERSION), // settings.vehicle.servint_ships
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AUTO_TIMETABLE, 2, 2)), // settings.vehicle.auto_timetable_by_default
|
||||
|
||||
SLE_CONDNULL(63, SLV_2, SLV_144), // old reserved space
|
||||
};
|
||||
|
||||
static const SaveLoad _company_economy_desc[] = {
|
||||
/* these were changed to 64-bit in savegame format 2 */
|
||||
SLE_CONDVAR(CompanyEconomyEntry, income, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, income, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, SL_MIN_VERSION, SLV_170),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, SLV_170, SLV_EXTEND_CARGOTYPES),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||
SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32),
|
||||
};
|
||||
|
||||
/* We do need to read this single value, as the bigger it gets, the more data is stored */
|
||||
struct CompanyOldAI {
|
||||
uint8 num_build_rec;
|
||||
};
|
||||
|
||||
static const SaveLoad _company_ai_desc[] = {
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_107),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_13),
|
||||
SLE_CONDNULL(4, SLV_13, SLV_107),
|
||||
SLE_CONDNULL(8, SL_MIN_VERSION, SLV_107),
|
||||
SLE_CONDVAR(CompanyOldAI, num_build_rec, SLE_UINT8, SL_MIN_VERSION, SLV_107),
|
||||
SLE_CONDNULL(3, SL_MIN_VERSION, SLV_107),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDNULL(4, SLV_6, SLV_107),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDNULL(4, SLV_6, SLV_107),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_107),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDNULL(4, SLV_6, SLV_107),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDNULL(4, SLV_6, SLV_107),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_107),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_69),
|
||||
SLE_CONDNULL(4, SLV_69, SLV_107),
|
||||
|
||||
SLE_CONDNULL(18, SL_MIN_VERSION, SLV_107),
|
||||
SLE_CONDNULL(20, SL_MIN_VERSION, SLV_107),
|
||||
SLE_CONDNULL(32, SL_MIN_VERSION, SLV_107),
|
||||
|
||||
SLE_CONDNULL(64, SLV_2, SLV_107),
|
||||
};
|
||||
|
||||
static const SaveLoad _company_ai_build_rec_desc[] = {
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDNULL(4, SLV_6, SLV_107),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDNULL(4, SLV_6, SLV_107),
|
||||
SLE_CONDNULL(8, SL_MIN_VERSION, SLV_107),
|
||||
};
|
||||
|
||||
static const SaveLoad _company_livery_desc[] = {
|
||||
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),
|
||||
};
|
||||
|
||||
static void SaveLoad_PLYR_common(Company *c, CompanyProperties *cprops)
|
||||
{
|
||||
int i;
|
||||
|
||||
SlObject(cprops, _company_desc);
|
||||
if (c != nullptr) {
|
||||
SlObject(c, _company_settings_desc);
|
||||
} else {
|
||||
char nothing;
|
||||
SlObject(¬hing, _company_settings_skip_desc);
|
||||
}
|
||||
|
||||
/* Keep backwards compatible for savegames, so load the old AI block */
|
||||
if (IsSavegameVersionBefore(SLV_107) && cprops->is_ai) {
|
||||
CompanyOldAI old_ai;
|
||||
char nothing;
|
||||
|
||||
SlObject(&old_ai, _company_ai_desc);
|
||||
for (i = 0; i != old_ai.num_build_rec; i++) {
|
||||
SlObject(¬hing, _company_ai_build_rec_desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write economy */
|
||||
SlObject(&cprops->cur_economy, _company_economy_desc);
|
||||
|
||||
/* Write old economy entries. */
|
||||
if (cprops->num_valid_stat_ent > lengthof(cprops->old_economy)) SlErrorCorrupt("Too many old economy entries");
|
||||
for (i = 0; i < cprops->num_valid_stat_ent; i++) {
|
||||
SlObject(&cprops->old_economy[i], _company_economy_desc);
|
||||
}
|
||||
|
||||
/* Write each livery entry. */
|
||||
int num_liveries = IsSavegameVersionBefore(SLV_63) ? LS_END - 4 : (IsSavegameVersionBefore(SLV_85) ? LS_END - 2: LS_END);
|
||||
bool update_in_use = IsSavegameVersionBefore(SLV_GROUP_LIVERIES);
|
||||
if (c != nullptr) {
|
||||
for (i = 0; i < num_liveries; i++) {
|
||||
SlObject(&c->livery[i], _company_livery_desc);
|
||||
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 {
|
||||
c->livery[i].in_use = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_liveries < LS_END) {
|
||||
/* We want to insert some liveries somewhere in between. This means some have to be moved. */
|
||||
memmove(&c->livery[LS_FREIGHT_WAGON], &c->livery[LS_PASSENGER_WAGON_MONORAIL], (LS_END - LS_FREIGHT_WAGON) * sizeof(c->livery[0]));
|
||||
c->livery[LS_PASSENGER_WAGON_MONORAIL] = c->livery[LS_MONORAIL];
|
||||
c->livery[LS_PASSENGER_WAGON_MAGLEV] = c->livery[LS_MAGLEV];
|
||||
}
|
||||
|
||||
if (num_liveries == LS_END - 4) {
|
||||
/* 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];
|
||||
}
|
||||
} else {
|
||||
/* Skip liveries */
|
||||
Livery dummy_livery;
|
||||
for (i = 0; i < num_liveries; i++) {
|
||||
SlObject(&dummy_livery, _company_livery_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SaveLoad_PLYR(Company *c)
|
||||
{
|
||||
SaveLoad_PLYR_common(c, c);
|
||||
}
|
||||
|
||||
static void Save_PLYR()
|
||||
{
|
||||
for (Company *c : Company::Iterate()) {
|
||||
SlSetArrayIndex(c->index);
|
||||
SlAutolength((AutolengthProc*)SaveLoad_PLYR, c);
|
||||
SlObject(c, _company_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_PLYR()
|
||||
{
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Company *c = new (index) Company();
|
||||
SetDefaultCompanySettings(c->index);
|
||||
SaveLoad_PLYR(c);
|
||||
SlObject((CompanyProperties *)c, slt);
|
||||
_company_colours[index] = (Colours)c->colour;
|
||||
}
|
||||
}
|
||||
|
||||
// settings moved from game settings to company settings
|
||||
if (SlXvIsFeaturePresent(XSLFI_AUTO_TIMETABLE, 1, 2)) {
|
||||
c->settings.auto_timetable_separation_rate = _settings_game.order.old_timetable_separation_rate;
|
||||
}
|
||||
if (SlXvIsFeaturePresent(XSLFI_AUTO_TIMETABLE, 1, 3)) {
|
||||
c->settings.vehicle.auto_separation_by_default = _settings_game.order.old_timetable_separation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Check_PLYR()
|
||||
{
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
CompanyProperties *cprops = new CompanyProperties();
|
||||
SaveLoad_PLYR_common(nullptr, cprops);
|
||||
SlObject(cprops, slt);
|
||||
|
||||
/* We do not load old custom names */
|
||||
if (IsSavegameVersionBefore(SLV_84)) {
|
||||
@@ -539,165 +343,21 @@ static void Check_PLYR()
|
||||
|
||||
if (!_load_check_data.companies.Insert(index, cprops)) delete cprops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_PLYR()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (Company *c : Company::Iterate()) {
|
||||
SlObject(c, _company_settings_desc);
|
||||
}
|
||||
}
|
||||
|
||||
extern void LoadSettingsPlyx(bool skip);
|
||||
extern void SaveSettingsPlyx();
|
||||
|
||||
static void Load_PLYX()
|
||||
{
|
||||
LoadSettingsPlyx(false);
|
||||
}
|
||||
|
||||
static void Check_PLYX()
|
||||
{
|
||||
LoadSettingsPlyx(true);
|
||||
}
|
||||
|
||||
static void Save_PLYX()
|
||||
{
|
||||
SaveSettingsPlyx();
|
||||
}
|
||||
|
||||
static void Load_PLYP()
|
||||
{
|
||||
size_t size = SlGetFieldLength();
|
||||
CompanyMask invalid_mask = 0;
|
||||
if (SlXvIsFeaturePresent(XSLFI_COMPANY_PW, 2)) {
|
||||
if (size <= 2) return;
|
||||
invalid_mask = SlReadUint16();
|
||||
size -= 2;
|
||||
}
|
||||
if (size <= 16 + 24 + 16 || (_networking && !_network_server)) {
|
||||
SlSkipBytes(size);
|
||||
return;
|
||||
}
|
||||
if (!_network_server) {
|
||||
extern CompanyMask _saved_PLYP_invalid_mask;
|
||||
extern std::vector<uint8> _saved_PLYP_data;
|
||||
|
||||
_saved_PLYP_invalid_mask = invalid_mask;
|
||||
_saved_PLYP_data.resize(size);
|
||||
ReadBuffer::GetCurrent()->CopyBytes(_saved_PLYP_data.data(), _saved_PLYP_data.size());
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 token[16];
|
||||
ReadBuffer::GetCurrent()->CopyBytes(token, 16);
|
||||
if (memcmp(token, _network_company_password_storage_token, 16) != 0) {
|
||||
DEBUG(sl, 2, "Skipping encrypted company passwords");
|
||||
SlSkipBytes(size - 16);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 nonce[24];
|
||||
uint8 mac[16];
|
||||
ReadBuffer::GetCurrent()->CopyBytes(nonce, 24);
|
||||
ReadBuffer::GetCurrent()->CopyBytes(mac, 16);
|
||||
|
||||
std::vector<uint8> buffer(size - 16 - 24 - 16);
|
||||
ReadBuffer::GetCurrent()->CopyBytes(buffer.data(), buffer.size());
|
||||
|
||||
if (crypto_unlock(buffer.data(), _network_company_password_storage_key, nonce, mac, buffer.data(), buffer.size()) == 0) {
|
||||
SlLoadFromBuffer(buffer.data(), buffer.size(), [invalid_mask]() {
|
||||
_network_company_server_id.resize(SlReadUint32());
|
||||
ReadBuffer::GetCurrent()->CopyBytes((uint8 *)_network_company_server_id.data(), _network_company_server_id.size());
|
||||
|
||||
while (true) {
|
||||
uint16 cid = SlReadUint16();
|
||||
if (cid >= MAX_COMPANIES) break;
|
||||
std::string password;
|
||||
password.resize(SlReadUint32());
|
||||
ReadBuffer::GetCurrent()->CopyBytes((uint8 *)password.data(), password.size());
|
||||
if (!HasBit(invalid_mask, cid)) {
|
||||
NetworkServerSetCompanyPassword((CompanyID)cid, password, true);
|
||||
SlObject((CompanyProperties *)c, _company_desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ReadBuffer::GetCurrent()->SkipBytes(SlReadByte()); // Skip padding
|
||||
});
|
||||
DEBUG(sl, 2, "Decrypted company passwords");
|
||||
} else {
|
||||
DEBUG(sl, 2, "Failed to decrypt company passwords");
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_PLYP()
|
||||
{
|
||||
if ((_networking && !_network_server) || IsNetworkServerSave()) {
|
||||
SlSetLength(0);
|
||||
return;
|
||||
}
|
||||
if (!_network_server) {
|
||||
extern CompanyMask _saved_PLYP_invalid_mask;
|
||||
extern std::vector<uint8> _saved_PLYP_data;
|
||||
|
||||
if (_saved_PLYP_data.empty()) {
|
||||
SlSetLength(0);
|
||||
} else {
|
||||
SlSetLength(2 + _saved_PLYP_data.size());
|
||||
SlWriteUint16(_saved_PLYP_invalid_mask);
|
||||
MemoryDumper::GetCurrent()->CopyBytes((const uint8 *)_saved_PLYP_data.data(), _saved_PLYP_data.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 nonce[24]; /* Use only once per key: random */
|
||||
if (randombytes(nonce, 24) < 0) {
|
||||
/* Can't get a random nonce, just give up */
|
||||
SlSetLength(0);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<byte> buffer = SlSaveToVector([](void *) {
|
||||
SlWriteUint32((uint32)_network_company_server_id.size());
|
||||
MemoryDumper::GetCurrent()->CopyBytes((const uint8 *)_network_company_server_id.data(), _network_company_server_id.size());
|
||||
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
SlWriteUint16(c->index);
|
||||
|
||||
const std::string &password = _network_company_states[c->index].password;
|
||||
SlWriteUint32((uint32)password.size());
|
||||
MemoryDumper::GetCurrent()->CopyBytes((const uint8 *)password.data(), password.size());
|
||||
}
|
||||
|
||||
SlWriteUint16(0xFFFF);
|
||||
|
||||
/* Add some random length padding to not make it too obvious from the length whether passwords are set or not */
|
||||
uint8 padding[256];
|
||||
if (randombytes(padding, 256) >= 0) {
|
||||
SlWriteByte(padding[0]);
|
||||
MemoryDumper::GetCurrent()->CopyBytes(padding + 1, padding[0]);
|
||||
} else {
|
||||
SlWriteByte(0);
|
||||
}
|
||||
}, nullptr);
|
||||
|
||||
|
||||
uint8 mac[16]; /* Message authentication code */
|
||||
|
||||
/* Encrypt in place */
|
||||
crypto_lock(mac, buffer.data(), _network_company_password_storage_key, nonce, buffer.data(), buffer.size());
|
||||
|
||||
SlSetLength(2 + 16 + 24 + 16 + buffer.size());
|
||||
SlWriteUint16(0); // Invalid mask
|
||||
MemoryDumper::GetCurrent()->CopyBytes(_network_company_password_storage_token, 16);
|
||||
MemoryDumper::GetCurrent()->CopyBytes(nonce, 24);
|
||||
MemoryDumper::GetCurrent()->CopyBytes(mac, 16);
|
||||
MemoryDumper::GetCurrent()->CopyBytes(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
static const ChunkHandler company_chunk_handlers[] = {
|
||||
{ 'PLYR', Save_PLYR, Load_PLYR, Ptrs_PLYR, Check_PLYR, CH_ARRAY },
|
||||
{ 'PLYX', Save_PLYX, Load_PLYX, nullptr, Check_PLYX, CH_RIFF },
|
||||
{ 'PLYP', Save_PLYP, Load_PLYP, nullptr, nullptr, CH_RIFF },
|
||||
static const PLYRChunkHandler PLYR;
|
||||
static const ChunkHandlerRef company_chunk_handlers[] = {
|
||||
PLYR,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _company_chunk_handlers(company_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,57 +8,71 @@
|
||||
/** @file depot_sl.cpp Code handling saving and loading of depots */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/depot_sl_compat.h"
|
||||
|
||||
#include "../depot_base.h"
|
||||
#include "../town.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static TownID _town_index;
|
||||
|
||||
static const SaveLoad _depot_desc[] = {
|
||||
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDVAR(Depot, xy, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR(_town_index, SLE_UINT16, SL_MIN_VERSION, SLV_141),
|
||||
SLEG_CONDVAR("town_index", _town_index, SLE_UINT16, SL_MIN_VERSION, SLV_141),
|
||||
SLE_CONDREF(Depot, town, REF_TOWN, SLV_141, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Depot, town_cn, SLE_UINT16, SLV_141, SL_MAX_VERSION),
|
||||
SLE_CONDSTR(Depot, name, SLE_STR, 0, SLV_141, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Depot, build_date, SLE_INT32, SLV_142, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP, 5)),
|
||||
};
|
||||
|
||||
static void Save_DEPT()
|
||||
{
|
||||
struct DEPTChunkHandler : ChunkHandler {
|
||||
DEPTChunkHandler() : ChunkHandler('DEPT', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_depot_desc);
|
||||
|
||||
for (Depot *depot : Depot::Iterate()) {
|
||||
SlSetArrayIndex(depot->index);
|
||||
SlObject(depot, _depot_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_depot_desc, _depot_sl_compat);
|
||||
|
||||
static void Load_DEPT()
|
||||
{
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Depot *depot = new (index) Depot();
|
||||
SlObject(depot, _depot_desc);
|
||||
SlObject(depot, slt);
|
||||
|
||||
/* Set the town 'pointer' so we can restore it later. */
|
||||
if (IsSavegameVersionBefore(SLV_141)) depot->town = (Town *)(size_t)_town_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_DEPT()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (Depot *depot : Depot::Iterate()) {
|
||||
SlObject(depot, _depot_desc);
|
||||
if (IsSavegameVersionBefore(SLV_141)) depot->town = Town::Get((size_t)depot->town);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler depot_chunk_handlers[] = {
|
||||
{ 'DEPT', Save_DEPT, Load_DEPT, Ptrs_DEPT, nullptr, CH_ARRAY },
|
||||
static const DEPTChunkHandler DEPT;
|
||||
static const ChunkHandlerRef depot_chunk_handlers[] = {
|
||||
DEPT,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _depot_chunk_handlers(depot_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,34 +8,18 @@
|
||||
/** @file economy_sl.cpp Code handling saving and loading of economy data */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/economy_sl_compat.h"
|
||||
|
||||
#include "../economy_func.h"
|
||||
#include "../economy_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Prices in pre 126 savegames */
|
||||
static void Load_PRIC()
|
||||
{
|
||||
/* Old games store 49 base prices, very old games store them as int32 */
|
||||
int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64;
|
||||
SlArray(nullptr, 49, vt | SLE_VAR_NULL);
|
||||
SlArray(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL);
|
||||
}
|
||||
|
||||
/** Cargo payment rates in pre 126 savegames */
|
||||
static void Load_CAPR()
|
||||
{
|
||||
uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
|
||||
int vt = IsSavegameVersionBefore(SLV_65) ? SLE_FILE_I32 : SLE_FILE_I64;
|
||||
SlArray(nullptr, num_cargo, vt | SLE_VAR_NULL);
|
||||
SlArray(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL);
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _economy_desc[] = {
|
||||
SLE_CONDNULL(4, SL_MIN_VERSION, SLV_65), // max_loan
|
||||
SLE_CONDNULL(8, SLV_65, SLV_144), // max_loan
|
||||
SLE_CONDVAR(Economy, old_max_loan_unround, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
|
||||
SLE_CONDVAR(Economy, old_max_loan_unround, SLE_INT64, SLV_65, SLV_126),
|
||||
SLE_CONDVAR(Economy, old_max_loan_unround_fract, SLE_UINT16, SLV_70, SLV_126),
|
||||
@@ -46,60 +30,80 @@ static const SaveLoad _economy_desc[] = {
|
||||
SLE_VAR(Economy, infl_amount, SLE_UINT8),
|
||||
SLE_VAR(Economy, infl_amount_pr, SLE_UINT8),
|
||||
SLE_CONDVAR(Economy, industry_daily_change_counter, SLE_UINT32, SLV_102, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP)),
|
||||
};
|
||||
|
||||
/** Economy variables */
|
||||
static void Save_ECMY()
|
||||
{
|
||||
SlObject(&_economy, _economy_desc);
|
||||
}
|
||||
struct ECMYChunkHandler : ChunkHandler {
|
||||
ECMYChunkHandler() : ChunkHandler('ECMY', CH_TABLE) {}
|
||||
|
||||
/** Economy variables */
|
||||
static void Load_ECMY()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_economy_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlObject(&_economy, _economy_desc);
|
||||
}
|
||||
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_economy_desc, _economy_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlObject(&_economy, slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries");
|
||||
|
||||
StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102)); // old savegames will need to be initialized
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const SaveLoad _cargopayment_desc[] = {
|
||||
SLE_REF(CargoPayment, front, REF_VEHICLE),
|
||||
SLE_VAR(CargoPayment, route_profit, SLE_INT64),
|
||||
SLE_VAR(CargoPayment, visual_profit, SLE_INT64),
|
||||
SLE_CONDVAR_X(CargoPayment, visual_transfer, SLE_INT64, SLV_181, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_OR, XSLFI_CHILLPP)),
|
||||
SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, SLV_181, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_CAPY()
|
||||
{
|
||||
struct CAPYChunkHandler : ChunkHandler {
|
||||
CAPYChunkHandler() : ChunkHandler('CAPY', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cargopayment_desc);
|
||||
|
||||
for (CargoPayment *cp : CargoPayment::Iterate()) {
|
||||
SlSetArrayIndex(cp->index);
|
||||
SlObject(cp, _cargopayment_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargopayment_desc, _cargopayment_sl_compat);
|
||||
|
||||
static void Load_CAPY()
|
||||
{
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
CargoPayment *cp = new (index) CargoPayment();
|
||||
SlObject(cp, _cargopayment_desc);
|
||||
SlObject(cp, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_CAPY()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (CargoPayment *cp : CargoPayment::Iterate()) {
|
||||
SlObject(cp, _cargopayment_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const ChunkHandler economy_chunk_handlers[] = {
|
||||
{ 'CAPY', Save_CAPY, Load_CAPY, Ptrs_CAPY, nullptr, CH_ARRAY },
|
||||
{ 'PRIC', nullptr, Load_PRIC, nullptr, nullptr, CH_RIFF },
|
||||
{ 'CAPR', nullptr, Load_CAPR, nullptr, nullptr, CH_RIFF },
|
||||
{ 'ECMY', Save_ECMY, Load_ECMY, nullptr, nullptr, CH_RIFF },
|
||||
static const CAPYChunkHandler CAPY;
|
||||
static const ECMYChunkHandler ECMY;
|
||||
static const ChunkHandlerRef economy_chunk_handlers[] = {
|
||||
CAPY,
|
||||
ECMY,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _economy_chunk_handlers(economy_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,14 +8,20 @@
|
||||
/** @file engine_sl.cpp Code handling saving and loading of engines */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/engine_sl_compat.h"
|
||||
|
||||
#include "../engine_base.h"
|
||||
#include "../engine_func.h"
|
||||
#include "../string_func.h"
|
||||
#include <vector>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
Engine *GetTempDataEngine(EngineID index);
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _engine_desc[] = {
|
||||
SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLE_CONDVAR(Engine, intro_date, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
@@ -29,77 +35,40 @@ static const SaveLoad _engine_desc[] = {
|
||||
SLE_VAR(Engine, duration_phase_1, SLE_UINT16),
|
||||
SLE_VAR(Engine, duration_phase_2, SLE_UINT16),
|
||||
SLE_VAR(Engine, duration_phase_3, SLE_UINT16),
|
||||
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_121),
|
||||
SLE_VAR(Engine, flags, SLE_UINT8),
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_179), // old preview_company_rank
|
||||
SLE_CONDVAR(Engine, preview_asked, SLE_UINT16, SLV_179, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, preview_company, SLE_UINT8, SLV_179, SL_MAX_VERSION),
|
||||
SLE_VAR(Engine, preview_wait, SLE_UINT8),
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_45),
|
||||
SLE_CONDVAR(Engine, company_avail, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDVAR(Engine, company_avail, SLE_UINT16, SLV_104, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, company_hidden, SLE_UINT16, SLV_193, SL_MAX_VERSION),
|
||||
SLE_CONDSTR(Engine, name, SLE_STR, 0, SLV_84, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space
|
||||
};
|
||||
|
||||
static std::vector<Engine*> _temp_engine;
|
||||
struct ENGNChunkHandler : ChunkHandler {
|
||||
ENGNChunkHandler() : ChunkHandler('ENGN', CH_TABLE) {}
|
||||
|
||||
/**
|
||||
* Allocate an Engine structure, but not using the pools.
|
||||
* The allocated Engine must be freed using FreeEngine;
|
||||
* @return Allocated engine.
|
||||
*/
|
||||
static Engine* CallocEngine()
|
||||
{
|
||||
uint8 *zero = CallocT<uint8>(sizeof(Engine));
|
||||
Engine *engine = new (zero) Engine();
|
||||
return engine;
|
||||
}
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_engine_desc);
|
||||
|
||||
/**
|
||||
* Deallocate an Engine constructed by CallocEngine.
|
||||
* @param e Engine to free.
|
||||
*/
|
||||
static void FreeEngine(Engine *e)
|
||||
{
|
||||
if (e != nullptr) {
|
||||
e->~Engine();
|
||||
free(e);
|
||||
}
|
||||
}
|
||||
|
||||
Engine *GetTempDataEngine(EngineID index)
|
||||
{
|
||||
if (index < _temp_engine.size()) {
|
||||
return _temp_engine[index];
|
||||
} else if (index == _temp_engine.size()) {
|
||||
_temp_engine.push_back(CallocEngine());
|
||||
return _temp_engine[index];
|
||||
} else {
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_ENGN()
|
||||
{
|
||||
for (Engine *e : Engine::Iterate()) {
|
||||
SlSetArrayIndex(e->index);
|
||||
SlObject(e, _engine_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_desc, _engine_sl_compat);
|
||||
|
||||
static void Load_ENGN()
|
||||
{
|
||||
/* As engine data is loaded before engines are initialized we need to load
|
||||
* this information into a temporary array. This is then copied into the
|
||||
* engine pool after processing NewGRFs by CopyTempEngineData(). */
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Engine *e = GetTempDataEngine(index);
|
||||
SlObject(e, _engine_desc);
|
||||
SlObject(e, slt);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_179)) {
|
||||
/* preview_company_rank was replaced with preview_company and preview_asked.
|
||||
@@ -109,62 +78,8 @@ static void Load_ENGN()
|
||||
e->preview_asked = MAX_UVALUE(CompanyMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data from temporary engine array into the real engine pool.
|
||||
*/
|
||||
void CopyTempEngineData()
|
||||
{
|
||||
for (Engine *e : Engine::Iterate()) {
|
||||
if (e->index >= _temp_engine.size()) break;
|
||||
|
||||
const Engine *se = GetTempDataEngine(e->index);
|
||||
e->intro_date = se->intro_date;
|
||||
e->age = se->age;
|
||||
e->reliability = se->reliability;
|
||||
e->reliability_spd_dec = se->reliability_spd_dec;
|
||||
e->reliability_start = se->reliability_start;
|
||||
e->reliability_max = se->reliability_max;
|
||||
e->reliability_final = se->reliability_final;
|
||||
e->duration_phase_1 = se->duration_phase_1;
|
||||
e->duration_phase_2 = se->duration_phase_2;
|
||||
e->duration_phase_3 = se->duration_phase_3;
|
||||
e->flags = se->flags;
|
||||
e->preview_asked = se->preview_asked;
|
||||
e->preview_company = se->preview_company;
|
||||
e->preview_wait = se->preview_wait;
|
||||
e->company_avail = se->company_avail;
|
||||
e->company_hidden = se->company_hidden;
|
||||
e->name = se->name;
|
||||
}
|
||||
|
||||
ResetTempEngineData();
|
||||
}
|
||||
|
||||
void ResetTempEngineData()
|
||||
{
|
||||
/* Get rid of temporary data */
|
||||
for (std::vector<Engine*>::iterator it = _temp_engine.begin(); it != _temp_engine.end(); ++it) {
|
||||
FreeEngine(*it);
|
||||
}
|
||||
_temp_engine.clear();
|
||||
}
|
||||
|
||||
static void Load_ENGS()
|
||||
{
|
||||
/* Load old separate String ID list into a temporary array. This
|
||||
* was always 256 entries. */
|
||||
StringID names[256];
|
||||
|
||||
SlArray(names, lengthof(names), SLE_STRINGID);
|
||||
|
||||
/* Copy each string into the temporary engine array. */
|
||||
for (EngineID engine = 0; engine < lengthof(names); engine++) {
|
||||
Engine *e = GetTempDataEngine(engine);
|
||||
e->name = CopyFromOldName(names[engine]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Save and load the mapping between the engine id in the pool, and the grf file it came from. */
|
||||
static const SaveLoad _engine_id_mapping_desc[] = {
|
||||
@@ -174,35 +89,41 @@ static const SaveLoad _engine_id_mapping_desc[] = {
|
||||
SLE_VAR(EngineIDMapping, substitute_id, SLE_UINT8),
|
||||
};
|
||||
|
||||
static void Save_EIDS()
|
||||
{
|
||||
struct EIDSChunkHandler : ChunkHandler {
|
||||
EIDSChunkHandler() : ChunkHandler('EIDS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_engine_id_mapping_desc);
|
||||
|
||||
uint index = 0;
|
||||
for (EngineIDMapping &eid : _engine_mngr) {
|
||||
SlSetArrayIndex(index);
|
||||
SlObject(&eid, _engine_id_mapping_desc);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_id_mapping_desc, _engine_id_mapping_sl_compat);
|
||||
|
||||
static void Load_EIDS()
|
||||
{
|
||||
_engine_mngr.clear();
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
EngineIDMapping *eid = &_engine_mngr.emplace_back();
|
||||
SlObject(eid, _engine_id_mapping_desc);
|
||||
SlObject(eid, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AfterLoadEngines()
|
||||
{
|
||||
AnalyseEngineCallbacks();
|
||||
}
|
||||
|
||||
static const ChunkHandler engine_chunk_handlers[] = {
|
||||
{ 'EIDS', Save_EIDS, Load_EIDS, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'ENGN', Save_ENGN, Load_ENGN, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'ENGS', nullptr, Load_ENGS, nullptr, nullptr, CH_RIFF },
|
||||
static const EIDSChunkHandler EIDS;
|
||||
static const ENGNChunkHandler ENGN;
|
||||
static const ChunkHandlerRef engine_chunk_handlers[] = {
|
||||
EIDS,
|
||||
ENGN,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _engine_chunk_handlers(engine_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -9,9 +9,11 @@
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../debug.h"
|
||||
#include "saveload.h"
|
||||
#include "../string_func.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/game_sl_compat.h"
|
||||
|
||||
#include "../string_func.h"
|
||||
#include "../game/game.hpp"
|
||||
#include "../game/game_config.hpp"
|
||||
#include "../network/network.h"
|
||||
@@ -20,16 +22,20 @@
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern GameStrings *_current_data;
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static std::string _game_saveload_name;
|
||||
static int _game_saveload_version;
|
||||
static std::string _game_saveload_settings;
|
||||
static bool _game_saveload_is_random;
|
||||
|
||||
static const SaveLoad _game_script[] = {
|
||||
SLEG_SSTR(_game_saveload_name, SLE_STR),
|
||||
SLEG_SSTR(_game_saveload_settings, SLE_STR),
|
||||
SLEG_VAR(_game_saveload_version, SLE_UINT32),
|
||||
SLEG_VAR(_game_saveload_is_random, SLE_BOOL),
|
||||
static const SaveLoad _game_script_desc[] = {
|
||||
SLEG_SSTR("name", _game_saveload_name, SLE_STR),
|
||||
SLEG_SSTR("settings", _game_saveload_settings, SLE_STR),
|
||||
SLEG_VAR("version", _game_saveload_version, SLE_UINT32),
|
||||
SLEG_VAR("is_random", _game_saveload_is_random, SLE_BOOL),
|
||||
};
|
||||
|
||||
static void SaveReal_GSDT(int *index_ptr)
|
||||
@@ -48,23 +54,28 @@ static void SaveReal_GSDT(int *index_ptr)
|
||||
_game_saveload_is_random = config->IsRandom();
|
||||
_game_saveload_settings = config->SettingsToString();
|
||||
|
||||
SlObject(nullptr, _game_script);
|
||||
SlObject(nullptr, _game_script_desc);
|
||||
Game::Save();
|
||||
}
|
||||
|
||||
static void Load_GSDT()
|
||||
{
|
||||
struct GSDTChunkHandler : ChunkHandler {
|
||||
GSDTChunkHandler() : ChunkHandler('GSDT', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_script_desc, _game_script_sl_compat);
|
||||
|
||||
/* Free all current data */
|
||||
GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr);
|
||||
|
||||
if ((CompanyID)SlIterateArray() == (CompanyID)-1) return;
|
||||
if (SlIterateArray() == -1) return;
|
||||
|
||||
_game_saveload_version = -1;
|
||||
SlObject(nullptr, _game_script);
|
||||
SlObject(nullptr, slt);
|
||||
|
||||
if (_game_mode == GM_MENU || (_networking && !_network_server)) {
|
||||
GameInstance::LoadEmpty();
|
||||
if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
|
||||
if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -77,14 +88,14 @@ static void Load_GSDT()
|
||||
config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
if (_game_saveload_name.compare("%_dummy") != 0) {
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version);
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %u which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version);
|
||||
DEBUG(script, 0, "This game will continue to run without GameScript.");
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame had no GameScript available at the time of saving.");
|
||||
DEBUG(script, 0, "This game will continue to run without GameScript.");
|
||||
}
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %d which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version);
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %u which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version);
|
||||
DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible.");
|
||||
}
|
||||
/* Make sure the GameScript doesn't get the saveload data, as it was not the
|
||||
@@ -98,56 +109,67 @@ static void Load_GSDT()
|
||||
/* Load the GameScript saved data */
|
||||
config->SetToLoadData(GameInstance::Load(_game_saveload_version));
|
||||
|
||||
if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs");
|
||||
}
|
||||
if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
|
||||
}
|
||||
|
||||
static void Save_GSDT()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_game_script_desc);
|
||||
SlSetArrayIndex(0);
|
||||
SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr);
|
||||
}
|
||||
|
||||
extern GameStrings *_current_data;
|
||||
}
|
||||
};
|
||||
|
||||
static std::string _game_saveload_string;
|
||||
static uint _game_saveload_strings;
|
||||
static uint32 _game_saveload_strings;
|
||||
|
||||
static const SaveLoad _game_language_header[] = {
|
||||
SLEG_SSTR(_game_saveload_string, SLE_STR),
|
||||
SLEG_VAR(_game_saveload_strings, SLE_UINT32),
|
||||
};
|
||||
class SlGameLanguageString : public DefaultSaveLoadHandler<SlGameLanguageString, LanguageStrings> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_SSTR("string", _game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _game_language_string_sl_compat;
|
||||
|
||||
static const SaveLoad _game_language_string[] = {
|
||||
SLEG_SSTR(_game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
};
|
||||
void Save(LanguageStrings *ls) const override
|
||||
{
|
||||
SlSetStructListLength(ls->lines.size());
|
||||
|
||||
static void SaveReal_GSTR(const LanguageStrings *ls)
|
||||
{
|
||||
_game_saveload_string = ls->language.c_str();
|
||||
_game_saveload_strings = (uint)ls->lines.size();
|
||||
|
||||
SlObject(nullptr, _game_language_header);
|
||||
for (const auto &i : ls->lines) {
|
||||
_game_saveload_string = i.c_str();
|
||||
SlObject(nullptr, _game_language_string);
|
||||
for (const auto &string : ls->lines) {
|
||||
_game_saveload_string = string;
|
||||
SlObject(nullptr, this->GetDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_GSTR()
|
||||
{
|
||||
void Load(LanguageStrings *ls) const override
|
||||
{
|
||||
uint32 length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _game_saveload_strings : (uint32)SlGetStructListLength(UINT32_MAX);
|
||||
|
||||
for (uint32 i = 0; i < length; i++) {
|
||||
SlObject(nullptr, this->GetLoadDescription());
|
||||
ls->lines.emplace_back(_game_saveload_string);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const SaveLoad _game_language_desc[] = {
|
||||
SLE_SSTR(LanguageStrings, language, SLE_STR),
|
||||
SLEG_CONDVAR("count", _game_saveload_strings, SLE_UINT32, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
|
||||
SLEG_STRUCTLIST("strings", SlGameLanguageString),
|
||||
};
|
||||
|
||||
struct GSTRChunkHandler : ChunkHandler {
|
||||
GSTRChunkHandler() : ChunkHandler('GSTR', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_language_desc, _game_language_sl_compat);
|
||||
|
||||
delete _current_data;
|
||||
_current_data = new GameStrings();
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
_game_saveload_string.clear();
|
||||
SlObject(nullptr, _game_language_header);
|
||||
|
||||
LanguageStrings ls(_game_saveload_string);
|
||||
for (uint i = 0; i < _game_saveload_strings; i++) {
|
||||
SlObject(nullptr, _game_language_string);
|
||||
ls.lines.emplace_back(_game_saveload_string);
|
||||
}
|
||||
|
||||
LanguageStrings ls;
|
||||
SlObject(&ls, slt);
|
||||
_current_data->raw_strings.push_back(std::move(ls));
|
||||
}
|
||||
|
||||
@@ -160,21 +182,28 @@ static void Load_GSTR()
|
||||
|
||||
_current_data->Compile();
|
||||
ReconsiderGameScriptLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_game_language_desc);
|
||||
|
||||
static void Save_GSTR()
|
||||
{
|
||||
if (_current_data == nullptr) return;
|
||||
|
||||
for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlAutolength((AutolengthProc *)SaveReal_GSTR, &_current_data->raw_strings[i]);
|
||||
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 },
|
||||
static const GSTRChunkHandler GSTR;
|
||||
static const GSDTChunkHandler GSDT;
|
||||
static const ChunkHandlerRef game_chunk_handlers[] = {
|
||||
GSTR,
|
||||
GSDT,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _game_chunk_handlers(game_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,113 +8,320 @@
|
||||
/** @file gamelog_sl.cpp Code handling saving and loading of gamelog data */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/gamelog_sl_compat.h"
|
||||
|
||||
#include "../gamelog_internal.h"
|
||||
#include "../fios.h"
|
||||
#include "../string_func.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static const SaveLoad _glog_action_desc[] = {
|
||||
SLE_CONDVAR_X(LoggedAction, tick, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0)),
|
||||
SLE_CONDVAR_X(LoggedAction, tick, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)),
|
||||
};
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _glog_mode_desc[] = {
|
||||
class SlGamelogMode : public DefaultSaveLoadHandler<SlGamelogMode, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, mode.mode, SLE_UINT8),
|
||||
SLE_VAR(LoggedChange, mode.landscape, SLE_UINT8),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_mode_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_MODE) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_MODE) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static char old_revision_text[GAMELOG_REVISION_LENGTH];
|
||||
static std::string revision_test;
|
||||
|
||||
static const SaveLoad _glog_revision_desc[] = {
|
||||
SLEG_CONDARR_X(old_revision_text, SLE_UINT8, GAMELOG_REVISION_LENGTH, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_EXTENDED_GAMELOG, 0, 0)),
|
||||
SLE_CONDSTR_X(LoggedChange, revision.text, SLE_STR, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_EXTENDED_GAMELOG)),
|
||||
class SlGamelogRevision : public DefaultSaveLoadHandler<SlGamelogRevision, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_CONDARR("revision.text", old_revision_text, SLE_UINT8, GAMELOG_REVISION_LENGTH, SL_MIN_VERSION, SLV_STRING_GAMELOG),
|
||||
SLEG_CONDSSTR("revision.text", revision_test, SLE_STR, SLV_STRING_GAMELOG, SL_MAX_VERSION),
|
||||
SLE_VAR(LoggedChange, revision.newgrf, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, revision.slver, SLE_UINT16),
|
||||
SLE_VAR(LoggedChange, revision.modified, SLE_UINT8),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_revision_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_REVISION) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_REVISION) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
if (IsSavegameVersionBefore(SLV_STRING_GAMELOG)) {
|
||||
lc->revision.text = stredup(old_revision_text, lastof(old_revision_text));
|
||||
} else {
|
||||
lc->revision.text = stredup(revision_test.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_oldver_desc[] = {
|
||||
class SlGamelogOldver : public DefaultSaveLoadHandler<SlGamelogOldver, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, oldver.type, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, oldver.version, SLE_UINT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_oldver_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_OLDVER) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_OLDVER) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_setting_desc[] = {
|
||||
class SlGamelogSetting : public DefaultSaveLoadHandler<SlGamelogSetting, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_STR(LoggedChange, setting.name, SLE_STR, 128),
|
||||
SLE_VAR(LoggedChange, setting.oldval, SLE_INT32),
|
||||
SLE_VAR(LoggedChange, setting.newval, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_setting_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_SETTING) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_SETTING) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_grfadd_desc[] = {
|
||||
class SlGamelogGrfadd : public DefaultSaveLoadHandler<SlGamelogGrfadd, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfadd.grfid, SLE_UINT32 ),
|
||||
SLE_ARR(LoggedChange, grfadd.md5sum, SLE_UINT8, 16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfadd_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFADD) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFADD) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_grfrem_desc[] = {
|
||||
class SlGamelogGrfrem : public DefaultSaveLoadHandler<SlGamelogGrfrem, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfrem.grfid, SLE_UINT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfrem_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFREM) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFREM) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_grfcompat_desc[] = {
|
||||
class SlGamelogGrfcompat : public DefaultSaveLoadHandler<SlGamelogGrfcompat, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfcompat.grfid, SLE_UINT32 ),
|
||||
SLE_ARR(LoggedChange, grfcompat.md5sum, SLE_UINT8, 16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfcompat_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFCOMPAT) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFCOMPAT) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_grfparam_desc[] = {
|
||||
class SlGamelogGrfparam : public DefaultSaveLoadHandler<SlGamelogGrfparam, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfparam.grfid, SLE_UINT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfparam_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFPARAM) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFPARAM) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_grfmove_desc[] = {
|
||||
class SlGamelogGrfmove : public DefaultSaveLoadHandler<SlGamelogGrfmove, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfmove.grfid, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, grfmove.offset, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfmove_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFMOVE) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFMOVE) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_grfbug_desc[] = {
|
||||
class SlGamelogGrfbug : public DefaultSaveLoadHandler<SlGamelogGrfbug, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfbug.data, SLE_UINT64),
|
||||
SLE_VAR(LoggedChange, grfbug.grfid, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, grfbug.bug, SLE_UINT8),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfbug_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFBUG) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFBUG) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoad _glog_emergency_desc[] = {
|
||||
SLE_CONDNULL(0, SL_MIN_VERSION, SL_MIN_VERSION), // Just an empty list, to keep the rest of the code easier.
|
||||
static bool _is_emergency_save = true;
|
||||
|
||||
class SlGamelogEmergency : public DefaultSaveLoadHandler<SlGamelogEmergency, LoggedChange> {
|
||||
public:
|
||||
/* We need to store something, so store a "true" value. */
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_CONDVAR("is_emergency_save", _is_emergency_save, SLE_BOOL, SLV_RIFF_TO_ARRAY, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_emergency_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_EMERGENCY) return;
|
||||
|
||||
_is_emergency_save = true;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_EMERGENCY) return;
|
||||
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static const SaveLoadTable _glog_desc[] = {
|
||||
_glog_mode_desc,
|
||||
_glog_revision_desc,
|
||||
_glog_oldver_desc,
|
||||
_glog_setting_desc,
|
||||
_glog_grfadd_desc,
|
||||
_glog_grfrem_desc,
|
||||
_glog_grfcompat_desc,
|
||||
_glog_grfparam_desc,
|
||||
_glog_grfmove_desc,
|
||||
_glog_grfbug_desc,
|
||||
_glog_emergency_desc,
|
||||
};
|
||||
class SlGamelogAction : public DefaultSaveLoadHandler<SlGamelogAction, LoggedAction> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_SAVEBYTE(LoggedChange, ct),
|
||||
SLEG_STRUCT("mode", SlGamelogMode),
|
||||
SLEG_STRUCT("revision", SlGamelogRevision),
|
||||
SLEG_STRUCT("oldver", SlGamelogOldver),
|
||||
SLEG_STRUCT("setting", SlGamelogSetting),
|
||||
SLEG_STRUCT("grfadd", SlGamelogGrfadd),
|
||||
SLEG_STRUCT("grfrem", SlGamelogGrfrem),
|
||||
SLEG_STRUCT("grfcompat", SlGamelogGrfcompat),
|
||||
SLEG_STRUCT("grfparam", SlGamelogGrfparam),
|
||||
SLEG_STRUCT("grfmove", SlGamelogGrfmove),
|
||||
SLEG_STRUCT("grfbug", SlGamelogGrfbug),
|
||||
SLEG_STRUCT("emergency", SlGamelogEmergency),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_action_sl_compat;
|
||||
|
||||
static_assert(lengthof(_glog_desc) == GLCT_END);
|
||||
void Save(LoggedAction *la) const override
|
||||
{
|
||||
SlSetStructListLength(la->changes);
|
||||
|
||||
static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_actions)
|
||||
{
|
||||
assert(gamelog_action == nullptr);
|
||||
assert(gamelog_actions == 0);
|
||||
const LoggedChange *lcend = &la->change[la->changes];
|
||||
for (LoggedChange *lc = la->change; lc != lcend; lc++) {
|
||||
assert((uint)lc->ct < GLCT_END);
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(LoggedAction *la) const override
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
|
||||
byte type;
|
||||
while ((type = SlReadByte()) != GLAT_NONE) {
|
||||
if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type");
|
||||
GamelogActionType at = (GamelogActionType)type;
|
||||
|
||||
gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
|
||||
LoggedAction *la = &gamelog_action[gamelog_actions++];
|
||||
|
||||
la->at = at;
|
||||
|
||||
SlObject(la, _glog_action_desc); // has to be saved after 'DATE'!
|
||||
la->change = nullptr;
|
||||
la->changes = 0;
|
||||
|
||||
while ((type = SlReadByte()) != GLCT_NONE) {
|
||||
if (type >= GLCT_END) SlErrorCorrupt("Invalid gamelog change type");
|
||||
GamelogChangeType ct = (GamelogChangeType)type;
|
||||
@@ -122,62 +329,100 @@ static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_action
|
||||
la->change = ReallocT(la->change, la->changes + 1);
|
||||
|
||||
LoggedChange *lc = &la->change[la->changes++];
|
||||
/* for SLE_STR, pointer has to be valid! so make it nullptr */
|
||||
memset(lc, 0, sizeof(*lc));
|
||||
lc->ct = ct;
|
||||
|
||||
SlObject(lc, _glog_desc[ct]);
|
||||
if (ct == GLCT_REVISION && SlXvIsFeatureMissing(XSLFI_EXTENDED_GAMELOG)) {
|
||||
lc->revision.text = stredup(old_revision_text, lastof(old_revision_text));
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_GLOG()
|
||||
{
|
||||
size_t length = SlGetStructListLength(UINT32_MAX);
|
||||
la->change = ReallocT(la->change, length);
|
||||
la->changes = (uint32)length;
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
LoggedChange *lc = &la->change[i];
|
||||
memset(lc, 0, sizeof(*lc));
|
||||
|
||||
lc->ct = (GamelogChangeType)SlReadByte();
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedAction *la) const override { this->Load(la); }
|
||||
};
|
||||
|
||||
static const SaveLoad _gamelog_desc[] = {
|
||||
SLE_CONDVAR(LoggedAction, at, SLE_UINT8, SLV_RIFF_TO_ARRAY, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(LoggedAction, tick, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER),
|
||||
SLE_CONDVAR(LoggedAction, tick, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
|
||||
SLEG_STRUCTLIST("action", SlGamelogAction),
|
||||
};
|
||||
|
||||
struct GLOGChunkHandler : ChunkHandler {
|
||||
GLOGChunkHandler() : ChunkHandler('GLOG', CH_TABLE) {}
|
||||
|
||||
void LoadCommon(LoggedAction *&gamelog_action, uint &gamelog_actions) const
|
||||
{
|
||||
assert(gamelog_action == nullptr);
|
||||
assert(gamelog_actions == 0);
|
||||
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
|
||||
byte type;
|
||||
while ((type = SlReadByte()) != GLAT_NONE) {
|
||||
if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type");
|
||||
|
||||
gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
|
||||
LoggedAction *la = &gamelog_action[gamelog_actions++];
|
||||
memset(la, 0, sizeof(*la));
|
||||
|
||||
la->at = (GamelogActionType)type;
|
||||
SlObject(la, slt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
|
||||
LoggedAction *la = &gamelog_action[gamelog_actions++];
|
||||
memset(la, 0, sizeof(*la));
|
||||
|
||||
SlObject(la, slt);
|
||||
}
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_gamelog_desc);
|
||||
|
||||
const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
|
||||
size_t length = 0;
|
||||
|
||||
for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
|
||||
const LoggedChange *lcend = &la->change[la->changes];
|
||||
for (LoggedChange *lc = la->change; lc != lcend; lc++) {
|
||||
assert((uint)lc->ct < lengthof(_glog_desc));
|
||||
length += SlCalcObjLength(lc, _glog_desc[lc->ct]) + 1;
|
||||
uint i = 0;
|
||||
for (LoggedAction *la = _gamelog_action; la != laend; la++, i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(la, _gamelog_desc);
|
||||
}
|
||||
length += 10;
|
||||
}
|
||||
length++;
|
||||
|
||||
SlSetLength(length);
|
||||
|
||||
for (LoggedAction *la = _gamelog_action; la != laend; la++) {
|
||||
SlWriteByte(la->at);
|
||||
SlObject(la, _glog_action_desc);
|
||||
|
||||
const LoggedChange *lcend = &la->change[la->changes];
|
||||
for (LoggedChange *lc = la->change; lc != lcend; lc++) {
|
||||
SlWriteByte(lc->ct);
|
||||
assert((uint)lc->ct < GLCT_END);
|
||||
SlObject(lc, _glog_desc[lc->ct]);
|
||||
void Load() const override
|
||||
{
|
||||
this->LoadCommon(_gamelog_action, _gamelog_actions);
|
||||
}
|
||||
SlWriteByte(GLCT_NONE);
|
||||
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
this->LoadCommon(_load_check_data.gamelog_action, _load_check_data.gamelog_actions);
|
||||
}
|
||||
SlWriteByte(GLAT_NONE);
|
||||
}
|
||||
};
|
||||
|
||||
static void Load_GLOG()
|
||||
{
|
||||
Load_GLOG_common(_gamelog_action, _gamelog_actions);
|
||||
}
|
||||
|
||||
static void Check_GLOG()
|
||||
{
|
||||
Load_GLOG_common(_load_check_data.gamelog_action, _load_check_data.gamelog_actions);
|
||||
}
|
||||
|
||||
static const ChunkHandler gamelog_chunk_handlers[] = {
|
||||
{ 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_RIFF }
|
||||
static const GLOGChunkHandler GLOG;
|
||||
static const ChunkHandlerRef gamelog_chunk_handlers[] = {
|
||||
GLOG,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _gamelog_chunk_handlers(gamelog_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,12 +8,16 @@
|
||||
/** @file goal_sl.cpp Code handling saving and loading of goals */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../goal_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/goal_sl_compat.h"
|
||||
|
||||
#include "../goal_base.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _goals_desc[] = {
|
||||
SLE_VAR(Goal, company, SLE_FILE_U16 | SLE_VAR_U8),
|
||||
SLE_VAR(Goal, type, SLE_FILE_U16 | SLE_VAR_U8),
|
||||
@@ -23,25 +27,36 @@ static const SaveLoad _goals_desc[] = {
|
||||
SLE_CONDVAR(Goal, completed, SLE_BOOL, SLV_182, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_GOAL()
|
||||
{
|
||||
struct GOALChunkHandler : ChunkHandler {
|
||||
GOALChunkHandler() : ChunkHandler('GOAL', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_goals_desc);
|
||||
|
||||
for (Goal *s : Goal::Iterate()) {
|
||||
SlSetArrayIndex(s->index);
|
||||
SlObject(s, _goals_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_goals_desc, _goals_sl_compat);
|
||||
|
||||
static void Load_GOAL()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Goal *s = new (index) Goal();
|
||||
SlObject(s, _goals_desc);
|
||||
SlObject(s, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler goal_chunk_handlers[] = {
|
||||
{ 'GOAL', Save_GOAL, Load_GOAL, nullptr, nullptr, CH_ARRAY },
|
||||
static const GOALChunkHandler GOAL;
|
||||
static const ChunkHandlerRef goal_chunk_handlers[] = {
|
||||
GOAL,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _goal_chunk_handlers(goal_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -12,13 +12,15 @@
|
||||
#include "../company_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/group_sl_compat.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _group_desc[] = {
|
||||
SLE_CONDVAR(Group, name, SLE_NAME, SL_MIN_VERSION, SLV_84),
|
||||
SLE_CONDSSTR(Group, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_164), // num_vehicle
|
||||
SLE_VAR(Group, owner, SLE_UINT8),
|
||||
SLE_VAR(Group, vehicle_type, SLE_UINT8),
|
||||
SLE_VAR(Group, flags, SLE_UINT8),
|
||||
@@ -28,22 +30,29 @@ static const SaveLoad _group_desc[] = {
|
||||
SLE_CONDVAR(Group, parent, SLE_UINT16, SLV_189, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_GRPS()
|
||||
{
|
||||
struct GRPSChunkHandler : ChunkHandler {
|
||||
GRPSChunkHandler() : ChunkHandler('GRPS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_group_desc);
|
||||
|
||||
for (Group *g : Group::Iterate()) {
|
||||
SlSetArrayIndex(g->index);
|
||||
SlObject(g, _group_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Load_GRPS()
|
||||
{
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_group_desc, _group_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Group *g = new (index) Group();
|
||||
SlObject(g, _group_desc);
|
||||
SlObject(g, slt);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_189)) g->parent = INVALID_GROUP;
|
||||
|
||||
@@ -53,10 +62,14 @@ static void Load_GRPS()
|
||||
g->livery.colour2 = c->livery[LS_DEFAULT].colour2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler group_chunk_handlers[] = {
|
||||
{ 'GRPS', Save_GRPS, Load_GRPS, nullptr, nullptr, CH_ARRAY },
|
||||
static const GRPSChunkHandler GRPS;
|
||||
static const ChunkHandlerRef group_chunk_handlers[] = {
|
||||
GRPS,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _group_chunk_handlers(group_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,13 +8,134 @@
|
||||
/** @file industry_sl.cpp Code handling saving and loading of industries */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../industry.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/industry_sl_compat.h"
|
||||
|
||||
#include "../industry.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const int THIS_MONTH = 0;
|
||||
static const int LAST_MONTH = 1;
|
||||
|
||||
struct ProducedHistory {
|
||||
uint16_t production; ///< Total produced
|
||||
uint16_t transported; ///< Total transported
|
||||
|
||||
uint8_t PctTransported() const
|
||||
{
|
||||
if (this->production == 0) return 0;
|
||||
return ClampTo<uint8_t>(this->transported * 256 / this->production);
|
||||
}
|
||||
};
|
||||
|
||||
struct ProducedCargo {
|
||||
CargoID cargo; ///< Cargo type
|
||||
uint16_t waiting; ///< Amount of cargo produced
|
||||
uint8_t rate; ///< Production rate
|
||||
std::array<ProducedHistory, 2> history; ///< History of cargo produced and transported
|
||||
};
|
||||
|
||||
struct AcceptedCargo {
|
||||
CargoID cargo; ///< Cargo type
|
||||
uint16_t waiting; ///< Amount of cargo waiting to processed
|
||||
Date last_accepted; ///< Last day cargo was accepted by this industry
|
||||
};
|
||||
|
||||
class SlIndustryAccepted : public DefaultSaveLoadHandler<SlIndustryAccepted, Industry> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(AcceptedCargo, cargo, SLE_UINT8),
|
||||
SLE_VAR(AcceptedCargo, waiting, SLE_UINT16),
|
||||
SLE_VAR(AcceptedCargo, last_accepted, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = {};
|
||||
|
||||
void Save(Industry *i) const override
|
||||
{
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
void Load(Industry *i) const override
|
||||
{
|
||||
size_t len = SlGetStructListLength(INDUSTRY_NUM_INPUTS);
|
||||
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
AcceptedCargo a = {};
|
||||
SlObject(&a, this->GetDescription());
|
||||
if (j < INDUSTRY_NUM_INPUTS) {
|
||||
i->accepts_cargo[j] = a.cargo;
|
||||
i->incoming_cargo_waiting[j] = a.waiting;
|
||||
i->last_cargo_accepted_at[j] = a.last_accepted;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlIndustryProducedHistory : public DefaultSaveLoadHandler<SlIndustryProducedHistory, ProducedCargo> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(ProducedHistory, production, SLE_UINT16),
|
||||
SLE_VAR(ProducedHistory, transported, SLE_UINT16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = {};
|
||||
|
||||
void Save(ProducedCargo *p) const override
|
||||
{
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
void Load(ProducedCargo *p) const override
|
||||
{
|
||||
size_t len = SlGetStructListLength(p->history.size());
|
||||
|
||||
for (auto &h : p->history) {
|
||||
if (--len > p->history.size()) break; // unsigned so wraps after hitting zero.
|
||||
SlObject(&h, this->GetDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlIndustryProduced : public DefaultSaveLoadHandler<SlIndustryProduced, Industry> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(ProducedCargo, cargo, SLE_UINT8),
|
||||
SLE_VAR(ProducedCargo, waiting, SLE_UINT16),
|
||||
SLE_VAR(ProducedCargo, rate, SLE_UINT8),
|
||||
SLEG_STRUCTLIST("history", SlIndustryProducedHistory),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = {};
|
||||
|
||||
void Save(Industry *i) const override
|
||||
{
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
void Load(Industry *i) const override
|
||||
{
|
||||
size_t len = SlGetStructListLength(INDUSTRY_NUM_OUTPUTS);
|
||||
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
ProducedCargo p = {};
|
||||
SlObject(&p, this->GetDescription());
|
||||
if (j < INDUSTRY_NUM_OUTPUTS) {
|
||||
i->produced_cargo[j] = p.cargo;
|
||||
i->produced_cargo_waiting[j] = p.waiting;
|
||||
i->production_rate[j] = p.rate;
|
||||
i->this_month_production[j] = p.history[THIS_MONTH].production;
|
||||
i->this_month_transported[j] = p.history[THIS_MONTH].transported;
|
||||
i->last_month_production[j] = p.history[LAST_MONTH].production;
|
||||
i->last_month_transported[j] = p.history[LAST_MONTH].transported;
|
||||
i->last_month_pct_transported[j] = p.history[LAST_MONTH].PctTransported();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static OldPersistentStorage _old_ind_persistent_storage;
|
||||
|
||||
static const SaveLoad _industry_desc[] = {
|
||||
@@ -24,29 +145,27 @@ static const SaveLoad _industry_desc[] = {
|
||||
SLE_VAR(Industry, location.h, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
SLE_REF(Industry, town, REF_TOWN),
|
||||
SLE_CONDREF(Industry, neutral_station, REF_STATION, SLV_SERVE_NEUTRAL_INDUSTRIES, SL_MAX_VERSION),
|
||||
SLE_CONDNULL( 2, SL_MIN_VERSION, SLV_61), ///< used to be industry's produced_cargo
|
||||
SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 2, SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, produced_cargo, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 3, SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, incoming_cargo_waiting, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, produced_cargo_waiting, SLE_UINT16, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, produced_cargo_waiting, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, produced_cargo_waiting, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, production_rate, SLE_UINT8, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, production_rate, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDNULL( 3, SL_MIN_VERSION, SLV_61), ///< used to be industry's accepts_cargo
|
||||
SLE_CONDARR(Industry, production_rate, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 3, SLV_78, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, accepts_cargo, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_VAR(Industry, prod_level, SLE_UINT8),
|
||||
SLE_CONDARR(Industry, this_month_production, SLE_UINT16, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, this_month_production, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, this_month_production, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, this_month_transported, SLE_UINT16, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, this_month_transported, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, this_month_transported, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, last_month_pct_transported, SLE_UINT8, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, last_month_production, SLE_UINT16, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, last_month_production, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, last_month_production, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDARR(Industry, last_month_transported, SLE_UINT16, 2, SL_MIN_VERSION, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, last_month_transported, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, last_month_transported, SLE_UINT16, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
|
||||
SLE_VAR(Industry, counter, SLE_UINT16),
|
||||
|
||||
@@ -62,49 +181,46 @@ static const SaveLoad _industry_desc[] = {
|
||||
SLE_CONDVAR(Industry, construction_date, SLE_INT32, SLV_70, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Industry, construction_type, SLE_UINT8, SLV_70, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Industry, last_cargo_accepted_at[0], SLE_INT32, SLV_70, SLV_EXTEND_INDUSTRY_CARGO_SLOTS),
|
||||
SLE_CONDARR(Industry, last_cargo_accepted_at, SLE_INT32, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Industry, last_cargo_accepted_at, SLE_INT32, 16, SLV_EXTEND_INDUSTRY_CARGO_SLOTS, SLV_INDUSTRY_CARGO_REORGANISE),
|
||||
SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, SLV_73, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Industry, exclusive_supplier, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Industry, exclusive_consumer, SLE_UINT8, SLV_GS_INDUSTRY_CONTROL, SL_MAX_VERSION),
|
||||
|
||||
SLEG_CONDARR(_old_ind_persistent_storage.storage, SLE_UINT32, 16, SLV_76, SLV_161),
|
||||
SLEG_CONDARR("storage", _old_ind_persistent_storage.storage, SLE_UINT32, 16, SLV_76, SLV_161),
|
||||
SLE_CONDREF(Industry, psa, REF_STORAGE, SLV_161, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(1, SLV_82, SLV_197), // random_triggers
|
||||
SLE_CONDVAR(Industry, random, SLE_UINT16, SLV_82, SL_MAX_VERSION),
|
||||
SLE_CONDSSTR(Industry, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_INDUSTRY_TEXT, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(32, SLV_2, SLV_144), // old reserved space
|
||||
SLEG_CONDSTRUCTLIST("accepted", SlIndustryAccepted, SLV_INDUSTRY_CARGO_REORGANISE, SL_MAX_VERSION),
|
||||
SLEG_CONDSTRUCTLIST("produced", SlIndustryProduced, SLV_INDUSTRY_CARGO_REORGANISE, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_INDY()
|
||||
{
|
||||
struct INDYChunkHandler : ChunkHandler {
|
||||
INDYChunkHandler() : ChunkHandler('INDY', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_industry_desc);
|
||||
|
||||
/* Write the industries */
|
||||
for (Industry *ind : Industry::Iterate()) {
|
||||
SlSetArrayIndex(ind->index);
|
||||
SlObject(ind, _industry_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_IIDS()
|
||||
{
|
||||
Save_NewGRFMapping(_industry_mngr);
|
||||
}
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_desc, _industry_sl_compat);
|
||||
|
||||
static void Save_TIDS()
|
||||
{
|
||||
Save_NewGRFMapping(_industile_mngr);
|
||||
}
|
||||
|
||||
static void Load_INDY()
|
||||
{
|
||||
int index;
|
||||
|
||||
Industry::ResetIndustryCounts();
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Industry *i = new (index) Industry();
|
||||
SlObject(i, _industry_desc);
|
||||
SlObject(i, slt);
|
||||
|
||||
/* Before savegame version 161, persistent storages were not stored in a pool. */
|
||||
if (IsSavegameVersionBefore(SLV_161) && !IsSavegameVersionBefore(SLV_76)) {
|
||||
@@ -115,35 +231,50 @@ static void Load_INDY()
|
||||
}
|
||||
Industry::IncIndustryTypeCount(i->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_IIDS()
|
||||
{
|
||||
Load_NewGRFMapping(_industry_mngr);
|
||||
}
|
||||
|
||||
static void Load_TIDS()
|
||||
{
|
||||
Load_NewGRFMapping(_industile_mngr);
|
||||
}
|
||||
|
||||
static void Ptrs_INDY()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (Industry *i : Industry::Iterate()) {
|
||||
SlObject(i, _industry_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct IIDSChunkHandler : NewGRFMappingChunkHandler {
|
||||
IIDSChunkHandler() : NewGRFMappingChunkHandler('IIDS', _industry_mngr) {}
|
||||
};
|
||||
|
||||
struct TIDSChunkHandler : NewGRFMappingChunkHandler {
|
||||
TIDSChunkHandler() : NewGRFMappingChunkHandler('TIDS', _industile_mngr) {}
|
||||
};
|
||||
|
||||
/** Description of the data to save and load in #IndustryBuildData. */
|
||||
static const SaveLoad _industry_builder_desc[] = {
|
||||
SLEG_VAR(_industry_builder.wanted_inds, SLE_UINT32),
|
||||
SLEG_VAR("wanted_inds", _industry_builder.wanted_inds, SLE_UINT32),
|
||||
};
|
||||
|
||||
/** Load/save industry builder. */
|
||||
static void LoadSave_IBLD()
|
||||
{
|
||||
/** Industry builder. */
|
||||
struct IBLDChunkHandler : ChunkHandler {
|
||||
IBLDChunkHandler() : ChunkHandler('IBLD', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_industry_builder_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlGlobList(_industry_builder_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_industry_builder_desc, _industry_builder_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlGlobList(slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many IBLD entries");
|
||||
}
|
||||
};
|
||||
|
||||
/** Description of the data to save and load in #IndustryTypeBuildData. */
|
||||
static const SaveLoad _industrytype_builder_desc[] = {
|
||||
@@ -154,34 +285,48 @@ static const SaveLoad _industrytype_builder_desc[] = {
|
||||
SLE_VAR(IndustryTypeBuildData, wait_count, SLE_UINT16),
|
||||
};
|
||||
|
||||
/** Save industry-type build data. */
|
||||
static void Save_ITBL()
|
||||
{
|
||||
/** Industry-type build data. */
|
||||
struct ITBLChunkHandler : ChunkHandler {
|
||||
ITBLChunkHandler() : ChunkHandler('ITBL', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_industrytype_builder_desc);
|
||||
|
||||
for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(_industry_builder.builddata + i, _industrytype_builder_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_industrytype_builder_desc, _industrytype_builder_sl_compat);
|
||||
|
||||
/** Load industry-type build data. */
|
||||
static void Load_ITBL()
|
||||
{
|
||||
for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
|
||||
_industry_builder.builddata[it].Reset();
|
||||
}
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if ((uint)index >= NUM_INDUSTRYTYPES) SlErrorCorrupt("Too many industry builder datas");
|
||||
SlObject(_industry_builder.builddata + index, _industrytype_builder_desc);
|
||||
SlObject(_industry_builder.builddata + index, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler industry_chunk_handlers[] = {
|
||||
{ 'INDY', Save_INDY, Load_INDY, Ptrs_INDY, nullptr, CH_ARRAY },
|
||||
{ 'IIDS', Save_IIDS, Load_IIDS, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'TIDS', Save_TIDS, Load_TIDS, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'IBLD', LoadSave_IBLD, LoadSave_IBLD, nullptr, nullptr, CH_RIFF },
|
||||
{ 'ITBL', Save_ITBL, Load_ITBL, nullptr, nullptr, CH_ARRAY },
|
||||
static const INDYChunkHandler INDY;
|
||||
static const IIDSChunkHandler IIDS;
|
||||
static const TIDSChunkHandler TIDS;
|
||||
static const IBLDChunkHandler IBLD;
|
||||
static const ITBLChunkHandler ITBL;
|
||||
static const ChunkHandlerRef industry_chunk_handlers[] = {
|
||||
INDY,
|
||||
IIDS,
|
||||
TIDS,
|
||||
IBLD,
|
||||
ITBL,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _industry_chunk_handlers(industry_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,94 +8,20 @@
|
||||
/** @file labelmaps_sl.cpp Code handling saving and loading of rail type label mappings */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/labelmaps_sl_compat.h"
|
||||
|
||||
#include "../station_map.h"
|
||||
#include "../tunnelbridge_map.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
std::vector<RailTypeLabel> _railtype_list;
|
||||
void ResetLabelMaps();
|
||||
|
||||
/**
|
||||
* Test if any saved rail type labels are different to the currently loaded
|
||||
* rail types, which therefore requires conversion.
|
||||
* @return true if (and only if) conversion due to rail type changes is needed.
|
||||
*/
|
||||
static bool NeedRailTypeConversion()
|
||||
{
|
||||
for (uint i = 0; i < _railtype_list.size(); i++) {
|
||||
if ((RailType)i < RAILTYPE_END) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo((RailType)i);
|
||||
if (rti->label != _railtype_list[i]) return true;
|
||||
} else {
|
||||
if (_railtype_list[i] != 0) return true;
|
||||
}
|
||||
}
|
||||
extern std::vector<RailTypeLabel> _railtype_list;
|
||||
|
||||
/* No rail type conversion is necessary */
|
||||
return false;
|
||||
}
|
||||
|
||||
void AfterLoadLabelMaps()
|
||||
{
|
||||
if (NeedRailTypeConversion()) {
|
||||
RailType railtype_conversion_map[RAILTYPE_END];
|
||||
|
||||
for (uint i = 0; i < _railtype_list.size(); i++) {
|
||||
RailType r = GetRailTypeByLabel(_railtype_list[i]);
|
||||
if (r == INVALID_RAILTYPE) r = RAILTYPE_BEGIN;
|
||||
|
||||
railtype_conversion_map[i] = r;
|
||||
}
|
||||
for (uint i = (uint)_railtype_list.size(); i < RAILTYPE_END; i++) {
|
||||
railtype_conversion_map[i] = RAILTYPE_RAIL;
|
||||
}
|
||||
|
||||
auto convert = [&](TileIndex t) {
|
||||
SetRailType(t, railtype_conversion_map[GetRailType(t)]);
|
||||
RailType secondary = GetTileSecondaryRailTypeIfValid(t);
|
||||
if (secondary != INVALID_RAILTYPE) SetSecondaryRailType(t, railtype_conversion_map[secondary]);
|
||||
};
|
||||
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
switch (GetTileType(t)) {
|
||||
case MP_RAILWAY:
|
||||
convert(t);
|
||||
break;
|
||||
|
||||
case MP_ROAD:
|
||||
if (IsLevelCrossing(t)) {
|
||||
convert(t);
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_STATION:
|
||||
if (HasStationRail(t)) {
|
||||
convert(t);
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_TUNNELBRIDGE:
|
||||
if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) {
|
||||
convert(t);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResetLabelMaps();
|
||||
}
|
||||
|
||||
void ResetLabelMaps()
|
||||
{
|
||||
_railtype_list.clear();
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
/** Container for a label for SaveLoad system */
|
||||
struct LabelObject {
|
||||
@@ -106,8 +32,13 @@ static const SaveLoad _label_object_desc[] = {
|
||||
SLE_VAR(LabelObject, label, SLE_UINT32),
|
||||
};
|
||||
|
||||
static void Save_RAIL()
|
||||
{
|
||||
struct RAILChunkHandler : ChunkHandler {
|
||||
RAILChunkHandler() : ChunkHandler('RAIL', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_label_object_desc);
|
||||
|
||||
LabelObject lo;
|
||||
|
||||
for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
|
||||
@@ -116,23 +47,28 @@ static void Save_RAIL()
|
||||
SlSetArrayIndex(r);
|
||||
SlObject(&lo, _label_object_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_label_object_desc, _label_object_sl_compat);
|
||||
|
||||
static void Load_RAIL()
|
||||
{
|
||||
ResetLabelMaps();
|
||||
|
||||
LabelObject lo;
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
SlObject(&lo, _label_object_desc);
|
||||
SlObject(&lo, slt);
|
||||
_railtype_list.push_back((RailTypeLabel)lo.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler labelmaps_chunk_handlers[] = {
|
||||
{ 'RAIL', Save_RAIL, Load_RAIL, nullptr, nullptr, CH_ARRAY },
|
||||
static const RAILChunkHandler RAIL;
|
||||
static const ChunkHandlerRef labelmaps_chunk_handlers[] = {
|
||||
RAIL,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _labelmaps_chunk_handlers(labelmaps_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -6,23 +6,91 @@
|
||||
*/
|
||||
|
||||
/** @file league_sl.cpp Code handling saving and loading of league tables */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
extern SaveLoadVersion _sl_xv_upstream_version;
|
||||
#include "../league_base.h"
|
||||
|
||||
struct GetLeagueChunkLoadInfo
|
||||
{
|
||||
static SaveLoadVersion GetLoadVersion()
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _league_table_elements_desc[] = {
|
||||
SLE_VAR(LeagueTableElement, table, SLE_UINT8),
|
||||
SLE_CONDVAR(LeagueTableElement, rating, SLE_FILE_U64 | SLE_VAR_I64, SL_MIN_VERSION, SLV_LINKGRAPH_EDGES),
|
||||
SLE_CONDVAR(LeagueTableElement, rating, SLE_INT64, SLV_LINKGRAPH_EDGES, SL_MAX_VERSION),
|
||||
SLE_VAR(LeagueTableElement, company, SLE_UINT8),
|
||||
SLE_SSTR(LeagueTableElement, text, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
SLE_SSTR(LeagueTableElement, score, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
SLE_VAR(LeagueTableElement, link.type, SLE_UINT8),
|
||||
SLE_VAR(LeagueTableElement, link.target, SLE_UINT32),
|
||||
};
|
||||
|
||||
struct LEAEChunkHandler : ChunkHandler {
|
||||
LEAEChunkHandler() : ChunkHandler('LEAE', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
return _sl_xv_upstream_version != SL_MIN_VERSION ? _sl_xv_upstream_version : SLV_MULTITRACK_LEVEL_CROSSINGS;
|
||||
SlTableHeader(_league_table_elements_desc);
|
||||
|
||||
for (LeagueTableElement *lte : LeagueTableElement::Iterate()) {
|
||||
SlSetArrayIndex(lte->index);
|
||||
SlObject(lte, _league_table_elements_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlTableHeader(_league_table_elements_desc);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
LeagueTableElement *lte = new (index) LeagueTableElement();
|
||||
SlObject(lte, slt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler league_chunk_handlers[] = {
|
||||
MakeUpstreamChunkHandler<'LEAE', GetLeagueChunkLoadInfo>(),
|
||||
MakeUpstreamChunkHandler<'LEAT', GetLeagueChunkLoadInfo>(),
|
||||
static const SaveLoad _league_tables_desc[] = {
|
||||
SLE_SSTR(LeagueTable, title, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
SLE_SSTR(LeagueTable, header, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
SLE_SSTR(LeagueTable, footer, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
};
|
||||
|
||||
struct LEATChunkHandler : ChunkHandler {
|
||||
LEATChunkHandler() : ChunkHandler('LEAT', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_league_tables_desc);
|
||||
|
||||
for (LeagueTable *lt : LeagueTable::Iterate()) {
|
||||
SlSetArrayIndex(lt->index);
|
||||
SlObject(lt, _league_tables_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlTableHeader(_league_tables_desc);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
LeagueTable *lt = new (index) LeagueTable();
|
||||
SlObject(lt, slt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const LEAEChunkHandler LEAE;
|
||||
static const LEATChunkHandler LEAT;
|
||||
static const ChunkHandlerRef league_chunk_handlers[] = {
|
||||
LEAE,
|
||||
LEAT,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _league_chunk_handlers(league_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,21 +8,115 @@
|
||||
/** @file linkgraph_sl.cpp Code handling saving and loading of link graphs */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/linkgraph_sl_compat.h"
|
||||
|
||||
#include "../linkgraph/linkgraph.h"
|
||||
#include "../linkgraph/linkgraphjob.h"
|
||||
#include "../linkgraph/linkgraphschedule.h"
|
||||
#include "../network/network.h"
|
||||
#include "../settings_internal.h"
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
typedef LinkGraph::BaseNode Node;
|
||||
typedef LinkGraph::BaseEdge Edge;
|
||||
|
||||
const SettingDesc *GetSettingDescription(uint index);
|
||||
|
||||
static uint16 _num_nodes;
|
||||
static LinkGraph *_linkgraph; ///< Contains the current linkgraph being saved/loaded.
|
||||
static NodeID _linkgraph_from; ///< Contains the current "from" node being saved/loaded.
|
||||
static NodeID _edge_dest_node;
|
||||
static NodeID _edge_next_edge;
|
||||
|
||||
class SlLinkgraphEdge : public DefaultSaveLoadHandler<SlLinkgraphEdge, Node> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(Edge, capacity, SLE_UINT32),
|
||||
SLE_VAR(Edge, usage, SLE_UINT32),
|
||||
SLE_CONDVAR(Edge, travel_time_sum, SLE_UINT64, SLV_LINKGRAPH_TRAVEL_TIME, SL_MAX_VERSION),
|
||||
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
|
||||
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
|
||||
SLEG_VAR("dest_node", _edge_dest_node, SLE_UINT16),
|
||||
SLEG_CONDVAR("next_edge", _edge_next_edge, SLE_UINT16, SL_MIN_VERSION, SLV_LINKGRAPH_EDGES),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _linkgraph_edge_sl_compat;
|
||||
|
||||
void Save(Node *bn) const override
|
||||
{
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
void Load(Node *bn) const override
|
||||
{
|
||||
uint16 max_size = _linkgraph->Size();
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_191)) {
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_LINKGRAPH_EDGES)) {
|
||||
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 = _edge_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[std::make_pair(_linkgraph_from, to)], this->GetLoadDescription());
|
||||
}
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");
|
||||
} else {
|
||||
/* Edge data is now a simple vector and not any kind of matrix. */
|
||||
size_t size = SlGetStructListLength(UINT16_MAX);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
Edge edge;
|
||||
SlObject(&edge, this->GetLoadDescription());
|
||||
if (_edge_dest_node >= max_size) SlErrorCorrupt("Link graph structure overflow");
|
||||
_linkgraph->edges[std::make_pair(_linkgraph_from, _edge_dest_node)] = edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlLinkgraphNode : public DefaultSaveLoadHandler<SlLinkgraphNode, LinkGraph> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(Node, xy, SLE_UINT32, SLV_191, SL_MAX_VERSION),
|
||||
SLE_VAR(Node, supply, SLE_UINT32),
|
||||
SLE_VAR(Node, demand, SLE_UINT32),
|
||||
SLE_VAR(Node, station, SLE_UINT16),
|
||||
SLE_VAR(Node, last_update, SLE_INT32),
|
||||
SLEG_STRUCTLIST("edges", SlLinkgraphEdge),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _linkgraph_node_sl_compat;
|
||||
|
||||
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;
|
||||
|
||||
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->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a SaveLoad array for a link graph.
|
||||
@@ -32,18 +126,36 @@ 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", _num_nodes, SLE_UINT16, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
|
||||
SLE_VAR(LinkGraph, cargo, SLE_UINT8),
|
||||
SLEG_STRUCTLIST("nodes", SlLinkgraphNode),
|
||||
};
|
||||
return link_graph_desc;
|
||||
}
|
||||
|
||||
void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj)
|
||||
{
|
||||
lgj->join_date_ticks *= DAY_TICKS;
|
||||
lgj->join_date_ticks += LinkGraphSchedule::SPAWN_JOIN_TICK;
|
||||
lgj->start_date_ticks = lgj->join_date_ticks - (lgj->Settings().recalc_time * DAY_TICKS);
|
||||
}
|
||||
/**
|
||||
* Proxy to reuse LinkGraph to save/load a LinkGraphJob.
|
||||
* One of the members of a LinkGraphJob is a LinkGraph, but SLEG_STRUCT()
|
||||
* doesn't allow us to select a member. So instead, we add a bit of glue to
|
||||
* accept a LinkGraphJob, get the LinkGraph, and use that to call the
|
||||
* save/load routines for a regular LinkGraph.
|
||||
*/
|
||||
class SlLinkgraphJobProxy : public DefaultSaveLoadHandler<SlLinkgraphJobProxy, LinkGraphJob> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {{}}; // Needed to keep DefaultSaveLoadHandler happy.
|
||||
SaveLoadTable GetDescription() const override { return GetLinkGraphDesc(); }
|
||||
inline const static SaveLoadCompatTable compat_description = _linkgraph_sl_compat;
|
||||
|
||||
void Save(LinkGraphJob *lgj) const override
|
||||
{
|
||||
SlObject(const_cast<LinkGraph *>(&lgj->Graph()), this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LinkGraphJob *lgj) const override
|
||||
{
|
||||
SlObject(const_cast<LinkGraph *>(&lgj->Graph()), this->GetLoadDescription());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a SaveLoad array for a link graph job. The settings struct is derived from
|
||||
@@ -56,43 +168,24 @@ void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj)
|
||||
*/
|
||||
SaveLoadTable GetLinkGraphJobDesc()
|
||||
{
|
||||
static std::vector<SaveLoad> saveloads;
|
||||
static const char *prefix = "linkgraph.";
|
||||
static const SaveLoad job_desc[] = {
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.recalc_interval", settings.recalc_interval, SLE_UINT16),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.recalc_time", settings.recalc_time, SLE_UINT16),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.distribution_pax", settings.distribution_pax, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.distribution_mail", settings.distribution_mail, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.distribution_armoured", settings.distribution_armoured, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.distribution_default", settings.distribution_default, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.accuracy", settings.accuracy, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.demand_distance", settings.demand_distance, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.demand_size", settings.demand_size, SLE_UINT8),
|
||||
SLE_VAR2(LinkGraphJob, "linkgraph.short_path_saturation", settings.short_path_saturation, SLE_UINT8),
|
||||
|
||||
/* Build the SaveLoad array on first call and don't touch it later on */
|
||||
if (saveloads.size() == 0) {
|
||||
size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
|
||||
size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
|
||||
|
||||
size_t prefixlen = strlen(prefix);
|
||||
|
||||
int setting = 0;
|
||||
const SettingDesc *desc = GetSettingDescription(setting);
|
||||
while (desc != nullptr) {
|
||||
if (desc->name != nullptr && strncmp(desc->name, prefix, prefixlen) == 0) {
|
||||
SaveLoad sl = desc->save;
|
||||
if (GetVarMemType(sl.conv) != SLE_VAR_NULL) {
|
||||
char *&address = reinterpret_cast<char *&>(sl.address);
|
||||
address -= offset_gamesettings;
|
||||
address += offset_component;
|
||||
}
|
||||
saveloads.push_back(sl);
|
||||
}
|
||||
desc = GetSettingDescription(++setting);
|
||||
}
|
||||
|
||||
const SaveLoad job_desc[] = {
|
||||
SLE_VAR(LinkGraphJob, join_date_ticks, SLE_INT32),
|
||||
SLE_CONDVAR_X(LinkGraphJob, start_date_ticks, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_DAY_SCALE)),
|
||||
SLE_VAR2(LinkGraphJob, "join_date", join_date_ticks, SLE_INT32),
|
||||
SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
|
||||
SLEG_STRUCT("linkgraph", SlLinkgraphJobProxy),
|
||||
};
|
||||
|
||||
for (auto &sld : job_desc) {
|
||||
saveloads.push_back(sld);
|
||||
}
|
||||
}
|
||||
|
||||
return saveloads;
|
||||
return job_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,190 +201,6 @@ SaveLoadTable GetLinkGraphScheduleDesc()
|
||||
return schedule_desc;
|
||||
}
|
||||
|
||||
/* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
|
||||
|
||||
/**
|
||||
* SaveLoad desc for a link graph node.
|
||||
*/
|
||||
static const SaveLoad _node_desc[] = {
|
||||
SLE_CONDVAR(Node, xy, SLE_UINT32, SLV_191, SL_MAX_VERSION),
|
||||
SLE_VAR(Node, supply, SLE_UINT32),
|
||||
SLE_VAR(Node, demand, SLE_UINT32),
|
||||
SLE_VAR(Node, station, SLE_UINT16),
|
||||
SLE_VAR(Node, last_update, SLE_INT32),
|
||||
};
|
||||
|
||||
/**
|
||||
* SaveLoad desc for a link graph edge.
|
||||
*/
|
||||
static const SaveLoad _edge_desc[] = {
|
||||
SLE_CONDNULL(4, SL_MIN_VERSION, SLV_191), // distance
|
||||
SLE_VAR(Edge, capacity, SLE_UINT32),
|
||||
SLE_VAR(Edge, usage, SLE_UINT32),
|
||||
SLE_CONDVAR_X(Edge, travel_time_sum, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_TRAVEL_TIME)),
|
||||
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
|
||||
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(Edge, last_aircraft_update, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_LINKGRAPH_AIRCRAFT)),
|
||||
// SLE_VAR(Edge, next_edge, SLE_UINT16), // Removed since XSLFI_LINKGRAPH_SPARSE_EDGES
|
||||
};
|
||||
|
||||
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 a link graph.
|
||||
* @param lg Link graph to be saved or loaded.
|
||||
*/
|
||||
void Save_LinkGraph(LinkGraph &lg)
|
||||
{
|
||||
uint16 size = lg.Size();
|
||||
auto edge_iter = lg.edges.begin();
|
||||
auto edge_end = lg.edges.end();
|
||||
for (NodeID from = 0; from < size; ++from) {
|
||||
Node *node = &lg.nodes[from];
|
||||
SlObjectSaveFiltered(node, _filtered_node_desc);
|
||||
|
||||
while (edge_iter != edge_end && edge_iter->first.first == from) {
|
||||
SlWriteUint16(edge_iter->first.second);
|
||||
Edge *edge = &edge_iter->second;
|
||||
SlObjectSaveFiltered(edge, _filtered_edge_desc);
|
||||
++edge_iter;
|
||||
}
|
||||
SlWriteUint16(INVALID_NODE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a link graph.
|
||||
* @param lg Link graph to be saved or loaded.
|
||||
*/
|
||||
void Load_LinkGraph(LinkGraph &lg)
|
||||
{
|
||||
uint size = lg.Size();
|
||||
if (SlXvIsFeaturePresent(XSLFI_LINKGRAPH_SPARSE_EDGES)) {
|
||||
for (NodeID from = 0; from < size; ++from) {
|
||||
Node *node = &lg.nodes[from];
|
||||
SlObjectLoadFiltered(node, _filtered_node_desc);
|
||||
while (true) {
|
||||
NodeID to = SlReadUint16();
|
||||
if (to == INVALID_NODE) break;
|
||||
SlObjectLoadFiltered(&lg.edges[std::make_pair(from, to)], _filtered_edge_desc);
|
||||
}
|
||||
}
|
||||
} else if (IsSavegameVersionBefore(SLV_191)) {
|
||||
std::vector<Edge> temp_edges;
|
||||
std::vector<NodeID> temp_next_edges;
|
||||
temp_edges.resize(size);
|
||||
temp_next_edges.resize(size);
|
||||
for (NodeID from = 0; from < size; ++from) {
|
||||
Node *node = &lg.nodes[from];
|
||||
SlObjectLoadFiltered(node, _filtered_node_desc);
|
||||
/* We used to save the full matrix ... */
|
||||
for (NodeID to = 0; to < size; ++to) {
|
||||
SlObjectLoadFiltered(&temp_edges[to], _filtered_edge_desc);
|
||||
temp_next_edges[to] = SlReadUint16();
|
||||
}
|
||||
for (NodeID to = from; to != INVALID_NODE; to = temp_next_edges[to]) {
|
||||
lg.edges[std::make_pair(from, to)] = temp_edges[to];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (NodeID from = 0; from < size; ++from) {
|
||||
Node *node = &lg.nodes[from];
|
||||
SlObjectLoadFiltered(node, _filtered_node_desc);
|
||||
/* ... but as that wasted a lot of space we save a sparse matrix now. */
|
||||
for (NodeID to = from; to != INVALID_NODE;) {
|
||||
if (to >= size) SlErrorCorrupt("Link graph structure overflow");
|
||||
SlObjectLoadFiltered(&lg.edges[std::make_pair(from, to)], _filtered_edge_desc);
|
||||
to = SlReadUint16();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a link graph job.
|
||||
* @param lgj LinkGraphJob to be saved.
|
||||
*/
|
||||
static void DoSave_LGRJ(LinkGraphJob *lgj)
|
||||
{
|
||||
SlObjectSaveFiltered(lgj, _filtered_job_desc);
|
||||
_num_nodes = lgj->Size();
|
||||
SlObjectSaveFiltered(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
|
||||
Save_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a link graph.
|
||||
* @param lg LinkGraph to be saved.
|
||||
*/
|
||||
static void DoSave_LGRP(LinkGraph *lg)
|
||||
{
|
||||
_num_nodes = lg->Size();
|
||||
SlObjectSaveFiltered(lg, GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
|
||||
Save_LinkGraph(*lg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all link graphs.
|
||||
*/
|
||||
static void Load_LGRP()
|
||||
{
|
||||
FilterDescs();
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if (!LinkGraph::CanAllocateItem()) {
|
||||
/* Impossible as they have been present in previous game. */
|
||||
NOT_REACHED();
|
||||
}
|
||||
LinkGraph *lg = new (index) LinkGraph();
|
||||
SlObjectLoadFiltered(lg, GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
|
||||
lg->Init(_num_nodes);
|
||||
Load_LinkGraph(*lg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all link graph jobs.
|
||||
*/
|
||||
static void Load_LGRJ()
|
||||
{
|
||||
FilterDescs();
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if (!LinkGraphJob::CanAllocateItem()) {
|
||||
/* Impossible as they have been present in previous game. */
|
||||
NOT_REACHED();
|
||||
}
|
||||
LinkGraphJob *lgj = new (index) LinkGraphJob();
|
||||
SlObjectLoadFiltered(lgj, _filtered_job_desc);
|
||||
if (SlXvIsFeatureMissing(XSLFI_LINKGRAPH_DAY_SCALE)) {
|
||||
extern void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj);
|
||||
GetLinkGraphJobDayLengthScaleAfterLoad(lgj);
|
||||
}
|
||||
LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
|
||||
SlObjectLoadFiltered(&lg, GetLinkGraphDesc()); // GetLinkGraphDesc has no conditionals
|
||||
lg.Init(_num_nodes);
|
||||
Load_LinkGraph(lg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the link graph schedule.
|
||||
*/
|
||||
static void Load_LGRS()
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn the threads for running link graph calculations.
|
||||
* Has to be done after loading as the cargo classes might have changed.
|
||||
@@ -314,6 +223,9 @@ void AfterLoadLinkGraphs()
|
||||
}
|
||||
}
|
||||
}
|
||||
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
||||
GetLinkGraphJobDayLengthScaleAfterLoad(lgj);
|
||||
}
|
||||
|
||||
LinkGraphSchedule::instance.SpawnAll();
|
||||
|
||||
@@ -323,49 +235,99 @@ void AfterLoadLinkGraphs()
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all link graphs.
|
||||
* All link graphs.
|
||||
*/
|
||||
static void Save_LGRP()
|
||||
{
|
||||
FilterDescs();
|
||||
struct LGRPChunkHandler : ChunkHandler {
|
||||
LGRPChunkHandler() : ChunkHandler('LGRP', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(GetLinkGraphDesc());
|
||||
|
||||
for (LinkGraph *lg : LinkGraph::Iterate()) {
|
||||
SlSetArrayIndex(lg->index);
|
||||
SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
|
||||
SlObject(lg, GetLinkGraphDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphDesc(), _linkgraph_sl_compat);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
LinkGraph *lg = new (index) LinkGraph();
|
||||
SlObject(lg, slt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Save all link graph jobs.
|
||||
* All link graph jobs.
|
||||
*/
|
||||
static void Save_LGRJ()
|
||||
{
|
||||
FilterDescs();
|
||||
struct LGRJChunkHandler : ChunkHandler {
|
||||
LGRJChunkHandler() : ChunkHandler('LGRJ', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(GetLinkGraphJobDesc());
|
||||
|
||||
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
||||
SlSetArrayIndex(lgj->index);
|
||||
SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
|
||||
SlObject(lgj, GetLinkGraphJobDesc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphJobDesc(), _linkgraph_job_sl_compat);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
LinkGraphJob *lgj = new (index) LinkGraphJob();
|
||||
SlObject(lgj, slt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the link graph schedule.
|
||||
* Link graph schedule.
|
||||
*/
|
||||
static void Save_LGRS()
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
struct LGRSChunkHandler : ChunkHandler {
|
||||
LGRSChunkHandler() : ChunkHandler('LGRS', CH_TABLE) {}
|
||||
|
||||
/**
|
||||
* Substitute pointers in link graph schedule.
|
||||
*/
|
||||
static void Ptrs_LGRS()
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(GetLinkGraphScheduleDesc());
|
||||
|
||||
static const ChunkHandler linkgraph_chunk_handlers[] = {
|
||||
{ 'LGRP', Save_LGRP, Load_LGRP, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'LGRJ', Save_LGRJ, Load_LGRJ, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_RIFF }
|
||||
SlSetArrayIndex(0);
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphScheduleDesc(), _linkgraph_schedule_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlObject(&LinkGraphSchedule::instance, slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries");
|
||||
}
|
||||
|
||||
void FixPointers() const override
|
||||
{
|
||||
SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
|
||||
}
|
||||
};
|
||||
|
||||
static const LGRPChunkHandler LGRP;
|
||||
static const LGRJChunkHandler LGRJ;
|
||||
static const LGRSChunkHandler LGRS;
|
||||
static const ChunkHandlerRef linkgraph_chunk_handlers[] = {
|
||||
LGRP,
|
||||
LGRJ,
|
||||
LGRS,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _linkgraph_chunk_handlers(linkgraph_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,172 +8,271 @@
|
||||
/** @file map_sl.cpp Code handling saving and loading of map */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/map_sl_compat.h"
|
||||
|
||||
#include "../map_func.h"
|
||||
#include "../core/bitmath_func.hpp"
|
||||
#include "../core/endian_func.hpp"
|
||||
#include "../core/endian_type.hpp"
|
||||
#include "../fios.h"
|
||||
#include <array>
|
||||
|
||||
#include "saveload.h"
|
||||
#include "saveload_buffer.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static uint32 _map_dim_x;
|
||||
static uint32 _map_dim_y;
|
||||
|
||||
extern bool _sl_maybe_chillpp;
|
||||
|
||||
static const SaveLoad _map_dimensions[] = {
|
||||
SLEG_CONDVAR(_map_dim_x, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR(_map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
static const SaveLoad _map_desc[] = {
|
||||
SLEG_CONDVAR("dim_x", _map_dim_x, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("dim_y", _map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_MAPS()
|
||||
{
|
||||
struct MAPSChunkHandler : ChunkHandler {
|
||||
MAPSChunkHandler() : ChunkHandler('MAPS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_map_desc);
|
||||
|
||||
_map_dim_x = MapSizeX();
|
||||
_map_dim_y = MapSizeY();
|
||||
SlGlobList(_map_dimensions);
|
||||
}
|
||||
|
||||
static void Load_MAPS()
|
||||
{
|
||||
SlGlobList(_map_dimensions);
|
||||
if (!ValidateMapSize(_map_dim_x, _map_dim_y)) {
|
||||
SlErrorCorruptFmt("Invalid map size: %u x %u", _map_dim_x, _map_dim_y);
|
||||
SlSetArrayIndex(0);
|
||||
SlGlobList(_map_desc);
|
||||
}
|
||||
AllocateMap(_map_dim_x, _map_dim_y);
|
||||
}
|
||||
|
||||
static void Check_MAPS()
|
||||
{
|
||||
SlGlobList(_map_dimensions);
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlGlobList(slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
|
||||
|
||||
AllocateMap(_map_dim_x, _map_dim_y);
|
||||
}
|
||||
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_map_desc, _map_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlGlobList(slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries");
|
||||
|
||||
_load_check_data.map_size_x = _map_dim_x;
|
||||
_load_check_data.map_size_y = _map_dim_y;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const uint MAP_SL_BUF_SIZE = 4096;
|
||||
|
||||
static void Load_MAPT()
|
||||
{
|
||||
struct MAPTChunkHandler : ChunkHandler {
|
||||
MAPTChunkHandler() : ChunkHandler('MAPT', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type = buf[j];
|
||||
}
|
||||
}
|
||||
|
||||
static void Check_MAPH_common()
|
||||
{
|
||||
if (_sl_maybe_chillpp && (SlGetFieldLength() == 0 || SlGetFieldLength() == (size_t)_map_dim_x * (size_t)_map_dim_y * 2)) {
|
||||
_sl_maybe_chillpp = false;
|
||||
extern void SlXvChillPPSpecialSavegameVersions();
|
||||
SlXvChillPPSpecialSavegameVersions();
|
||||
}
|
||||
}
|
||||
|
||||
static void Check_MAPH()
|
||||
{
|
||||
Check_MAPH_common();
|
||||
SlSkipBytes(SlGetFieldLength());
|
||||
}
|
||||
|
||||
static void Load_MAPH()
|
||||
{
|
||||
Check_MAPH_common();
|
||||
if (SlXvIsFeaturePresent(XSLFI_CHILLPP)) {
|
||||
if (SlGetFieldLength() != 0) {
|
||||
_sl_xv_feature_versions[XSLFI_HEIGHT_8_BIT] = 2;
|
||||
std::array<uint16, MAP_SL_BUF_SIZE> buf;
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
struct MAPHChunkHandler : ChunkHandler {
|
||||
MAPHChunkHandler() : ChunkHandler('MAPH', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].height = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP1()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MAPOChunkHandler : ChunkHandler {
|
||||
MAPOChunkHandler() : ChunkHandler('MAPO', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP2()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MAP2ChunkHandler : ChunkHandler {
|
||||
MAP2ChunkHandler() : ChunkHandler('MAP2', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<uint16, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE,
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE,
|
||||
/* In those versions the m2 was 8 bits */
|
||||
IsSavegameVersionBefore(SLV_5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
|
||||
);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP3()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<uint16, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size * sizeof(uint16));
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct M3LOChunkHandler : ChunkHandler {
|
||||
M3LOChunkHandler() : ChunkHandler('M3LO', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP4()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct M3HIChunkHandler : ChunkHandler {
|
||||
M3HIChunkHandler() : ChunkHandler('M3HI', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP5()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MAP5ChunkHandler : ChunkHandler {
|
||||
MAP5ChunkHandler() : ChunkHandler('MAP5', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP6()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MAPEChunkHandler : ChunkHandler {
|
||||
MAPEChunkHandler() : ChunkHandler('MAPE', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_42)) {
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
/* 1024, otherwise we overflow on 64x64 maps! */
|
||||
SlArray(buf.data(), 1024, SLE_UINT8);
|
||||
SlCopy(buf.data(), 1024, SLE_UINT8);
|
||||
for (uint j = 0; j != 1024; j++) {
|
||||
_me[i++].m6 = GB(buf[j], 0, 2);
|
||||
_me[i++].m6 = GB(buf[j], 2, 2);
|
||||
@@ -183,238 +282,104 @@ static void Load_MAP6()
|
||||
}
|
||||
} else {
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m6 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP7()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MAP7ChunkHandler : ChunkHandler {
|
||||
MAP7ChunkHandler() : ChunkHandler('MAP7', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_MAP8()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
std::array<byte, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size);
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MAP8ChunkHandler : ChunkHandler {
|
||||
MAP8ChunkHandler() : ChunkHandler('MAP8', CH_RIFF) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::array<uint16, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m8 = buf[j];
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_WMAP()
|
||||
{
|
||||
static_assert(sizeof(Tile) == 8);
|
||||
static_assert(sizeof(TileExtended) == 4);
|
||||
assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 1 || _sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 2);
|
||||
|
||||
ReadBuffer *reader = ReadBuffer::GetCurrent();
|
||||
const TileIndex size = MapSize();
|
||||
|
||||
#if TTD_ENDIAN == TTD_LITTLE_ENDIAN
|
||||
reader->CopyBytes((byte *) _m, size * 8);
|
||||
#else
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
reader->CheckBytes(8);
|
||||
_m[i].type = reader->RawReadByte();
|
||||
_m[i].height = reader->RawReadByte();
|
||||
uint16 m2 = reader->RawReadByte();
|
||||
m2 |= ((uint16) reader->RawReadByte()) << 8;
|
||||
_m[i].m2 = m2;
|
||||
_m[i].m1 = reader->RawReadByte();
|
||||
_m[i].m3 = reader->RawReadByte();
|
||||
_m[i].m4 = reader->RawReadByte();
|
||||
_m[i].m5 = reader->RawReadByte();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 1) {
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
reader->CheckBytes(2);
|
||||
_me[i].m6 = reader->RawReadByte();
|
||||
_me[i].m7 = reader->RawReadByte();
|
||||
}
|
||||
} else if (_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 2) {
|
||||
#if TTD_ENDIAN == TTD_LITTLE_ENDIAN
|
||||
reader->CopyBytes((byte *) _me, size * 4);
|
||||
#else
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
reader->CheckBytes(4);
|
||||
_me[i].m6 = reader->RawReadByte();
|
||||
_me[i].m7 = reader->RawReadByte();
|
||||
uint16 m8 = reader->RawReadByte();
|
||||
m8 |= ((uint16) reader->RawReadByte()) << 8;
|
||||
_me[i].m8 = m8;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_WMAP()
|
||||
{
|
||||
static_assert(sizeof(Tile) == 8);
|
||||
static_assert(sizeof(TileExtended) == 4);
|
||||
assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 2);
|
||||
|
||||
MemoryDumper *dumper = MemoryDumper::GetCurrent();
|
||||
const TileIndex size = MapSize();
|
||||
SlSetLength(size * 12);
|
||||
|
||||
#if TTD_ENDIAN == TTD_LITTLE_ENDIAN
|
||||
dumper->CopyBytes((byte *) _m, size * 8);
|
||||
dumper->CopyBytes((byte *) _me, size * 4);
|
||||
#else
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
dumper->CheckBytes(8);
|
||||
dumper->RawWriteByte(_m[i].type);
|
||||
dumper->RawWriteByte(_m[i].height);
|
||||
dumper->RawWriteByte(GB(_m[i].m2, 0, 8));
|
||||
dumper->RawWriteByte(GB(_m[i].m2, 8, 8));
|
||||
dumper->RawWriteByte(_m[i].m1);
|
||||
dumper->RawWriteByte(_m[i].m3);
|
||||
dumper->RawWriteByte(_m[i].m4);
|
||||
dumper->RawWriteByte(_m[i].m5);
|
||||
}
|
||||
for (TileIndex i = 0; i != size; i++) {
|
||||
dumper->CheckBytes(4);
|
||||
dumper->RawWriteByte(_me[i].m6);
|
||||
dumper->RawWriteByte(_me[i].m7);
|
||||
dumper->RawWriteByte(GB(_me[i].m8, 0, 8));
|
||||
dumper->RawWriteByte(GB(_me[i].m8, 8, 8));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct MAPT {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].type; }
|
||||
};
|
||||
|
||||
struct MAPH {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].height; }
|
||||
};
|
||||
|
||||
struct MAP1 {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].m1; }
|
||||
};
|
||||
|
||||
struct MAP2 {
|
||||
typedef uint16 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].m2; }
|
||||
};
|
||||
|
||||
struct MAP3 {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].m3; }
|
||||
};
|
||||
|
||||
struct MAP4 {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].m4; }
|
||||
};
|
||||
|
||||
struct MAP5 {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _m[t].m5; }
|
||||
};
|
||||
|
||||
struct MAP6 {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _me[t].m6; }
|
||||
};
|
||||
|
||||
struct MAP7 {
|
||||
typedef uint8 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _me[t].m7; }
|
||||
};
|
||||
|
||||
struct MAP8 {
|
||||
typedef uint16 FieldT;
|
||||
static const FieldT &GetField(TileIndex t) { return _me[t].m8; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MAP_VarType {};
|
||||
|
||||
template <>
|
||||
struct MAP_VarType<uint8>
|
||||
{
|
||||
static const VarType var_type = SLE_UINT8;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MAP_VarType<uint16>
|
||||
{
|
||||
static const VarType var_type = SLE_UINT16;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static void Save_MAP()
|
||||
{
|
||||
assert(_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 0);
|
||||
|
||||
std::array<typename T::FieldT, MAP_SL_BUF_SIZE> buf;
|
||||
void Save() const override
|
||||
{
|
||||
std::array<uint16, MAP_SL_BUF_SIZE> buf;
|
||||
TileIndex size = MapSize();
|
||||
|
||||
SlSetLength(size * sizeof(typename T::FieldT));
|
||||
SlSetLength(size * sizeof(uint16));
|
||||
for (TileIndex i = 0; i != size;) {
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = T::GetField(i++);
|
||||
SlArray(buf.data(), MAP_SL_BUF_SIZE, MAP_VarType<typename T::FieldT>::var_type);
|
||||
for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8;
|
||||
SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16);
|
||||
}
|
||||
}
|
||||
|
||||
static ChunkSaveLoadSpecialOpResult Special_WMAP(uint32 chunk_id, ChunkSaveLoadSpecialOp op)
|
||||
{
|
||||
switch (op) {
|
||||
case CSLSO_SHOULD_SAVE_CHUNK:
|
||||
if (_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] == 0) return CSLSOR_DONT_SAVE_CHUNK;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CSLSOR_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
static ChunkSaveLoadSpecialOpResult Special_MAP_Chunks(uint32 chunk_id, ChunkSaveLoadSpecialOp op)
|
||||
{
|
||||
switch (op) {
|
||||
case CSLSO_SHOULD_SAVE_CHUNK:
|
||||
if (_sl_xv_feature_versions[XSLFI_WHOLE_MAP_CHUNK] != 0) return CSLSOR_DONT_SAVE_CHUNK;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CSLSOR_NONE;
|
||||
}
|
||||
|
||||
static const ChunkHandler map_chunk_handlers[] = {
|
||||
{ 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_RIFF },
|
||||
{ 'MAPT', Save_MAP<MAPT>, Load_MAPT, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAPH', Save_MAP<MAPH>, Load_MAPH, nullptr, Check_MAPH, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAPO', Save_MAP<MAP1>, Load_MAP1, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAP2', Save_MAP<MAP2>, Load_MAP2, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'M3LO', Save_MAP<MAP3>, Load_MAP3, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'M3HI', Save_MAP<MAP4>, Load_MAP4, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAP5', Save_MAP<MAP5>, Load_MAP5, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAPE', Save_MAP<MAP6>, Load_MAP6, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAP7', Save_MAP<MAP7>, Load_MAP7, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'MAP8', Save_MAP<MAP8>, Load_MAP8, nullptr, nullptr, CH_RIFF, Special_MAP_Chunks },
|
||||
{ 'WMAP', Save_WMAP, Load_WMAP, nullptr, nullptr, CH_RIFF, Special_WMAP },
|
||||
static const MAPSChunkHandler MAPS;
|
||||
static const MAPTChunkHandler MAPT;
|
||||
static const MAPHChunkHandler MAPH;
|
||||
static const MAPOChunkHandler MAPO;
|
||||
static const MAP2ChunkHandler MAP2;
|
||||
static const M3LOChunkHandler M3LO;
|
||||
static const M3HIChunkHandler M3HI;
|
||||
static const MAP5ChunkHandler MAP5;
|
||||
static const MAPEChunkHandler MAPE;
|
||||
static const MAP7ChunkHandler MAP7;
|
||||
static const MAP8ChunkHandler MAP8;
|
||||
static const ChunkHandlerRef map_chunk_handlers[] = {
|
||||
MAPS,
|
||||
MAPT,
|
||||
MAPH,
|
||||
MAPO,
|
||||
MAP2,
|
||||
M3LO,
|
||||
M3HI,
|
||||
MAP5,
|
||||
MAPE,
|
||||
MAP7,
|
||||
MAP8,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,6 +8,10 @@
|
||||
/** @file misc_sl.cpp Saving and loading of things that didn't fit anywhere else */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/misc_sl_compat.h"
|
||||
|
||||
#include "../date_func.h"
|
||||
#include "../zoom_func.h"
|
||||
#include "../window_gui.h"
|
||||
@@ -16,171 +20,128 @@
|
||||
#include "../gfx_func.h"
|
||||
#include "../core/random_func.hpp"
|
||||
#include "../fios.h"
|
||||
#include "../road_type.h"
|
||||
#include "../core/checksum_func.hpp"
|
||||
#include "../event_logs.h"
|
||||
#include "../timer/timer.h"
|
||||
#include "../timer/timer_game_tick.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
extern TileIndex _cur_tileloop_tile;
|
||||
extern TileIndex _aux_tileloop_tile;
|
||||
extern uint16 _disaster_delay;
|
||||
extern byte _trees_tick_ctr;
|
||||
extern uint64 _aspect_cfg_hash;
|
||||
|
||||
/* Keep track of current game position */
|
||||
int _saved_scrollpos_x;
|
||||
int _saved_scrollpos_y;
|
||||
ZoomLevel _saved_scrollpos_zoom;
|
||||
extern int _saved_scrollpos_x;
|
||||
extern int _saved_scrollpos_y;
|
||||
extern ZoomLevel _saved_scrollpos_zoom;
|
||||
|
||||
void SaveViewportBeforeSaveGame()
|
||||
{
|
||||
const Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
|
||||
|
||||
if (w != nullptr) {
|
||||
_saved_scrollpos_x = w->viewport->scrollpos_x;
|
||||
_saved_scrollpos_y = w->viewport->scrollpos_y;
|
||||
_saved_scrollpos_zoom = w->viewport->zoom;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetViewportAfterLoadGame()
|
||||
{
|
||||
Window *w = GetMainWindow();
|
||||
|
||||
w->viewport->scrollpos_x = _saved_scrollpos_x;
|
||||
w->viewport->scrollpos_y = _saved_scrollpos_y;
|
||||
w->viewport->dest_scrollpos_x = _saved_scrollpos_x;
|
||||
w->viewport->dest_scrollpos_y = _saved_scrollpos_y;
|
||||
|
||||
Viewport *vp = w->viewport;
|
||||
vp->zoom = std::min(_saved_scrollpos_zoom, ZOOM_LVL_MAX);
|
||||
vp->virtual_width = ScaleByZoom(vp->width, vp->zoom);
|
||||
vp->virtual_height = ScaleByZoom(vp->height, vp->zoom);
|
||||
|
||||
/* If zoom_max is ZOOM_LVL_MIN then the setting has not been loaded yet, therefore all levels are allowed. */
|
||||
if (_settings_client.gui.zoom_max != ZOOM_LVL_MIN) {
|
||||
/* Ensure zoom level is allowed */
|
||||
while (vp->zoom < _settings_client.gui.zoom_min) DoZoomInOutWindow(ZOOM_OUT, w);
|
||||
while (vp->zoom > _settings_client.gui.zoom_max) DoZoomInOutWindow(ZOOM_IN, w);
|
||||
}
|
||||
|
||||
DoZoomInOutWindow(ZOOM_NONE, w); // update button status
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
byte _age_cargo_skip_counter; ///< Skip aging of cargo? Used before savegame version 162.
|
||||
extern byte _age_cargo_skip_counter; ///< Skip aging of cargo? Used before savegame version 162.
|
||||
extern TimeoutTimer<TimerGameTick> _new_competitor_timeout;
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _date_desc[] = {
|
||||
SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLEG_CONDVAR(_date, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
SLEG_VAR(_date_fract, SLE_UINT16),
|
||||
SLEG_CONDVAR_X(_tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0)),
|
||||
SLEG_CONDVAR_X(_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)),
|
||||
SLEG_CONDVAR_X(_tick_skip_counter, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH)),
|
||||
SLEG_CONDVAR_X(_scaled_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)),
|
||||
SLEG_CONDVAR_X(_scaled_date_ticks_offset, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157), // _vehicle_id_ctr_day
|
||||
SLEG_CONDVAR(_age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162),
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46),
|
||||
SLEG_CONDVAR(_cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLEG_CONDVAR(_cur_tileloop_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_VAR(_disaster_delay, SLE_UINT16),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_120),
|
||||
SLEG_VAR(_random.state[0], SLE_UINT32),
|
||||
SLEG_VAR(_random.state[1], SLE_UINT32),
|
||||
SLEG_CONDVAR_X(_state_checksum.state, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_STATE_CHECKSUM)),
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_10),
|
||||
SLE_CONDNULL(4, SLV_10, SLV_120),
|
||||
SLEG_VAR(_cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32),
|
||||
SLEG_CONDVAR(_new_competitor_timeout.period, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_109),
|
||||
SLEG_CONDVAR_X(_new_competitor_timeout.period, SLE_UINT32, SLV_109, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AI_START_DATE, 0, 0)),
|
||||
SLEG_VAR(_trees_tick_ctr, SLE_UINT8),
|
||||
SLEG_CONDVAR(_pause_mode, SLE_UINT8, SLV_4, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR_X(_game_events_overall, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_GAME_EVENTS)),
|
||||
SLEG_CONDVAR_X(_road_layout_change_counter, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ROAD_LAYOUT_CHANGE_CTR)),
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 4, 6)), // _extra_aspects
|
||||
SLEG_CONDVAR_X(_aspect_cfg_hash, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 7)),
|
||||
SLEG_CONDVAR_X(_aux_tileloop_tile, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AUX_TILE_LOOP)),
|
||||
SLE_CONDNULL(4, SLV_11, SLV_120),
|
||||
SLEG_CONDVAR_X(_new_competitor_timeout.period, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AI_START_DATE)),
|
||||
SLEG_CONDVAR_X(_new_competitor_timeout.storage.elapsed, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AI_START_DATE)),
|
||||
SLEG_CONDVAR_X(_new_competitor_timeout.fired, SLE_BOOL, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AI_START_DATE)),
|
||||
SLEG_CONDVAR("date", _date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLEG_CONDVAR("date", _date, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
SLEG_VAR("date_fract", _date_fract, SLE_UINT16),
|
||||
SLEG_CONDVAR("tick_counter", _tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER),
|
||||
SLEG_CONDVAR("tick_counter", _tick_counter, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("age_cargo_skip_counter", _age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162),
|
||||
SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_VAR("next_disaster_start", _disaster_delay, SLE_UINT16),
|
||||
SLEG_VAR("random_state[0]", _random.state[0], SLE_UINT32),
|
||||
SLEG_VAR("random_state[1]", _random.state[1], SLE_UINT32),
|
||||
SLEG_VAR("company_tick_counter", _cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32),
|
||||
SLEG_VAR("trees_tick_counter", _trees_tick_ctr, SLE_UINT8),
|
||||
SLEG_CONDVAR("pause_mode", _pause_mode, SLE_UINT8, SLV_4, SL_MAX_VERSION),
|
||||
/* For older savegames, we load the current value as the "period"; afterload will set the "fired" and "elapsed". */
|
||||
SLEG_CONDVAR("next_competitor_start", _new_competitor_timeout.period, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_109),
|
||||
SLEG_CONDVAR("next_competitor_start", _new_competitor_timeout.period, SLE_UINT32, SLV_109, SLV_AI_START_DATE),
|
||||
SLEG_CONDVAR("competitors_interval", _new_competitor_timeout.period, SLE_UINT32, SLV_AI_START_DATE, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("competitors_interval_elapsed", _new_competitor_timeout.storage.elapsed, SLE_UINT32, SLV_AI_START_DATE, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("competitors_interval_fired", _new_competitor_timeout.fired, SLE_BOOL, SLV_AI_START_DATE, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static const SaveLoad _date_check_desc[] = {
|
||||
SLEG_CONDVAR(_load_check_data.current_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLEG_CONDVAR(_load_check_data.current_date, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
SLE_NULL(2), // _date_fract
|
||||
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0)), // _tick_counter
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)), // _tick_counter
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH)), // _tick_skip_counter
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)), // _scaled_tick_counter
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)), // _scaled_date_ticks_offset
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157), // _vehicle_id_ctr_day
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_162), // _age_cargo_skip_counter
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_6), // _cur_tileloop_tile
|
||||
SLE_CONDNULL(4, SLV_6, SL_MAX_VERSION), // _cur_tileloop_tile
|
||||
SLE_NULL(2), // _disaster_delay
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_120),
|
||||
SLE_NULL(4), // _random.state[0]
|
||||
SLE_NULL(4), // _random.state[1]
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_STATE_CHECKSUM)), // _state_checksum.state
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_10),
|
||||
SLE_CONDNULL(4, SLV_10, SLV_120),
|
||||
SLE_NULL(1), // _cur_company_tick_index
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_109), // _new_competitor_timeout.period
|
||||
SLE_CONDNULL_X(4, SLV_109, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AI_START_DATE, 0, 0)), // _new_competitor_timeout.period
|
||||
SLE_NULL(1), // _trees_tick_ctr
|
||||
SLE_CONDNULL(1, SLV_4, SL_MAX_VERSION), // _pause_mode
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_GAME_EVENTS)), // _game_events_overall
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ROAD_LAYOUT_CHANGE_CTR)), // _road_layout_change_counter
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 4, 6)), // _extra_aspects
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 7)), // _aspect_cfg_hash
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AUX_TILE_LOOP)), // _aux_tileloop_tile
|
||||
SLE_CONDNULL(4, SLV_11, SLV_120),
|
||||
SLE_CONDNULL_X(9, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_AI_START_DATE)), // _new_competitor_timeout
|
||||
SLEG_CONDVAR("date", _load_check_data.current_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLEG_CONDVAR("date", _load_check_data.current_date, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
/* Save load date related variables as well as persistent tick counters
|
||||
* XXX: currently some unrelated stuff is just put here */
|
||||
static void SaveLoad_DATE()
|
||||
{
|
||||
SlGlobList(_date_desc);
|
||||
SetScaledTickVariables();
|
||||
}
|
||||
struct DATEChunkHandler : ChunkHandler {
|
||||
DATEChunkHandler() : ChunkHandler('DATE', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_date_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlGlobList(_date_desc);
|
||||
}
|
||||
|
||||
void LoadCommon(const SaveLoadTable &slt, const SaveLoadCompatTable &slct) const
|
||||
{
|
||||
const std::vector<SaveLoad> oslt = SlCompatTableHeader(slt, slct);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlGlobList(oslt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
this->LoadCommon(_date_desc, _date_sl_compat);
|
||||
}
|
||||
|
||||
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
this->LoadCommon(_date_check_desc, _date_check_sl_compat);
|
||||
|
||||
static void Check_DATE()
|
||||
{
|
||||
SlGlobList(_date_check_desc);
|
||||
if (IsSavegameVersionBefore(SLV_31)) {
|
||||
_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const SaveLoad _view_desc[] = {
|
||||
SLEG_CONDVAR(_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
|
||||
SLEG_CONDVAR(_saved_scrollpos_x, SLE_INT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR(_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
|
||||
SLEG_CONDVAR(_saved_scrollpos_y, SLE_INT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_VAR(_saved_scrollpos_zoom, SLE_UINT8),
|
||||
}
|
||||
};
|
||||
|
||||
static void SaveLoad_VIEW()
|
||||
{
|
||||
SlGlobList(_view_desc);
|
||||
}
|
||||
static const SaveLoad _view_desc[] = {
|
||||
SLEG_CONDVAR("x", _saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
|
||||
SLEG_CONDVAR("x", _saved_scrollpos_x, SLE_INT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("y", _saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_6),
|
||||
SLEG_CONDVAR("y", _saved_scrollpos_y, SLE_INT32, SLV_6, SL_MAX_VERSION),
|
||||
SLEG_VAR("zoom", _saved_scrollpos_zoom, SLE_UINT8),
|
||||
};
|
||||
|
||||
static const ChunkHandler misc_chunk_handlers[] = {
|
||||
{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, nullptr, Check_DATE, CH_RIFF },
|
||||
{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, nullptr, nullptr, CH_RIFF },
|
||||
struct VIEWChunkHandler : ChunkHandler {
|
||||
VIEWChunkHandler() : ChunkHandler('VIEW', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_view_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlGlobList(_view_desc);
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_view_desc, _view_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlGlobList(slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries");
|
||||
}
|
||||
};
|
||||
|
||||
static const DATEChunkHandler DATE;
|
||||
static const VIEWChunkHandler VIEW;
|
||||
static const ChunkHandlerRef misc_chunk_handlers[] = {
|
||||
DATE,
|
||||
VIEW,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _misc_chunk_handlers(misc_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,63 +8,55 @@
|
||||
/** @file newgrf_sl.cpp Code handling saving and loading of newgrf config */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../fios.h"
|
||||
#include "../string_func.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/newgrf_sl_compat.h"
|
||||
|
||||
#include "newgrf_sl.h"
|
||||
#include "../fios.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/** Save and load the mapping between a spec and the NewGRF it came from. */
|
||||
static const SaveLoad _newgrf_mapping_desc_old[] = {
|
||||
static const SaveLoad _newgrf_mapping_desc[] = {
|
||||
SLE_VAR(EntityIDMapping, grfid, SLE_UINT32),
|
||||
SLE_VAR(EntityIDMapping, entity_id, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
SLE_VAR(EntityIDMapping, substitute_id, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
};
|
||||
static const SaveLoad _newgrf_mapping_desc_new[] = {
|
||||
SLE_VAR(EntityIDMapping, grfid, SLE_UINT32),
|
||||
SLE_VAR(EntityIDMapping, entity_id, SLE_UINT16),
|
||||
SLE_VAR(EntityIDMapping, substitute_id, SLE_UINT16),
|
||||
SLE_CONDVAR(EntityIDMapping, entity_id, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_EXTEND_ENTITY_MAPPING),
|
||||
SLE_CONDVAR(EntityIDMapping, entity_id, SLE_UINT16, SLV_EXTEND_ENTITY_MAPPING, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(EntityIDMapping, substitute_id, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_EXTEND_ENTITY_MAPPING),
|
||||
SLE_CONDVAR(EntityIDMapping, substitute_id, SLE_UINT16, SLV_EXTEND_ENTITY_MAPPING, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
/**
|
||||
* Save a GRF ID + local id -> OpenTTD's id mapping.
|
||||
* @param mapping The mapping to save.
|
||||
*/
|
||||
void Save_NewGRFMapping(const OverrideManagerBase &mapping)
|
||||
void NewGRFMappingChunkHandler::Save() const
|
||||
{
|
||||
for (uint i = 0; i < mapping.GetMaxMapping(); i++) {
|
||||
if (mapping.mappings[i].grfid == 0 &&
|
||||
mapping.mappings[i].entity_id == 0) continue;
|
||||
SlSetArrayIndex(i);
|
||||
SlSetLength(4 + 2 + 2);
|
||||
SlObjectSaveFiltered(const_cast<EntityIDMapping *>(&mapping.mappings[i]), _newgrf_mapping_desc_new); // _newgrf_mapping_desc_new has no conditionals
|
||||
}
|
||||
// removed
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a GRF ID + local id -> OpenTTD's id mapping.
|
||||
* @param mapping The mapping to load.
|
||||
*/
|
||||
void Load_NewGRFMapping(OverrideManagerBase &mapping)
|
||||
void NewGRFMappingChunkHandler::Load() const
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_newgrf_mapping_desc, _newgrf_mapping_sl_compat);
|
||||
|
||||
/* Clear the current mapping stored.
|
||||
* This will create the manager if ever it is not yet done */
|
||||
mapping.ResetMapping();
|
||||
this->mapping.ResetMapping();
|
||||
|
||||
uint max_id = mapping.GetMaxMapping();
|
||||
|
||||
SaveLoadTable slt = SlXvIsFeaturePresent(XSLFI_NEWGRF_ENTITY_EXTRA) ? SaveLoadTable(_newgrf_mapping_desc_new) : SaveLoadTable(_newgrf_mapping_desc_old);
|
||||
uint max_id = this->mapping.GetMaxMapping();
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
if (unlikely((uint)index >= max_id)) SlErrorCorrupt("Too many NewGRF entity mappings");
|
||||
SlObjectLoadFiltered(&mapping.mappings[index], slt); // _newgrf_mapping_desc_old/_newgrf_mapping_desc_new has no conditionals
|
||||
if ((uint)index >= max_id) SlErrorCorrupt("Too many NewGRF entity mappings");
|
||||
SlObject(&this->mapping.mappings[index], slt);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string _grf_name;
|
||||
|
||||
static const SaveLoad _grfconfig_desc[] = {
|
||||
SLE_SSTR(GRFConfig, filename, SLE_STR),
|
||||
@@ -74,40 +66,42 @@ static const SaveLoad _grfconfig_desc[] = {
|
||||
SLE_ARR(GRFConfig, param, SLE_UINT32, 0x80),
|
||||
SLE_VAR(GRFConfig, num_params, SLE_UINT8),
|
||||
SLE_CONDVAR(GRFConfig, palette, SLE_UINT8, SLV_101, SL_MAX_VERSION),
|
||||
SLEG_CONDSSTR_X(_grf_name, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_NEWGRF_INFO_EXTRA)),
|
||||
};
|
||||
|
||||
|
||||
static void Save_NGRF()
|
||||
{
|
||||
struct NGRFChunkHandler : ChunkHandler {
|
||||
NGRFChunkHandler() : ChunkHandler('NGRF', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_grfconfig_desc);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
|
||||
if (HasBit(c->flags, GCF_STATIC) || HasBit(c->flags, GCF_INIT_ONLY)) continue;
|
||||
SlSetArrayIndex(index++);
|
||||
_grf_name = str_strip_all_scc(GetDefaultLangGRFStringFromGRFText(c->name));
|
||||
SlObject(c, _grfconfig_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Load_NGRF_common(GRFConfig *&grfconfig)
|
||||
{
|
||||
void LoadCommon(GRFConfig *&grfconfig) const
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_grfconfig_desc, _grfconfig_sl_compat);
|
||||
|
||||
ClearGRFConfigList(&grfconfig);
|
||||
while (SlIterateArray() != -1) {
|
||||
GRFConfig *c = new GRFConfig();
|
||||
SlObject(c, _grfconfig_desc);
|
||||
if (SlXvIsFeaturePresent(XSLFI_NEWGRF_INFO_EXTRA)) {
|
||||
AddGRFTextToList(c->name, 0x7F, c->ident.grfid, false, _grf_name.c_str());
|
||||
}
|
||||
SlObject(c, slt);
|
||||
if (IsSavegameVersionBefore(SLV_101)) c->SetSuitablePalette();
|
||||
AppendToGRFConfigList(&grfconfig, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_NGRF()
|
||||
{
|
||||
Load_NGRF_common(_grfconfig);
|
||||
void Load() const override
|
||||
{
|
||||
this->LoadCommon(_grfconfig);
|
||||
|
||||
if (_game_mode == GM_MENU) {
|
||||
/* Intro game must not have NewGRF. */
|
||||
@@ -119,15 +113,19 @@ static void Load_NGRF()
|
||||
/* Append static NewGRF configuration */
|
||||
AppendStaticGRFConfigs(&_grfconfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Check_NGRF()
|
||||
{
|
||||
Load_NGRF_common(_load_check_data.grfconfig);
|
||||
}
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
this->LoadCommon(_load_check_data.grfconfig);
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler newgrf_chunk_handlers[] = {
|
||||
{ 'NGRF', Save_NGRF, Load_NGRF, nullptr, Check_NGRF, CH_ARRAY }
|
||||
static const NGRFChunkHandler NGRF;
|
||||
static const ChunkHandlerRef newgrf_chunk_handlers[] = {
|
||||
NGRF,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _newgrf_chunk_handlers(newgrf_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -7,12 +7,21 @@
|
||||
|
||||
/** @file newgrf_sl.h Code handling saving and loading of NewGRF mappings. */
|
||||
|
||||
#ifndef SAVELOAD_NEWGRF_SL_H
|
||||
#define SAVELOAD_NEWGRF_SL_H
|
||||
#ifndef SAVELOAD_UPSTREAM_NEWGRF_SL_H
|
||||
#define SAVELOAD_UPSTREAM_NEWGRF_SL_H
|
||||
|
||||
#include "../newgrf_commons.h"
|
||||
|
||||
void Save_NewGRFMapping(const OverrideManagerBase &mapping);
|
||||
void Load_NewGRFMapping(OverrideManagerBase &mapping);
|
||||
namespace upstream_sl {
|
||||
|
||||
#endif /* SAVELOAD_NEWGRF_SL_H */
|
||||
struct NewGRFMappingChunkHandler : ChunkHandler {
|
||||
OverrideManagerBase &mapping;
|
||||
|
||||
NewGRFMappingChunkHandler(uint32 id, OverrideManagerBase &mapping) : ChunkHandler(id, CH_TABLE), mapping(mapping) {}
|
||||
void Save() const override;
|
||||
void Load() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SAVELOAD_UPSTREAM_NEWGRF_SL_H */
|
||||
|
@@ -8,14 +8,18 @@
|
||||
/** @file object_sl.cpp Code handling saving and loading of objects */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../object_base.h"
|
||||
#include "../object_map.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/object_sl_compat.h"
|
||||
|
||||
#include "../object_base.h"
|
||||
#include "../object_map.h"
|
||||
#include "newgrf_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _object_desc[] = {
|
||||
SLE_VAR(Object, location.tile, SLE_UINT32),
|
||||
SLE_VAR(Object, location.w, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
@@ -27,26 +31,33 @@ static const SaveLoad _object_desc[] = {
|
||||
SLE_CONDVAR(Object, type, SLE_UINT16, SLV_186, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_OBJS()
|
||||
{
|
||||
struct OBJSChunkHandler : ChunkHandler {
|
||||
OBJSChunkHandler() : ChunkHandler('OBJS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_object_desc);
|
||||
|
||||
/* Write the objects */
|
||||
for (Object *o : Object::Iterate()) {
|
||||
SlSetArrayIndex(o->index);
|
||||
SlObject(o, _object_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_object_desc, _object_sl_compat);
|
||||
|
||||
static void Load_OBJS()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Object *o = new (index) Object();
|
||||
SlObject(o, _object_desc);
|
||||
SlObject(o, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_OBJS()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (Object *o : Object::Iterate()) {
|
||||
SlObject(o, _object_desc);
|
||||
if (IsSavegameVersionBefore(SLV_148) && !IsTileType(o->location.tile, MP_OBJECT)) {
|
||||
@@ -54,21 +65,20 @@ static void Ptrs_OBJS()
|
||||
delete o;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void Save_OBID()
|
||||
{
|
||||
Save_NewGRFMapping(_object_mngr);
|
||||
}
|
||||
struct OBIDChunkHandler : NewGRFMappingChunkHandler {
|
||||
OBIDChunkHandler() : NewGRFMappingChunkHandler('OBID', _object_mngr) {}
|
||||
};
|
||||
|
||||
static void Load_OBID()
|
||||
{
|
||||
Load_NewGRFMapping(_object_mngr);
|
||||
}
|
||||
|
||||
static const ChunkHandler object_chunk_handlers[] = {
|
||||
{ 'OBID', Save_OBID, Load_OBID, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'OBJS', Save_OBJS, Load_OBJS, Ptrs_OBJS, nullptr, CH_ARRAY },
|
||||
static const OBIDChunkHandler OBID;
|
||||
static const OBJSChunkHandler OBJS;
|
||||
static const ChunkHandlerRef object_chunk_handlers[] = {
|
||||
OBID,
|
||||
OBJS,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _object_chunk_handlers(object_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,72 +8,18 @@
|
||||
/** @file order_sl.cpp Code handling saving and loading of orders */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/order_sl_compat.h"
|
||||
|
||||
#include "../order_backup.h"
|
||||
#include "../order_base.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static uint32 _jokerpp_separation_mode;
|
||||
std::vector<OrderList *> _jokerpp_auto_separation;
|
||||
std::vector<OrderList *> _jokerpp_non_auto_separation;
|
||||
|
||||
/**
|
||||
* Converts this order from an old savegame's version;
|
||||
* it moves all bits to the new location.
|
||||
*/
|
||||
void Order::ConvertFromOldSavegame()
|
||||
{
|
||||
uint8 old_flags = this->flags;
|
||||
this->flags = 0;
|
||||
|
||||
/* First handle non-stop - use value from savegame if possible, else use value from config file */
|
||||
if (_settings_client.gui.sg_new_nonstop || (IsSavegameVersionBefore(SLV_22) && _savegame_type != SGT_TTO && _savegame_type != SGT_TTD && (_settings_client.gui.new_nonstop || _settings_game.order.nonstop_only))) {
|
||||
/* OFB_NON_STOP */
|
||||
this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
|
||||
} else {
|
||||
this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
|
||||
}
|
||||
|
||||
switch (this->GetType()) {
|
||||
/* Only a few types need the other savegame conversions. */
|
||||
case OT_GOTO_DEPOT: case OT_GOTO_STATION: case OT_LOADING: break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (this->GetType() != OT_GOTO_DEPOT) {
|
||||
/* Then the load flags */
|
||||
if ((old_flags & 2) != 0) { // OFB_UNLOAD
|
||||
this->SetLoadType(OLFB_NO_LOAD);
|
||||
} else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD
|
||||
this->SetLoadType(OLF_LOAD_IF_POSSIBLE);
|
||||
} else {
|
||||
/* old OTTD versions stored full_load_any in config file - assume it was enabled when loading */
|
||||
this->SetLoadType(_settings_client.gui.sg_full_load_any || IsSavegameVersionBefore(SLV_22) ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD);
|
||||
}
|
||||
|
||||
if (this->IsType(OT_GOTO_STATION)) this->SetStopLocation(OSL_PLATFORM_FAR_END);
|
||||
|
||||
/* Finally fix the unload flags */
|
||||
if ((old_flags & 1) != 0) { // OFB_TRANSFER
|
||||
this->SetUnloadType(OUFB_TRANSFER);
|
||||
} else if ((old_flags & 2) != 0) { // OFB_UNLOAD
|
||||
this->SetUnloadType(OUFB_UNLOAD);
|
||||
} else {
|
||||
this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
|
||||
}
|
||||
} else {
|
||||
/* Then the depot action flags */
|
||||
this->SetDepotActionType(((old_flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY);
|
||||
|
||||
/* Finally fix the depot type flags */
|
||||
uint t = ((old_flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL;
|
||||
if ((old_flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS;
|
||||
this->SetDepotOrderType((OrderDepotTypeFlags)t);
|
||||
}
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
/**
|
||||
* Unpacks a order from savegames with version 4 and lower
|
||||
@@ -82,17 +28,7 @@ void Order::ConvertFromOldSavegame()
|
||||
*/
|
||||
static Order UnpackVersion4Order(uint16 packed)
|
||||
{
|
||||
return Order(((uint64) GB(packed, 8, 8)) << 24 | ((uint64) GB(packed, 4, 4)) << 8 | ((uint64) GB(packed, 0, 4)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks a order from savegames with version 5.1 and lower
|
||||
* @param packed packed order
|
||||
* @return unpacked order
|
||||
*/
|
||||
static Order UnpackVersion5Order(uint32 packed)
|
||||
{
|
||||
return Order(((uint64) GB(packed, 16, 16)) << 24 | ((uint64) GB(packed, 8, 8)) << 8 | ((uint64) GB(packed, 0, 8)));
|
||||
return Order(GB(packed, 8, 8) << 16 | GB(packed, 4, 4) << 8 | GB(packed, 0, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,42 +53,34 @@ SaveLoadTable GetOrderDescription()
|
||||
{
|
||||
static const SaveLoad _order_desc[] = {
|
||||
SLE_VAR(Order, type, SLE_UINT8),
|
||||
SLE_CONDVAR_X(Order, flags, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ORDER_FLAGS_EXTRA, 0, 0)),
|
||||
SLE_CONDVAR_X(Order, flags, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ORDER_FLAGS_EXTRA, 1)),
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP)),
|
||||
SLE_VAR(Order, flags, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
SLE_VAR(Order, dest, SLE_UINT16),
|
||||
SLE_REF(Order, next, REF_ORDER),
|
||||
SLE_CONDVAR(Order, refit_cargo, SLE_UINT8, SLV_36, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(1, SLV_36, SLV_182), // refit_subtype
|
||||
SLE_CONDVAR_X(Order, occupancy, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ORDER_OCCUPANCY)),
|
||||
SLE_CONDVAR_X(Order, wait_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 0, 5)),
|
||||
SLE_CONDVAR_X(Order, wait_time, SLE_UINT32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 6)),
|
||||
SLE_CONDVAR_X(Order, travel_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 0, 5)),
|
||||
SLE_CONDVAR_X(Order, travel_time, SLE_UINT32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 6)),
|
||||
SLE_CONDVAR(Order, wait_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Order, travel_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Order, max_speed, SLE_UINT16, SLV_172, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_MORE_COND_ORDERS, 1, 6)), // jump_counter
|
||||
|
||||
/* Leftover from the minor savegame version stuff
|
||||
* We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
|
||||
SLE_CONDNULL(10, SLV_5, SLV_36),
|
||||
};
|
||||
|
||||
return _order_desc;
|
||||
}
|
||||
|
||||
static std::vector<SaveLoad> _filtered_desc;
|
||||
struct ORDRChunkHandler : ChunkHandler {
|
||||
ORDRChunkHandler() : ChunkHandler('ORDR', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
const SaveLoadTable slt = GetOrderDescription();
|
||||
SlTableHeader(slt);
|
||||
|
||||
static void Save_ORDR()
|
||||
{
|
||||
_filtered_desc = SlFilterObject(GetOrderDescription());
|
||||
for (Order *order : Order::Iterate()) {
|
||||
SlSetArrayIndex(order->index);
|
||||
SlObjectSaveFiltered(order, _filtered_desc);
|
||||
SlObject(order, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_ORDR()
|
||||
{
|
||||
void Load() const override
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_5, 2)) {
|
||||
/* Version older than 5.2 did not have a ->next pointer. Convert them
|
||||
* (in the old days, the orderlist was 5000 items big) */
|
||||
@@ -164,7 +92,7 @@ static void Load_ORDR()
|
||||
len /= sizeof(uint16);
|
||||
uint16 *orders = MallocT<uint16>(len + 1);
|
||||
|
||||
SlArray(orders, len, SLE_UINT16);
|
||||
SlCopy(orders, len, SLE_UINT16);
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
Order *o = new (i) Order();
|
||||
@@ -176,11 +104,10 @@ static void Load_ORDR()
|
||||
len /= sizeof(uint32);
|
||||
uint32 *orders = MallocT<uint32>(len + 1);
|
||||
|
||||
SlArray(orders, len, SLE_UINT32);
|
||||
SlCopy(orders, len, SLE_UINT32);
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
Order *o = new (i) Order();
|
||||
o->AssignOrder(UnpackVersion5Order(orders[i]));
|
||||
new (i) Order(orders[i]);
|
||||
}
|
||||
|
||||
free(orders);
|
||||
@@ -200,138 +127,72 @@ static void Load_ORDR()
|
||||
if (prev != nullptr) prev->next = o;
|
||||
}
|
||||
} else {
|
||||
_filtered_desc = SlFilterObject(GetOrderDescription());
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderDescription(), _order_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Order *order = new (index) Order();
|
||||
SlObjectLoadFiltered(order, _filtered_desc);
|
||||
SlObject(order, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SaveLoadTable GetOrderExtraInfoDescription()
|
||||
{
|
||||
static const SaveLoad _order_extra_info_desc[] = {
|
||||
SLE_CONDARR_X(OrderExtraInfo, cargo_type_flags, SLE_UINT8, 32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CARGO_TYPE_ORDERS, 1, 2)),
|
||||
SLE_CONDARR_X(OrderExtraInfo, cargo_type_flags, SLE_UINT8, NUM_CARGO, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CARGO_TYPE_ORDERS, 3)),
|
||||
SLE_CONDVAR_X(OrderExtraInfo, xflags, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA)),
|
||||
SLE_CONDVAR_X(OrderExtraInfo, xdata, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ORDER_EXTRA_DATA)),
|
||||
SLE_CONDVAR_X(OrderExtraInfo, dispatch_index, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SCHEDULED_DISPATCH, 3)),
|
||||
SLE_CONDVAR_X(OrderExtraInfo, colour, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ORDER_EXTRA_DATA, 2)),
|
||||
};
|
||||
|
||||
return _order_extra_info_desc;
|
||||
}
|
||||
|
||||
void Save_ORDX()
|
||||
{
|
||||
_filtered_desc = SlFilterObject(GetOrderExtraInfoDescription());
|
||||
for (Order *order : Order::Iterate()) {
|
||||
if (order->extra) {
|
||||
SlSetArrayIndex(order->index);
|
||||
SlObjectSaveFiltered(order->extra.get(), _filtered_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load_ORDX()
|
||||
{
|
||||
_filtered_desc = SlFilterObject(GetOrderExtraInfoDescription());
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Order *order = Order::GetIfValid(index);
|
||||
assert(order != nullptr);
|
||||
order->AllocExtraInfo();
|
||||
SlObjectLoadFiltered(order->extra.get(), _filtered_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_ORDR()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
/* Orders from old savegames have pointers corrected in Load_ORDR */
|
||||
if (IsSavegameVersionBefore(SLV_5, 2)) return;
|
||||
|
||||
for (Order *o : Order::Iterate()) {
|
||||
SlObject(o, GetOrderDescription());
|
||||
}
|
||||
}
|
||||
|
||||
SaveLoadTable GetDispatchScheduleDescription()
|
||||
{
|
||||
static const SaveLoad _order_extra_info_desc[] = {
|
||||
SLE_VARVEC(DispatchSchedule, scheduled_dispatch, SLE_UINT32),
|
||||
SLE_VAR(DispatchSchedule, scheduled_dispatch_duration, SLE_UINT32),
|
||||
SLE_VAR(DispatchSchedule, scheduled_dispatch_start_date, SLE_INT32),
|
||||
SLE_VAR(DispatchSchedule, scheduled_dispatch_start_full_date_fract, SLE_UINT16),
|
||||
SLE_VAR(DispatchSchedule, scheduled_dispatch_last_dispatch, SLE_INT32),
|
||||
SLE_VAR(DispatchSchedule, scheduled_dispatch_max_delay, SLE_INT32),
|
||||
SLE_CONDSSTR_X(DispatchSchedule, name, 0, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SCHEDULED_DISPATCH, 4)),
|
||||
};
|
||||
|
||||
return _order_extra_info_desc;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SaveLoadTable GetOrderListDescription()
|
||||
{
|
||||
static const SaveLoad _orderlist_desc[] = {
|
||||
SLE_REF(OrderList, first, REF_ORDER),
|
||||
SLEG_CONDVAR_X(_jokerpp_separation_mode, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP)),
|
||||
SLE_CONDNULL_X(21, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP)),
|
||||
};
|
||||
|
||||
return _orderlist_desc;
|
||||
}
|
||||
|
||||
static void Save_ORDL()
|
||||
{
|
||||
struct ORDLChunkHandler : ChunkHandler {
|
||||
ORDLChunkHandler() : ChunkHandler('ORDL', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
const SaveLoadTable slt = GetOrderListDescription();
|
||||
SlTableHeader(slt);
|
||||
|
||||
for (OrderList *list : OrderList::Iterate()) {
|
||||
SlSetArrayIndex(list->index);
|
||||
SlAutolength([](void *data) {
|
||||
OrderList *list = static_cast<OrderList *>(data);
|
||||
SlObject(list, GetOrderListDescription());
|
||||
SlWriteUint32(list->GetScheduledDispatchScheduleCount());
|
||||
for (DispatchSchedule &ds : list->GetScheduledDispatchScheduleSet()) {
|
||||
SlObject(&ds, GetDispatchScheduleDescription());
|
||||
SlObject(list, slt);
|
||||
}
|
||||
}, list);
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_ORDL()
|
||||
{
|
||||
_jokerpp_auto_separation.clear();
|
||||
_jokerpp_non_auto_separation.clear();
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderListDescription(), _orderlist_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
/* set num_orders to 0 so it's a valid OrderList */
|
||||
OrderList *list = new (index) OrderList(0);
|
||||
SlObject(list, GetOrderListDescription());
|
||||
if (SlXvIsFeaturePresent(XSLFI_JOKERPP)) {
|
||||
if (_jokerpp_separation_mode == 0) {
|
||||
_jokerpp_auto_separation.push_back(list);
|
||||
} else {
|
||||
_jokerpp_non_auto_separation.push_back(list);
|
||||
SlObject(list, slt);
|
||||
}
|
||||
}
|
||||
if (SlXvIsFeaturePresent(XSLFI_SCHEDULED_DISPATCH)) {
|
||||
uint count = SlXvIsFeaturePresent(XSLFI_SCHEDULED_DISPATCH, 3) ? SlReadUint32() : 1;
|
||||
list->GetScheduledDispatchScheduleSet().resize(count);
|
||||
for (DispatchSchedule &ds : list->GetScheduledDispatchScheduleSet()) {
|
||||
SlObject(&ds, GetDispatchScheduleDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ptrs_ORDL()
|
||||
{
|
||||
}
|
||||
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (OrderList *list : OrderList::Iterate()) {
|
||||
SlObject(list, GetOrderListDescription());
|
||||
list->ReindexOrderList();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SaveLoadTable GetOrderBackupDescription()
|
||||
{
|
||||
@@ -341,28 +202,29 @@ SaveLoadTable GetOrderBackupDescription()
|
||||
SLE_VAR(OrderBackup, group, SLE_UINT16),
|
||||
SLE_CONDVAR(OrderBackup, service_interval, SLE_FILE_U32 | SLE_VAR_U16, SL_MIN_VERSION, SLV_192),
|
||||
SLE_CONDVAR(OrderBackup, service_interval, SLE_UINT16, SLV_192, SL_MAX_VERSION),
|
||||
SLE_STR(OrderBackup, name, SLE_STR, 0),
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_192), // clone (2 bytes of pointer, i.e. garbage)
|
||||
SLE_SSTR(OrderBackup, name, SLE_STR),
|
||||
SLE_CONDREF(OrderBackup, clone, REF_VEHICLE, SLV_192, SL_MAX_VERSION),
|
||||
SLE_VAR(OrderBackup, cur_real_order_index, SLE_VEHORDERID),
|
||||
SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_VEHORDERID, SLV_176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(OrderBackup, cur_timetable_order_index, SLE_VEHORDERID, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA)),
|
||||
SLE_VAR(OrderBackup, cur_real_order_index, SLE_FILE_U8 | SLE_VAR_U16),
|
||||
SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_FILE_U8 | SLE_VAR_U16, SLV_176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, current_order_time, SLE_UINT32, SLV_176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, SLV_176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, SLV_176, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(OrderBackup,timetable_start_subticks, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 2)),
|
||||
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_176, SLV_180),
|
||||
SLE_CONDVAR_X(OrderBackup, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 0, 0)),
|
||||
SLE_CONDVAR_X(OrderBackup, vehicle_flags, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 1)),
|
||||
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION),
|
||||
SLE_REF(OrderBackup, orders, REF_ORDER),
|
||||
SLE_CONDNULL_X(18, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SCHEDULED_DISPATCH, 2, 2)),
|
||||
};
|
||||
|
||||
return _order_backup_desc;
|
||||
}
|
||||
|
||||
void Save_BKOR()
|
||||
{
|
||||
struct BKORChunkHandler : ChunkHandler {
|
||||
BKORChunkHandler() : ChunkHandler('BKOR', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
const SaveLoadTable slt = GetOrderBackupDescription();
|
||||
SlTableHeader(slt);
|
||||
|
||||
/* We only save this when we're a network server
|
||||
* as we want this information on our clients. For
|
||||
* normal games this information isn't needed. */
|
||||
@@ -370,47 +232,42 @@ void Save_BKOR()
|
||||
|
||||
for (OrderBackup *ob : OrderBackup::Iterate()) {
|
||||
SlSetArrayIndex(ob->index);
|
||||
SlAutolength([](void *data) {
|
||||
OrderBackup *ob = static_cast<OrderBackup *>(data);
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
SlWriteUint32((uint)ob->dispatch_schedules.size());
|
||||
for (DispatchSchedule &ds : ob->dispatch_schedules) {
|
||||
SlObject(&ds, GetDispatchScheduleDescription());
|
||||
SlObject(ob, slt);
|
||||
}
|
||||
}, ob);
|
||||
}
|
||||
}
|
||||
|
||||
void Load_BKOR()
|
||||
{
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderBackupDescription(), _order_backup_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
/* set num_orders to 0 so it's a valid OrderList */
|
||||
OrderBackup *ob = new (index) OrderBackup();
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
if (SlXvIsFeaturePresent(XSLFI_SCHEDULED_DISPATCH, 3)) {
|
||||
uint count = SlReadUint32();
|
||||
ob->dispatch_schedules.resize(count);
|
||||
for (DispatchSchedule &ds : ob->dispatch_schedules) {
|
||||
SlObject(&ds, GetDispatchScheduleDescription());
|
||||
SlObject(ob, slt);
|
||||
if (ob->cur_real_order_index == 0xFF) ob->cur_real_order_index = INVALID_VEH_ORDER_ID;
|
||||
if (ob->cur_implicit_order_index == 0xFF) ob->cur_implicit_order_index = INVALID_VEH_ORDER_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_BKOR()
|
||||
{
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (OrderBackup *ob : OrderBackup::Iterate()) {
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler order_chunk_handlers[] = {
|
||||
{ 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, nullptr, CH_ARRAY },
|
||||
{ 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, nullptr, CH_ARRAY },
|
||||
{ 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, nullptr, CH_ARRAY },
|
||||
{ 'ORDX', Save_ORDX, Load_ORDX, nullptr, nullptr, CH_SPARSE_ARRAY },
|
||||
static const BKORChunkHandler BKOR;
|
||||
static const ORDRChunkHandler ORDR;
|
||||
static const ORDLChunkHandler ORDL;
|
||||
static const ChunkHandlerRef order_chunk_handlers[] = {
|
||||
BKOR,
|
||||
ORDR,
|
||||
ORDL,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _order_chunk_handlers(order_chunk_handlers);
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,18 +7,18 @@
|
||||
|
||||
/** @file settings_sl.cpp Handles the saveload part of the settings. */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "debug.h"
|
||||
#include "compat/settings_sl_compat.h"
|
||||
|
||||
#include "../../settings_type.h"
|
||||
#include "../../settings_internal.h"
|
||||
#include "../../network/network.h"
|
||||
#include "../../fios.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../settings_internal.h"
|
||||
#include "../network/network.h"
|
||||
#include "../fios.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
#include "../safeguards.h"
|
||||
|
||||
const SettingTable &GetSettingsTableInternal();
|
||||
|
@@ -8,13 +8,17 @@
|
||||
/** @file signs_sl.cpp Code handling saving and loading of economy data */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/signs_sl_compat.h"
|
||||
|
||||
#include "../signs_base.h"
|
||||
#include "../fios.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/** Description of a sign within the savegame. */
|
||||
static const SaveLoad _sign_desc[] = {
|
||||
SLE_CONDVAR(Sign, name, SLE_NAME, SL_MIN_VERSION, SLV_84),
|
||||
@@ -24,26 +28,31 @@ static const SaveLoad _sign_desc[] = {
|
||||
SLE_CONDVAR(Sign, x, SLE_INT32, SLV_5, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Sign, y, SLE_INT32, SLV_5, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Sign, owner, SLE_UINT8, SLV_6, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(Sign, z, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164, SlXvFeatureTest(XSLFTO_AND, XSLFI_ZPOS_32_BIT, 0, 0)),
|
||||
SLE_CONDVAR_X(Sign, z, SLE_INT32, SLV_164, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_OR, XSLFI_ZPOS_32_BIT)),
|
||||
SLE_CONDVAR(Sign, z, SLE_FILE_U8 | SLE_VAR_I32, SL_MIN_VERSION, SLV_164),
|
||||
SLE_CONDVAR(Sign, z, SLE_INT32, SLV_164, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
/** Save all signs */
|
||||
static void Save_SIGN()
|
||||
{
|
||||
struct SIGNChunkHandler : ChunkHandler {
|
||||
SIGNChunkHandler() : ChunkHandler('SIGN', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_sign_desc);
|
||||
|
||||
for (Sign *si : Sign::Iterate()) {
|
||||
SlSetArrayIndex(si->index);
|
||||
SlObject(si, _sign_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_sign_desc, _sign_sl_compat);
|
||||
|
||||
/** Load all signs */
|
||||
static void Load_SIGN()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Sign *si = new (index) Sign();
|
||||
SlObject(si, _sign_desc);
|
||||
SlObject(si, slt);
|
||||
/* Before version 6.1, signs didn't have owner.
|
||||
* Before version 83, invalid signs were determined by si->str == 0.
|
||||
* Before version 103, owner could be a bankrupted company.
|
||||
@@ -55,15 +64,18 @@ static void Load_SIGN()
|
||||
}
|
||||
|
||||
/* Signs placed in scenario editor shall now be OWNER_DEITY */
|
||||
if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && _file_to_saveload.abstract_ftype == FT_SCENARIO) {
|
||||
if (IsSavegameVersionBefore(SLV_171) && si->owner == OWNER_NONE && SaveLoadFileTypeIsScenario()) {
|
||||
si->owner = OWNER_DEITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Chunk handlers related to signs. */
|
||||
static const ChunkHandler sign_chunk_handlers[] = {
|
||||
{ 'SIGN', Save_SIGN, Load_SIGN, nullptr, nullptr, CH_ARRAY },
|
||||
static const SIGNChunkHandler SIGN;
|
||||
static const ChunkHandlerRef sign_chunk_handlers[] = {
|
||||
SIGN,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _sign_chunk_handlers(sign_chunk_handlers);
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -8,11 +8,16 @@
|
||||
/** @file storage_sl.cpp Code handling saving and loading of persistent storages. */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../newgrf_storage.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/storage_sl_compat.h"
|
||||
|
||||
#include "../newgrf_storage.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/** Description of the data to save and load in #PersistentStorage. */
|
||||
static const SaveLoad _storage_desc[] = {
|
||||
SLE_CONDVAR(PersistentStorage, grfid, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
@@ -20,32 +25,41 @@ static const SaveLoad _storage_desc[] = {
|
||||
SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 256, SLV_EXTEND_PERSISTENT_STORAGE, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
/** Load persistent storage data. */
|
||||
static void Load_PSAC()
|
||||
{
|
||||
/** Persistent storage data. */
|
||||
struct PSACChunkHandler : ChunkHandler {
|
||||
PSACChunkHandler() : ChunkHandler('PSAC', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_storage_desc, _storage_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
assert(PersistentStorage::CanAllocateItem());
|
||||
PersistentStorage *ps = new (index) PersistentStorage(0, 0, 0);
|
||||
SlObject(ps, _storage_desc);
|
||||
SlObject(ps, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Save persistent storage data. */
|
||||
static void Save_PSAC()
|
||||
{
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_storage_desc);
|
||||
|
||||
/* Write the industries */
|
||||
for (PersistentStorage *ps : PersistentStorage::Iterate()) {
|
||||
ps->ClearChanges();
|
||||
SlSetArrayIndex(ps->index);
|
||||
SlObject(ps, _storage_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Chunk handler for persistent storages. */
|
||||
static const ChunkHandler persistent_storage_chunk_handlers[] = {
|
||||
{ 'PSAC', Save_PSAC, Load_PSAC, nullptr, nullptr, CH_ARRAY },
|
||||
static const PSACChunkHandler PSAC;
|
||||
static const ChunkHandlerRef persistent_storage_chunk_handlers[] = {
|
||||
PSAC,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _persistent_storage_chunk_handlers(persistent_storage_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,23 +8,15 @@
|
||||
/** @file story_sl.cpp Code handling saving and loading of story pages */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../story_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/story_sl_compat.h"
|
||||
|
||||
#include "../story_base.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Called after load to trash broken pages. */
|
||||
void AfterLoadStoryBook()
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_185)) {
|
||||
/* Trash all story pages and page elements because
|
||||
* they were saved with wrong data types.
|
||||
*/
|
||||
_story_page_element_pool.CleanPool();
|
||||
_story_page_pool.CleanPool();
|
||||
}
|
||||
}
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _story_page_elements_desc[] = {
|
||||
SLE_CONDVAR(StoryPageElement, sort_value, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_185),
|
||||
@@ -36,21 +28,28 @@ static const SaveLoad _story_page_elements_desc[] = {
|
||||
SLE_SSTR(StoryPageElement, text, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
};
|
||||
|
||||
static void Save_STORY_PAGE_ELEMENT()
|
||||
{
|
||||
struct STPEChunkHandler : ChunkHandler {
|
||||
STPEChunkHandler() : ChunkHandler('STPE', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_story_page_elements_desc);
|
||||
|
||||
for (StoryPageElement *s : StoryPageElement::Iterate()) {
|
||||
SlSetArrayIndex(s->index);
|
||||
SlObject(s, _story_page_elements_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_page_elements_desc, _story_page_elements_sl_compat);
|
||||
|
||||
static void Load_STORY_PAGE_ELEMENT()
|
||||
{
|
||||
int index;
|
||||
uint32 max_sort_value = 0;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
StoryPageElement *s = new (index) StoryPageElement();
|
||||
SlObject(s, _story_page_elements_desc);
|
||||
SlObject(s, slt);
|
||||
if (s->sort_value > max_sort_value) {
|
||||
max_sort_value = s->sort_value;
|
||||
}
|
||||
@@ -59,7 +58,8 @@ static void Load_STORY_PAGE_ELEMENT()
|
||||
* created page is shown after all existing pages.
|
||||
*/
|
||||
_story_page_element_next_sort_value = max_sort_value + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const SaveLoad _story_pages_desc[] = {
|
||||
SLE_CONDVAR(StoryPage, sort_value, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_185),
|
||||
@@ -70,21 +70,28 @@ static const SaveLoad _story_pages_desc[] = {
|
||||
SLE_SSTR(StoryPage, title, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
};
|
||||
|
||||
static void Save_STORY_PAGE()
|
||||
{
|
||||
struct STPAChunkHandler : ChunkHandler {
|
||||
STPAChunkHandler() : ChunkHandler('STPA', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_story_pages_desc);
|
||||
|
||||
for (StoryPage *s : StoryPage::Iterate()) {
|
||||
SlSetArrayIndex(s->index);
|
||||
SlObject(s, _story_pages_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_story_pages_desc, _story_pages_sl_compat);
|
||||
|
||||
static void Load_STORY_PAGE()
|
||||
{
|
||||
int index;
|
||||
uint32 max_sort_value = 0;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
StoryPage *s = new (index) StoryPage();
|
||||
SlObject(s, _story_pages_desc);
|
||||
SlObject(s, slt);
|
||||
if (s->sort_value > max_sort_value) {
|
||||
max_sort_value = s->sort_value;
|
||||
}
|
||||
@@ -93,11 +100,16 @@ static void Load_STORY_PAGE()
|
||||
* created page is shown after all existing pages.
|
||||
*/
|
||||
_story_page_next_sort_value = max_sort_value + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler story_page_chunk_handlers[] = {
|
||||
{ 'STPE', Save_STORY_PAGE_ELEMENT, Load_STORY_PAGE_ELEMENT, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'STPA', Save_STORY_PAGE, Load_STORY_PAGE, nullptr, nullptr, CH_ARRAY },
|
||||
static const STPEChunkHandler STPE;
|
||||
static const STPAChunkHandler STPA;
|
||||
static const ChunkHandlerRef story_page_chunk_handlers[] = {
|
||||
STPE,
|
||||
STPA,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _story_page_chunk_handlers(story_page_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,12 +8,16 @@
|
||||
/** @file subsidy_sl.cpp Code handling saving and loading of subsidies */
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../subsidy_base.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/subsidy_sl_compat.h"
|
||||
|
||||
#include "../subsidy_base.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _subsidies_desc[] = {
|
||||
SLE_VAR(Subsidy, cargo_type, SLE_UINT8),
|
||||
SLE_CONDVAR(Subsidy, remaining, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_CUSTOM_SUBSIDY_DURATION),
|
||||
@@ -27,25 +31,36 @@ static const SaveLoad _subsidies_desc[] = {
|
||||
SLE_CONDVAR(Subsidy, dst, SLE_UINT16, SLV_5, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void Save_SUBS()
|
||||
{
|
||||
struct SUBSChunkHandler : ChunkHandler {
|
||||
SUBSChunkHandler() : ChunkHandler('SUBS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_subsidies_desc);
|
||||
|
||||
for (Subsidy *s : Subsidy::Iterate()) {
|
||||
SlSetArrayIndex(s->index);
|
||||
SlObject(s, _subsidies_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_subsidies_desc, _subsidies_sl_compat);
|
||||
|
||||
static void Load_SUBS()
|
||||
{
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Subsidy *s = new (index) Subsidy();
|
||||
SlObject(s, _subsidies_desc);
|
||||
SlObject(s, slt);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ChunkHandler subsidy_chunk_handlers[] = {
|
||||
{ 'SUBS', Save_SUBS, Load_SUBS, nullptr, nullptr, CH_ARRAY },
|
||||
static const SUBSChunkHandler SUBS;
|
||||
static const ChunkHandlerRef subsidy_chunk_handlers[] = {
|
||||
SUBS,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _subsidy_chunk_handlers(subsidy_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -8,238 +8,169 @@
|
||||
/** @file town_sl.cpp Code handling saving and loading of towns and houses */
|
||||
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/town_sl_compat.h"
|
||||
|
||||
#include "newgrf_sl.h"
|
||||
#include "../newgrf_house.h"
|
||||
#include "../town.h"
|
||||
#include "../landscape.h"
|
||||
#include "../subsidy_func.h"
|
||||
#include "../strings_func.h"
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "newgrf_sl.h"
|
||||
#include "../tilematrix_type.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
static bool _town_zone_radii_no_update = false;
|
||||
namespace upstream_sl {
|
||||
|
||||
extern bool IsGetTownZonesCallbackHandlerPresent();
|
||||
typedef TileMatrix<CargoTypes, 4> AcceptanceMatrix;
|
||||
|
||||
HouseID SLGetCleanHouseType(TileIndex t, bool old_map_position)
|
||||
{
|
||||
if (old_map_position && SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) {
|
||||
return _m[t].m4 | (GB(_m[t].m3, 6, 1) << 8);
|
||||
} else {
|
||||
return GetCleanHouseType(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild all the cached variables of towns.
|
||||
*/
|
||||
void RebuildTownCaches(bool cargo_update_required, bool old_map_position)
|
||||
{
|
||||
InitializeBuildingCounts();
|
||||
RebuildTownKdtree();
|
||||
|
||||
/* Reset town population and num_houses */
|
||||
for (Town *town : Town::Iterate()) {
|
||||
town->cache.population = 0;
|
||||
town->cache.num_houses = 0;
|
||||
}
|
||||
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (!IsTileType(t, MP_HOUSE)) continue;
|
||||
|
||||
HouseID house_id = GetTranslatedHouseID(SLGetCleanHouseType(t, old_map_position));
|
||||
Town *town = Town::GetByTile(t);
|
||||
IncreaseBuildingCount(town, house_id);
|
||||
if (IsHouseCompleted(t)) town->cache.population += HouseSpec::Get(house_id)->population;
|
||||
|
||||
/* Increase the number of houses for every house, but only once. */
|
||||
if (GetHouseNorthPart(house_id) == 0) town->cache.num_houses++;
|
||||
}
|
||||
|
||||
if (!_town_zone_radii_no_update) {
|
||||
/* Update the population and num_house dependent values */
|
||||
for (Town *town : Town::Iterate()) {
|
||||
UpdateTownRadius(town);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckMultiTileHouseTypes(bool &cargo_update_required, bool old_map_position, bool translate_house_types)
|
||||
{
|
||||
auto get_clean_house_type = [&](TileIndex t) -> HouseID {
|
||||
HouseID type = SLGetCleanHouseType(t, old_map_position);
|
||||
if (translate_house_types) type = GetTranslatedHouseID(type);
|
||||
return type;
|
||||
class SlTownSupplied : public DefaultSaveLoadHandler<SlTownSupplied, Town> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _town_supplied_sl_compat;
|
||||
|
||||
/* Check for cases when a NewGRF has set a wrong house substitute type. */
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (!IsTileType(t, MP_HOUSE)) continue;
|
||||
|
||||
HouseID house_type = get_clean_house_type(t);
|
||||
TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'!
|
||||
if (t == north_tile) {
|
||||
const HouseSpec *hs = HouseSpec::Get(house_type);
|
||||
bool valid_house = true;
|
||||
if (hs->building_flags & TILE_SIZE_2x1) {
|
||||
TileIndex tile = t + TileDiffXY(1, 0);
|
||||
if (!IsTileType(tile, MP_HOUSE) || get_clean_house_type(tile) != house_type + 1) valid_house = false;
|
||||
} else if (hs->building_flags & TILE_SIZE_1x2) {
|
||||
TileIndex tile = t + TileDiffXY(0, 1);
|
||||
if (!IsTileType(tile, MP_HOUSE) || get_clean_house_type(tile) != house_type + 1) valid_house = false;
|
||||
} else if (hs->building_flags & TILE_SIZE_2x2) {
|
||||
TileIndex tile = t + TileDiffXY(0, 1);
|
||||
if (!IsTileType(tile, MP_HOUSE) || get_clean_house_type(tile) != house_type + 1) valid_house = false;
|
||||
tile = t + TileDiffXY(1, 0);
|
||||
if (!IsTileType(tile, MP_HOUSE) || get_clean_house_type(tile) != house_type + 2) valid_house = false;
|
||||
tile = t + TileDiffXY(1, 1);
|
||||
if (!IsTileType(tile, MP_HOUSE) || get_clean_house_type(tile) != house_type + 3) valid_house = false;
|
||||
}
|
||||
/* If not all tiles of this house are present remove the house.
|
||||
* The other tiles will get removed later in this loop because
|
||||
* their north tile is not the correct type anymore. */
|
||||
if (!valid_house) {
|
||||
DoClearSquare(t);
|
||||
cargo_update_required = true;
|
||||
}
|
||||
} else if (!IsTileType(north_tile, MP_HOUSE) || get_clean_house_type(north_tile) != house_type) {
|
||||
/* This tile should be part of a multi-tile building but the
|
||||
* north tile of this house isn't on the map. */
|
||||
DoClearSquare(t);
|
||||
cargo_update_required = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and update town and house values.
|
||||
*
|
||||
* Checked are the HouseIDs. Updated are the
|
||||
* town population the number of houses per
|
||||
* town, the town radius and the max passengers
|
||||
* of the town.
|
||||
/**
|
||||
* Get the number of cargoes used by this savegame version.
|
||||
* @return The number of cargoes used by this savegame version.
|
||||
*/
|
||||
void UpdateHousesAndTowns(bool cargo_update_required, bool old_map_position)
|
||||
{
|
||||
auto get_clean_house_type = [&](TileIndex t) -> HouseID {
|
||||
return SLGetCleanHouseType(t, old_map_position);
|
||||
size_t GetNumCargo() const
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES)) return 32;
|
||||
if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return NUM_CARGO;
|
||||
/* Read from the savegame how long the list is. */
|
||||
return SlGetStructListLength(NUM_CARGO);
|
||||
}
|
||||
|
||||
void Save(Town *t) const override
|
||||
{
|
||||
SlSetStructListLength(NUM_CARGO);
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
SlObject(&t->supplied[i], this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(Town *t) const override
|
||||
{
|
||||
size_t num_cargo = this->GetNumCargo();
|
||||
for (size_t i = 0; i < num_cargo; i++) {
|
||||
SlObject(&t->supplied[i], this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SlTownReceived : public DefaultSaveLoadHandler<SlTownReceived, Town> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
};
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (!IsTileType(t, MP_HOUSE)) continue;
|
||||
inline const static SaveLoadCompatTable compat_description = _town_received_sl_compat;
|
||||
|
||||
HouseID house_id = get_clean_house_type(t);
|
||||
if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
|
||||
/* The specs for this type of house are not available any more, so
|
||||
* replace it with the substitute original house type. */
|
||||
house_id = _house_mngr.GetSubstituteID(house_id);
|
||||
if (old_map_position && SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) {
|
||||
_m[t].m4 = GB(house_id, 0, 8);
|
||||
SB(_m[t].m3, 6, 1, GB(house_id, 8, 1));
|
||||
} else {
|
||||
SetHouseType(t, house_id);
|
||||
}
|
||||
cargo_update_required = true;
|
||||
void Save(Town *t) const override
|
||||
{
|
||||
SlSetStructListLength(NUM_TE);
|
||||
for (size_t i = TE_BEGIN; i < TE_END; i++) {
|
||||
SlObject(&t->received[i], this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
CheckMultiTileHouseTypes(cargo_update_required, old_map_position, false);
|
||||
if (cargo_update_required || SlXvIsFeatureMissing(XSLFI_MORE_HOUSES, 2)) CheckMultiTileHouseTypes(cargo_update_required, old_map_position, true);
|
||||
void Load(Town *t) const override
|
||||
{
|
||||
size_t length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? (size_t)TE_END : SlGetStructListLength(TE_END);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
SlObject(&t->received[i], this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RebuildTownCaches(cargo_update_required, old_map_position);
|
||||
}
|
||||
class SlTownAcceptanceMatrix : public DefaultSaveLoadHandler<SlTownAcceptanceMatrix, Town> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(AcceptanceMatrix, area.tile, SLE_UINT32),
|
||||
SLE_VAR(AcceptanceMatrix, area.w, SLE_UINT16),
|
||||
SLE_VAR(AcceptanceMatrix, area.h, SLE_UINT16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _town_acceptance_matrix_sl_compat;
|
||||
|
||||
void Load(Town *t) const override
|
||||
{
|
||||
/* Discard now unused acceptance matrix. */
|
||||
AcceptanceMatrix dummy;
|
||||
SlObject(&dummy, this->GetLoadDescription());
|
||||
if (dummy.area.w != 0) {
|
||||
uint arr_len = dummy.area.w / AcceptanceMatrix::GRID * dummy.area.h / AcceptanceMatrix::GRID;
|
||||
SlSkipBytes(4 * arr_len);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Save and load of towns. */
|
||||
static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDVAR(Town, xy, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDVAR(Town, xy, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_3), ///< population, no longer in use
|
||||
SLE_CONDNULL(4, SLV_3, SLV_85), ///< population, no longer in use
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_92), ///< num_houses, no longer in use
|
||||
|
||||
SLE_CONDVAR(Town, townnamegrfid, SLE_UINT32, SLV_66, SL_MAX_VERSION),
|
||||
SLE_VAR(Town, townnametype, SLE_UINT16),
|
||||
SLE_VAR(Town, townnameparts, SLE_UINT32),
|
||||
SLE_CONDSTR(Town, name, SLE_STR | SLF_ALLOW_CONTROL, 0, SLV_84, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Town, flags, SLE_UINT8),
|
||||
SLE_CONDVAR_X(Town, church_count, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_MULTI_BUILDING)),
|
||||
SLE_CONDVAR_X(Town, stadium_count, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_MULTI_BUILDING)),
|
||||
SLE_CONDVAR(Town, statues, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDVAR(Town, statues, SLE_UINT16, SLV_104, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_2), ///< sort_index, no longer in use
|
||||
|
||||
SLE_CONDVAR(Town, have_ratings, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDVAR(Town, have_ratings, SLE_UINT16, SLV_104, SL_MAX_VERSION),
|
||||
SLE_CONDARR(Town, ratings, SLE_INT16, 8, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(MAX_COMPANIES, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SPRINGPP)),
|
||||
/* failed bribe attempts are stored since savegame format 4 */
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104),
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_164), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
|
||||
SLE_CONDNULL_X(3, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
|
||||
SLE_CONDVAR(Town, received[TE_FOOD].old_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDVAR(Town, received[TE_WATER].old_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, received[TE_FOOD].new_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDVAR(Town, received[TE_WATER].new_act, SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
|
||||
SLE_CONDARR(Town, goal, SLE_UINT32, NUM_TE, SLV_165, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDSSTR(Town, text, SLE_STR | SLF_ALLOW_CONTROL, SLV_168, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, time_until_rebuild, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, grow_counter, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_FILE_U8 | SLE_VAR_I16, SL_MIN_VERSION, SLV_54),
|
||||
|
||||
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP)),
|
||||
SLE_CONDVAR(Town, time_until_rebuild, SLE_UINT16, SLV_54, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_26)),
|
||||
SLE_CONDVAR(Town, grow_counter, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, grow_counter, SLE_UINT16, SLV_54, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_FILE_U8 | SLE_VAR_I16, SL_MIN_VERSION, SLV_54),
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_FILE_I16 | SLE_VAR_U16, SLV_54, SLV_165),
|
||||
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_26)),
|
||||
SLE_CONDVAR(Town, growth_rate, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Town, fund_buildings_months, SLE_UINT8),
|
||||
SLE_VAR(Town, road_build_months, SLE_UINT8),
|
||||
|
||||
SLE_CONDVAR(Town, exclusivity, SLE_UINT8, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, exclusive_counter, SLE_UINT8, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, larger_town, SLE_BOOL, SLV_56, SL_MAX_VERSION),
|
||||
@@ -247,193 +178,61 @@ static const SaveLoad _town_desc[] = {
|
||||
|
||||
SLE_CONDREFLIST(Town, psa_list, REF_STORAGE, SLV_161, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(4, SLV_166, SLV_EXTEND_CARGOTYPES), ///< cargo_produced, no longer in use
|
||||
SLE_CONDNULL(8, SLV_EXTEND_CARGOTYPES, SLV_REMOVE_TOWN_CARGO_CACHE), ///< cargo_produced, no longer in use
|
||||
SLE_CONDNULL(30, SLV_2, SLV_REMOVE_TOWN_CARGO_CACHE), ///< old reserved space
|
||||
|
||||
SLE_CONDVAR_X(Town, override_flags, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||
SLE_CONDVAR_X(Town, override_values, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||
SLE_CONDVAR_X(Town, build_tunnels, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||
SLE_CONDVAR_X(Town, max_road_slope, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TOWN_SETTING_OVERRIDE)),
|
||||
SLEG_CONDSTRUCTLIST("supplied", SlTownSupplied, SLV_165, SL_MAX_VERSION),
|
||||
SLEG_CONDSTRUCTLIST("received", SlTownReceived, SLV_165, SL_MAX_VERSION),
|
||||
SLEG_CONDSTRUCTLIST("acceptance_matrix", SlTownAcceptanceMatrix, SLV_166, SLV_REMOVE_TOWN_CARGO_CACHE),
|
||||
};
|
||||
|
||||
static const SaveLoad _town_supplied_desc[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_max, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, old_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint32>, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION),
|
||||
struct HIDSChunkHandler : NewGRFMappingChunkHandler {
|
||||
HIDSChunkHandler() : NewGRFMappingChunkHandler('HIDS', _house_mngr) {}
|
||||
};
|
||||
|
||||
static const SaveLoad _town_received_desc[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_max, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_act, SLE_UINT16, SLV_165, SL_MAX_VERSION),
|
||||
};
|
||||
struct CITYChunkHandler : ChunkHandler {
|
||||
CITYChunkHandler() : ChunkHandler('CITY', CH_TABLE) {}
|
||||
|
||||
static const SaveLoad _town_received_desc_spp[] = {
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_max, SLE_FILE_U32 | SLE_VAR_U16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_max, SLE_FILE_U32 | SLE_VAR_U16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, old_act, SLE_FILE_U32 | SLE_VAR_U16, SLV_165, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(TransportedCargoStat<uint16>, new_act, SLE_FILE_U32 | SLE_VAR_U16, SLV_165, SL_MAX_VERSION),
|
||||
};
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_town_desc);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void Load_HIDS()
|
||||
{
|
||||
Load_NewGRFMapping(_house_mngr);
|
||||
}
|
||||
|
||||
static void RealSave_Town(Town *t)
|
||||
{
|
||||
SlObjectSaveFiltered(t, _filtered_town_desc);
|
||||
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
SlObjectSaveFiltered(&t->supplied[i], _filtered_town_supplied_desc);
|
||||
}
|
||||
for (int i = TE_BEGIN; i < NUM_TE; i++) {
|
||||
SlObjectSaveFiltered(&t->received[i], _filtered_town_received_desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void Save_TOWN()
|
||||
{
|
||||
SetupDescs_TOWN();
|
||||
for (Town *t : Town::Iterate()) {
|
||||
SlSetArrayIndex(t->index);
|
||||
SlAutolength((AutolengthProc*)RealSave_Town, t);
|
||||
SlObject(t, _town_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Load_TOWN()
|
||||
{
|
||||
SetupDescs_TOWN();
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_town_desc, _town_sl_compat);
|
||||
|
||||
int index;
|
||||
uint num_cargo = IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Town *t = new (index) Town();
|
||||
SlObjectLoadFiltered(t, _filtered_town_desc);
|
||||
|
||||
for (CargoID i = 0; i < num_cargo; i++) {
|
||||
SlObjectLoadFiltered(&t->supplied[i], _filtered_town_supplied_desc);
|
||||
}
|
||||
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++) {
|
||||
SlObjectLoadFiltered(&t->received[i], _filtered_town_received_desc);
|
||||
}
|
||||
}
|
||||
SlObject(t, slt);
|
||||
|
||||
if (t->townnamegrfid == 0 && !IsInsideMM(t->townnametype, SPECSTR_TOWNNAME_START, SPECSTR_TOWNNAME_LAST + 1) && GetStringTab(t->townnametype) != TEXT_TAB_OLD_CUSTOM) {
|
||||
SlErrorCorrupt("Invalid town name generator");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!IsSavegameVersionBefore(SLV_166) && IsSavegameVersionBefore(SLV_REMOVE_TOWN_CARGO_CACHE)) || SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX)) {
|
||||
SlSkipBytes(4); // tile
|
||||
uint16 w = SlReadUint16();
|
||||
uint16 h = SlReadUint16();
|
||||
if (w != 0) {
|
||||
SlSkipBytes((SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX) ? 8 : 4) * ((uint)(w / 4) * (uint)(h / 4)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fix pointers when loading town data. */
|
||||
static void Ptrs_TOWN()
|
||||
{
|
||||
/* Don't run when savegame version lower than 161. */
|
||||
void FixPointers() const override
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_161)) return;
|
||||
|
||||
SetupDescs_TOWN();
|
||||
for (Town *t : Town::Iterate()) {
|
||||
SlObjectPtrOrNullFiltered(t, _filtered_town_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void SlResetTNNC()
|
||||
{
|
||||
_town_zone_radii_no_update = false;
|
||||
}
|
||||
|
||||
void Save_TNNC()
|
||||
{
|
||||
assert(_sl_xv_feature_versions[XSLFI_TNNC_CHUNK] != 0);
|
||||
|
||||
if (!IsNetworkServerSave() || !IsGetTownZonesCallbackHandlerPresent()) {
|
||||
SlSetLength(0);
|
||||
return;
|
||||
}
|
||||
|
||||
SlSetLength(4 + (Town::GetNumItems() * (1 + lengthof(TownCache::squared_town_zone_radius)) * 4));
|
||||
|
||||
SlWriteUint32((uint32)Town::GetNumItems());
|
||||
|
||||
for (const Town *t : Town::Iterate()) {
|
||||
SlWriteUint32(t->index);
|
||||
for (uint i = 0; i < lengthof(TownCache::squared_town_zone_radius); i++) {
|
||||
SlWriteUint32(t->cache.squared_town_zone_radius[i]);
|
||||
SlObject(t, _town_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Load_TNNC()
|
||||
{
|
||||
if (SlGetFieldLength() == 0) return;
|
||||
|
||||
if (!_networking || _network_server) {
|
||||
SlSkipBytes(SlGetFieldLength());
|
||||
return;
|
||||
}
|
||||
|
||||
_town_zone_radii_no_update = true;
|
||||
|
||||
const uint32 count = SlReadUint32();
|
||||
for (uint32 idx = 0; idx < count; idx++) {
|
||||
Town *t = Town::Get(SlReadUint32());
|
||||
for (uint i = 0; i < lengthof(TownCache::squared_town_zone_radius); i++) {
|
||||
t->cache.squared_town_zone_radius[i] = SlReadUint32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ChunkSaveLoadSpecialOpResult Special_TNNC(uint32 chunk_id, ChunkSaveLoadSpecialOp op)
|
||||
{
|
||||
switch (op) {
|
||||
case CSLSO_SHOULD_SAVE_CHUNK:
|
||||
if (_sl_xv_feature_versions[XSLFI_TNNC_CHUNK] == 0) return CSLSOR_DONT_SAVE_CHUNK;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CSLSOR_NONE;
|
||||
}
|
||||
|
||||
/** Chunk handler for towns. */
|
||||
static const ChunkHandler town_chunk_handlers[] = {
|
||||
{ 'HIDS', Save_HIDS, Load_HIDS, nullptr, nullptr, CH_ARRAY },
|
||||
{ 'CITY', Save_TOWN, Load_TOWN, Ptrs_TOWN, nullptr, CH_ARRAY },
|
||||
{ 'TNNC', Save_TNNC, Load_TNNC, nullptr, nullptr, CH_RIFF, Special_TNNC },
|
||||
static const HIDSChunkHandler HIDS;
|
||||
static const CITYChunkHandler CITY;
|
||||
static const ChunkHandlerRef town_chunk_handlers[] = {
|
||||
HIDS,
|
||||
CITY,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _town_chunk_handlers(town_chunk_handlers);
|
||||
|
||||
}
|
||||
|
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file ai_sl.cpp Handles the saveload part of the AIs */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/ai_sl_compat.h"
|
||||
|
||||
#include "../../company_base.h"
|
||||
#include "../../string_func.h"
|
||||
|
||||
#include "../../ai/ai.hpp"
|
||||
#include "../../ai/ai_config.hpp"
|
||||
#include "../../network/network.h"
|
||||
#include "../../ai/ai_instance.hpp"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static std::string _ai_saveload_name;
|
||||
static int _ai_saveload_version;
|
||||
static std::string _ai_saveload_settings;
|
||||
static bool _ai_saveload_is_random;
|
||||
|
||||
static const SaveLoad _ai_company_desc[] = {
|
||||
SLEG_SSTR("name", _ai_saveload_name, SLE_STR),
|
||||
SLEG_SSTR("settings", _ai_saveload_settings, SLE_STR),
|
||||
SLEG_CONDVAR("version", _ai_saveload_version, SLE_UINT32, SLV_108, SL_MAX_VERSION),
|
||||
SLEG_CONDVAR("is_random", _ai_saveload_is_random, SLE_BOOL, SLV_136, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
static void SaveReal_AIPL(int *index_ptr)
|
||||
{
|
||||
CompanyID index = (CompanyID)*index_ptr;
|
||||
AIConfig *config = AIConfig::GetConfig(index);
|
||||
|
||||
if (config->HasScript()) {
|
||||
_ai_saveload_name = config->GetName();
|
||||
_ai_saveload_version = config->GetVersion();
|
||||
} else {
|
||||
/* No AI is configured for this so store an empty string as name. */
|
||||
_ai_saveload_name.clear();
|
||||
_ai_saveload_version = -1;
|
||||
}
|
||||
|
||||
_ai_saveload_is_random = config->IsRandom();
|
||||
_ai_saveload_settings = config->SettingsToString();
|
||||
|
||||
SlObject(nullptr, _ai_company_desc);
|
||||
/* If the AI was active, store its data too */
|
||||
if (Company::IsValidAiID(index)) AI::Save(index);
|
||||
}
|
||||
|
||||
struct AIPLChunkHandler : ChunkHandler {
|
||||
AIPLChunkHandler() : ChunkHandler('AIPL', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_ai_company_desc, _ai_company_sl_compat);
|
||||
|
||||
/* Free all current data */
|
||||
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
|
||||
AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(nullptr);
|
||||
}
|
||||
|
||||
CompanyID index;
|
||||
while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) {
|
||||
if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs");
|
||||
|
||||
_ai_saveload_is_random = false;
|
||||
_ai_saveload_version = -1;
|
||||
SlObject(nullptr, slt);
|
||||
|
||||
if (_game_mode == GM_MENU || (_networking && !_network_server)) {
|
||||
if (Company::IsValidAiID(index)) AIInstance::LoadEmpty();
|
||||
continue;
|
||||
}
|
||||
|
||||
AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME);
|
||||
if (_ai_saveload_name.empty()) {
|
||||
/* A random AI. */
|
||||
config->Change(nullptr, -1, false, true);
|
||||
} else {
|
||||
config->Change(_ai_saveload_name.c_str(), _ai_saveload_version, false, _ai_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
/* No version of the AI available that can load the data. Try to load the
|
||||
* latest version of the AI instead. */
|
||||
config->Change(_ai_saveload_name.c_str(), -1, false, _ai_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
if (_ai_saveload_name.compare("%_dummy") != 0) {
|
||||
DEBUG(script, 0, "The savegame has an AI by the name '%s', version %u which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version);
|
||||
DEBUG(script, 0, "A random other AI will be loaded in its place.");
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame had no AIs available at the time of saving.");
|
||||
DEBUG(script, 0, "A random available AI will be loaded now.");
|
||||
}
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame has an AI by the name '%s', version %u which is no longer available.", _ai_saveload_name.c_str(), _ai_saveload_version);
|
||||
DEBUG(script, 0, "The latest version of that AI has been loaded instead, but it'll not get the savegame data as it's incompatible.");
|
||||
}
|
||||
/* Make sure the AI doesn't get the saveload data, as it was not the
|
||||
* writer of the saveload data in the first place */
|
||||
_ai_saveload_version = -1;
|
||||
}
|
||||
}
|
||||
|
||||
config->StringToSettings(_ai_saveload_settings);
|
||||
|
||||
/* Load the AI saved data */
|
||||
if (Company::IsValidAiID(index)) config->SetToLoadData(AIInstance::Load(_ai_saveload_version));
|
||||
}
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_ai_company_desc);
|
||||
|
||||
for (int i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlAutolength((AutolengthProc *)SaveReal_AIPL, &i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const AIPLChunkHandler AIPL;
|
||||
static const ChunkHandlerRef ai_chunk_handlers[] = {
|
||||
AIPL,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _ai_chunk_handlers(ai_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file animated_tile_sl.cpp Code handling saving and loading of animated tiles */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/animated_tile_sl_compat.h"
|
||||
|
||||
#include "../../tile_type.h"
|
||||
#include "../../animated_tile.h"
|
||||
#include "../../core/alloc_func.hpp"
|
||||
#include "../../core/smallvec_type.hpp"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static std::vector <TileIndex> _tmp_animated_tiles;
|
||||
|
||||
static const SaveLoad _animated_tile_desc[] = {
|
||||
SLEG_VECTOR("tiles", _tmp_animated_tiles, SLE_UINT32),
|
||||
};
|
||||
|
||||
struct ANITChunkHandler : ChunkHandler {
|
||||
ANITChunkHandler() : ChunkHandler('ANIT', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
// removed
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
/* Before version 80 we did NOT have a variable length animated tile table */
|
||||
if (IsSavegameVersionBefore(SLV_80)) {
|
||||
/* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */
|
||||
TileIndex anim_list[256];
|
||||
SlCopy(anim_list, 256, IsSavegameVersionBefore(SLV_6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (anim_list[i] == 0) break;
|
||||
_animated_tiles[anim_list[i]] = {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
|
||||
size_t count = SlGetFieldLength() / sizeof(uint32);
|
||||
_animated_tiles.clear();
|
||||
for (uint i = 0; i < count; i++) {
|
||||
_animated_tiles[SlReadUint32()] = {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_animated_tile_desc, _animated_tile_sl_compat);
|
||||
|
||||
if (SlIterateArray() == -1) return;
|
||||
SlGlobList(slt);
|
||||
if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries");
|
||||
|
||||
for (TileIndex t : _tmp_animated_tiles) {
|
||||
_animated_tiles[t] = {};
|
||||
}
|
||||
_tmp_animated_tiles.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const ANITChunkHandler ANIT;
|
||||
static const ChunkHandlerRef animated_tile_chunk_handlers[] = {
|
||||
ANIT,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _animated_tile_chunk_handlers(animated_tile_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file autoreplace_sl.cpp Code handling saving and loading of autoreplace rules */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/autoreplace_sl_compat.h"
|
||||
|
||||
#include "../../autoreplace_base.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _engine_renew_desc[] = {
|
||||
SLE_VAR(EngineRenew, from, SLE_UINT16),
|
||||
SLE_VAR(EngineRenew, to, SLE_UINT16),
|
||||
|
||||
SLE_REF(EngineRenew, next, REF_ENGINE_RENEWS),
|
||||
SLE_CONDVAR(EngineRenew, group_id, SLE_UINT16, SLV_60, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(EngineRenew, replace_when_old, SLE_BOOL, SLV_175, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
struct ERNWChunkHandler : ChunkHandler {
|
||||
ERNWChunkHandler() : ChunkHandler('ERNW', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_engine_renew_desc);
|
||||
|
||||
for (EngineRenew *er : EngineRenew::Iterate()) {
|
||||
SlSetArrayIndex(er->index);
|
||||
SlObject(er, _engine_renew_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_renew_desc, _engine_renew_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
EngineRenew *er = new (index) EngineRenew();
|
||||
SlObject(er, slt);
|
||||
|
||||
/* Advanced vehicle lists, ungrouped vehicles got added */
|
||||
if (IsSavegameVersionBefore(SLV_60)) {
|
||||
er->group_id = ALL_GROUP;
|
||||
} else if (IsSavegameVersionBefore(SLV_71)) {
|
||||
if (er->group_id == DEFAULT_GROUP) er->group_id = ALL_GROUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (EngineRenew *er : EngineRenew::Iterate()) {
|
||||
SlObject(er, _engine_renew_desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ERNWChunkHandler ERNW;
|
||||
static const ChunkHandlerRef autoreplace_chunk_handlers[] = {
|
||||
ERNW,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _autoreplace_chunk_handlers(autoreplace_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file cargomonitor_sl.cpp Code handling saving and loading of Cargo monitoring. */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/cargomonitor_sl_compat.h"
|
||||
|
||||
#include "../../cargomonitor.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/** Temporary storage of cargo monitoring data for loading or saving it. */
|
||||
struct TempStorage {
|
||||
CargoMonitorID number;
|
||||
uint32 amount;
|
||||
};
|
||||
|
||||
/** Description of the #TempStorage structure for the purpose of load and save. */
|
||||
static const SaveLoad _cargomonitor_pair_desc[] = {
|
||||
SLE_VAR(TempStorage, number, SLE_UINT32),
|
||||
SLE_VAR(TempStorage, amount, SLE_UINT32),
|
||||
};
|
||||
|
||||
static CargoMonitorID FixupCargoMonitor(CargoMonitorID number)
|
||||
{
|
||||
/* Between SLV_EXTEND_CARGOTYPES and SLV_FIX_CARGO_MONITOR, the
|
||||
* CargoMonitorID structure had insufficient packing for more
|
||||
* than 32 cargo types. Here we have to shuffle bits to account
|
||||
* for the change.
|
||||
* Company moved from bits 24-31 to 25-28.
|
||||
* Cargo type increased from bits 19-23 to 19-24.
|
||||
*/
|
||||
SB(number, 25, 4, GB(number, 24, 4));
|
||||
SB(number, 29, 3, 0);
|
||||
ClrBit(number, 24);
|
||||
return number;
|
||||
}
|
||||
|
||||
/** #_cargo_deliveries monitoring map. */
|
||||
struct CMDLChunkHandler : ChunkHandler {
|
||||
CMDLChunkHandler() : ChunkHandler('CMDL', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cargomonitor_pair_desc);
|
||||
|
||||
TempStorage storage;
|
||||
|
||||
int i = 0;
|
||||
CargoMonitorMap::const_iterator iter = _cargo_deliveries.begin();
|
||||
while (iter != _cargo_deliveries.end()) {
|
||||
storage.number = iter->first;
|
||||
storage.amount = iter->second;
|
||||
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
|
||||
|
||||
TempStorage storage;
|
||||
bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
|
||||
|
||||
ClearCargoDeliveryMonitoring();
|
||||
for (;;) {
|
||||
if (SlIterateArray() < 0) break;
|
||||
SlObject(&storage, slt);
|
||||
|
||||
if (fix) storage.number = FixupCargoMonitor(storage.number);
|
||||
|
||||
std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
|
||||
_cargo_deliveries.insert(p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** #_cargo_pickups monitoring map. */
|
||||
struct CMPUChunkHandler : ChunkHandler {
|
||||
CMPUChunkHandler() : ChunkHandler('CMPU', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cargomonitor_pair_desc);
|
||||
|
||||
TempStorage storage;
|
||||
|
||||
int i = 0;
|
||||
CargoMonitorMap::const_iterator iter = _cargo_pickups.begin();
|
||||
while (iter != _cargo_pickups.end()) {
|
||||
storage.number = iter->first;
|
||||
storage.amount = iter->second;
|
||||
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(&storage, _cargomonitor_pair_desc);
|
||||
|
||||
i++;
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargomonitor_pair_desc, _cargomonitor_pair_sl_compat);
|
||||
|
||||
TempStorage storage;
|
||||
bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR);
|
||||
|
||||
ClearCargoPickupMonitoring();
|
||||
for (;;) {
|
||||
if (SlIterateArray() < 0) break;
|
||||
SlObject(&storage, slt);
|
||||
|
||||
if (fix) storage.number = FixupCargoMonitor(storage.number);
|
||||
|
||||
std::pair<CargoMonitorID, uint32> p(storage.number, storage.amount);
|
||||
_cargo_pickups.insert(p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Chunk definition of the cargomonitoring maps. */
|
||||
static const CMDLChunkHandler CMDL;
|
||||
static const CMPUChunkHandler CMPU;
|
||||
static const ChunkHandlerRef cargomonitor_chunk_handlers[] = {
|
||||
CMDL,
|
||||
CMPU,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _cargomonitor_chunk_handlers(cargomonitor_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file cargopacket_sl.cpp Code handling saving and loading of cargo packets */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/cargopacket_sl_compat.h"
|
||||
|
||||
#include "../../vehicle_base.h"
|
||||
#include "../../station_base.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/**
|
||||
* Wrapper function to get the CargoPacket's internal structure while
|
||||
* some of the variables itself are private.
|
||||
* @return the saveload description for CargoPackets.
|
||||
*/
|
||||
SaveLoadTable GetCargoPacketDesc()
|
||||
{
|
||||
static const SaveLoad _cargopacket_desc[] = {
|
||||
SLE_VAR(CargoPacket, source, SLE_UINT16),
|
||||
SLE_VAR(CargoPacket, source_xy, SLE_UINT32),
|
||||
SLE_VAR(CargoPacket, loaded_at_xy, SLE_UINT32),
|
||||
SLE_VAR(CargoPacket, count, SLE_UINT16),
|
||||
SLE_CONDVAR(CargoPacket, days_in_transit, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_MORE_CARGO_AGE),
|
||||
SLE_CONDVAR(CargoPacket, days_in_transit, SLE_UINT16, SLV_MORE_CARGO_AGE, SL_MAX_VERSION),
|
||||
SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
|
||||
SLE_CONDVAR(CargoPacket, source_type, SLE_UINT8, SLV_125, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CargoPacket, source_id, SLE_UINT16, SLV_125, SL_MAX_VERSION),
|
||||
};
|
||||
return _cargopacket_desc;
|
||||
}
|
||||
|
||||
struct CAPAChunkHandler : ChunkHandler {
|
||||
CAPAChunkHandler() : ChunkHandler('CAPA', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(GetCargoPacketDesc());
|
||||
|
||||
for (CargoPacket *cp : CargoPacket::Iterate()) {
|
||||
SlSetArrayIndex(cp->index);
|
||||
SlObject(cp, GetCargoPacketDesc());
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
CargoPacket *cp = new (index) CargoPacket();
|
||||
SlObject(cp, slt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const CAPAChunkHandler CAPA;
|
||||
static const ChunkHandlerRef cargopacket_chunk_handlers[] = {
|
||||
CAPA,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _cargopacket_chunk_handlers(cargopacket_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file cheat_sl.cpp Code handling saving and loading of cheats */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/cheat_sl_compat.h"
|
||||
|
||||
#include "../../cheat_type.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _cheats_desc[] = {
|
||||
SLE_VAR(Cheats, magic_bulldozer.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, magic_bulldozer.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, switch_company.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, switch_company.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, money.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, money.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, crossing_tunnels.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, crossing_tunnels.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, no_jetcrash.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, no_jetcrash.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, change_date.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, change_date.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, setup_prod.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, setup_prod.value, SLE_BOOL),
|
||||
SLE_VAR(Cheats, edit_max_hl.been_used, SLE_BOOL),
|
||||
SLE_VAR(Cheats, edit_max_hl.value, SLE_BOOL),
|
||||
};
|
||||
|
||||
|
||||
struct CHTSChunkHandler : ChunkHandler {
|
||||
CHTSChunkHandler() : ChunkHandler('CHTS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cheats_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlObject(&_cheats, _cheats_desc);
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
std::vector<SaveLoad> slt = SlCompatTableHeader(_cheats_desc, _cheats_sl_compat);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_TABLE_CHUNKS)) {
|
||||
size_t count = SlGetFieldLength();
|
||||
std::vector<SaveLoad> oslt;
|
||||
|
||||
/* Cheats were added over the years without a savegame bump. They are
|
||||
* stored as 2 SLE_BOOLs per entry. "count" indicates how many SLE_BOOLs
|
||||
* are stored for this savegame. So read only "count" SLE_BOOLs (and in
|
||||
* result "count / 2" cheats). */
|
||||
for (auto &sld : slt) {
|
||||
count--;
|
||||
oslt.push_back(sld);
|
||||
|
||||
if (count == 0) break;
|
||||
}
|
||||
slt = oslt;
|
||||
}
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlObject(&_cheats, slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many CHTS entries");
|
||||
}
|
||||
};
|
||||
|
||||
static const CHTSChunkHandler CHTS;
|
||||
static const ChunkHandlerRef cheat_chunk_handlers[] = {
|
||||
CHTS,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _cheat_chunk_handlers(cheat_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,363 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file company_sl.cpp Code handling saving and loading of company data */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/company_sl_compat.h"
|
||||
|
||||
#include "../../company_func.h"
|
||||
#include "../../company_manager_face.h"
|
||||
#include "../../fios.h"
|
||||
#include "../../tunnelbridge_map.h"
|
||||
#include "../../tunnelbridge.h"
|
||||
#include "../../station_base.h"
|
||||
#include "../../strings_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
void SetDefaultCompanySettings(CompanyID cid);
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
/* We do need to read this single value, as the bigger it gets, the more data is stored */
|
||||
struct CompanyOldAI {
|
||||
uint8 num_build_rec;
|
||||
};
|
||||
|
||||
class SlCompanyOldAIBuildRec : public DefaultSaveLoadHandler<SlCompanyOldAIBuildRec, CompanyOldAI> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {{}}; // Needed to keep DefaultSaveLoadHandler happy.
|
||||
inline const static SaveLoadCompatTable compat_description = _company_old_ai_buildrec_compat;
|
||||
|
||||
SaveLoadTable GetDescription() const override { return {}; }
|
||||
|
||||
void Load(CompanyOldAI *old_ai) const override
|
||||
{
|
||||
for (int i = 0; i != old_ai->num_build_rec; i++) {
|
||||
SlObject(nullptr, this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyOldAI *old_ai) const override { this->Load(old_ai); }
|
||||
};
|
||||
|
||||
class SlCompanyOldAI : public DefaultSaveLoadHandler<SlCompanyOldAI, CompanyProperties> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(CompanyOldAI, num_build_rec, SLE_UINT8, SL_MIN_VERSION, SLV_107),
|
||||
SLEG_STRUCTLIST("buildrec", SlCompanyOldAIBuildRec),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_old_ai_compat;
|
||||
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
if (!c->is_ai) return;
|
||||
|
||||
CompanyOldAI old_ai;
|
||||
SlObject(&old_ai, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
class SlCompanySettings : public DefaultSaveLoadHandler<SlCompanySettings, CompanyProperties> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
/* Engine renewal settings */
|
||||
SLE_CONDREF(CompanyProperties, engine_renew_list, REF_ENGINE_RENEWS, SLV_19, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.engine_renew, SLE_BOOL, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.engine_renew_months, SLE_INT16, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.engine_renew_money, SLE_UINT32, SLV_16, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.renew_keep_length, SLE_BOOL, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
/* Default vehicle settings */
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_ispercent, SLE_BOOL, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_trains, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_roadveh, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_aircraft, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, settings.vehicle.servint_ships, SLE_UINT16, SLV_120, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_settings_compat;
|
||||
|
||||
void Save(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(c, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(c, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void FixPointers(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(c, this->GetDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
class SlCompanyEconomy : public DefaultSaveLoadHandler<SlCompanyEconomy, CompanyProperties> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_CONDVAR(CompanyEconomyEntry, income, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, income, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, expenses, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, SL_MIN_VERSION, SLV_170),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, SLV_170, SLV_EXTEND_CARGOTYPES),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||
SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_economy_compat;
|
||||
|
||||
void Save(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(&c->cur_economy, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(&c->cur_economy, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void FixPointers(CompanyProperties *c) const override
|
||||
{
|
||||
SlObject(&c->cur_economy, this->GetDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(CompanyProperties *c) const override { this->Load(c); }
|
||||
};
|
||||
|
||||
class SlCompanyOldEconomy : public SlCompanyEconomy {
|
||||
public:
|
||||
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->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _company_liveries_compat;
|
||||
|
||||
/**
|
||||
* Get the number of liveries used by this savegame version.
|
||||
* @return The number of liveries used by this savegame version.
|
||||
*/
|
||||
size_t GetNumLiveries() const
|
||||
{
|
||||
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 (size_t i = 0; i < num_liveries; i++) {
|
||||
SlObject(&c->livery[i], this->GetLoadDescription());
|
||||
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 {
|
||||
c->livery[i].in_use = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_85)) {
|
||||
/* We want to insert some liveries somewhere in between. This means some have to be moved. */
|
||||
memmove(&c->livery[LS_FREIGHT_WAGON], &c->livery[LS_PASSENGER_WAGON_MONORAIL], (LS_END - LS_FREIGHT_WAGON) * sizeof(c->livery[0]));
|
||||
c->livery[LS_PASSENGER_WAGON_MONORAIL] = c->livery[LS_MONORAIL];
|
||||
c->livery[LS_PASSENGER_WAGON_MAGLEV] = c->livery[LS_MAGLEV];
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_63)) {
|
||||
/* 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 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),
|
||||
SLE_CONDSSTR(CompanyProperties, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(CompanyProperties, president_name_1, SLE_STRINGID),
|
||||
SLE_VAR(CompanyProperties, president_name_2, SLE_UINT32),
|
||||
SLE_CONDSSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(CompanyProperties, face, SLE_UINT32),
|
||||
|
||||
/* money was changed to a 64 bit field in savegame version 1. */
|
||||
SLE_CONDVAR(CompanyProperties, money, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_1),
|
||||
SLE_CONDVAR(CompanyProperties, money, SLE_INT64, SLV_1, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, current_loan, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_65),
|
||||
SLE_CONDVAR(CompanyProperties, current_loan, SLE_INT64, SLV_65, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(CompanyProperties, colour, SLE_UINT8),
|
||||
SLE_VAR(CompanyProperties, money_fraction, SLE_UINT8),
|
||||
SLE_VAR(CompanyProperties, block_preview, SLE_UINT8),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, location_of_HQ, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
SLE_CONDVAR(CompanyProperties, location_of_HQ, SLE_UINT32, SLV_6, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, last_build_coordinate, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_6),
|
||||
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_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),
|
||||
SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_INT64, SLV_65, SL_MAX_VERSION),
|
||||
|
||||
/* yearly expenses was changed to 64-bit in savegame version 2. */
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, SL_MIN_VERSION, SLV_2),
|
||||
SLE_CONDARR(CompanyProperties, yearly_expenses, SLE_INT64, 3 * 13, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, is_ai, SLE_BOOL, SLV_2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(CompanyProperties, terraform_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, clear_limit, SLE_UINT32, SLV_156, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(CompanyProperties, tree_limit, SLE_UINT32, SLV_175, SL_MAX_VERSION),
|
||||
SLEG_STRUCT("settings", SlCompanySettings),
|
||||
SLEG_CONDSTRUCT("old_ai", SlCompanyOldAI, SL_MIN_VERSION, SLV_107),
|
||||
SLEG_STRUCT("cur_economy", SlCompanyEconomy),
|
||||
SLEG_STRUCTLIST("old_economy", SlCompanyOldEconomy),
|
||||
SLEG_CONDSTRUCTLIST("liveries", SlCompanyLiveries, SLV_34, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
struct PLYRChunkHandler : ChunkHandler {
|
||||
PLYRChunkHandler() : ChunkHandler('PLYR', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_company_desc);
|
||||
|
||||
for (Company *c : Company::Iterate()) {
|
||||
SlSetArrayIndex(c->index);
|
||||
SlObject(c, _company_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Company *c = new (index) Company();
|
||||
SetDefaultCompanySettings(c->index);
|
||||
SlObject((CompanyProperties *)c, slt);
|
||||
_company_colours[index] = (Colours)c->colour;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_company_desc, _company_sl_compat);
|
||||
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
CompanyProperties *cprops = new CompanyProperties();
|
||||
SlObject(cprops, slt);
|
||||
|
||||
/* We do not load old custom names */
|
||||
if (IsSavegameVersionBefore(SLV_84)) {
|
||||
if (GetStringTab(cprops->name_1) == TEXT_TAB_OLD_CUSTOM) {
|
||||
cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (GetStringTab(cprops->president_name_1) == TEXT_TAB_OLD_CUSTOM) {
|
||||
cprops->president_name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (cprops->name.empty() && !IsInsideMM(cprops->name_1, SPECSTR_COMPANY_NAME_START, SPECSTR_COMPANY_NAME_LAST + 1) &&
|
||||
cprops->name_1 != STR_GAME_SAVELOAD_NOT_AVAILABLE && cprops->name_1 != STR_SV_UNNAMED &&
|
||||
cprops->name_1 != SPECSTR_ANDCO_NAME && cprops->name_1 != SPECSTR_PRESIDENT_NAME &&
|
||||
cprops->name_1 != SPECSTR_SILLY_NAME) {
|
||||
cprops->name_1 = STR_GAME_SAVELOAD_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!_load_check_data.companies.Insert(index, cprops)) delete cprops;
|
||||
}
|
||||
}
|
||||
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (Company *c : Company::Iterate()) {
|
||||
SlObject((CompanyProperties *)c, _company_desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const PLYRChunkHandler PLYR;
|
||||
static const ChunkHandlerRef company_chunk_handlers[] = {
|
||||
PLYR,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _company_chunk_handlers(company_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file economy_sl.cpp Code handling saving and loading of economy data */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/economy_sl_compat.h"
|
||||
|
||||
#include "../../economy_func.h"
|
||||
#include "../../economy_base.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _economy_desc[] = {
|
||||
SLE_CONDVAR(Economy, old_max_loan_unround, SLE_FILE_I32 | SLE_VAR_I64, SL_MIN_VERSION, SLV_65),
|
||||
SLE_CONDVAR(Economy, old_max_loan_unround, SLE_INT64, SLV_65, SLV_126),
|
||||
SLE_CONDVAR(Economy, old_max_loan_unround_fract, SLE_UINT16, SLV_70, SLV_126),
|
||||
SLE_CONDVAR(Economy, inflation_prices, SLE_UINT64, SLV_126, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Economy, inflation_payment, SLE_UINT64, SLV_126, SL_MAX_VERSION),
|
||||
SLE_VAR(Economy, fluct, SLE_INT16),
|
||||
SLE_VAR(Economy, interest_rate, SLE_UINT8),
|
||||
SLE_VAR(Economy, infl_amount, SLE_UINT8),
|
||||
SLE_VAR(Economy, infl_amount_pr, SLE_UINT8),
|
||||
SLE_CONDVAR(Economy, industry_daily_change_counter, SLE_UINT32, SLV_102, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
/** Economy variables */
|
||||
struct ECMYChunkHandler : ChunkHandler {
|
||||
ECMYChunkHandler() : ChunkHandler('ECMY', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_economy_desc);
|
||||
|
||||
SlSetArrayIndex(0);
|
||||
SlObject(&_economy, _economy_desc);
|
||||
}
|
||||
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_economy_desc, _economy_sl_compat);
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return;
|
||||
SlObject(&_economy, slt);
|
||||
if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries");
|
||||
|
||||
StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102)); // old savegames will need to be initialized
|
||||
}
|
||||
};
|
||||
|
||||
static const SaveLoad _cargopayment_desc[] = {
|
||||
SLE_REF(CargoPayment, front, REF_VEHICLE),
|
||||
SLE_VAR(CargoPayment, route_profit, SLE_INT64),
|
||||
SLE_VAR(CargoPayment, visual_profit, SLE_INT64),
|
||||
SLE_CONDVAR(CargoPayment, visual_transfer, SLE_INT64, SLV_181, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
struct CAPYChunkHandler : ChunkHandler {
|
||||
CAPYChunkHandler() : ChunkHandler('CAPY', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_cargopayment_desc);
|
||||
|
||||
for (CargoPayment *cp : CargoPayment::Iterate()) {
|
||||
SlSetArrayIndex(cp->index);
|
||||
SlObject(cp, _cargopayment_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_cargopayment_desc, _cargopayment_sl_compat);
|
||||
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
CargoPayment *cp = new (index) CargoPayment();
|
||||
SlObject(cp, slt);
|
||||
}
|
||||
}
|
||||
|
||||
void FixPointers() const override
|
||||
{
|
||||
for (CargoPayment *cp : CargoPayment::Iterate()) {
|
||||
SlObject(cp, _cargopayment_desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const CAPYChunkHandler CAPY;
|
||||
static const ECMYChunkHandler ECMY;
|
||||
static const ChunkHandlerRef economy_chunk_handlers[] = {
|
||||
CAPY,
|
||||
ECMY,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _economy_chunk_handlers(economy_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file engine_sl.cpp Code handling saving and loading of engines */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/engine_sl_compat.h"
|
||||
|
||||
#include "../../engine_base.h"
|
||||
#include "../../string_func.h"
|
||||
#include <vector>
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
Engine *GetTempDataEngine(EngineID index);
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static const SaveLoad _engine_desc[] = {
|
||||
SLE_CONDVAR(Engine, intro_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLE_CONDVAR(Engine, intro_date, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, age, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
|
||||
SLE_CONDVAR(Engine, age, SLE_INT32, SLV_31, SL_MAX_VERSION),
|
||||
SLE_VAR(Engine, reliability, SLE_UINT16),
|
||||
SLE_VAR(Engine, reliability_spd_dec, SLE_UINT16),
|
||||
SLE_VAR(Engine, reliability_start, SLE_UINT16),
|
||||
SLE_VAR(Engine, reliability_max, SLE_UINT16),
|
||||
SLE_VAR(Engine, reliability_final, SLE_UINT16),
|
||||
SLE_VAR(Engine, duration_phase_1, SLE_UINT16),
|
||||
SLE_VAR(Engine, duration_phase_2, SLE_UINT16),
|
||||
SLE_VAR(Engine, duration_phase_3, SLE_UINT16),
|
||||
SLE_VAR(Engine, flags, SLE_UINT8),
|
||||
SLE_CONDVAR(Engine, preview_asked, SLE_UINT16, SLV_179, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, preview_company, SLE_UINT8, SLV_179, SL_MAX_VERSION),
|
||||
SLE_VAR(Engine, preview_wait, SLE_UINT8),
|
||||
SLE_CONDVAR(Engine, company_avail, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
|
||||
SLE_CONDVAR(Engine, company_avail, SLE_UINT16, SLV_104, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Engine, company_hidden, SLE_UINT16, SLV_193, SL_MAX_VERSION),
|
||||
SLE_CONDSTR(Engine, name, SLE_STR, 0, SLV_84, SL_MAX_VERSION),
|
||||
};
|
||||
|
||||
struct ENGNChunkHandler : ChunkHandler {
|
||||
ENGNChunkHandler() : ChunkHandler('ENGN', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_engine_desc);
|
||||
|
||||
for (Engine *e : Engine::Iterate()) {
|
||||
SlSetArrayIndex(e->index);
|
||||
SlObject(e, _engine_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_desc, _engine_sl_compat);
|
||||
|
||||
/* As engine data is loaded before engines are initialized we need to load
|
||||
* this information into a temporary array. This is then copied into the
|
||||
* engine pool after processing NewGRFs by CopyTempEngineData(). */
|
||||
int index;
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
Engine *e = GetTempDataEngine(index);
|
||||
SlObject(e, slt);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_179)) {
|
||||
/* preview_company_rank was replaced with preview_company and preview_asked.
|
||||
* Just cancel any previews. */
|
||||
e->flags &= ~4; // ENGINE_OFFER_WINDOW_OPEN
|
||||
e->preview_company = INVALID_COMPANY;
|
||||
e->preview_asked = MAX_UVALUE(CompanyMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Save and load the mapping between the engine id in the pool, and the grf file it came from. */
|
||||
static const SaveLoad _engine_id_mapping_desc[] = {
|
||||
SLE_VAR(EngineIDMapping, grfid, SLE_UINT32),
|
||||
SLE_VAR(EngineIDMapping, internal_id, SLE_UINT16),
|
||||
SLE_VAR(EngineIDMapping, type, SLE_UINT8),
|
||||
SLE_VAR(EngineIDMapping, substitute_id, SLE_UINT8),
|
||||
};
|
||||
|
||||
struct EIDSChunkHandler : ChunkHandler {
|
||||
EIDSChunkHandler() : ChunkHandler('EIDS', CH_TABLE) {}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_engine_id_mapping_desc);
|
||||
|
||||
uint index = 0;
|
||||
for (EngineIDMapping &eid : _engine_mngr) {
|
||||
SlSetArrayIndex(index);
|
||||
SlObject(&eid, _engine_id_mapping_desc);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_engine_id_mapping_desc, _engine_id_mapping_sl_compat);
|
||||
|
||||
_engine_mngr.clear();
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
EngineIDMapping *eid = &_engine_mngr.emplace_back();
|
||||
SlObject(eid, slt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const EIDSChunkHandler EIDS;
|
||||
static const ENGNChunkHandler ENGN;
|
||||
static const ChunkHandlerRef engine_chunk_handlers[] = {
|
||||
EIDS,
|
||||
ENGN,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _engine_chunk_handlers(engine_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file game_sl.cpp Handles the saveload part of the GameScripts */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/game_sl_compat.h"
|
||||
|
||||
#include "../../string_func.h"
|
||||
#include "../../game/game.hpp"
|
||||
#include "../../game/game_config.hpp"
|
||||
#include "../../network/network.h"
|
||||
#include "../../game/game_instance.hpp"
|
||||
#include "../../game/game_text.hpp"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
extern GameStrings *_current_data;
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
static std::string _game_saveload_name;
|
||||
static int _game_saveload_version;
|
||||
static std::string _game_saveload_settings;
|
||||
static bool _game_saveload_is_random;
|
||||
|
||||
static const SaveLoad _game_script_desc[] = {
|
||||
SLEG_SSTR("name", _game_saveload_name, SLE_STR),
|
||||
SLEG_SSTR("settings", _game_saveload_settings, SLE_STR),
|
||||
SLEG_VAR("version", _game_saveload_version, SLE_UINT32),
|
||||
SLEG_VAR("is_random", _game_saveload_is_random, SLE_BOOL),
|
||||
};
|
||||
|
||||
static void SaveReal_GSDT(int *index_ptr)
|
||||
{
|
||||
GameConfig *config = GameConfig::GetConfig();
|
||||
|
||||
if (config->HasScript()) {
|
||||
_game_saveload_name = config->GetName();
|
||||
_game_saveload_version = config->GetVersion();
|
||||
} else {
|
||||
/* No GameScript is configured for this so store an empty string as name. */
|
||||
_game_saveload_name.clear();
|
||||
_game_saveload_version = -1;
|
||||
}
|
||||
|
||||
_game_saveload_is_random = config->IsRandom();
|
||||
_game_saveload_settings = config->SettingsToString();
|
||||
|
||||
SlObject(nullptr, _game_script_desc);
|
||||
Game::Save();
|
||||
}
|
||||
|
||||
struct GSDTChunkHandler : ChunkHandler {
|
||||
GSDTChunkHandler() : ChunkHandler('GSDT', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_script_desc, _game_script_sl_compat);
|
||||
|
||||
/* Free all current data */
|
||||
GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME)->Change(nullptr);
|
||||
|
||||
if (SlIterateArray() == -1) return;
|
||||
|
||||
_game_saveload_version = -1;
|
||||
SlObject(nullptr, slt);
|
||||
|
||||
if (_game_mode == GM_MENU || (_networking && !_network_server)) {
|
||||
GameInstance::LoadEmpty();
|
||||
if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
|
||||
return;
|
||||
}
|
||||
|
||||
GameConfig *config = GameConfig::GetConfig(GameConfig::SSS_FORCE_GAME);
|
||||
if (!_game_saveload_name.empty()) {
|
||||
config->Change(_game_saveload_name.c_str(), _game_saveload_version, false, _game_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
/* No version of the GameScript available that can load the data. Try to load the
|
||||
* latest version of the GameScript instead. */
|
||||
config->Change(_game_saveload_name.c_str(), -1, false, _game_saveload_is_random);
|
||||
if (!config->HasScript()) {
|
||||
if (_game_saveload_name.compare("%_dummy") != 0) {
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %u which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version);
|
||||
DEBUG(script, 0, "This game will continue to run without GameScript.");
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame had no GameScript available at the time of saving.");
|
||||
DEBUG(script, 0, "This game will continue to run without GameScript.");
|
||||
}
|
||||
} else {
|
||||
DEBUG(script, 0, "The savegame has an GameScript by the name '%s', version %u which is no longer available.", _game_saveload_name.c_str(), _game_saveload_version);
|
||||
DEBUG(script, 0, "The latest version of that GameScript has been loaded instead, but it'll not get the savegame data as it's incompatible.");
|
||||
}
|
||||
/* Make sure the GameScript doesn't get the saveload data, as it was not the
|
||||
* writer of the saveload data in the first place */
|
||||
_game_saveload_version = -1;
|
||||
}
|
||||
}
|
||||
|
||||
config->StringToSettings(_game_saveload_settings);
|
||||
|
||||
/* Load the GameScript saved data */
|
||||
config->SetToLoadData(GameInstance::Load(_game_saveload_version));
|
||||
|
||||
if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs");
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_game_script_desc);
|
||||
SlSetArrayIndex(0);
|
||||
SlAutolength((AutolengthProc *)SaveReal_GSDT, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
static std::string _game_saveload_string;
|
||||
static uint32 _game_saveload_strings;
|
||||
|
||||
class SlGameLanguageString : public DefaultSaveLoadHandler<SlGameLanguageString, LanguageStrings> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_SSTR("string", _game_saveload_string, SLE_STR | SLF_ALLOW_CONTROL),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _game_language_string_sl_compat;
|
||||
|
||||
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
|
||||
{
|
||||
uint32 length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _game_saveload_strings : (uint32)SlGetStructListLength(UINT32_MAX);
|
||||
|
||||
for (uint32 i = 0; i < length; i++) {
|
||||
SlObject(nullptr, this->GetLoadDescription());
|
||||
ls->lines.emplace_back(_game_saveload_string);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const SaveLoad _game_language_desc[] = {
|
||||
SLE_SSTR(LanguageStrings, language, SLE_STR),
|
||||
SLEG_CONDVAR("count", _game_saveload_strings, SLE_UINT32, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
|
||||
SLEG_STRUCTLIST("strings", SlGameLanguageString),
|
||||
};
|
||||
|
||||
struct GSTRChunkHandler : ChunkHandler {
|
||||
GSTRChunkHandler() : ChunkHandler('GSTR', CH_TABLE) {}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_game_language_desc, _game_language_sl_compat);
|
||||
|
||||
delete _current_data;
|
||||
_current_data = new GameStrings();
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
LanguageStrings ls;
|
||||
SlObject(&ls, slt);
|
||||
_current_data->raw_strings.push_back(std::move(ls));
|
||||
}
|
||||
|
||||
/* If there were no strings in the savegame, set GameStrings to nullptr */
|
||||
if (_current_data->raw_strings.size() == 0) {
|
||||
delete _current_data;
|
||||
_current_data = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
_current_data->Compile();
|
||||
ReconsiderGameScriptLanguage();
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_game_language_desc);
|
||||
|
||||
if (_current_data == nullptr) return;
|
||||
|
||||
for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(&_current_data->raw_strings[i], _game_language_desc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const GSTRChunkHandler GSTR;
|
||||
static const GSDTChunkHandler GSDT;
|
||||
static const ChunkHandlerRef game_chunk_handlers[] = {
|
||||
GSTR,
|
||||
GSDT,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _game_chunk_handlers(game_chunk_handlers);
|
||||
|
||||
}
|
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file gamelog_sl.cpp Code handling saving and loading of gamelog data */
|
||||
|
||||
#include "../../stdafx.h"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "compat/gamelog_sl_compat.h"
|
||||
|
||||
#include "../../gamelog_internal.h"
|
||||
#include "../../fios.h"
|
||||
#include "../../string_func.h"
|
||||
|
||||
#include "../../safeguards.h"
|
||||
|
||||
namespace upstream_sl {
|
||||
|
||||
class SlGamelogMode : public DefaultSaveLoadHandler<SlGamelogMode, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, mode.mode, SLE_UINT8),
|
||||
SLE_VAR(LoggedChange, mode.landscape, SLE_UINT8),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_mode_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_MODE) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_MODE) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static char old_revision_text[GAMELOG_REVISION_LENGTH];
|
||||
static std::string revision_test;
|
||||
|
||||
class SlGamelogRevision : public DefaultSaveLoadHandler<SlGamelogRevision, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_CONDARR("revision.text", old_revision_text, SLE_UINT8, GAMELOG_REVISION_LENGTH, SL_MIN_VERSION, SLV_STRING_GAMELOG),
|
||||
SLEG_CONDSSTR("revision.text", revision_test, SLE_STR, SLV_STRING_GAMELOG, SL_MAX_VERSION),
|
||||
SLE_VAR(LoggedChange, revision.newgrf, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, revision.slver, SLE_UINT16),
|
||||
SLE_VAR(LoggedChange, revision.modified, SLE_UINT8),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_revision_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_REVISION) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_REVISION) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
if (IsSavegameVersionBefore(SLV_STRING_GAMELOG)) {
|
||||
lc->revision.text = stredup(old_revision_text, lastof(old_revision_text));
|
||||
} else {
|
||||
lc->revision.text = stredup(revision_test.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogOldver : public DefaultSaveLoadHandler<SlGamelogOldver, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, oldver.type, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, oldver.version, SLE_UINT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_oldver_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_OLDVER) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_OLDVER) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogSetting : public DefaultSaveLoadHandler<SlGamelogSetting, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_STR(LoggedChange, setting.name, SLE_STR, 128),
|
||||
SLE_VAR(LoggedChange, setting.oldval, SLE_INT32),
|
||||
SLE_VAR(LoggedChange, setting.newval, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_setting_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_SETTING) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_SETTING) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogGrfadd : public DefaultSaveLoadHandler<SlGamelogGrfadd, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfadd.grfid, SLE_UINT32 ),
|
||||
SLE_ARR(LoggedChange, grfadd.md5sum, SLE_UINT8, 16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfadd_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFADD) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFADD) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogGrfrem : public DefaultSaveLoadHandler<SlGamelogGrfrem, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfrem.grfid, SLE_UINT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfrem_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFREM) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFREM) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogGrfcompat : public DefaultSaveLoadHandler<SlGamelogGrfcompat, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfcompat.grfid, SLE_UINT32 ),
|
||||
SLE_ARR(LoggedChange, grfcompat.md5sum, SLE_UINT8, 16),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfcompat_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFCOMPAT) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFCOMPAT) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogGrfparam : public DefaultSaveLoadHandler<SlGamelogGrfparam, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfparam.grfid, SLE_UINT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfparam_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFPARAM) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFPARAM) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogGrfmove : public DefaultSaveLoadHandler<SlGamelogGrfmove, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfmove.grfid, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, grfmove.offset, SLE_INT32),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfmove_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFMOVE) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFMOVE) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogGrfbug : public DefaultSaveLoadHandler<SlGamelogGrfbug, LoggedChange> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_VAR(LoggedChange, grfbug.data, SLE_UINT64),
|
||||
SLE_VAR(LoggedChange, grfbug.grfid, SLE_UINT32),
|
||||
SLE_VAR(LoggedChange, grfbug.bug, SLE_UINT8),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_grfbug_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFBUG) return;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_GRFBUG) return;
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
static bool _is_emergency_save = true;
|
||||
|
||||
class SlGamelogEmergency : public DefaultSaveLoadHandler<SlGamelogEmergency, LoggedChange> {
|
||||
public:
|
||||
/* We need to store something, so store a "true" value. */
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_CONDVAR("is_emergency_save", _is_emergency_save, SLE_BOOL, SLV_RIFF_TO_ARRAY, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_emergency_sl_compat;
|
||||
|
||||
void Save(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_EMERGENCY) return;
|
||||
|
||||
_is_emergency_save = true;
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
|
||||
void Load(LoggedChange *lc) const override
|
||||
{
|
||||
if (lc->ct != GLCT_EMERGENCY) return;
|
||||
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedChange *lc) const override { this->Load(lc); }
|
||||
};
|
||||
|
||||
class SlGamelogAction : public DefaultSaveLoadHandler<SlGamelogAction, LoggedAction> {
|
||||
public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLE_SAVEBYTE(LoggedChange, ct),
|
||||
SLEG_STRUCT("mode", SlGamelogMode),
|
||||
SLEG_STRUCT("revision", SlGamelogRevision),
|
||||
SLEG_STRUCT("oldver", SlGamelogOldver),
|
||||
SLEG_STRUCT("setting", SlGamelogSetting),
|
||||
SLEG_STRUCT("grfadd", SlGamelogGrfadd),
|
||||
SLEG_STRUCT("grfrem", SlGamelogGrfrem),
|
||||
SLEG_STRUCT("grfcompat", SlGamelogGrfcompat),
|
||||
SLEG_STRUCT("grfparam", SlGamelogGrfparam),
|
||||
SLEG_STRUCT("grfmove", SlGamelogGrfmove),
|
||||
SLEG_STRUCT("grfbug", SlGamelogGrfbug),
|
||||
SLEG_STRUCT("emergency", SlGamelogEmergency),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _gamelog_action_sl_compat;
|
||||
|
||||
void Save(LoggedAction *la) const override
|
||||
{
|
||||
SlSetStructListLength(la->changes);
|
||||
|
||||
const LoggedChange *lcend = &la->change[la->changes];
|
||||
for (LoggedChange *lc = la->change; lc != lcend; lc++) {
|
||||
assert((uint)lc->ct < GLCT_END);
|
||||
SlObject(lc, this->GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load(LoggedAction *la) const override
|
||||
{
|
||||
if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
|
||||
byte type;
|
||||
while ((type = SlReadByte()) != GLCT_NONE) {
|
||||
if (type >= GLCT_END) SlErrorCorrupt("Invalid gamelog change type");
|
||||
GamelogChangeType ct = (GamelogChangeType)type;
|
||||
|
||||
la->change = ReallocT(la->change, la->changes + 1);
|
||||
|
||||
LoggedChange *lc = &la->change[la->changes++];
|
||||
memset(lc, 0, sizeof(*lc));
|
||||
lc->ct = ct;
|
||||
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t length = SlGetStructListLength(UINT32_MAX);
|
||||
la->change = ReallocT(la->change, length);
|
||||
la->changes = (uint32)length;
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
LoggedChange *lc = &la->change[i];
|
||||
memset(lc, 0, sizeof(*lc));
|
||||
|
||||
lc->ct = (GamelogChangeType)SlReadByte();
|
||||
SlObject(lc, this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheck(LoggedAction *la) const override { this->Load(la); }
|
||||
};
|
||||
|
||||
static const SaveLoad _gamelog_desc[] = {
|
||||
SLE_CONDVAR(LoggedAction, at, SLE_UINT8, SLV_RIFF_TO_ARRAY, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(LoggedAction, tick, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER),
|
||||
SLE_CONDVAR(LoggedAction, tick, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
|
||||
SLEG_STRUCTLIST("action", SlGamelogAction),
|
||||
};
|
||||
|
||||
struct GLOGChunkHandler : ChunkHandler {
|
||||
GLOGChunkHandler() : ChunkHandler('GLOG', CH_TABLE) {}
|
||||
|
||||
void LoadCommon(LoggedAction *&gamelog_action, uint &gamelog_actions) const
|
||||
{
|
||||
assert(gamelog_action == nullptr);
|
||||
assert(gamelog_actions == 0);
|
||||
|
||||
const std::vector<SaveLoad> slt = SlCompatTableHeader(_gamelog_desc, _gamelog_sl_compat);
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) {
|
||||
byte type;
|
||||
while ((type = SlReadByte()) != GLAT_NONE) {
|
||||
if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type");
|
||||
|
||||
gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
|
||||
LoggedAction *la = &gamelog_action[gamelog_actions++];
|
||||
memset(la, 0, sizeof(*la));
|
||||
|
||||
la->at = (GamelogActionType)type;
|
||||
SlObject(la, slt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (SlIterateArray() != -1) {
|
||||
gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1);
|
||||
LoggedAction *la = &gamelog_action[gamelog_actions++];
|
||||
memset(la, 0, sizeof(*la));
|
||||
|
||||
SlObject(la, slt);
|
||||
}
|
||||
}
|
||||
|
||||
void Save() const override
|
||||
{
|
||||
SlTableHeader(_gamelog_desc);
|
||||
|
||||
const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
|
||||
|
||||
uint i = 0;
|
||||
for (LoggedAction *la = _gamelog_action; la != laend; la++, i++) {
|
||||
SlSetArrayIndex(i);
|
||||
SlObject(la, _gamelog_desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Load() const override
|
||||
{
|
||||
this->LoadCommon(_gamelog_action, _gamelog_actions);
|
||||
}
|
||||
|
||||
void LoadCheck(size_t) const override
|
||||
{
|
||||
this->LoadCommon(_load_check_data.gamelog_action, _load_check_data.gamelog_actions);
|
||||
}
|
||||
};
|
||||
|
||||
static const GLOGChunkHandler GLOG;
|
||||
static const ChunkHandlerRef gamelog_chunk_handlers[] = {
|
||||
GLOG,
|
||||
};
|
||||
|
||||
extern const ChunkHandlerTable _gamelog_chunk_handlers(gamelog_chunk_handlers);
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user