From 2e1d8d1166cee1a055f85669fa44d4bd514acea0 Mon Sep 17 00:00:00 2001 From: Brambor Date: Wed, 11 Dec 2024 21:14:29 +0100 Subject: [PATCH] Filter items by can_contain L, V, M (longest_side, volume, mass) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - affects AIM, inventory… --- src/item_search.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++ src/output.cpp | 3 +++ 2 files changed, 60 insertions(+) diff --git a/src/item_search.cpp b/src/item_search.cpp index 9c65bbfc26a5c..d4e3d6b31ee37 100644 --- a/src/item_search.cpp +++ b/src/item_search.cpp @@ -5,15 +5,46 @@ #include "avatar.h" #include "cata_utility.h" +#include "flag.h" #include "item.h" #include "item_category.h" +#include "item_factory.h" #include "itype.h" +#include "make_static.h" #include "material.h" #include "requirements.h" #include "type_id.h" static std::pair get_both( std::string_view a ); +template +static std::function< bool( const item & )> can_contain_filter( std::string_view hint, + std::string_view filter, Unit max, std::vector> units, + std::function set_function ) +{ + auto const error = [hint, filter]( char const * /* suffix */, size_t /* offset */ ) { + throw math::runtime_error( _( string_format( hint, filter ) ) ); + }; + // Start at max. On convert failure: results are empty and user knows it is unusable. + Unit uni = max; + try { + uni = detail::read_from_json_string_common( filter, units, error ); + } catch( math::runtime_error &err ) { + // TODO notify the user: popup( err.what() ); + } + // copy the debug item template (itype), put it on heap so the itype pointer doesn't move + // TODO unique_ptr + std::shared_ptr filtered_fake_itype = std::make_shared( *( item_controller->find( []( + const itype & i ) { + return i.get_id() == STATIC( itype_id( "debug_item_search" ) ); + } )[0] ) ); + item filtered_fake_item = set_function( filtered_fake_itype.get(), uni ); + // pass to keep filtered_fake_itype valid until lambda capture is destroyed (while item is needed) + return [filtered_fake_itype, filtered_fake_item]( const item & i ) { + return i.can_contain( filtered_fake_item ).success(); + }; +} + std::function basic_item_filter( std::string filter ) { size_t colon; @@ -87,6 +118,32 @@ std::function basic_item_filter( std::string filter ) } return false; }; + // by can contain length + case 'L': { + return can_contain_filter( "Failed to convert '%s' to length.\nValid examples:\n122 cm\n1101mm\n2 meter", + filter, units::length_max, units::length_units, []( itype * typ, units::length len ) { + typ->longest_side = len; + item itm( typ ); + itm.set_flag( flag_HARD ); + return itm; + } ); + } + // by can contain volume + case 'V': { + return can_contain_filter( "Failed to convert '%s' to volume.\nValid examples:\n750 ml\n4L", + filter, units::volume_max, units::volume_units, []( itype * typ, units::volume vol ) { + typ->volume = vol; + return item( typ ); + } ); + } + // by can contain mass + case 'M': { + return can_contain_filter( "Failed to convert '%s' to mass.\nValid examples:\n12 mg\n400g\n25 kg", + filter, units::mass_max, units::mass_units, []( itype * typ, units::mass mas ) { + typ->weight = mas; + return item( typ ); + } ); + } // covers bodypart case 'v': { std::unordered_set filtered_bodyparts; diff --git a/src/output.cpp b/src/output.cpp index ab62899d31507..fed3ddc345241 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -1081,6 +1081,9 @@ static const std::vector item_filter_prefixes = { { 'f', to_translation( "freezerburn" ), to_translation( "hidden flags of an item" ) }, { 's', to_translation( "devices" ), to_translation( "skill taught by books" ) }, { 'd', to_translation( "pipe" ), to_translation( "disassembled components" ) }, + { 'L', to_translation( "122 cm" ), to_translation( "can contain item of length" ) }, + { 'V', to_translation( "450 ml" ), to_translation( "can contain item of volume" ) }, + { 'M', to_translation( "250 kg" ), to_translation( "can contain item of mass" ) }, { 'v', to_translation( "hand" ), to_translation( "covers body part" ) }, { 'e', to_translation( "close to skin" ), to_translation( "covers layer" ) }, { 'b', to_translation( "mre;sealed" ), to_translation( "items satisfying both conditions" ) }