diff --git a/src/cargotype.cpp b/src/cargotype.cpp index fc53f3de48..3b5bad3205 100644 --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -46,14 +46,14 @@ static std::vector _default_cargo_labels; * This maps the original 12 cargo slots to their original label. If a climate dependent cargo is not present it will * map to CT_INVALID. For default cargoes this ends up as a 1:1 mapping via climate slot -> label -> cargo ID. */ -static std::array _v7_cargo_labels; +static std::array _climate_dependent_cargo_labels; /** * Default cargo translation for version 8+ NewGRFs. * This maps the 32 "bitnum" cargo slots to their original label. If a bitnum is not present it will * map to CT_INVALID. */ -static std::array _v8_cargo_labels; +static std::array _climate_independent_cargo_labels; /** * Set up the default cargo types for the given landscape type. @@ -65,8 +65,8 @@ void SetupCargoForClimate(LandscapeID l) _cargo_mask = 0; _default_cargo_labels.clear(); - _v7_cargo_labels.fill(CT_INVALID); - _v8_cargo_labels.fill(CT_INVALID); + _climate_dependent_cargo_labels.fill(CT_INVALID); + _climate_independent_cargo_labels.fill(CT_INVALID); /* Copy from default cargo by label or index. */ auto insert = std::begin(CargoSpec::array); @@ -94,8 +94,8 @@ void SetupCargoForClimate(LandscapeID l) if (insert->IsValid()) { SetBit(_cargo_mask, insert->Index()); _default_cargo_labels.push_back(insert->label); - _v7_cargo_labels[insert->Index()] = insert->label; - _v8_cargo_labels[insert->bitnum] = insert->label; + _climate_dependent_cargo_labels[insert->Index()] = insert->label; + _climate_independent_cargo_labels[insert->bitnum] = insert->label; } ++insert; } @@ -107,14 +107,21 @@ void SetupCargoForClimate(LandscapeID l) } /** - * Get default cargo translation table for a NewGRF, used if the NewGRF does not provide its own. - * @param grf_version GRF version of translation table. + * Get default climate-dependent cargo translation table for a NewGRF, used if the NewGRF does not provide its own. * @return Default translation table for GRF version. */ -std::span GetDefaultCargoTranslationTable(uint8_t grf_version) +std::span GetClimateDependentCargoTranslationTable() { - if (grf_version < 8) return _v7_cargo_labels; - return _v8_cargo_labels; + return _climate_dependent_cargo_labels; +} + +/** + * Get default climate-independent cargo translation table for a NewGRF, used if the NewGRF does not provide its own. + * @return Default translation table for GRF version. + */ +std::span GetClimateIndependentCargoTranslationTable() +{ + return _climate_independent_cargo_labels; } /** diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 5c18141d97..8dd9044c1d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5562,20 +5562,39 @@ static void NewSpriteGroup(ByteReader &buf) _cur.spritegroups[setid] = act_group; } +/** + * Get the cargo translation table to use for the given GRF file. + * @param grffile GRF file. + * @returns Readonly cargo translation table to use. + */ +std::span GetCargoTranslationTable(const GRFFile &grffile) +{ + /* Always use the translation table if it's installed. */ + if (!grffile.cargo_list.empty()) return grffile.cargo_list; + + /* Pre-v7 use climate-dependent "slot" table. */ + if (grffile.grf_version < 7) return GetClimateDependentCargoTranslationTable(); + + /* Otherwise use climate-independent "bitnum" table. */ + return GetClimateIndependentCargoTranslationTable(); +} + static CargoID TranslateCargo(uint8_t feature, uint8_t ctype) { /* Special cargo types for purchase list and stations */ if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return SpriteGroupCargo::SG_DEFAULT_NA; if (ctype == 0xFF) return SpriteGroupCargo::SG_PURCHASE; + auto cargo_list = GetCargoTranslationTable(*_cur.grffile); + /* Check if the cargo type is out of bounds of the cargo translation table */ - if (ctype >= _cur.grffile->cargo_list.size()) { + if (ctype >= cargo_list.size()) { GrfMsg(1, "TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (unsigned int)_cur.grffile->cargo_list.size() - 1); return INVALID_CARGO; } /* Look up the cargo label from the translation table */ - CargoLabel cl = _cur.grffile->cargo_list[ctype]; + CargoLabel cl = cargo_list[ctype]; if (cl == CT_INVALID) { GrfMsg(5, "TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype); return INVALID_CARGO; @@ -7059,13 +7078,6 @@ static void GRFInfo(ByteReader &buf) _cur.grffile->grf_version = version; _cur.grfconfig->status = _cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED; - /* Install the default cargo translation table. */ - if (_cur.stage < GLS_RESERVE && _cur.grffile->cargo_list.empty()) { - auto default_table = GetDefaultCargoTranslationTable(version); - _cur.grffile->cargo_list.assign(default_table.begin(), default_table.end()); - GrfMsg(3, "GRFInfo: Installing default GRFv{} translation table for {:08X}", version, BSWAP32(grfid)); - } - /* Do swap the GRFID for displaying purposes since people expect that */ Debug(grf, 1, "GRFInfo: Loaded GRFv{} set {:08X} - {} (palette: {}, version: {})", version, BSWAP32(grfid), StrMakeValid(name), (_cur.grfconfig->palette & GRFP_USE_MASK) ? "Windows" : "DOS", _cur.grfconfig->version); } @@ -8905,11 +8917,13 @@ static void BuildCargoTranslationMap() { _cur.grffile->cargo_map.fill(UINT8_MAX); + auto cargo_list = GetCargoTranslationTable(*_cur.grffile); + for (const CargoSpec *cs : CargoSpec::Iterate()) { if (!cs->IsValid()) continue; /* Check the translation table for this cargo's label */ - int idx = find_index(_cur.grffile->cargo_list, {cs->label}); + int idx = find_index(cargo_list, cs->label); if (idx >= 0) _cur.grffile->cargo_map[cs->Index()] = idx; } } diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp index 8c75c84835..7b6aba7475 100644 --- a/src/newgrf_cargo.cpp +++ b/src/newgrf_cargo.cpp @@ -79,14 +79,17 @@ uint16_t GetCargoCallback(CallbackID callback, uint32_t param1, uint32_t param2, */ CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit) { + /* We can't use GetCargoTranslationTable here as the usebit flag changes behviour. */ /* Pre-version 7 uses the bitnum lookup from (standard in v8) instead of climate dependent in some places.. */ - if (grffile->grf_version < 7 && usebit) { - auto default_table = GetDefaultCargoTranslationTable(8); - if (cargo < default_table.size()) return GetCargoIDByLabel(default_table[cargo]); - return INVALID_CARGO; + std::span cargo_list; + if (grffile->grf_version < 7 && !usebit) { + cargo_list = GetClimateDependentCargoTranslationTable(); + } else if (!grffile->cargo_list.empty()) { + cargo_list = grffile->cargo_list; + } else { + cargo_list = GetClimateIndependentCargoTranslationTable(); } - /* Look in translation table. */ - if (cargo < grffile->cargo_list.size()) return GetCargoIDByLabel(grffile->cargo_list[cargo]); + if (cargo < cargo_list.size()) return GetCargoIDByLabel(cargo_list[cargo]); return INVALID_CARGO; } diff --git a/src/newgrf_cargo.h b/src/newgrf_cargo.h index b590a5d98e..e77401a26b 100644 --- a/src/newgrf_cargo.h +++ b/src/newgrf_cargo.h @@ -33,6 +33,7 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs); uint16_t GetCargoCallback(CallbackID callback, uint32_t param1, uint32_t param2, const CargoSpec *cs); CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit = false); -std::span GetDefaultCargoTranslationTable(uint8_t grf_version); +std::span GetClimateDependentCargoTranslationTable(); +std::span GetClimateIndependentCargoTranslationTable(); #endif /* NEWGRF_CARGO_H */