"Boxing" items for neatness and performance

Currently, you can’t store solid obects in containers, as you can with liquids. Would it be possible to make an object that “encapsulates” a number of items chosen by the player, stores a list of them and unloads them from the game resulting in a box with weight dependent on what items were deposited when sealed? Think of it like an carryable item equivalen of a crate. You could put spare food/water/medicine as to not accidentally use it in crafting or to leave at a safehouse. You could migrate First Aid Kits and MREs to be sealed “boxes” instead of specific items to be deconstructed. You could box all the random weapons you don’t use to reduce clutter in the inventory.

“Boxing” could potentially increase performance, as a sealed box could require less calculations than the multiple different items contained therein.
A “NO_BOXING” flag would need to be added for time/charge dependent items such as activated flashlight and grenades as they would be unloaded inside the box.

Thoughts?

there is currently a boxing/container mod. it lets you pack a bunch of something into a box to greatly lower their volume and turn the set into one item in exchange for being a little heavier.

Well it wouldn’t reduce volume, that violating the laws of physics and all that. The problem with the packaging mod (if we are thinking of the same one) is that a single box can only contain one type of item, and that there needs to be a recepie for every item to be stored. If different items were allowed to me packed in this manner, you would need to define a recepie for every permutation of items, which would be an absurd number.

It would be complex to implement and would not increase performance by any noticeable amount.
If someone wants to implement it, I’d try to help, but I’d expect it to be abandoned in less than a week, after encountering all the blocking bugs and code that instantly stops working as soon as there is more than one object contained in a different object.

Well how simple could you make it? In my mind, there would be practically no interaction with the items inside the box, similar to MREs from a user perspective.

Take a group of items of no greater volume than the capacity of the box.
Make a list of the items.
Sum the weight of the items.
Store the list.
Delete all items.
Add the total item weight to the box.
Write a simple manifest of the items as a string to the box description.
Ignore all items and the list within the box until it is destroyed or opened.
Upon opening, run a check on decomposition, etc. (All handled by item birth date, unless I’m mistaken)
Spawn items in the list.
Remove the list
Reset box to default empty weight and description.

Naturally, I’ve probably overlooked something in my psedo-pseudo-code.

    /**
     * @name Containers
     *
     * Containers come in two flavors:
     * - suitable for liquids (@ref is_watertight_container),
     * - and the remaining one (they are for currently only for flavor).
     */
    /*@{*/
    /** Whether this is container. Note that container does not necessarily means it's
     * suitable for liquids. */
    bool is_container() const;
    /** Whether this is a container which can be used to store liquids. */
    bool is_watertight_container() const;
    /** Whether this item has no contents at all. */
    bool is_container_empty() const;
    /** Whether removing this item's contents will permanently alter it. */
    bool is_non_resealable_container() const;
    /**
     * Whether this item has no more free capacity for its current content.
     * @param allow_bucket Allow filling non-sealable containers
     */
    bool is_container_full( bool allow_bucket = false ) const;
    /**
     * Fill item with liquid up to its capacity. This works for guns and tools that accept
     * liquid ammo.
     * @param liquid Liquid to fill the container with.
     * @param amount Amount to fill item with, capped by remaining capacity
     */
    void fill_with( item &liquid, long amount = INFINITE_CHARGES );
    /**
     * How much more of this liquid (in charges) can be put in this container.
     * If this is not a container (or not suitable for the liquid), it returns 0.
     * Note that mixing different types of liquid is not possible.
     * Also note that this works for guns and tools that accept liquid ammo.
     * @param liquid Liquid to check capacity for
     * @param allow_bucket Allow filling non-sealable containers
     * @param err Message to print if no more material will fit
     */
    long get_remaining_capacity_for_liquid( const item &liquid, bool allow_bucket = false,
                                            std::string *err = nullptr ) const;
    long get_remaining_capacity_for_liquid( const item &liquid, const Character &p,
                                            std::string *err = nullptr ) const;
    /**
     * It returns the total capacity (volume) of the container.
     */
    units::volume get_container_capacity() const;
    /**
     * Puts the given item into this one, no checks are performed.
     */
    void put_in( item payload );

    /** Stores a newly constructed item at the end of this item's contents */
    template<typename ... Args>
    item& emplace_back( Args&&... args ) {
        contents.emplace_back( std::forward<Args>( args )... );
        if( contents.back().is_null() ) {
            debugmsg( "Tried to emplace null item" );
        }
        return contents.back();
    }

    /**
     * Returns this item into its default container. If it does not have a default container,
     * returns this. It's intended to be used like \code newitem = newitem.in_its_container();\endcode
     */
    item in_its_container() const;
    item in_container( const itype_id &container_type ) const;

You can actually store items inside other items - here is the LUA code:

local container_id = "30gal_barrel"
local container = item(container_id, 1)

local item_id = "hamburger"
local item = item(item_id, 1)

local item_id2 = "water"
local item2 = item(item_id2, 1)

local item_id3 = "bottle_plastic"
local item3 = item(item_id3, 1)

container:put_in(item)
container:put_in(item2)
container:put_in(item3)

player:i_add(container)

After running this code via LUA console (I prefer put this code to 1.lua in cataclysm folder and execute dofile('./1.lua')) you will get 30 gallon barrel, full item and when you unload it you will get all of the contents.

[quote=“Zhilkin, post:7, topic:14228”]You can actually store items inside other items - here is the LUA code:

local container_id = "30gal_barrel"
local container = item(container_id, 1)

local item_id = "hamburger"
local item = item(item_id, 1)

local item_id2 = "water"
local item2 = item(item_id2, 1)

local item_id3 = "bottle_plastic"
local item3 = item(item_id3, 1)

container:put_in(item)
container:put_in(item2)
container:put_in(item3)

player:i_add(container)

After running this code via LUA console (I prefer put this code to 1.lua in cataclysm folder and execute dofile('./1.lua')) you will get 30 gallon barrel, full item and when you unload it you will get all of the contents.[/quote]
Can you stack that lot inside another 30gal drum etc.?

[quote=“BorkBorkGoesTheCode, post:8, topic:14228”][quote=“Zhilkin, post:7, topic:14228”]You can actually store items inside other items - here is the LUA code:

local container_id = "30gal_barrel"
local container = item(container_id, 1)

local item_id = "hamburger"
local item = item(item_id, 1)

local item_id2 = "water"
local item2 = item(item_id2, 1)

local item_id3 = "bottle_plastic"
local item3 = item(item_id3, 1)

container:put_in(item)
container:put_in(item2)
container:put_in(item3)

player:i_add(container)

After running this code via LUA console (I prefer put this code to 1.lua in cataclysm folder and execute dofile('./1.lua')) you will get 30 gallon barrel, full item and when you unload it you will get all of the contents.[/quote]
Can you stack that lot inside another 30gal drum etc.?[/quote]
Sure. With a little more code. After you created container and put all items to it, you just create another container and put first container with items to the second container.

local container_id = "30gal_barrel"
local container = item(container_id, 1)

local item_id = "hamburger"
local item = item(item_id, 1)

local item_id2 = "water"
local item2 = item(item_id2, 1)

local item_id3 = "bottle_plastic"
local item3 = item(item_id3, 1)

container:put_in(item)
container:put_in(item)
container:put_in(item)
container:put_in(item)
container:put_in(item2)
container:put_in(item2)
container:put_in(item3)
container:put_in(item3)
container:put_in(item3)

local container_id2 = "30gal_barrel"
local container2 = item(container_id2, 1)

container2:put_in(container)

player:i_add(container2)

LUA is used just for quick example. C++ functions are working in the very same manner.

LUA lacks support of GUI elements, so it will be hard (but not impossible) to implement container interaction. Actually there is only text popup wihtout callbacks and menu with callbacks (you know which menu item was selected), so something could be implemented through text menus like in classic console RPGs - you highlight item from inventory, select one of possible actions (“put to container”, “remove from container”, “move to another container” etc) then select new container to put the item in (from the list of possible containers).

And through the C++ you can do anything with the GUI.

You can see item contents with


local contents_string = container2:serialize()

print(tostring(contents_string))

I think all volume increasing equipment should be handled independently. In your inventory it would list each piece of volume increasing equipment followed by its contents.
Like this:
/–
Inventory Weight (lbs): #/#
Item hotkeys assigned: #/69 Volume (L): #/#

Cargo Pants: Volume #/#
-Item 1
-Item 2

Backpack (Label): Volume #/#
-Item 1
-Item 2
–/

Then when it’s dropped it has a weight of all items plus it’s weight and takes up a volume of its volume. It would allow organizing stuff on the ground… Make them accessible through the “Apply or Use Item” menu. Maybe allow labeling them like you would a vehicle? Just a thought.