From 14636d2512f558c29dd7f4b0f8b8d63e7d1c08e0 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 19 Apr 2021 22:55:32 +0100 Subject: [PATCH] Check multi-tile ID-translated houses after house ID limit change (Or when reloading NewGRFs) If an overriding house type which newly fit in the limit changed the tile layout, existing houses on the map could have the wrong layout See: #243 --- src/saveload/extended_ver_sl.cpp | 2 +- src/saveload/town_sl.cpp | 66 +++++++++++++++++++------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index bbdc33a790..58840bb7aa 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -147,7 +147,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 2, 2, "realistic_train_braking", nullptr, nullptr, "VLKA" }, { XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr }, { XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr }, - { XSLFI_MORE_HOUSES, XSCF_NULL, 1, 1, "more_houses", nullptr, nullptr, nullptr }, + { XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr }, { XSLFI_CUSTOM_TOWN_ZONE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "custom_town_zone", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 7ec7f75f26..cf4d9cbb1d 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -60,36 +60,13 @@ void RebuildTownCaches(bool cargo_update_required, bool old_map_position) } } -/** - * Check and update town and house values. - * - * Checked are the HouseIDs. Updated are the - * town population the number of houses per - * town, the town radius and the max passengers - * of the town. - */ -void UpdateHousesAndTowns(bool cargo_update_required, bool old_map_position) +static void CheckMultiTileHouseTypes(bool &cargo_update_required, bool old_map_position, bool translate_house_types) { auto get_clean_house_type = [&](TileIndex t) -> HouseID { - return SLGetCleanHouseType(t, old_map_position); + HouseID type = SLGetCleanHouseType(t, old_map_position); + if (translate_house_types) type = GetTranslatedHouseID(type); + return type; }; - for (TileIndex t = 0; t < MapSize(); t++) { - if (!IsTileType(t, MP_HOUSE)) continue; - - HouseID house_id = get_clean_house_type(t); - if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) { - /* The specs for this type of house are not available any more, so - * replace it with the substitute original house type. */ - house_id = _house_mngr.GetSubstituteID(house_id); - if (old_map_position && SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) { - _m[t].m4 = GB(house_id, 0, 8); - SB(_m[t].m3, 6, 1, GB(house_id, 8, 1)); - } else { - SetHouseType(t, house_id); - } - cargo_update_required = true; - } - } /* Check for cases when a NewGRF has set a wrong house substitute type. */ for (TileIndex t = 0; t < MapSize(); t++) { @@ -128,6 +105,41 @@ void UpdateHousesAndTowns(bool cargo_update_required, bool old_map_position) cargo_update_required = true; } } +} + +/** + * Check and update town and house values. + * + * Checked are the HouseIDs. Updated are the + * town population the number of houses per + * town, the town radius and the max passengers + * of the town. + */ +void UpdateHousesAndTowns(bool cargo_update_required, bool old_map_position) +{ + auto get_clean_house_type = [&](TileIndex t) -> HouseID { + return SLGetCleanHouseType(t, old_map_position); + }; + for (TileIndex t = 0; t < MapSize(); t++) { + if (!IsTileType(t, MP_HOUSE)) continue; + + HouseID house_id = get_clean_house_type(t); + if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) { + /* The specs for this type of house are not available any more, so + * replace it with the substitute original house type. */ + house_id = _house_mngr.GetSubstituteID(house_id); + if (old_map_position && SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) { + _m[t].m4 = GB(house_id, 0, 8); + SB(_m[t].m3, 6, 1, GB(house_id, 8, 1)); + } else { + SetHouseType(t, house_id); + } + cargo_update_required = true; + } + } + + CheckMultiTileHouseTypes(cargo_update_required, old_map_position, false); + if (cargo_update_required || SlXvIsFeatureMissing(XSLFI_MORE_HOUSES, 2)) CheckMultiTileHouseTypes(cargo_update_required, old_map_position, true); RebuildTownCaches(cargo_update_required, old_map_position); }