Change: Reorganise industry accept/produce arrays. (#10853)

Use a array of struct for each cargo instead of an array for each statistic.
This makes iterating for acceptance and production much simpler.
pct_transported is now calculated when needed.
This commit is contained in:
PeterN
2023-05-25 21:25:46 +01:00
committed by GitHub
parent db3b086a52
commit 584faaf064
16 changed files with 527 additions and 355 deletions

View File

@@ -189,6 +189,33 @@ static inline void GetAllCargoSuffixes(CargoSuffixInOut use_input, CargoSuffixTy
}
}
/**
* Gets the strings to display after the cargo of industries (using callback 37)
* @param use_input get suffixes for output cargo or input cargo?
* @param cst the cargo suffix type (for which window is it requested). @see CargoSuffixType
* @param ind the industry (nullptr if in fund window)
* @param ind_type the industry type
* @param indspec the industry spec
* @param cargo cargotype. for CT_INVALID no suffix will be determined
* @param slot accepts/produced slot number, used for old-style 3-in/2-out industries.
* @param suffix is filled with the suffix
*/
void GetCargoSuffix(CargoSuffixInOut use_input, CargoSuffixType cst, const Industry *ind, IndustryType ind_type, const IndustrySpec *indspec, CargoID cargo, uint8_t slot, CargoSuffix &suffix)
{
suffix.text[0] = '\0';
suffix.display = CSD_CARGO;
if (!IsValidCargoID(cargo)) return;
if (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) {
byte local_id = indspec->grf_prop.grffile->cargo_map[cargo]; // should we check the value for valid?
uint cargotype = local_id << 16 | use_input;
GetCargoSuffix(cargotype, cst, ind, ind_type, indspec, suffix);
} else if (use_input == CARGOSUFFIX_IN) {
if (slot < 3) GetCargoSuffix(slot, cst, ind, ind_type, indspec, suffix);
} else if (use_input == CARGOSUFFIX_OUT) {
if (slot < 2) GetCargoSuffix(slot + 3, cst, ind, ind_type, indspec, suffix);
}
}
std::array<IndustryType, NUM_INDUSTRYTYPES> _sorted_industry_types; ///< Industry types sorted by name.
/** Sort industry types by their name. */
@@ -840,33 +867,35 @@ public:
ir.top += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
}
CargoSuffix cargo_suffix[lengthof(i->accepts_cargo)];
GetAllCargoSuffixes(CARGOSUFFIX_IN, CST_VIEW, i, i->type, ind, i->accepts_cargo, cargo_suffix);
bool stockpiling = HasBit(ind->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(ind->callback_mask, CBM_IND_PRODUCTION_256_TICKS);
for (byte j = 0; j < lengthof(i->accepts_cargo); j++) {
if (!IsValidCargoID(i->accepts_cargo[j])) continue;
for (const auto &a : i->accepted) {
if (!IsValidCargoID(a.cargo)) continue;
has_accept = true;
if (first) {
DrawString(ir, STR_INDUSTRY_VIEW_REQUIRES);
ir.top += FONT_HEIGHT_NORMAL;
first = false;
}
SetDParam(0, CargoSpec::Get(i->accepts_cargo[j])->name);
SetDParam(1, i->accepts_cargo[j]);
SetDParam(2, i->incoming_cargo_waiting[j]);
CargoSuffix suffix;
GetCargoSuffix(CARGOSUFFIX_IN, CST_VIEW, i, i->type, ind, a.cargo, &a - i->accepted.data(), suffix);
SetDParam(0, CargoSpec::Get(a.cargo)->name);
SetDParam(1, a.cargo);
SetDParam(2, a.waiting);
SetDParamStr(3, "");
StringID str = STR_NULL;
switch (cargo_suffix[j].display) {
switch (suffix.display) {
case CSD_CARGO_AMOUNT_TEXT:
SetDParamStr(3, cargo_suffix[j].text);
SetDParamStr(3, suffix.text);
FALLTHROUGH;
case CSD_CARGO_AMOUNT:
str = stockpiling ? STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT : STR_INDUSTRY_VIEW_ACCEPT_CARGO;
break;
case CSD_CARGO_TEXT:
SetDParamStr(3, cargo_suffix[j].text);
SetDParamStr(3, suffix.text);
FALLTHROUGH;
case CSD_CARGO:
str = STR_INDUSTRY_VIEW_ACCEPT_CARGO;
@@ -879,13 +908,12 @@ public:
ir.top += FONT_HEIGHT_NORMAL;
}
GetAllCargoSuffixes(CARGOSUFFIX_OUT, CST_VIEW, i, i->type, ind, i->produced_cargo, cargo_suffix);
int line_height = this->editable == EA_RATE ? this->cheat_line_height : FONT_HEIGHT_NORMAL;
int text_y_offset = (line_height - FONT_HEIGHT_NORMAL) / 2;
int button_y_offset = (line_height - SETTING_BUTTON_HEIGHT) / 2;
first = true;
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (!IsValidCargoID(i->produced_cargo[j])) continue;
for (const auto &p : i->produced) {
if (!IsValidCargoID(p.cargo)) continue;
if (first) {
if (has_accept) ir.top += WidgetDimensions::scaled.vsep_wide;
DrawString(ir, STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE);
@@ -894,15 +922,18 @@ public:
first = false;
}
SetDParam(0, i->produced_cargo[j]);
SetDParam(1, i->last_month_production[j]);
SetDParamStr(2, cargo_suffix[j].text);
SetDParam(3, ToPercent8(i->last_month_pct_transported[j]));
CargoSuffix suffix;
GetCargoSuffix(CARGOSUFFIX_OUT, CST_VIEW, i, i->type, ind, p.cargo, &p - i->produced.data(), suffix);
SetDParam(0, p.cargo);
SetDParam(1, p.history[LAST_MONTH].production);
SetDParamStr(2, suffix.text);
SetDParam(3, ToPercent8(p.history[LAST_MONTH].PctTransported()));
DrawString(ir.Indent(WidgetDimensions::scaled.hsep_indent + (this->editable == EA_RATE ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_normal : 0), rtl).Translate(0, text_y_offset), STR_INDUSTRY_VIEW_TRANSPORTED);
/* Let's put out those buttons.. */
if (this->editable == EA_RATE) {
DrawArrowButtons(ir.Indent(WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(SETTING_BUTTON_WIDTH, rtl).left, ir.top + button_y_offset, COLOUR_YELLOW, (this->clicked_line == IL_RATE1 + j) ? this->clicked_button : 0,
i->production_rate[j] > 0, i->production_rate[j] < 255);
DrawArrowButtons(ir.Indent(WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(SETTING_BUTTON_WIDTH, rtl).left, ir.top + button_y_offset, COLOUR_YELLOW, (this->clicked_line == IL_RATE1 + (&p - i->produced.data())) ? this->clicked_button : 0,
p.rate > 0, p.rate < 255);
}
ir.top += line_height;
}
@@ -980,11 +1011,11 @@ public:
case EA_RATE:
if (pt.y >= this->production_offset_y) {
int row = (pt.y - this->production_offset_y) / this->cheat_line_height;
for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
if (!IsValidCargoID(i->produced_cargo[j])) continue;
for (auto itp = std::begin(i->produced); itp != std::end(i->produced); ++itp) {
if (!IsValidCargoID(itp->cargo)) continue;
row--;
if (row < 0) {
line = (InfoLine)(IL_RATE1 + j);
line = (InfoLine)(IL_RATE1 + (itp - std::begin(i->produced)));
break;
}
}
@@ -1012,13 +1043,13 @@ public:
case EA_RATE:
if (decrease) {
if (i->production_rate[line - IL_RATE1] <= 0) return;
i->production_rate[line - IL_RATE1] = std::max(i->production_rate[line - IL_RATE1] / 2, 0);
if (i->produced[line - IL_RATE1].rate <= 0) return;
i->produced[line - IL_RATE1].rate = std::max(i->produced[line - IL_RATE1].rate / 2, 0);
} else {
if (i->production_rate[line - IL_RATE1] >= 255) return;
if (i->produced[line - IL_RATE1].rate >= 255) return;
/* a zero production industry is unlikely to give anything but zero, so push it a little bit */
int new_prod = i->production_rate[line - IL_RATE1] == 0 ? 1 : i->production_rate[line - IL_RATE1] * 2;
i->production_rate[line - IL_RATE1] = ClampTo<byte>(new_prod);
int new_prod = i->produced[line - IL_RATE1].rate == 0 ? 1 : i->produced[line - IL_RATE1].rate * 2;
i->produced[line - IL_RATE1].rate = ClampTo<byte>(new_prod);
}
break;
@@ -1040,7 +1071,7 @@ public:
break;
case EA_RATE:
SetDParam(0, i->production_rate[line - IL_RATE1] * 8);
SetDParam(0, i->produced[line - IL_RATE1].rate * 8);
ShowQueryString(STR_JUST_INT, STR_CONFIG_GAME_PRODUCTION, 10, this, CS_ALPHANUMERAL, QSF_NONE);
break;
@@ -1099,7 +1130,7 @@ public:
break;
default:
i->production_rate[this->editbox_line - IL_RATE1] = ClampU(RoundDivSU(value, 8), 0, 255);
i->produced[this->editbox_line - IL_RATE1].rate = ClampU(RoundDivSU(value, 8), 0, 255);
break;
}
UpdateIndustryProduction(i);
@@ -1139,9 +1170,9 @@ static void UpdateIndustryProduction(Industry *i)
const IndustrySpec *indspec = GetIndustrySpec(i->type);
if (indspec->UsesOriginalEconomy()) i->RecomputeProductionMultipliers();
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (IsValidCargoID(i->produced_cargo[j])) {
i->last_month_production[j] = 8 * i->production_rate[j];
for (auto &p : i->produced) {
if (IsValidCargoID(p.cargo)) {
p.history[LAST_MONTH].production = 8 * p.rate;
}
}
}
@@ -1415,12 +1446,10 @@ protected:
* @param id cargo slot
* @return percents of cargo transported, or -1 if industry doesn't use this cargo slot
*/
static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id)
static inline int GetCargoTransportedPercentsIfValid(const Industry::ProducedCargo &p)
{
assert(id < lengthof(i->produced_cargo));
if (!IsValidCargoID(i->produced_cargo[id])) return -1;
return ToPercent8(i->last_month_pct_transported[id]);
if (!IsValidCargoID(p.cargo)) return -1;
return ToPercent8(p.history[LAST_MONTH].PctTransported());
}
/**
@@ -1436,18 +1465,18 @@ protected:
if (filter == CF_NONE) return 0;
int percentage = 0, produced_cargo_count = 0;
for (uint id = 0; id < lengthof(i->produced_cargo); id++) {
for (const auto &p : i->produced) {
if (filter == CF_ANY) {
int transported = GetCargoTransportedPercentsIfValid(i, id);
int transported = GetCargoTransportedPercentsIfValid(p);
if (transported != -1) {
produced_cargo_count++;
percentage += transported;
}
if (produced_cargo_count == 0 && id == lengthof(i->produced_cargo) - 1 && percentage == 0) {
if (produced_cargo_count == 0 && &p == &i->produced.back() && percentage == 0) {
return transported;
}
} else if (filter == i->produced_cargo[id]) {
return GetCargoTransportedPercentsIfValid(i, id);
} else if (filter == p.cargo) {
return GetCargoTransportedPercentsIfValid(p);
}
}
@@ -1481,13 +1510,13 @@ protected:
if (filter == CF_NONE) return IndustryTypeSorter(a, b);
uint prod_a = 0, prod_b = 0;
for (uint i = 0; i < lengthof(a->produced_cargo); i++) {
for (auto ita = std::begin(a->produced), itb = std::begin(b->produced); ita != std::end(a->produced) && itb != std::end(b->produced); ++ita, ++itb) {
if (filter == CF_ANY) {
if (IsValidCargoID(a->produced_cargo[i])) prod_a += a->last_month_production[i];
if (IsValidCargoID(b->produced_cargo[i])) prod_b += b->last_month_production[i];
if (IsValidCargoID(ita->cargo)) prod_a += ita->history[LAST_MONTH].production;
if (IsValidCargoID(itb->cargo)) prod_b += ita->history[LAST_MONTH].production;
} else {
if (a->produced_cargo[i] == filter) prod_a += a->last_month_production[i];
if (b->produced_cargo[i] == filter) prod_b += b->last_month_production[i];
if (ita->cargo == filter) prod_a += ita->history[LAST_MONTH].production;
if (itb->cargo == filter) prod_b += itb->history[LAST_MONTH].production;
}
}
int r = prod_a - prod_b;
@@ -1515,8 +1544,7 @@ protected:
/* Industry name */
SetDParam(p++, i->index);
static CargoSuffix cargo_suffix[lengthof(i->produced_cargo)];
GetAllCargoSuffixes(CARGOSUFFIX_OUT, CST_DIR, i, i->type, indsp, i->produced_cargo, cargo_suffix);
static CargoSuffix cargo_suffix[INDUSTRY_NUM_OUTPUTS];
/* Get industry productions (CargoID, production, suffix, transported) */
struct CargoInfo {
@@ -1527,9 +1555,10 @@ protected:
};
std::vector<CargoInfo> cargos;
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (!IsValidCargoID(i->produced_cargo[j])) continue;
cargos.push_back({ i->produced_cargo[j], i->last_month_production[j], cargo_suffix[j].text.c_str(), ToPercent8(i->last_month_pct_transported[j]) });
for (auto itp = std::begin(i->produced); itp != std::end(i->produced); ++itp) {
if (!IsValidCargoID(itp->cargo)) continue;
GetCargoSuffix(CARGOSUFFIX_OUT, CST_DIR, i, i->type, indsp, itp->cargo, itp - std::begin(i->produced), cargo_suffix[itp - std::begin(i->produced)]);
cargos.push_back({ itp->cargo, itp->history[LAST_MONTH].production, cargo_suffix[itp - std::begin(i->produced)].text.c_str(), ToPercent8(itp->history[LAST_MONTH].PctTransported()) });
}
switch (static_cast<IndustryDirectoryWindow::SorterType>(this->industries.SortType())) {