Skip to content

Commit

Permalink
Merge pull request #78519 from Brambor/inventory-filters-lvm
Browse files Browse the repository at this point in the history
Filter items by can_contain `L:`, `V:`, `M:` (longest_side, volume, mass); affects AIM, inventory…
  • Loading branch information
Night-Pryanik authored Dec 13, 2024
2 parents 4565e01 + 6ca0bee commit 1205496
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/item_search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string, std::string> get_both( std::string_view a );

template<typename Unit>
static std::function< bool( const item & )> can_contain_filter( std::string_view hint,
std::string_view filter, Unit max, std::vector<std::pair<std::string, Unit>> units,
std::function<item( itype *, Unit u )> set_function )
{
auto const error = [hint, filter]( char const *, 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<Unit>( 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<itype> filtered_fake_itype = std::make_shared<itype>( *( 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<bool( const item & )> basic_item_filter( std::string filter )
{
size_t colon;
Expand Down Expand Up @@ -87,6 +118,32 @@ std::function<bool( const item & )> basic_item_filter( std::string filter )
}
return false;
};
// by can contain length
case 'L': {
return can_contain_filter<units::length>( "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<units::volume>( "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<units::mass>( "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<bodypart_id> filtered_bodyparts;
Expand Down
3 changes: 3 additions & 0 deletions src/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,9 @@ static const std::vector<ItemFilterPrefix> item_filter_prefixes = {
{ 'f', to_translation( "freezerburn" ), to_translation( "<color_cyan>hidden flags</color> of an item" ) },
{ 's', to_translation( "devices" ), to_translation( "<color_cyan>skill</color> taught by books" ) },
{ 'd', to_translation( "pipe" ), to_translation( "<color_cyan>disassembled</color> components" ) },
{ 'L', to_translation( "122 cm" ), to_translation( "can contain item of <color_cyan>length</color>" ) },
{ 'V', to_translation( "450 ml" ), to_translation( "can contain item of <color_cyan>volume</color>" ) },
{ 'M', to_translation( "250 kg" ), to_translation( "can contain item of <color_cyan>mass</color>" ) },
{ 'v', to_translation( "hand" ), to_translation( "covers <color_cyan>body part</color>" ) },
{ 'e', to_translation( "close to skin" ), to_translation( "covers <color_cyan>layer</color>" ) },
{ 'b', to_translation( "mre;sealed" ), to_translation( "items satisfying <color_cyan>both</color> conditions" ) }
Expand Down

0 comments on commit 1205496

Please sign in to comment.