Skip to content

Commit

Permalink
Merge pull request CleverRaven#70475 from Kamayana/handle_invalid_mod…
Browse files Browse the repository at this point in the history
…_pocket_contents

Handle invalid mod pocket contents
  • Loading branch information
Maleclypse authored Dec 28, 2023
2 parents 2f88ea5 + 6163aa6 commit faa3c3b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 19 deletions.
24 changes: 23 additions & 1 deletion src/item_contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,12 @@ void item_contents::read_mods( const item_contents &read_input )
for( const item_pocket &pocket : read_input.contents ) {
if( pocket.saved_type() == pocket_type::MOD ) {
for( const item *it : pocket.all_items_top() ) {
insert_item( *it, pocket_type::MOD );
if( it->is_gunmod() || it->is_toolmod() ) {
insert_item( *it, pocket_type::MOD );
} else {
debugmsg( "Non-mod %s in MOD pocket!", it->tname() );
insert_item( *it, pocket_type::MIGRATION );
}
}
}
}
Expand All @@ -655,6 +660,7 @@ void item_contents::read_mods( const item_contents &read_input )
void item_contents::combine( const item_contents &read_input, const bool convert,
const bool into_bottom, bool restack_charges, bool ignore_contents )
{
std::list<item_pocket> mismatched_pockets;
std::vector<item> uninserted_items;
size_t pocket_index = 0;

Expand Down Expand Up @@ -697,6 +703,11 @@ void item_contents::combine( const item_contents &read_input, const bool convert
auto current_pocket_iter = contents.begin();
std::advance( current_pocket_iter, pocket_index );

if( !current_pocket_iter->is_type( pocket.saved_type() ) ) {
mismatched_pockets.push_back( pocket );
continue;
}

for( const item *it : pocket.all_items_top() ) {
const ret_val<item *> inserted = current_pocket_iter->insert_item( *it,
into_bottom, restack_charges, ignore_contents );
Expand All @@ -719,6 +730,17 @@ void item_contents::combine( const item_contents &read_input, const bool convert
++pocket_index;
}

for( const item_pocket &pocket : mismatched_pockets ) {
for( const item *it : pocket.all_items_top() ) {
const ret_val<item *> inserted = insert_item( *it, pocket.saved_type(), ignore_contents );
if( !inserted.success() ) {
uninserted_items.push_back( *it );
debugmsg( "error: item %s cannot fit into any pocket while loading: %s",
it->typeId().str(), inserted.str() );
}
}
}

for( const item &uninserted_item : uninserted_items ) {
insert_item( uninserted_item, pocket_type::MIGRATION, ignore_contents );
}
Expand Down
47 changes: 29 additions & 18 deletions src/item_pocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1331,9 +1331,18 @@ static int charges_per_volume_recursive( const units::volume &max_item_volume,

ret_val<item_pocket::contain_code> item_pocket::is_compatible( const item &it ) const
{
if( it.has_flag( flag_NO_UNWIELD ) ) {
return ret_val<item_pocket::contain_code>::make_failure(
contain_code::ERR_MOD, _( "cannot unwield item" ) );
if( data->type == pocket_type::MIGRATION ) {
// migration pockets need to always succeed
return ret_val<item_pocket::contain_code>::make_success();
}

if( data->type == pocket_type::MOD ) {
if( it.is_toolmod() || it.is_gunmod() ) {
return ret_val<item_pocket::contain_code>::make_success();
} else {
return ret_val<item_pocket::contain_code>::make_failure(
contain_code::ERR_MOD, _( "only mods can go into mod pocket" ) );
}
}

if( data->type == pocket_type::CORPSE ) {
Expand All @@ -1342,6 +1351,15 @@ ret_val<item_pocket::contain_code> item_pocket::is_compatible( const item &it )
return ret_val<item_pocket::contain_code>::make_success();
}

if( data->type == pocket_type::SOFTWARE ) {
if( it.has_flag( flag_NO_DROP ) && it.has_flag( flag_IRREMOVABLE ) ) {
return ret_val<item_pocket::contain_code>::make_success();
} else {
return ret_val<item_pocket::contain_code>::make_failure(
contain_code::ERR_MOD, _( "only immaterial items can go into software pocket" ) );
}
}

if( data->type == pocket_type::EBOOK ) {
if( it.is_book() ) {
return ret_val<item_pocket::contain_code>::make_success();
Expand All @@ -1360,13 +1378,9 @@ ret_val<item_pocket::contain_code> item_pocket::is_compatible( const item &it )
}
}

if( data->type == pocket_type::MOD ) {
if( it.is_toolmod() || it.is_gunmod() ) {
return ret_val<item_pocket::contain_code>::make_success();
} else {
return ret_val<item_pocket::contain_code>::make_failure(
contain_code::ERR_MOD, _( "only mods can go into mod pocket" ) );
}
if( it.has_flag( flag_NO_UNWIELD ) ) {
return ret_val<item_pocket::contain_code>::make_failure(
contain_code::ERR_MOD, _( "cannot unwield item" ) );
}

if( !data->item_id_restriction.empty() || !data->get_flag_restrictions().empty() ||
Expand Down Expand Up @@ -1456,12 +1470,6 @@ ret_val<item_pocket::contain_code> item_pocket::_can_contain( const item &it,
if( copies_remaining <= 0 ) {
return ret_val<item_pocket::contain_code>::make_success();
}
if( data->type == pocket_type::CORPSE ) {
// corpses can't have items stored in them the normal way,
// we simply don't want them to "spill"
copies_remaining = 0;
return ret_val<item_pocket::contain_code>::make_success();
}
// To prevent debugmsg. Casings can only be inserted in a magazine during firing.
if( data->type == pocket_type::MAGAZINE && it.has_flag( flag_CASING ) ) {
copies_remaining = 0;
Expand All @@ -1471,6 +1479,10 @@ ret_val<item_pocket::contain_code> item_pocket::_can_contain( const item &it,
if( !compatible.success() ) {
return compatible;
}
if( !is_standard_type() ) {
copies_remaining = 0;
return ret_val<item_pocket::contain_code>::make_success();
}

if( it.made_of( phase_id::LIQUID ) ) {
if( size() != 0 && !contents.front().can_combine( it ) && data->watertight ) {
Expand Down Expand Up @@ -2185,8 +2197,7 @@ std::list<item> &item_pocket::edit_contents()
ret_val<item *> item_pocket::insert_item( const item &it,
const bool into_bottom, bool restack_charges, bool ignore_contents )
{
ret_val<item_pocket::contain_code> containable = !is_standard_type() ?
ret_val<item_pocket::contain_code>::make_success() : can_contain( it, ignore_contents );
ret_val<item_pocket::contain_code> containable = can_contain( it, ignore_contents );

if( !containable.success() ) {
return ret_val<item *>::make_failure( nullptr, containable.str() );
Expand Down

0 comments on commit faa3c3b

Please sign in to comment.