Fix town production and acceptance cache saveload/update handling

pull/91/head
Jonathan G Rennison 5 years ago
parent 33344482ae
commit c2470a21af

@ -1341,8 +1341,8 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log)
const CargoTypes old_town_cargoes_accepted = _town_cargoes_accepted; const CargoTypes old_town_cargoes_accepted = _town_cargoes_accepted;
extern void RebuildTownCaches(); extern void RebuildTownCaches(bool cargo_update_required);
RebuildTownCaches(); RebuildTownCaches(false);
RebuildSubsidisedSourceAndDestinationCache(); RebuildSubsidisedSourceAndDestinationCache();
Station::RecomputeCatchmentForAll(); Station::RecomputeCatchmentForAll();

@ -3093,17 +3093,21 @@ bool AfterLoadGame()
* which is done by StartupEngines(). */ * which is done by StartupEngines(). */
if (gcf_res != GLC_ALL_GOOD) StartupEngines(); if (gcf_res != GLC_ALL_GOOD) StartupEngines();
if (IsSavegameVersionBefore(SLV_166)) { if (SlXvIsFeatureMissing(XSLFI_TOWN_CARGO_MATRIX)) {
/* Update cargo acceptance map of towns. */ /* Update cargo acceptance map of towns. */
Town *town;
FOR_ALL_TOWNS(town) {
town->cargo_accepted.Clear();
}
for (TileIndex t = 0; t < map_size; t++) { for (TileIndex t = 0; t < map_size; t++) {
if (!IsTileType(t, MP_HOUSE)) continue; if (!IsTileType(t, MP_HOUSE)) continue;
Town::Get(GetTownIndex(t))->cargo_accepted.Add(t); Town::Get(GetTownIndex(t))->cargo_accepted.Add(t);
} }
Town *town;
FOR_ALL_TOWNS(town) { FOR_ALL_TOWNS(town) {
UpdateTownCargoes(town); UpdateTownCargoes(town);
} }
UpdateTownCargoBitmap();
} }
/* Set some breakdown-related variables to the correct values. */ /* Set some breakdown-related variables to the correct values. */

@ -107,6 +107,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_LINKGRAPH_MODES, XSCF_NULL, 1, 1, "linkgraph_modes", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_MODES, XSCF_NULL, 1, 1, "linkgraph_modes", nullptr, nullptr, nullptr },
{ XSLFI_GAME_EVENTS, XSCF_NULL, 1, 1, "game_events", nullptr, nullptr, nullptr }, { XSLFI_GAME_EVENTS, XSCF_NULL, 1, 1, "game_events", nullptr, nullptr, nullptr },
{ XSLFI_ROAD_LAYOUT_CHANGE_CTR, XSCF_NULL, 1, 1, "road_layout_change_ctr", nullptr, nullptr, nullptr }, { XSLFI_ROAD_LAYOUT_CHANGE_CTR, XSCF_NULL, 1, 1, "road_layout_change_ctr", nullptr, nullptr, nullptr },
{ XSLFI_TOWN_CARGO_MATRIX, XSCF_NULL, 1, 1, "town_cargo_matrix", nullptr, nullptr, nullptr },
{ XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" }, { XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
}; };

@ -74,6 +74,7 @@ enum SlXvFeatureIndex {
XSLFI_LINKGRAPH_MODES, ///< Linkgraph additional distribution modes XSLFI_LINKGRAPH_MODES, ///< Linkgraph additional distribution modes
XSLFI_GAME_EVENTS, ///< Game event flags XSLFI_GAME_EVENTS, ///< Game event flags
XSLFI_ROAD_LAYOUT_CHANGE_CTR, ///< Road layout change counter XSLFI_ROAD_LAYOUT_CHANGE_CTR, ///< Road layout change counter
XSLFI_TOWN_CARGO_MATRIX, ///< Town cargo matrix savegame format changes
XSLFI_DEBUG, ///< Debugging info XSLFI_DEBUG, ///< Debugging info
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit

@ -24,7 +24,7 @@
/** /**
* Rebuild all the cached variables of towns. * Rebuild all the cached variables of towns.
*/ */
void RebuildTownCaches() void RebuildTownCaches(bool cargo_update_required)
{ {
Town *town; Town *town;
InitializeBuildingCounts(); InitializeBuildingCounts();
@ -51,7 +51,11 @@ void RebuildTownCaches()
/* Update the population and num_house dependent values */ /* Update the population and num_house dependent values */
FOR_ALL_TOWNS(town) { FOR_ALL_TOWNS(town) {
UpdateTownRadius(town); UpdateTownRadius(town);
UpdateTownCargoes(town); if (cargo_update_required) {
UpdateTownCargoes(town);
} else {
UpdateTownCargoTotal(town);
}
} }
UpdateTownCargoBitmap(); UpdateTownCargoBitmap();
} }
@ -66,6 +70,8 @@ void RebuildTownCaches()
*/ */
void UpdateHousesAndTowns() void UpdateHousesAndTowns()
{ {
bool cargo_update_required = false;
for (TileIndex t = 0; t < MapSize(); t++) { for (TileIndex t = 0; t < MapSize(); t++) {
if (!IsTileType(t, MP_HOUSE)) continue; if (!IsTileType(t, MP_HOUSE)) continue;
@ -75,6 +81,7 @@ void UpdateHousesAndTowns()
* replace it with the substitute original house type. */ * replace it with the substitute original house type. */
house_id = _house_mngr.GetSubstituteID(house_id); house_id = _house_mngr.GetSubstituteID(house_id);
SetHouseType(t, house_id); SetHouseType(t, house_id);
cargo_update_required = true;
} }
} }
@ -104,15 +111,19 @@ void UpdateHousesAndTowns()
/* If not all tiles of this house are present remove the house. /* If not all tiles of this house are present remove the house.
* The other tiles will get removed later in this loop because * The other tiles will get removed later in this loop because
* their north tile is not the correct type anymore. */ * their north tile is not the correct type anymore. */
if (!valid_house) DoClearSquare(t); if (!valid_house) {
DoClearSquare(t);
cargo_update_required = true;
}
} else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) { } else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) {
/* This tile should be part of a multi-tile building but the /* This tile should be part of a multi-tile building but the
* north tile of this house isn't on the map. */ * north tile of this house isn't on the map. */
DoClearSquare(t); DoClearSquare(t);
cargo_update_required = true;
} }
} }
RebuildTownCaches(); RebuildTownCaches(cargo_update_required);
} }
/** Save and load of towns. */ /** Save and load of towns. */
@ -273,7 +284,7 @@ static void RealSave_Town(Town *t)
SlObject(&t->cargo_accepted, GetTileMatrixDesc()); SlObject(&t->cargo_accepted, GetTileMatrixDesc());
if (t->cargo_accepted.area.w != 0) { if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); SlArray(t->cargo_accepted.data, arr_len, SLE_UINT64);
} }
} }
@ -313,16 +324,24 @@ static void Load_TOWN()
SlErrorCorrupt("Invalid town name generator"); SlErrorCorrupt("Invalid town name generator");
} }
if (IsSavegameVersionBefore(SLV_166)) continue; if (!IsSavegameVersionBefore(SLV_166) && SlXvIsFeatureMissing(XSLFI_TOWN_CARGO_MATRIX)) {
SlSkipBytes(4); // tile
SlObject(&t->cargo_accepted, GetTileMatrixDesc()); uint16 w = SlReadUint16();
if (t->cargo_accepted.area.w != 0) { uint16 h = SlReadUint16();
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID; if (w != 0) {
t->cargo_accepted.data = MallocT<CargoTypes>(arr_len); SlSkipBytes(4 * (w / 4 * h / 4));
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT32); }
}
/* Rebuild total cargo acceptance. */ if (SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX)) {
UpdateTownCargoTotal(t); SlObject(&t->cargo_accepted, GetTileMatrixDesc());
if (t->cargo_accepted.area.w != 0) {
uint arr_len = t->cargo_accepted.area.w / AcceptanceMatrix::GRID * t->cargo_accepted.area.h / AcceptanceMatrix::GRID;
t->cargo_accepted.data = MallocT<CargoTypes>(arr_len);
SlArray(t->cargo_accepted.data, arr_len, SLE_UINT64);
/* Rebuild total cargo acceptance. */
UpdateTownCargoTotal(t);
}
} }
} }
} }

@ -76,6 +76,13 @@ public:
free(this->data); free(this->data);
} }
void Clear()
{
this->area = TileArea(INVALID_TILE, 0, 0);
free(this->data);
this->data = nullptr;
}
/** /**
* Get the total covered area. * Get the total covered area.
* @return The area covered by the matrix. * @return The area covered by the matrix.

@ -93,7 +93,7 @@ struct Town : TownPool::PoolItem<&_town_pool> {
/* Cargo production and acceptance stats. */ /* Cargo production and acceptance stats. */
CargoTypes cargo_produced; ///< Bitmap of all cargoes produced by houses in this town. CargoTypes cargo_produced; ///< Bitmap of all cargoes produced by houses in this town.
AcceptanceMatrix cargo_accepted; ///< Bitmap of cargoes accepted by houses for each 4*4 map square of the town. AcceptanceMatrix cargo_accepted; ///< Bitmap of cargoes accepted by houses for each 4*4 (really 6*6) map square of the town.
CargoTypes cargo_accepted_total; ///< NOSAVE: Bitmap of all cargoes accepted by houses in this town. CargoTypes cargo_accepted_total; ///< NOSAVE: Bitmap of all cargoes accepted by houses in this town.
StationList stations_near; ///< NOSAVE: List of nearby stations. StationList stations_near; ///< NOSAVE: List of nearby stations.

@ -964,14 +964,12 @@ void UpdateTownCargoTotal(Town *t)
* @param start Update the values around this tile. * @param start Update the values around this tile.
* @param update_total Set to true if the total cargo acceptance should be updated. * @param update_total Set to true if the total cargo acceptance should be updated.
*/ */
static void UpdateTownCargoes(Town *t, TileIndex start, bool update_total = true) static void UpdateTownCargoesSingleGridArea(Town *t, TileIndex start, bool update_total = true)
{ {
CargoArray accepted, produced; CargoArray accepted, produced;
CargoTypes dummy = 0; CargoTypes dummy = 0;
/* Gather acceptance for all houses in an area around the start tile. /* Gather acceptance for all houses in an area around the start tile. */
* The area is composed of the square the tile is in, extended one square in all
* directions as the coverage area of a single station is bigger than just one square. */
TileArea area = AcceptanceMatrix::GetAreaForTile(start, 1); TileArea area = AcceptanceMatrix::GetAreaForTile(start, 1);
TILE_AREA_LOOP(tile, area) { TILE_AREA_LOOP(tile, area) {
if (!IsTileType(tile, MP_HOUSE) || GetTownIndex(tile) != t->index) continue; if (!IsTileType(tile, MP_HOUSE) || GetTownIndex(tile) != t->index) continue;
@ -991,6 +989,18 @@ static void UpdateTownCargoes(Town *t, TileIndex start, bool update_total = true
if (update_total) UpdateTownCargoTotal(t); if (update_total) UpdateTownCargoTotal(t);
} }
static void UpdateTownCargoesHouse(Town *t, TileIndex start, bool x_two_tiles, bool y_two_tiles, bool update_total = true)
{
TileIndex lower = TileAddWrap(start, -1, -1);
TileIndex upper = TileAddWrap(start, x_two_tiles ? 2 : 1, y_two_tiles ? 2 : 1);
for (uint x = TileX(lower) & ~(AcceptanceMatrix::GRID - 1); x <= TileX(upper); x += AcceptanceMatrix::GRID) {
for (uint y = TileY(lower) & ~(AcceptanceMatrix::GRID - 1); y <= TileY(upper); y += AcceptanceMatrix::GRID) {
UpdateTownCargoesSingleGridArea(t, TileXY(x, y), false);
}
}
if (update_total) UpdateTownCargoTotal(t);
}
/** Update cargo acceptance for the complete town. /** Update cargo acceptance for the complete town.
* @param t The town to update. * @param t The town to update.
*/ */
@ -1003,7 +1013,7 @@ void UpdateTownCargoes(Town *t)
/* Update acceptance for each grid square. */ /* Update acceptance for each grid square. */
TILE_AREA_LOOP_STEP(tile, area, AcceptanceMatrix::GRID) { TILE_AREA_LOOP_STEP(tile, area, AcceptanceMatrix::GRID) {
UpdateTownCargoes(t, tile, false); UpdateTownCargoesSingleGridArea(t, tile, false);
} }
/* Update the total acceptance. */ /* Update the total acceptance. */
@ -2643,7 +2653,7 @@ static void DoBuildHouse(Town *t, TileIndex tile, HouseID house, byte random_bit
MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits); MakeTownHouse(tile, t, construction_counter, construction_stage, house, random_bits);
UpdateTownRadius(t); UpdateTownRadius(t);
UpdateTownGrowthRate(t); UpdateTownGrowthRate(t);
UpdateTownCargoes(t, tile); UpdateTownCargoesHouse(t, tile, hs->building_flags & BUILDING_2_TILES_X, hs->building_flags & BUILDING_2_TILES_Y);
} }
/** /**
@ -2852,7 +2862,7 @@ void ClearTownHouse(Town *t, TileIndex tile)
UpdateTownRadius(t); UpdateTownRadius(t);
/* Update cargo acceptance. */ /* Update cargo acceptance. */
UpdateTownCargoes(t, tile); UpdateTownCargoesHouse(t, tile, eflags & BUILDING_2_TILES_X, eflags & BUILDING_2_TILES_Y);
} }
/** /**

Loading…
Cancel
Save