Merge branch 'cpp-11' into save_ext

# Conflicts:
#	src/saveload/saveload.cpp
#	src/settings.cpp
#	src/settings_gui.cpp
This commit is contained in:
Jonathan G Rennison
2019-04-09 18:54:02 +01:00
553 changed files with 11523 additions and 11311 deletions

View File

@@ -19,6 +19,7 @@
#include "../network/network_func.h"
#include "../gfxinit.h"
#include "../viewport_func.h"
#include "../viewport_kdtree.h"
#include "../industry.h"
#include "../clear_map.h"
#include "../vehicle_func.h"
@@ -221,6 +222,7 @@ void UpdateAllVirtCoords()
UpdateAllStationVirtCoords();
UpdateAllSignVirtCoords();
UpdateAllTownVirtCoords();
RebuildViewportKdtree();
}
/**
@@ -285,7 +287,6 @@ static void InitializeWindowsAndCaches()
GroupStatistics::UpdateAfterLoad();
Station::RecomputeIndustriesNearForAll();
RebuildSubsidisedSourceAndDestinationCache();
/* Towns have a noise controlled number of airports system
@@ -537,6 +538,12 @@ bool AfterLoadGame()
GamelogTestRevision();
GamelogTestMode();
RebuildTownKdtree();
RebuildStationKdtree();
/* This needs to be done even before conversion, because some conversions will destroy objects
* that otherwise won't exist in the tree. */
RebuildViewportKdtree();
if (IsSavegameVersionBefore(SLV_98)) GamelogGRFAddList(_grfconfig);
if (IsSavegameVersionBefore(SLV_119)) {
@@ -1868,7 +1875,7 @@ bool AfterLoadGame()
if (_settings_game.pf.yapf.ship_use_yapf) {
_settings_game.pf.pathfinder_for_ships = VPF_YAPF;
} else {
_settings_game.pf.pathfinder_for_ships = (_settings_game.pf.new_pathfinding_all ? VPF_NPF : VPF_OPF);
_settings_game.pf.pathfinder_for_ships = VPF_NPF;
}
}
@@ -2188,14 +2195,14 @@ bool AfterLoadGame()
/* Animated tiles would sometimes not be actually animated or
* in case of old savegames duplicate. */
extern SmallVector<TileIndex, 256> _animated_tiles;
extern std::vector<TileIndex> _animated_tiles;
for (TileIndex *tile = _animated_tiles.Begin(); tile < _animated_tiles.End(); /* Nothing */) {
for (auto tile = _animated_tiles.begin(); tile < _animated_tiles.end(); /* Nothing */) {
/* Remove if tile is not animated */
bool remove = _tile_type_procs[GetTileType(*tile)]->animate_tile_proc == NULL;
/* and remove if duplicate */
for (TileIndex *j = _animated_tiles.Begin(); !remove && j < tile; j++) {
for (auto j = _animated_tiles.begin(); !remove && j < tile; j++) {
remove = *tile == *j;
}
@@ -2932,10 +2939,10 @@ bool AfterLoadGame()
* So, make articulated parts catch up. */
RoadVehicle *v;
bool roadside = _settings_game.vehicle.road_side == 1;
SmallVector<uint, 16> skip_frames;
std::vector<uint> skip_frames;
FOR_ALL_ROADVEHICLES(v) {
if (!v->IsFrontEngine()) continue;
skip_frames.Clear();
skip_frames.clear();
TileIndex prev_tile = v->tile;
uint prev_tile_skip = 0;
uint cur_skip = 0;
@@ -2947,24 +2954,24 @@ bool AfterLoadGame()
cur_skip = prev_tile_skip;
}
uint *this_skip = skip_frames.Append();
*this_skip = prev_tile_skip;
/*C++17: uint &this_skip = */ skip_frames.push_back(prev_tile_skip);
uint &this_skip = skip_frames.back();
/* The following 3 curves now take longer than before */
switch (u->state) {
case 2:
cur_skip++;
if (u->frame <= (roadside ? 9 : 5)) *this_skip = cur_skip;
if (u->frame <= (roadside ? 9 : 5)) this_skip = cur_skip;
break;
case 4:
cur_skip++;
if (u->frame <= (roadside ? 5 : 9)) *this_skip = cur_skip;
if (u->frame <= (roadside ? 5 : 9)) this_skip = cur_skip;
break;
case 5:
cur_skip++;
if (u->frame <= (roadside ? 4 : 2)) *this_skip = cur_skip;
if (u->frame <= (roadside ? 4 : 2)) this_skip = cur_skip;
break;
default:
@@ -2974,9 +2981,12 @@ bool AfterLoadGame()
while (cur_skip > skip_frames[0]) {
RoadVehicle *u = v;
RoadVehicle *prev = NULL;
for (uint *it = skip_frames.Begin(); it != skip_frames.End(); ++it, prev = u, u = u->Next()) {
for (uint sf : skip_frames) {
extern bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev);
if (*it >= cur_skip) IndividualRoadVehicleController(u, prev);
if (sf >= cur_skip) IndividualRoadVehicleController(u, prev);
prev = u;
u = u->Next();
}
cur_skip--;
}
@@ -3080,6 +3090,40 @@ bool AfterLoadGame()
}
}
if (IsSavegameVersionBefore(SLV_TOWN_CARGOGEN)) {
/* Ensure the original cargo generation mode is used */
_settings_game.economy.town_cargogen_mode = TCGM_ORIGINAL;
}
if (IsSavegameVersionBefore(SLV_SERVE_NEUTRAL_INDUSTRIES)) {
/* Ensure the original neutral industry/station behaviour is used */
_settings_game.station.serve_neutral_industries = true;
/* Link oil rigs to their industry and back. */
Station *st;
FOR_ALL_STATIONS(st) {
if (IsTileType(st->xy, MP_STATION) && IsOilRig(st->xy)) {
/* Industry tile is always adjacent during construction by TileDiffXY(0, 1) */
st->industry = Industry::GetByTile(st->xy + TileDiffXY(0, 1));
st->industry->neutral_station = st;
}
}
} else {
/* Link neutral station back to industry, as this is not saved. */
Industry *ind;
FOR_ALL_INDUSTRIES(ind) if (ind->neutral_station != NULL) ind->neutral_station->industry = ind;
}
if (IsSavegameVersionBefore(SLV_TREES_WATER_CLASS)) {
/* Update water class for trees. */
for (TileIndex t = 0; t < map_size; t++) {
if (IsTileType(t, MP_TREES)) SetWaterClass(t, GetTreeGround(t) == TREE_GROUND_SHORE ? WATER_CLASS_SEA : WATER_CLASS_INVALID);
}
}
/* Compute station catchment areas. This is needed here in case UpdateStationAcceptance is called below. */
Station::RecomputeCatchmentForAll();
/* Station acceptance is some kind of cache */
if (IsSavegameVersionBefore(SLV_127)) {
Station *st;

View File

@@ -18,15 +18,15 @@
#include "../safeguards.h"
extern SmallVector<TileIndex, 256> _animated_tiles;
extern std::vector<TileIndex> _animated_tiles;
/**
* Save the ANIT chunk.
*/
static void Save_ANIT()
{
SlSetLength(_animated_tiles.Length() * sizeof(*_animated_tiles.Begin()));
SlArray(_animated_tiles.Begin(), _animated_tiles.Length(), SLE_UINT32);
SlSetLength(_animated_tiles.size() * sizeof(_animated_tiles.front()));
SlArray(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32);
}
/**
@@ -42,15 +42,15 @@ static void Load_ANIT()
for (int i = 0; i < 256; i++) {
if (anim_list[i] == 0) break;
*_animated_tiles.Append() = anim_list[i];
_animated_tiles.push_back(anim_list[i]);
}
return;
}
uint count = (uint)SlGetFieldLength() / sizeof(*_animated_tiles.Begin());
_animated_tiles.Clear();
_animated_tiles.Append(count);
SlArray(_animated_tiles.Begin(), count, SLE_UINT32);
uint count = (uint)SlGetFieldLength() / sizeof(_animated_tiles.front());
_animated_tiles.clear();
_animated_tiles.resize(_animated_tiles.size() + count);
SlArray(_animated_tiles.data(), count, SLE_UINT32);
}
/**

View File

@@ -177,20 +177,21 @@ static const SaveLoad _engine_id_mapping_desc[] = {
static void Save_EIDS()
{
const EngineIDMapping *end = _engine_mngr.End();
uint index = 0;
for (EngineIDMapping *eid = _engine_mngr.Begin(); eid != end; eid++, index++) {
for (EngineIDMapping &eid : _engine_mngr) {
SlSetArrayIndex(index);
SlObject(eid, _engine_id_mapping_desc);
SlObject(&eid, _engine_id_mapping_desc);
index++;
}
}
static void Load_EIDS()
{
_engine_mngr.Clear();
_engine_mngr.clear();
while (SlIterateArray() != -1) {
EngineIDMapping *eid = _engine_mngr.Append();
/*C++17: EngineIDMapping *eid = &*/ _engine_mngr.emplace_back();
EngineIDMapping *eid = &_engine_mngr.back();
SlObject(eid, _engine_id_mapping_desc);
}
}

View File

@@ -132,7 +132,7 @@ static const SaveLoad _game_language_string[] = {
static void SaveReal_GSTR(LanguageStrings *ls)
{
_game_saveload_string = ls->language;
_game_saveload_strings = ls->lines.Length();
_game_saveload_strings = (uint)ls->lines.size();
SlObject(NULL, _game_language_header);
for (uint i = 0; i < _game_saveload_strings; i++) {
@@ -153,14 +153,14 @@ static void Load_GSTR()
LanguageStrings *ls = new LanguageStrings(_game_saveload_string != NULL ? _game_saveload_string : "");
for (uint i = 0; i < _game_saveload_strings; i++) {
SlObject(NULL, _game_language_string);
*ls->lines.Append() = stredup(_game_saveload_string != NULL ? _game_saveload_string : "");
ls->lines.push_back(stredup(_game_saveload_string != NULL ? _game_saveload_string : ""));
}
*_current_data->raw_strings.Append() = ls;
_current_data->raw_strings.push_back(ls);
}
/* If there were no strings in the savegame, set GameStrings to NULL */
if (_current_data->raw_strings.Length() == 0) {
if (_current_data->raw_strings.size() == 0) {
delete _current_data;
_current_data = NULL;
return;
@@ -174,7 +174,7 @@ static void Save_GSTR()
{
if (_current_data == NULL) return;
for (uint i = 0; i < _current_data->raw_strings.Length(); i++) {
for (uint i = 0; i < _current_data->raw_strings.size(); i++) {
SlSetArrayIndex(i);
SlAutolength((AutolengthProc *)SaveReal_GSTR, _current_data->raw_strings[i]);
}

View File

@@ -25,6 +25,7 @@ static const SaveLoad _industry_desc[] = {
SLE_VAR(Industry, location.w, SLE_FILE_U8 | SLE_VAR_U16),
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),

View File

@@ -17,7 +17,7 @@
#include "../safeguards.h"
static SmallVector<RailTypeLabel, RAILTYPE_END> _railtype_list;
static std::vector<RailTypeLabel> _railtype_list;
/**
* Test if any saved rail type labels are different to the currently loaded
@@ -26,7 +26,7 @@ static SmallVector<RailTypeLabel, RAILTYPE_END> _railtype_list;
*/
static bool NeedRailTypeConversion()
{
for (uint i = 0; i < _railtype_list.Length(); i++) {
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;
@@ -42,13 +42,13 @@ static bool NeedRailTypeConversion()
void AfterLoadLabelMaps()
{
if (NeedRailTypeConversion()) {
SmallVector<RailType, RAILTYPE_END> railtype_conversion_map;
std::vector<RailType> railtype_conversion_map;
for (uint i = 0; i < _railtype_list.Length(); i++) {
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.Append() = r;
railtype_conversion_map.push_back(r);
}
for (TileIndex t = 0; t < MapSize(); t++) {
@@ -81,7 +81,7 @@ void AfterLoadLabelMaps()
}
}
_railtype_list.Clear();
_railtype_list.clear();
}
/** Container for a label for SaveLoad system */
@@ -108,13 +108,13 @@ static void Save_RAIL()
static void Load_RAIL()
{
_railtype_list.Clear();
_railtype_list.clear();
LabelObject lo;
while (SlIterateArray() != -1) {
SlObject(&lo, _label_object_desc);
*_railtype_list.Append() = (RailTypeLabel)lo.label;
_railtype_list.push_back((RailTypeLabel)lo.label);
}
}

View File

@@ -51,11 +51,11 @@ const SaveLoad *GetLinkGraphDesc()
*/
const SaveLoad *GetLinkGraphJobDesc()
{
static SmallVector<SaveLoad, 16> saveloads;
static std::vector<SaveLoad> saveloads;
static const char *prefix = "linkgraph.";
/* Build the SaveLoad array on first call and don't touch it later on */
if (saveloads.Length() == 0) {
if (saveloads.size() == 0) {
size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
@@ -69,7 +69,7 @@ const SaveLoad *GetLinkGraphJobDesc()
char *&address = reinterpret_cast<char *&>(sl.address);
address -= offset_gamesettings;
address += offset_component;
*(saveloads.Append()) = sl;
saveloads.push_back(sl);
}
desc = GetSettingDescription(++setting);
}
@@ -82,8 +82,8 @@ const SaveLoad *GetLinkGraphJobDesc()
int i = 0;
do {
*(saveloads.Append()) = job_desc[i++];
} while (saveloads[saveloads.Length() - 1].cmd != SL_END);
saveloads.push_back(job_desc[i++]);
} while (saveloads[saveloads.size() - 1].cmd != SL_END);
}
return &saveloads[0];

View File

@@ -491,7 +491,7 @@ static inline uint RemapOrderIndex(uint x)
return _savegame_type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2;
}
extern SmallVector<TileIndex, 256> _animated_tiles;
extern std::vector<TileIndex> _animated_tiles;
extern char *_old_name_array;
static uint32 _old_town_index;
@@ -651,7 +651,7 @@ static bool LoadOldAnimTileList(LoadgameState *ls, int num)
/* The first zero in the loaded array indicates the end of the list. */
for (int i = 0; i < 256; i++) {
if (anim_list[i] == 0) break;
*_animated_tiles.Append() = anim_list[i];
_animated_tiles.push_back(anim_list[i]);
}
return true;

View File

@@ -25,7 +25,7 @@
#include "../stdafx.h"
#include "../debug.h"
#include "../station_base.h"
#include "../thread/thread.h"
#include "../thread.h"
#include "../town.h"
#include "../network/network.h"
#include "../window_func.h"
@@ -45,6 +45,7 @@
#include "../string_func_extra.h"
#include "../fios.h"
#include "../error.h"
#include <atomic>
#include "table/strings.h"
@@ -410,9 +411,9 @@ void NORETURN CDECL SlErrorCorruptFmt(const char *format, ...)
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_SAVEGAME, str, true);
}
typedef void (*AsyncSaveFinishProc)(); ///< Callback for when the savegame loading is finished.
static AsyncSaveFinishProc _async_save_finish = NULL; ///< Callback to call when the savegame loading is finished.
static ThreadObject *_save_thread; ///< The thread we're using to compress and write a savegame
typedef void (*AsyncSaveFinishProc)(); ///< Callback for when the savegame loading is finished.
static std::atomic<AsyncSaveFinishProc> _async_save_finish; ///< Callback to call when the savegame loading is finished.
static std::thread _save_thread; ///< The thread we're using to compress and write a savegame
/**
* Called by save thread to tell we finished saving.
@@ -421,9 +422,9 @@ static ThreadObject *_save_thread; ///< The thread we're usin
static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
{
if (_exit_game) return;
while (_async_save_finish != NULL) CSleep(10);
while (_async_save_finish.load(std::memory_order_acquire) != NULL) CSleep(10);
_async_save_finish = proc;
_async_save_finish.store(proc, std::memory_order_release);
}
/**
@@ -431,16 +432,13 @@ static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
*/
void ProcessAsyncSaveFinish()
{
if (_async_save_finish == NULL) return;
AsyncSaveFinishProc proc = _async_save_finish.exchange(NULL, std::memory_order_acq_rel);
if (proc == NULL) return;
_async_save_finish();
proc();
_async_save_finish = NULL;
if (_save_thread != NULL) {
_save_thread->Join();
delete _save_thread;
_save_thread = NULL;
if (_save_thread.joinable()) {
_save_thread.join();
}
}
@@ -2077,7 +2075,7 @@ struct FileReader : LoadFilter {
_sl.sf = NULL;
}
/* virtual */ size_t Read(byte *buf, size_t size)
size_t Read(byte *buf, size_t size) override
{
/* We're in the process of shutting down, i.e. in "failure" mode. */
if (this->file == NULL) return 0;
@@ -2085,7 +2083,7 @@ struct FileReader : LoadFilter {
return fread(buf, 1, size, this->file);
}
/* virtual */ void Reset()
void Reset() override
{
clearerr(this->file);
if (fseek(this->file, this->begin, SEEK_SET)) {
@@ -2115,7 +2113,7 @@ struct FileWriter : SaveFilter {
_sl.sf = NULL;
}
/* virtual */ void Write(byte *buf, size_t size)
void Write(byte *buf, size_t size) override
{
/* We're in the process of shutting down, i.e. in "failure" mode. */
if (this->file == NULL) return;
@@ -2123,7 +2121,7 @@ struct FileWriter : SaveFilter {
if (fwrite(buf, 1, size, this->file) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
}
/* virtual */ void Finish()
void Finish() override
{
if (this->file != NULL) fclose(this->file);
this->file = NULL;
@@ -2151,7 +2149,7 @@ struct LZOLoadFilter : LoadFilter {
if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
}
/* virtual */ size_t Read(byte *buf, size_t ssize)
size_t Read(byte *buf, size_t ssize) override
{
assert(ssize >= LZO_BUFFER_SIZE);
@@ -2199,7 +2197,7 @@ struct LZOSaveFilter : SaveFilter {
if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
}
/* virtual */ void Write(byte *buf, size_t size)
void Write(byte *buf, size_t size) override
{
const lzo_bytep in = buf;
/* Buffer size is from the LZO docs plus the chunk header size. */
@@ -2238,7 +2236,7 @@ struct NoCompLoadFilter : LoadFilter {
{
}
/* virtual */ size_t Read(byte *buf, size_t size)
size_t Read(byte *buf, size_t size) override
{
return this->chain->Read(buf, size);
}
@@ -2255,7 +2253,7 @@ struct NoCompSaveFilter : SaveFilter {
{
}
/* virtual */ void Write(byte *buf, size_t size)
void Write(byte *buf, size_t size) override
{
this->chain->Write(buf, size);
}
@@ -2289,7 +2287,7 @@ struct ZlibLoadFilter : LoadFilter {
inflateEnd(&this->z);
}
/* virtual */ size_t Read(byte *buf, size_t size)
size_t Read(byte *buf, size_t size) override
{
this->z.next_out = buf;
this->z.avail_out = (uint)size;
@@ -2368,12 +2366,12 @@ struct ZlibSaveFilter : SaveFilter {
} while (this->z.avail_in || !this->z.avail_out);
}
/* virtual */ void Write(byte *buf, size_t size)
void Write(byte *buf, size_t size) override
{
this->WriteLoop(buf, size, 0);
}
/* virtual */ void Finish()
void Finish() override
{
this->WriteLoop(NULL, 0, Z_FINISH);
this->chain->Finish();
@@ -2386,7 +2384,7 @@ struct ZlibSaveFilter : SaveFilter {
********** START OF LZMA CODE **************
********************************************/
#if defined(WITH_LZMA)
#if defined(WITH_LIBLZMA)
#include <lzma.h>
/**
@@ -2418,7 +2416,7 @@ struct LZMALoadFilter : LoadFilter {
lzma_end(&this->lzma);
}
/* virtual */ size_t Read(byte *buf, size_t size)
size_t Read(byte *buf, size_t size) override
{
this->lzma.next_out = buf;
this->lzma.avail_out = size;
@@ -2487,19 +2485,19 @@ struct LZMASaveFilter : SaveFilter {
} while (this->lzma.avail_in || !this->lzma.avail_out);
}
/* virtual */ void Write(byte *buf, size_t size)
void Write(byte *buf, size_t size) override
{
this->WriteLoop(buf, size, LZMA_RUN);
}
/* virtual */ void Finish()
void Finish() override
{
this->WriteLoop(NULL, 0, LZMA_FINISH);
this->chain->Finish();
}
};
#endif /* WITH_LZMA */
#endif /* WITH_LIBLZMA */
/*******************************************
************* END OF CODE *****************
@@ -2536,7 +2534,7 @@ static const SaveLoadFormat _saveload_formats[] = {
#else
{"zlib", TO_BE32X('OTTZ'), NULL, NULL, 0, 0, 0},
#endif
#if defined(WITH_LZMA)
#if defined(WITH_LIBLZMA)
/* Level 2 compression is speed wise as fast as zlib level 6 compression (old default), but results in ~10% smaller saves.
* Higher compression levels are possible, and might improve savegame size by up to 25%, but are also up to 10 times slower.
* The next significant reduction in file size is at level 4, but that is already 4 times slower. Level 3 is primarily 50%
@@ -2719,19 +2717,11 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded)
}
}
/** Thread run function for saving the file to disk. */
static void SaveFileToDiskThread(void *arg)
{
SaveFileToDisk(true);
}
void WaitTillSaved()
{
if (_save_thread == NULL) return;
if (!_save_thread.joinable()) return;
_save_thread->Join();
delete _save_thread;
_save_thread = NULL;
_save_thread.join();
/* Make sure every other state is handled properly as well. */
ProcessAsyncSaveFinish();
@@ -2759,7 +2749,8 @@ static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
SlSaveChunks();
SaveFileStart();
if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread, "ottd:savegame")) {
if (!threaded || !StartNewThread(&_save_thread, "ottd:savegame", &SaveFileToDisk, true)) {
if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
SaveOrLoadResult result = SaveFileToDisk(false);

View File

@@ -269,7 +269,7 @@ enum SaveLoadVersion : uint16 {
SLV_185, ///< 185 25620 Storybooks
SLV_186, ///< 186 25833 Objects storage
SLV_187, ///< 187 25899 Linkgraph - restricted flows
SLV_188, ///< 188 26169 FS#5831 Unify RV travel time
SLV_188, ///< 188 26169 v1.4 FS#5831 Unify RV travel time
SLV_189, ///< 189 26450 Heirarchical vehicle subgroups
SLV_190, ///< 190 26547 Separate order travel and wait times
@@ -293,7 +293,14 @@ enum SaveLoadVersion : uint16 {
SLV_GROUP_LIVERIES, ///< 205 PR#7108 Livery storage change and group liveries.
SLV_SHIPS_STOP_IN_LOCKS, ///< 206 PR#7150 Ship/lock movement changes.
SLV_FIX_CARGO_MONITOR, ///< 207 PR#7175 Cargo monitor data packing fix to support 64 cargotypes.
SLV_FIX_CARGO_MONITOR, ///< 207 PR#7175 v1.9 Cargo monitor data packing fix to support 64 cargotypes.
SLV_TOWN_CARGOGEN, ///< 208 PR#6965 New algorithms for town building cargo generation.
SLV_SHIP_CURVE_PENALTY, ///< 209 PR#7289 Configurable ship curve penalties.
SLV_SERVE_NEUTRAL_INDUSTRIES, ///< 210 PR#7234 Company stations can serve industries with attached neutral stations.
SLV_ROADVEH_PATH_CACHE, ///< 211 PR#7261 Add path cache for road vehicles.
SLV_REMOVE_OPF, ///< 212 PR#7245 Remove OPF.
SLV_TREES_WATER_CLASS, ///< 213 PR#7405 WaterClass update for tree tiles.
SL_MAX_VERSION, ///< Highest possible saveload version
};

View File

@@ -28,6 +28,7 @@ void RebuildTownCaches()
{
Town *town;
InitializeBuildingCounts();
RebuildTownKdtree();
/* Reset town population and num_houses */
FOR_ALL_TOWNS(town) {

View File

@@ -752,21 +752,23 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
static const SaveLoad _roadveh_desc[] = {
SLE_WRITEBYTE(Vehicle, type),
SLE_VEH_INCLUDE(),
SLE_VAR(RoadVehicle, state, SLE_UINT8),
SLE_VAR(RoadVehicle, frame, SLE_UINT8),
SLE_VAR(RoadVehicle, blocked_ctr, SLE_UINT16),
SLE_VAR(RoadVehicle, overtaking, SLE_UINT8),
SLE_VAR(RoadVehicle, overtaking_ctr, SLE_UINT8),
SLE_VAR(RoadVehicle, crashed_ctr, SLE_UINT16),
SLE_VAR(RoadVehicle, reverse_ctr, SLE_UINT8),
SLE_VAR(RoadVehicle, state, SLE_UINT8),
SLE_VAR(RoadVehicle, frame, SLE_UINT8),
SLE_VAR(RoadVehicle, blocked_ctr, SLE_UINT16),
SLE_VAR(RoadVehicle, overtaking, SLE_UINT8),
SLE_VAR(RoadVehicle, overtaking_ctr, SLE_UINT8),
SLE_VAR(RoadVehicle, crashed_ctr, SLE_UINT16),
SLE_VAR(RoadVehicle, reverse_ctr, SLE_UINT8),
SLE_CONDDEQUE(RoadVehicle, path.td, SLE_UINT8, SLV_ROADVEH_PATH_CACHE, SL_MAX_VERSION),
SLE_CONDDEQUE(RoadVehicle, path.tile, SLE_UINT32, SLV_ROADVEH_PATH_CACHE, SL_MAX_VERSION),
SLE_CONDNULL(2, SLV_6, SLV_69),
SLE_CONDVAR(RoadVehicle, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION),
SLE_CONDNULL(4, SLV_69, SLV_131),
SLE_CONDNULL(2, SLV_6, SLV_131),
SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space
SLE_CONDNULL(2, SLV_6, SLV_69),
SLE_CONDVAR(RoadVehicle, gv_flags, SLE_UINT16, SLV_139, SL_MAX_VERSION),
SLE_CONDNULL(4, SLV_69, SLV_131),
SLE_CONDNULL(2, SLV_6, SLV_131),
SLE_CONDNULL(16, SLV_2, SLV_144), // old reserved space
SLE_END()
SLE_END()
};
static const SaveLoad _ship_desc[] = {

View File

@@ -42,7 +42,7 @@ struct OldWaypoint {
};
/** Temporary array with old waypoints. */
static SmallVector<OldWaypoint, 16> _old_waypoints;
static std::vector<OldWaypoint> _old_waypoints;
/**
* Update the waypoint orders to get the new waypoint ID.
@@ -52,10 +52,10 @@ static void UpdateWaypointOrder(Order *o)
{
if (!o->IsType(OT_GOTO_WAYPOINT)) return;
for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
if (wp->index != o->GetDestination()) continue;
for (OldWaypoint &wp : _old_waypoints) {
if (wp.index != o->GetDestination()) continue;
o->SetDestination((DestinationID)wp->new_index);
o->SetDestination((DestinationID)wp.new_index);
return;
}
}
@@ -71,47 +71,47 @@ void MoveWaypointsToBaseStations()
* id which was stored in m4 is now saved as a grf/id reference in the
* waypoint struct. */
if (IsSavegameVersionBefore(SLV_17)) {
for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
if (wp->delete_ctr != 0) continue; // The waypoint was deleted
for (OldWaypoint &wp : _old_waypoints) {
if (wp.delete_ctr != 0) continue; // The waypoint was deleted
/* Waypoint indices were not added to the map prior to this. */
_m[wp->xy].m2 = (StationID)wp->index;
_m[wp.xy].m2 = (StationID)wp.index;
if (HasBit(_m[wp->xy].m3, 4)) {
wp->spec = StationClass::Get(STAT_CLASS_WAYP)->GetSpec(_m[wp->xy].m4 + 1);
if (HasBit(_m[wp.xy].m3, 4)) {
wp.spec = StationClass::Get(STAT_CLASS_WAYP)->GetSpec(_m[wp.xy].m4 + 1);
}
}
} else {
/* As of version 17, we recalculate the custom graphic ID of waypoints
* from the GRF ID / station index. */
for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
for (OldWaypoint &wp : _old_waypoints) {
StationClass* stclass = StationClass::Get(STAT_CLASS_WAYP);
for (uint i = 0; i < stclass->GetSpecCount(); i++) {
const StationSpec *statspec = stclass->GetSpec(i);
if (statspec != NULL && statspec->grf_prop.grffile->grfid == wp->grfid && statspec->grf_prop.local_id == wp->localidx) {
wp->spec = statspec;
if (statspec != NULL && statspec->grf_prop.grffile->grfid == wp.grfid && statspec->grf_prop.local_id == wp.localidx) {
wp.spec = statspec;
break;
}
}
}
}
if (!Waypoint::CanAllocateItem(_old_waypoints.Length())) SlError(STR_ERROR_TOO_MANY_STATIONS_LOADING);
if (!Waypoint::CanAllocateItem(_old_waypoints.size())) SlError(STR_ERROR_TOO_MANY_STATIONS_LOADING);
/* All saveload conversions have been done. Create the new waypoints! */
for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
Waypoint *new_wp = new Waypoint(wp->xy);
new_wp->town = wp->town;
new_wp->town_cn = wp->town_cn;
new_wp->name = wp->name;
for (OldWaypoint &wp : _old_waypoints) {
Waypoint *new_wp = new Waypoint(wp.xy);
new_wp->town = wp.town;
new_wp->town_cn = wp.town_cn;
new_wp->name = wp.name;
new_wp->delete_ctr = 0; // Just reset delete counter for once.
new_wp->build_date = wp->build_date;
new_wp->owner = wp->owner;
new_wp->build_date = wp.build_date;
new_wp->owner = wp.owner;
new_wp->string_id = STR_SV_STNAME_WAYPOINT;
TileIndex t = wp->xy;
if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp->index) {
TileIndex t = wp.xy;
if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp.index) {
/* The tile might've been reserved! */
bool reserved = !IsSavegameVersionBefore(SLV_100) && HasBit(_m[t].m5, 4);
@@ -122,13 +122,13 @@ void MoveWaypointsToBaseStations()
SetRailStationReservation(t, reserved);
if (wp->spec != NULL) {
SetCustomStationSpecIndex(t, AllocateSpecToStation(wp->spec, new_wp, true));
if (wp.spec != NULL) {
SetCustomStationSpecIndex(t, AllocateSpecToStation(wp.spec, new_wp, true));
}
new_wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
}
wp->new_index = new_wp->index;
wp.new_index = new_wp->index;
}
/* Update the orders of vehicles */
@@ -146,7 +146,8 @@ void MoveWaypointsToBaseStations()
UpdateWaypointOrder(&v->current_order);
}
_old_waypoints.Reset();
_old_waypoints.clear();
_old_waypoints.shrink_to_fit();
}
static const SaveLoad _old_waypoint_desc[] = {
@@ -172,12 +173,13 @@ static const SaveLoad _old_waypoint_desc[] = {
static void Load_WAYP()
{
/* Precaution for when loading failed and it didn't get cleared */
_old_waypoints.Clear();
_old_waypoints.clear();
int index;
while ((index = SlIterateArray()) != -1) {
OldWaypoint *wp = _old_waypoints.Append();
/*C++17: OldWaypoint *wp = &*/ _old_waypoints.emplace_back();
OldWaypoint *wp = &_old_waypoints.back();
memset(wp, 0, sizeof(*wp));
wp->index = index;
@@ -187,27 +189,27 @@ static void Load_WAYP()
static void Ptrs_WAYP()
{
for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
SlObject(wp, _old_waypoint_desc);
for (OldWaypoint &wp : _old_waypoints) {
SlObject(&wp, _old_waypoint_desc);
if (IsSavegameVersionBefore(SLV_12)) {
wp->town_cn = (wp->string_id & 0xC000) == 0xC000 ? (wp->string_id >> 8) & 0x3F : 0;
wp->town = ClosestTownFromTile(wp->xy, UINT_MAX);
wp.town_cn = (wp.string_id & 0xC000) == 0xC000 ? (wp.string_id >> 8) & 0x3F : 0;
wp.town = ClosestTownFromTile(wp.xy, UINT_MAX);
} else if (IsSavegameVersionBefore(SLV_122)) {
/* Only for versions 12 .. 122 */
if (!Town::IsValidID(wp->town_index)) {
if (!Town::IsValidID(wp.town_index)) {
/* Upon a corrupted waypoint we'll likely get here. The next step will be to
* loop over all Ptrs procs to NULL the pointers. However, we don't know
* whether we're in the NULL or "normal" Ptrs proc. So just clear the list
* of old waypoints we constructed and then this waypoint (and the other
* possibly corrupt ones) will not be queried in the NULL Ptrs proc run. */
_old_waypoints.Clear();
_old_waypoints.clear();
SlErrorCorrupt("Referencing invalid Town");
}
wp->town = Town::Get(wp->town_index);
wp.town = Town::Get(wp.town_index);
}
if (IsSavegameVersionBefore(SLV_84)) {
wp->name = CopyFromOldName(wp->string_id);
wp.name = CopyFromOldName(wp.string_id);
}
}
}