Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter items by can_contain L:, V:, M: (longest_side, volume, mass); affects AIM, inventory… #78519

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading