See it running
The short version
- Godot 4 plugin made for a client: Tarkov-style grid inventory with Pockets, Stash, equipment, nested bags, and a hotbar.
- Designers add items in the Inspector. No script required to add a medkit, backpack, or magazine.
- 3D world only sends an id. Cameras and raycasts stay in the game; inventory stays in the plugin.
- Belt is real storage: extra hotbar slots belong to the belt, so unequip does not dump items.
- 152 unit tests (549 asserts) on placement, persistence, pickup, and belt storage.
- Not on the Asset Library yet. Split-stack UI and player-facing tooltips are still open.
What it does
- Tab overlay: Pockets, Stash, equipment, character preview; hotbar stays on screen
- Items occupy cells by shape (1x1 through L and T). Rotate with R. Green if it fits, red if not
- Equip helmet, vest, belt, backpack, rig, primary and secondary. Occupied slots reject a second drop
- Equipping a backpack or chest rig opens that bag’s grid. Unequip keeps the contents inside the bag
- Belt grows the hotbar. Extra slots belong to the belt, so taking it off never dumps loot on the floor
- Drop into a closed bag without opening it. Nested bags cannot contain themselves (depth cap 8)
- 3D pickup: WASD, E, Tab, Esc. Raycast reads an id; inventory decides where the item lands
- Right-click: Open, Customize (attachments), Use, Combine, Drop. New items are editor data, not scripts
- 152 unit tests, 549 asserts: placement, save/load, pickup routing, belt storage
Built for a client
Made for a client from a written spec: a drop-in Godot inventory plugin. I owned the addon, the designer workflow, and the tests. Nested bags, equipment, belt-backed hotbar, and 3D pickup. Their game talks to it through an id.
The thought
A client needed a grid inventory a designer can fill without calling a programmer. This plugin is that piece: items on a grid, bags that hold bags, equipment slots, a hotbar backed by the belt, and a 3D pickup demo that never lets the world own the UI.
Mechanics
Tab opens the overlay. Left column is storage: Pockets on top, Stash below. Equipping a backpack or chest rig adds that bag’s grid under Pockets. Center is equipment: Helmet, Vest, Belt, Backpack, Rig, plus Primary and Secondary weapons. The hotbar stays at the bottom whether the overlay is open or closed. Esc frees the cursor so you can drag without turning the camera. Click an item to pick it up. It follows the cursor. R rotates 90 degrees. Cells light green if it fits, red if it does not. Type and tag filters block illegal drops. A failed drop goes back where it started. Occupied equip slots reject a second item; you unequip first. Right-click opens Open / Customize / Use / Combine / Drop. Storage bags open as floating windows. Weapons open an attachments panel instead of a bag. You can still drop into a closed bag: hover shows the footprint, a valid drop inserts without opening the window. Number keys use the hotbar. Base size is 4. Equip a belt and extra slots appear. Those slots are the belt’s own cells, so taking the belt off keeps every item inside it.
Systems
Each item has two layers. The definition is the template in the editor: size, filters, whether it is a bag, attachment mounts, charges, durability. The instance is what exists in play: stack count, rotation, grid cell, rolled stats, and whatever is stored inside it. A coordinator finds every open grid and slot and hit-tests from the top window down, so a bag on top of the backpack wins the click. Nested bags cannot contain themselves. Depth stops at 8. Closing a parent bag closes the windows inside it. Pickup walks a priority list: top up matching stacks first, then best-fit a free cell, then report no room. Save/load writes a versioned JSON snapshot of the whole graph, including bags sitting in the 3D world.
Under the hood
It ships as a Godot editor plugin. Grids preview live in the Inspector. Sample items, shapes, and loadouts ship with the addon so a team can run the demos without making art first. The inventory code never touches cameras or raycasts. In the 3D demo, looking at loot reads an id, an adapter turns that id into the real item, and the coordinator decides which grid it lands in. World code stays world code. UI stays UI. Tests: 152 passing, 549 asserts, across placement, persistence, pickup routing, belt storage, and a parse gate. Still open: split-stack UI, a player-facing tooltip panel, and an Asset Library listing.
Controls
How it came together
Core grids
Definition vs instance split, multi-grid drag, rotation, filters, nested bags, silent transfer into closed containers.
Full screen
Pockets, Stash, non-grid equip slots, backpack/rig binders, persistent hotbar. Tab overlay on a 3D demo.
Capability pass
Save/load, pickup routing, combine recipes, rolled stats, layout profiles. GUT suite brought to 152/152.
Belt storage
Belt-granted hotbar slots write into the belt itself, so unequip never spills or deletes items.
What I would do differently
If a designer needs a script to add a medkit, the plugin failed. The belt bug was the same lesson: extra hotbar slots that do not belong to an item will spill on unequip. Tests caught rotation and nested-bag cases that playtesting missed. Next step is a clean addon repo, not more demo content.