InfiniteBags | Backpack with Shop 1.3.0
Unlimited per-item storage with a built-in shop hook to sell straight from your bag.
Two new API methods, so another plugin can read what a bag holds and take items back out of it.
🔌 Reading and Removing
Until now the developer API could only put items into a bag. These two methods let another plugin on your server take them back out, which is what makes a bag usable as a live source of blocks or materials rather than just storage.
long count(UUID player, ItemStack item)
int remove(UUID player, ItemStack item)
countreturns how many of that item type the bag holds. The amount on the item you pass in is ignored. It returns along, because a well-stocked bag can hold more of one type than anintcan expressremovetakes items of that type back out, with the amount on the item you pass in being the quantity to take. It returns how many were actually removed
✂️ Removal Is Partial, On Purpose
Unlike add, which is all or nothing, remove takes what is there. Ask for 5 against a bag holding 3 and you get 3 taken and 3 returned, so the caller can cover the shortfall itself. The return value is always between 0 and the amount you asked for, never more.
A slot drained to zero is deleted rather than left sitting empty, so it frees up for a different item type straight away.
📌 Worth Knowing
- Same grouping as the rest of the API (material plus full NBT hash), so
count(...) > 0is exactly equivalent tocontains(...). A renamed or enchanted block is a different type and is never consumed to satisfy a request for the plain one - Both work offline and are locked per player, like the rest of the API. They are async-safe, touching only the database and in-memory data
- Neither runs a permission check internally. Call
isEnabled(uuid)yourself if you want that gate - Both see items on pages or slots the player's current permissions no longer reach, the ones
/bag recoverexposes, so everythingcountreports is somethingremovecan actually hand over - Null or air items, and null UUIDs, return
0. No exceptions - Calling the API by reflection is supported and now documented
📦 Install
Stop the server, replace the old jar in plugins/ with InfiniteBags-1.3.0.jar, and start it again. No existing method changed behaviour and the storage is untouched, so your bags carry over exactly as they are and anything already built against the API keeps working unchanged.
Join the Discord
Enjoying the plugin? A ⭐ review goes a long way!
Localized bag item names for every player, plus new snapshot methods for the developer API.
🌐 Client-Localized Item Names
Item names in the bag and recovery menus now show in each player's own game language. An un-renamed item renders its vanilla name localized to the viewer, instead of a fixed English string. Items you've given a custom name keep that name. (The GUI search filter still matches the English material name, by design.)
🧩 Developer API: Bag Snapshots
Two new read-only methods let companion plugins (like AT-MailBox) snapshot a bag once and test items against it later, without re-reading the live bag each time.
String typeKey(ItemStack item)the bag's grouping key for an item (material plus full NBT, amount ignored), ornullfor a null/air item. Same "same type" rule thatcontainsuses.Set<String> contentKeys(UUID player)a plain-value snapshot of the grouping keys of every type currently in the player's bag. Safe to keep, persist, and compare later.
Checking whether typeKey(item) is in a saved contentKeys set answers "was this type in the bag at snapshot time?"
- Both work offline (UUID-keyed database read) and are per-UUID locked, like the rest of the API. Async-safe, no world or entity calls.
- No write path or existing method behavior changed, so existing integrations keep working unchanged.
Full details on the Developer API page, including the methods table and a "Snapshotting a bag" section.
📦 Install
Replace the jar in plugins/ and restart. No config changes needed.
📋 Version Breakdown
| Version | Focus |
1.2.3 |
New read-only API methods (typeKey, contentKeys) so companion plugins can snapshot a bag and compare later. |
1.2.2 |
Bag and recovery menu item names now render in each viewer's own game language. |
Read the Developer API guide | Join the Discord
Enjoying the plugin? A ⭐ review goes a long way!
Patch release, fixes a storage dupe when an auto-collector plugin is installed alongside InfiniteBags.
🔧 Fixed
Dropping an item out of the bag at a full inventory spawns a world item with no thrower, which looked identical to a real overflow drop. An external auto-collector plugin (like a mailbox) could vacuum that item back into its own storage, duping it out of the bag.
InfiniteBags now stamps every bag-withdrawal drop with a persistent marker (infinitebags:bag_drop) the instant it spawns, so cooperating plugins can tell it apart and leave it alone. The marker is set before the item enters the world, so spawn-time listeners see it.
🧩 Compatibility
Spigot, Paper, and Purpur on Minecraft 1.21.x. A drop-in upgrade with no config changes, and the v1.2.0 developer API is unchanged.
📦 Install
Just replace your old jar with the new one and restart. No config changes needed.
Read the documentation | Join the Discord
Enjoying the plugin? A ⭐ review goes a long way!
An optional developer API so other plugins can read and write a player's bag.
✨ What's New
This release adds an optional developer API so other plugins can read and write a player's bag at runtime. No hard dependency and no extra jar to install, it's soft-depend friendly and ships inside the normal plugin jar.
🖥 For Server Owners
- Nothing to configure. A drop-in upgrade from 1.1.x, with no config or language changes.
- Better integrations. Other plugins you install (mail systems, reward systems, custom shops) can now deposit items straight into a player's bag, even while they're offline.
🧩 For Developers
A new InfiniteBagAPI (in cc.arrowtan.infiniteBags.api) with four methods:
isEnabled(UUID)can the player use their bagaccepts(ItemStack)would the bag store this item typecontains(UUID, ItemStack)does the bag already hold this exact typeadd(UUID, ItemStack)store an item, returns the amount that did not fit
Also:
- Static accessor
InfiniteBag.getApi()(null-checked, soft-depend safe) - Works offline (UUID-keyed database access) and is async-safe (per-UUID locked, touches only database and bag data)
- Strict item grouping: matches full material plus NBT (name, enchants, damage, custom model data), not just material
📦 Install
Replace the jar in plugins/ and restart. No config or language changes needed.
Read the Developer API guide | Join the Discord
Enjoying the plugin? A ⭐ review goes a long way!
Bag item survives /clear
Fixed
The bag item used to vanish when an inventory was wiped by command, since /clear edits inventories directly and skips the events the plugin listens to. It now restores one tick after the wipe.
Survives:
- Vanilla
/clear - EssentialsX
/clearinventory,/ci,/clean,/clearinvent - Namespaced forms (
minecraft:clear,essentials:ci, etc.) - Player-typed, console, and command-block execution
Config
New keys under bag-item (auto-added on upgrade):
restore-on-clear- toggle (defaulttrue)clear-commands- which command names trigger a restore. Case-insensitive, namespace-insensitive, first-word match.
If InfiniteBags has been useful, a review goes a long way.
CustomModelData pricing for custom items
What's New
- CustomModelData pricing in
shopworth.yml. Newcmd-prices:section using the formatMATERIAL:CMD: price. - Lookup order: CMD match first, then NBT match, then simple material match.
- Works with ItemsAdder, Nexo, Oraxen, MMOItems, and plain resource-pack items. Zero soft-depends added.
Example Config
cmd-prices:
DIAMOND_SWORD:1001: 500.0
PAPER:2050: 25.0
STICK:9999: 10000.0
Upgrade Notes
- Fresh installs: the new
cmd-prices:section appears automatically with commented examples. - Existing installs:
shopworth.ymluses plain Bukkit YAML, so the section will not auto-insert. Either hand-paste the new section into your file, or deleteshopworth.ymlto let it regenerate. - This only affects the local provider. To use CMD pricing through UltimateShop, ShopGUI+, EconomyShopGUI, or EssentialsX, you will need a separate per-provider hook (planned for a future update).
How to Find a CustomModelData
Hold the item in your main hand and run:
/data get entity @s SelectedItem
Look for CustomModel1234 in the output. That number is your CMD value.
Statistics
Views
Purchases
Downloads
File size
Published
Updated
Info
Share & Earn
Share and earn part of the profits, an estimated €0.5 per product sale.