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;
extern void RebuildTownCaches();
RebuildTownCaches();
extern void RebuildTownCaches(bool cargo_update_required);
RebuildTownCaches(false);
RebuildSubsidisedSourceAndDestinationCache();
Station::RecomputeCatchmentForAll();

@ -3093,17 +3093,21 @@ bool AfterLoadGame()
* which is done by StartupEngines(). */
if (gcf_res != GLC_ALL_GOOD) StartupEngines();
if (IsSavegameVersionBefore(SLV_166)) {
if (SlXvIsFeatureMissing(XSLFI_TOWN_CARGO_MATRIX)) {
/* Update cargo acceptance map of towns. */
Town *town;
FOR_ALL_TOWNS(town) {
town->cargo_accepted.Clear();
}
for (TileIndex t = 0; t < map_size; t++) {
if (!IsTileType(t, MP_HOUSE)) continue;
Town::Get(GetTownIndex(t))->cargo_accepted.Add(t);
}
Town *town;
FOR_ALL_TOWNS(town) {
UpdateTownCargoes(town);
}
UpdateTownCargoBitmap();
}
/* 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_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_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_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_GAME_EVENTS, ///< Game event flags
XSLFI_ROAD_LAYOUT_CHANGE_CTR, ///< Road layout change counter
XSLFI_TOWN_CARGO_MATRIX, ///< Town cargo matrix savegame format changes
XSLFI_DEBUG, ///< Debugging info
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.
*/
void RebuildTownCaches()
void RebuildTownCaches(bool cargo_update_required)
{
Town *town;
InitializeBuildingCounts();
@ -51,7 +51,11 @@ void RebuildTownCaches()
/* Update the population and num_house dependent values */
FOR_ALL_TOWNS(town) {
UpdateTownRadius(town);
UpdateTownCargoes(town);
if (cargo_update_required) {
UpdateTownCargoes(town);
} else {
UpdateTownCargoTotal(town);
}
}
UpdateTownCargoBitmap();
}
@ -66,6 +70,8 @@ void RebuildTownCaches()
*/
void UpdateHousesAndTowns()
{
bool cargo_update_required = false;
for (TileIndex t = 0; t < MapSize(); t++) {
if (!IsTileType(t, MP_HOUSE)) continue;
@ -75,6 +81,7 @@ void UpdateHousesAndTowns()
* replace it with the substitute original house type. */
house_id = _house_mngr.GetSubstituteID(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.
* The other tiles will get removed later in this loop because
* 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) {
/* This tile should be part of a multi-tile building but the
* north tile of this house isn't on the map. */
DoClearSquare(t);
cargo_update_required = true;
}
}
RebuildTownCaches();
RebuildTownCaches(cargo_update_required);
}
/** Save and load of towns. */
@ -273,7 +284,7 @@ static void RealSave_Town(Town *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;
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");
}
if (IsSavegameVersionBefore(SLV_166)) continue;
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_UINT32);
/* Rebuild total cargo acceptance. */
UpdateTownCargoTotal(t);
if (!IsSavegameVersionBefore(SLV_166) && SlXvIsFeatureMissing(XSLFI_TOWN_CARGO_MATRIX)) {
SlSkipBytes(4); // tile
uint16 w = SlReadUint16();
uint16 h = SlReadUint16();
if (w != 0) {
SlSkipBytes(4 * (w / 4 * h / 4));
}
}
if (SlXvIsFeaturePresent(XSLFI_TOWN_CARGO_MATRIX)) {
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);
}
void Clear()
{
this->area = TileArea(INVALID_TILE, 0, 0);
free(this->data);
this->data = nullptr;
}
/**
* Get the total covered area.
* @return The area covered by the matrix.

@ -93,7 +93,7 @@ struct Town : TownPool::PoolItem<&_town_pool> {
/* Cargo production and acceptance stats. */
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.
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 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;
CargoTypes dummy = 0;
/* 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. */
/* Gather acceptance for all houses in an area around the start tile. */
TileArea area = AcceptanceMatrix::GetAreaForTile(start, 1);
TILE_AREA_LOOP(tile, area) {
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);
}
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.
* @param t The town to update.
*/
@ -1003,7 +1013,7 @@ void UpdateTownCargoes(Town *t)
/* Update acceptance for each grid square. */
TILE_AREA_LOOP_STEP(tile, area, AcceptanceMatrix::GRID) {
UpdateTownCargoes(t, tile, false);
UpdateTownCargoesSingleGridArea(t, tile, false);
}
/* 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);
UpdateTownRadius(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);
/* Update cargo acceptance. */
UpdateTownCargoes(t, tile);
UpdateTownCargoesHouse(t, tile, eflags & BUILDING_2_TILES_X, eflags & BUILDING_2_TILES_Y);
}
/**

Loading…
Cancel
Save