From a146bcfe93a6c913781cfe471166359e744195d7 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 6 Jun 2021 23:23:12 +0200 Subject: [PATCH 01/53] Change: store length of SL_STRUCTLIST in the savegame This wasn't consistently done, and often variables were used that were read by an earlier blob. By moving it next to the struct itself, the code becomes a bit more self-contained and easier to read. Additionally, this allows for external tooling to know how many structs to expect, instead of having to know where to find the length-field or a hard-coded value that can change at any moment. --- src/saveload/company_sl.cpp | 52 ++++++++++++++++++++++++--------- src/saveload/game_sl.cpp | 12 ++++---- src/saveload/linkgraph_sl.cpp | 25 +++++++++++----- src/saveload/saveload.cpp | 28 ++++++++++++++++++ src/saveload/saveload.h | 5 ++++ src/saveload/station_sl.cpp | 55 ++++++++++++++++++++++++++--------- src/saveload/town_sl.cpp | 21 +++++++++++-- 7 files changed, 156 insertions(+), 42 deletions(-) diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 550816a077..880fc9e891 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -372,8 +372,19 @@ public: class SlCompanyOldEconomy : public SlCompanyEconomy { public: - void GenericSaveLoad(CompanyProperties *c) const + void Save(CompanyProperties *c) const override + { + SlSetStructListLength(c->num_valid_stat_ent); + for (int i = 0; i < c->num_valid_stat_ent; i++) { + SlObject(&c->old_economy[i], this->GetDescription()); + } + } + + void Load(CompanyProperties *c) const override { + if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) { + c->num_valid_stat_ent = (uint8)SlGetStructListLength(UINT8_MAX); + } if (c->num_valid_stat_ent > lengthof(c->old_economy)) SlErrorCorrupt("Too many old economy entries"); for (int i = 0; i < c->num_valid_stat_ent; i++) { @@ -381,10 +392,7 @@ public: } } - void Save(CompanyProperties *c) const override { this->GenericSaveLoad(c); } - void Load(CompanyProperties *c) const override { this->GenericSaveLoad(c); } - void LoadCheck(CompanyProperties *c) const override { this->GenericSaveLoad(c); } - void FixPointers(CompanyProperties *c) const override { this->GenericSaveLoad(c); } + void LoadCheck(CompanyProperties *c) const override { this->Load(c); } }; class SlCompanyLiveries : public DefaultSaveLoadHandler { @@ -395,12 +403,33 @@ public: SLE_CONDVAR(Livery, colour2, SLE_UINT8, SLV_34, SL_MAX_VERSION), }; - void GenericSaveLoad(CompanyProperties *c) const + /** + * Get the number of liveries used by this savegame version. + * @return The number of liveries used by this savegame version. + */ + size_t GetNumLiveries() const { - int num_liveries = IsSavegameVersionBefore(SLV_63) ? LS_END - 4 : (IsSavegameVersionBefore(SLV_85) ? LS_END - 2: LS_END); + if (IsSavegameVersionBefore(SLV_63)) return LS_END - 4; + if (IsSavegameVersionBefore(SLV_85)) return LS_END - 2; + if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return LS_END; + /* Read from the savegame how long the list is. */ + return SlGetStructListLength(LS_END); + } + + void Save(CompanyProperties *c) const override + { + SlSetStructListLength(LS_END); + for (int i = 0; i < LS_END; i++) { + SlObject(&c->livery[i], this->GetDescription()); + } + } + + void Load(CompanyProperties *c) const override + { + size_t num_liveries = this->GetNumLiveries(); bool update_in_use = IsSavegameVersionBefore(SLV_GROUP_LIVERIES); - for (int i = 0; i < num_liveries; i++) { + for (size_t i = 0; i < num_liveries; i++) { SlObject(&c->livery[i], this->GetDescription()); if (update_in_use && i != LS_DEFAULT) { if (c->livery[i].in_use == 0) { @@ -426,10 +455,7 @@ public: } } - void Save(CompanyProperties *c) const override { this->GenericSaveLoad(c); } - void Load(CompanyProperties *c) const override { this->GenericSaveLoad(c); } - void LoadCheck(CompanyProperties *c) const override { this->GenericSaveLoad(c); } - void FixPointers(CompanyProperties *c) const override { this->GenericSaveLoad(c); } + void LoadCheck(CompanyProperties *c) const override { this->Load(c); } }; /* Save/load of companies */ @@ -467,7 +493,7 @@ 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(CompanyProperties, bankrupt_asked, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index af01d5bd07..76a81e167c 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -121,6 +121,8 @@ public: void Save(LanguageStrings *ls) const override { + SlSetStructListLength(ls->lines.size()); + for (const auto &string : ls->lines) { _game_saveload_string = string; SlObject(nullptr, this->GetDescription()); @@ -129,7 +131,9 @@ public: void Load(LanguageStrings *ls) const override { - for (uint32 i = 0; i < _game_saveload_strings; i++) { + uint32 length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _game_saveload_strings : (uint32)SlGetStructListLength(UINT32_MAX); + + for (uint32 i = 0; i < length; i++) { SlObject(nullptr, this->GetDescription()); ls->lines.emplace_back(_game_saveload_string); } @@ -138,7 +142,7 @@ public: static const SaveLoad _game_language_desc[] = { SLE_SSTR(LanguageStrings, language, SLE_STR), - SLEG_VAR(_game_saveload_strings, SLE_UINT32), + SLEG_CONDVAR(_game_saveload_strings, SLE_UINT32, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH), SLEG_STRUCTLIST(SlGameLanguageString), }; @@ -170,9 +174,7 @@ static void Save_GSTR() for (uint i = 0; i < _current_data->raw_strings.size(); i++) { SlSetArrayIndex(i); - LanguageStrings *ls = &_current_data->raw_strings[i]; - _game_saveload_strings = (uint32)ls->lines.size(); - SlObject(ls, _game_language_desc); + SlObject(&_current_data->raw_strings[i], _game_language_desc); } } diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index cf0292e6ef..fc72d43832 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -37,6 +37,12 @@ public: void Save(Node *bn) const override { + uint16 size = 0; + for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) { + size++; + } + + SlSetStructListLength(size); for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) { SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription()); } @@ -54,11 +60,18 @@ public: return; } + size_t used_size = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? max_size : SlGetStructListLength(UINT16_MAX); + /* ... but as that wasted a lot of space we save a sparse matrix now. */ for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) { + if (used_size == 0) SlErrorCorrupt("Link graph structure overflow"); + used_size--; + if (to >= max_size) SlErrorCorrupt("Link graph structure overflow"); SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription()); } + + if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph"); } }; @@ -77,6 +90,7 @@ public: { _linkgraph = lg; + SlSetStructListLength(lg->Size()); for (NodeID from = 0; from < lg->Size(); ++from) { _linkgraph_from = from; SlObject(&lg->nodes[from], this->GetDescription()); @@ -87,8 +101,9 @@ public: { _linkgraph = lg; - lg->Init(_num_nodes); - for (NodeID from = 0; from < _num_nodes; ++from) { + 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->GetDescription()); } @@ -103,7 +118,7 @@ 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, SLE_UINT16, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH), SLE_VAR(LinkGraph, cargo, SLE_UINT8), SLEG_STRUCTLIST(SlLinkgraphNode), }; @@ -227,8 +242,6 @@ void AfterLoadLinkGraphs() static void Save_LGRP() { for (LinkGraph *lg : LinkGraph::Iterate()) { - _num_nodes = lg->Size(); - SlSetArrayIndex(lg->index); SlObject(lg, GetLinkGraphDesc()); } @@ -252,8 +265,6 @@ static void Load_LGRP() static void Save_LGRJ() { for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) { - _num_nodes = lgj->Size(); - SlSetArrayIndex(lgj->index); SlObject(lgj, GetLinkGraphJobDesc()); } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index cb28fb6d28..3ca10b527a 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1589,6 +1589,34 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) return true; } +/** + * Set the length of this list. + * @param The length of the list. + */ +void SlSetStructListLength(size_t length) +{ + /* Automatically calculate the length? */ + if (_sl.need_length != NL_NONE) { + SlSetLength(SlGetArrayLength(length)); + if (_sl.need_length == NL_CALCLENGTH) return; + } + + SlWriteArrayLength(length); +} + +/** + * Get the length of this list; if it exceeds the limit, error out. + * @param limit The maximum size the list can be. + * @return The length of the list. + */ +size_t SlGetStructListLength(size_t limit) +{ + size_t length = SlReadArrayLength(); + if (length > limit) SlErrorCorrupt("List exceeds storage size"); + + return length; +} + /** * Main SaveLoad function. * @param object The object that is being saved or loaded. diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 7b0127709f..42d14c785b 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -326,9 +326,11 @@ enum SaveLoadVersion : uint16 { SLV_GS_INDUSTRY_CONTROL, ///< 287 PR#7912 and PR#8115 GS industry control. SLV_VEH_MOTION_COUNTER, ///< 288 PR#8591 Desync safe motion counter SLV_INDUSTRY_TEXT, ///< 289 PR#8576 v1.11.0-RC1 Additional GS text for industries. + SLV_MAPGEN_SETTINGS_REVAMP, ///< 290 PR#8891 v1.11 Revamp of some mapgen settings (snow coverage, desert coverage, heightmap height, custom terrain type). SLV_GROUP_REPLACE_WAGON_REMOVAL, ///< 291 PR#7441 Per-group wagon removal flag. SLV_CUSTOM_SUBSIDY_DURATION, ///< 292 PR#9081 Configurable subsidy duration. + SLV_SAVELOAD_LIST_LENGTH, ///< 293 PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST. SL_MAX_VERSION, ///< Highest possible saveload version }; @@ -992,6 +994,9 @@ void WriteValue(void *ptr, VarType conv, int64 val); void SlSetArrayIndex(uint index); int SlIterateArray(); +void SlSetStructListLength(size_t length); +size_t SlGetStructListLength(size_t limit); + void SlAutolength(AutolengthProc *proc, void *arg); size_t SlGetFieldLength(); void SlSetLength(size_t length); diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 4421e0f9f6..7144c5de4f 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -157,14 +157,14 @@ static const SaveLoad _roadstop_desc[] = { }; static uint16 _waiting_acceptance; -static uint32 _num_flows; +static uint32 _old_num_flows; static uint16 _cargo_source; static uint32 _cargo_source_xy; static uint8 _cargo_days; static Money _cargo_feeder_share; std::list _packets; -uint32 _num_dests; +uint32 _old_num_dests; struct FlowSaveLoad { FlowSaveLoad() : source(0), via(0), share(0), restricted(false) {} @@ -209,6 +209,7 @@ public: void Save(BaseStation *bst) const override { + SlSetStructListLength(bst->num_specs); for (uint i = 0; i < bst->num_specs; i++) { SlObject(&bst->speclist[i], this->GetDescription()); } @@ -216,6 +217,10 @@ public: void Load(BaseStation *bst) const override { + if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) { + bst->num_specs = (uint8)SlGetStructListLength(UINT8_MAX); + } + if (bst->num_specs != 0) { /* Allocate speclist memory when loading a game */ bst->speclist = CallocT(bst->num_specs); @@ -235,6 +240,7 @@ public: void Save(GoodsEntry *ge) const override { + SlSetStructListLength(ge->cargo.Packets()->MapSize()); for (StationCargoPacketMap::ConstMapIterator it(ge->cargo.Packets()->begin()); it != ge->cargo.Packets()->end(); ++it) { SlObject(const_cast(&(*it)), this->GetDescription()); } @@ -242,8 +248,10 @@ public: void Load(GoodsEntry *ge) const override { + size_t num_dests = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _old_num_dests : SlGetStructListLength(UINT32_MAX); + StationCargoPair pair; - for (uint j = 0; j < _num_dests; ++j) { + for (uint j = 0; j < num_dests; ++j) { SlObject(&pair, this->GetDescription()); const_cast(*(ge->cargo.Packets()))[pair.first].swap(pair.second); assert(pair.second.empty()); @@ -269,6 +277,12 @@ public: void Save(GoodsEntry *ge) const override { + uint32 num_flows = 0; + for (FlowStatMap::const_iterator it(ge->flows.begin()); it != ge->flows.end(); ++it) { + num_flows += (uint32)it->second.GetShares()->size(); + } + SlSetStructListLength(num_flows); + for (FlowStatMap::const_iterator outer_it(ge->flows.begin()); outer_it != ge->flows.end(); ++outer_it) { const FlowStat::SharesMap *shares = outer_it->second.GetShares(); uint32 sum_shares = 0; @@ -287,10 +301,12 @@ public: void Load(GoodsEntry *ge) const override { + size_t num_flows = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _old_num_flows : SlGetStructListLength(UINT32_MAX); + FlowSaveLoad flow; FlowStat *fs = nullptr; StationID prev_source = INVALID_STATION; - for (uint32 j = 0; j < _num_flows; ++j) { + for (uint32 j = 0; j < num_flows; ++j) { SlObject(&flow, this->GetDescription()); if (fs == nullptr || prev_source != flow.source) { fs = &(ge->flows.insert(std::make_pair(flow.source, FlowStat(flow.via, flow.share, flow.restricted))).first->second); @@ -330,11 +346,11 @@ public: SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, SLV_65, SLV_68), SLE_CONDVAR(GoodsEntry, amount_fract, SLE_UINT8, SLV_150, SL_MAX_VERSION), SLEG_CONDREFLIST( _packets, REF_CARGO_PACKET, SLV_68, SLV_183), - SLEG_CONDVAR( _num_dests, SLE_UINT32, SLV_183, SL_MAX_VERSION), + SLEG_CONDVAR( _old_num_dests, SLE_UINT32, SLV_183, SLV_SAVELOAD_LIST_LENGTH), SLE_CONDVAR(GoodsEntry, cargo.reserved_count, SLE_UINT, SLV_181, SL_MAX_VERSION), SLE_CONDVAR(GoodsEntry, link_graph, SLE_UINT16, SLV_183, SL_MAX_VERSION), SLE_CONDVAR(GoodsEntry, node, SLE_UINT16, SLV_183, SL_MAX_VERSION), - SLEG_CONDVAR( _num_flows, SLE_UINT32, SLV_183, SL_MAX_VERSION), + SLEG_CONDVAR( _old_num_flows, SLE_UINT32, SLV_183, SLV_SAVELOAD_LIST_LENGTH), SLE_CONDVAR(GoodsEntry, max_waiting_cargo, SLE_UINT32, SLV_183, SL_MAX_VERSION), SLEG_CONDSTRUCTLIST(SlStationFlow, SLV_183, SL_MAX_VERSION), SLEG_CONDSTRUCTLIST(SlStationCargo, SLV_183, SL_MAX_VERSION), @@ -344,15 +360,26 @@ public: } #endif + /** + * Get the number of cargoes used by this savegame version. + * @return The number of cargoes used by this savegame version. + */ + size_t GetNumCargo() const + { + if (IsSavegameVersionBefore(SLV_55)) return 12; + if (IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES)) return 32; + if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return NUM_CARGO; + /* Read from the savegame how long the list is. */ + return SlGetStructListLength(NUM_CARGO); + } + void Save(BaseStation *bst) const override { Station *st = Station::From(bst); + + SlSetStructListLength(NUM_CARGO); + for (CargoID i = 0; i < NUM_CARGO; i++) { - _num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize(); - _num_flows = 0; - for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) { - _num_flows += (uint32)it->second.GetShares()->size(); - } SlObject(&st->goods[i], this->GetDescription()); } } @@ -369,7 +396,7 @@ public: memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(_old_st_persistent_storage.storage)); } - uint num_cargo = IsSavegameVersionBefore(SLV_55) ? 12 : IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO; + size_t num_cargo = this->GetNumCargo(); for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; SlObject(ge, this->GetDescription()); @@ -520,7 +547,7 @@ public: /* Used by newstations for graphic variations */ SLE_VAR(BaseStation, random_bits, SLE_UINT16), SLE_VAR(BaseStation, waiting_triggers, SLE_UINT8), - SLE_VAR(BaseStation, num_specs, SLE_UINT8), + SLE_CONDVAR(BaseStation, num_specs, SLE_UINT8, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH), }; void GenericSaveLoad(BaseStation *bst) const @@ -626,7 +653,7 @@ static void Save_STNN() static void Load_STNN() { - _num_flows = 0; + _old_num_flows = 0; int index; while ((index = SlIterateArray()) != -1) { diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 4151e3c754..38c000e3b9 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -122,8 +122,21 @@ public: SLE_CONDVAR(TransportedCargoStat, new_act, SLE_UINT32, SLV_165, SL_MAX_VERSION), }; + /** + * Get the number of cargoes used by this savegame version. + * @return The number of cargoes used by this savegame version. + */ + size_t GetNumCargo() const + { + if (IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES)) return 32; + if (IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) return NUM_CARGO; + /* Read from the savegame how long the list is. */ + return SlGetStructListLength(NUM_CARGO); + } + void Save(Town *t) const override { + SlSetStructListLength(NUM_CARGO); for (CargoID i = 0; i < NUM_CARGO; i++) { SlObject(&t->supplied[i], this->GetDescription()); } @@ -131,7 +144,7 @@ public: void Load(Town *t) const override { - uint num_cargo = IsSavegameVersionBefore(SLV_EXTEND_CARGOTYPES) ? 32 : NUM_CARGO; + size_t num_cargo = this->GetNumCargo(); for (CargoID i = 0; i < num_cargo; i++) { SlObject(&t->supplied[i], this->GetDescription()); } @@ -149,14 +162,16 @@ public: void Save(Town *t) const override { - for (int i = TE_BEGIN; i < TE_END; i++) { + SlSetStructListLength(NUM_TE); + for (size_t i = TE_BEGIN; i < TE_END; i++) { SlObject(&t->received[i], this->GetDescription()); } } void Load(Town *t) const override { - for (int i = TE_BEGIN; i < TE_END; i++) { + size_t length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? (size_t)TE_END : SlGetStructListLength(TE_END); + for (size_t i = 0; i < length; i++) { SlObject(&t->received[i], this->GetDescription()); } } From 75e7451151ea9ab1ed18cd04b1229f68b7d3dcf5 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 11 Jun 2021 15:05:58 +0200 Subject: [PATCH 02/53] Change: indicate in the savegame if a SL_STRUCT contains any data This helps external tooling to understand if a SL_STRUCT should be skipped when reading. Basically, this transforms an SL_STRUCT into a SL_STRUCTLIST with either 0 or 1 length. --- src/saveload/saveload.cpp | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 3ca10b527a..9f3aa7d1d8 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1467,6 +1467,10 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) _sl.obj_len = old_obj_len; _sl.need_length = old_need_length; + if (sld.cmd == SL_STRUCT) { + length += SlGetArrayLength(1); + } + return length; } default: NOT_REACHED(); @@ -1575,10 +1579,35 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) if (!SlIsObjectValidInSavegame(sld)) return false; switch (_sl.action) { - case SLA_SAVE: sld.handler->Save(object); break; - case SLA_LOAD_CHECK: sld.handler->LoadCheck(object); break; - case SLA_LOAD: sld.handler->Load(object); break; - case SLA_PTRS: sld.handler->FixPointers(object); break; + case SLA_SAVE: { + if (sld.cmd == SL_STRUCT) { + /* Store in the savegame if this struct was written or not. */ + SlSetStructListLength(SlCalcObjMemberLength(object, sld) > SlGetArrayLength(1) ? 1 : 0); + } + sld.handler->Save(object); + break; + } + + case SLA_LOAD_CHECK: { + if (sld.cmd == SL_STRUCT && !IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) { + SlGetStructListLength(1); + } + sld.handler->LoadCheck(object); + break; + } + + case SLA_LOAD: { + if (sld.cmd == SL_STRUCT && !IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) { + SlGetStructListLength(1); + } + sld.handler->Load(object); + break; + } + + case SLA_PTRS: + sld.handler->FixPointers(object); + break; + case SLA_NULL: break; default: NOT_REACHED(); } From 0d2e3437e3317a5bc7f9a806e76a89091d2cb6d3 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 12 Jun 2021 13:23:19 +0200 Subject: [PATCH 03/53] Change: switch SL_DEQUE and SL_REFLIST length field to a gamma The current SaveLoad is a bit inconsistent how long a length field is. Sometimes it is a 32bit, sometimes a gamma. Make it consistent across the board by making them all gammas. --- src/saveload/saveload.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 9f3aa7d1d8..2d1e6fc78d 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1261,7 +1261,7 @@ public: const SlStorageT *list = static_cast(storage); - int type_size = SlCalcConvFileLen(SLE_FILE_U32); // Size of the length of the list. + int type_size = SlGetArrayLength(list->size()); int item_size = SlCalcConvFileLen(cmd == SL_VAR ? conv : (VarType)SLE_FILE_U32); return list->size() * item_size + type_size; } @@ -1290,7 +1290,7 @@ public: switch (_sl.action) { case SLA_SAVE: - SlWriteUint32((uint32)list->size()); + SlWriteArrayLength(list->size()); for (auto &item : *list) { SlSaveLoadMember(cmd, &item, conv); @@ -1301,8 +1301,8 @@ public: case SLA_LOAD: { size_t length; switch (cmd) { - case SL_VAR: length = SlReadUint32(); break; - case SL_REF: length = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : SlReadUint32(); break; + case SL_VAR: length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? SlReadUint32() : SlReadArrayLength(); break; + case SL_REF: length = IsSavegameVersionBefore(SLV_69) ? SlReadUint16() : IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? SlReadUint32() : SlReadArrayLength(); break; default: NOT_REACHED(); } From d5cda58158726b80ff619d0ba691420469f18e90 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 15 Jun 2021 11:59:38 +0200 Subject: [PATCH 04/53] Codechange: use SL_NULL if you want to store null-bytes or load to nothing Using SL_ARR for this gives us a bit of trouble later on, where we add a length-field to SL_ARR. This of course is not the intention of SLE_CONDNULL. So better seperate it. --- src/saveload/saveload.cpp | 56 +++++++++++++++++++-------------------- src/saveload/saveload.h | 5 ++-- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 2d1e6fc78d..c07330cabb 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1425,33 +1425,21 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) { assert(_sl.action == SLA_SAVE); - switch (sld.cmd) { - case SL_VAR: - case SL_REF: - case SL_ARR: - case SL_STR: - case SL_REFLIST: - case SL_DEQUE: - case SL_STDSTR: - /* CONDITIONAL saveload types depend on the savegame version */ - if (!SlIsObjectValidInSavegame(sld)) break; + if (!SlIsObjectValidInSavegame(sld)) return 0; - switch (sld.cmd) { - case SL_VAR: return SlCalcConvFileLen(sld.conv); - case SL_REF: return SlCalcRefLen(); - case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); - case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); - case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); - case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); - case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); - default: NOT_REACHED(); - } - break; + switch (sld.cmd) { + case SL_VAR: return SlCalcConvFileLen(sld.conv); + case SL_REF: return SlCalcRefLen(); + case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); + case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); + case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); + case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); + case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); case SL_SAVEBYTE: return 1; // a byte is logically of size 1 + case SL_NULL: return SlCalcConvFileLen(sld.conv) * sld.length; + case SL_STRUCT: case SL_STRUCTLIST: { - if (!SlIsObjectValidInSavegame(sld)) break; - NeedLength old_need_length = _sl.need_length; size_t old_obj_len = _sl.obj_len; @@ -1473,6 +1461,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) return length; } + default: NOT_REACHED(); } return 0; @@ -1530,6 +1519,8 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) { assert(IsVariableSizeRight(sld)); + if (!SlIsObjectValidInSavegame(sld)) return false; + VarType conv = GB(sld.conv, 0, 8); switch (sld.cmd) { case SL_VAR: @@ -1539,9 +1530,6 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_REFLIST: case SL_DEQUE: case SL_STDSTR: { - /* CONDITIONAL saveload types depend on the savegame version */ - if (!SlIsObjectValidInSavegame(sld)) return false; - void *ptr = GetVariableAddress(object, sld); switch (sld.cmd) { @@ -1574,10 +1562,22 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) break; } + case SL_NULL: { + assert(GetVarMemType(sld.conv) == SLE_VAR_NULL); + + switch (_sl.action) { + case SLA_LOAD_CHECK: + case SLA_LOAD: SlSkipBytes(SlCalcConvFileLen(sld.conv) * sld.length); break; + case SLA_SAVE: for (int i = 0; i < SlCalcConvFileLen(sld.conv) * sld.length; i++) SlWriteByte(0); break; + case SLA_PTRS: + case SLA_NULL: break; + default: NOT_REACHED(); + } + break; + } + case SL_STRUCT: case SL_STRUCTLIST: - if (!SlIsObjectValidInSavegame(sld)) return false; - switch (_sl.action) { case SLA_SAVE: { if (sld.cmd == SL_STRUCT) { diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 42d14c785b..c63740ae09 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -573,6 +573,7 @@ enum SaveLoadType : byte { SL_STRUCT = 7, ///< Save/load a struct. SL_STRUCTLIST = 8, ///< Save/load a list of structs. SL_SAVEBYTE = 9, ///< Save (but not load) a byte. + SL_NULL = 10, ///< Save null-bytes and load to nowhere. }; typedef void *SaveLoadAddrProc(void *base, size_t extra); @@ -737,7 +738,7 @@ struct SaveLoad { * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLE_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} +#define SLE_CONDNULL(length, from, to) {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} /** * Only write byte during saving; never read it during loading. @@ -895,7 +896,7 @@ struct SaveLoad { * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLEG_CONDNULL(length, from, to) {SL_ARR, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} +#define SLEG_CONDNULL(length, from, to) {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} /** * Checks whether the savegame is below \a major.\a minor. From f67af5cbe5cb754c3b64553b9cc03b5c18ca7e79 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 15 Jun 2021 12:00:48 +0200 Subject: [PATCH 05/53] Codechange: make it more obvious SlArray supports SLE_VAR_NULL In the end, the code was already doing the right thing, but a few functions deep, and not really obvious. When validating what objects can handle SLE_VAR_NULL, it is nicer to just have this obvious. --- src/saveload/saveload.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index c07330cabb..d4ca1b3081 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1069,6 +1069,12 @@ void SlArray(void *array, size_t length, VarType conv) if (_sl.need_length == NL_CALCLENGTH) return; } + if (GetVarMemType(conv) == SLE_VAR_NULL) { + assert(_sl.action != SLA_SAVE); // Use SL_NULL if you want to write null-bytes + SlSkipBytes(SlCalcArrayLen(length, conv)); + return; + } + /* NOTICE - handle some buggy stuff, in really old versions everything was saved * as a byte-type. So detect this, and adjust array size accordingly */ if (_sl.action != SLA_SAVE && _sl_version == 0) { From 97b94bdc9ab4ceeb589c5022d5c238442faf0454 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 12 Jun 2021 14:49:51 +0200 Subject: [PATCH 06/53] Change: prefix SL_ARR with the length of the array This means that during loading we can validate that what is saved is also that what is expected. Additionally, this makes all list types similar to how they are stored on disk: First a gamma to indicate length, followed by the data. The size still depends on the type. --- src/saveload/animated_tile_sl.cpp | 6 +- src/saveload/economy_sl.cpp | 8 +- src/saveload/engine_sl.cpp | 2 +- src/saveload/map_sl.cpp | 42 ++++----- src/saveload/order_sl.cpp | 4 +- src/saveload/saveload.cpp | 110 +++++++++++++++++------- src/saveload/saveload.h | 2 +- src/saveload/strings_sl.cpp | 2 +- src/script/script_instance.cpp | 8 +- src/table/settings/gameopt_settings.ini | 2 +- 10 files changed, 117 insertions(+), 69 deletions(-) diff --git a/src/saveload/animated_tile_sl.cpp b/src/saveload/animated_tile_sl.cpp index 2b38421046..89eb881b1b 100644 --- a/src/saveload/animated_tile_sl.cpp +++ b/src/saveload/animated_tile_sl.cpp @@ -24,7 +24,7 @@ extern std::vector _animated_tiles; static void Save_ANIT() { SlSetLength(_animated_tiles.size() * sizeof(_animated_tiles.front())); - SlArray(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32); + SlCopy(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32); } /** @@ -36,7 +36,7 @@ static void Load_ANIT() 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; @@ -48,7 +48,7 @@ static void Load_ANIT() 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); + SlCopy(_animated_tiles.data(), count, SLE_UINT32); } /** diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index b51151c146..82e3014ad5 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -20,8 +20,8 @@ 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); + SlCopy(nullptr, 49, vt | SLE_VAR_NULL); + SlCopy(nullptr, 49, SLE_FILE_U16 | SLE_VAR_NULL); } /** Cargo payment rates in pre 126 savegames */ @@ -29,8 +29,8 @@ 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); + SlCopy(nullptr, num_cargo, vt | SLE_VAR_NULL); + SlCopy(nullptr, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL); } static const SaveLoad _economy_desc[] = { diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index 430ae29d19..336c932826 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -156,7 +156,7 @@ static void Load_ENGS() * was always 256 entries. */ StringID names[256]; - SlArray(names, lengthof(names), SLE_STRINGID); + SlCopy(names, lengthof(names), SLE_STRINGID); /* Copy each string into the temporary engine array. */ for (EngineID engine = 0; engine < lengthof(names); engine++) { diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index d13900fc64..5924f4440a 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -53,7 +53,7 @@ static void Load_MAPT() 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]; } } @@ -66,7 +66,7 @@ static void Save_MAPT() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -76,7 +76,7 @@ static void Load_MAPH() 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]; } } @@ -89,7 +89,7 @@ static void Save_MAPH() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].height; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -99,7 +99,7 @@ static void Load_MAP1() 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]; } } @@ -112,7 +112,7 @@ static void Save_MAP1() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -122,7 +122,7 @@ static void Load_MAP2() 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 ); @@ -138,7 +138,7 @@ static void Save_MAP2() 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; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); } } @@ -148,7 +148,7 @@ static void Load_MAP3() 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]; } } @@ -161,7 +161,7 @@ static void Save_MAP3() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -171,7 +171,7 @@ static void Load_MAP4() 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]; } } @@ -184,7 +184,7 @@ static void Save_MAP4() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -194,7 +194,7 @@ static void Load_MAP5() 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]; } } @@ -207,7 +207,7 @@ static void Save_MAP5() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -219,7 +219,7 @@ static void Load_MAP6() 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); @@ -229,7 +229,7 @@ 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]; } } @@ -243,7 +243,7 @@ static void Save_MAP6() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m6; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -253,7 +253,7 @@ static void Load_MAP7() 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]; } } @@ -266,7 +266,7 @@ static void Save_MAP7() SlSetLength(size); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT8); } } @@ -276,7 +276,7 @@ static void Load_MAP8() 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]; } } @@ -289,7 +289,7 @@ static void Save_MAP8() SlSetLength(size * sizeof(uint16)); for (TileIndex i = 0; i != size;) { for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m8; - SlArray(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT16); } } diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index 523a8b804b..81e485606e 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -141,7 +141,7 @@ static void Load_ORDR() len /= sizeof(uint16); uint16 *orders = MallocT(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(); @@ -153,7 +153,7 @@ static void Load_ORDR() len /= sizeof(uint32); uint32 *orders = MallocT(len + 1); - SlArray(orders, len, SLE_UINT32); + SlCopy(orders, len, SLE_UINT32); for (size_t i = 0; i < len; ++i) { new (i) Order(orders[i]); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index d4ca1b3081..04002fd3fa 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1043,51 +1043,34 @@ static void SlStdString(void *ptr, VarType conv) } /** - * Return the size in bytes of a certain type of atomic array - * @param length The length of the array counted in elements - * @param conv VarType type of the variable that is used in calculating the size + * Internal function to save/Load a list of SL_VARs. + * SlCopy() and SlArray() are very similar, with the exception of the header. + * This function represents the common part. + * @param object The object being manipulated. + * @param length The length of the object in elements + * @param conv VarType type of the items. */ -static inline size_t SlCalcArrayLen(size_t length, VarType conv) +static void SlCopyInternal(void *object, size_t length, VarType conv) { - return SlCalcConvFileLen(conv) * length; -} - -/** - * Save/Load an array. - * @param array The array being manipulated - * @param length The length of the array in elements - * @param conv VarType type of the atomic array (int, byte, uint64, etc.) - */ -void SlArray(void *array, size_t length, VarType conv) -{ - if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return; - - /* Automatically calculate the length? */ - if (_sl.need_length != NL_NONE) { - SlSetLength(SlCalcArrayLen(length, conv)); - /* Determine length only? */ - if (_sl.need_length == NL_CALCLENGTH) return; - } - if (GetVarMemType(conv) == SLE_VAR_NULL) { assert(_sl.action != SLA_SAVE); // Use SL_NULL if you want to write null-bytes - SlSkipBytes(SlCalcArrayLen(length, conv)); + SlSkipBytes(length * SlCalcConvFileLen(conv)); return; } /* NOTICE - handle some buggy stuff, in really old versions everything was saved - * as a byte-type. So detect this, and adjust array size accordingly */ + * as a byte-type. So detect this, and adjust object size accordingly */ if (_sl.action != SLA_SAVE && _sl_version == 0) { - /* all arrays except difficulty settings */ + /* all objects except difficulty settings */ if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID || conv == SLE_INT32 || conv == SLE_UINT32) { - SlCopyBytes(array, length * SlCalcConvFileLen(conv)); + SlCopyBytes(object, length * SlCalcConvFileLen(conv)); return; } /* used for conversion of Money 32bit->64bit */ if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) { for (uint i = 0; i < length; i++) { - ((int64*)array)[i] = (int32)BSWAP32(SlReadUint32()); + ((int64*)object)[i] = (int32)BSWAP32(SlReadUint32()); } return; } @@ -1096,9 +1079,9 @@ void SlArray(void *array, size_t length, VarType conv) /* If the size of elements is 1 byte both in file and memory, no special * conversion is needed, use specialized copy-copy function to speed up things */ if (conv == SLE_INT8 || conv == SLE_UINT8) { - SlCopyBytes(array, length); + SlCopyBytes(object, length); } else { - byte *a = (byte*)array; + byte *a = (byte*)object; byte mem_size = SlCalcConvMemLen(conv); for (; length != 0; length --) { @@ -1108,6 +1091,71 @@ void SlArray(void *array, size_t length, VarType conv) } } +/** + * Copy a list of SL_VARs to/from a savegame. + * These entries are copied as-is, and you as caller have to make sure things + * like length-fields are calculated correctly. + * @param object The object being manipulated. + * @param length The length of the object in elements + * @param conv VarType type of the items. + */ +void SlCopy(void *object, size_t length, VarType conv) +{ + if (_sl.action == SLA_PTRS || _sl.action == SLA_NULL) return; + + /* Automatically calculate the length? */ + if (_sl.need_length != NL_NONE) { + SlSetLength(length * SlCalcConvFileLen(conv)); + /* Determine length only? */ + if (_sl.need_length == NL_CALCLENGTH) return; + } + + SlCopyInternal(object, length, conv); +} + +/** + * Return the size in bytes of a certain type of atomic array + * @param length The length of the array counted in elements + * @param conv VarType type of the variable that is used in calculating the size + */ +static inline size_t SlCalcArrayLen(size_t length, VarType conv) +{ + return SlCalcConvFileLen(conv) * length + SlGetArrayLength(length); +} + +/** + * Save/Load the length of the array followed by the array of SL_VAR elements. + * @param array The array being manipulated + * @param length The length of the array in elements + * @param conv VarType type of the atomic array (int, byte, uint64, etc.) + */ +static void SlArray(void *array, size_t length, VarType conv) +{ + switch (_sl.action) { + case SLA_SAVE: + SlWriteArrayLength(length); + SlCopyInternal(array, length, conv); + return; + + case SLA_LOAD_CHECK: + case SLA_LOAD: { + if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH)) { + size_t sv_length = SlReadArrayLength(); + if (sv_length != length) SlErrorCorrupt("Fixed-length array is of wrong length"); + } + + SlCopyInternal(array, length, conv); + return; + } + + case SLA_PTRS: + case SLA_NULL: + return; + + default: + NOT_REACHED(); + } +} /** * Pointers cannot be saved to a savegame, so this functions gets diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index c63740ae09..7ed76ff2d7 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -1008,7 +1008,7 @@ byte SlReadByte(); void SlWriteByte(byte b); void SlGlobList(const SaveLoadTable &slt); -void SlArray(void *array, size_t length, VarType conv); +void SlCopy(void *object, size_t length, VarType conv); void SlObject(void *object, const SaveLoadTable &slt); void NORETURN SlError(StringID string, const char *extra_msg = nullptr); void NORETURN SlErrorCorrupt(const char *msg); diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index 52f70b8d58..c4f56ed432 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -124,7 +124,7 @@ static void Load_NAME() if (index >= NUM_OLD_STRINGS) SlErrorCorrupt("Invalid old name index"); if (SlGetFieldLength() > (uint)LEN_OLD_STRINGS) SlErrorCorrupt("Invalid old name length"); - SlArray(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8); + SlCopy(&_old_name_array[LEN_OLD_STRINGS * index], SlGetFieldLength(), SLE_UINT8); /* Make sure the old name is null terminated */ _old_name_array[LEN_OLD_STRINGS * index + LEN_OLD_STRINGS - 1] = '\0'; } diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index 2d32b02e8d..2665a86846 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -365,7 +365,7 @@ static const SaveLoad _script_byte[] = { sq_getinteger(vm, index, &res); if (!test) { int value = (int)res; - SlArray(&value, 1, SLE_INT32); + SlCopy(&value, 1, SLE_INT32); } return true; } @@ -385,7 +385,7 @@ static const SaveLoad _script_byte[] = { if (!test) { _script_sl_byte = (byte)len; SlObject(nullptr, _script_byte); - SlArray(const_cast(buf), len, SLE_CHAR); + SlCopy(const_cast(buf), len, SLE_CHAR); } return true; } @@ -565,7 +565,7 @@ bool ScriptInstance::IsPaused() switch (_script_sl_byte) { case SQSL_INT: { int value; - SlArray(&value, 1, SLE_INT32); + SlCopy(&value, 1, SLE_INT32); if (vm != nullptr) sq_pushinteger(vm, (SQInteger)value); return true; } @@ -573,7 +573,7 @@ bool ScriptInstance::IsPaused() case SQSL_STRING: { SlObject(nullptr, _script_byte); static char buf[std::numeric_limits::max()]; - SlArray(buf, _script_sl_byte, SLE_CHAR); + SlCopy(buf, _script_sl_byte, SLE_CHAR); StrMakeValidInPlace(buf, buf + _script_sl_byte); if (vm != nullptr) sq_pushstring(vm, buf, -1); return true; diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index addcbeb027..ce28def632 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -41,7 +41,7 @@ static const SettingTable _gameopt_settings{ * XXX - To save file-space and since values are never bigger than about 10? only * save the first 16 bits in the savegame. Question is why the values are still int32 * and why not byte for example? - * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlArray() hack + * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlCopy() hack * for savegames version 0 - though it is an array, it has to go through the byteswap process */ [post-amble] }; From b9ab9e4d051eea7d6aedfb60930b039b778568af Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 14 Jun 2021 20:03:35 +0200 Subject: [PATCH 07/53] Codechange: add the ability to save/load a std::vector std::vector is not possible, as .. that is a nice special case in C++. This new type will be used in next commit. --- src/saveload/saveload.cpp | 46 +++++++++++++++++++++++++++++++++++++++ src/saveload/saveload.h | 36 +++++++++++++++++++++++------- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 04002fd3fa..9b177dd0d9 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -44,6 +44,7 @@ #include "../error.h" #include #include +#include #include #ifdef __EMSCRIPTEN__ # include @@ -1452,6 +1453,48 @@ static void SlDeque(void *deque, VarType conv) } } +/** + * Return the size in bytes of a std::vector. + * @param vector The std::vector to find the size of + * @param conv VarType type of variable that is used for calculating the size + */ +static inline size_t SlCalcVectorLen(const void *vector, VarType conv) +{ + switch (GetVarMemType(conv)) { + case SLE_VAR_BL: NOT_REACHED(); // Not supported + case SLE_VAR_I8: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_U8: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_I16: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_U16: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_I32: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_U32: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_I64: return SlStorageHelper::SlCalcLen(vector, conv); + case SLE_VAR_U64: return SlStorageHelper::SlCalcLen(vector, conv); + default: NOT_REACHED(); + } +} + +/** + * Save/load a std::vector. + * @param vector The std::vector being manipulated + * @param conv VarType type of variable that is used for calculating the size + */ +static void SlVector(void *vector, VarType conv) +{ + switch (GetVarMemType(conv)) { + case SLE_VAR_BL: NOT_REACHED(); // Not supported + case SLE_VAR_I8: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_U8: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_I16: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_U16: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_I32: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_U32: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_I64: SlStorageHelper::SlSaveLoad(vector, conv); break; + case SLE_VAR_U64: SlStorageHelper::SlSaveLoad(vector, conv); break; + default: NOT_REACHED(); + } +} + /** Are we going to save this object or not? */ static inline bool SlIsObjectValidInSavegame(const SaveLoad &sld) { @@ -1488,6 +1531,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) case SL_STR: return SlCalcStringLen(GetVariableAddress(object, sld), sld.length, sld.conv); case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); + case SL_VECTOR: return SlCalcVectorLen(GetVariableAddress(object, sld), sld.conv); case SL_STDSTR: return SlCalcStdStringLen(GetVariableAddress(object, sld)); case SL_SAVEBYTE: return 1; // a byte is logically of size 1 case SL_NULL: return SlCalcConvFileLen(sld.conv) * sld.length; @@ -1583,6 +1627,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_STR: case SL_REFLIST: case SL_DEQUE: + case SL_VECTOR: case SL_STDSTR: { void *ptr = GetVariableAddress(object, sld); @@ -1593,6 +1638,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_STR: SlString(ptr, sld.length, sld.conv); break; case SL_REFLIST: SlRefList(ptr, conv); break; case SL_DEQUE: SlDeque(ptr, conv); break; + case SL_VECTOR: SlVector(ptr, conv); break; case SL_STDSTR: SlStdString(ptr, sld.conv); break; default: NOT_REACHED(); } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 7ed76ff2d7..559876b97b 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -565,15 +565,19 @@ typedef uint32 VarType; enum SaveLoadType : byte { SL_VAR = 0, ///< Save/load a variable. SL_REF = 1, ///< Save/load a reference. - SL_ARR = 2, ///< Save/load a fixed-size array of #SL_VAR elements. + SL_STRUCT = 2, ///< Save/load a struct. + SL_STR = 3, ///< Save/load a string. - SL_REFLIST = 4, ///< Save/load a list of #SL_REF elements. - SL_DEQUE = 5, ///< Save/load a deque of #SL_VAR elements. - SL_STDSTR = 6, ///< Save/load a \c std::string. - SL_STRUCT = 7, ///< Save/load a struct. - SL_STRUCTLIST = 8, ///< Save/load a list of structs. - SL_SAVEBYTE = 9, ///< Save (but not load) a byte. - SL_NULL = 10, ///< Save null-bytes and load to nowhere. + SL_STDSTR = 4, ///< Save/load a \c std::string. + + SL_ARR = 5, ///< Save/load a fixed-size array of #SL_VAR elements. + SL_DEQUE = 6, ///< Save/load a deque of #SL_VAR elements. + SL_VECTOR = 7, ///< Save/load a vector of #SL_VAR elements. + SL_REFLIST = 8, ///< Save/load a list of #SL_REF elements. + SL_STRUCTLIST = 9, ///< Save/load a list of structs. + + SL_SAVEBYTE = 10, ///< Save (but not load) a byte. + SL_NULL = 11, ///< Save null-bytes and load to nowhere. }; typedef void *SaveLoadAddrProc(void *base, size_t extra); @@ -828,6 +832,15 @@ struct SaveLoad { */ #define SLEG_CONDREFLIST(variable, type, from, to) SLEG_GENERAL(SL_REFLIST, variable, type, 0, from, to, 0) +/** + * Storage of a global vector of #SL_VAR elements in some savegame versions. + * @param variable Name of the global variable. + * @param type Storage of the data in memory and in the savegame. + * @param from First savegame version that has the list. + * @param to Last savegame version that has the list. + */ +#define SLEG_CONDVECTOR(variable, type, from, to) SLEG_GENERAL(SL_VECTOR, variable, type, 0, from, to, 0) + /** * Storage of a list of structs in some savegame versions. * @param handler SaveLoadHandler for the list of structs. @@ -884,6 +897,13 @@ struct SaveLoad { */ #define SLEG_REFLIST(variable, type) SLEG_CONDREFLIST(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) +/** + * Storage of a global vector of #SL_VAR elements in every savegame version. + * @param variable Name of the global variable. + * @param type Storage of the data in memory and in the savegame. + */ +#define SLEG_VECTOR(variable, type) SLEG_CONDVECTOR(variable, type, SL_MIN_VERSION, SL_MAX_VERSION) + /** * Storage of a list of structs in every savegame version. * @param handler SaveLoadHandler for the list of structs. From 88edfd4ef16bedd98a07a2142e693ab50fbdcef2 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sun, 6 Jun 2021 09:59:33 +0200 Subject: [PATCH 08/53] Change: rework several CH_RIFF chunks to use CH_ARRAY instead This adds two byte extra to those chunks, and might feel a bit silly at first. But in later changes we will prefix CH_ARRAY with a table header, and then this change shines. Without this, we could still add headers to these chunks, but any external reader wouldn't know if the CH_RIFF has them or not. This way is much more practical, as they are now more like any other chunk. --- src/saveload/animated_tile_sl.cpp | 25 +++++++++++++++++------- src/saveload/cheat_sl.cpp | 6 +++++- src/saveload/economy_sl.cpp | 6 +++++- src/saveload/game_sl.cpp | 6 +++--- src/saveload/industry_sl.cpp | 23 +++++++++++++++------- src/saveload/linkgraph_sl.cpp | 5 ++++- src/saveload/map_sl.cpp | 18 ++++++++++++----- src/saveload/misc_sl.cpp | 32 ++++++++++++++++++++++++++----- src/saveload/saveload.h | 1 + src/settings.cpp | 7 +++++-- 10 files changed, 97 insertions(+), 32 deletions(-) diff --git a/src/saveload/animated_tile_sl.cpp b/src/saveload/animated_tile_sl.cpp index 89eb881b1b..7f05eaeeb7 100644 --- a/src/saveload/animated_tile_sl.cpp +++ b/src/saveload/animated_tile_sl.cpp @@ -18,13 +18,17 @@ extern std::vector _animated_tiles; +static const SaveLoad _animated_tile_desc[] = { + SLEG_VECTOR(_animated_tiles, SLE_UINT32), +}; + /** * Save the ANIT chunk. */ static void Save_ANIT() { - SlSetLength(_animated_tiles.size() * sizeof(_animated_tiles.front())); - SlCopy(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32); + SlSetArrayIndex(0); + SlGlobList(_animated_tile_desc); } /** @@ -45,10 +49,17 @@ static void Load_ANIT() return; } - uint count = (uint)SlGetFieldLength() / sizeof(_animated_tiles.front()); - _animated_tiles.clear(); - _animated_tiles.resize(_animated_tiles.size() + count); - SlCopy(_animated_tiles.data(), count, SLE_UINT32); + if (IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY)) { + size_t count = SlGetFieldLength() / sizeof(_animated_tiles.front()); + _animated_tiles.clear(); + _animated_tiles.resize(_animated_tiles.size() + count); + SlCopy(_animated_tiles.data(), count, SLE_UINT32); + return; + } + + if (SlIterateArray() == -1) return; + SlGlobList(_animated_tile_desc); + if (SlIterateArray() != -1) SlErrorCorrupt("Too many ANIT entries"); } /** @@ -56,7 +67,7 @@ static void Load_ANIT() * the animated tile table. */ static const ChunkHandler animated_tile_chunk_handlers[] = { - { 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_RIFF }, + { 'ANIT', Save_ANIT, Load_ANIT, nullptr, nullptr, CH_ARRAY }, }; extern const ChunkHandlerTable _animated_tile_chunk_handlers(animated_tile_chunk_handlers); diff --git a/src/saveload/cheat_sl.cpp b/src/saveload/cheat_sl.cpp index fde1fc1761..51df50314e 100644 --- a/src/saveload/cheat_sl.cpp +++ b/src/saveload/cheat_sl.cpp @@ -44,6 +44,8 @@ static const SaveLoad _cheats_desc[] = { */ static void Save_CHTS() { + SlSetArrayIndex(0); + SlSetLength(std::size(_cheats_desc)); SlObject(&_cheats, _cheats_desc); } @@ -67,12 +69,14 @@ static void Load_CHTS() if (count == 0) break; } + 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"); } /** Chunk handlers related to cheats. */ static const ChunkHandler cheat_chunk_handlers[] = { - { 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_RIFF }, + { 'CHTS', Save_CHTS, Load_CHTS, nullptr, nullptr, CH_ARRAY }, }; extern const ChunkHandlerTable _cheat_chunk_handlers(cheat_chunk_handlers); diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index 82e3014ad5..7a0f536b23 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -51,13 +51,17 @@ static const SaveLoad _economy_desc[] = { /** Economy variables */ static void Save_ECMY() { + SlSetArrayIndex(0); SlObject(&_economy, _economy_desc); } /** Economy variables */ static void Load_ECMY() { + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; SlObject(&_economy, _economy_desc); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many ECMY entries"); + StartupIndustryDailyChanges(IsSavegameVersionBefore(SLV_102)); // old savegames will need to be initialized } @@ -98,7 +102,7 @@ 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 }, + { 'ECMY', Save_ECMY, Load_ECMY, nullptr, nullptr, CH_ARRAY }, }; extern const ChunkHandlerTable _economy_chunk_handlers(economy_chunk_handlers); diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index 76a81e167c..48281ed665 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -57,14 +57,14 @@ static void Load_GSDT() /* 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); if (_networking && !_network_server) { GameInstance::LoadEmpty(); - if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs"); + if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs"); return; } @@ -99,7 +99,7 @@ static void Load_GSDT() Game::StartNew(); Game::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() diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index c75674069e..1043023b1d 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -139,12 +139,21 @@ static const SaveLoad _industry_builder_desc[] = { SLEG_VAR(_industry_builder.wanted_inds, SLE_UINT32), }; -/** Load/save industry builder. */ -static void LoadSave_IBLD() +/** Save industry builder. */ +static void Save_IBLD() { + SlSetArrayIndex(0); SlGlobList(_industry_builder_desc); } +/** Load industry builder. */ +static void Load_IBLD() +{ + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(_industry_builder_desc); + 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[] = { SLE_VAR(IndustryTypeBuildData, probability, SLE_UINT32), @@ -177,11 +186,11 @@ static void Load_ITBL() } 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 }, + { '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', Save_IBLD, Load_IBLD, nullptr, nullptr, CH_ARRAY }, + { 'ITBL', Save_ITBL, Load_ITBL, nullptr, nullptr, CH_ARRAY }, }; extern const ChunkHandlerTable _industry_chunk_handlers(industry_chunk_handlers); diff --git a/src/saveload/linkgraph_sl.cpp b/src/saveload/linkgraph_sl.cpp index fc72d43832..7000946daf 100644 --- a/src/saveload/linkgraph_sl.cpp +++ b/src/saveload/linkgraph_sl.cpp @@ -287,6 +287,7 @@ static void Load_LGRJ() */ static void Save_LGRS() { + SlSetArrayIndex(0); SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); } @@ -295,7 +296,9 @@ static void Save_LGRS() */ static void Load_LGRS() { + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc()); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries"); } /** @@ -309,7 +312,7 @@ static void Ptrs_LGRS() 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 } + { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, nullptr, CH_ARRAY }, }; extern const ChunkHandlerTable _linkgraph_chunk_handlers(linkgraph_chunk_handlers); diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 5924f4440a..de043d5137 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -20,7 +20,7 @@ static uint32 _map_dim_x; static uint32 _map_dim_y; -static const SaveLoad _map_dimensions[] = { +static const SaveLoad _map_desc[] = { SLEG_CONDVAR(_map_dim_x, SLE_UINT32, SLV_6, SL_MAX_VERSION), SLEG_CONDVAR(_map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION), }; @@ -29,18 +29,26 @@ static void Save_MAPS() { _map_dim_x = MapSizeX(); _map_dim_y = MapSizeY(); - SlGlobList(_map_dimensions); + + SlSetArrayIndex(0); + SlGlobList(_map_desc); } static void Load_MAPS() { - SlGlobList(_map_dimensions); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(_map_desc); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many MAPS entries"); + AllocateMap(_map_dim_x, _map_dim_y); } static void Check_MAPS() { - SlGlobList(_map_dimensions); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; + SlGlobList(_map_desc); + 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; } @@ -295,7 +303,7 @@ static void Save_MAP8() static const ChunkHandler map_chunk_handlers[] = { - { 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_RIFF }, + { 'MAPS', Save_MAPS, Load_MAPS, nullptr, Check_MAPS, CH_ARRAY }, { 'MAPT', Save_MAPT, Load_MAPT, nullptr, nullptr, CH_RIFF }, { 'MAPH', Save_MAPH, Load_MAPH, nullptr, nullptr, CH_RIFF }, { 'MAPO', Save_MAP1, Load_MAP1, nullptr, nullptr, CH_RIFF }, diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index 027d68bae4..4c66f4e26a 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -118,14 +118,28 @@ static const SaveLoad _date_check_desc[] = { /* Save load date related variables as well as persistent tick counters * XXX: currently some unrelated stuff is just put here */ -static void SaveLoad_DATE() +static void Save_DATE() { + SlSetArrayIndex(0); SlGlobList(_date_desc); } +static void Load_DATE_common(const SaveLoadTable &slt) +{ + 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 void Load_DATE() +{ + Load_DATE_common(_date_desc); +} + static void Check_DATE() { - SlGlobList(_date_check_desc); + Load_DATE_common(_date_check_desc); + if (IsSavegameVersionBefore(SLV_31)) { _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR; } @@ -140,14 +154,22 @@ static const SaveLoad _view_desc[] = { SLEG_VAR(_saved_scrollpos_zoom, SLE_UINT8), }; -static void SaveLoad_VIEW() +static void Save_VIEW() +{ + SlSetArrayIndex(0); + SlGlobList(_view_desc); +} + +static void Load_VIEW() { + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; SlGlobList(_view_desc); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many DATE entries"); } 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 }, + { 'DATE', Save_DATE, Load_DATE, nullptr, Check_DATE, CH_ARRAY }, + { 'VIEW', Save_VIEW, Load_VIEW, nullptr, nullptr, CH_ARRAY }, }; extern const ChunkHandlerTable _misc_chunk_handlers(misc_chunk_handlers); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 559876b97b..1a4cb46e82 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -331,6 +331,7 @@ enum SaveLoadVersion : uint16 { SLV_GROUP_REPLACE_WAGON_REMOVAL, ///< 291 PR#7441 Per-group wagon removal flag. SLV_CUSTOM_SUBSIDY_DURATION, ///< 292 PR#9081 Configurable subsidy duration. SLV_SAVELOAD_LIST_LENGTH, ///< 293 PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST. + SLV_RIFF_TO_ARRAY, ///< 294 PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/settings.cpp b/src/settings.cpp index 54189a0fce..1695499559 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2045,7 +2045,9 @@ static void LoadSettings(const SettingTable &settings, void *object) { const std::vector slt = GetSettingsDesc(settings, true); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() == -1) return; SlObject(object, slt); + if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many settings entries"); /* Ensure all IntSettings are valid (min/max could have changed between versions etc). */ for (auto &sd : settings) { @@ -2070,6 +2072,7 @@ static void SaveSettings(const SettingTable &settings, void *object) { const std::vector slt = GetSettingsDesc(settings, false); + SlSetArrayIndex(0); SlObject(object, slt); } @@ -2102,8 +2105,8 @@ static void Save_PATS() } static const ChunkHandler setting_chunk_handlers[] = { - { 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_RIFF }, - { 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_RIFF }, + { 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_RIFF }, + { 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_ARRAY }, }; extern const ChunkHandlerTable _setting_chunk_handlers(setting_chunk_handlers); From 4c4b55ecbdb6206afef7f20d905de2f2a343959a Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 12 Jun 2021 17:12:35 +0200 Subject: [PATCH 09/53] Change: rework GLOG chunk to be more like the rest Basically it is very similar to Vehicles, where there first is a type field, followed by data of that type. So this commit makes it looks like how Vehicles solved that. This removes a lot of custom "keeping track of length" stuff. --- src/gamelog.h | 2 +- src/gamelog_internal.h | 2 +- src/saveload/gamelog_sl.cpp | 366 ++++++++++++++++++++++++++---------- 3 files changed, 270 insertions(+), 100 deletions(-) diff --git a/src/gamelog.h b/src/gamelog.h index d9e0dd529e..cfa6c626a2 100644 --- a/src/gamelog.h +++ b/src/gamelog.h @@ -13,7 +13,7 @@ #include "newgrf_config.h" /** The actions we log. */ -enum GamelogActionType { +enum GamelogActionType : uint8 { GLAT_START, ///< Game created GLAT_LOAD, ///< Game loaded GLAT_GRF, ///< GRF changed diff --git a/src/gamelog_internal.h b/src/gamelog_internal.h index 2b5c6ed0a1..fb7c88e48c 100644 --- a/src/gamelog_internal.h +++ b/src/gamelog_internal.h @@ -13,7 +13,7 @@ #include "gamelog.h" /** Type of logged change */ -enum GamelogChangeType { +enum GamelogChangeType : uint8 { GLCT_MODE, ///< Scenario editor x Game, different landscape GLCT_REVISION, ///< Changed game revision string GLCT_OLDVER, ///< Loaded from savegame without logged data diff --git a/src/saveload/gamelog_sl.cpp b/src/saveload/gamelog_sl.cpp index 6569954f87..9f7f4f140d 100644 --- a/src/saveload/gamelog_sl.cpp +++ b/src/saveload/gamelog_sl.cpp @@ -15,147 +15,317 @@ #include "../safeguards.h" -static const SaveLoad _glog_action_desc[] = { - SLE_VAR(LoggedAction, tick, SLE_UINT16), -}; -static const SaveLoad _glog_mode_desc[] = { - SLE_VAR(LoggedChange, mode.mode, SLE_UINT8), - SLE_VAR(LoggedChange, mode.landscape, SLE_UINT8), -}; +class SlGamelogMode : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, mode.mode, SLE_UINT8), + SLE_VAR(LoggedChange, mode.landscape, SLE_UINT8), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_MODE) return; + SlObject(lc, this->GetDescription()); + } -static const SaveLoad _glog_revision_desc[] = { - SLE_ARR(LoggedChange, revision.text, SLE_UINT8, GAMELOG_REVISION_LENGTH), - SLE_VAR(LoggedChange, revision.newgrf, SLE_UINT32), - SLE_VAR(LoggedChange, revision.slver, SLE_UINT16), - SLE_VAR(LoggedChange, revision.modified, SLE_UINT8), + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_oldver_desc[] = { - SLE_VAR(LoggedChange, oldver.type, SLE_UINT32), - SLE_VAR(LoggedChange, oldver.version, SLE_UINT32), -}; +class SlGamelogRevision : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_ARR(LoggedChange, revision.text, SLE_UINT8, GAMELOG_REVISION_LENGTH), + SLE_VAR(LoggedChange, revision.newgrf, SLE_UINT32), + SLE_VAR(LoggedChange, revision.slver, SLE_UINT16), + SLE_VAR(LoggedChange, revision.modified, SLE_UINT8), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_REVISION) return; + SlObject(lc, this->GetDescription()); + } -static const SaveLoad _glog_setting_desc[] = { - SLE_STR(LoggedChange, setting.name, SLE_STR, 128), - SLE_VAR(LoggedChange, setting.oldval, SLE_INT32), - SLE_VAR(LoggedChange, setting.newval, SLE_INT32), + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_grfadd_desc[] = { - SLE_VAR(LoggedChange, grfadd.grfid, SLE_UINT32 ), - SLE_ARR(LoggedChange, grfadd.md5sum, SLE_UINT8, 16), +class SlGamelogOldver : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, oldver.type, SLE_UINT32), + SLE_VAR(LoggedChange, oldver.version, SLE_UINT32), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_OLDVER) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_grfrem_desc[] = { - SLE_VAR(LoggedChange, grfrem.grfid, SLE_UINT32), +class SlGamelogSetting : public DefaultSaveLoadHandler { +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), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_SETTING) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_grfcompat_desc[] = { - SLE_VAR(LoggedChange, grfcompat.grfid, SLE_UINT32 ), - SLE_ARR(LoggedChange, grfcompat.md5sum, SLE_UINT8, 16), +class SlGamelogGrfadd : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, grfadd.grfid, SLE_UINT32 ), + SLE_ARR(LoggedChange, grfadd.md5sum, SLE_UINT8, 16), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_GRFADD) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_grfparam_desc[] = { - SLE_VAR(LoggedChange, grfparam.grfid, SLE_UINT32), +class SlGamelogGrfrem : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, grfrem.grfid, SLE_UINT32), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_GRFREM) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_grfmove_desc[] = { - SLE_VAR(LoggedChange, grfmove.grfid, SLE_UINT32), - SLE_VAR(LoggedChange, grfmove.offset, SLE_INT32), +class SlGamelogGrfcompat : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, grfcompat.grfid, SLE_UINT32 ), + SLE_ARR(LoggedChange, grfcompat.md5sum, SLE_UINT8, 16), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_GRFCOMPAT) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static const SaveLoad _glog_grfbug_desc[] = { - SLE_VAR(LoggedChange, grfbug.data, SLE_UINT64), - SLE_VAR(LoggedChange, grfbug.grfid, SLE_UINT32), - SLE_VAR(LoggedChange, grfbug.bug, SLE_UINT8), +class SlGamelogGrfparam : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, grfparam.grfid, SLE_UINT32), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_GRFPARAM) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(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. +class SlGamelogGrfmove : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_VAR(LoggedChange, grfmove.grfid, SLE_UINT32), + SLE_VAR(LoggedChange, grfmove.offset, SLE_INT32), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_GRFMOVE) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(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 SlGamelogGrfbug : public DefaultSaveLoadHandler { +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), + }; + + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_GRFBUG) return; + SlObject(lc, this->GetDescription()); + } + + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } }; -static_assert(lengthof(_glog_desc) == GLCT_END); +static bool _is_emergency_save = true; -static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_actions) -{ - assert(gamelog_action == nullptr); - assert(gamelog_actions == 0); +class SlGamelogEmergency : public DefaultSaveLoadHandler { +public: + /* We need to store something, so store a "true" value. */ + inline static const SaveLoad description[] = { + SLEG_CONDVAR(_is_emergency_save, SLE_BOOL, SLV_RIFF_TO_ARRAY, SL_MAX_VERSION), + }; - byte type; - while ((type = SlReadByte()) != GLAT_NONE) { - if (type >= GLAT_END) SlErrorCorrupt("Invalid gamelog action type"); - GamelogActionType at = (GamelogActionType)type; + void GenericSaveLoad(LoggedChange *lc) const + { + if (lc->ct != GLCT_EMERGENCY) return; - gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1); - LoggedAction *la = &gamelog_action[gamelog_actions++]; + _is_emergency_save = true; + SlObject(lc, this->GetDescription()); + } - la->at = at; + void Save(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void Load(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } + void LoadCheck(LoggedChange *lc) const override { this->GenericSaveLoad(lc); } +}; - SlObject(la, _glog_action_desc); // has to be saved after 'DATE'! - la->change = nullptr; - la->changes = 0; +class SlGamelogAction : public DefaultSaveLoadHandler { +public: + inline static const SaveLoad description[] = { + SLE_SAVEBYTE(LoggedChange, ct), + SLEG_STRUCT(SlGamelogMode), + SLEG_STRUCT(SlGamelogRevision), + SLEG_STRUCT(SlGamelogOldver), + SLEG_STRUCT(SlGamelogSetting), + SLEG_STRUCT(SlGamelogGrfadd), + SLEG_STRUCT(SlGamelogGrfrem), + SLEG_STRUCT(SlGamelogGrfcompat), + SLEG_STRUCT(SlGamelogGrfparam), + SLEG_STRUCT(SlGamelogGrfmove), + SLEG_STRUCT(SlGamelogGrfbug), + SLEG_STRUCT(SlGamelogEmergency), + }; + + void Save(LoggedAction *la) const override + { + SlSetStructListLength(la->changes); - while ((type = SlReadByte()) != GLCT_NONE) { - if (type >= GLCT_END) SlErrorCorrupt("Invalid gamelog change type"); - GamelogChangeType ct = (GamelogChangeType)type; + 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); + 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 */ + LoggedChange *lc = &la->change[la->changes++]; + memset(lc, 0, sizeof(*lc)); + lc->ct = ct; + + SlObject(lc, this->GetDescription()); + } + return; + } + + size_t length = SlGetStructListLength(UINT32_MAX); + la->change = ReallocT(la->change, length); + + for (size_t i = 0; i < length; i++) { + LoggedChange *lc = &la->change[i]; memset(lc, 0, sizeof(*lc)); - lc->ct = ct; - SlObject(lc, _glog_desc[ct]); + lc->ct = (GamelogChangeType)SlReadByte(); + SlObject(lc, this->GetDescription()); } } -} -static void Save_GLOG() + 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_VAR(LoggedAction, tick, SLE_UINT16), + SLEG_STRUCTLIST(SlGamelogAction), +}; + +static void Load_GLOG_common(LoggedAction *&gamelog_action, uint &gamelog_actions) { - const LoggedAction *laend = &_gamelog_action[_gamelog_actions]; - size_t length = 0; + assert(gamelog_action == nullptr); + assert(gamelog_actions == 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; + 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, _gamelog_desc); } - length += 4; + return; } - length++; - SlSetLength(length); + while (SlIterateArray() != -1) { + gamelog_action = ReallocT(gamelog_action, gamelog_actions + 1); + LoggedAction *la = &gamelog_action[gamelog_actions++]; + memset(la, 0, sizeof(*la)); - for (LoggedAction *la = _gamelog_action; la != laend; la++) { - SlWriteByte(la->at); - SlObject(la, _glog_action_desc); + SlObject(la, _gamelog_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]); - } - SlWriteByte(GLCT_NONE); +static void Save_GLOG() +{ + 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); } - SlWriteByte(GLAT_NONE); } static void Load_GLOG() @@ -169,7 +339,7 @@ static void Check_GLOG() } static const ChunkHandler gamelog_chunk_handlers[] = { - { 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_RIFF } + { 'GLOG', Save_GLOG, Load_GLOG, nullptr, Check_GLOG, CH_ARRAY } }; extern const ChunkHandlerTable _gamelog_chunk_handlers(gamelog_chunk_handlers); From 8e91527251c8190889abbfe80ee35f9fef057a94 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Mon, 14 Jun 2021 13:57:53 +0200 Subject: [PATCH 10/53] Codechange: mark chunks that are not stored as CH_READONLY This makes it easier to spot chunks that have a save_proc that is a nullptr, but also prevents confusion, where it looks like the CH_ type of a chunk has influence on how it is being read. It is not, it is only used for saving. --- src/saveload/economy_sl.cpp | 4 ++-- src/saveload/engine_sl.cpp | 2 +- src/saveload/saveload.cpp | 6 +++--- src/saveload/saveload.h | 1 + src/saveload/station_sl.cpp | 2 +- src/saveload/strings_sl.cpp | 2 +- src/saveload/waypoint_sl.cpp | 2 +- src/settings.cpp | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index 7a0f536b23..d8624f5d66 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -100,8 +100,8 @@ static void Ptrs_CAPY() 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 }, + { 'PRIC', nullptr, Load_PRIC, nullptr, nullptr, CH_READONLY }, + { 'CAPR', nullptr, Load_CAPR, nullptr, nullptr, CH_READONLY }, { 'ECMY', Save_ECMY, Load_ECMY, nullptr, nullptr, CH_ARRAY }, }; diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index 336c932826..12670449e8 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -196,7 +196,7 @@ static void Load_EIDS() 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 }, + { 'ENGS', nullptr, Load_ENGS, nullptr, nullptr, CH_READONLY }, }; extern const ChunkHandlerTable _engine_chunk_handlers(engine_chunk_handlers); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 9b177dd0d9..2184ef85b9 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1897,10 +1897,10 @@ static void SlLoadCheckChunk(const ChunkHandler &ch) */ static void SlSaveChunk(const ChunkHandler &ch) { - ChunkSaveLoadProc *proc = ch.save_proc; + if (ch.type == CH_READONLY) return; - /* Don't save any chunk information if there is no save handler. */ - if (proc == nullptr) return; + ChunkSaveLoadProc *proc = ch.save_proc; + assert(proc != nullptr); SlWriteUint32(ch.id); Debug(sl, 2, "Saving chunk {:c}{:c}{:c}{:c}", ch.id >> 24, ch.id >> 16, ch.id >> 8, ch.id); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 1a4cb46e82..dfd687f356 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -388,6 +388,7 @@ enum ChunkType { CH_RIFF = 0, CH_ARRAY = 1, CH_SPARSE_ARRAY = 2, + CH_READONLY, ///< Chunk is never saved. }; /** Handlers and description of chunk. */ diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 7144c5de4f..a536c02db4 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -703,7 +703,7 @@ static void Ptrs_ROADSTOP() } static const ChunkHandler station_chunk_handlers[] = { - { 'STNS', nullptr, Load_STNS, Ptrs_STNS, nullptr, CH_ARRAY }, + { 'STNS', nullptr, Load_STNS, Ptrs_STNS, nullptr, CH_READONLY }, { 'STNN', Save_STNN, Load_STNN, Ptrs_STNN, nullptr, CH_ARRAY }, { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, nullptr, CH_ARRAY }, }; diff --git a/src/saveload/strings_sl.cpp b/src/saveload/strings_sl.cpp index c4f56ed432..784d89d8fd 100644 --- a/src/saveload/strings_sl.cpp +++ b/src/saveload/strings_sl.cpp @@ -132,7 +132,7 @@ static void Load_NAME() /** Chunk handlers related to strings. */ static const ChunkHandler name_chunk_handlers[] = { - { 'NAME', nullptr, Load_NAME, nullptr, nullptr, CH_ARRAY }, + { 'NAME', nullptr, Load_NAME, nullptr, nullptr, CH_READONLY }, }; extern const ChunkHandlerTable _name_chunk_handlers(name_chunk_handlers); diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index c94a909537..8105cc1901 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -225,7 +225,7 @@ static void Ptrs_WAYP() } static const ChunkHandler waypoint_chunk_handlers[] = { - { 'CHKP', nullptr, Load_WAYP, Ptrs_WAYP, nullptr, CH_ARRAY }, + { 'CHKP', nullptr, Load_WAYP, Ptrs_WAYP, nullptr, CH_READONLY }, }; extern const ChunkHandlerTable _waypoint_chunk_handlers(waypoint_chunk_handlers); diff --git a/src/settings.cpp b/src/settings.cpp index 1695499559..dab0fe08cb 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -2105,7 +2105,7 @@ static void Save_PATS() } static const ChunkHandler setting_chunk_handlers[] = { - { 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_RIFF }, + { 'OPTS', nullptr, Load_OPTS, nullptr, nullptr, CH_READONLY }, { 'PATS', Save_PATS, Load_PATS, nullptr, Check_PATS, CH_ARRAY }, }; From b560620eb9a63813cba1f8eccdb7424c5d2532b5 Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 15 Jun 2021 18:57:22 +0000 Subject: [PATCH 11/53] Update: Translations from eints spanish: 3 changes by MontyMontana hindi: 28 changes by ritwikraghav14 --- src/lang/hindi.txt | 29 ++++++++++++++++++++++++++++- src/lang/spanish.txt | 3 +++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/lang/hindi.txt b/src/lang/hindi.txt index b993e19477..1fabeb2892 100644 --- a/src/lang/hindi.txt +++ b/src/lang/hindi.txt @@ -19,11 +19,26 @@ ##id 0x0000 STR_NULL : STR_EMPTY : +STR_UNDEFINED :(अपरिभाषित सूत्र) +STR_JUST_NOTHING :कुछ नहीं # Cargo related strings # Plural cargo name STR_CARGO_PLURAL_NOTHING : +STR_CARGO_PLURAL_PASSENGERS :यात्रीगण STR_CARGO_PLURAL_COAL :कोयला +STR_CARGO_PLURAL_MAIL :डाक +STR_CARGO_PLURAL_OIL :तेल +STR_CARGO_PLURAL_LIVESTOCK :पशुधन +STR_CARGO_PLURAL_GOODS :वस्तुएं +STR_CARGO_PLURAL_GRAIN :अन्न +STR_CARGO_PLURAL_WOOD :काष्ठ +STR_CARGO_PLURAL_IRON_ORE :लौह अयस्क +STR_CARGO_PLURAL_STEEL :इस्पात +STR_CARGO_PLURAL_VALUABLES :मूल्यवान वस्तुएं +STR_CARGO_PLURAL_COPPER_ORE :ताम्र अयस्क +STR_CARGO_PLURAL_MAIZE :मक्के +STR_CARGO_PLURAL_FRUIT :फल # Singular cargo name STR_CARGO_SINGULAR_NOTHING : @@ -222,7 +237,7 @@ STR_NEWS_NEW_VEHICLE_TYPE :{BIG_FONT}{BLAC # Game options window ############ start of currency region -STR_GAME_OPTIONS_CURRENCY_FIM :मार्का, फिनलैंड (FIM) +STR_GAME_OPTIONS_CURRENCY_FIM :फिनलैंड मार्का (FIM) STR_GAME_OPTIONS_CURRENCY_HKD :हाँग काँग डॉलर (एचकेडी) ############ end of currency region @@ -358,6 +373,9 @@ STR_INTRO_TOOLTIP_SCENARIO_EDITOR :{BLACK}अप STR_QUIT_YES :{BLACK}हाँ # Abandon game +STR_ABANDON_GAME_CAPTION :{WHITE}खेल छोड़ें +STR_ABANDON_GAME_QUERY :{YELLOW}क्या आप वास्तव में खेल छोड़ना चाहते हैं? +STR_ABANDON_SCENARIO_QUERY :{YELLOW}क्या आप वास्तव में यह परिदृश्य छोड़ना चाहते हैं? # Cheat window @@ -418,6 +436,7 @@ STR_NETWORK_GAME_LOBBY_INAUGURATION_YEAR :{SILVER}उद ############ Leave those lines in this order!! ############ End of leave-in-this-order +STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION :{WHITE}संपर्क विच्छेद संभावित # Network related errors ############ Leave those lines in this order!! @@ -463,8 +482,10 @@ STR_CONTENT_ERROR_COULD_NOT_DOWNLOAD :{WHITE}डा STR_STATION_CLASS_DFLT :मानक स्टेशन +STR_STATION_CLASS_WAYP :पथ-संकेत # Signal window +STR_BUILD_SIGNAL_DRAG_SIGNALS_DENSITY_TOOLTIP :{BLACK}खींचते समय संकेतों के बीच की दूरी # Bridge selection window @@ -495,6 +516,7 @@ STR_AIRPORT_CLASS_SMALL :लघु व # Object construction window +STR_OBJECT_CLASS_LTHS :प्रकाश स्तम्भ # Tree planting window (last eight for SE only) @@ -511,10 +533,12 @@ STR_FOUND_TOWN_CITY :{BLACK}शह # Fund new industry window # Industry cargoes window +STR_INDUSTRY_CARGOES_SELECT_INDUSTRY :{BLACK}उद्योग चुनें # Land area window # Description of land area of different tiles +STR_LAI_CLEAR_DESCRIPTION_BARE_LAND :रिक्त भूमि @@ -542,6 +566,7 @@ STR_FRAMERATE_BYTES_BAD :{RED}{BYTES} ############ Leave those lines in this order!! ############ End of leave-in-this-order ############ Leave those lines in this order!! +STR_FRAMETIME_CAPTION_GL_ECONOMY :माल प्रबंधन ############ End of leave-in-this-order @@ -925,6 +950,7 @@ STR_ERROR_TOO_HIGH :{WHITE}... ब # Town related errors STR_ERROR_CAN_T_RENAME_TOWN :{WHITE}नगर का नाम नहीं बदला जा सकता है... +STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... मानचित्र के किनारों के बहुत समीप # Industry related errors STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... वन केवल बर्फ की सीमा के ऊपर ही लगाये जा सकते हैं। @@ -951,6 +977,7 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... व STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}स्वतः नवीनीकरण/बदलाव का कोई भी नियम लागू नहीं किया गया # Rail construction errors +STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}पटरियों को यहाँ से नहीं हटा सकते... # Road construction errors diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 7bbb2507b2..d688ffa9c1 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -885,7 +885,10 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subvención terminada:{}{}{STRING} de {STRING} a {STRING} ya no conlleva una subvención STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvención retirada:{}{}El servicio de {STRING} desde {STRING} a {STRING} ya no está subvencionado STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Se ofrece subvención:{}{}¡Al primer servicio de {STRING} que cubra la línea desde {STRING} a {STRING} se le otorgará una subvención durante {NUM} año{P "" s} por parte de las autoridades locales! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará un 50% más caro durante {NUM} año{P "" s}! STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa doble durante los próximos {NUM} año{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa triple durante {NUM} año{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}¡Subvención otorgada a {STRING}!{}{}¡El servicio de {STRING} desde {STRING} a {STRING} se pagará a tarifa cuádruple durante {NUM} año{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}¡Colapso circulatorio en {TOWN}!{}{}¡El programa de reconstrucción de carreteras patrocinado por {STRING} causa 6 meses de problemas a los conductores! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}¡Monopolio de transportes! From 930bb224168145f942a426dc8404f02f20fa2be0 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 16 Jun 2021 20:47:31 +0200 Subject: [PATCH 12/53] Cleanup: remove lines from station_base.h that are already included in includes base_station_base.h --- src/station_base.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/station_base.h b/src/station_base.h index 4f79dd98c6..c63dcade17 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -21,9 +21,6 @@ #include #include -typedef Pool StationPool; -extern StationPool _station_pool; - static const byte INITIAL_STATION_RATING = 175; /** From 3237e97b3592d4f3920dab556d551da65a465b8d Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 16 Jun 2021 21:10:41 +0200 Subject: [PATCH 13/53] Cleanup: [Script] Use nullptr instead of 0 or NULL --- cmake/scripts/SquirrelExport.cmake | 8 ++++---- src/ai/ai_info.cpp | 4 ++-- src/game/game_info.cpp | 2 +- src/script/api/script_text.cpp | 2 +- src/script/squirrel.cpp | 2 +- src/script/squirrel.hpp | 2 +- src/script/squirrel_helper.hpp | 12 ++++++------ 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cmake/scripts/SquirrelExport.cmake b/cmake/scripts/SquirrelExport.cmake index 3b230de00f..d0c2283550 100644 --- a/cmake/scripts/SquirrelExport.cmake +++ b/cmake/scripts/SquirrelExport.cmake @@ -28,10 +28,10 @@ endmacro() macro(dump_class_templates NAME) string(REGEX REPLACE "^Script" "" REALNAME ${NAME}) - string(APPEND SQUIRREL_EXPORT "\n template <> inline ${NAME} *GetParam(ForceType<${NAME} *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (${NAME} *)instance; }") - string(APPEND SQUIRREL_EXPORT "\n template <> inline ${NAME} &GetParam(ForceType<${NAME} &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(${NAME} *)instance; }") - string(APPEND SQUIRREL_EXPORT "\n template <> inline const ${NAME} *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (${NAME} *)instance; }") - string(APPEND SQUIRREL_EXPORT "\n template <> inline const ${NAME} &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(${NAME} *)instance; }") + string(APPEND SQUIRREL_EXPORT "\n template <> inline ${NAME} *GetParam(ForceType<${NAME} *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return (${NAME} *)instance; }") + string(APPEND SQUIRREL_EXPORT "\n template <> inline ${NAME} &GetParam(ForceType<${NAME} &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return *(${NAME} *)instance; }") + string(APPEND SQUIRREL_EXPORT "\n template <> inline const ${NAME} *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return (${NAME} *)instance; }") + string(APPEND SQUIRREL_EXPORT "\n template <> inline const ${NAME} &GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, nullptr); return *(${NAME} *)instance; }") if("${NAME}" STREQUAL "ScriptEvent") string(APPEND SQUIRREL_EXPORT "\n template <> inline int Return<${NAME} *>(HSQUIRRELVM vm, ${NAME} *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, \"${REALNAME}\", res, nullptr, DefSQDestructorCallback<${NAME}>, true); return 1; }") elseif("${NAME}" STREQUAL "ScriptText") diff --git a/src/ai/ai_info.cpp b/src/ai/ai_info.cpp index dfb2e5fbf5..10d34ea58a 100644 --- a/src/ai/ai_info.cpp +++ b/src/ai/ai_info.cpp @@ -63,7 +63,7 @@ template <> const char *GetClassName() { return "AIInfo"; } { /* Get the AIInfo */ SQUserPointer instance = nullptr; - if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, 0)) || instance == nullptr) return sq_throwerror(vm, "Pass an instance of a child class of AIInfo to RegisterAI"); + if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, nullptr)) || instance == nullptr) return sq_throwerror(vm, "Pass an instance of a child class of AIInfo to RegisterAI"); AIInfo *info = (AIInfo *)instance; SQInteger res = ScriptInfo::Constructor(vm, info); @@ -107,7 +107,7 @@ template <> const char *GetClassName() { return "AIInfo"; } { /* Get the AIInfo */ SQUserPointer instance; - sq_getinstanceup(vm, 2, &instance, 0); + sq_getinstanceup(vm, 2, &instance, nullptr); AIInfo *info = (AIInfo *)instance; info->api_version = nullptr; diff --git a/src/game/game_info.cpp b/src/game/game_info.cpp index 3d07a10c4e..60b4d0dcca 100644 --- a/src/game/game_info.cpp +++ b/src/game/game_info.cpp @@ -54,7 +54,7 @@ template <> const char *GetClassName() { return "GSInfo"; } { /* Get the GameInfo */ SQUserPointer instance = nullptr; - if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, 0)) || instance == nullptr) return sq_throwerror(vm, "Pass an instance of a child class of GameInfo to RegisterGame"); + if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, nullptr)) || instance == nullptr) return sq_throwerror(vm, "Pass an instance of a child class of GameInfo to RegisterGame"); GameInfo *info = (GameInfo *)instance; SQInteger res = ScriptInfo::Constructor(vm, info); diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index eeb7b22212..62980326ce 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -109,7 +109,7 @@ SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm) sq_pop(vm, 3); /* Get the 'real' instance of this class */ - sq_getinstanceup(vm, -1, &real_instance, 0); + sq_getinstanceup(vm, -1, &real_instance, nullptr); if (real_instance == nullptr) return SQ_ERROR; ScriptText *value = static_cast(real_instance); diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index 995776408f..6489c87371 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -256,7 +256,7 @@ void Squirrel::RunError(HSQUIRRELVM vm, const SQChar *error) SQInteger Squirrel::_RunError(HSQUIRRELVM vm) { - const SQChar *sErr = 0; + const SQChar *sErr = nullptr; if (sq_gettop(vm) >= 1) { if (SQ_SUCCEEDED(sq_getstring(vm, -1, &sErr))) { diff --git a/src/script/squirrel.hpp b/src/script/squirrel.hpp index 412011cccc..c1fdc75118 100644 --- a/src/script/squirrel.hpp +++ b/src/script/squirrel.hpp @@ -190,7 +190,7 @@ public: * @note This will only work just after a function-call from within Squirrel * to your C++ function. */ - static bool GetRealInstance(HSQUIRRELVM vm, SQUserPointer *ptr) { return SQ_SUCCEEDED(sq_getinstanceup(vm, 1, ptr, 0)); } + static bool GetRealInstance(HSQUIRRELVM vm, SQUserPointer *ptr) { return SQ_SUCCEEDED(sq_getinstanceup(vm, 1, ptr, nullptr)); } /** * Get the Squirrel-instance pointer. diff --git a/src/script/squirrel_helper.hpp b/src/script/squirrel_helper.hpp index ff25a5d58a..6a3ba6125b 100644 --- a/src/script/squirrel_helper.hpp +++ b/src/script/squirrel_helper.hpp @@ -754,9 +754,9 @@ namespace SQConvert { sq_pop(vm, 3); /* Get the 'real' instance of this class */ - sq_getinstanceup(vm, 1, &real_instance, 0); + sq_getinstanceup(vm, 1, &real_instance, nullptr); /* Get the real function pointer */ - sq_getuserdata(vm, nparam, &ptr, 0); + sq_getuserdata(vm, nparam, &ptr, nullptr); if (real_instance == nullptr) return sq_throwerror(vm, "couldn't detect real instance of class for non-static call"); /* Remove the userdata from the stack */ sq_pop(vm, 1); @@ -796,9 +796,9 @@ namespace SQConvert { sq_pop(vm, 3); /* Get the 'real' instance of this class */ - sq_getinstanceup(vm, 1, &real_instance, 0); + sq_getinstanceup(vm, 1, &real_instance, nullptr); /* Get the real function pointer */ - sq_getuserdata(vm, nparam, &ptr, 0); + sq_getuserdata(vm, nparam, &ptr, nullptr); if (real_instance == nullptr) return sq_throwerror(vm, "couldn't detect real instance of class for non-static call"); /* Remove the userdata from the stack */ sq_pop(vm, 1); @@ -820,7 +820,7 @@ namespace SQConvert { SQUserPointer ptr = nullptr; /* Get the real function pointer */ - sq_getuserdata(vm, nparam, &ptr, 0); + sq_getuserdata(vm, nparam, &ptr, nullptr); try { /* Delegate it to a template that can handle this specific function */ @@ -844,7 +844,7 @@ namespace SQConvert { SQUserPointer ptr = nullptr; /* Get the real function pointer */ - sq_getuserdata(vm, nparam, &ptr, 0); + sq_getuserdata(vm, nparam, &ptr, nullptr); /* Remove the userdata from the stack */ sq_pop(vm, 1); From a9774f3e341812d43427b9e0166b0def08202477 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 16 Jun 2021 21:15:40 +0200 Subject: [PATCH 14/53] Cleanup: [Squirrel] Use nullptr instead of 0 or NULL --- src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp | 4 +- src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp | 4 +- src/3rdparty/squirrel/squirrel/sqapi.cpp | 46 ++++++++--------- src/3rdparty/squirrel/squirrel/sqbaselib.cpp | 50 +++++++++---------- src/3rdparty/squirrel/squirrel/sqclass.cpp | 10 ++-- src/3rdparty/squirrel/squirrel/sqclosure.h | 2 +- src/3rdparty/squirrel/squirrel/sqcompiler.cpp | 4 +- src/3rdparty/squirrel/squirrel/sqlexer.cpp | 4 +- src/3rdparty/squirrel/squirrel/sqobject.cpp | 10 ++-- src/3rdparty/squirrel/squirrel/sqobject.h | 6 +-- src/3rdparty/squirrel/squirrel/sqstate.cpp | 44 ++++++++-------- src/3rdparty/squirrel/squirrel/sqtable.cpp | 12 ++--- src/3rdparty/squirrel/squirrel/sqtable.h | 8 +-- src/3rdparty/squirrel/squirrel/squserdata.h | 6 +-- src/3rdparty/squirrel/squirrel/squtils.h | 2 +- src/3rdparty/squirrel/squirrel/sqvm.cpp | 18 +++---- 16 files changed, 115 insertions(+), 115 deletions(-) diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp index a4f4e21c33..4eaa2cb3cd 100644 --- a/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp +++ b/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp @@ -17,7 +17,7 @@ void sqstd_printcallstack(HSQUIRRELVM v) SQFloat f; const SQChar *s; SQInteger level=1; //1 is to skip this function that is level 0 - const SQChar *name=0; + const SQChar *name=nullptr; SQInteger seq=0; pf(v,"\nCALLSTACK\n"); while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si))) @@ -116,7 +116,7 @@ static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v) { SQPRINTFUNCTION pf = sq_getprintfunc(v); if(pf) { - const SQChar *sErr = 0; + const SQChar *sErr = nullptr; if(sq_gettop(v)>=1) { if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { pf(v,"\nAN ERROR HAS OCCURRED [%s]\n",sErr); diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp index 0ff0090209..3ba6811a6c 100644 --- a/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp +++ b/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp @@ -88,7 +88,7 @@ static SQRegFunction mathlib_funcs[] = { #endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */ _DECL_FUNC(fabs,2,".n"), _DECL_FUNC(abs,2,".n"), - {0,0,0,0}, + {nullptr,nullptr,0,nullptr}, }; #ifndef M_PI @@ -98,7 +98,7 @@ static SQRegFunction mathlib_funcs[] = { SQRESULT sqstd_register_mathlib(HSQUIRRELVM v) { SQInteger i=0; - while(mathlib_funcs[i].name!=0) { + while(mathlib_funcs[i].name!=nullptr) { sq_pushstring(v,mathlib_funcs[i].name,-1); sq_newclosure(v,mathlib_funcs[i].f,0); sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); diff --git a/src/3rdparty/squirrel/squirrel/sqapi.cpp b/src/3rdparty/squirrel/squirrel/sqapi.cpp index 0d769bf1f7..aeef3779b6 100644 --- a/src/3rdparty/squirrel/squirrel/sqapi.cpp +++ b/src/3rdparty/squirrel/squirrel/sqapi.cpp @@ -60,11 +60,11 @@ HSQUIRRELVM sq_open(SQInteger initialstacksize) v = (SQVM *)SQ_MALLOC(sizeof(SQVM)); new (v) SQVM(ss); ss->_root_vm = v; - if(v->Init(NULL, initialstacksize)) { + if(v->Init(nullptr, initialstacksize)) { return v; } else { sq_delete(v, SQVM); - return NULL; + return nullptr; } return v; } @@ -83,7 +83,7 @@ HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize) return v; } else { sq_delete(v, SQVM); - return NULL; + return nullptr; } } @@ -178,7 +178,7 @@ const SQChar *sq_objtostring(HSQOBJECT *o) if(sq_type(*o) == OT_STRING) { return _stringval(*o); } - return NULL; + return nullptr; } SQInteger sq_objtointeger(HSQOBJECT *o) @@ -256,7 +256,7 @@ void sq_newarray(HSQUIRRELVM v,SQInteger size) SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase) { - SQClass *baseclass = NULL; + SQClass *baseclass = nullptr; if(hasbase) { SQObjectPtr &base = stack_get(v,-1); if(type(base) != OT_CLASS) @@ -555,7 +555,7 @@ SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b) SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_STRING,o); *c = _stringval(*o); return SQ_OK; @@ -563,7 +563,7 @@ SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c) SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_THREAD,o); *thread = _thread(*o); return SQ_OK; @@ -598,7 +598,7 @@ SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx) SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_USERDATA,o); (*p) = _userdataval(*o); if(typetag) *typetag = _userdata(*o)->_typetag; @@ -637,7 +637,7 @@ SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag) SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o); (*p) = _userpointer(*o); return SQ_OK; @@ -666,13 +666,13 @@ SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserP SQObjectPtr &o = stack_get(v,idx); if(type(o) != OT_INSTANCE) return sq_throwerror(v,"the object is not a class instance"); (*p) = _instance(o)->_userpointer; - if(typetag != 0) { + if(typetag != nullptr) { SQClass *cl = _instance(o)->_class; do{ if(cl->_typetag == typetag) return SQ_OK; cl = cl->_base; - }while(cl != NULL); + }while(cl != nullptr); return sq_throwerror(v,"invalid type tag"); } return SQ_OK; @@ -801,14 +801,14 @@ SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx) if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, "delagate cycle"); v->Pop();} else if(type(mt)==OT_NULL) { - _table(self)->SetDelegate(NULL); v->Pop(); } + _table(self)->SetDelegate(nullptr); v->Pop(); } else return sq_aux_invalidtype(v,type); break; case OT_USERDATA: if(type(mt)==OT_TABLE) { _userdata(self)->SetDelegate(_table(mt)); v->Pop(); } else if(type(mt)==OT_NULL) { - _userdata(self)->SetDelegate(NULL); v->Pop(); } + _userdata(self)->SetDelegate(nullptr); v->Pop(); } else return sq_aux_invalidtype(v, type); break; default: @@ -909,7 +909,7 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege } SQVM::CallInfo &ci=v->_callsstack[lvl]; if(type(ci._closure)!=OT_CLOSURE) - return NULL; + return nullptr; SQClosure *c=_closure(ci._closure); SQFunctionProto *func=_funcproto(c->_function); if(func->_noutervalues > (SQInteger)idx) { @@ -919,7 +919,7 @@ const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedIntege idx -= func->_noutervalues; return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1); } - return NULL; + return nullptr; } void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj) @@ -929,7 +929,7 @@ void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj) void sq_resetobject(HSQOBJECT *po) { - po->_unVal.pUserPointer=NULL;po->_type=OT_NULL; + po->_unVal.pUserPointer=nullptr;po->_type=OT_NULL; } SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) @@ -1051,7 +1051,7 @@ void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f) SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); unsigned short tag = SQ_BYTECODE_STREAM_TAG; if(w(up,&tag,2) != 2) @@ -1093,7 +1093,7 @@ SQInteger sq_collectgarbage(HSQUIRRELVM v) const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) { SQObjectPtr &self = stack_get(v,idx); - const SQChar *name = NULL; + const SQChar *name = nullptr; if(type(self) == OT_CLOSURE) { if(_closure(self)->_outervalues.size()>nval) { v->Push(_closure(self)->_outervalues[nval]); @@ -1131,7 +1131,7 @@ SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_CLASS,o); SQObjectPtr &key = stack_get(v,-2); SQObjectPtr &val = stack_get(v,-1); @@ -1153,7 +1153,7 @@ SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx) SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_CLASS,o); SQObjectPtr &key = stack_get(v,-1); SQObjectPtr attrs; @@ -1173,7 +1173,7 @@ SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_CLASS,o); if(_class(*o)->_base) v->Push(SQObjectPtr(_class(*o)->_base)); @@ -1184,7 +1184,7 @@ SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_INSTANCE,o); v->Push(SQObjectPtr(_instance(*o)->_class)); return SQ_OK; @@ -1192,7 +1192,7 @@ SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx) SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx) { - SQObjectPtr *o = NULL; + SQObjectPtr *o = nullptr; _GETSAFE_OBJ(v, idx, OT_CLASS,o); v->Push(_class(*o)->CreateInstance()); return SQ_OK; diff --git a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp index 232c27d2be..c542ee5a47 100644 --- a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp +++ b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp @@ -248,29 +248,29 @@ static SQRegFunction base_funcs[]={ {"getconsttable",base_getconsttable,1, NULL}, {"setconsttable",base_setconsttable,2, NULL}, #endif - {"assert",base_assert,2, NULL}, - {"print",base_print,2, NULL}, + {"assert",base_assert,2, nullptr}, + {"print",base_print,2, nullptr}, #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS {"compilestring",base_compilestring,-2, ".ss"}, {"newthread",base_newthread,2, ".c"}, {"suspend",base_suspend,-1, NULL}, #endif {"array",base_array,-2, ".n"}, - {"type",base_type,2, NULL}, + {"type",base_type,2, nullptr}, #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS {"dummy",base_dummy,0,NULL}, #ifndef NO_GARBAGE_COLLECTOR {"collectgarbage",base_collectgarbage,1, "t"}, #endif #endif - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; void sq_base_register(HSQUIRRELVM v) { SQInteger i=0; sq_pushroottable(v); - while(base_funcs[i].name!=0) { + while(base_funcs[i].name!=nullptr) { sq_pushstring(v,base_funcs[i].name,-1); sq_newclosure(v,base_funcs[i].f,0); sq_setnativeclosurename(v,-1,base_funcs[i].name); @@ -415,10 +415,10 @@ SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ {"rawset",table_rawset,3, "t"}, {"rawdelete",table_rawdelete,2, "t"}, {"rawin",container_rawexists,2, "t"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, {"clear",obj_clear,1, "."}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; //ARRAY DEFAULT DELEGATE/////////////////////////////////////// @@ -624,10 +624,10 @@ SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ {"reverse",array_reverse,1, "a"}, {"sort",array_sort,-1, "ac"}, {"slice",array_slice,-1, "ann"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, {"clear",obj_clear,1, "."}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; //STRING DEFAULT DELEGATE////////////////////////// @@ -687,8 +687,8 @@ SQRegFunction SQSharedState::_string_default_delegate_funcz[]={ {"find",string_find,-2, "s s n "}, {"tolower",string_tolower,1, "s"}, {"toupper",string_toupper,1, "s"}, - {"weakref",obj_delegate_weakref,1, NULL }, - {0,0,0,0} + {"weakref",obj_delegate_weakref,1, nullptr }, + {nullptr,nullptr,0,nullptr} }; //INTEGER DEFAULT DELEGATE////////////////////////// @@ -697,8 +697,8 @@ SQRegFunction SQSharedState::_number_default_delegate_funcz[]={ {"tofloat",default_delegate_tofloat,1, "n|b"}, {"tostring",default_delegate_tostring,1, "."}, {"tochar",number_delegate_tochar,1, "n|b"}, - {"weakref",obj_delegate_weakref,1, NULL }, - {0,0,0,0} + {"weakref",obj_delegate_weakref,1, nullptr }, + {nullptr,nullptr,0,nullptr} }; //CLOSURE DEFAULT DELEGATE////////////////////////// @@ -782,11 +782,11 @@ SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={ {"pcall",closure_pcall,-1, "c"}, {"acall",closure_acall,2, "ca"}, {"pacall",closure_pacall,2, "ca"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, {"bindenv",closure_bindenv,2, "c x|y|t"}, {"getinfos",closure_getinfos,1, "c"}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; //GENERATOR DEFAULT DELEGATE @@ -803,9 +803,9 @@ static SQInteger generator_getstatus(HSQUIRRELVM v) SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={ {"getstatus",generator_getstatus,1, "g"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; //THREAD DEFAULT DELEGATE @@ -889,9 +889,9 @@ SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { {"call", thread_call, -1, "v"}, {"wakeup", thread_wakeup, -1, "v"}, {"getstatus", thread_getstatus, 1, "v"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, - {0,0,0,0}, + {nullptr,nullptr,0,nullptr}, }; static SQInteger class_getattributes(HSQUIRRELVM v) @@ -919,10 +919,10 @@ SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { {"getattributes", class_getattributes, 2, "y."}, {"setattributes", class_setattributes, 3, "y.."}, {"rawin",container_rawexists,2, "y"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, {"instance",class_instance,1, "y"}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; static SQInteger instance_getclass(HSQUIRRELVM v) @@ -935,9 +935,9 @@ static SQInteger instance_getclass(HSQUIRRELVM v) SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { {"getclass", instance_getclass, 1, "x"}, {"rawin",container_rawexists,2, "x"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; static SQInteger weakref_ref(HSQUIRRELVM v) @@ -949,9 +949,9 @@ static SQInteger weakref_ref(HSQUIRRELVM v) SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = { {"ref",weakref_ref,1, "r"}, - {"weakref",obj_delegate_weakref,1, NULL }, + {"weakref",obj_delegate_weakref,1, nullptr }, {"tostring",default_delegate_tostring,1, "."}, - {0,0,0,0} + {nullptr,nullptr,0,nullptr} }; diff --git a/src/3rdparty/squirrel/squirrel/sqclass.cpp b/src/3rdparty/squirrel/squirrel/sqclass.cpp index 71743f4644..643685c9e6 100644 --- a/src/3rdparty/squirrel/squirrel/sqclass.cpp +++ b/src/3rdparty/squirrel/squirrel/sqclass.cpp @@ -15,8 +15,8 @@ SQClass::SQClass(SQSharedState *ss,SQClass *base) { _base = base; - _typetag = 0; - _hook = NULL; + _typetag = nullptr; + _hook = nullptr; _udsize = 0; _metamethods.resize(MT_LAST); //size it to max size if(_base) { @@ -139,8 +139,8 @@ bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval) /////////////////////////////////////////////////////////////////////// void SQInstance::Init(SQSharedState *ss) { - _userpointer = NULL; - _hook = NULL; + _userpointer = nullptr; + _hook = nullptr; __ObjAddRef(_class); _delegate = _class->_members; INIT_CHAIN(); @@ -196,7 +196,7 @@ bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) bool SQInstance::InstanceOf(SQClass *trg) { SQClass *parent = _class; - while(parent != NULL) { + while(parent != nullptr) { if(parent == trg) return true; parent = parent->_base; diff --git a/src/3rdparty/squirrel/squirrel/sqclosure.h b/src/3rdparty/squirrel/squirrel/sqclosure.h index 8480fb8af2..49a84b7924 100644 --- a/src/3rdparty/squirrel/squirrel/sqclosure.h +++ b/src/3rdparty/squirrel/squirrel/sqclosure.h @@ -45,7 +45,7 @@ struct SQGenerator : public CHAINABLE_OBJ { enum SQGeneratorState{eRunning,eSuspended,eDead}; private: - SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=nullptr;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} public: static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); diff --git a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp index a80e08639b..3af111a28a 100644 --- a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp +++ b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp @@ -57,7 +57,7 @@ typedef sqvector ExpStateVec; class SQCompiler { public: - SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) : _token(0), _fs(NULL), _lex(_ss(v), rg, up, ThrowError, this), _debugline(0), _debugop(0) + SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) : _token(0), _fs(nullptr), _lex(_ss(v), rg, up, ThrowError, this), _debugline(0), _debugop(0) { _vm=v; _sourcename = SQString::Create(_ss(v), sourcename); @@ -164,7 +164,7 @@ public: _debugline = 1; _debugop = 0; - SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this); + SQFuncState funcstate(_ss(_vm), nullptr,ThrowError,this); funcstate._name = SQString::Create(_ss(_vm), "main"); _fs = &funcstate; _fs->AddParameter(_fs->CreateString("this")); diff --git a/src/3rdparty/squirrel/squirrel/sqlexer.cpp b/src/3rdparty/squirrel/squirrel/sqlexer.cpp index 77c487a269..a4bac82279 100644 --- a/src/3rdparty/squirrel/squirrel/sqlexer.cpp +++ b/src/3rdparty/squirrel/squirrel/sqlexer.cpp @@ -87,7 +87,7 @@ SQLexer::SQLexer(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerE _prevtoken = -1; _curtoken = -1; - _svalue = NULL; + _svalue = nullptr; _nvalue = 0; _fvalue = 0; @@ -119,7 +119,7 @@ const SQChar *SQLexer::Tok2Str(SQInteger tok) if(((SQInteger)_integer(val)) == tok) return _stringval(key); } - return NULL; + return nullptr; } void SQLexer::LexBlockComment() diff --git a/src/3rdparty/squirrel/squirrel/sqobject.cpp b/src/3rdparty/squirrel/squirrel/sqobject.cpp index a113f316de..298efe610c 100644 --- a/src/3rdparty/squirrel/squirrel/sqobject.cpp +++ b/src/3rdparty/squirrel/squirrel/sqobject.cpp @@ -41,7 +41,7 @@ const SQChar *IdType2Name(SQObjectType type) case _RT_INSTANCE: return "instance"; case _RT_WEAKREF: return "weakref"; default: - return NULL; + return nullptr; } } @@ -101,13 +101,13 @@ SQRefCounted::~SQRefCounted() { if(_weakref) { _weakref->_obj._type = OT_NULL; - _weakref->_obj._unVal.pRefCounted = NULL; + _weakref->_obj._unVal.pRefCounted = nullptr; } } void SQWeakRef::Release() { if(ISREFCOUNTED(_obj._type)) { - _obj._unVal.pRefCounted->_weakref = NULL; + _obj._unVal.pRefCounted->_weakref = nullptr; } sq_delete(this,SQWeakRef); } @@ -149,7 +149,7 @@ bool SQGenerator::Yield(SQVM *v) for(SQInteger j = nvargs - 1; j >= 0; j--) { _vargsstack.push_back(v->_vargsstack[vargsbase+j]); } - _ci._generator=NULL; + _ci._generator=nullptr; for(SQInteger i=0;i<_ci._etraps;i++) { _etraps.push_back(v->_etraps.top()); v->_etraps.pop_back(); @@ -204,7 +204,7 @@ void SQArray::Extend(const SQArray *a){ const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop) { SQUnsignedInteger nvars=_nlocalvarinfos; - const SQChar *res=NULL; + const SQChar *res=nullptr; if(nvars>=nseq){ for(SQUnsignedInteger i=0;i=nop) diff --git a/src/3rdparty/squirrel/squirrel/sqobject.h b/src/3rdparty/squirrel/squirrel/sqobject.h index 9212766eef..129674b5a6 100644 --- a/src/3rdparty/squirrel/squirrel/sqobject.h +++ b/src/3rdparty/squirrel/squirrel/sqobject.h @@ -56,7 +56,7 @@ enum SQMetaMethod{ struct SQRefCounted { - SQRefCounted() { _uiRef = 0; _weakref = NULL; } + SQRefCounted() { _uiRef = 0; _weakref = nullptr; } virtual ~SQRefCounted(); SQWeakRef *GetWeakRef(SQObjectType type); SQUnsignedInteger _uiRef; @@ -134,7 +134,7 @@ struct SQObjectPtr : public SQObject { SQ_OBJECT_RAWINIT() _type=OT_NULL; - _unVal.pUserPointer=NULL; + _unVal.pUserPointer=nullptr; } SQObjectPtr(const SQObjectPtr &o) { @@ -281,7 +281,7 @@ struct SQObjectPtr : public SQObject tOldType = _type; unOldVal = _unVal; _type = OT_NULL; - _unVal.pUserPointer = NULL; + _unVal.pUserPointer = nullptr; __Release(tOldType,unOldVal); } inline SQObjectPtr& operator=(SQInteger i) diff --git a/src/3rdparty/squirrel/squirrel/sqstate.cpp b/src/3rdparty/squirrel/squirrel/sqstate.cpp index 31345d6640..0f95c396c9 100644 --- a/src/3rdparty/squirrel/squirrel/sqstate.cpp +++ b/src/3rdparty/squirrel/squirrel/sqstate.cpp @@ -79,12 +79,12 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) { SQInteger i=0; SQTable *t=SQTable::Create(ss,0); - while(funcz[i].name!=0){ + while(funcz[i].name!=nullptr){ SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f); nc->_nparamscheck = funcz[i].nparamscheck; nc->_name = SQString::Create(ss,funcz[i].name); if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) - return NULL; + return nullptr; t->NewSlot(SQString::Create(ss,funcz[i].name),nc); i++; } @@ -93,15 +93,15 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) SQSharedState::SQSharedState() { - _compilererrorhandler = NULL; - _printfunc = NULL; + _compilererrorhandler = nullptr; + _printfunc = nullptr; _debuginfo = false; _notifyallexceptions = false; - _scratchpad=NULL; + _scratchpad=nullptr; _scratchpadsize=0; _collectable_free_processing = false; #ifndef NO_GARBAGE_COLLECTOR - _gc_chain=NULL; + _gc_chain=nullptr; #endif sq_new(_stringtable,SQStringTable); sq_new(_metamethods,SQObjectPtrVec); @@ -189,7 +189,7 @@ SQSharedState::~SQSharedState() _refs_table.Finalize(); #ifndef NO_GARBAGE_COLLECTOR SQCollectable *t = _gc_chain; - SQCollectable *nx = NULL; + SQCollectable *nx = nullptr; if(t) { t->_uiRef++; while(t) { @@ -299,7 +299,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm) EnqueueMarkObject(_instance_default_delegate,queue); EnqueueMarkObject(_weakref_default_delegate,queue); - SQCollectable *tchain=NULL; + SQCollectable *tchain=nullptr; while (!queue.IsEmpty()) { SQCollectable *q = queue.Pop(); @@ -309,7 +309,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm) } SQCollectable *t = _gc_chain; - SQCollectable *nx = NULL; + SQCollectable *nx = nullptr; if(t) { t->_uiRef++; while(t) { @@ -340,7 +340,7 @@ SQInteger SQSharedState::CollectGarbage(SQVM *vm) #ifndef NO_GARBAGE_COLLECTOR void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c) { - c->_prev = NULL; + c->_prev = nullptr; c->_next = *chain; if(*chain) (*chain)->_prev = c; *chain = c; @@ -352,8 +352,8 @@ void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c) else *chain = c->_next; if(c->_next) c->_next->_prev = c->_prev; - c->_next = NULL; - c->_prev = NULL; + c->_next = nullptr; + c->_prev = nullptr; } #endif @@ -483,16 +483,16 @@ RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bo { RefNode *ref; mainpos = ::HashObj(obj)&(_numofslots-1); - *prev = NULL; + *prev = nullptr; for (ref = _buckets[mainpos]; ref; ) { if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj)) break; *prev = ref; ref = ref->next; } - if(ref == NULL && add) { + if(ref == nullptr && add) { if(_numofslots == _slotused) { - assert(_freelist == 0); + assert(_freelist == nullptr); Resize(_numofslots*2); mainpos = ::HashObj(obj)&(_numofslots-1); } @@ -510,16 +510,16 @@ void RefTable::AllocNodes(SQUnsignedInteger size) RefNode *temp = nodes; SQUnsignedInteger n; for(n = 0; n < size - 1; n++) { - bucks[n] = NULL; + bucks[n] = nullptr; temp->refs = 0; new (&temp->obj) SQObjectPtr; temp->next = temp+1; temp++; } - bucks[n] = NULL; + bucks[n] = nullptr; temp->refs = 0; new (&temp->obj) SQObjectPtr; - temp->next = NULL; + temp->next = nullptr; _freelist = nodes; _nodes = nodes; _buckets = bucks; @@ -543,7 +543,7 @@ SQStringTable::SQStringTable() SQStringTable::~SQStringTable() { SQ_FREE(_strings,sizeof(SQString*)*_numofslots); - _strings = NULL; + _strings = nullptr; } void SQStringTable::AllocNodes(SQInteger size) @@ -580,8 +580,8 @@ SQString::SQString(const SQChar *news, SQInteger len) _val[len] = '\0'; _len = len; _hash = ::_hashstr(news,(size_t)len); - _next = NULL; - _sharedstate = NULL; + _next = nullptr; + _sharedstate = nullptr; } void SQStringTable::Resize(SQInteger size) @@ -605,7 +605,7 @@ void SQStringTable::Resize(SQInteger size) void SQStringTable::Remove(SQString *bs) { SQString *s; - SQString *prev=NULL; + SQString *prev=nullptr; SQHash h = bs->_hash&(_numofslots - 1); for (s = _strings[h]; s; ){ diff --git a/src/3rdparty/squirrel/squirrel/sqtable.cpp b/src/3rdparty/squirrel/squirrel/sqtable.cpp index 60146fe738..6f466d686a 100644 --- a/src/3rdparty/squirrel/squirrel/sqtable.cpp +++ b/src/3rdparty/squirrel/squirrel/sqtable.cpp @@ -18,7 +18,7 @@ SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize) while(nInitialSize>pow2size)pow2size=pow2size<<1; AllocNodes(pow2size); _usednodes = 0; - _delegate = NULL; + _delegate = nullptr; INIT_CHAIN(); ADD_TO_CHAIN(&_sharedstate->_gc_chain,this); } @@ -39,7 +39,7 @@ void SQTable::AllocNodes(SQInteger nSize) _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); for(SQInteger i=0;i n && (othern = &_nodes[mph]) != mp){ /* yes; move colliding node into free position */ while (othern->next != mp){ - assert(othern->next != NULL); + assert(othern->next != nullptr); othern = othern->next; /* find previous */ } othern->next = n; /* redo the chain with `n' in place of `mp' */ @@ -129,7 +129,7 @@ bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) n->next = mp->next; mp->key = _null_; mp->val = _null_; - mp->next = NULL; /* now `mp' is free */ + mp->next = nullptr; /* now `mp' is free */ } else{ /* new node will go into free position */ @@ -141,7 +141,7 @@ bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) mp->key = key; for (;;) { /* correct `firstfree' */ - if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) { + if (type(_firstfree->key) == OT_NULL && _firstfree->next == nullptr) { mp->val = val; _usednodes++; return true; /* OK; table still has a free place */ @@ -190,7 +190,7 @@ void SQTable::_ClearNodes() void SQTable::Finalize() { _ClearNodes(); - SetDelegate(NULL); + SetDelegate(nullptr); } void SQTable::Clear() diff --git a/src/3rdparty/squirrel/squirrel/sqtable.h b/src/3rdparty/squirrel/squirrel/sqtable.h index fad2fdc605..6bdda15773 100644 --- a/src/3rdparty/squirrel/squirrel/sqtable.h +++ b/src/3rdparty/squirrel/squirrel/sqtable.h @@ -27,7 +27,7 @@ struct SQTable : public SQDelegable private: struct _HashNode { - _HashNode() { next = NULL; } + _HashNode() { next = nullptr; } SQObjectPtr val; SQObjectPtr key; _HashNode *next; @@ -47,14 +47,14 @@ public: { SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable)); new (newtable) SQTable(ss, nInitialSize); - newtable->_delegate = NULL; + newtable->_delegate = nullptr; return newtable; } void Finalize() override; SQTable *Clone(); ~SQTable() { - SetDelegate(NULL); + SetDelegate(nullptr); REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode(); SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode)); @@ -70,7 +70,7 @@ public: return n; } }while((n = n->next)); - return NULL; + return nullptr; } bool Get(const SQObjectPtr &key,SQObjectPtr &val); void Remove(const SQObjectPtr &key); diff --git a/src/3rdparty/squirrel/squirrel/squserdata.h b/src/3rdparty/squirrel/squirrel/squserdata.h index ca4933de2d..aed3e83498 100644 --- a/src/3rdparty/squirrel/squirrel/squserdata.h +++ b/src/3rdparty/squirrel/squirrel/squserdata.h @@ -4,12 +4,12 @@ struct SQUserData : SQDelegable { - SQUserData(SQSharedState *ss, SQInteger size){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); _size = size; _typetag = 0; + SQUserData(SQSharedState *ss, SQInteger size){ _delegate = nullptr; _hook = nullptr; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); _size = size; _typetag = nullptr; } ~SQUserData() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this); - SetDelegate(NULL); + SetDelegate(nullptr); } static SQUserData* Create(SQSharedState *ss, SQInteger size) { @@ -19,7 +19,7 @@ struct SQUserData : SQDelegable } #ifndef NO_GARBAGE_COLLECTOR void EnqueueMarkObjectForChildren(SQGCMarkerQueue &queue); - void Finalize(){SetDelegate(NULL);} + void Finalize(){SetDelegate(nullptr);} #endif void Release() { if (_hook) _hook(_val,_size); diff --git a/src/3rdparty/squirrel/squirrel/squtils.h b/src/3rdparty/squirrel/squirrel/squtils.h index b1138dcb1a..d7d260dba4 100644 --- a/src/3rdparty/squirrel/squirrel/squtils.h +++ b/src/3rdparty/squirrel/squirrel/squtils.h @@ -18,7 +18,7 @@ template class sqvector public: sqvector() { - _vals = NULL; + _vals = nullptr; _size = 0; _allocated = 0; } diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index 1987a30098..b6f2c526db 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -33,7 +33,7 @@ void SQVM::ClearStack(SQInteger last_top) tOldType = o._type; unOldVal = o._unVal; o._type = OT_NULL; - o._unVal.pUserPointer = NULL; + o._unVal.pUserPointer = nullptr; __Release(tOldType,unOldVal); } } @@ -107,7 +107,7 @@ SQVM::SQVM(SQSharedState *ss) _suspended_target=-1; _suspended_root = SQFalse; _suspended_traps=0; - _foreignptr=NULL; + _foreignptr=nullptr; _nnativecalls=0; _lasterror = _null_; _errorhandler = _null_; @@ -115,12 +115,12 @@ SQVM::SQVM(SQSharedState *ss) _can_suspend = false; _in_stackoverflow = false; _ops_till_suspend = 0; - _callsstack = NULL; + _callsstack = nullptr; _callsstacksize = 0; _alloccallsstacksize = 0; _top = 0; _stackbase = 0; - ci = NULL; + ci = nullptr; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } @@ -379,7 +379,7 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege if (!tailcall) { CallInfo lc = {}; - lc._generator = NULL; + lc._generator = nullptr; lc._etraps = 0; lc._prevstkbase = (SQInt32) ( stackbase - _stackbase ); lc._target = (SQInt32) target; @@ -557,7 +557,7 @@ bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2) } break; case OT_NULL: - _table(o1)->SetDelegate(NULL); + _table(o1)->SetDelegate(nullptr); break; default: Raise_Error("using '%s' as delegate", GetTypeName(o2)); @@ -627,7 +627,7 @@ bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci) bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) { - SQClass *base = NULL; + SQClass *base = nullptr; SQObjectPtr attrs; if(baseclass != -1) { if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error("trying to inherit from a %s",GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } @@ -708,7 +708,7 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn temp_reg = closure; if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { //call the handler if there are no calls in the stack, if not relies on the previous node - if(ci == NULL) CallErrorHandler(_lasterror); + if(ci == nullptr) CallErrorHandler(_lasterror); return false; } if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) { @@ -1160,7 +1160,7 @@ bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackb _top = stackbase + nargs; CallInfo lci = {}; lci._closure = nclosure; - lci._generator = NULL; + lci._generator = nullptr; lci._etraps = 0; lci._prevstkbase = (SQInt32) (stackbase - _stackbase); lci._ncalls = 1; From f904aef176b7bde38f27cc9b4f23c55dc13d2ce5 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 16 Jun 2021 21:12:08 +0200 Subject: [PATCH 15/53] Cleanup: use nullptr instead of 0 or NULL --- src/main_gui.cpp | 2 +- src/network/core/tcp_connect.cpp | 2 +- src/network/network_command.cpp | 2 +- src/newgrf_commons.h | 2 +- src/os/unix/font_unix.cpp | 4 ++-- src/os/unix/unix.cpp | 2 +- src/video/opengl.cpp | 2 +- src/video/sdl2_v.cpp | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 559040f378..79960d51bb 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -309,7 +309,7 @@ struct MainWindow : Window case GHK_REFRESH_SCREEN: MarkWholeScreenDirty(); break; case GHK_CRASH: // Crash the game - *(volatile byte *)0 = 0; + *(volatile byte *)nullptr = 0; break; case GHK_MONEY: // Gimme money diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index f251f02884..c4f5415b04 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -268,7 +268,7 @@ bool TCPConnecter::CheckActivity() timeval tv; tv.tv_usec = 0; tv.tv_sec = 0; - int n = select(FD_SETSIZE, NULL, &write_fd, NULL, &tv); + int n = select(FD_SETSIZE, nullptr, &write_fd, nullptr, &tv); /* select() failed; hopefully next try it doesn't. */ if (n < 0) { /* select() normally never fails; so hopefully it works next try! */ diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index 1a9849a346..6d03aaaa13 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -179,7 +179,7 @@ void NetworkSyncCommandQueue(NetworkClientSocket *cs) { for (CommandPacket *p = _local_execution_queue.Peek(); p != nullptr; p = p->next) { CommandPacket c = *p; - c.callback = 0; + c.callback = nullptr; cs->outgoing_queue.Append(&c); } } diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index ed18aaa9e2..ff241369a2 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -309,7 +309,7 @@ bool Convert8bitBooleanCallback(const struct GRFFile *grffile, uint16 cbid, uint */ template struct GRFFilePropsBase { - GRFFilePropsBase() : local_id(0), grffile(0) + GRFFilePropsBase() : local_id(0), grffile(nullptr) { /* The lack of some compilers to provide default constructors complying to the specs * requires us to zero the stuff ourself. */ diff --git a/src/os/unix/font_unix.cpp b/src/os/unix/font_unix.cpp index f8cf96a48b..246d65e63f 100644 --- a/src/os/unix/font_unix.cpp +++ b/src/os/unix/font_unix.cpp @@ -51,10 +51,10 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) /* Resolve the name and populate the information structure */ pat = FcNameParse((FcChar8 *)font_family); if (font_style != nullptr) FcPatternAddString(pat, FC_STYLE, (FcChar8 *)font_style); - FcConfigSubstitute(0, pat, FcMatchPattern); + FcConfigSubstitute(nullptr, pat, FcMatchPattern); FcDefaultSubstitute(pat); fs = FcFontSetCreate(); - match = FcFontMatch(0, pat, &result); + match = FcFontMatch(nullptr, pat, &result); if (fs != nullptr && match != nullptr) { int i; diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index f696f817f4..95d6fa1fa5 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -277,7 +277,7 @@ bool GetClipboardContents(char *buffer, const char *last) } char *clip = SDL_GetClipboardText(); - if (clip != NULL) { + if (clip != nullptr) { strecpy(buffer, clip, last); SDL_free(clip); return true; diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 576bdd78bf..2014d1cf95 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -1309,7 +1309,7 @@ void OpenGLBackend::RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, int _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); _glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, 256, GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1); - _glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RED, GL_UNSIGNED_BYTE, 0); + _glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RED, GL_UNSIGNED_BYTE, nullptr); _glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 66bea5d8c3..98c04fd85c 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -593,7 +593,7 @@ void VideoDriver_SDL_Base::Stop() void VideoDriver_SDL_Base::InputLoop() { uint32 mod = SDL_GetModState(); - const Uint8 *keys = SDL_GetKeyboardState(NULL); + const Uint8 *keys = SDL_GetKeyboardState(nullptr); bool old_ctrl_pressed = _ctrl_pressed; From 357af686dc5e0a0085da5c42639abe83caebe6c3 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 16 Jun 2021 22:29:57 +0200 Subject: [PATCH 16/53] Cleanup: use true/false instead of 1/0 where applicable --- src/saveload/afterload.cpp | 2 +- src/saveload/ai_sl.cpp | 2 +- src/video/opengl.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index b67d57a654..83f3c6fc65 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -733,7 +733,7 @@ bool AfterLoadGame() if (IsSavegameVersionBefore(SLV_6, 1)) _settings_game.pf.forbid_90_deg = false; if (IsSavegameVersionBefore(SLV_21)) _settings_game.vehicle.train_acceleration_model = 0; if (IsSavegameVersionBefore(SLV_90)) _settings_game.vehicle.plane_speed = 4; - if (IsSavegameVersionBefore(SLV_95)) _settings_game.vehicle.dynamic_engines = 0; + if (IsSavegameVersionBefore(SLV_95)) _settings_game.vehicle.dynamic_engines = false; if (IsSavegameVersionBefore(SLV_96)) _settings_game.economy.station_noise_level = false; if (IsSavegameVersionBefore(SLV_133)) { _settings_game.vehicle.train_slope_steepness = 3; diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index c821dfe59d..49221ef300 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -65,7 +65,7 @@ static void Load_AIPL() while ((index = (CompanyID)SlIterateArray()) != (CompanyID)-1) { if (index >= MAX_COMPANIES) SlErrorCorrupt("Too many AI configs"); - _ai_saveload_is_random = 0; + _ai_saveload_is_random = false; _ai_saveload_version = -1; SlObject(nullptr, _ai_company); diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 2014d1cf95..6e37db03ba 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -146,7 +146,7 @@ GetOGLProcAddressProc GetOGLProcAddress; */ const char *FindStringInExtensionList(const char *string, const char *substring) { - while (1) { + while (true) { /* Is the extension string present at all? */ const char *pos = strstr(string, substring); if (pos == nullptr) break; From 281a65b3e17310d07458652a3f6cba55aff59dc0 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 16 Jun 2021 23:21:21 +0200 Subject: [PATCH 17/53] Cleanup: simplify some boolean expressions --- src/3rdparty/squirrel/squirrel/sqapi.cpp | 12 ++++++------ src/3rdparty/squirrel/squirrel/sqvm.cpp | 6 +++--- src/fios_gui.cpp | 2 +- src/news_gui.cpp | 3 +-- src/pathfinder/npf/npf.cpp | 4 +--- src/saveload/saveload.h | 4 +--- src/script/api/script_list.cpp | 4 ++-- src/settings_gui.cpp | 3 +-- src/signal.cpp | 4 +--- 9 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/3rdparty/squirrel/squirrel/sqapi.cpp b/src/3rdparty/squirrel/squirrel/sqapi.cpp index aeef3779b6..80c5d816e8 100644 --- a/src/3rdparty/squirrel/squirrel/sqapi.cpp +++ b/src/3rdparty/squirrel/squirrel/sqapi.cpp @@ -135,7 +135,7 @@ void sq_close(HSQUIRRELVM v) SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) { SQObjectPtr o; - if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { + if(Compile(v, read, p, sourcename, o, raiseerror != 0, _ss(v)->_debuginfo)) { v->Push(SQClosure::Create(_ss(v), _funcproto(o))); return SQ_OK; } @@ -144,12 +144,12 @@ SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQCha void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable) { - _ss(v)->_debuginfo = enable?true:false; + _ss(v)->_debuginfo = enable != 0; } void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable) { - _ss(v)->_notifyallexceptions = enable?true:false; + _ss(v)->_notifyallexceptions = enable != 0; } void sq_addref(HSQUIRRELVM v,HSQOBJECT *po) @@ -224,7 +224,7 @@ void sq_pushinteger(HSQUIRRELVM v,SQInteger n) void sq_pushbool(HSQUIRRELVM v,SQBool b) { - v->Push(b?true:false); + v->Push(b != 0); } void sq_pushfloat(HSQUIRRELVM v,SQFloat n) @@ -724,7 +724,7 @@ SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic) if(type(self) == OT_TABLE || type(self) == OT_CLASS) { SQObjectPtr &key = v->GetUp(-2); if(type(key) == OT_NULL) return sq_throwerror(v, "null is not a valid key"); - v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false); + v->NewSlot(self, key, v->GetUp(-1),bstatic != 0); v->Pop(2); } return SQ_OK; @@ -975,7 +975,7 @@ SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror, v->_can_suspend = suspend >= 0; if (v->_can_suspend) v->_ops_till_suspend = suspend; - if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false,v->_can_suspend)){ + if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror != 0,v->_can_suspend)){ if(!v->_suspended) { v->Pop(params);//pop closure and args } diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index b6f2c526db..1f81a2e9a6 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -437,7 +437,7 @@ bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) while (last_top > oldstackbase) _stack._vals[last_top--].Null(); assert(oldstackbase >= _stackbase); - return broot?true:false; + return broot != 0; } #define _RET_ON_FAIL(exp) { if(!exp) return false; } @@ -653,7 +653,7 @@ bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) { if(type(o1) == type(o2)) { - res = ((_rawval(o1) == _rawval(o2)?true:false)); + res = ((_rawval(o1) == _rawval(o2))); } else { if(sq_isnumeric(o1) && sq_isnumeric(o2)) { @@ -1028,7 +1028,7 @@ common_call: case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; case _OP_NEWSLOTA: - bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false; + bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG) != 0; if(type(STK(arg1)) == OT_CLASS) { if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) { Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3)); diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index 2d33875f67..c0551701e8 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -868,7 +868,7 @@ public: this->fios_items_shown[i] = this->string_filter.GetState(); if (this->fios_items_shown[i]) items_shown_count++; - if (&(this->fios_items[i]) == this->selected && this->fios_items_shown[i] == false) { + if (&(this->fios_items[i]) == this->selected && !this->fios_items_shown[i]) { /* The selected element has been filtered out */ this->selected = nullptr; this->OnInvalidateData(SLIWD_SELECTION_CHANGES); diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 731eb95c22..5c72f87410 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -639,8 +639,7 @@ static bool ReadyForNextTickerItem() /* Ticker message * Check if the status bar message is still being displayed? */ - if (IsNewsTickerShown()) return false; - return true; + return !IsNewsTickerShown(); } /** diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index 733b2eba9d..5887181851 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -826,9 +826,7 @@ static bool CanEnterTile(TileIndex tile, DiagDirection dir, AyStarUserData *user /* Depots, standard roadstops and single tram bits can only be entered from one direction */ DiagDirection single_entry = GetTileSingleEntry(tile, user->type, user->subtype); - if (single_entry != INVALID_DIAGDIR && single_entry != ReverseDiagDir(dir)) return false; - - return true; + return single_entry == INVALID_DIAGDIR || single_entry == ReverseDiagDir(dir); } /** diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index dfd687f356..8456da4150 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -956,9 +956,7 @@ static inline bool IsSavegameVersionUntil(SaveLoadVersion major) static inline bool SlIsObjectCurrentlyValid(SaveLoadVersion version_from, SaveLoadVersion version_to) { extern const SaveLoadVersion SAVEGAME_VERSION; - if (SAVEGAME_VERSION < version_from || SAVEGAME_VERSION >= version_to) return false; - - return true; + return version_from <= SAVEGAME_VERSION && SAVEGAME_VERSION < version_to; } /** diff --git a/src/script/api/script_list.cpp b/src/script/api/script_list.cpp index 1985cdbfb4..623128bdd8 100644 --- a/src/script/api/script_list.cpp +++ b/src/script/api/script_list.cpp @@ -468,7 +468,7 @@ int64 ScriptList::Begin() int64 ScriptList::Next() { - if (this->initialized == false) { + if (!this->initialized) { Debug(script, 0, "Next() is invalid as Begin() is never called"); return 0; } @@ -482,7 +482,7 @@ bool ScriptList::IsEmpty() bool ScriptList::IsEnd() { - if (this->initialized == false) { + if (!this->initialized) { Debug(script, 0, "IsEnd() is invalid as Begin() is never called"); return true; } diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index b17b343c79..a63448aef6 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -930,8 +930,7 @@ void BaseSettingEntry::Init(byte level) bool BaseSettingEntry::IsVisible(const BaseSettingEntry *item) const { if (this->IsFiltered()) return false; - if (this == item) return true; - return false; + return this == item; } /** diff --git a/src/signal.cpp b/src/signal.cpp index 4a7e7913e1..329b1b05d9 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -216,9 +216,7 @@ static inline bool CheckAddToTodoSet(TileIndex t1, DiagDirection d1, TileIndex t assert(!_tbdset.IsIn(t1, d1)); // it really shouldn't be there already - if (_tbdset.Remove(t2, d2)) return false; - - return true; + return !_tbdset.Remove(t2, d2); } From c12a152ec972309a87ab1637091990520ce9c123 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 17 Jun 2021 18:58:59 +0200 Subject: [PATCH 18/53] Fix: thread safety issue during exiting the game (#9380) _exit_game is read by the draw-thread to know when to exit, but most of the time written by the game-thread. --- src/gfx.cpp | 2 +- src/openttd.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index d787dc26f6..ff2c80bfc0 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -41,7 +41,7 @@ bool _right_button_down; ///< Is right mouse button pressed? bool _right_button_clicked; ///< Is right mouse button clicked? DrawPixelInfo _screen; bool _screen_disable_anim = false; ///< Disable palette animation (important for 32bpp-anim blitter during giant screenshot) -bool _exit_game; +std::atomic _exit_game; GameMode _game_mode; SwitchMode _switch_mode; ///< The next mainloop command. PauseMode _pause_mode; diff --git a/src/openttd.h b/src/openttd.h index 2cd9cc1f09..6473168ee1 100644 --- a/src/openttd.h +++ b/src/openttd.h @@ -10,6 +10,7 @@ #ifndef OPENTTD_H #define OPENTTD_H +#include #include "core/enum_type.hpp" /** Mode which defines the state of the game. */ @@ -52,7 +53,7 @@ enum DisplayOptions { extern GameMode _game_mode; extern SwitchMode _switch_mode; -extern bool _exit_game; +extern std::atomic _exit_game; extern bool _save_config; /** Modes of pausing we've got */ From b45c006ab9bdfb92fa6be66dcfa00099adbb85a8 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 17 Jun 2021 20:10:40 +0200 Subject: [PATCH 19/53] Fix: on startup, NewGRF scan could case race-condition (#9382) Creating a thread was not thread-safe. The irony. The video-driver has a function GameLoopPause() which first checks if the thread is the game-thread or not. For this it needs access to this->game_thread. This variable is set in StartNewThread(). However, due to timing, it is well possible GameLoopPause() is called from the thread well before this->game_thread is assigned. And so we have a race-condition! Simply solve this by preventing a thread to start till we are done with our bookkeeping. --- src/thread.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/thread.h b/src/thread.h index bcd4690811..24f4f8e2aa 100644 --- a/src/thread.h +++ b/src/thread.h @@ -14,6 +14,7 @@ #include "crashlog.h" #include #include +#include /** * Sleep on the current thread for a defined time. @@ -46,7 +47,17 @@ inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs& { #ifndef NO_THREADS try { + static std::mutex thread_startup_mutex; + std::lock_guard lock(thread_startup_mutex); + std::thread t([] (const char *name, TFn&& F, TArgs&&... A) { + /* Delay starting the thread till the main thread is finished + * with the administration. This prevent race-conditions on + * startup. */ + { + std::lock_guard lock(thread_startup_mutex); + } + SetCurrentThreadName(name); CrashLog::InitThread(); try { From cf865597f8f14c56e96b22b9a7fef1b693fbcb08 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 17 Jun 2021 20:22:57 +0200 Subject: [PATCH 20/53] Fix: don't propagate shift/ctrl state till next game-tick (#9381) When the game-loop is very slow, it was easily possible to start the loop with _shift_pressed being false, but end with _shift_pressed being true. This doesn't hurt the game as such, but for the user this can be very weird: I pressed "Buy Vehicle", pressed shift a bit later, and I still get a cost indication. --- src/video/video_driver.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp index 27824674ab..8fe582760f 100644 --- a/src/video/video_driver.cpp +++ b/src/video/video_driver.cpp @@ -116,21 +116,6 @@ void VideoDriver::Tick() /* Avoid next_draw_tick getting behind more and more if it cannot keep up. */ if (this->next_draw_tick < now - ALLOWED_DRIFT * this->GetDrawInterval()) this->next_draw_tick = now; - /* Keep the interactive randomizer a bit more random by requesting - * new values when-ever we can. */ - InteractiveRandom(); - - this->InputLoop(); - - /* Check if the fast-forward button is still pressed. */ - if (fast_forward_key_pressed && !_networking && _game_mode != GM_MENU) { - ChangeGameSpeed(true); - this->fast_forward_via_key = true; - } else if (this->fast_forward_via_key) { - ChangeGameSpeed(false); - this->fast_forward_via_key = false; - } - /* Locking video buffer can block (especially with vsync enabled), do it before taking game state lock. */ this->LockVideoBuffer(); @@ -139,9 +124,24 @@ void VideoDriver::Tick() std::lock_guard lock_wait(this->game_thread_wait_mutex); std::lock_guard lock_state(this->game_state_mutex); + /* Keep the interactive randomizer a bit more random by requesting + * new values when-ever we can. */ + InteractiveRandom(); + this->DrainCommandQueue(); while (this->PollEvent()) {} + this->InputLoop(); + + /* Check if the fast-forward button is still pressed. */ + if (fast_forward_key_pressed && !_networking && _game_mode != GM_MENU) { + ChangeGameSpeed(true); + this->fast_forward_via_key = true; + } else if (this->fast_forward_via_key) { + ChangeGameSpeed(false); + this->fast_forward_via_key = false; + } + ::InputLoop(); /* Prevent drawing when switching mode, as windows can be removed when they should still appear. */ From 1e6a2163a5ca5fe0e17fbd9adef23571f2c36a8a Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Thu, 17 Jun 2021 23:08:49 +0100 Subject: [PATCH 21/53] Fix #9358: Don't skip empty files in tar (#9367) --- src/fileio.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index bee02ab355..fe9c947dff 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -541,9 +541,6 @@ bool TarScanner::AddFile(const std::string &filename, size_t basepath_length, co switch (th.typeflag) { case '\0': case '0': { // regular file - /* Ignore empty files */ - if (skip == 0) break; - if (strlen(name) == 0) break; /* Store this entry in the list */ From ce7ef4d824b9e6cd852826b6fcc41263487ebd5e Mon Sep 17 00:00:00 2001 From: PeterN Date: Thu, 17 Jun 2021 23:34:59 +0100 Subject: [PATCH 22/53] Fix: Wrong cargo line position in IndustryCargo window. (#9383) Resolved by changing calculation to determine the offset based on centring the cargo lines in the available space. --- src/industry_gui.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index fd5f5d4872..6489399757 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2021,11 +2021,7 @@ struct CargoesField { assert(this->type == CFT_CARGO); int n = this->u.cargo.num_cargoes; - if (n % 2 == 0) { - return xpos + cargo_field_width / 2 - (CargoesField::cargo_line.width + CargoesField::cargo_space.width / 2) * (n / 2); - } else { - return xpos + cargo_field_width / 2 - CargoesField::cargo_line.width / 2 - (CargoesField::cargo_line.width + CargoesField::cargo_space.width) * (n / 2); - } + return xpos + cargo_field_width / 2 - (CargoesField::cargo_line.width * n + CargoesField::cargo_space.width * (n - 1)) / 2; } /** From 052f6b5d9fd17ca38105b27e5a1d616dacc2e2da Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 19 Jun 2021 18:53:27 +0000 Subject: [PATCH 23/53] Update: Translations from eints swedish: 12 changes by joeax910 --- src/lang/swedish.txt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 20f40e8d9c..a5baf80549 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -386,7 +386,7 @@ STR_SCENEDIT_FILE_MENU_QUIT :Avsluta ############ range for settings menu starts STR_SETTINGS_MENU_GAME_OPTIONS :Spelinställningar STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE :Inställningar -STR_SETTINGS_MENU_SCRIPT_SETTINGS :Inställningar för AI / spelskript +STR_SETTINGS_MENU_SCRIPT_SETTINGS :Inställningar för datorspelare / spelskript STR_SETTINGS_MENU_NEWGRF_SETTINGS :Inställningar för NewGRF STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Inställningar för genomskinlighet STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Stadsnamn visas @@ -484,7 +484,7 @@ STR_NEWS_MENU_DELETE_ALL_MESSAGES :Ta bort alla me STR_ABOUT_MENU_LAND_BLOCK_INFO :Information om mark STR_ABOUT_MENU_SEPARATOR : STR_ABOUT_MENU_TOGGLE_CONSOLE :Visa/dölj konsolen -STR_ABOUT_MENU_AI_DEBUG :Felsökning av AI / spelskript +STR_ABOUT_MENU_AI_DEBUG :Felsökning av datorspelare / spelskript STR_ABOUT_MENU_SCREENSHOT :Skärmdump STR_ABOUT_MENU_SHOW_FRAMERATE :Visa bildfrekvens STR_ABOUT_MENU_ABOUT_OPENTTD :Om 'OpenTTD' @@ -883,6 +883,7 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventionen har gått ut:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventionen gäller inte längre:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ny subvention:{}{}Första transporten av {STRING} från {STRING} till {STRING} får {NUM} års subvention från kommunen! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i {TOWN}!{}{}Vägombyggnadsprogram bekostat av {STRING} medför 6 månader av elände för bilister! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! @@ -1193,11 +1194,15 @@ STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Räntenivå fö STR_CONFIG_SETTING_RUNNING_COSTS :Driftkostnader: {STRING} STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Sätt nivån för underhålls- och driftskostnader för fordon och infrastruktur STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Konstruktionshastighet: {STRING} -STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Begränsar antalet konstruktionshandlingar för AI-spelare +STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Begränsar antalet konstruktionshandlingar för datorspelare STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Fordonshaverier: {STRING} STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Styr hur ofta otillräckligt servade fordon kan få motorstopp STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subvention (multiplikativ): {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Ange hur mycket betalt som subventionerade anslutningar ger +STR_CONFIG_SETTING_SUBSIDY_DURATION :Subventioners varaktighet: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Ställ in hur många år en subvention ska gälla +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} år +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Inga subventioner STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Konstruktionskostnader: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Sätt nivån för konstruktions- och inköpskostnader STR_CONFIG_SETTING_RECESSIONS :Lågkonjunkturer: {STRING} @@ -1528,7 +1533,7 @@ STR_CONFIG_SETTING_AI_PROFILE_MEDIUM :Mellan STR_CONFIG_SETTING_AI_PROFILE_HARD :Svår STR_CONFIG_SETTING_AI_IN_MULTIPLAYER :Tillåt datorspelare i flerspelarläge: {STRING} -STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :Tillåt datorstyrda AI-spelare att delta i spel för flera spelare +STR_CONFIG_SETTING_AI_IN_MULTIPLAYER_HELPTEXT :Tillåt datorstyrda spelare att delta i spel för flera spelare STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES :#opcodes innan skript sätts i viloläge: {STRING} STR_CONFIG_SETTING_SCRIPT_MAX_OPCODES_HELPTEXT :Maximalt antal beräkningssteg ett skript kan utföra i en omgång STR_CONFIG_SETTING_SCRIPT_MAX_MEMORY :Maximalt minnesanvändning per skript: {STRING} @@ -4206,12 +4211,12 @@ STR_AI_DEBUG_SETTINGS :{BLACK}Inställ STR_AI_DEBUG_SETTINGS_TOOLTIP :{BLACK}Ändra inställningarna för spelskriptet STR_AI_DEBUG_RELOAD :{BLACK}Ladda om datorspelaren STR_AI_DEBUG_RELOAD_TOOLTIP :{BLACK}Stoppa datorspelaren, ladda om skriptet och starta sedan om datorspelaren -STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP :{BLACK}Slå på/av brytning då AI-loggmeddelande matchar brytsträngen +STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP :{BLACK}Slå på/av brytning då datorspelares loggmeddelande matchar brytsträngen STR_AI_DEBUG_BREAK_ON_LABEL :{BLACK}Bryt på: STR_AI_DEBUG_BREAK_STR_OSKTITLE :{BLACK}Bryt på -STR_AI_DEBUG_BREAK_STR_TOOLTIP :{BLACK}När ett AI-loggmeddelande matchar angiven sträng så kommer spelet att pausas +STR_AI_DEBUG_BREAK_STR_TOOLTIP :{BLACK}När ett loggmeddelande om datorspelare matchar angiven sträng så kommer spelet att pausas STR_AI_DEBUG_MATCH_CASE :{BLACK}Matcha VERSALER/gemener -STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Slå på/av matchning av VERSALER/gemener när AI-loggmeddelanden jämförs mot brytsträngen +STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Slå på/av matchning av VERSALER/gemener när datorspelares loggmeddelanden jämförs mot brytsträngen STR_AI_DEBUG_CONTINUE :{BLACK}Fortsätt STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Opausa och fortsätt datorspelaren STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Visa debug-utskrifter för denna datorspelare From 8a33e988340e6a4021e18f1c7b412c8ce53572fb Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sat, 19 Jun 2021 22:31:23 +0100 Subject: [PATCH 24/53] Fix #8169: nullptr dereference when autoreplacing vehicle with no orders (#9387) --- src/autoreplace_cmd.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 9e82944b64..4f9cf92bb4 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -207,6 +207,7 @@ static int GetIncompatibleRefitOrderIdForAutoreplace(const Vehicle *v, EngineID const Vehicle *u = (v->type == VEH_TRAIN) ? v->First() : v; const OrderList *orders = u->orders.list; + if (orders == nullptr) return -1; for (VehicleOrderID i = 0; i < orders->GetNumOrders(); i++) { o = orders->GetOrderAt(i); if (!o->IsRefit()) continue; From 6a05839d8d26eaaaae5b5df2948b77f5f0993499 Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 20 Jun 2021 18:53:19 +0000 Subject: [PATCH 25/53] Update: Translations from eints swedish: 1 change by kustridaren korean: 1 change by telk5093 --- src/lang/korean.txt | 2 +- src/lang/swedish.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index d9adccf79b..ef3e85fa50 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -1654,7 +1654,7 @@ STR_CONFIG_SETTING_TOWN_FOUNDING :게임 도중 STR_CONFIG_SETTING_TOWN_FOUNDING_HELPTEXT :플레이어가 게임 중에 새로운 도시를 설립하는 것을 허용합니다. STR_CONFIG_SETTING_TOWN_FOUNDING_FORBIDDEN :금지 STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :허용 -STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :허용, 도시 구조 선택 가능 +STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :허용, 도로 모양 선택 가능 STR_CONFIG_SETTING_TOWN_CARGOGENMODE :도시 화물 생성: {STRING} STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :도시의 전반적인 인구에 따라, 도시가 얼마나 많은 화물을 생산하는 지를 설정합니다.{}제곱 성장: 도시의 규모가 2배 커지면 승객을 4배 더 생산합니다.{}선형 성장: 도시의 규모가 2배 커지면 승객을 2배 더 생산합니다. STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :제곱 (기본) diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index a5baf80549..9de23c23e9 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -884,6 +884,7 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventionen har gått ut:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventionen gäller inte längre:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ny subvention:{}{}Första transporten av {STRING} från {STRING} till {STRING} får {NUM} års subvention från kommunen! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger dubbelt så mycket nästa {NUM} år{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i {TOWN}!{}{}Vägombyggnadsprogram bekostat av {STRING} medför 6 månader av elände för bilister! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! From 8c1b89e1079e411a2a87f2faae4c8546de6979de Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 22 Jun 2021 18:55:02 +0000 Subject: [PATCH 26/53] Update: Translations from eints english (us): 9 changes by 2TallTyler --- src/lang/english_US.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index f62da4cf90..7550f8314e 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -883,6 +883,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING} to {STRING} will now not attract a subsidy STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING} to {STRING} is no longer subsidized +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} service from {STRING} to {STRING} will attract a {NUM} year subsidy from the local authority! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay 50% extra for the next {NUM} year{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay double rates for the next {NUM} year{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay triple rates for the next {NUM} year{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {STRING}!{}{}{STRING} service from {STRING} to {STRING} will pay quadruple rates for the next {NUM} year{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding program funded by {STRING} brings 6 months of misery to motorists! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopoly! @@ -1198,6 +1203,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Vehicle breakdo STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Control how often inadequately maintained vehicles may break down STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subsidy multiplier: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Set how much is paid for subsidized connections +STR_CONFIG_SETTING_SUBSIDY_DURATION :Subsidy duration: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Set the number of years for which a subsidy is awarded +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} year{P "" s} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :No subsidies STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Construction costs: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Set level of construction and purchase costs STR_CONFIG_SETTING_RECESSIONS :Recessions: {STRING} From 0d5d3083bd6f0f3c51b15d58a6cb525912e1b775 Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Mon, 21 Jun 2021 23:37:49 +0200 Subject: [PATCH 27/53] Codechange: [OSX] Use more exact enum names where introduced with the 10.12 SDK. The enum values still have the exact same numerical values, but the 10.12 SDK introduced more explicit names (e.g. like NSEventTypeApplicationDefined instead of NSApplicationDefined) for several enum constants. Use them when available. --- src/os/macosx/macos.mm | 4 +-- src/os/macosx/osx_stdafx.h | 4 +++ src/video/cocoa/cocoa_v.mm | 28 ++++++++++++++++++--- src/video/cocoa/cocoa_wnd.mm | 47 +++++++++++++++++++++++++----------- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/os/macosx/macos.mm b/src/os/macosx/macos.mm index 6f0ab8d63a..90bcd6dc40 100644 --- a/src/os/macosx/macos.mm +++ b/src/os/macosx/macos.mm @@ -191,13 +191,13 @@ const char *GetCurrentLocale(const char *) bool GetClipboardContents(char *buffer, const char *last) { NSPasteboard *pb = [ NSPasteboard generalPasteboard ]; - NSArray *types = [ NSArray arrayWithObject:NSStringPboardType ]; + NSArray *types = [ NSArray arrayWithObject:NSPasteboardTypeString ]; NSString *bestType = [ pb availableTypeFromArray:types ]; /* Clipboard has no text data available. */ if (bestType == nil) return false; - NSString *string = [ pb stringForType:NSStringPboardType ]; + NSString *string = [ pb stringForType:NSPasteboardTypeString ]; if (string == nil || [ string length ] == 0) return false; strecpy(buffer, [ string UTF8String ], last); diff --git a/src/os/macosx/osx_stdafx.h b/src/os/macosx/osx_stdafx.h index e147fcf74c..9c4276d055 100644 --- a/src/os/macosx/osx_stdafx.h +++ b/src/os/macosx/osx_stdafx.h @@ -26,6 +26,10 @@ #define HAVE_OSX_1011_SDK #endif +#ifdef MAC_OS_X_VERSION_10_12 +#define HAVE_OSX_1012_SDK +#endif + /* It would seem that to ensure backward compatibility we have to ensure that we have defined MAC_OS_X_VERSION_10_x everywhere */ #ifndef MAC_OS_X_VERSION_10_3 #define MAC_OS_X_VERSION_10_3 1030 diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 2a8737333e..f43ea9b28a 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -45,6 +45,17 @@ #import /* gettimeofday */ #include +/* The 10.12 SDK added new names for some enum constants and + * deprecated the old ones. As there's no functional change in any + * way, just use a define for older SDKs to the old names. */ +#ifndef HAVE_OSX_1012_SDK +# define NSEventModifierFlagCommand NSCommandKeyMask +# define NSEventModifierFlagControl NSControlKeyMask +# define NSEventModifierFlagOption NSAlternateKeyMask +# define NSEventModifierFlagShift NSShiftKeyMask +# define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask +#endif + /** * Important notice regarding all modifications!!!!!!! * There are certain limitations because the file is objective C++. @@ -360,7 +371,11 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) NSRect contentRect = NSMakeRect(0, 0, width, height); /* Create main window. */ +#ifdef HAVE_OSX_1012_SDK + unsigned int style = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable; +#else unsigned int style = NSTitledWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask; +#endif this->window = [ [ OTTD_CocoaWindow alloc ] initWithContentRect:contentRect styleMask:style backing:NSBackingStoreBuffered defer:NO driver:this ]; if (this->window == nil) { Debug(driver, 0, "Could not create the Cocoa window."); @@ -376,7 +391,7 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) behavior |= NSWindowCollectionBehaviorFullScreenPrimary; [ this->window setCollectionBehavior:behavior ]; - NSButton* fullscreenButton = [ this->window standardWindowButton:NSWindowFullScreenButton ]; + NSButton* fullscreenButton = [ this->window standardWindowButton:NSWindowZoomButton ]; [ fullscreenButton setAction:@selector(toggleFullScreen:) ]; [ fullscreenButton setTarget:this->window ]; } @@ -430,7 +445,12 @@ bool VideoDriver_Cocoa::MakeWindow(int width, int height) */ bool VideoDriver_Cocoa::PollEvent() { - NSEvent *event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[ NSDate distantPast ] inMode:NSDefaultRunLoopMode dequeue:YES ]; +#ifdef HAVE_OSX_1012_SDK + NSEventMask mask = NSEventMaskAny; +#else + NSEventMask mask = NSAnyEventMask; +#endif + NSEvent *event = [ NSApp nextEventMatchingMask:mask untilDate:[ NSDate distantPast ] inMode:NSDefaultRunLoopMode dequeue:YES ]; if (event == nil) return false; @@ -445,8 +465,8 @@ void VideoDriver_Cocoa::InputLoop() bool old_ctrl_pressed = _ctrl_pressed; - _ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0; - _shift_pressed = (cur_mods & NSShiftKeyMask) != 0; + _ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSEventModifierFlagControl : NSEventModifierFlagCommand)) != 0; + _shift_pressed = (cur_mods & NSEventModifierFlagShift) != 0; #if defined(_DEBUG) this->fast_forward_key_pressed = _shift_pressed; diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index c0a1bb694c..1f470a9481 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -37,6 +37,16 @@ /* Table data for key mapping. */ #include "cocoa_keys.h" +/* The 10.12 SDK added new names for some enum constants and + * deprecated the old ones. As there's no functional change in any + * way, just use a define for older SDKs to the old names. */ +#ifndef HAVE_OSX_1012_SDK +# define NSEventModifierFlagCommand NSCommandKeyMask +# define NSEventModifierFlagControl NSControlKeyMask +# define NSEventModifierFlagOption NSAlternateKeyMask +# define NSEventModifierFlagShift NSShiftKeyMask +# define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask +#endif /** * Important notice regarding all modifications!!!!!!! @@ -135,7 +145,12 @@ static std::vector NSStringToUTF32(NSString *s) [ NSApp stop:self ]; /* Send an empty event to return from the run loop. Without that, application is stuck waiting for an event. */ - NSEvent *event = [ NSEvent otherEventWithType:NSApplicationDefined location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil subtype:0 data1:0 data2:0 ]; +#ifdef HAVE_OSX_1012_SDK + NSEventType type = NSEventTypeApplicationDefined; +#else + NSEventType type = NSApplicationDefined; +#endif + NSEvent *event = [ NSEvent otherEventWithType:type location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil subtype:0 data1:0 data2:0 ]; [ NSApp postEvent:event atStart:YES ]; } @@ -207,7 +222,7 @@ static void setApplicationMenu() [ appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h" ]; NSMenuItem *menuItem = [ appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h" ]; - [ menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask) ]; + [ menuItem setKeyEquivalentModifierMask:(NSEventModifierFlagOption | NSEventModifierFlagCommand) ]; [ appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@"" ]; @@ -329,7 +344,11 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel @autoreleasepool { NSAlert *alert = [ [ NSAlert alloc ] init ]; +#ifdef HAVE_OSX_1012_SDK + [ alert setAlertStyle: NSAlertStyleCritical ]; +#else [ alert setAlertStyle: NSCriticalAlertStyle ]; +#endif [ alert setMessageText:[ NSString stringWithUTF8String:title ] ]; [ alert setInformativeText:[ NSString stringWithUTF8String:message ] ]; [ alert addButtonWithTitle: [ NSString stringWithUTF8String:buttonLabel ] ]; @@ -536,8 +555,8 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel - (BOOL)emulateRightButton:(NSEvent *)event { uint32 keymask = 0; - if (_settings_client.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask; - if (_settings_client.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask; + if (_settings_client.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSEventModifierFlagCommand; + if (_settings_client.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSEventModifierFlagControl; return (event.modifierFlags & keymask) != 0; } @@ -653,18 +672,18 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel case QZ_RETURN: case QZ_f: - if (down && (modifiers & NSCommandKeyMask)) { + if (down && (modifiers & NSEventModifierFlagCommand)) { VideoDriver::GetInstance()->ToggleFullscreen(!_fullscreen); } break; case QZ_v: - if (down && EditBoxInGlobalFocus() && (modifiers & (NSCommandKeyMask | NSControlKeyMask))) { + if (down && EditBoxInGlobalFocus() && (modifiers & (NSEventModifierFlagCommand | NSEventModifierFlagControl))) { HandleKeypress(WKC_CTRL | 'V', unicode); } break; case QZ_u: - if (down && EditBoxInGlobalFocus() && (modifiers & (NSCommandKeyMask | NSControlKeyMask))) { + if (down && EditBoxInGlobalFocus() && (modifiers & (NSEventModifierFlagCommand | NSEventModifierFlagControl))) { HandleKeypress(WKC_CTRL | 'U', unicode); } break; @@ -676,10 +695,10 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel auto vk = std::find_if(std::begin(_vk_mapping), std::end(_vk_mapping), [=](const CocoaVkMapping &m) { return m.vk_from == keycode; }); uint32 pressed_key = vk != std::end(_vk_mapping) ? vk->map_to : 0; - if (modifiers & NSShiftKeyMask) pressed_key |= WKC_SHIFT; - if (modifiers & NSControlKeyMask) pressed_key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META); - if (modifiers & NSAlternateKeyMask) pressed_key |= WKC_ALT; - if (modifiers & NSCommandKeyMask) pressed_key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL); + if (modifiers & NSEventModifierFlagShift) pressed_key |= WKC_SHIFT; + if (modifiers & NSEventModifierFlagControl) pressed_key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META); + if (modifiers & NSEventModifierFlagOption) pressed_key |= WKC_ALT; + if (modifiers & NSEventModifierFlagCommand) pressed_key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL); static bool console = false; @@ -715,7 +734,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel case QZ_q: case QZ_h: case QZ_m: - if (event.modifierFlags & NSCommandKeyMask) { + if (event.modifierFlags & NSEventModifierFlagCommand) { [ self interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; } break; @@ -744,7 +763,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel case QZ_q: case QZ_h: case QZ_m: - if (event.modifierFlags & NSCommandKeyMask) { + if (event.modifierFlags & NSEventModifierFlagCommand) { [ self interpretKeyEvents:[ NSArray arrayWithObject:event ] ]; } break; @@ -765,7 +784,7 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel if (self->_current_mods == newMods) return; /* Iterate through the bits, testing each against the current modifiers */ - for (unsigned int i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) { + for (unsigned int i = 0, bit = NSEventModifierFlagCapsLock; bit <= NSEventModifierFlagCommand; bit <<= 1, ++i) { unsigned int currentMask, newMask; currentMask = self->_current_mods & bit; From 883e21dbb743831c3e100043717909e5819174ce Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 22 Jun 2021 01:40:40 +0200 Subject: [PATCH 28/53] Codechange: [OSX] We use OpenGL even if Apple doesn't like it. --- src/video/cocoa/cocoa_ogl.mm | 2 ++ src/video/opengl.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/video/cocoa/cocoa_ogl.mm b/src/video/cocoa/cocoa_ogl.mm index 96c3ea1bfe..81222d2abf 100644 --- a/src/video/cocoa/cocoa_ogl.mm +++ b/src/video/cocoa/cocoa_ogl.mm @@ -12,6 +12,8 @@ #include "../../stdafx.h" #include "../../os/macosx/macos.h" +#define GL_SILENCE_DEPRECATION + #define Rect OTTDRect #define Point OTTDPoint #import diff --git a/src/video/opengl.cpp b/src/video/opengl.cpp index 6e37db03ba..8ac12b959a 100644 --- a/src/video/opengl.cpp +++ b/src/video/opengl.cpp @@ -22,6 +22,7 @@ #define GL_GLEXT_PROTOTYPES #if defined(__APPLE__) +# define GL_SILENCE_DEPRECATION # include #else # include From 37116a7575c1dd96ae93c11ffbae64358d59d4aa Mon Sep 17 00:00:00 2001 From: Michael Lutz Date: Tue, 22 Jun 2021 01:41:15 +0200 Subject: [PATCH 29/53] Codechange: [OSX] Remove old code that has no effect on current OSX versions. --- src/video/cocoa/cocoa_ogl.mm | 1 - src/video/cocoa/cocoa_wnd.h | 1 - src/video/cocoa/cocoa_wnd.mm | 17 ----------------- 3 files changed, 19 deletions(-) diff --git a/src/video/cocoa/cocoa_ogl.mm b/src/video/cocoa/cocoa_ogl.mm index 81222d2abf..af9839a1c5 100644 --- a/src/video/cocoa/cocoa_ogl.mm +++ b/src/video/cocoa/cocoa_ogl.mm @@ -152,7 +152,6 @@ static bool _allowSoftware; { if (self = [ super initWithFrame:frameRect ]) { /* We manage our content updates ourselves. */ - self.wantsBestResolutionOpenGLSurface = _allow_hidpi_window ? YES : NO; self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; /* Create backing layer. */ diff --git a/src/video/cocoa/cocoa_wnd.h b/src/video/cocoa/cocoa_wnd.h index f8b9385ac2..3ddd5a4f04 100644 --- a/src/video/cocoa/cocoa_wnd.h +++ b/src/video/cocoa/cocoa_wnd.h @@ -32,7 +32,6 @@ extern NSString *OTTDMainLaunchGameEngine; @interface OTTD_CocoaWindow : NSWindow - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag driver:(VideoDriver_Cocoa *)drv; -- (void)display; - (void)setFrame:(NSRect)frameRect display:(BOOL)flag; @end diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 1f470a9481..05b55e2a83 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -405,23 +405,6 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel return self; } -/** - * This method fires just before the window deminaturizes from the Dock. - * We'll save the current visible surface, let the window manager redraw any - * UI elements, and restore the surface. This way, no expose event - * is required, and the deminiaturize works perfectly. - */ -- (void)display -{ - /* save current visible surface */ - [ self cacheImageInRect:[ driver->cocoaview frame ] ]; - - /* let the window manager redraw controls, border, etc */ - [ super display ]; - - /* restore visible surface */ - [ self restoreCachedImage ]; -} /** * Define the rectangle we draw our window in */ From 95a94dcf90847463f8c9a249f15ee9fe5dc14247 Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 25 Jun 2021 18:50:57 +0000 Subject: [PATCH 30/53] Update: Translations from eints swedish: 1 change by joeax910 dutch: 9 changes by Afoklala --- src/lang/dutch.txt | 9 +++++++++ src/lang/swedish.txt | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 4deb9d1df2..c4cff623c3 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -883,6 +883,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subsidieaanbod is verlopen:{}{}{STRING} van {STRING} naar {STRING} wordt nu niet meer gesubsidieerd STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidie ingetrokken:{}{}{STRING}route van {STRING} naar {STRING} wordt nu niet meer gesubsidieerd +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Subsidie aangeboden:{}{}Eerste {STRING}route van {STRING} naar {STRING} krijgt {NUM} jaar lang subsidie van de gemeente! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt de volgende {NUM} jaar 50% extra betaald! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt de volgende {NUM} jaar dubbel betaald! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt devolgende {NUM} jaar driedubbel betaald! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subsidie toegekend aan {STRING}!{}{}{STRING}route van {STRING} naar {STRING} krijgt de volgende {NUM} jaar vierdubbel betaald! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Verkeerschaos in {TOWN}!{}{}Wegreconstructie betaald door {STRING} zorgt voor 6 maanden van misère bij weggebruikers! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopolie! @@ -1198,6 +1203,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Voertuigstoring STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Bepaal hoe vaak onvoldoende onderhouden voertuigen kapot kunnen gaan STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subsidiefactor: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Instellen hoeveel wordt betaald voor gesubsidieerde verbindingen +STR_CONFIG_SETTING_SUBSIDY_DURATION :Duur van subsidie: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Bepaal het aantal jaar dat de subsidie wordt verleend +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} jaar{P "" ""} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Geen subsidie STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Bouwkosten: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Het niveau van bouw- en aankoopkosten instellen STR_CONFIG_SETTING_RECESSIONS :Recessies: {STRING} diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 9de23c23e9..94b67e4c6f 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -1769,7 +1769,7 @@ STR_CONFIG_SETTING_LOCALISATION :{ORANGE}Lokalis STR_CONFIG_SETTING_GRAPHICS :{ORANGE}Grafik STR_CONFIG_SETTING_SOUND :{ORANGE}Ljud STR_CONFIG_SETTING_INTERFACE :{ORANGE}Gränssnitt -STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE}Generelt +STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE}Generellt STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Vyfönster STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Konstruktion STR_CONFIG_SETTING_ADVISORS :{ORANGE} Nyheter / Rådgivare From 1ed7afc0a8f40325dca8f4bef0b46e5b8dc06713 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 26 Jun 2021 13:51:29 +0200 Subject: [PATCH 31/53] Change: [GitHub] use an issue form to let people fill in bug report / crashes (#9400) --- .github/ISSUE_TEMPLATE/bug.md | 17 ------------- .github/ISSUE_TEMPLATE/bug.yaml | 41 +++++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/crash.md | 12 --------- .github/ISSUE_TEMPLATE/crash.yaml | 37 ++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 29 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/bug.yaml delete mode 100644 .github/ISSUE_TEMPLATE/crash.md create mode 100644 .github/ISSUE_TEMPLATE/crash.yaml diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index 4801435901..0000000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Bugs -about: Found a bug in OpenTTD? -title: "Bug Report" ---- - -## Version of OpenTTD - - -## Expected result - - -## Actual result - - -## Steps to reproduce - diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml new file mode 100644 index 0000000000..39168fe5f4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -0,0 +1,41 @@ +name: Bug Report +description: Found a bug in OpenTTD? +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: input + id: version + attributes: + label: Version of OpenTTD + description: Fill in below what version of OpenTTD you are using, including your OS. + placeholder: ex. 1.11.2, Windows 10 + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected result + description: Describe in a few words what you expected to happen. + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual result + description: Describe in a few words what actually happens. + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: As detailed as possible, please tell us how we can reproduce this. Feel free to attach a savegame (zip it first) to make it more clear. + placeholder: | + 1. Loaded the attached savegame. + 2. Click on the button left of that other icon. + 3. The window doesn't open. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/crash.md b/.github/ISSUE_TEMPLATE/crash.md deleted file mode 100644 index 00f62f05c9..0000000000 --- a/.github/ISSUE_TEMPLATE/crash.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Crash -about: Did OpenTTD crash? -title: "Crash Report" ---- - - -## Version of OpenTTD - - -## Steps to reproduce - diff --git a/.github/ISSUE_TEMPLATE/crash.yaml b/.github/ISSUE_TEMPLATE/crash.yaml new file mode 100644 index 0000000000..b5b6531105 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/crash.yaml @@ -0,0 +1,37 @@ +name: Crash +description: Did OpenTTD crash? +title: "[Crash]: " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this crash report! + - type: input + id: version + attributes: + label: Version of OpenTTD + description: Fill in below what version of OpenTTD you are using, including your OS. + placeholder: ex. 1.11.2, Windows 10 + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: Please spend a few words if you can reproduce this problem. + placeholder: | + 1. Bought a new train. + 2. The game crashed. + validations: + required: true + - type: textarea + id: crashlogs + attributes: + label: Upload crash files + description: With the `crash.log`, `crash.dmp`, and `crash.sav` we can analyze the crash in detail; this way you allow us to easier triage and fix the problem. + placeholder: | + 1. Zip the `crash.log`, `crash.dmp` and `crash.sav`. + 2. Click on this field. + 3. Drag and drop the zip file in here. + validations: + required: true From 74186998a2ab7f45053aa771d179dd8aa24f0d86 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 17 Jun 2021 10:34:43 +0200 Subject: [PATCH 32/53] Codechange: use _cur_palette the same in all the drivers It was a bit of a mixed bag. With this change, gfx.cpp is in control who accesses _cur_palette from the video-drivers. --- src/gfx.cpp | 24 ++++++++++++++++++++++++ src/gfx_func.h | 1 + src/video/allegro_v.cpp | 36 ++++++++++++++++++------------------ src/video/cocoa/cocoa_ogl.mm | 10 +++++----- src/video/cocoa/cocoa_v.mm | 36 ++++++++++++++++++------------------ src/video/sdl2_default_v.cpp | 10 ++++------ src/video/sdl2_opengl_v.cpp | 8 +++----- src/video/sdl2_v.cpp | 9 ++------- src/video/sdl2_v.h | 2 +- src/video/sdl_v.cpp | 33 ++++++++++++++------------------- src/video/win32_v.cpp | 24 ++++++++---------------- 11 files changed, 98 insertions(+), 95 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index ff2c80bfc0..46870dc42b 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1201,6 +1201,30 @@ void GfxInitPalettes() DoPaletteAnimations(); } +/** + * Copy the current palette if the palette was updated. + * Used by video-driver to get a current up-to-date version of the palette, + * to avoid two threads accessing the same piece of memory (with a good chance + * one is already updating the palette while the other is drawing based on it). + * @param local_palette The location to copy the palette to. + * @param force_copy Whether to ignore if there is an update for the palette. + * @return True iff a copy was done. + */ +bool CopyPalette(Palette &local_palette, bool force_copy) +{ + if (!force_copy && _cur_palette.count_dirty == 0) return false; + + local_palette = _cur_palette; + _cur_palette.count_dirty = 0; + + if (force_copy) { + local_palette.first_dirty = 0; + local_palette.count_dirty = 256; + } + + return true; +} + #define EXTR(p, q) (((uint16)(palette_animation_counter * (p)) * (q)) >> 16) #define EXTR2(p, q) (((uint16)(~palette_animation_counter * (p)) * (q)) >> 16) diff --git a/src/gfx_func.h b/src/gfx_func.h index 1d138f3d5e..f23f8bfee7 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -121,6 +121,7 @@ void DrawDirtyBlocks(); void AddDirtyBlock(int left, int top, int right, int bottom); void MarkWholeScreenDirty(); +bool CopyPalette(Palette &local_palette, bool force_copy = false); void GfxInitPalettes(); void CheckBlitter(); diff --git a/src/video/allegro_v.cpp b/src/video/allegro_v.cpp index 6693932c70..3a0a4beb01 100644 --- a/src/video/allegro_v.cpp +++ b/src/video/allegro_v.cpp @@ -43,6 +43,7 @@ static BITMAP *_allegro_screen; #define MAX_DIRTY_RECTS 100 static PointDimension _dirty_rects[MAX_DIRTY_RECTS]; static int _num_dirty_rects; +static Palette _local_palette; ///< Current palette to use for drawing. void VideoDriver_Allegro::MakeDirty(int left, int top, int width, int height) { @@ -80,9 +81,9 @@ static void UpdatePalette(uint start, uint count) uint end = start + count; for (uint i = start; i != end; i++) { - pal[i].r = _cur_palette.palette[i].r / 4; - pal[i].g = _cur_palette.palette[i].g / 4; - pal[i].b = _cur_palette.palette[i].b / 4; + pal[i].r = _local_palette.palette[i].r / 4; + pal[i].g = _local_palette.palette[i].g / 4; + pal[i].b = _local_palette.palette[i].b / 4; pal[i].filler = 0; } @@ -96,25 +97,24 @@ static void InitPalette() void VideoDriver_Allegro::CheckPaletteAnim() { - if (_cur_palette.count_dirty != 0) { - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + if (!CopyPalette(_local_palette)) return; - switch (blitter->UsePaletteAnimation()) { - case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - UpdatePalette(_cur_palette.first_dirty, _cur_palette.count_dirty); - break; + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - case Blitter::PALETTE_ANIMATION_BLITTER: - blitter->PaletteAnimate(_cur_palette); - break; + switch (blitter->UsePaletteAnimation()) { + case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: + UpdatePalette(_local_palette.first_dirty, _local_palette.count_dirty); + break; - case Blitter::PALETTE_ANIMATION_NONE: - break; + case Blitter::PALETTE_ANIMATION_BLITTER: + blitter->PaletteAnimate(_local_palette); + break; - default: - NOT_REACHED(); - } - _cur_palette.count_dirty = 0; + case Blitter::PALETTE_ANIMATION_NONE: + break; + + default: + NOT_REACHED(); } } diff --git a/src/video/cocoa/cocoa_ogl.mm b/src/video/cocoa/cocoa_ogl.mm index af9839a1c5..30c299d3d5 100644 --- a/src/video/cocoa/cocoa_ogl.mm +++ b/src/video/cocoa/cocoa_ogl.mm @@ -37,6 +37,8 @@ #import #import +static Palette _local_palette; ///< Current palette to use for drawing. + /** * Important notice regarding all modifications!!!!!!! @@ -304,17 +306,15 @@ void VideoDriver_CocoaOpenGL::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); - if (_cur_palette.count_dirty != 0) { + if (CopyPalette(_local_palette)) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); /* Always push a changed palette to OpenGL. */ CGLSetCurrentContext(this->gl_context); - OpenGLBackend::Get()->UpdatePalette(_cur_palette.palette, _cur_palette.first_dirty, _cur_palette.count_dirty); + OpenGLBackend::Get()->UpdatePalette(_local_palette.palette, _local_palette.first_dirty, _local_palette.count_dirty); if (blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_BLITTER) { - blitter->PaletteAnimate(_cur_palette); + blitter->PaletteAnimate(_local_palette); } - - _cur_palette.count_dirty = 0; } [ CATransaction begin ]; diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index f43ea9b28a..2f0f2a746a 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -72,6 +72,7 @@ #endif bool _cocoa_video_started = false; +static Palette _local_palette; ///< Current palette to use for drawing. extern bool _tab_is_down; @@ -714,9 +715,9 @@ void VideoDriver_CocoaQuartz::UpdatePalette(uint first_color, uint num_colors) for (uint i = first_color; i < first_color + num_colors; i++) { uint32 clr = 0xff000000; - clr |= (uint32)_cur_palette.palette[i].r << 16; - clr |= (uint32)_cur_palette.palette[i].g << 8; - clr |= (uint32)_cur_palette.palette[i].b; + clr |= (uint32)_local_palette.palette[i].r << 16; + clr |= (uint32)_local_palette.palette[i].g << 8; + clr |= (uint32)_local_palette.palette[i].b; this->palette[i] = clr; } @@ -725,25 +726,24 @@ void VideoDriver_CocoaQuartz::UpdatePalette(uint first_color, uint num_colors) void VideoDriver_CocoaQuartz::CheckPaletteAnim() { - if (_cur_palette.count_dirty != 0) { - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + if (!CopyPalette(_local_palette)) return; - switch (blitter->UsePaletteAnimation()) { - case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - this->UpdatePalette(_cur_palette.first_dirty, _cur_palette.count_dirty); - break; + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - case Blitter::PALETTE_ANIMATION_BLITTER: - blitter->PaletteAnimate(_cur_palette); - break; + switch (blitter->UsePaletteAnimation()) { + case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: + this->UpdatePalette(_local_palette.first_dirty, _local_palette.count_dirty); + break; - case Blitter::PALETTE_ANIMATION_NONE: - break; + case Blitter::PALETTE_ANIMATION_BLITTER: + blitter->PaletteAnimate(_local_palette); + break; - default: - NOT_REACHED(); - } - _cur_palette.count_dirty = 0; + case Blitter::PALETTE_ANIMATION_NONE: + break; + + default: + NOT_REACHED(); } } diff --git a/src/video/sdl2_default_v.cpp b/src/video/sdl2_default_v.cpp index 4db1c33cee..e164e499e8 100644 --- a/src/video/sdl2_default_v.cpp +++ b/src/video/sdl2_default_v.cpp @@ -62,9 +62,7 @@ void VideoDriver_SDL_Default::MakePalette() if (_sdl_palette == nullptr) usererror("SDL2: Couldn't allocate palette: %s", SDL_GetError()); } - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - this->local_palette = _cur_palette; + CopyPalette(this->local_palette, true); this->UpdatePalette(); if (_sdl_surface != _sdl_real_surface) { @@ -96,9 +94,9 @@ void VideoDriver_SDL_Default::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); - if (IsEmptyRect(this->dirty_rect) && _cur_palette.count_dirty == 0) return; + if (IsEmptyRect(this->dirty_rect) && this->local_palette.count_dirty == 0) return; - if (_cur_palette.count_dirty != 0) { + if (this->local_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); switch (blitter->UsePaletteAnimation()) { @@ -117,7 +115,7 @@ void VideoDriver_SDL_Default::Paint() default: NOT_REACHED(); } - _cur_palette.count_dirty = 0; + this->local_palette.count_dirty = 0; } SDL_Rect r = { this->dirty_rect.left, this->dirty_rect.top, this->dirty_rect.right - this->dirty_rect.left, this->dirty_rect.bottom - this->dirty_rect.top }; diff --git a/src/video/sdl2_opengl_v.cpp b/src/video/sdl2_opengl_v.cpp index 003e194380..596a63a28f 100644 --- a/src/video/sdl2_opengl_v.cpp +++ b/src/video/sdl2_opengl_v.cpp @@ -146,9 +146,7 @@ bool VideoDriver_SDL_OpenGL::AllocateBackingStore(int w, int h, bool force) SDL_GL_SwapWindow(this->sdl_window); _screen.dst_ptr = this->GetVideoPointer(); - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - this->local_palette = _cur_palette; + CopyPalette(this->local_palette, true); return res; } @@ -173,7 +171,7 @@ void VideoDriver_SDL_OpenGL::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); - if (_cur_palette.count_dirty != 0) { + if (this->local_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); /* Always push a changed palette to OpenGL. */ @@ -182,7 +180,7 @@ void VideoDriver_SDL_OpenGL::Paint() blitter->PaletteAnimate(this->local_palette); } - _cur_palette.count_dirty = 0; + this->local_palette.count_dirty = 0; } OpenGLBackend::Get()->Paint(); diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 98c04fd85c..875491652e 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -43,9 +43,7 @@ void VideoDriver_SDL_Base::MakeDirty(int left, int top, int width, int height) void VideoDriver_SDL_Base::CheckPaletteAnim() { - if (_cur_palette.count_dirty == 0) return; - - this->local_palette = _cur_palette; + if (!CopyPalette(this->local_palette)) return; this->MakeDirty(0, 0, _screen.width, _screen.height); } @@ -131,10 +129,7 @@ void VideoDriver_SDL_Base::ClientSizeChanged(int w, int h, bool force) { /* Allocate backing store of the new size. */ if (this->AllocateBackingStore(w, h, force)) { - /* Mark all palette colours dirty. */ - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - this->local_palette = _cur_palette; + CopyPalette(this->local_palette, true); BlitterFactory::GetCurrentBlitter()->PostResize(); diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h index d706cc6654..48c597d4fd 100644 --- a/src/video/sdl2_v.h +++ b/src/video/sdl2_v.h @@ -45,7 +45,7 @@ public: protected: struct SDL_Window *sdl_window; ///< Main SDL window. - Palette local_palette; ///< Copy of _cur_palette. + Palette local_palette; ///< Current palette to use for drawing. bool buffer_locked; ///< Video buffer was locked by the main thread. Rect dirty_rect; ///< Rectangle encompassing the dirty area of the video buffer. diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index 644978e1f3..1b180d3b8b 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -106,35 +106,30 @@ static void UpdatePalette(bool init = false) static void InitPalette() { - _local_palette = _cur_palette; - _local_palette.first_dirty = 0; - _local_palette.count_dirty = 256; + CopyPalette(_local_palette, true); UpdatePalette(true); } void VideoDriver_SDL::CheckPaletteAnim() { - _local_palette = _cur_palette; + if (!CopyPalette(_local_palette)) return; - if (_cur_palette.count_dirty != 0) { - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - switch (blitter->UsePaletteAnimation()) { - case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - UpdatePalette(); - break; + switch (blitter->UsePaletteAnimation()) { + case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: + UpdatePalette(); + break; - case Blitter::PALETTE_ANIMATION_BLITTER: - blitter->PaletteAnimate(_local_palette); - break; + case Blitter::PALETTE_ANIMATION_BLITTER: + blitter->PaletteAnimate(_local_palette); + break; - case Blitter::PALETTE_ANIMATION_NONE: - break; + case Blitter::PALETTE_ANIMATION_NONE: + break; - default: - NOT_REACHED(); - } - _cur_palette.count_dirty = 0; + default: + NOT_REACHED(); } } diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index df0917ffa0..22b8f35412 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -42,8 +42,7 @@ bool _window_maximize; static Dimension _bck_resolution; DWORD _imm_props; -/** Local copy of the palette for use in the drawing thread. */ -static Palette _local_palette; +static Palette _local_palette; ///< Current palette to use for drawing. bool VideoDriver_Win32Base::ClaimMousePointer() { @@ -812,9 +811,7 @@ void VideoDriver_Win32Base::MakeDirty(int left, int top, int width, int height) void VideoDriver_Win32Base::CheckPaletteAnim() { - if (_cur_palette.count_dirty == 0) return; - - _local_palette = _cur_palette; + if (!CopyPalette(_local_palette)) return; this->MakeDirty(0, 0, _screen.width, _screen.height); } @@ -878,10 +875,7 @@ void VideoDriver_Win32Base::ClientSizeChanged(int w, int h, bool force) { /* Allocate backing store of the new size. */ if (this->AllocateBackingStore(w, h, force)) { - /* Mark all palette colours dirty. */ - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - _local_palette = _cur_palette; + CopyPalette(_local_palette, true); BlitterFactory::GetCurrentBlitter()->PostResize(); @@ -1078,9 +1072,7 @@ bool VideoDriver_Win32GDI::AfterBlitterChange() void VideoDriver_Win32GDI::MakePalette() { - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - _local_palette = _cur_palette; + CopyPalette(_local_palette, true); LOGPALETTE *pal = (LOGPALETTE*)alloca(sizeof(LOGPALETTE) + (256 - 1) * sizeof(PALETTEENTRY)); @@ -1135,7 +1127,7 @@ void VideoDriver_Win32GDI::Paint() HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, this->dib_sect); HPALETTE old_palette = SelectPalette(dc, this->gdi_palette, FALSE); - if (_cur_palette.count_dirty != 0) { + if (_local_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); switch (blitter->UsePaletteAnimation()) { @@ -1154,7 +1146,7 @@ void VideoDriver_Win32GDI::Paint() default: NOT_REACHED(); } - _cur_palette.count_dirty = 0; + _local_palette.count_dirty = 0; } BitBlt(dc, 0, 0, this->width, this->height, dc2, 0, 0, SRCCOPY); @@ -1474,7 +1466,7 @@ void VideoDriver_Win32OpenGL::Paint() { PerformanceMeasurer framerate(PFE_VIDEO); - if (_cur_palette.count_dirty != 0) { + if (_local_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); /* Always push a changed palette to OpenGL. */ @@ -1483,7 +1475,7 @@ void VideoDriver_Win32OpenGL::Paint() blitter->PaletteAnimate(_local_palette); } - _cur_palette.count_dirty = 0; + _local_palette.count_dirty = 0; } OpenGLBackend::Get()->Paint(); From 0013673fafc74034df77ce0588ea6d568f120b45 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 17 Jun 2021 10:38:04 +0200 Subject: [PATCH 33/53] Change: prevent palette updates during copying to the video driver ThreadSanitizer rightfully notices that the game-thread could update the palette while the draw-thread is copying it for local use. The odds of this are very small, but nevertheless, it does carry a very good point. It wouldn't hurt the application in any way, but it might cause visual glitches on the screen. --- src/gfx.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gfx.cpp b/src/gfx.cpp index 46870dc42b..9ccb036d25 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -51,6 +51,8 @@ static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of ofte DrawPixelInfo *_cur_dpi; byte _colour_gradient[COLOUR_END][8]; +static std::recursive_mutex _palette_mutex; ///< To coordinate access to _cur_palette. + static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE); static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE, ZoomLevel zoom = ZOOM_LVL_NORMAL); @@ -1197,6 +1199,7 @@ void DoPaletteAnimations(); void GfxInitPalettes() { + std::lock_guard lock(_palette_mutex); memcpy(&_cur_palette, &_palette, sizeof(_cur_palette)); DoPaletteAnimations(); } @@ -1212,6 +1215,8 @@ void GfxInitPalettes() */ bool CopyPalette(Palette &local_palette, bool force_copy) { + std::lock_guard lock(_palette_mutex); + if (!force_copy && _cur_palette.count_dirty == 0) return false; local_palette = _cur_palette; @@ -1230,6 +1235,8 @@ bool CopyPalette(Palette &local_palette, bool force_copy) void DoPaletteAnimations() { + std::lock_guard lock(_palette_mutex); + /* Animation counter for the palette animation. */ static int palette_animation_counter = 0; palette_animation_counter += 8; From cdf9caf8eae152d81ef17ed6c7f56e52d07dbe3f Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 21 Jun 2021 18:29:21 +0200 Subject: [PATCH 34/53] Codechange: [Network] Remove overload on NetworkValidateClientName Rename the zero-parameter NetworkValidateClientName to NetworkValidateOurClientName to make it clearer it is performed on our client name, and to make it a non-overloaded function to aid with the variant being added a few commits later --- src/network/network.cpp | 2 +- src/network/network_client.cpp | 2 +- src/network/network_func.h | 2 +- src/network/network_gui.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index a407d0d83e..9304048726 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -795,7 +795,7 @@ bool NetworkClientConnectGame(const std::string &connection_string, CompanyID de std::string resolved_connection_string = ParseGameConnectionString(connection_string, NETWORK_DEFAULT_PORT, &join_as).GetAddressAsString(false); if (!_network_available) return false; - if (!NetworkValidateClientName()) return false; + if (!NetworkValidateOurClientName()) return false; _network_join.connection_string = resolved_connection_string; _network_join.company = join_as; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index e4b60873fa..779ffe6fd7 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -1338,7 +1338,7 @@ bool NetworkValidateClientName(std::string &client_name) * See \c NetworkValidateClientName(char*) for details about the functionality. * @return True iff the client name is valid. */ -bool NetworkValidateClientName() +bool NetworkValidateOurClientName() { return NetworkValidateClientName(_settings_client.network.client_name); } diff --git a/src/network/network_func.h b/src/network/network_func.h index ec27d4b785..0dd9328eb6 100644 --- a/src/network/network_func.h +++ b/src/network/network_func.h @@ -36,7 +36,7 @@ extern StringList _network_ban_list; byte NetworkSpectatorCount(); bool NetworkIsValidClientName(const std::string_view client_name); -bool NetworkValidateClientName(); +bool NetworkValidateOurClientName(); bool NetworkValidateClientName(std::string &client_name); bool NetworkValidateServerName(std::string &server_name); void NetworkUpdateClientName(const std::string &client_name); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 04303e7ac5..52819660d5 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1263,7 +1263,7 @@ static WindowDesc _network_start_server_window_desc( static void ShowNetworkStartServerWindow() { - if (!NetworkValidateClientName()) return; + if (!NetworkValidateOurClientName()) return; CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); @@ -1557,7 +1557,7 @@ static WindowDesc _network_lobby_window_desc( */ static void ShowNetworkLobbyWindow(NetworkGameList *ngl) { - if (!NetworkValidateClientName()) return; + if (!NetworkValidateOurClientName()) return; CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_START); CloseWindowById(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME); From f029fd0f3bb8253a7cb9bfa0f9182619835b4512 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 21 Jun 2021 18:31:56 +0200 Subject: [PATCH 35/53] Codechange: remove overloading on UpdateServiceInterval One UpdateServiceInterval has two parameters to update the service interval for a vehicle type, the other for all vehicle types at once. Rename the latter to help with function resolution for the introduction of variants. --- src/settings.cpp | 2 +- src/table/settings/company_settings.ini | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index dab0fe08cb..b52a00f3af 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -833,7 +833,7 @@ static void UpdateConsists(int32 new_value) } /* Check service intervals of vehicles, newvalue is value of % or day based servicing */ -static void UpdateServiceInterval(int32 new_value) +static void UpdateAllServiceInterval(int32 new_value) { bool update_vehicles; VehicleDefaultSettings *vds; diff --git a/src/table/settings/company_settings.ini b/src/table/settings/company_settings.ini index 469e1aceae..71f99d5a21 100644 --- a/src/table/settings/company_settings.ini +++ b/src/table/settings/company_settings.ini @@ -8,7 +8,7 @@ ; company changes them, it changes for all players. [pre-amble] -static void UpdateServiceInterval(int32 new_value); +static void UpdateAllServiceInterval(int32 new_value); static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value); static void UpdateServiceInterval(VehicleType type, int32 new_value); @@ -77,7 +77,7 @@ var = vehicle.servint_ispercent def = false str = STR_CONFIG_SETTING_SERVINT_ISPERCENT strhelp = STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT -post_cb = UpdateServiceInterval +post_cb = UpdateAllServiceInterval [SDT_VAR] var = vehicle.servint_trains From f7f1d530b8d98fe06186e0ea68121310d87188d6 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 21 Jun 2021 18:33:37 +0200 Subject: [PATCH 36/53] Codechange: instead of "naked" initializer lists, declare the type in the saveload macros This to help variant's constructor to be able to resolve the constructor of the setting --- src/saveload/saveload.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 8456da4150..0ce46cbe98 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -608,7 +608,7 @@ struct SaveLoad { * @param extra Extra data to pass to the address callback function. * @note In general, it is better to use one of the SLE_* macros below. */ -#define SLE_GENERAL(cmd, base, variable, type, length, from, to, extra) {cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast(static_cast(std::addressof(static_cast(b)->variable))); }, extra, nullptr} +#define SLE_GENERAL(cmd, base, variable, type, length, from, to, extra) SaveLoad {cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast(static_cast(std::addressof(static_cast(b)->variable))); }, extra, nullptr} /** * Storage of a variable in some savegame versions. @@ -744,7 +744,7 @@ struct SaveLoad { * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLE_CONDNULL(length, from, to) {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} +#define SLE_CONDNULL(length, from, to) SaveLoad {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} /** * Only write byte during saving; never read it during loading. @@ -768,7 +768,7 @@ struct SaveLoad { * @param extra Extra data to pass to the address callback function. * @note In general, it is better to use one of the SLEG_* macros below. */ -#define SLEG_GENERAL(cmd, variable, type, length, from, to, extra) {cmd, type, length, from, to, sizeof(variable), [] (void *, size_t) -> void * { return static_cast(std::addressof(variable)); }, extra, nullptr} +#define SLEG_GENERAL(cmd, variable, type, length, from, to, extra) SaveLoad {cmd, type, length, from, to, sizeof(variable), [] (void *, size_t) -> void * { return static_cast(std::addressof(variable)); }, extra, nullptr} /** * Storage of a global variable in some savegame versions. @@ -823,7 +823,7 @@ struct SaveLoad { * @param from First savegame version that has the struct. * @param to Last savegame version that has the struct. */ -#define SLEG_CONDSTRUCT(handler, from, to) {SL_STRUCT, 0, 0, from, to, 0, nullptr, 0, new handler()} +#define SLEG_CONDSTRUCT(handler, from, to) SaveLoad {SL_STRUCT, 0, 0, from, to, 0, nullptr, 0, new handler()} /** * Storage of a global reference list in some savegame versions. @@ -849,7 +849,7 @@ struct SaveLoad { * @param from First savegame version that has the list. * @param to Last savegame version that has the list. */ -#define SLEG_CONDSTRUCTLIST(handler, from, to) {SL_STRUCTLIST, 0, 0, from, to, 0, nullptr, 0, new handler()} +#define SLEG_CONDSTRUCTLIST(handler, from, to) SaveLoad {SL_STRUCTLIST, 0, 0, from, to, 0, nullptr, 0, new handler()} /** * Storage of a global variable in every savegame version. @@ -918,7 +918,7 @@ struct SaveLoad { * @param from First savegame version that has the empty space. * @param to Last savegame version that has the empty space. */ -#define SLEG_CONDNULL(length, from, to) {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} +#define SLEG_CONDNULL(length, from, to) SaveLoad {SL_NULL, SLE_FILE_U8 | SLE_VAR_NULL, length, from, to, 0, nullptr, 0, nullptr} /** * Checks whether the savegame is below \a major.\a minor. From c93fcbcb286222f366c2e182a337c52c50fe36d5 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 21 Jun 2021 18:39:27 +0200 Subject: [PATCH 37/53] Codechange: introduce helper to convert from the iterated type to the actual SettingDesc --- src/settings.cpp | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index b52a00f3af..5e3ba5be74 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -93,6 +93,16 @@ typedef void SettingDescProcList(IniFile *ini, const char *grpname, StringList & static bool IsSignedVarMemType(VarType vt); +/** + * Helper to convert the type of the iterated settings description to a pointer to it. + * @param desc The type of the iterator of the value in SettingTable. + * @return The actual pointer to SettingDesc. + */ +static const SettingDesc *GetSettingDesc(const std::unique_ptr &desc) +{ + return desc.get(); +} + /** * Groups in openttd.cfg that are actually lists. */ @@ -511,7 +521,8 @@ static void IniLoadSettings(IniFile *ini, const SettingTable &settings_table, co IniGroup *group; IniGroup *group_def = ini->GetGroup(grpname); - for (auto &sd : settings_table) { + for (auto &desc : settings_table) { + const SettingDesc *sd = GetSettingDesc(desc); if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (sd->startup != only_startup) continue; @@ -587,7 +598,8 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co IniItem *item; char buf[512]; - for (auto &sd : settings_table) { + for (auto &desc : settings_table) { + const SettingDesc *sd = GetSettingDesc(desc); /* If the setting is not saved to the configuration * file, just continue with the next setting */ if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; @@ -1708,16 +1720,18 @@ void IntSettingDesc::ChangeValue(const void *object, int32 newval) const static const SettingDesc *GetSettingFromName(const std::string_view name, const SettingTable &settings) { /* First check all full names */ - for (auto &sd : settings) { + for (auto &desc : settings) { + const SettingDesc *sd = GetSettingDesc(desc); if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (sd->name == name) return sd.get(); + if (sd->name == name) return sd; } /* Then check the shortcut variant of the name. */ std::string short_name_suffix = std::string{ "." }.append(name); - for (auto &sd : settings) { + for (auto &desc : settings) { + const SettingDesc *sd = GetSettingDesc(desc); if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - if (StrEndsWith(sd->name, short_name_suffix)) return sd.get(); + if (StrEndsWith(sd->name, short_name_suffix)) return sd; } return nullptr; @@ -1730,7 +1744,8 @@ static const SettingDesc *GetSettingFromName(const std::string_view name, const */ void GetSettingSaveLoadByPrefix(std::string_view prefix, std::vector &saveloads) { - for (auto &sd : _settings) { + for (auto &desc : _settings) { + const SettingDesc *sd = GetSettingDesc(desc); if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (StrStartsWith(sd->name, prefix)) saveloads.push_back(sd->save); } @@ -1866,8 +1881,8 @@ bool SetSettingValue(const IntSettingDesc *sd, int32 value, bool force_newgame) void SetDefaultCompanySettings(CompanyID cid) { Company *c = Company::Get(cid); - for (auto &sd : _company_settings) { - const IntSettingDesc *int_setting = sd->AsIntSetting(); + for (auto &desc : _company_settings) { + const IntSettingDesc *int_setting = GetSettingDesc(desc)->AsIntSetting(); int_setting->MakeValueValidAndWrite(&c->settings, int_setting->def); } } @@ -1879,7 +1894,8 @@ void SyncCompanySettings() { const void *old_object = &Company::Get(_current_company)->settings; const void *new_object = &_settings_client.company; - for (auto &sd : _company_settings) { + for (auto &desc : _company_settings) { + const SettingDesc *sd = GetSettingDesc(desc); uint32 old_value = (uint32)sd->AsIntSetting()->Read(new_object); uint32 new_value = (uint32)sd->AsIntSetting()->Read(old_object); if (old_value != new_value) NetworkSendCommand(0, 0, new_value, CMD_CHANGE_COMPANY_SETTING, nullptr, sd->name, _local_company); @@ -1999,7 +2015,8 @@ void IConsoleListSettings(const char *prefilter) { IConsolePrint(CC_HELP, "All settings with their current value:"); - for (auto &sd : _settings) { + for (auto &desc : _settings) { + const SettingDesc *sd = GetSettingDesc(desc); if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (prefilter != nullptr && sd->name.find(prefilter) == std::string::npos) continue; char value[80]; @@ -2019,7 +2036,8 @@ void IConsoleListSettings(const char *prefilter) static std::vector GetSettingsDesc(const SettingTable &settings, bool is_loading) { std::vector saveloads; - for (auto &sd : settings) { + for (auto &desc : settings) { + const SettingDesc *sd = GetSettingDesc(desc); if (sd->flags & SF_NOT_IN_SAVE) continue; if (is_loading && (sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) { @@ -2050,7 +2068,8 @@ static void LoadSettings(const SettingTable &settings, void *object) if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many settings entries"); /* Ensure all IntSettings are valid (min/max could have changed between versions etc). */ - for (auto &sd : settings) { + for (auto &desc : settings) { + const SettingDesc *sd = GetSettingDesc(desc); if (sd->flags & SF_NOT_IN_SAVE) continue; if ((sd->flags & SF_NO_NETWORK_SYNC) && _networking && !_network_server) continue; if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; From f35e6c1c7fdaefc9153a54c089dbaa6e2549e6b1 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 21 Jun 2021 18:41:30 +0200 Subject: [PATCH 38/53] Codechange: use C-style strings instread of std::string in the SettingDesc constructor This as using std::string causes much more variables to be tracked, potentially causing problemes for certain compilers in certain situations --- src/settings_internal.h | 16 ++++++++-------- src/table/settings/settings.ini | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/settings_internal.h b/src/settings_internal.h index 5ba7ca454a..5b35d328ad 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -69,7 +69,7 @@ struct IniItem; /** Properties of config file settings. */ struct SettingDesc { - SettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup) : + SettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup) : name(name), flags(flags), startup(startup), save(save) {} virtual ~SettingDesc() {} @@ -140,7 +140,7 @@ struct IntSettingDesc : SettingDesc { */ typedef void PostChangeCallback(int32 value); - IntSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, int32 def, + IntSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def), min(min), max(max), interval(interval), @@ -182,7 +182,7 @@ private: /** Boolean setting. */ struct BoolSettingDesc : IntSettingDesc { - BoolSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, bool def, + BoolSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, bool def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback) : IntSettingDesc(save, name, flags, startup, def, 0, 1, 0, str, str_help, str_val, cat, @@ -198,7 +198,7 @@ struct BoolSettingDesc : IntSettingDesc { struct OneOfManySettingDesc : IntSettingDesc { typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error - OneOfManySettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, int32 def, + OneOfManySettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : @@ -222,7 +222,7 @@ struct OneOfManySettingDesc : IntSettingDesc { /** Many of many setting. */ struct ManyOfManySettingDesc : OneOfManySettingDesc { - ManyOfManySettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, + ManyOfManySettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, PreChangeCheck pre_check, PostChangeCallback post_callback, std::initializer_list many, OnConvert *many_cnvt) : @@ -251,7 +251,7 @@ struct StringSettingDesc : SettingDesc { */ typedef void PostChangeCallback(const std::string &value); - StringSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, const char *def, + StringSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, const char *def, uint32 max_length, PreChangeCheck pre_check, PostChangeCallback post_callback) : SettingDesc(save, name, flags, startup), def(def == nullptr ? "" : def), max_length(max_length), pre_check(pre_check), post_callback(post_callback) {} @@ -277,7 +277,7 @@ private: /** List/array settings. */ struct ListSettingDesc : SettingDesc { - ListSettingDesc(SaveLoad save, const std::string &name, SettingFlag flags, bool startup, const char *def) : + ListSettingDesc(SaveLoad save, const char *name, SettingFlag flags, bool startup, const char *def) : SettingDesc(save, name, flags, startup), def(def) {} virtual ~ListSettingDesc() {} @@ -291,7 +291,7 @@ struct ListSettingDesc : SettingDesc { /** Placeholder for settings that have been removed, but might still linger in the savegame. */ struct NullSettingDesc : SettingDesc { NullSettingDesc(SaveLoad save) : - SettingDesc(save, {}, SF_NOT_IN_CONFIG, false) {} + SettingDesc(save, "", SF_NOT_IN_CONFIG, false) {} virtual ~NullSettingDesc() {} void FormatValue(char *buf, const char *last, const void *object) const override { NOT_REACHED(); } diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 7c5cac8869..6fe4d9d515 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -1002,14 +1002,14 @@ post_cb = MaxVehiclesChanged cat = SC_BASIC [SDTG_BOOL] -name = {} +name = """" flags = SF_NO_NETWORK var = _old_vds.servint_ispercent def = false to = SLV_120 [SDTG_VAR] -name = {} +name = """" type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_trains @@ -1019,7 +1019,7 @@ max = 800 to = SLV_120 [SDTG_VAR] -name = {} +name = """" type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_roadveh @@ -1029,7 +1029,7 @@ max = 800 to = SLV_120 [SDTG_VAR] -name = {} +name = """" type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_ships @@ -1039,7 +1039,7 @@ max = 800 to = SLV_120 [SDTG_VAR] -name = {} +name = """" type = SLE_UINT16 flags = SF_GUI_0_IS_SPECIAL var = _old_vds.servint_aircraft From 98e653dacc98d308e440503c9cf9bba01933d1b4 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Mon, 21 Jun 2021 18:46:27 +0200 Subject: [PATCH 39/53] Fix #9386: compilers failing to compile with LTO by using variants instead of new + unique_ptr With std::variant all memory can be figured out at compile time, so the compiler needs to keep track of fewer elements. It also saves out a unique_ptr and its memory management, over a slight impact for resolving a setting. --- .github/workflows/ci-build.yml | 2 +- .github/workflows/release.yml | 2 +- CMakeLists.txt | 2 +- src/settings.cpp | 5 +++-- src/settings_internal.h | 3 ++- src/table/settings.h.preamble | 2 +- src/table/settings/company_settings.ini | 2 +- src/table/settings/currency_settings.ini | 2 +- src/table/settings/gameopt_settings.ini | 2 +- src/table/settings/misc_settings.ini | 2 +- src/table/settings/settings.ini | 2 +- src/table/settings/win32_settings.ini | 2 +- src/table/settings/window_settings.ini | 2 +- 13 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 8a7835c1e7..3f05869e05 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -157,7 +157,7 @@ jobs: runs-on: macos-latest env: - MACOSX_DEPLOYMENT_TARGET: 10.9 + MACOSX_DEPLOYMENT_TARGET: 10.14 steps: - name: Checkout diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 447b165f9c..90d1a9d5b3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -470,7 +470,7 @@ jobs: runs-on: macos-10.15 env: - MACOSX_DEPLOYMENT_TARGET: 10.9 + MACOSX_DEPLOYMENT_TARGET: 10.14 steps: - name: Download source diff --git a/CMakeLists.txt b/CMakeLists.txt index fe03b5ae11..36d504e105 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ if (EMSCRIPTEN) endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") -set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14) # Use GNUInstallDirs to allow customisation # but set our own default data and bin dir diff --git a/src/settings.cpp b/src/settings.cpp index 5e3ba5be74..9d0e125b04 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -87,6 +87,7 @@ std::string _config_file; ///< Configuration file of OpenTTD typedef std::list ErrorList; static ErrorList _settings_error_list; ///< Errors while loading minimal settings. +typedef span SettingTable; typedef void SettingDescProc(IniFile *ini, const SettingTable &desc, const char *grpname, void *object, bool only_startup); typedef void SettingDescProcList(IniFile *ini, const char *grpname, StringList &list); @@ -98,9 +99,9 @@ static bool IsSignedVarMemType(VarType vt); * @param desc The type of the iterator of the value in SettingTable. * @return The actual pointer to SettingDesc. */ -static const SettingDesc *GetSettingDesc(const std::unique_ptr &desc) +static constexpr const SettingDesc *GetSettingDesc(const SettingVariant &desc) { - return desc.get(); + return std::visit([](auto&& arg) -> const SettingDesc * { return &arg; }, desc); } /** diff --git a/src/settings_internal.h b/src/settings_internal.h index 5b35d328ad..0e6637a5b7 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -10,6 +10,7 @@ #ifndef SETTINGS_INTERNAL_H #define SETTINGS_INTERNAL_H +#include #include "saveload/saveload.h" enum SettingFlag : uint16 { @@ -299,7 +300,7 @@ struct NullSettingDesc : SettingDesc { bool IsSameValue(const IniItem *item, void *object) const override { NOT_REACHED(); } }; -typedef std::initializer_list> SettingTable; +typedef std::variant SettingVariant; const SettingDesc *GetSettingFromName(const std::string_view name); void GetSettingSaveLoadByPrefix(const std::string_view prefix, std::vector &saveloads); diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index c9b47626c4..5fd1a9bac6 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -54,7 +54,7 @@ static size_t ConvertLandscape(const char *value); * on the appropriate macro. */ -#define NSD(type, ...) std::unique_ptr(new type##SettingDesc(__VA_ARGS__)) +#define NSD(type, ...) SettingVariant { std::in_place_type, __VA_ARGS__ } /* Macros for various objects to go in the configuration file. * This section is for global variables */ diff --git a/src/table/settings/company_settings.ini b/src/table/settings/company_settings.ini index 71f99d5a21..e5019305f7 100644 --- a/src/table/settings/company_settings.ini +++ b/src/table/settings/company_settings.ini @@ -12,7 +12,7 @@ static void UpdateAllServiceInterval(int32 new_value); static bool CanUpdateServiceInterval(VehicleType type, int32 &new_value); static void UpdateServiceInterval(VehicleType type, int32 new_value); -static const SettingTable _company_settings{ +static const SettingVariant _company_settings[] = { [post-amble] }; [templates] diff --git a/src/table/settings/currency_settings.ini b/src/table/settings/currency_settings.ini index c8ba3d76cd..d0950db8e6 100644 --- a/src/table/settings/currency_settings.ini +++ b/src/table/settings/currency_settings.ini @@ -7,7 +7,7 @@ ; Settings for the in-game custom currency. [pre-amble] -static const SettingTable _currency_settings{ +static const SettingVariant _currency_settings[] = { [post-amble] }; [templates] diff --git a/src/table/settings/gameopt_settings.ini b/src/table/settings/gameopt_settings.ini index ce28def632..4474006236 100644 --- a/src/table/settings/gameopt_settings.ini +++ b/src/table/settings/gameopt_settings.ini @@ -33,7 +33,7 @@ static std::initializer_list _osk_activation{"disabled", "double", static std::initializer_list _settings_profiles{"easy", "medium", "hard"}; static std::initializer_list _news_display{ "off", "summarized", "full"}; -static const SettingTable _gameopt_settings{ +static const SettingVariant _gameopt_settings[] = { /* In version 4 a new difficulty setting has been added to the difficulty settings, * town attitude towards demolishing. Needs special handling because some dimwit thought * it funny to have the GameDifficulty struct be an array while it is a struct of diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index 453c6e8162..9f73573b20 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -20,7 +20,7 @@ extern bool _allow_hidpi_window; #define WITHOUT_COCOA #endif -static const SettingTable _misc_settings{ +static const SettingVariant _misc_settings[] = { [post-amble] }; [templates] diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index 6fe4d9d515..a0a835364e 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -49,7 +49,7 @@ static void UpdateClientConfigValues(); * assigns its own value. If the setting was company-based, that would mean that * vehicles could decide on different moments that they are heading back to a * service depot, causing desyncs on a massive scale. */ -const SettingTable _settings{ +static const SettingVariant _settings[] = { [post-amble] }; [templates] diff --git a/src/table/settings/win32_settings.ini b/src/table/settings/win32_settings.ini index df1e0cb272..51b5796294 100644 --- a/src/table/settings/win32_settings.ini +++ b/src/table/settings/win32_settings.ini @@ -12,7 +12,7 @@ #if defined(_WIN32) && !defined(DEDICATED) extern bool _window_maximize; -static const SettingTable _win32_settings{ +static const SettingVariant _win32_settings[] = { [post-amble] }; #endif /* _WIN32 */ diff --git a/src/table/settings/window_settings.ini b/src/table/settings/window_settings.ini index 3a7669754f..d9327aa92c 100644 --- a/src/table/settings/window_settings.ini +++ b/src/table/settings/window_settings.ini @@ -9,7 +9,7 @@ [pre-amble] -static const SettingTable _window_settings{ +static const SettingVariant _window_settings[] = { [post-amble] }; [templates] From da7621cc557a0f81cb4f9419a65b4d57fe200699 Mon Sep 17 00:00:00 2001 From: translators Date: Sat, 26 Jun 2021 18:50:34 +0000 Subject: [PATCH 40/53] Update: Translations from eints swedish: 1 change by joeax910 --- src/lang/swedish.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 94b67e4c6f..6c93df71a9 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -884,6 +884,7 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Subventionen har gått ut:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subventionen gäller inte längre:{}{}{STRING} från {STRING} till {STRING} är inte längre subventionerad STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ny subvention:{}{}Första transporten av {STRING} från {STRING} till {STRING} får {NUM} års subvention från kommunen! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger 50% extra de{P 4 t ""} {NUM} kommande år{P et en}! STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger dubbelt så mycket nästa {NUM} år{P "" s}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i {TOWN}!{}{}Vägombyggnadsprogram bekostat av {STRING} medför 6 månader av elände för bilister! From 87eb0e4fcec76f88c4c502d074b2ae79f48fe09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sun, 27 Jun 2021 17:18:21 +0200 Subject: [PATCH 41/53] Fix #9402, 2e136285: Crash when founding town using default name (#9403) --- src/town_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 021590cb9f..2d7aa8f20f 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -1151,7 +1151,7 @@ public: void ExecuteFoundTownCommand(TileIndex tile, bool random, StringID errstr, CommandCallback cc) { - const char *name = nullptr; + std::string name; if (!this->townnamevalid) { name = this->townname_editbox.text.buf; From 59e96cd56a69f2b44fb22ca0e4eb9cc2157fd7c6 Mon Sep 17 00:00:00 2001 From: translators Date: Sun, 27 Jun 2021 18:50:30 +0000 Subject: [PATCH 42/53] Update: Translations from eints swedish: 6 changes by joeax910 finnish: 1 change by hpiirai catalan: 9 changes by J0anJosep --- src/lang/catalan.txt | 9 +++++++++ src/lang/finnish.txt | 2 +- src/lang/swedish.txt | 10 ++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index bbb399eb55..0bf9a01db5 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -884,6 +884,11 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Oferta de subvenció caducada:{}{}El transport de {STRING} des de {STRING} fins a {STRING} no tindrà subvenció STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subvenció retirada:{}{}El transport de {STRING} des de {STRING} fins a {STRING} ja no està subvencionat +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Oferta de subvenció per a un servei:{}{}La primera companyia en transportar {STRING} des de {STRING} fins a {STRING} tindrà una subvenció de {NUM} any{P "" s} per part de l'autoritat local +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} rebrà uns ingressos addicionals del 50% durant {NUM} any{P "" s} +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} ingressarà el doble de la tarifa habitual durant {NUM} any{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} ingressarà el triple de la tarifa habitual durant {NUM} any{P "" s} +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvenció concedida a {STRING}{}{}El transport de {STRING} des de {STRING} fins a {STRING} ingressarà el quàdruple de la tarifa habitual durant {NUM} any{P "" s} STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trànsit caòtic a {TOWN}{}{}El programa de reconstrucció dels carrers patrocinat per {STRING} porta 6 mesos de misèria als automobilistes STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopoli de transports @@ -1199,6 +1204,10 @@ STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS :Nombre d'avarie STR_CONFIG_SETTING_VEHICLE_BREAKDOWNS_HELPTEXT :Controla cada quan els vehicles revisats inadequadament s'espatllen STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Multiplicador del subsidi: {STRING} STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Fixa quant es paga pels transports subsidiats +STR_CONFIG_SETTING_SUBSIDY_DURATION :Durada dels subsidis: {STRING} +STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Establiu el nombre d'anys que duren els subsidis. +STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} any{P "" s} +STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Sense subsidis STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Costos de construcció: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Fixa el nivell de construcció i els preus de compra STR_CONFIG_SETTING_RECESSIONS :Recessions: {STRING} diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 31ba5390a4..31d45d4109 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -2309,7 +2309,7 @@ STR_CONTENT_DETAIL_SUBTITLE_SELECTED :{SILVER}Olet va STR_CONTENT_DETAIL_SUBTITLE_AUTOSELECTED :{SILVER}Tämä vaatimus on valittu ladattavaksi STR_CONTENT_DETAIL_SUBTITLE_ALREADY_HERE :{SILVER}Sinulla on jo tämä STR_CONTENT_DETAIL_SUBTITLE_DOES_NOT_EXIST :{SILVER}Tämä sisältö on tuntematon, ja sitä ei voida ladata OpenTTD:ssä -STR_CONTENT_DETAIL_UPDATE :{SILVER}Tämä korvaa sisällön {STRING} +STR_CONTENT_DETAIL_UPDATE :{SILVER}Tällä korvataan olemassa oleva {STRING} STR_CONTENT_DETAIL_NAME :{SILVER}Nimi: {WHITE}{STRING} STR_CONTENT_DETAIL_VERSION :{SILVER}Versio: {WHITE}{STRING} STR_CONTENT_DETAIL_DESCRIPTION :{SILVER}Kuvaus: {WHITE}{STRING} diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 6c93df71a9..72140a73ca 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -886,6 +886,8 @@ STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLAC STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Ny subvention:{}{}Första transporten av {STRING} från {STRING} till {STRING} får {NUM} års subvention från kommunen! STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger 50% extra de{P 4 t ""} {NUM} kommande år{P et en}! STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger dubbelt så mycket nästa {NUM} år{P "" s}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger tre gånger så mycket de{P 4 t ""} kommande {NUM} år{P et en}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Subvention tilldelad {STRING}!{}{}{STRING} från {STRING} till {STRING} ger fyra gånger så mycket de{P 4 t ""} kommande {NUM} år{P et en}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Trafikkaos i {TOWN}!{}{}Vägombyggnadsprogram bekostat av {STRING} medför 6 månader av elände för bilister! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transportmonopol! @@ -1271,9 +1273,9 @@ STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :På förarsidan STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :På höger sida STR_CONFIG_SETTING_SHOWFINANCES :Visa finansfönstret vid slutet av året: {STRING} STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :Om aktiverad kommer finans-fönstret att visas vid slutet av varje år för att möjliggöra enkel granskning av den finansiella statusen för företaget. -STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :Nya orders är 'non-stop' om inte annat anges.{STRING} +STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :Nya order är 'non-stop' om inte annat anges.{STRING} STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :I normala fall stannar ett fordon vid varje station det passerar. Aktiveras den här inställningen kommer det istället att köra igenom alla stationer på väg till dess slutdestination utan att stanna. Tänk på att den här inställningen bara definierar ett förinställt värde för nya order. Individuella order kan uttryckligen definiera båda typerna av beteende oavsett inställning -STR_CONFIG_SETTING_STOP_LOCATION :Nya tåg-orders stannar som standard vid {STRING} av platformen +STR_CONFIG_SETTING_STOP_LOCATION :Nya tåg-order stannar som standard vid {STRING} av platformen STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Grundinställning för var tåg stannar utmed plattformar. 'början' betyder i början av plattformen sett från var tåget kommer ifrån. 'mitten' betyder i mitten av plattformen och 'slutet' betyder så långt bort som möjligt. Notera att denna inställning endast anger grundvärdet för nya ordrar. Individuella instruktioner kan ges per orderrad explicit till valfritt värde oberoende av denna inställning. STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :början STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :mitten @@ -2663,7 +2665,7 @@ STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Ta bort STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Är du säker på att du vill ta bort alla industrier? # Industry cargoes window -STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Industrikedja för {STRING} industrin +STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Industrikedja för industrin {STRING} STR_INDUSTRY_CARGOES_CARGO_CAPTION :{WHITE}Industrikedja för godset {STRING} STR_INDUSTRY_CARGOES_PRODUCERS :{WHITE}Producerande industrier STR_INDUSTRY_CARGOES_CUSTOMERS :{WHITE}Mottagande industrier @@ -2933,7 +2935,7 @@ STR_MAPGEN_BORDER_FREEFORM :{BLACK}Fri form STR_MAPGEN_BORDER_WATER :{BLACK}Vatten STR_MAPGEN_BORDER_RANDOM :{BLACK}På måfå STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}På måfå -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuell +STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuella STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotation på höjdkarta: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Namn på höjdkarta: From 003b6a0c85157059d0339dbfa551db7ec3b40cd9 Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Sun, 27 Jun 2021 23:58:54 +0100 Subject: [PATCH 43/53] Fix ea9715d: not all setting values were clamped properly (#9401) --- src/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.cpp b/src/settings.cpp index 9d0e125b04..a7a50db11c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -439,7 +439,7 @@ void IntSettingDesc::MakeValueValid(int32 &val) const uval = (uint32)this->def; } } - val = (int32)val; + val = (int32)uval; return; } case SLE_VAR_I64: From 883e4ea325886e5cee88b34c2d9e069f12697c96 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 28 Jun 2021 12:39:09 -0400 Subject: [PATCH 44/53] Change: [Emscripten] set default scrolling mode to non-pointer-locking (#9191) --- os/emscripten/shell.html | 2 ++ src/table/settings/settings.ini | 14 ++++++++++++++ src/video/sdl2_v.cpp | 33 +++++---------------------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/os/emscripten/shell.html b/os/emscripten/shell.html index 17ea5b414f..af031c6df8 100644 --- a/os/emscripten/shell.html +++ b/os/emscripten/shell.html @@ -85,6 +85,8 @@ position: absolute; width: 100%; z-index: 2; + /* OpenTTD draws the cursor itself */ + cursor: none !important; } diff --git a/src/table/settings/settings.ini b/src/table/settings/settings.ini index a0a835364e..5e352ff3c7 100644 --- a/src/table/settings/settings.ini +++ b/src/table/settings/settings.ini @@ -2516,6 +2516,20 @@ strval = STR_CONFIG_SETTING_AUTOSCROLL_DISABLED cat = SC_BASIC [SDTC_VAR] +ifdef = __EMSCRIPTEN__ +var = gui.scroll_mode +type = SLE_UINT8 +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN +def = 2 +min = 0 +max = 3 +str = STR_CONFIG_SETTING_SCROLLMODE +strhelp = STR_CONFIG_SETTING_SCROLLMODE_HELPTEXT +strval = STR_CONFIG_SETTING_SCROLLMODE_DEFAULT +cat = SC_BASIC + +[SDTC_VAR] +ifndef = __EMSCRIPTEN__ var = gui.scroll_mode type = SLE_UINT8 flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 875491652e..8ef00a00c3 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -30,11 +30,6 @@ #include "../safeguards.h" -#ifdef __EMSCRIPTEN__ -/** Whether we just had a window-enter event. */ -static bool _cursor_new_in_window = false; -#endif - void VideoDriver_SDL_Base::MakeDirty(int left, int top, int width, int height) { Rect r = {left, top, left + width, top + height}; @@ -203,9 +198,9 @@ bool VideoDriver_SDL_Base::CreateMainSurface(uint w, uint h, bool resize) bool VideoDriver_SDL_Base::ClaimMousePointer() { + /* Emscripten never claims the pointer, so we do not need to change the cursor visibility. */ +#ifndef __EMSCRIPTEN__ SDL_ShowCursor(0); -#ifdef __EMSCRIPTEN__ - SDL_SetRelativeMouseMode(SDL_TRUE); #endif return true; } @@ -377,27 +372,9 @@ bool VideoDriver_SDL_Base::PollEvent() switch (ev.type) { case SDL_MOUSEMOTION: -#ifdef __EMSCRIPTEN__ - if (_cursor_new_in_window) { - /* The cursor just moved into the window; this means we don't - * know the absolutely position yet to move relative from. - * Before this time, SDL didn't know it either, and this is - * why we postpone it till now. Update the absolute position - * for this once, and work relative after. */ - _cursor.pos.x = ev.motion.x; - _cursor.pos.y = ev.motion.y; - _cursor.dirty = true; - - _cursor_new_in_window = false; - SDL_SetRelativeMouseMode(SDL_TRUE); - } else { - _cursor.UpdateCursorPositionRelative(ev.motion.xrel, ev.motion.yrel); - } -#else if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) { SDL_WarpMouseInWindow(this->sdl_window, _cursor.pos.x, _cursor.pos.y); } -#endif HandleMouseEvents(); break; @@ -502,9 +479,7 @@ bool VideoDriver_SDL_Base::PollEvent() // mouse entered the window, enable cursor _cursor.in_window = true; #ifdef __EMSCRIPTEN__ - /* Disable relative mouse mode for the first mouse motion, - * so we can pick up the absolutely position again. */ - _cursor_new_in_window = true; + /* Ensure pointer lock will not occur. */ SDL_SetRelativeMouseMode(SDL_FALSE); #endif } else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) { @@ -525,7 +500,9 @@ static const char *InitializeSDL() * UpdateWindowSurface() to update the window's texture instead of * its surface. */ SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0"); +#ifndef __EMSCRIPTEN__ SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); +#endif /* Check if the video-driver is already initialized. */ if (SDL_WasInit(SDL_INIT_VIDEO) != 0) return nullptr; From f9b4a3a5e69bbf7ac7a353d2b1bb5061be96158b Mon Sep 17 00:00:00 2001 From: TELK Date: Tue, 29 Jun 2021 01:42:23 +0900 Subject: [PATCH 45/53] Add: Show the number of clients and companies in the online players window (#9376) --- src/lang/english.txt | 1 + src/network/network_gui.cpp | 10 +++++++++- src/widgets/network_widget.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 206cc212f7..bd5cff8d36 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2152,6 +2152,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(New company) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Create a new company and join it STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}This is you STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}This is the host of the game +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} client{P "" s} / {NUM} compan{P y ies} STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kick STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Ban diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 52819660d5..e3e05db926 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -1627,7 +1627,10 @@ static const NWidgetPart _nested_client_list_widgets[] = { EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_CL_MATRIX), SetMinimalSize(180, 0), SetResize(1, 1), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_CL_SCROLLBAR), + NWidget(NWID_VERTICAL), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_CL_MATRIX), SetMinimalSize(180, 0), SetResize(1, 1), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_CL_SCROLLBAR), + NWidget(WWT_TEXT, COLOUR_GREY, WID_CL_CLIENT_COMPANY_COUNT), SetFill(1, 0), SetMinimalTextLines(1, 0), SetResize(1, 0), SetPadding(2, 1, 2, 1), SetAlignment(SA_CENTER), SetDataTip(STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT, STR_NULL), + EndContainer(), NWidget(NWID_VERTICAL), NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_CL_SCROLLBAR), NWidget(WWT_RESIZEBOX, COLOUR_GREY), @@ -2050,6 +2053,11 @@ public: case WID_CL_CLIENT_NAME: SetDParamStr(0, _settings_client.network.client_name); break; + + case WID_CL_CLIENT_COMPANY_COUNT: + SetDParam(0, NetworkClientInfo::GetNumItems()); + SetDParam(1, Company::GetNumItems()); + break; } } diff --git a/src/widgets/network_widget.h b/src/widgets/network_widget.h index 2ed94d2849..a96a56fa81 100644 --- a/src/widgets/network_widget.h +++ b/src/widgets/network_widget.h @@ -106,6 +106,7 @@ enum ClientListWidgets { WID_CL_MATRIX, ///< Company/client list. WID_CL_SCROLLBAR, ///< Scrollbar for company/client list. WID_CL_COMPANY_JOIN, ///< Used for QueryWindow when a company has a password. + WID_CL_CLIENT_COMPANY_COUNT, ///< Count of clients and companies. }; /** Widgets of the #NetworkJoinStatusWindow class. */ From c539343ba914d68a9ab560bf09ed1854ab6d43f6 Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 28 Jun 2021 19:00:24 +0000 Subject: [PATCH 46/53] Update: Translations from eints swedish: 1 change by joeax910 --- src/lang/swedish.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 72140a73ca..206da87e30 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -1294,7 +1294,7 @@ STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS :Tillåt att byg STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Tillåt företag att ge pengar till städer för att bekosta nybyggnation av hus STR_CONFIG_SETTING_ALLOW_FUND_ROAD :Tillåt finansiering av lokal vägrekonstruktion: {STRING} STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT :Tillåt att företag ger pengar till städer för vägbyggen och därmed saboterar för vägtransporter i staden. -STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :Tillåt skicka pengar till andra företag: {STRING} +STR_CONFIG_SETTING_ALLOW_GIVE_MONEY :Tillåt att skicka pengar till andra företag: {STRING} STR_CONFIG_SETTING_ALLOW_GIVE_MONEY_HELPTEXT :Tillåt överföring av pengar mellan företag i flerspelarläge STR_CONFIG_SETTING_FREIGHT_TRAINS :Godsfaktor för att simulera tunga tåg: {STRING} STR_CONFIG_SETTING_FREIGHT_TRAINS_HELPTEXT :Ställ in påverkan av att frakta gods i tåg. Ett högre värde gör att fraktgods är mer krävande för tågen, speciellt vid lutningar From 8336d21b2577e02c754cd78f10b4daba3fbe478f Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 29 Jun 2021 18:52:43 +0000 Subject: [PATCH 47/53] Update: Translations from eints swedish: 27 changes by joeax910 korean: 4 changes by telk5093 russian: 1 change by Ln-Wolf portuguese: 1 change by azulcosta --- src/lang/korean.txt | 7 +++--- src/lang/portuguese.txt | 1 + src/lang/russian.txt | 1 + src/lang/swedish.txt | 53 +++++++++++++++++++++-------------------- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/lang/korean.txt b/src/lang/korean.txt index ef3e85fa50..60faed06ab 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -2153,6 +2153,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(새 회사) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}새 회사를 만듭니다 STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}당신입니다 STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}이 게임을 연 사람입니다 +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}접속자 {NUM}명 / 회사 {NUM}개 STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :추방 STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :차단 @@ -3637,7 +3638,7 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_REFIT_VEHICLE_BUTTON :{BLACK}차량 STR_BUY_VEHICLE_SHIP_BUY_REFIT_VEHICLE_BUTTON :{BLACK}선박 구입 및 개조 STR_BUY_VEHICLE_AIRCRAFT_BUY_REFIT_VEHICLE_BUTTON :{BLACK}항공기 구입 및 개조 -STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}선택된 차량을 구입합니다. SHIFT+클릭으로 예상 구입 비용을 볼 수 있습니다. +STR_BUY_VEHICLE_TRAIN_BUY_VEHICLE_TOOLTIP :{BLACK}선택된 차량을 구입합니다. SHIFT+클릭으로 예상 구입 비용을 볼 수 있습니다 STR_BUY_VEHICLE_ROAD_VEHICLE_BUY_VEHICLE_TOOLTIP :{BLACK}선택한 차량을 구입합니다. SHIFT+클릭하면 예상 구입 비용을 볼 수 있습니다 STR_BUY_VEHICLE_SHIP_BUY_VEHICLE_TOOLTIP :{BLACK}선택한 선박을 구입합니다. SHIFT+클릭으로 예상 구입 비용을 볼 수 있습니다 STR_BUY_VEHICLE_AIRCRAFT_BUY_VEHICLE_TOOLTIP :{BLACK}선택한 항공기를 구입합니다. SHIFT+클릭으로 예상 구입 비용을 볼 수 있습니다 @@ -3653,7 +3654,7 @@ STR_BUY_VEHICLE_SHIP_RENAME_BUTTON :{BLACK}이름 STR_BUY_VEHICLE_AIRCRAFT_RENAME_BUTTON :{BLACK}이름 지정 STR_BUY_VEHICLE_TRAIN_RENAME_TOOLTIP :{BLACK}열차의 모델명을 변경합니다 -STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_TOOLTIP :{BLACK}차종의 이름을 변경합니다. +STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_TOOLTIP :{BLACK}자동차의 모델명을 변경합니다 STR_BUY_VEHICLE_SHIP_RENAME_TOOLTIP :{BLACK}선박의 모델명을 변경합니다 STR_BUY_VEHICLE_AIRCRAFT_RENAME_TOOLTIP :{BLACK}항공기의 모델명을 변경합니다 @@ -3673,7 +3674,7 @@ STR_BUY_VEHICLE_SHIP_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}숨김 STR_BUY_VEHICLE_AIRCRAFT_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}숨김 처리한 항공기 모델을 목록에 보여주거나 숨깁니다 STR_QUERY_RENAME_TRAIN_TYPE_CAPTION :{WHITE}열차의 모델명을 변경합니다 -STR_QUERY_RENAME_ROAD_VEHICLE_TYPE_CAPTION :{WHITE}차종 이름을 변경합니다. +STR_QUERY_RENAME_ROAD_VEHICLE_TYPE_CAPTION :{WHITE}자동차의 모델명을 변경합니다 STR_QUERY_RENAME_SHIP_TYPE_CAPTION :{WHITE}선박의 모델명을 변경합니다 STR_QUERY_RENAME_AIRCRAFT_TYPE_CAPTION :{WHITE}항공기의 모델명을 변경합니다 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 9bdd352261..4975058db4 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -2153,6 +2153,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nova empresa) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Criar uma nova empresa e juntar-se a ela STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Este é você STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Este é o anfitrião do jogo +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} cliente{P "" s} / {NUM} companhi{P a as} STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Expulsar STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Banir diff --git a/src/lang/russian.txt b/src/lang/russian.txt index f2356d6856..fa367b1136 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -2303,6 +2303,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Новая к STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Основать новую транспортную компанию и присоединиться к ней STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Это вы! STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Это организатор игры +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} клиент{P "" а ов} / {NUM} компани{P я и й} STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Отключить STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Заблокировать diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 206da87e30..7aa63245c3 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -779,7 +779,7 @@ STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS :{BLACK}Visa all STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS :{BLACK}Visa senaste meddelande eller nyhet STR_STATUSBAR_COMPANY_NAME :{SILVER}- - {COMPANY} - - STR_STATUSBAR_PAUSED :{YELLOW}* * PAUSAD * * -STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * PAUSAD (väntar på updatering av länkdiagram) * * +STR_STATUSBAR_PAUSED_LINK_GRAPH :{ORANGE}* * PAUSAD (väntar på uppdatering av länkgraf) * * STR_STATUSBAR_AUTOSAVE :{RED}AUTOSPARA STR_STATUSBAR_SAVING_GAME :{RED}* * SPARAR SPEL * * @@ -824,7 +824,7 @@ STR_NEWS_COMPANY_LAUNCH_DESCRIPTION :{BIG_FONT}{BLAC STR_NEWS_MERGER_TAKEOVER_TITLE :{BIG_FONT}{BLACK}{STRING} har tagits över av {STRING}! STR_PRESIDENT_NAME_MANAGER :{BLACK}{PRESIDENT_NAME}{}(VD) -STR_NEWS_NEW_TOWN :{BLACK}{BIG_FONT}{STRING} har sponsrat byggnationen av nya staden {TOWN}! +STR_NEWS_NEW_TOWN :{BLACK}{BIG_FONT}{STRING} har sponsrat byggnationen av den nya staden {TOWN}! STR_NEWS_NEW_TOWN_UNSPONSORED :{BLACK}{BIG_FONT}En ny stad, kallad {TOWN}, har grundats! STR_NEWS_INDUSTRY_CONSTRUCTION :{BIG_FONT}{BLACK}Ny {STRING} under konstruktion nära {TOWN}! @@ -1037,7 +1037,7 @@ STR_GAME_OPTIONS_REFRESH_RATE_WARNING :{WHITE}uppdater STR_GAME_OPTIONS_BASE_GRF :{BLACK}Grafikpaket som standard STR_GAME_OPTIONS_BASE_GRF_TOOLTIP :{BLACK}Välj vilket grafikpaket som ska användas som standard STR_GAME_OPTIONS_BASE_GRF_STATUS :{RED}{NUM} saknad{P "" e}/trasig{P "" a} fil{P "" er} -STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP :{BLACK}Ytterligare information om basgrafik-set +STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP :{BLACK}Ytterligare information om basgrafik-settet STR_GAME_OPTIONS_BASE_SFX :{BLACK}Grundljudspaket STR_GAME_OPTIONS_BASE_SFX_TOOLTIP :{BLACK}Välj vilket grundljudspaket som ska användas @@ -1368,10 +1368,10 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Begränsar hur STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Snögränsens höjd: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Kontrollerar på vilken höjd snön börjar i det subarktiska landskapet. Snö påverkar även industrigeneration och städers tillväxtkrav. Kan endast modifieras via Scenarioredigeraren eller beräknas via "snötäckning" STR_CONFIG_SETTING_SNOW_COVERAGE :Snötäckning: {STRING} -STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Kontrollerar ungefärlig mängd snö på den subarktiska landskapet. Snö påverkar även industri generation och städernas tillväxtkrav. Används endast under kartgeneration. Land precis över havsnivån är alltid utan snö +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Kontrollerar ungefärlig mängd snö i det subarktiska landskapet. Snö påverkar även industrigeneration och städernas tillväxtkrav. Används endast under kartgeneration. Land precis över havsnivån är alltid utan snö STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% -STR_CONFIG_SETTING_DESERT_COVERAGE :Öken täckning: {STRING} -STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Kontrollera ungefärligt mängd öken i tropiskt landskap. Öken påverkar även industri generation. Används bara under kartgeneration +STR_CONFIG_SETTING_DESERT_COVERAGE :Ökentäckning: {STRING} +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Kontrollera ungefärlig mängd öken i tropiskt landskap. Öken påverkar även industrigeneration. Används bara under kartgeneration STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Terrängens svårhetsgrad: {STRING} STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesis endast) Välj frekvensen av kullar: Smooth landskap har färre, mer utbredda kullar. Rough landskap har många kullar, som kan se repetitiva @@ -1383,14 +1383,14 @@ STR_CONFIG_SETTING_VARIETY :Varierad distri STR_CONFIG_SETTING_VARIETY_HELPTEXT :(TerraGenesis endast) Styr om kartan innehåller både bergs och flacka områden. Eftersom detta gör bara kartan flackare bör andra inställningar ställas in på bergiga STR_CONFIG_SETTING_RIVER_AMOUNT :Antal floder: {STRING} STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :Välj hur många floder att generera -STR_CONFIG_SETTING_TREE_PLACER :Trädplacerings-algoritm: {STRING} -STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :Välj fördelningen av träden på kartan: "Original" växter träd jämnt utspridda, "Förbättrad" växter dem i grupper +STR_CONFIG_SETTING_TREE_PLACER :Trädplaceringsalgoritm: {STRING} +STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :Välj hur träd fördelas över kartan: "Original" planterar träden jämnt utspridda, "Förbättrad" planterar dem i grupper STR_CONFIG_SETTING_TREE_PLACER_NONE :Inget STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :Original STR_CONFIG_SETTING_TREE_PLACER_IMPROVED :Förbättrad -STR_CONFIG_SETTING_ROAD_SIDE :Väg fordon: {STRING} -STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :Välj kör sida -STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Höjkartans rotation: {STRING} +STR_CONFIG_SETTING_ROAD_SIDE :Vägfordon: {STRING} +STR_CONFIG_SETTING_ROAD_SIDE_HELPTEXT :Välj körsida +STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Höjdkartans rotation: {STRING} STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Motsols STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :Medsols STR_CONFIG_SETTING_SE_FLAT_WORLD_HEIGHT :Vilken nivåhöjd en platt scenario-karta får: {STRING} @@ -1586,7 +1586,7 @@ STR_CONFIG_SETTING_NEWS_INDUSTRY_CHANGES_UNSERVED_HELPTEXT :Visa nyhetstidn STR_CONFIG_SETTING_NEWS_ADVICE :Råd / information om företagets fordon: {STRING} STR_CONFIG_SETTING_NEWS_ADVICE_HELPTEXT :Visa meddelande ifall att ett fordon behöver uppmärksamhet STR_CONFIG_SETTING_NEWS_NEW_VEHICLES :Nya fordon: {STRING} -STR_CONFIG_SETTING_NEWS_NEW_VEHICLES_HELPTEXT :Visa nyhetstidning när en ny typ av fordon blir tillgängligt +STR_CONFIG_SETTING_NEWS_NEW_VEHICLES_HELPTEXT :Visa nyhetstidning när en ny typ av fordon blir tillgänglig STR_CONFIG_SETTING_NEWS_CHANGES_ACCEPTANCE :Ändringar i godsacceptans: {STRING} STR_CONFIG_SETTING_NEWS_CHANGES_ACCEPTANCE_HELPTEXT :Visa meddelande vid förändring av stationers varuacceptans STR_CONFIG_SETTING_NEWS_SUBSIDIES :Subventioner: {STRING} @@ -1707,8 +1707,8 @@ STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :Inga STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Initial stadsstorleks-multiplikator: {STRING} STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Storstäders genomsnittliga storlek i relation till vanliga städers vid spelets början -STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Uppdatera distributionsgrafen var {STRING}:e{NBSP}dag{P 0:2 "" s} -STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :Tid mellan efterföljande omräkningar av länkgrafen. Varje omräkning beräknar planer för en komponent i grafen. Det medför att ett värde X för den här inställningen inte innebär att hela grafen uppdateras var X:e dag, bara vissa komponenter. Ju lägre värde du ställer in desto mer processorkraft kommer att behövas för beräkningarna. Ju högre värde du ställer in desto längre tid kommer det att ta innan distributionen av last börjar använda nya rutter. +STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Uppdatera distributionsgrafen var {STRING}:e{NBSP}dag +STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :Tid mellan efterföljande omräkningar av länkgrafen. Varje omräkning beräknar planerna för en komponent i grafen. Det medför att ett värde X för den här inställningen inte innebär att hela grafen uppdateras var X:e dag, utan bara vissa komponenter. Ju kortare intervall du ställer in desto mer processorkraft kommer att behövas för beräkningarna. Ju längre intervall du ställer in desto längre tid kommer det att ta innan distributionen av last börjar använda nya rutter. STR_CONFIG_SETTING_LINKGRAPH_TIME :Avsätt {STRING}{NBSP}dag{P 0:2 "" ar} för omberäkning av distributionsgraf STR_CONFIG_SETTING_LINKGRAPH_TIME_HELPTEXT :Den tid varje omberäkning av en länkgrafkomponent tillåts ta. När en omberäkning startas skapas en tråd som tillåts löpa detta antal dagar. Ju kortare du sätter denna, desto mer troligt är det att tråden inte är hinner bli färdig i tid. Då kommer spelet att stanna tills den är klar (vilket gör att det laggar). Ju längre du sätter denna, desto längre tid tar det för distributionen att uppdateras när rutter ändras. STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manuellt @@ -2007,7 +2007,7 @@ STR_NETWORK_SERVER_LIST_GAME_NAME :{BLACK}Namn STR_NETWORK_SERVER_LIST_GAME_NAME_TOOLTIP :{BLACK}Namn på nätverksspelet STR_NETWORK_SERVER_LIST_GENERAL_ONLINE :{BLACK}{COMMA}/{COMMA} - {COMMA}/{COMMA} STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION :{BLACK}Klienter -STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION_TOOLTIP :{BLACK}Klienter online / klienter max{}Företag online / företag max +STR_NETWORK_SERVER_LIST_CLIENTS_CAPTION_TOOLTIP :{BLACK}Klienter online / max antal klienter{}Företag online / max antal företag STR_NETWORK_SERVER_LIST_MAP_SIZE_SHORT :{BLACK}{COMMA}x{COMMA} STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION :{BLACK}Kartstorlek STR_NETWORK_SERVER_LIST_MAP_SIZE_CAPTION_TOOLTIP :{BLACK}Kartstorlek av spelet{}Klicka för att sortera efter område @@ -2152,6 +2152,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Nytt företag) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Skapa ett nytt företag och gå med i det STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Det här är du STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Det här är spelets värd +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} klient{P "" er} / {NUM} företag STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Kasta ut STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Bannlys @@ -2254,10 +2255,10 @@ STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION :{WHITE}De senas # Network related errors STR_NETWORK_SERVER_MESSAGE :*** {1:STRING} ############ Leave those lines in this order!! -STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED :Spel pausad ({STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_PAUSED :Spelet är pausat ({STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_1 :Spelet är fortfarande pausat ({STRING}) -STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Spel fortfarande pausad ({STRING}, {STRING}) -STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Spel fortfarande pausad ({STRING}, {STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_2 :Spelet är fortfarande pausat ({STRING}, {STRING}) +STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_3 :Spelet är fortfarande pausat ({STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_4 :Spelet är fortfarande pausat ({STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_STILL_PAUSED_5 :Spelet är fortfarande pausat ({STRING}, {STRING}, {STRING}, {STRING}, {STRING}) STR_NETWORK_SERVER_MESSAGE_GAME_UNPAUSED :Spelet är opausat ({STRING}) @@ -2265,11 +2266,11 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_NOT_ENOUGH_PLAYERS :antal spelare STR_NETWORK_SERVER_MESSAGE_GAME_REASON_CONNECTING_CLIENTS :ansluter klienter STR_NETWORK_SERVER_MESSAGE_GAME_REASON_MANUAL :manuell STR_NETWORK_SERVER_MESSAGE_GAME_REASON_GAME_SCRIPT :spelskript -STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :Väntar på updatering av länkdiagram +STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :väntar på uppdatering av länkgraf ############ End of leave-in-this-order STR_NETWORK_MESSAGE_CLIENT_LEAVING :lämnar STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} har gått med i spelet -STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} har gått med i spelet (Client #{2:NUM}) +STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} har gått med i spelet (Klient #{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} har gått med i företag #{2:NUM} STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} har gått med som åskådare STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} har startat ett nytt företag (#{2:NUM}) @@ -2913,9 +2914,9 @@ STR_MAPGEN_SNOW_COVERAGE :{BLACK}Snötäc STR_MAPGEN_SNOW_COVERAGE_UP :{BLACK}Öka snötäckning med tio procent STR_MAPGEN_SNOW_COVERAGE_DOWN :{BLACK}Minska snötäckning med tio procent STR_MAPGEN_SNOW_COVERAGE_TEXT :{BLACK}{NUM}% -STR_MAPGEN_DESERT_COVERAGE :{BLACK}Öken täckning: +STR_MAPGEN_DESERT_COVERAGE :{BLACK}Ökentäckning: STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}Öka ökentäckning med tio procent -STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Minska öken täckning med tio procent +STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Minska ökentäckning med tio procent STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_LAND_GENERATOR :{BLACK}Landgenerator: STR_MAPGEN_TERRAIN_TYPE :{BLACK}Terrängtyp: @@ -2937,7 +2938,7 @@ STR_MAPGEN_BORDER_RANDOM :{BLACK}På måf STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}På måfå STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuella -STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotation på höjdkarta: +STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Höjdkartans rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Namn på höjdkarta: STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Storlek: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} @@ -2945,7 +2946,7 @@ STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Måltopp höjd STR_MAPGEN_HEIGHTMAP_HEIGHT_QUERY_CAPT :{WHITE}Högsta höjdpunkt STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Snötäckning (i %) -STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Öken täckning (i %) +STR_MAPGEN_DESERT_COVERAGE_QUERY_CAPT :{WHITE}Ökentäckning (i %) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Ändra Startår # SE Map generation @@ -3229,7 +3230,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}Starta STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}Starta en stor lokal reklamkampanj, för att attrahera fler passagerare och gods till dina transporttjänster.{}Tillhandahåller en temporär boost till stationens betyg i en stor radie runt stadens centrum.{}Kostnad: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}Bekosta ombyggnad av stadens vägnätverk.{}Orsakar ansenliga störningar för vägtrafik i upp till 6 månader.{}Kostnad: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}Bygg en staty i ditt företags ära.{}Tillhandahåller en permanent boost till stations betyg i staden.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Bekosta uppbyggnad av nya byggnader i staden.{}Tillhandahåller en temporär boost till stadens tillväxt.{}Kostnad: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Bekosta uppbyggnad av nya byggnader i staden.{}Ger en temporär boost till stadens tillväxt.{}Kostnad: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Köp 1 års exklusiva transport rättigheter i staden.{}Lokala myndigheterna kommer inte tillåta passagerare och gods att använda dina motståndares stationer.{}Cost: {CURRENCY_LONG} STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW} Muta de lokala myndigheterna för att öka din värdering, med risk för att få höga böter om du blir upptäckt.{} Kostnad: {CURRENCY_LONG} @@ -3584,7 +3585,7 @@ STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION :Nya elektriska STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :Nytt monorailfordon STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :Nytt maglevfordon -STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :Nytt Vägfordon +STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :Nytt vägfordon STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :Nya spårvägsfordon ############ range for vehicle availability starts From b6fb0203886debf786662b0bbc47c41e0578e905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Tue, 29 Jun 2021 22:19:24 +0200 Subject: [PATCH 48/53] Change: [strgen] Change warnings for translations into infos (#9406) Unless invoked with -w, --warning ("print a warning for any untranslated strings") or -t, --todo ("replace any untranslated strings with ''"). Eints normally fixes the warnings after a Pull Request, so it is not really useful information for the developer to see as a warning. --- src/strgen/strgen.cpp | 6 +++++- src/strgen/strgen_base.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index 68002cc3f0..025f9406df 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -46,7 +46,11 @@ void CDECL strgen_warning(const char *s, ...) va_start(va, s); vseprintf(buf, lastof(buf), s, va); va_end(va); - fprintf(stderr, LINE_NUM_FMT("warning"), _file, _cur_line, buf); + if (_show_todo > 0) { + fprintf(stderr, LINE_NUM_FMT("warning"), _file, _cur_line, buf); + } else { + fprintf(stderr, LINE_NUM_FMT("info"), _file, _cur_line, buf); + } _warnings++; } diff --git a/src/strgen/strgen_base.cpp b/src/strgen/strgen_base.cpp index 9d1346e17f..078e0abbf2 100644 --- a/src/strgen/strgen_base.cpp +++ b/src/strgen/strgen_base.cpp @@ -818,9 +818,13 @@ void StringReader::ParseFile() char buf[2048]; _warnings = _errors = 0; - _translation = this->master || this->translation; + _translation = this->translation; _file = this->file; + /* Abusing _show_todo to replace "warning" with "info" for translations. */ + _show_todo &= 3; + if (!this->translation) _show_todo |= 4; + /* For each new file we parse, reset the genders, and language codes. */ MemSetT(&_lang, 0); strecpy(_lang.digit_group_separator, ",", lastof(_lang.digit_group_separator)); From d38079d053c39194ea6073a6c466d76421bb45b5 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Tue, 29 Jun 2021 23:02:25 +0200 Subject: [PATCH 49/53] Fix f7e390bd: freeaddrinfo() is not guaranteed to handle a nullptr graceful (#9404) --- src/network/core/tcp_connect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index c4f5415b04..dc7a23bb38 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -45,7 +45,7 @@ TCPConnecter::~TCPConnecter() this->sockets.clear(); this->sock_to_address.clear(); - freeaddrinfo(this->ai); + if (this->ai != nullptr) freeaddrinfo(this->ai); } /** From df601b8559b3d5de179b5b9e65ab9674fbd8bf5e Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 30 Jun 2021 18:53:37 +0000 Subject: [PATCH 50/53] Update: Translations from eints finnish: 1 change by hpiirai --- src/lang/finnish.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 31d45d4109..5c85f86785 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -2152,6 +2152,7 @@ STR_NETWORK_CLIENT_LIST_NEW_COMPANY :(Uusi yhtiö) STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP :{BLACK}Perusta uusi yhtiö ja liity siihen STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP :{BLACK}Tämä olet sinä STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP :{BLACK}Tämä on pelin ylläpitäjä +STR_NETWORK_CLIENT_LIST_CLIENT_COMPANY_COUNT :{BLACK}{NUM} pelaaja{P "" a} / {NUM} yhtiö{P "" tä} STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK :Potki STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN :Estä From aa9818db90b910b1b3d62d080f4a670a6a9d14af Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 16 Jun 2021 17:50:18 +0200 Subject: [PATCH 51/53] Codechange: create a type for the "free_data" of NewsItems and (de)allocate it with new and delete --- src/company_cmd.cpp | 4 ++-- src/economy.cpp | 4 ++-- src/news_func.h | 6 +++--- src/news_gui.cpp | 14 +++++++------- src/news_type.h | 18 +++++++++++++++--- src/subsidy.cpp | 9 +++------ src/town_cmd.cpp | 18 +++++++----------- 7 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 1c79c4b8a5..3c5e5f5c75 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -376,7 +376,7 @@ set_name:; MarkWholeScreenDirty(); if (c->is_ai) { - CompanyNewsInformation *cni = MallocT(1); + CompanyNewsInformation *cni = new CompanyNewsInformation(); cni->FillData(c); SetDParam(0, STR_NEWS_COMPANY_LAUNCH_TITLE); SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION); @@ -888,7 +888,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 /* Delete any open window of the company */ CloseCompanyWindows(c->index); - CompanyNewsInformation *cni = MallocT(1); + CompanyNewsInformation *cni = new CompanyNewsInformation(); cni->FillData(c); /* Show the bankrupt news */ diff --git a/src/economy.cpp b/src/economy.cpp index 7f14bed8ad..cb45d55b75 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -580,7 +580,7 @@ static void CompanyCheckBankrupt(Company *c) /* Warn about bankruptcy after 3 months */ case 4: { - CompanyNewsInformation *cni = MallocT(1); + CompanyNewsInformation *cni = new CompanyNewsInformation(); cni->FillData(c); SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE); SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION); @@ -1975,7 +1975,7 @@ static void DoAcquireCompany(Company *c) { CompanyID ci = c->index; - CompanyNewsInformation *cni = MallocT(1); + CompanyNewsInformation *cni = new CompanyNewsInformation(); cni->FillData(c, Company::Get(_current_company)); SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE); diff --git a/src/news_func.h b/src/news_func.h index 2131c8a749..3f21f3dca1 100644 --- a/src/news_func.h +++ b/src/news_func.h @@ -15,7 +15,7 @@ #include "station_type.h" #include "industry_type.h" -void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1 = NR_NONE, uint32 ref1 = UINT32_MAX, NewsReferenceType reftype2 = NR_NONE, uint32 ref2 = UINT32_MAX, void *free_data = nullptr); +void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1 = NR_NONE, uint32 ref1 = UINT32_MAX, NewsReferenceType reftype2 = NR_NONE, uint32 ref2 = UINT32_MAX, const NewsAllocatedData *data = nullptr); static inline void AddCompanyNewsItem(StringID string, CompanyNewsInformation *cni) { @@ -42,9 +42,9 @@ static inline void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle) AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle); } -static inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, void *free_data = nullptr, StationID station = INVALID_STATION) +static inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, const NewsAllocatedData *data = nullptr, StationID station = INVALID_STATION) { - AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile, station == INVALID_STATION ? NR_NONE : NR_STATION, station, free_data); + AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile, station == INVALID_STATION ? NR_NONE : NR_STATION, station, data); } static inline void AddIndustryNewsItem(StringID string, NewsType type, IndustryID industry) diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 5c72f87410..fb03207150 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -355,7 +355,7 @@ struct NewsWindow : Window { break; case WID_N_MGR_NAME: - SetDParamStr(0, static_cast(this->ni->free_data)->president_name); + SetDParamStr(0, static_cast(this->ni->data)->president_name); str = STR_JUST_RAW_STRING; break; @@ -433,13 +433,13 @@ struct NewsWindow : Window { break; case WID_N_MGR_FACE: { - const CompanyNewsInformation *cni = (const CompanyNewsInformation*)this->ni->free_data; + const CompanyNewsInformation *cni = static_cast(this->ni->data); DrawCompanyManagerFace(cni->face, cni->colour, r.left, r.top); GfxFillRect(r.left, r.top, r.right, r.bottom, PALETTE_NEWSPAPER, FILLRECT_RECOLOUR); break; } case WID_N_MGR_NAME: { - const CompanyNewsInformation *cni = (const CompanyNewsInformation*)this->ni->free_data; + const CompanyNewsInformation *cni = static_cast(this->ni->data); SetDParamStr(0, cni->president_name); DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER); break; @@ -783,7 +783,7 @@ static void DeleteNewsItem(NewsItem *ni) * * @see NewsSubtype */ -void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32 ref1, NewsReferenceType reftype2, uint32 ref2, void *free_data) +void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32 ref1, NewsReferenceType reftype2, uint32 ref2, const NewsAllocatedData *data) { if (_game_mode == GM_MENU) return; @@ -801,7 +801,7 @@ void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceTy ni->reftype2 = reftype2; ni->ref1 = ref1; ni->ref2 = ref2; - ni->free_data = free_data; + ni->data = data; ni->date = _date; CopyOutDParam(ni->params, 0, lengthof(ni->params)); @@ -882,8 +882,8 @@ CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, ui if (company != INVALID_OWNER && company != _local_company) return CommandCost(); if (flags & DC_EXEC) { - char *news = stredup(text.c_str()); - SetDParamStr(0, news); + NewsStringData *news = new NewsStringData(text); + SetDParamStr(0, news->string); AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, reftype1, p2, NR_NONE, UINT32_MAX, news); } diff --git a/src/news_type.h b/src/news_type.h index 1929804e4b..bed8f16e7c 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -115,6 +115,12 @@ struct NewsTypeData { NewsDisplay GetDisplay() const; }; +/** Container for any custom data that must be deleted after the news item has reached end-of-life. */ +struct NewsAllocatedData { + virtual ~NewsAllocatedData() {} +}; + + /** Information about a single item of news. */ struct NewsItem { NewsItem *prev; ///< Previous news item @@ -129,23 +135,29 @@ struct NewsItem { uint32 ref1; ///< Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. uint32 ref2; ///< Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. - void *free_data; ///< Data to be freed when the news item has reached its end. + const NewsAllocatedData *data; ///< Custom data for the news item that have to be deallocated (deleted) when the news item has reached its end. ~NewsItem() { - free(this->free_data); + delete this->data; } uint64 params[10]; ///< Parameters for string resolving. }; +/** Container for a single string to be passed as NewsAllocatedData. */ +struct NewsStringData : NewsAllocatedData { + std::string string; ///< The string to retain. + NewsStringData(const std::string &str) : string(str) {} +}; + /** * Data that needs to be stored for company news messages. * The problem with company news messages are the custom name * of the companies and the fact that the company data is reset, * resulting in wrong names and such. */ -struct CompanyNewsInformation { +struct CompanyNewsInformation : NewsAllocatedData { char company_name[64]; ///< The name of the company char president_name[64]; ///< The name of the president char other_company_name[64]; ///< The name of the company taking over this one diff --git a/src/subsidy.cpp b/src/subsidy.cpp index 8800da1bd0..28cb0d3ccb 100644 --- a/src/subsidy.cpp +++ b/src/subsidy.cpp @@ -43,22 +43,19 @@ void Subsidy::AwardTo(CompanyID company) this->awarded = company; this->remaining = _settings_game.difficulty.subsidy_duration * MONTHS_IN_YEAR; - char company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, company); - GetString(company_name, STR_COMPANY_NAME, lastof(company_name)); - - char *cn = stredup(company_name); + NewsStringData *company_name = new NewsStringData(GetString(STR_COMPANY_NAME)); /* Add a news item */ std::pair reftype = SetupSubsidyDecodeParam(this, SubsidyDecodeParamType::NewsAwarded); InjectDParam(1); - SetDParamStr(0, cn); + SetDParamStr(0, company_name->string); AddNewsItem( STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier, NT_SUBSIDIES, NF_NORMAL, reftype.first, this->src, reftype.second, this->dst, - cn + company_name ); AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index)); Game::NewEvent(new ScriptEventSubsidyAwarded(this->index)); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index d397825afc..b21d0ab714 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2020,15 +2020,13 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 SetDParam(0, t->index); AddTileNewsItem(STR_NEWS_NEW_TOWN_UNSPONSORED, NT_INDUSTRY_OPEN, tile); } else { - char company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, _current_company); - GetString(company_name, STR_COMPANY_NAME, lastof(company_name)); + NewsStringData *company_name = new NewsStringData(GetString(STR_COMPANY_NAME)); - char *cn = stredup(company_name); - SetDParamStr(0, cn); + SetDParamStr(0, company_name->string); SetDParam(1, t->index); - AddTileNewsItem(STR_NEWS_NEW_TOWN, NT_INDUSTRY_OPEN, tile, cn); + AddTileNewsItem(STR_NEWS_NEW_TOWN, NT_INDUSTRY_OPEN, tile, company_name); } AI::BroadcastNewEvent(new ScriptEventTownFounded(t->index)); Game::NewEvent(new ScriptEventTownFounded(t->index)); @@ -3090,15 +3088,13 @@ static CommandCost TownActionRoadRebuild(Town *t, DoCommandFlag flags) if (flags & DC_EXEC) { t->road_build_months = 6; - char company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, _current_company); - GetString(company_name, STR_COMPANY_NAME, lastof(company_name)); + NewsStringData *company_name = new NewsStringData(GetString(STR_COMPANY_NAME)); - char *cn = stredup(company_name); SetDParam(0, t->index); - SetDParamStr(1, cn); + SetDParamStr(1, company_name->string); - AddNewsItem(STR_NEWS_ROAD_REBUILDING, NT_GENERAL, NF_NORMAL, NR_TOWN, t->index, NR_NONE, UINT32_MAX, cn); + AddNewsItem(STR_NEWS_ROAD_REBUILDING, NT_GENERAL, NF_NORMAL, NR_TOWN, t->index, NR_NONE, UINT32_MAX, company_name); AI::BroadcastNewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); Game::NewEvent(new ScriptEventRoadReconstruction((ScriptCompany::CompanyID)(Owner)_current_company, t->index)); } @@ -3235,7 +3231,7 @@ static CommandCost TownActionBuyRights(Town *t, DoCommandFlag flags) SetWindowClassesDirty(WC_STATION_VIEW); /* Spawn news message */ - CompanyNewsInformation *cni = MallocT(1); + CompanyNewsInformation *cni = new CompanyNewsInformation(); cni->FillData(Company::Get(_current_company)); SetDParam(0, STR_NEWS_EXCLUSIVE_RIGHTS_TITLE); SetDParam(1, STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION); From 9a7750f14eccd8afb6e8bb608ec421c09a486d53 Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Wed, 16 Jun 2021 17:54:08 +0200 Subject: [PATCH 52/53] Codechange: use the constructor for CompanyNewsItem to fill the data instead of a separate function --- src/company_cmd.cpp | 18 +++++++----------- src/economy.cpp | 6 ++---- src/news_type.h | 8 ++++---- src/town_cmd.cpp | 3 +-- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 3c5e5f5c75..7549212849 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -376,8 +376,7 @@ set_name:; MarkWholeScreenDirty(); if (c->is_ai) { - CompanyNewsInformation *cni = new CompanyNewsInformation(); - cni->FillData(c); + CompanyNewsInformation *cni = new CompanyNewsInformation(c); SetDParam(0, STR_NEWS_COMPANY_LAUNCH_TITLE); SetDParam(1, STR_NEWS_COMPANY_LAUNCH_DESCRIPTION); SetDParamStr(2, cni->company_name); @@ -755,21 +754,19 @@ void CompaniesYearlyLoop() * @param c the current company. * @param other the other company (use \c nullptr if not relevant). */ -void CompanyNewsInformation::FillData(const Company *c, const Company *other) +CompanyNewsInformation::CompanyNewsInformation(const Company *c, const Company *other) { SetDParam(0, c->index); - GetString(this->company_name, STR_COMPANY_NAME, lastof(this->company_name)); + this->company_name = GetString(STR_COMPANY_NAME); - if (other == nullptr) { - *this->other_company_name = '\0'; - } else { + if (other != nullptr) { SetDParam(0, other->index); - GetString(this->other_company_name, STR_COMPANY_NAME, lastof(this->other_company_name)); + this->other_company_name = GetString(STR_COMPANY_NAME); c = other; } SetDParam(0, c->index); - GetString(this->president_name, STR_PRESIDENT_NAME_MANAGER, lastof(this->president_name)); + this->president_name = GetString(STR_PRESIDENT_NAME_MANAGER); this->colour = c->colour; this->face = c->face; @@ -888,8 +885,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 /* Delete any open window of the company */ CloseCompanyWindows(c->index); - CompanyNewsInformation *cni = new CompanyNewsInformation(); - cni->FillData(c); + CompanyNewsInformation *cni = new CompanyNewsInformation(c); /* Show the bankrupt news */ SetDParam(0, STR_NEWS_COMPANY_BANKRUPT_TITLE); diff --git a/src/economy.cpp b/src/economy.cpp index cb45d55b75..0c2e73cbdc 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -580,8 +580,7 @@ static void CompanyCheckBankrupt(Company *c) /* Warn about bankruptcy after 3 months */ case 4: { - CompanyNewsInformation *cni = new CompanyNewsInformation(); - cni->FillData(c); + CompanyNewsInformation *cni = new CompanyNewsInformation(c); SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE); SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION); SetDParamStr(2, cni->company_name); @@ -1975,8 +1974,7 @@ static void DoAcquireCompany(Company *c) { CompanyID ci = c->index; - CompanyNewsInformation *cni = new CompanyNewsInformation(); - cni->FillData(c, Company::Get(_current_company)); + CompanyNewsInformation *cni = new CompanyNewsInformation(c, Company::Get(_current_company)); SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE); SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION); diff --git a/src/news_type.h b/src/news_type.h index bed8f16e7c..8045a58fa9 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -158,14 +158,14 @@ struct NewsStringData : NewsAllocatedData { * resulting in wrong names and such. */ struct CompanyNewsInformation : NewsAllocatedData { - char company_name[64]; ///< The name of the company - char president_name[64]; ///< The name of the president - char other_company_name[64]; ///< The name of the company taking over this one + std::string company_name; ///< The name of the company + std::string president_name; ///< The name of the president + std::string other_company_name; ///< The name of the company taking over this one uint32 face; ///< The face of the president byte colour; ///< The colour related to the company - void FillData(const struct Company *c, const struct Company *other = nullptr); + CompanyNewsInformation(const struct Company *c, const struct Company *other = nullptr); }; #endif /* NEWS_TYPE_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index b21d0ab714..d53cd57835 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -3231,8 +3231,7 @@ static CommandCost TownActionBuyRights(Town *t, DoCommandFlag flags) SetWindowClassesDirty(WC_STATION_VIEW); /* Spawn news message */ - CompanyNewsInformation *cni = new CompanyNewsInformation(); - cni->FillData(Company::Get(_current_company)); + CompanyNewsInformation *cni = new CompanyNewsInformation(Company::Get(_current_company)); SetDParam(0, STR_NEWS_EXCLUSIVE_RIGHTS_TITLE); SetDParam(1, STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION); SetDParam(2, t->index); From 9c7a7b53a192deef9dadf7f31d68c9a76cfaf35c Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 17 Jun 2021 16:38:34 +0200 Subject: [PATCH 53/53] Codechange: use a contructor for NewsItem to set the values And use std::unique_ptr to manage the memory of the allocated data --- src/news_gui.cpp | 46 ++++++++++++++++++++++++++-------------------- src/news_type.h | 9 +++------ 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/news_gui.cpp b/src/news_gui.cpp index fb03207150..4bd4bcecbb 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -355,7 +355,7 @@ struct NewsWindow : Window { break; case WID_N_MGR_NAME: - SetDParamStr(0, static_cast(this->ni->data)->president_name); + SetDParamStr(0, static_cast(this->ni->data.get())->president_name); str = STR_JUST_RAW_STRING; break; @@ -433,13 +433,13 @@ struct NewsWindow : Window { break; case WID_N_MGR_FACE: { - const CompanyNewsInformation *cni = static_cast(this->ni->data); + const CompanyNewsInformation *cni = static_cast(this->ni->data.get()); DrawCompanyManagerFace(cni->face, cni->colour, r.left, r.top); GfxFillRect(r.left, r.top, r.right, r.bottom, PALETTE_NEWSPAPER, FILLRECT_RECOLOUR); break; } case WID_N_MGR_NAME: { - const CompanyNewsInformation *cni = static_cast(this->ni->data); + const CompanyNewsInformation *cni = static_cast(this->ni->data.get()); SetDParamStr(0, cni->president_name); DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER); break; @@ -770,6 +770,27 @@ static void DeleteNewsItem(NewsItem *ni) SetWindowDirty(WC_MESSAGE_HISTORY, 0); } +/** + * Create a new newsitem to be shown. + * @param string_id String to display. + * @param type The type of news. + * @param flags Flags related to how to display the news. + * @param reftype1 Type of ref1. + * @param ref1 Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. + * @param reftype2 Type of ref2. + * @param ref2 Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. + * @param data Pointer to data that must be released once the news message is cleared. + * + * @see NewsSubtype + */ +NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32 ref1, NewsReferenceType reftype2, uint32 ref2, const NewsAllocatedData *data) : + string_id(string_id), date(_date), type(type), flags(flags), reftype1(reftype1), reftype2(reftype2), ref1(ref1), ref2(ref2), data(data) +{ + /* show this news message in colour? */ + if (_cur_year >= _settings_client.gui.coloured_news_year) this->flags |= NF_INCOLOUR; + CopyOutDParam(this->params, 0, lengthof(this->params)); +} + /** * Add a new newsitem to be shown. * @param string String to display @@ -779,7 +800,7 @@ static void DeleteNewsItem(NewsItem *ni) * @param ref1 Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. * @param reftype2 Type of ref2 * @param ref2 Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. - * @param free_data Pointer to data that must be freed once the news message is cleared + * @param data Pointer to data that must be released once the news message is cleared. * * @see NewsSubtype */ @@ -788,22 +809,7 @@ void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceTy if (_game_mode == GM_MENU) return; /* Create new news item node */ - NewsItem *ni = new NewsItem; - - ni->string_id = string; - ni->type = type; - ni->flags = flags; - - /* show this news message in colour? */ - if (_cur_year >= _settings_client.gui.coloured_news_year) ni->flags |= NF_INCOLOUR; - - ni->reftype1 = reftype1; - ni->reftype2 = reftype2; - ni->ref1 = ref1; - ni->ref2 = ref2; - ni->data = data; - ni->date = _date; - CopyOutDParam(ni->params, 0, lengthof(ni->params)); + NewsItem *ni = new NewsItem(string, type, flags, reftype1, ref1, reftype2, ref2, data); if (_total_news++ == 0) { assert(_oldest_news == nullptr); diff --git a/src/news_type.h b/src/news_type.h index 8045a58fa9..4dea8c46f5 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -135,14 +135,11 @@ struct NewsItem { uint32 ref1; ///< Reference 1 to some object: Used for a possible viewport, scrolling after clicking on the news, and for deleting the news when the object is deleted. uint32 ref2; ///< Reference 2 to some object: Used for scrolling after clicking on the news, and for deleting the news when the object is deleted. - const NewsAllocatedData *data; ///< Custom data for the news item that have to be deallocated (deleted) when the news item has reached its end. - - ~NewsItem() - { - delete this->data; - } + std::unique_ptr data; ///< Custom data for the news item that will be deallocated (deleted) when the news item has reached its end. uint64 params[10]; ///< Parameters for string resolving. + + NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32 ref1, NewsReferenceType reftype2, uint32 ref2, const NewsAllocatedData *data); }; /** Container for a single string to be passed as NewsAllocatedData. */