1
0
mirror of https://github.com/OpenTTD/OpenTTD synced 2026-01-27 06:04:25 +01:00

Fix #15116: install fallback cargo translation table for old cargo sets (#15150)

Old combined cargo/industry sets may set up cargo types with labels and expect them to be usable without a translation table.

Install a fallback table if the NewGRF does not install one to give them a better chance of working.
This commit is contained in:
Peter Nelson
2026-01-24 14:42:58 +00:00
committed by GitHub
parent 1716d36ebb
commit a8d0241c0b
4 changed files with 30 additions and 1 deletions

View File

@@ -154,6 +154,7 @@ struct GRFFile {
int traininfo_vehicle_pitch = 0; ///< Vertical offset for drawing train images in depot GUI and vehicle details
uint traininfo_vehicle_width = 0; ///< Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details
bool cargo_list_is_fallback = false; ///< Set if cargo types have been created but a cargo list has not been installed
GrfSpecFeatures grf_features{}; ///< Bitset of GrfSpecFeature the grf uses
PriceMultipliers price_base_multipliers{}; ///< Price base multipliers as set by the grf.

View File

@@ -16,6 +16,29 @@
#include "../safeguards.h"
/**
* Install cargo label in a fallback cargo list, if a NewGRF-defined cargo list is not present.
* This allows this NewGRF to use its self-defined cargo types without needing an explicit translation table.
* @param id ID of the cargo.
* @param last ID of the last cargo being set up.
* @param label Label to install.
*/
static void MaybeInstallFallbackCargoLabel(uint id, uint last, CargoLabel label)
{
if (_cur_gps.grffile->cargo_list.empty()) {
/* Cargo translation table isn't configured yet, assume it won't be and configure the cargo list as a fallback list. */
auto default_cargo_list = GetCargoTranslationTable(*_cur_gps.grffile);
_cur_gps.grffile->cargo_list.assign(default_cargo_list.begin(), default_cargo_list.end());
_cur_gps.grffile->cargo_list_is_fallback = true;
}
if (_cur_gps.grffile->cargo_list_is_fallback) {
/* Automatically fill fallback cargo list with the defined label, resizing as needed. */
if (_cur_gps.grffile->cargo_list.size() < last) _cur_gps.grffile->cargo_list.resize(last, CT_INVALID);
_cur_gps.grffile->cargo_list[id] = label;
}
}
/**
* Define properties for cargoes
* @param first ID of the first cargo.
@@ -115,6 +138,7 @@ static ChangeInfoResult CargoReserveInfo(uint first, uint last, int prop, ByteRe
case 0x17: // Cargo label
cs->label = CargoLabel{std::byteswap(buf.ReadDWord())};
BuildCargoLabelMap();
MaybeInstallFallbackCargoLabel(id, last, cs->label);
break;
case 0x18: { // Town growth substitute type

View File

@@ -110,6 +110,8 @@ static ChangeInfoResult GlobalVarChangeInfo(uint first, uint last, int prop, Byt
/* Properties which are handled as a whole */
switch (prop) {
case 0x09: // Cargo Translation Table; loading during both reservation and activation stage (in case it is selected depending on defined cargos)
/* Explicitly defined cargo translation table means it's no longer a fallback list. LoadTranslationTable erases any existing list. */
_cur_gps.grffile->cargo_list_is_fallback = false;
return LoadTranslationTable<CargoLabel>(first, last, buf, [](GRFFile &grf) -> std::vector<CargoLabel> & { return grf.cargo_list; }, "Cargo");
case 0x12: // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
@@ -336,6 +338,8 @@ static ChangeInfoResult GlobalVarReserveInfo(uint first, uint last, int prop, By
/* Properties which are handled as a whole */
switch (prop) {
case 0x09: // Cargo Translation Table; loading during both reservation and activation stage (in case it is selected depending on defined cargos)
/* Explicitly defined cargo translation table means it's no longer a fallback list. LoadTranslationTable erases any existing list. */
_cur_gps.grffile->cargo_list_is_fallback = false;
return LoadTranslationTable<CargoLabel>(first, last, buf, [](GRFFile &grf) -> std::vector<CargoLabel> & { return grf.cargo_list; }, "Cargo");
case 0x12: // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)

View File

@@ -82,7 +82,7 @@ CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit
/* We can't use GetCargoTranslationTable here as the usebit flag changes behaviour. */
/* Pre-version 7 uses the bitnum lookup from (standard in v8) instead of climate dependent in some places.. */
std::span<const CargoLabel> cargo_list;
if (grffile->grf_version < 7 && !usebit) {
if (grffile->grf_version < 7 && !usebit && !grffile->cargo_list_is_fallback) {
cargo_list = GetClimateDependentCargoTranslationTable();
} else if (!grffile->cargo_list.empty()) {
cargo_list = grffile->cargo_list;