Skip to main content
Version: 1.21.x

Basic Inventory Management

Learn how to access and manage the Curios inventory attached to an entity.

Overview


Each entity that has been assigned any number of slot types based on entity registration will automatically gain a Curios inventory, initialized with a sub-inventory for each slot type that has been assigned. This inventory can be used for a variety of purposes, such as finding out which items are held in the inventory or modifying the number of slots that are in each sub-inventory.

The interface for the Curios inventory can be found as top.theillusivec4.curios.api.type.capability.ICuriosItemHandler, which holds all the methods that developers can use to access and manage the inventory.

Using the inventory


To begin using the inventory, developers will need to grab the instance associated with each entity. The top.theillusivec4.curios.api.CuriosApi class has a getCuriosInventory method that can be used:

Optional<ICuriosItemHandler> maybeCuriosInventory = CuriosApi.getCuriosInventory(livingEntity);

The query returns a Optional as the specified entity may not have a curios inventory. If the result is certain to exist, then the optionality can be disregarded and simplified to:

ICuriosItemHandler curiosInventory = CuriosApi.getCuriosInventory(livingEntity).get();

Since the method returns an Optional by default, developers will need to make sure to use Optional#ifPresent first in order to check that the inventory actually exists:

CuriosApi.getCuriosInventory(livingEntity).ifPresent(curiosInventory -> {
// code here - with access to the inventory instance that now definitely exists
});

Once a developer has the ICuriosItemHandler instance, they can use the methods from that instance to interact with the Curios inventory.

Without external dependencies

It's possible to access the Curios inventory without a declared dependency on Curios in a developer's mod. This provides a way to code simple Curios compatibility without needing to manage an additional external dependency on Curios itself or any of its classes.

In order to do so, first declare a field for the entity capability in any class, like the following example:

public class CuriosCompatibility {

public static final EntityCapability<IItemHandler, Void> CURIOS_INVENTORY =
EntityCapability.createVoid(ResourceLocation.fromNamespaceAndPath("curios", "item_handler"), IItemHandler.class);
}

Since Curios is the one responsible for registering this capability, this is all developers need to do to gain access to the IItemHandler instance.

To retrieve the inventory instance, developers can call the previously declared field like any other capability using LivingEntity#getCapability provided by NeoForge:

livingEntity.getCapability(CuriosCompatibility.CURIOS_INVENTORY);

This capability, like the native Curios one, is not guaranteed to exist on every instance of LivingEntity so an additional null check is recommended before accessing the returned IItemHandler.

The returned IItemHandler can be used to modify both the inventory contents and the stack contents using the methods provided in the IItemHandler interface. These changes will be reflected back onto the main inventory object.

Accessing the inventory


As mentioned previously, each slot type assigned to an entity is given a sub-inventory in the Curios inventory to provide easy and categorical access. There are two main ways to interact with these slot inventories, depending on whether the developer wants to access all of the slot inventories or just a particular one.

Accessing the entire inventory

The entire Curios inventory exists as a Map<String, ICurioStackHandler>, with the slot type identifiers acting as each key and the ICurioStackHandler acting as the inventory attached to the slot type. To access this, the getCurios method can be used:

Map<String, ICurioStackHandler> curios = curiosInventory.getCurios();
caution

This returns an unmodifiable map so attempts to change the structure of the map directly through this method, such as adding or removing slot inventories, will not work. Any changes to the structure needs to be done through other methods, this method is primarily for accessing the list of slot inventories on the entity.

From here, developers can either iterate through the entire map:

curios.forEach((identifier, slotInventory) -> {
// code here - with the identifier and slot inventory access
})

Or developers can access a particular sub-inventory, such as a slot type with the "ring" identifier:

ICurioStackHandler slotInventory = curios.get("ring");

// null check to ensure that the slot inventory exists
if (slotInventory != null) {
// code here
}

However, if all a developer wants is to access a particular sub-inventory, there's a more straightforward method outlined in the next section that can be used instead.

Accessing an inventory for a slot type

In order to access a particular inventory for slot type, developers can either access the whole inventory as outlined in the preceding section or skip straight to a sub-inventory for that slot type:

Optional<ICurioStackHandler> slotInventory = curiosInventory.getStacksHandler("ring");

The above code will retrive an Optional for the slot inventory with the "ring" identifier passed into the parameter. This is an Optional because the slot inventory being queried may not exist on the entity, which is a possibility that developers must consider because higher-priority datapacks are capable of removing slot types from entities. For that reason, be sure to use ifPresent before accessing the inventory:

curiosInventory.getStacksHandler("ring").ifPresent(slotInventory -> {
// code here - with access to the slot inventory with the "ring" identifier
});