Packed Inventory
No reviews yet
Inventory management has never been so easy.
Includes quality of life improvements and small tweaks to enhance and customize gameplay.
Features systems for better item storage and organization.
Provides a framework or library for other mods to use.
Fabric is a mod loader for versions 1.14+ of Minecraft, particularly popular for client side and optimization mods.
Community voices
Reviews
Click once to include, again to exclude, again to clear
No reviews yet. Be the first to review this project!
Get it on
Available Platforms
Compatibility
Supported Environments
Must be installed on both the client and the server.
About
Project Details
For authors
Embed Badge
If you're the author of this project, you can embed a live badge anywhere that supports HTML or Markdown. It updates automatically whenever ratings change.
Use HTML for any page that supports it, or Markdown for README files and Markdown-based descriptions.
Identifiers
Platform IDs
About
Description

Packed Inventory
A Minecraft mod that attempts to mitigate the ever-growing Inventory Problem by making it possible to manage the contents of shulker boxes, ender chests, and more directly from your inventory.
Oh, we also have fancy tooltips for shulker boxes, ender chests, maps, and beyond!
Features
- Manage the inventory of shulker boxes without ever placing them.
- Manage the inventory of your ender chest without ever placing it.
- Quickly move items into or out of shulker boxes, ender chests, and other inventory-providing items.
- Access crafting tables, stonecutters, and other workstations directly from your inventory.
- Vanilla-like tooltips for shulker boxes.
- Vanilla-like tooltips for ender chests.
- Vanilla-like tooltips for filled maps.
- Vanilla-like tooltips for NBT-containing items acquired in Creative mode via
Ctrl + MMB, such as chests, barrels, furnaces, hoppers, dispensers, droppers, and more. - An extensive and simple API that helps other modders implement these features for their blocks and items.
Bundle-Like Functionality

As mentioned earlier, inventory-providing items (e.g., shulker boxes, ender chests, and any items registered via the Packed Inventory API) automatically gain bundle-like functionality, allowing you to quickly move items into or out of them.
To store items inside an inventory-providing item, you can either:
- Pick up the inventory-providing item and press
kon the item(s) to be stored, or - Pick up the inventory-providing item and press
kon the inventory-providing item(s) to be stored, or - Pick up the item(s) to be stored and press
kon the inventory-providing item.
To retrieve items from an inventory-providing item:
- Pick up the inventory-providing item and press
kon the empty slot(s) to extract the item(s) to, or - Pick up the inventory-providing item and press
lorctrl + kon the slot(s) to extract the item(s) to, or - Press
lorctrl + kon the inventory-providing item(s) to extract the items from.
To dump all items from an inventory-providing item out into the world:
- Pick up the inventory-providing item, move it outside of the inventory frame, and press
k.
Tooltips
Here are some tooltip examples for you:
- Container tooltip
- Colored container tooltip
- Compact container tooltip
- Filled map tooltip

More screenshots can be found here.
Key Binds
Key binds can be configured just like vanilla ones:
- Go to
Options. - Select
Controls. - Then choose
Key Binds. - Scroll down to the
Packed Inventorysection. - Configure the available key binds.
Available key binds:
Interact with item- Interacts with the item in the active hotbar slot. Alternatively, if the inventory screen is open, interacts with the item the mouse is hovering over. Depending on the context, this action can either: open a screen associated with the selected item, store an item inside the selected inventory-providing item, retrieve an item from the selected inventory-providing item, or dump all the items stored in the selected inventory-providing item out into the world (Kby default)Toggle interaction mode (hold)- Makes theInteract with itemkey bind behave likeExtract from item(Left Controlby default)Extract from item- Extracts an item from the selected inventory-providing item (Lby default)Invert tooltip visibility (hold)- Inverts tooltip visibility while pressed (Left Shiftby default)Invert tooltip compact mode (hold)- Inverts tooltip compact mode while pressed (Cby default)
Note that it's totally fine for these key binds to interfere with others since they are applied only when your inventory screen is open, where other key binds usually do not work.
Config
If you have Cloth Config installed, you can customize the behavior of the mod. A config is usually located at ./config/packed-inventory.json.
tooltip.enable- indicates whether a tooltip should be enabled by default or not (client,trueby default)tooltip.compact- indicates whether tooltip compact mode should be enabled by default or not (client,falseby default)tooltip.showWhenEmpty- indicates whether a tooltip should be shown when its content is empty or not (client,falseby default)tooltip.rows- specifies the number of rows used to display tooltip content (client,-1by default)tooltip.columns- specifies the number of columns used to display tooltip content (client,-1by default)tooltip.usePredefinedColor- indicates whether a tooltip should use item color or not (client,falseby default)tooltip.color- specifies default tooltip color in caseusePredefinedColoris set tofalse, or item color cannot be automatically determined (client,falseby default)tooltip.syncInterval- determines how often synchronization should occur (client,5000by default)tooltip.size- specifies size of a tooltip (mostly used by thefilled_maptooltip) (client,128by default)validation.enable- indicates whether an action associated with this validation rule should be allowed at all or not (server,trueby default)validation.suppressValidationInCreative- indicates whether validation should be suppressed for creative players (server,trueby default)validation.requiresPlayerOnGround- indicates whether a player should be on the ground in order to proceed (server,trueby default)validation.requiresSilkTouch- indicates whether a player should have a tool enchanted with silk touch enchantment in order to proceed (server,trueby default)
You can edit any of these values directly in the config file or via ModMenu.
Installation
Requirements:
- Minecraft >=1.17.1
- Fabric Loader >=0.11.3
- Fabric API >=0.83.0
You can download the mod from:
- GitHub Releases
- Modrinth
- CurseForge
- GitHub Actions (these builds may be unstable, but they represent the actual state of the development)

Packed Inventory
A Minecraft mod that attempts to mitigate the ever-growing Inventory Problem by making it possible to manage the contents of shulker boxes, ender chests, and more directly from your inventory.
Oh, we also have fancy tooltips for shulker boxes, ender chests, maps, and beyond!
Features
- Manage the inventory of shulker boxes without ever placing them.
- Manage the inventory of your ender chest without ever placing it.
- Quickly move items into or out of shulker boxes, ender chests, and other inventory-providing items.
- Access crafting tables, stonecutters, and other workstations directly from your inventory.
- Vanilla-like tooltips for shulker boxes.
- Vanilla-like tooltips for ender chests.
- Vanilla-like tooltips for filled maps.
- Vanilla-like tooltips for NBT-containing items acquired in Creative mode via
Ctrl + MMB, such as chests, barrels, furnaces, hoppers, dispensers, droppers, and more. - An extensive and simple API that helps other modders implement these features for their blocks and items.
Bundle-Like Functionality

As mentioned earlier, inventory-providing items (e.g., shulker boxes, ender chests, and any items registered via the Packed Inventory API) automatically gain bundle-like functionality, allowing you to quickly move items into or out of them.
To store items inside an inventory-providing item, you can either:
- Pick up the inventory-providing item and press
kon the item(s) to be stored, or - Pick up the inventory-providing item and press
kon the inventory-providing item(s) to be stored, or - Pick up the item(s) to be stored and press
kon the inventory-providing item.
To retrieve items from an inventory-providing item:
- Pick up the inventory-providing item and press
kon the empty slot(s) to extract the item(s) to, or - Pick up the inventory-providing item and press
lorctrl + kon the slot(s) to extract the item(s) to, or - Press
lorctrl + kon the inventory-providing item(s) to extract the items from.
To dump all items from an inventory-providing item out into the world:
- Pick up the inventory-providing item, move it outside of the inventory frame, and press
k.
Tooltips
Here are some tooltip examples for you:
- Container tooltip
- Colored container tooltip
- Compact container tooltip
- Filled map tooltip

More screenshots can be found here.
Key Binds
Key binds can be configured just like vanilla ones:
- Go to
Options. - Select
Controls. - Then choose
Key Binds. - Scroll down to the
Packed Inventorysection. - Configure the available key binds.
| Name | Description | Default |
|---|---|---|
Interact with item |
Interacts with the item in the active hotbar slot. Alternatively, if the inventory screen is open, interacts with the item the mouse is hovering over. Depending on the context, this action can either:
|
k |
Toggle interaction mode (hold) |
Makes the Interact with item key bind behave like Extract from item |
Left Control |
Extract from item |
Extracts an item from the selected inventory-providing item | l |
Invert tooltip visibility (hold) |
Inverts tooltip visibility while pressed | Left Shift |
Invert tooltip compact mode (hold) |
Inverts tooltip compact mode while pressed | c |
Note that it's totally fine for these key binds to interfere with others since they are applied only when your inventory screen is open, where other key binds usually do not work.
Config
If you have Cloth Config installed, you can customize the behavior of the mod. A config is usually located at ./config/packed-inventory.json and by default looks like this:
{
"defaultTooltipConfig": {
"showWhenEmpty": false,
"rows": -1,
"columns": -1,
"usePredefinedColor": false,
"enable": true,
"compact": false
},
"tooltips": {
"minecraft:shulker_box": {
"showWhenEmpty": false,
"rows": -1,
"columns": -1,
"usePredefinedColor": false,
"enable": true,
"compact": false
},
"minecraft:ender_chest": {
"syncInterval": 5000,
"showWhenEmpty": false,
"rows": -1,
"columns": -1,
"usePredefinedColor": false,
"enable": true,
"compact": false
},
"minecraft:filled_map": {
"size": 128,
"enable": false,
"compact": false
}
},
"defaultValidationConfig": {
"suppressValidationInCreative": true,
"requiresPlayerOnGround": true,
"enable": true
},
"validation": {
"minecraft:shulker_box": {
"suppressValidationInCreative": true,
"requiresPlayerOnGround": true,
"enable": true
},
"minecraft:ender_chest": {
"requiresSilkTouch": true,
"suppressValidationInCreative": true,
"requiresPlayerOnGround": true,
"enable": true
}
}
}
| Name | Description | Side | Default value |
|---|---|---|---|
tooltip.enable |
Indicates whether this tooltip should be enabled by default | client |
true |
tooltip.compact |
Indicates whether the compact mode should be enabled for this tooltip by default | client |
false |
tooltip.showWhenEmpty |
Indicates whether this tooltip should be shown when its content is empty | client |
false |
tooltip.rows |
Specifies the number of rows used to display the tooltip content | client |
-1 |
tooltip.columns |
Specifies the number of columns used to display the tooltip content | client |
-1 |
tooltip.usePredefinedColor |
Indicates whether this tooltip should use the item color | client |
false |
tooltip.color |
Specifies the default tooltip color in case usePredefinedColor is set to false or the item color cannot be automatically determined |
client |
NONE |
tooltip.syncInterval |
Specifies the frequency at which synchronization should occur | client |
5000 |
tooltip.size |
Specifies the size of this tooltip, if applicable | client |
128 |
| | | | |
validation.enable |
Indicates whether the action associated with this validation rule should be allowed | server |
true |
validation.suppressValidationInCreative |
Indicates whether this validation rule should be suppressed for creative players | server |
true |
validation.requiresPlayerOnGround |
Indicates whether a player should be on the ground in order to satisfy this validation rule | server |
true |
validation.requiresSilkTouch |
Indicates whether a player should have a tool enchanted with the Silk Touch enchantment in order to satisfy this validation rule | server |
true |
You can edit any of these values directly in the config file or via ModMenu.
Development
Dependency Installation
To use the API, add Packed Inventory as a dependency in your build script:
build.gradle:
repositories {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
content {
includeGroup "maven.modrinth"
}
}
}
dependencies {
modImplementation "maven.modrinth:packed-inventory:${project.packed_inventory_version}"
}
gradle.properties:
packed_inventory_version=/* version (e.g., 0.3.0+1.20.3) */
Entrypoints
The API introduces two new entrypoints that you can specify in your mod metadata:
| Name | Description | Interface | Side |
|---|---|---|---|
packed-inventory |
Will be run first and in any environment | PackedInventoryInitializer |
* |
packed-inventory-client |
Will be run second and only on the client side | PackedInventoryClientInitializer |
client |
fabric.mod.json:
{
"entrypoints": {
"packed-inventory": [
"a.b.c.MyMod"
],
"packed-inventory-client": [
"a.b.c.MyClientMod"
]
}
}
Inventory Views
Meet inventory views! This is the core concept of this mod that enables us to edit inventories provided by their respective items without ever interacting with their block forms.
Let's register a simple inventory viewer (the component that provides inventory views) for the ender chest item:
public class MyMod implements PackedInventoryInitializer {
@Override
public void registerInventoryViewers(InventoryViewerRegistry registry, PackedInventoryApiConfig config) {
registry.register(
// We need to "extract" an inventory from the given context.
// In this case, it's straightforward because ender chests have
// a shared inventory that can be retrieved from the player.
(inventory, slot, player) -> player.getEnderChestInventory(),
// While this absolutely could be a predicate -
// `(inventory, slot, player) -> inventory.getStack(slot).isOf(Items.ENDER_CHEST)`,
// this form is preferred.
Items.ENDER_CHEST
);
}
}
And that's it! You should be able to open the game, hover over an ender chest in your inventory, press k, and it will cause the inventory edit screen to pop up.
As for the next step, let's establish some rules to ensure our inventory viewer operates in a fair and non-cheaty way. To edit the ender chest inventory, a player should:
- Be on the ground, and
- Have a pickaxe enchanted with the Silk Touch enchantment, or
- Be in Creative mode.
To achieve this, we will use the InventoryValidators class, which contains some useful predefined inventory validators. Keep in mind that you can always create a new one from scratch.
public class MyMod implements PackedInventoryInitializer {
@Override
public void registerInventoryViewers(InventoryViewerRegistry registry, PackedInventoryApiConfig config) {
registry.register(
(inventory, slot, player) -> player.getEnderChestInventory(),
// isInCreative || isOnGround && hasSilkTouch
InventoryValidators.IS_IN_CREATIVE.or(
InventoryValidators.IS_ON_GROUND.and(InventoryValidators.HAS_PICKAXE_WITH_SILK_TOUCH)
),
Items.ENDER_CHEST
);
}
}
We're getting there! Now, you will see a friendly error message when attempting to open an ender chest in midair and/or without a pickaxe enchanted with the Silk Touch enchantment. However, the moment you switch to Creative mode, all restrictions will disappear.
One last thing to do is to make our inventory viewer configurable. After all, we have the config parameter for a reason ;)
public class MyMod implements PackedInventoryInitializer {
@Override
public void registerInventoryViewers(InventoryViewerRegistry registry, PackedInventoryApiConfig config) {
// Let's register a validation config entry for the Ender Chest item.
// The API provides these predefined configs (although you can create new ones):
// - ValidationConfig: can be enabled/disabled.
// - GenericValidationConfig: extends ValidationConfig, defines rules for being on the ground and suppressing validation for creative players.
// - SilkTouchableGenericValidationConfig: extends GenericValidationConfig, defines a rule for having a Silk Touch tool in the inventory.
config.registerValidationConfig(Items.ENDER_CHEST, SilkTouchableGenericValidationConfig::new);
// Inventory viewer may be completely disabled by the user in the config.
var isEnabled = InventoryValidators.config(Items.ENDER_CHEST, config, ValidationConfig.DEFAULT, ValidationConfig::isEnabled);
// Suppress validation for creative players only if the config says so.
var isInCreative = InventoryValidators.config(Items.ENDER_CHEST, config, GenericValidationConfig.DEFAULT, GenericValidationConfig::isSuppressedInCreative).and(InventoryValidators.IS_IN_CREATIVE);
// Require the player to be on the ground only if the config says so.
var isOnGround = InventoryValidators.config(Items.ENDER_CHEST, config, GenericValidationConfig.DEFAULT, x -> !x.requiresPlayerOnGround()).or(InventoryValidators.IS_ON_GROUND);
// Require the player to have a Silk Touch tool in their inventory only if the config says so.
var hasSilkTouch = InventoryValidators.config(Items.ENDER_CHEST, config, SilkTouchableGenericValidationConfig.DEFAULT, x -> !x.requiresSilkTouch()).or(InventoryValidators.HAS_PICKAXE_WITH_SILK_TOUCH);
registry.register(
(inventory, slot, player) -> player.getEnderChestInventory(),
isEnabled.and(isInCreative.or(isOnGround.and(hasSilkTouch))),
Items.ENDER_CHEST
);
}
}
This way, all restrictions can be configured via ModMenu or directly in the config file.
And after that, you've successfully integrated an item with Packed Inventory. Congratulations!
Inventory View Handlers
So, we've learned about inventory views, but where did that inventory edit screen come from? That's where the InventoryViewHandler comes in.
Most of the time, you do not need to register a custom handler if your inventory:
- Implements
NamedScreenHandlerFactory, or - Implements
ScreenHandlerFactory, or - Has a conventional size (i.e., 9, 18, 27, 36, 45, or 54) that can be processed by a
GenericContainerScreenHandler.
But, just as usual, you can register your own InventoryViewHandler:
public class MyMod implements PackedInventoryInitializer {
@Override
public void registerInventoryViewHandlers(InventoryViewHandlerRegistry registry, PackedInventoryApiConfig config) {
registry.register(
(inventoryView, parentInventory, slot, player) -> {
var name = parentInventory.getStack(slot).getName();
var playerInventory = player.getInventory();
var namedFactory = new SimpleNamedScreenHandlerFactory((sId, inv, p) -> new GenericContainerScreenHandler(ScreenHandlerType.GENERIC_9X3, sId, playerInventory, inventoryView, 3), name);
player.openHandledScreen(namedFactory);
},
Items.ENDER_CHEST
);
}
}
Note that you are not limited to just opening a handled screen; you can literally do whatever you want with the provided inventory view.
Inventory Validation Failure Handlers
So, we can customize inventory view handling, but what about failure handling? Of course, you can tweak that too.
By default, errors are sent to the corresponding player's action bar, but you can change this behavior:
public class MyMod implements PackedInventoryInitializer {
@Override
public void registerInventoryValidationFailureHandlers(InventoryValidationFailureHandlerRegistry registry, PackedInventoryApiConfig config) {
registry.register(
(failureReason, inventory, slot, player) -> {
var text = failureReason.toText();
if (text != null) {
player.sendMessage(text, false);
}
},
Items.ENDER_CHEST
);
}
}
Tooltips
What is good inventory management without descriptive tooltips? Let's create one for ender chests using TooltipProvider!
// Note that tooltips are completely client-side, so we use
// `PackedInventoryClientInitializer` instead of `PackedInventoryInitializer` here.
public class MyClientMod implements PackedInventoryClientInitializer {
@Override
public void registerTooltipProviders(TooltipProviderRegistry registry, PackedInventoryApiConfig config) {
registry.register(
TooltipProvider.builder()
.tooltipText((stack, context) -> List.of(Text.of("This is an ender chest")))
.build()
Items.ENDER_CHEST
);
}
}
This way, the ender chest's tooltip will be replaced with the text "This is an ender chest." However, this is not helpful, is it? The problem with ender chests is that the client does not have any information about their contents. So, is this a dead end? Of course not. We are going to use some magic:
public class MyClientMod implements PackedInventoryClientInitializer {
@Override
public void registerTooltipProviders(TooltipProviderRegistry registry, PackedInventoryApiConfig config) {
registry.register(
TooltipProvider.builder()
.useSyncData(GenericContainerTooltipSyncData::of)
.tooltipData((stack, context, syncData) -> GenericContainerTooltipData.of(syncData.getInventory()))
.build()
Items.ENDER_CHEST
);
}
}
After specifying that our TooltipProvider needs TooltipSyncData (in this case, I use the predefined GenericContainerTooltipSyncData because we only care about the ender chest's inventory), we can use it in the subsequent calls to tooltipData, tooltipText, etc. We'll delve into TooltipSyncData a bit later; for now, let's assume that everything just works.
Note that we override the ender chest's TooltipData with GenericContainerTooltipData. If you're not familiar with the vanilla treatment of this sort of things, when an item provides a TooltipData, Minecraft looks for a corresponding TooltipComponent. This component allows you to render anything you want inside a tooltip. GenericContainerTooltipData is provided by the API, so you don't need to worry about supplying the game with a tooltip component for it. However, if you want to use custom tooltip data, you'll need to register a tooltip component manually through Fabric API, like so:
TooltipComponentCallback.EVENT.register(tooltipData -> {
if (tooltipData instanceof MyTooltipData) {
return new MyTooltipComponent((MyTooltipData)tooltipData);
}
return null;
});
Alright, now we have a fancy tooltip that shows us the contents of the ender chest. Once again, it's time to make everything configurable:
public class MyClientMod implements PackedInventoryClientInitializer {
@Override
public void registerTooltipProviders(TooltipProviderRegistry registry, PackedInventoryApiConfig config) {
// Let's register a tooltip config entry for the Ender Chest item.
// The API provides these predefined configs (although you can create new ones):
// - TooltipConfig: can be enabled/disabled; compact mode can be switched on or off.
// - GenericTooltipConfig: extends TooltipConfig, defines properties commonly used by containers.
// - GenericSyncedTooltipConfig: extends GenericTooltipConfig, defines the `syncInterval` property used by tooltip providers requiring synchronization data.
config.registerTooltipConfig(Items.ENDER_CHEST, GenericSyncedTooltipConfig::new);
registry.register(
TooltipProvider.builder()
// Tooltip can be enabled/disabled in the config or by the key bind (`Left Shift` by default)
.when((stack, context) -> config.getTooltipConfigOrDefault(stack.getItem()).isEnabled())
.useSyncData(GenericContainerTooltipSyncData::of)
.tooltipData((stack, context, syncData) -> {
var cfg = config.getTooltipConfigOrDefault(stack.getItem());
var inventory = syncData.getInventory();
if (!cfg.shouldShowWhenEmpty() && inventory.isEmpty()) {
return null;
}
var color = cfg.usePredefinedColor() ? DyeColor.GRAY : cfg.color();
if (cfg.isCompact()) {
return GenericContainerTooltipData.ofZipped(inventory, cfg.rows(), cfg.columns(), color);
} else {
return GenericContainerTooltipData.of(inventory, cfg.rows(), cfg.columns(), color);
}
})
// Make the synchronization interval for this TooltipProvider configurable
.syncInterval(stack -> config.getTooltipConfigOrDefault(stack.getItem(), GenericSyncedTooltipConfig.DEFAULT).syncInterval())
.build(),
Items.ENDER_CHEST
);
}
}
Tooltip Sync Data Providers
As mentioned earlier, to make the example above work, we need some information from the server. That's where TooltipSyncData and TooltipSyncDataProviders come into play.
We already use GenericContainerTooltipSyncData in our ender chest's tooltip provider, so let's go back to the server and teach it how to handle it:
public class MyMod implements PackedInventoryInitializer {
@Override
public void registerTooltipSyncDataProviders(TooltipSyncDataProviderRegistry registry, PackedInventoryApiConfig config) {
registry.register(
// On the server side, we need to create the same TooltipSyncData
// and populate it with contents that are not present on the client.
// Everything else will be handled by Packed Inventory automatically.
(stack, player) -> GenericContainerTooltipSyncData.of(player.getEnderChestInventory()),
Items.ENDER_CHEST
);
}
}
With just a few lines of code, everything works as expected.
Installation
Requirements:
- Minecraft
1.20.x - Fabric Loader
>=0.15.0 - Fabric API
>=0.83.0
You can download the mod from:
- GitHub Releases
- Modrinth
- CurseForge
- GitHub Actions (these builds may be unstable, but they represent the actual state of the development)
Building from sources
Requirements:
- JDK
17
Linux/MacOS
git clone https://github.com/Kir-Antipov/packed-inventory.git
cd packed-inventory
chmod +x ./gradlew
./gradlew build
cd build/libs
Windows
git clone https://github.com/Kir-Antipov/packed-inventory.git
cd packed-inventory
gradlew build
cd build/libs
Screenshots
Gallery
Versions
Files
Relations
Project Relations
More like this
Similar Mods
Suggestions use data such as tags, dependencies, dependents, descriptions, titles, and more to rank how much they overlap with this mod.
On ModDex
Community snapshot
By the numbers
Statistics
Want to reach Minecraft players?
We're looking for a server hosting partner to feature here and other parts of the site. Interested? Send us a message!
Get in touchGet it on
Available Platforms
On ModDex
Community snapshot
By the numbers