From c0f5ad95fe92c867f497836121b6265a17d6fccb Mon Sep 17 00:00:00 2001 From: andrei Date: Fri, 15 Nov 2024 16:29:36 +0200 Subject: [PATCH] item: let translators reorder tname segments --- src/item.cpp | 3 +- src/item_tname.cpp | 138 +++++++++++++++++++++++++++++++++++++++++++++ src/item_tname.h | 3 + 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/src/item.cpp b/src/item.cpp index 9b791a9a7e605..9ffb8b93ebe8e 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -6859,8 +6859,7 @@ std::string item::tname( unsigned int quantity, tname::segment_bitset const &seg { std::string ret; - for( size_t i = 0; i < static_cast( tname::segments::last_segment ); i++ ) { - tname::segments const idx = static_cast( i ); + for( tname::segments idx : tname::get_tname_set() ) { if( !segments[idx] ) { continue; } diff --git a/src/item_tname.cpp b/src/item_tname.cpp index 5b4692fba670a..749601c51276e 100644 --- a/src/item_tname.cpp +++ b/src/item_tname.cpp @@ -609,6 +609,98 @@ static_assert( all_segments_have_printers(), "every element of tname::segments (up to tname::segments::last_segment) " "must map to a printer in segs_array" ); + +namespace io +{ +template<> +std::string enum_to_string( tname::segments seg ) +{ + switch( seg ) { + // *INDENT-OFF* + case tname::segments::FAULTS: return "FAULTS"; + case tname::segments::DIRT: return "DIRT"; + case tname::segments::OVERHEAT: return "OVERHEAT"; + case tname::segments::FAVORITE_PRE: return "FAVORITE_PRE"; + case tname::segments::DURABILITY: return "DURABILITY"; + case tname::segments::WHEEL_DIAMETER: return "WHEEL_DIAMETER"; + case tname::segments::BURN: return "BURN"; + case tname::segments::WEAPON_MODS: return "WEAPON_MODS"; + case tname::segments::CUSTOM_ITEM_PREFIX: return "CUSTOM_ITEM_PREFIX"; + case tname::segments::TYPE: return "TYPE"; + case tname::segments::CATEGORY: return "CATEGORY"; + case tname::segments::CUSTOM_ITEM_SUFFIX: return "CUSTOM_ITEM_SUFFIX"; + case tname::segments::MODS: return "MODS"; + case tname::segments::CRAFT: return "CRAFT"; + case tname::segments::WHITEBLACKLIST: return "WHITEBLACKLIST"; + case tname::segments::CHARGES: return "CHARGES"; + case tname::segments::FOOD_TRAITS: return "FOOD_TRAITS"; + case tname::segments::FOOD_STATUS: return "FOOD_STATUS"; + case tname::segments::FOOD_IRRADIATED: return "FOOD_IRRADIATED"; + case tname::segments::TEMPERATURE: return "TEMPERATURE"; + case tname::segments::LOCATION_HINT: return "LOCATION_HINT"; + case tname::segments::CLOTHING_SIZE: return "CLOTHING_SIZE"; + case tname::segments::ETHEREAL: return "ETHEREAL"; + case tname::segments::FILTHY: return "FILTHY"; + case tname::segments::BROKEN: return "BROKEN"; + case tname::segments::CBM_STATUS: return "CBM_STATUS"; + case tname::segments::UPS: return "UPS"; + case tname::segments::TAGS: return "TAGS"; + case tname::segments::VARS: return "VARS"; + case tname::segments::WETNESS: return "WETNESS"; + case tname::segments::ACTIVE: return "ACTIVE"; + case tname::segments::SEALED: return "SEALED"; + case tname::segments::FAVORITE_POST: return "FAVORITE_POST"; + case tname::segments::RELIC: return "RELIC"; + case tname::segments::LINK: return "LINK"; + case tname::segments::TECHNIQUES: return "TECHNIQUES"; + case tname::segments::CONTENTS: return "CONTENTS"; + case tname::segments::last_segment: return "last_segment"; + case tname::segments::VARIANT: return "VARIANT"; + case tname::segments::COMPONENTS: return "COMPONENTS"; + case tname::segments::CORPSE: return "CORPSE"; + case tname::segments::CONTENTS_FULL: return "CONTENTS_FULL"; + case tname::segments::CONTENTS_ABREV: return "CONTENTS_ABBREV"; + case tname::segments::CONTENTS_COUNT: return "CONTENTS_COUNT"; + case tname::segments::FOOD_PERISHABLE: return "FOOD_PERISHABLE"; + case tname::segments::last: return "last"; + default: + // *INDENT-ON* + break; + } + return {}; +} + +} // namespace io + +namespace +{ + +constexpr tname::segments fixed_pos_segments = tname::segments::CONTENTS; +static_assert( fixed_pos_segments <= tname::segments::last_segment ); + +using tname_array = std::array( fixed_pos_segments )>; +struct segment_order { + constexpr explicit segment_order( tname_array const &arr_ ) : arr( &arr_ ) {}; + constexpr bool operator()( tname::segments lhs, tname::segments rhs ) const { + return arr->at( static_cast( lhs ) ) < + arr->at( static_cast( rhs ) ); + } + + tname_array const *arr; +}; + +std::optional str_to_segment_idx( std::string const &str ) +{ + if( std::optional ret = io::string_to_enum_optional( str ); + ret && ret < fixed_pos_segments ) { + + return static_cast( *ret ); + } + + return {}; +} + +} // namespace namespace tname { std::string print_segment( tname::segments segment, item const &it, unsigned int quantity, @@ -618,4 +710,50 @@ std::string print_segment( tname::segments segment, item const &it, unsigned int size_t const idx = static_cast( segment ); return ( *arr.at( idx ) )( it, quantity, segments ); } + +tname_set const &get_tname_set() +{ + static tname_set tns; + static int lang_ver = INVALID_LANGUAGE_VERSION; + if( int const cur_lang_ver = detail::get_current_language_version(); lang_ver != cur_lang_ver ) { + lang_ver = cur_lang_ver; + tns.clear(); + for( size_t i = 0; i < static_cast( fixed_pos_segments ); i++ ) { + tns.emplace_back( static_cast( i ) ); + } + + tname_array tna; + tna.fill( 999 ); + //~ use this string to define the order for item name segments. The default order is: + //~ FAULTS DIRT OVERHEAT FAVORITE_PRE DURABILITY WHEEL_DIAMETER WEAPON_MODS + //~ CUSTOM_ITEM_PREFIX TYPE BURN CATEGORY CUSTOM_ITEM_SUFFIX MODS CRAFT WHITEBLACKLIST CHARGES + //~ FOOD_TRAITS FOOD_STATUS FOOD_IRRADIATED TEMPERATURE LOCATION_HINT CLOTHING_SIZE ETHEREAL + //~ FILTHY BROKEN CBM_STATUS UPS TAGS VARS WETNESS ACTIVE SEALED FAVORITE_POST RELIC LINK + //~ TECHNIQUES + //~ -- + //~ refer to io::enum_to_string for updated list + std::string order_i18n( _( "tname_segments_order" ) ); + std::stringstream ss( order_i18n ); + std::istream_iterator begin( ss ); + std::istream_iterator end; + std::vector tokens( begin, end ); + + int cur_order = 0; + for( auto &s : tokens ) { + if( auto idx = str_to_segment_idx( s ); idx ) { + tna[*idx] = cur_order++; + } else { + DebugLog( D_WARNING, D_MAIN ) << "Ignoring tname segment " << std::quoted( s ) << std::endl; + } + } + + std::stable_sort( tns.begin(), tns.end(), segment_order( tna ) ); + for( size_t i = static_cast( fixed_pos_segments ); + i < static_cast( tname::segments::last_segment ); i++ ) { + tns.emplace_back( static_cast( i ) ); + } + } + + return tns; +} } // namespace tname diff --git a/src/item_tname.h b/src/item_tname.h index 9d59f8247a38c..cdee759dfe120 100644 --- a/src/item_tname.h +++ b/src/item_tname.h @@ -79,6 +79,9 @@ using segment_bitset = enum_bitset; std::string print_segment( tname::segments segment, item const &it, unsigned int quantity, segment_bitset const &segments ); +using tname_set = std::vector; +tname_set const &get_tname_set(); + #endif // CATA_IN_TOOL } // namespace tname