From 1e769d050f987563b8f4d98225827f0285ffd7c3 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 17 Nov 2022 00:40:12 +0000 Subject: [PATCH] Leave PLYP chunk unchanged when loading/saving server saves in non-MP --- src/company_cmd.cpp | 18 ++++++++++++++ src/openttd.cpp | 3 +++ src/saveload/company_sl.cpp | 41 ++++++++++++++++++++++++++++---- src/saveload/extended_ver_sl.cpp | 2 +- 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index e0f8759425..ff4c26ce37 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -42,6 +42,8 @@ #include "table/strings.h" +#include + #include "safeguards.h" void ClearEnginesHiddenFlagOfCompany(CompanyID cid); @@ -54,6 +56,9 @@ CompanyManagerFace _company_manager_face; ///< for company manager face storage uint _next_competitor_start; ///< the number of ticks before the next AI is started uint _cur_company_tick_index; ///< used to generate a name for one company that doesn't have a name yet per tick +CompanyMask _saved_PLYP_invalid_mask; +std::vector _saved_PLYP_data; + CompanyPool _company_pool("Company"); ///< Pool of companies. INSTANTIATE_POOL_METHODS(Company) @@ -83,6 +88,7 @@ Company::~Company() if (CleaningPool()) return; DeleteCompanyWindows(this->index); + SetBit(_saved_PLYP_invalid_mask, this->index); } /** @@ -640,10 +646,22 @@ static bool MaybeStartNewCompany() return false; } +static void ClearSavedPLYP() +{ + _saved_PLYP_invalid_mask = 0; + _saved_PLYP_data.clear(); +} + /** Initialize the pool of companies. */ void InitializeCompanies() { _cur_company_tick_index = 0; + ClearSavedPLYP(); +} + +void UninitializeCompanies() +{ + ClearSavedPLYP(); } /** diff --git a/src/openttd.cpp b/src/openttd.cpp index a9fcd6845e..388a047383 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -475,6 +475,9 @@ static void ShutdownGame() ClearSpecialEventsLog(); ClearDesyncMsgLog(); + extern void UninitializeCompanies(); + UninitializeCompanies(); + _loaded_local_company = COMPANY_SPECTATOR; _game_events_since_load = (GameEventFlags) 0; _game_events_overall = (GameEventFlags) 0; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 92dc188e04..9f3118470c 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -569,10 +569,25 @@ static void Save_PLYX() static void Load_PLYP() { size_t size = SlGetFieldLength(); - if (size <= 16 + 24 + 16 || !_network_server) { + CompanyMask invalid_mask = 0; + if (SlXvIsFeaturePresent(XSLFI_COMPANY_PW, 2)) { + if (size <= 2) return; + invalid_mask = SlReadUint16(); + size -= 2; + } + if (size <= 16 + 24 + 16 || (_networking && !_network_server)) { SlSkipBytes(size); return; } + if (!_network_server) { + extern CompanyMask _saved_PLYP_invalid_mask; + extern std::vector _saved_PLYP_data; + + _saved_PLYP_invalid_mask = invalid_mask; + _saved_PLYP_data.resize(size); + ReadBuffer::GetCurrent()->CopyBytes(_saved_PLYP_data.data(), _saved_PLYP_data.size()); + return; + } uint8 token[16]; ReadBuffer::GetCurrent()->CopyBytes(token, 16); @@ -591,7 +606,7 @@ static void Load_PLYP() ReadBuffer::GetCurrent()->CopyBytes(buffer.data(), buffer.size()); if (crypto_unlock(buffer.data(), _network_company_password_storage_key, nonce, mac, buffer.data(), buffer.size()) == 0) { - SlLoadFromBuffer(buffer.data(), buffer.size(), []() { + SlLoadFromBuffer(buffer.data(), buffer.size(), [invalid_mask]() { _network_company_server_id.resize(SlReadUint32()); ReadBuffer::GetCurrent()->CopyBytes((uint8 *)_network_company_server_id.data(), _network_company_server_id.size()); @@ -601,7 +616,9 @@ static void Load_PLYP() std::string password; password.resize(SlReadUint32()); ReadBuffer::GetCurrent()->CopyBytes((uint8 *)password.data(), password.size()); - NetworkServerSetCompanyPassword((CompanyID)cid, password, true); + if (!HasBit(invalid_mask, cid)) { + NetworkServerSetCompanyPassword((CompanyID)cid, password, true); + } } ReadBuffer::GetCurrent()->SkipBytes(SlReadByte()); // Skip padding @@ -614,10 +631,23 @@ static void Load_PLYP() static void Save_PLYP() { - if (!_network_server || IsNetworkServerSave()) { + if ((_networking && !_network_server) || IsNetworkServerSave()) { SlSetLength(0); return; } + if (!_network_server) { + extern CompanyMask _saved_PLYP_invalid_mask; + extern std::vector _saved_PLYP_data; + + if (_saved_PLYP_data.empty()) { + SlSetLength(0); + } else { + SlSetLength(2 + _saved_PLYP_data.size()); + SlWriteUint16(_saved_PLYP_invalid_mask); + MemoryDumper::GetCurrent()->CopyBytes((const uint8 *)_saved_PLYP_data.data(), _saved_PLYP_data.size()); + } + return; + } uint8 nonce[24]; /* Use only once per key: random */ if (randombytes(nonce, 24) < 0) { @@ -656,7 +686,8 @@ static void Save_PLYP() /* Encrypt in place */ crypto_lock(mac, buffer.data(), _network_company_password_storage_key, nonce, buffer.data(), buffer.size()); - SlSetLength(16 + 24 + 16 + buffer.size()); + SlSetLength(2 + 16 + 24 + 16 + buffer.size()); + SlWriteUint16(0); // Invalid mask MemoryDumper::GetCurrent()->CopyBytes(_network_company_password_storage_token, 16); MemoryDumper::GetCurrent()->CopyBytes(nonce, 24); MemoryDumper::GetCurrent()->CopyBytes(mac, 16); diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index e2dc4a99ca..d0dda55f6f 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -164,7 +164,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_BANKRUPTCY_EXTRA, XSCF_NULL, 2, 2, "bankruptcy_extra", nullptr, nullptr, nullptr }, { XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 3, 3, "object_ground_types", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr }, - { XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 1, 1, "company_password", nullptr, nullptr, "PLYP" }, + { XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 2, 2, "company_password", nullptr, nullptr, "PLYP" }, { XSLFI_ST_INDUSTRY_CARGO_MODE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "st_industry_cargo_mode", nullptr, nullptr, nullptr }, { XSLFI_TL_SPEED_LIMIT, XSCF_IGNORABLE_UNKNOWN, 1, 1, "tl_speed_limit", nullptr, nullptr, nullptr }, { XSLFI_WAYPOINT_FLAGS, XSCF_NULL, 1, 1, "waypoint_flags", nullptr, nullptr, nullptr },