22 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Containers | docs | 2 |
Containers hold and manage collections of ItemStacks in Hytale. The inventory system uses ItemContainer as the base abstraction with Inventory as the player's specialized multi-section container.
Inventory Structure
Player inventories are composed of multiple ItemContainer sections:
Inventory inv = player.getInventory();
// Get individual sections
ItemContainer storage = inv.getStorage(); // Main storage (36 slots default)
ItemContainer hotbar = inv.getHotbar(); // Hotbar (9 slots default)
ItemContainer armor = inv.getArmor(); // Armor slots
ItemContainer utility = inv.getUtility(); // Utility items (4 slots default)
ItemContainer backpack = inv.getBackpack(); // Backpack (expandable)
// Combined containers for operations across multiple sections
CombinedItemContainer hotbarFirst = inv.getCombinedHotbarFirst();
CombinedItemContainer storageFirst = inv.getCombinedStorageFirst();
Section IDs
Each section has a constant ID for operations:
| Section | ID | Constant |
|---|---|---|
| Hotbar | -1 | Inventory.HOTBAR_SECTION_ID |
| Storage | -2 | Inventory.STORAGE_SECTION_ID |
| Armor | -3 | Inventory.ARMOR_SECTION_ID |
| Utility | -5 | Inventory.UTILITY_SECTION_ID |
| Tools | -8 | Inventory.TOOLS_SECTION_ID (deprecated) |
| Backpack | -9 | Inventory.BACKPACK_SECTION_ID |
ItemContainer Basics
Reading Items
ItemContainer container = inv.getStorage();
// Get capacity (NOT getSize!)
short capacity = container.getCapacity();
// Get item at slot (slot is SHORT type)
ItemStack item = container.getItemStack((short) 0);
// Check if empty
boolean empty = container.isEmpty();
// Safe item access
ItemStack stack = container.getItemStack((short) slot);
if (!ItemStack.isEmpty(stack)) {
String itemId = stack.getItemId();
int quantity = stack.getQuantity();
}
Setting Items
ItemContainer container = inv.getHotbar();
// Set item at slot - returns a Transaction
ItemStackSlotTransaction transaction = container.setItemStackForSlot(
(short) 0,
new ItemStack("iron_sword", 1)
);
// Check if operation succeeded
if (transaction.succeeded()) {
// Item was set successfully
}
// Clear a slot
container.setItemStackForSlot((short) 0, null);
Adding Items
ItemContainer container = inv.getStorage();
ItemStack toAdd = new ItemStack("wood_plank", 64);
// Add to first available slot (stacks with existing items first)
ItemStackTransaction transaction = container.addItemStack(toAdd);
// Check for remaining items that couldn't fit
ItemStack remainder = transaction.getRemainder();
if (!ItemStack.isEmpty(remainder)) {
// Some items couldn't fit
int leftover = remainder.getQuantity();
}
// Add to specific slot
ItemStackSlotTransaction slotTransaction = container.addItemStackToSlot(
(short) 5,
toAdd
);
// Check if container can fit items before adding
if (container.canAddItemStack(toAdd)) {
container.addItemStack(toAdd);
}
Removing Items
// Remove from specific slot
SlotTransaction transaction = container.removeItemStackFromSlot((short) 0);
// Remove specific quantity from slot
ItemStackSlotTransaction removeTransaction = container.removeItemStackFromSlot(
(short) 0,
10 // quantity to remove
);
// Remove specific item type from anywhere in container
ItemStack toRemove = new ItemStack("iron_ore", 5);
ItemStackTransaction itemTransaction = container.removeItemStack(toRemove);
// Check if items can be removed before removing
if (container.canRemoveItemStack(toRemove)) {
container.removeItemStack(toRemove);
}
Active Slots
Players have active slots for hotbar and utility items:
Inventory inv = player.getInventory();
// Get active hotbar slot (0-8)
byte activeHotbar = inv.getActiveHotbarSlot();
// Set active hotbar slot
inv.setActiveHotbarSlot((byte) 3);
// Get item currently in hand
ItemStack handItem = inv.getItemInHand();
// Get/set active utility slot
byte activeUtility = inv.getActiveUtilitySlot();
inv.setActiveUtilitySlot((byte) 1);
// Get utility item
ItemStack utilityItem = inv.getUtilityItem();
Moving Items
Between Slots
Inventory inv = player.getInventory();
ItemContainer storage = inv.getStorage();
ItemContainer hotbar = inv.getHotbar();
// Move item from one slot to another in same container
MoveTransaction<SlotTransaction> transaction = storage.moveItemStackFromSlotToSlot(
(short) 0, // from slot
64, // quantity
storage, // to container
(short) 5 // to slot
);
// Move between different containers
storage.moveItemStackFromSlotToSlot(
(short) 0,
32,
hotbar,
(short) 0
);
// Use Inventory's moveItem for section-based moves
inv.moveItem(
Inventory.STORAGE_SECTION_ID, // from section
5, // from slot
10, // quantity
Inventory.HOTBAR_SECTION_ID, // to section
0 // to slot
);
Smart Moving
// Smart move considers item type for optimal placement
inv.smartMoveItem(
Inventory.STORAGE_SECTION_ID,
0, // slot
64, // quantity
SmartMoveType.EquipOrMergeStack // tries to equip armor or merge stacks
);
Iterating Containers
ItemContainer container = inv.getStorage();
// Iterate all non-empty slots
container.forEach((slot, itemStack) -> {
getLogger().at(Level.INFO).log("Slot " + slot + ": " +
itemStack.getItemId() + " x" + itemStack.getQuantity());
});
// Count items matching a condition
int swordCount = container.countItemStacks(
stack -> stack.getItemId().contains("sword")
);
// Check if container has stackable items
ItemStack testStack = new ItemStack("stone", 1);
boolean hasStackable = container.containsItemStacksStackableWith(testStack);
Checking Contents
ItemContainer container = inv.getStorage();
// Check if inventory contains specific item type and quantity
public boolean hasItems(ItemContainer container, String itemId, int amount) {
int count = container.countItemStacks(
stack -> stack.getItemId().equals(itemId)
);
return count >= amount;
}
// Find first slot with specific item
public short findSlotWithItem(ItemContainer container, String itemId) {
for (short i = 0; i < container.getCapacity(); i++) {
ItemStack stack = container.getItemStack(i);
if (!ItemStack.isEmpty(stack) && stack.getItemId().equals(itemId)) {
return i;
}
}
return -1; // Not found
}
// Count empty slots
public int countEmptySlots(ItemContainer container) {
int empty = 0;
for (short i = 0; i < container.getCapacity(); i++) {
if (ItemStack.isEmpty(container.getItemStack(i))) {
empty++;
}
}
return empty;
}
Clearing Containers
ItemContainer container = inv.getStorage();
// Clear entire container
ClearTransaction transaction = container.clear();
// Drop all items (returns list of dropped items)
List<ItemStack> droppedItems = container.dropAllItemStacks();
// Remove all items (returns list)
List<ItemStack> removedItems = container.removeAllItemStacks();
// Clear entire player inventory
inv.clear();
// Drop all from player inventory
List<ItemStack> allDropped = inv.dropAllItemStacks();
Sorting
Available SortType values: NAME, TYPE, RARITY
ItemContainer container = inv.getStorage();
// Sort items
container.sortItems(SortType.NAME);
// Sort via Inventory (also saves sort preference)
inv.sortStorage(SortType.NAME);
inv.setSortType(SortType.RARITY); // Or TYPE
Container Events
// Register for container change events
container.registerChangeEvent(event -> {
ItemContainer changedContainer = event.container();
Transaction transaction = event.transaction();
getLogger().at(Level.INFO).log("Container changed!");
});
// With priority
container.registerChangeEvent(EventPriority.EARLY, event -> {
// Handle early
});
Transaction System
All modification operations return Transaction objects:
// Transactions track success and changes
ItemStackTransaction transaction = container.addItemStack(itemStack);
if (transaction.succeeded()) {
ItemStack remainder = transaction.getRemainder();
// ...
}
// Slot transactions include slot info
ItemStackSlotTransaction slotTransaction = container.setItemStackForSlot(
(short) 0,
itemStack
);
if (slotTransaction.succeeded()) {
short slot = slotTransaction.getSlot();
ItemStack before = slotTransaction.getSlotBefore();
ItemStack after = slotTransaction.getSlotAfter();
}
Operation Parameters
Most container operations support optional parameters:
// Default values
DEFAULT_ADD_ALL_OR_NOTHING = false; // Partial adds allowed
DEFAULT_REMOVE_ALL_OR_NOTHING = true; // Only full removals
DEFAULT_FULL_STACKS = false; // Can split stacks
DEFAULT_EXACT_AMOUNT = true; // Exact quantities only
DEFAULT_FILTER = true; // Apply slot filters
// Add with parameters
container.addItemStack(itemStack, allOrNothing, fullStacks, filter);
// allOrNothing: if true, fails entirely if not all items fit
// fullStacks: if true, only fills empty slots (no stacking)
// filter: if true, respects slot filters
Material and Resource Removal
Containers support removing items by material type or resource type (used for crafting):
{{< callout type="info" >}}
MaterialQuantity constructor: MaterialQuantity(itemId, resourceTypeId, tag, quantity, metadata)
At least one of itemId, resourceTypeId, or tag must be non-null.
{{< /callout >}}
// Remove by material using itemId
MaterialQuantity materialByItem = new MaterialQuantity("iron_ingot", null, null, 5, null);
if (container.canRemoveMaterial(materialByItem)) {
MaterialTransaction transaction = container.removeMaterial(materialByItem);
}
// Remove by material using resourceTypeId
MaterialQuantity materialByResource = new MaterialQuantity(null, "iron", null, 5, null);
if (container.canRemoveMaterial(materialByResource)) {
MaterialTransaction transaction = container.removeMaterial(materialByResource);
}
// Remove by resource type (simpler constructor)
ResourceQuantity resource = new ResourceQuantity("wood", 10);
if (container.canRemoveResource(resource)) {
ResourceTransaction transaction = container.removeResource(resource);
}
// Remove by tag index
if (container.canRemoveTag(tagIndex, quantity)) {
TagTransaction transaction = container.removeTag(tagIndex, quantity);
}
// Bulk removal
List<MaterialQuantity> materials = List.of(
new MaterialQuantity("iron_ingot", null, null, 2, null),
new MaterialQuantity(null, null, "Wood", 5, null) // Using tag
);
if (container.canRemoveMaterials(materials)) {
container.removeMaterials(materials);
}
Bulk Operations
Add or remove multiple items at once:
// Add multiple items
List<ItemStack> items = List.of(
new ItemStack("iron_ore", 10),
new ItemStack("gold_ore", 5)
);
if (container.canAddItemStacks(items)) {
ListTransaction<ItemStackTransaction> transaction = container.addItemStacks(items);
}
// Remove multiple items
if (container.canRemoveItemStacks(items)) {
container.removeItemStacks(items);
}
// Add items in order (preserves slot positions)
container.addItemStacksOrdered(items);
container.addItemStacksOrdered((short) 5, items); // Starting at slot 5
Advanced Move Operations
// Move all items to another container
ListTransaction<MoveTransaction<ItemStackTransaction>> result =
storage.moveAllItemStacksTo(hotbar, backpack);
// Move all items matching a condition
storage.moveAllItemStacksTo(
item -> item.getItemId().contains("ore"),
hotbar
);
// Quick stack: only moves items that can stack with existing items
storage.quickStackTo(hotbar);
// Combine small stacks into one slot
container.combineItemStacksIntoSlot(targetContainer, (short) 0);
// Swap items between containers
storage.swapItems(
(short) 0, // source position
hotbar, // target container
(short) 0, // destination position
(short) 5 // number of slots to swap
);
Replace Operations
// Replace item in slot if it matches expected
ItemStackSlotTransaction transaction = container.replaceItemStackInSlot(
(short) 0,
expectedItem, // must match current item to proceed
newItem
);
// Replace all items using a function
container.replaceAll((slot, existing) -> {
if (existing.getItemId().equals("old_item")) {
return new ItemStack("new_item", existing.getQuantity());
}
return existing;
});
Slot Filters
Control which items can go in which slots:
// Set global filter for the container
container.setGlobalFilter(FilterType.WHITELIST);
// Set filter for specific slot
container.setSlotFilter(
FilterActionType.ADD, // Filter on add operations
(short) 0, // Slot
slotFilter // Filter implementation
);
Best Practices
{{< callout type="info" >}} Container Tips:
- Slot indices are
short, notint- cast appropriately - Always check
ItemStack.isEmpty(stack)- handles both null and empty - Use
getQuantity()notgetCount() - Check transaction success with
succeeded() - Use combined containers for cross-section operations
- Player inventory changes trigger
LivingEntityInventoryChangeEvent{{< /callout >}}
// Safe pattern for working with containers
public void safeAddItem(ItemContainer container, ItemStack item) {
if (ItemStack.isEmpty(item)) {
return;
}
if (!container.canAddItemStack(item)) {
// Handle full container
return;
}
ItemStackTransaction transaction = container.addItemStack(item);
if (!transaction.succeeded()) {
// Handle failure
}
}
ItemContainer API Reference
Core Methods
| Method | Returns | Description |
|---|---|---|
getCapacity() |
short |
Total number of slots |
getItemStack(short) |
ItemStack? |
Get item at slot |
isEmpty() |
boolean |
True if no items |
clone() |
ItemContainer |
Clone the container |
clear() |
ClearTransaction |
Remove all items |
Add Operations
| Method | Returns | Description |
|---|---|---|
canAddItemStack(ItemStack) |
boolean |
Check if can add |
canAddItemStack(ItemStack, fullStacks, filter) |
boolean |
Check with options |
addItemStack(ItemStack) |
ItemStackTransaction |
Add to first available |
addItemStack(ItemStack, allOrNothing, fullStacks, filter) |
ItemStackTransaction |
Add with options |
canAddItemStackToSlot(short, ItemStack, allOrNothing, filter) |
boolean |
Check if can add to slot |
addItemStackToSlot(short, ItemStack) |
ItemStackSlotTransaction |
Add to specific slot |
addItemStackToSlot(short, ItemStack, allOrNothing, filter) |
ItemStackSlotTransaction |
Add to slot with options |
canAddItemStacks(List<ItemStack>) |
boolean |
Check if can add multiple |
addItemStacks(List<ItemStack>) |
ListTransaction |
Add multiple items |
addItemStacksOrdered(List<ItemStack>) |
ListTransaction |
Add in order |
addItemStacksOrdered(short offset, List<ItemStack>) |
ListTransaction |
Add in order from offset |
Set Operations
| Method | Returns | Description |
|---|---|---|
setItemStackForSlot(short, ItemStack) |
ItemStackSlotTransaction |
Set item at slot |
setItemStackForSlot(short, ItemStack, filter) |
ItemStackSlotTransaction |
Set with filter option |
replaceItemStackInSlot(short, ItemStack expected, ItemStack new) |
ItemStackSlotTransaction |
Replace if matches |
replaceAll(SlotReplacementFunction) |
ListTransaction |
Replace all items |
Remove Operations
| Method | Returns | Description |
|---|---|---|
removeItemStackFromSlot(short) |
SlotTransaction |
Remove entire slot |
removeItemStackFromSlot(short, filter) |
SlotTransaction |
Remove with filter |
removeItemStackFromSlot(short, quantity) |
ItemStackSlotTransaction |
Remove quantity |
removeItemStackFromSlot(short, ItemStack, quantity) |
ItemStackSlotTransaction |
Remove matching item |
canRemoveItemStack(ItemStack) |
boolean |
Check if can remove |
removeItemStack(ItemStack) |
ItemStackTransaction |
Remove item type |
canRemoveItemStacks(List<ItemStack>) |
boolean |
Check if can remove multiple |
removeItemStacks(List<ItemStack>) |
ListTransaction |
Remove multiple items |
removeAllItemStacks() |
List<ItemStack> |
Remove and return all |
dropAllItemStacks() |
List<ItemStack> |
Drop all (respects cantDrop) |
dropAllItemStacks(filter) |
List<ItemStack> |
Drop with filter option |
Material/Resource/Tag Removal
| Method | Returns | Description |
|---|---|---|
canRemoveMaterial(MaterialQuantity) |
boolean |
Check material removal |
removeMaterial(MaterialQuantity) |
MaterialTransaction |
Remove by material |
removeMaterialFromSlot(short, MaterialQuantity) |
MaterialSlotTransaction |
Remove material from slot |
canRemoveMaterials(List<MaterialQuantity>) |
boolean |
Check multiple materials |
removeMaterials(List<MaterialQuantity>) |
ListTransaction |
Remove multiple materials |
canRemoveResource(ResourceQuantity) |
boolean |
Check resource removal |
removeResource(ResourceQuantity) |
ResourceTransaction |
Remove by resource |
removeResourceFromSlot(short, ResourceQuantity) |
ResourceSlotTransaction |
Remove resource from slot |
canRemoveResources(List<ResourceQuantity>) |
boolean |
Check multiple resources |
removeResources(List<ResourceQuantity>) |
ListTransaction |
Remove multiple resources |
canRemoveTag(tagIndex, quantity) |
boolean |
Check tag removal |
removeTag(tagIndex, quantity) |
TagTransaction |
Remove by tag |
removeTagFromSlot(short, tagIndex, quantity) |
TagSlotTransaction |
Remove tag from slot |
Move Operations
| Method | Returns | Description |
|---|---|---|
moveItemStackFromSlot(short, ItemContainer) |
MoveTransaction |
Move slot to container |
moveItemStackFromSlot(short, quantity, ItemContainer) |
MoveTransaction |
Move quantity |
moveItemStackFromSlot(short, ItemContainer...) |
ListTransaction |
Move to multiple containers |
moveItemStackFromSlotToSlot(short, quantity, ItemContainer, short) |
MoveTransaction |
Move to specific slot |
moveAllItemStacksTo(ItemContainer...) |
ListTransaction |
Move all items |
moveAllItemStacksTo(Predicate, ItemContainer...) |
ListTransaction |
Move matching items |
quickStackTo(ItemContainer...) |
ListTransaction |
Move stackable items only |
combineItemStacksIntoSlot(ItemContainer, short) |
ListTransaction |
Combine stacks into slot |
swapItems(short srcPos, ItemContainer, short destPos, short length) |
ListTransaction |
Swap item ranges |
Utility Methods
| Method | Returns | Description |
|---|---|---|
forEach(ShortObjectConsumer) |
void |
Iterate non-empty slots |
forEachWithMeta(consumer, meta) |
void |
Iterate with metadata |
countItemStacks(Predicate) |
int |
Count matching items (total quantity) |
containsItemStacksStackableWith(ItemStack) |
boolean |
Check for stackable items |
sortItems(SortType) |
ListTransaction |
Sort container |
registerChangeEvent(Consumer) |
EventRegistration |
Listen for changes |
registerChangeEvent(EventPriority, Consumer) |
EventRegistration |
Listen with priority |
setGlobalFilter(FilterType) |
void |
Set container filter |
setSlotFilter(FilterActionType, short, SlotFilter) |
void |
Set slot filter |
containsContainer(ItemContainer) |
boolean |
Check if contains container |
Static Methods
| Method | Returns | Description |
|---|---|---|
copy(from, to, remainder) |
T |
Copy items between containers |
ensureContainerCapacity(container, capacity, supplier, remainder) |
T |
Ensure container has capacity |
getNewContainer(capacity, supplier) |
ItemContainer |
Create or get empty |
getMatchingResourceType(Item, resourceId) |
ItemResourceType? |
Find resource type for item |
validateQuantity(int) |
void |
Throws if < 0 |
validateSlotIndex(short, capacity) |
void |
Throws if out of bounds |
Static Constants
| Field | Type | Description |
|---|---|---|
CODEC |
CodecMapCodec<ItemContainer> |
Serialization codec |
DEFAULT_ADD_ALL_OR_NOTHING |
boolean |
false |
DEFAULT_REMOVE_ALL_OR_NOTHING |
boolean |
true |
DEFAULT_FULL_STACKS |
boolean |
false |
DEFAULT_EXACT_AMOUNT |
boolean |
true |
DEFAULT_FILTER |
boolean |
true |
Nested Classes
| Class | Description |
|---|---|
ItemContainerChangeEvent |
Event record with container() and transaction() |
Inventory API Reference
| Method | Returns | Description |
|---|---|---|
getStorage() |
ItemContainer |
Main storage section |
getHotbar() |
ItemContainer |
Hotbar section |
getArmor() |
ItemContainer |
Armor section |
getUtility() |
ItemContainer |
Utility section |
getBackpack() |
ItemContainer |
Backpack section |
getSectionById(int) |
ItemContainer? |
Get section by ID |
getItemInHand() |
ItemStack? |
Currently held item |
getActiveHotbarSlot() |
byte |
Active hotbar slot |
setActiveHotbarSlot(byte) |
void |
Set active hotbar |
getCombinedHotbarFirst() |
CombinedItemContainer |
Hotbar+Storage combined |
moveItem(...) |
void |
Move between sections |
clear() |
void |
Clear all sections |