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

Item contents refactor (holster refactor 2 of 3) #36660

Closed
wants to merge 2 commits into from

Conversation

KorGgenT
Copy link
Member

@KorGgenT KorGgenT commented Jan 3, 2020

Summary

SUMMARY: Infrastructure "Refactor item contents to use item pockets"

Purpose of change

This is the most invasive part of the large amount of changes necessary for the nested container project. item::contents was previously a std::list. not only that, but it was a public member. this means there are many instances in which the list was treated exactly like that: a list. As such, some extra encapsulation was required in order to use the new classes, and some new functions that essentially act like psuedo-wrapper functions needed to be created.
Of note: there are some functions that are either all_items() and all_items_ptr(). this is due to needing to act on some arbitrary number of items in an arbitrary point in the list, not knowing what item you wanted to act upon in the first place. These functions aren't meant to be permanent and used as often as they are, but using them reduces the line count and complexity for now.
Additionally, there are many item functions that pick a specific item in order to determine whether it's a liquid container, or what name to display, etc. This also needs to be eventually moved away from in the future. The migration function was surprisingly easy to do, and additional changes to it should be fairly doable as well. Especially using savegame versions.

There are another two notable additions/changes that are important:

  • a new item_location type called container. this item_location stores its parent, and will be used for things such as obtain_cost.
  • visitable was adjusted in order to use item::contents properly.
    I would appreciate those who are acquainted with these two things to double-check my work -- i'm fairly sure i've got them right, but I'm only using the item_location in one place for now, and plan to use that more with inventory code in the near future.

Testing

This PR was tested as part of the batch of all three PRs by several volunteers. It might be possible that some slipped through in this particular stage, and it is probably a good idea to test this PR individually as well.

Additional Notes

relies on #36656 and has the commits from that PR

@KorGgenT KorGgenT added [C++] Changes (can be) made in C++. Previously named `Code` 0.E Feature Freeze labels Jan 3, 2020
@KorGgenT KorGgenT force-pushed the item-contents-refactor branch from 6c88f8c to ded1eb9 Compare January 3, 2020 04:55
@KorGgenT KorGgenT force-pushed the item-contents-refactor branch from ded1eb9 to a869e6d Compare January 4, 2020 03:46
@KorGgenT
Copy link
Member Author

KorGgenT commented Jan 4, 2020

note Consider adding a new test to tests/iteminfo_test.cpp for your new iteminfo features.

contents.insert_legacy( it );
}
} else {
optional( data, false, "contents", contents );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
optional( data, false, "contents", contents );
data.read( "contents", contents );

Or is there an advantage to using optional here?

if( !target() ) {
return std::string();
}
return _( string_format( "inside %s", container->tname() ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same translation problem as in the other PR.

Suggested change
return _( string_format( "inside %s", container->tname() ) );
return string_format( _( "inside %s" ), container->tname() );


const int container_mv = container->contents.obtain_cost( *target() );
if( container_mv == 0 ) {
debugmsg( string_format( "ERROR: %s does not contain %s", container->tname(), target()->tname() ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
debugmsg( string_format( "ERROR: %s does not contain %s", container->tname(), target()->tname() ) );
debugmsg( "ERROR: %s does not contain %s", container->tname(), target()->tname() );

debugmsg does string formatting.

@@ -7942,10 +7937,11 @@ int iuse::foodperson( player *p, item *it, bool t, const tripoint &pos )
int iuse::radiocar( player *p, item *it, bool, const tripoint & )
{
int choice = -1;
auto bomb_it = std::find_if( it->contents.begin(), it->contents.end(), []( const item & c ) {
std::list<item> all_items{ it->contents.all_items() };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This list contains copies of all the items within the pockets. bomb_it contains a reference to one of those copied items.

Later you call it->contents.remove_item( *bomb_it ), but remove_item does removal based on the item pointer (see item_pocket::remove_item) , which is now a pointer to the copy stored in the all_items list. It won't remove anything.

This problem might exist at other places that use the result of all_items.

@@ -8439,7 +8433,7 @@ int iuse::autoclave( player *p, item *it, bool t, const tripoint &pos )

bool empty = true;
item *clean_cbm = nullptr;
for( item &bio : it->contents ) {
for( item &bio : it->contents.all_items() ) {
if( bio.is_bionic() ) {
clean_cbm = &bio;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this will lead directly to UB. all_items returns a std::list<item>, so the loop iterates over that list. But the list is never stored, so after the loop finishes, it's deleted (including all the contained items), and clean_cbm will now point to a deleted object.

@@ -923,6 +924,9 @@ struct itype {
/** Weight difference with the part it replaces for mods */
units::mass integral_weight = -1_gram;

// information related to being able to store things inside the item.
std::vector<pocket_data> pocket_data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the error thrown by the build bot:

pocket_data now has two meanings: the local member, and the type. Either rename the member, or use a fully qualified type name:

Suggested change
std::vector<pocket_data> pocket_data;
std::vector<::pocket_data> pocket_data;

(This makes it unambiguous: pocket_data is the member, and ::pocket_data is the global type.)

@@ -17,6 +17,7 @@
#include "catacharset.h"
#include "debug.h"
#include "enums.h"
#include "generic_factory.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be unused.

@KorGgenT
Copy link
Member Author

KorGgenT commented Jan 4, 2020

This PR was merged with the other one due to the code needed in order for anything to happen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C++] Changes (can be) made in C++. Previously named `Code`
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants