Install
$ agentstack add skill-jame581-godotprompter-inventory-system ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Inventory Systems in Godot 4.3+
All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.
> Related skills: resource-pattern for custom Resource data containers, save-load for inventory serialization, event-bus for inventory change notifications, hud-system for inventory UI display.
1. Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ UI Layer │
│ InventoryUI (Control) │
│ └─ GridContainer │
│ └─ SlotUI × N (Button) │
│ └─ TextureRect (icon) + Label (qty) │
│ │
│ Connects to: inventory_changed signal │
│ Drag-and-drop via _get_drag_data / _drop_data │
└───────────────────────┬─────────────────────────────────┘
│ reads / mutates
┌───────────────────────▼─────────────────────────────────┐
│ Inventory (Node) │
│ slots: Array[InventorySlot] │
│ add_item(item, qty) → leftover: int │
│ remove_item(item, qty) │
│ has_item(item, qty) → bool │
│ get_item_count(item) → int │
│ │
│ signals: inventory_changed │
│ item_added(item, quantity) │
│ item_removed(item, quantity) │
└───────────────────────┬─────────────────────────────────┘
│ references
┌───────────────────────▼─────────────────────────────────┐
│ Data Layer (Resources) │
│ ItemData (Resource) │
│ id, name, description, icon, max_stack_size, │
│ item_type enum │
│ │
│ InventorySlot (inner class / Resource) │
│ item: ItemData, quantity: int │
└─────────────────────────────────────────────────────────┘
2. ItemData Resource
Define items as Resources so they live in .tres files, are shareable across scenes, and benefit from full editor integration.
GDScript
# item_data.gd
class_name ItemData
extends Resource
enum ItemType {
CONSUMABLE,
EQUIPMENT,
MATERIAL,
KEY_ITEM,
}
@export var id: String = ""
@export var name: String = ""
@export var description: String = ""
@export var icon: Texture2D
@export var max_stack_size: int = 99
@export var item_type: ItemType = ItemType.MATERIAL
Create item assets: res://items/potion_health.tres, set id = "potion_health", etc.
C#
// ItemData.cs
using Godot;
[GlobalClass]
public partial class ItemData : Resource
{
public enum ItemType
{
Consumable,
Equipment,
Material,
KeyItem,
}
[Export] public string Id { get; set; } = "";
[Export] public string Name { get; set; } = "";
[Export] public string Description { get; set; } = "";
[Export] public Texture2D Icon { get; set; }
[Export] public int MaxStackSize { get; set; } = 99;
[Export] public ItemType Type { get; set; } = ItemType.Material;
}
> Use [GlobalClass] so the Inspector dropdown shows ItemData as a resource type when creating .tres files.
3. Inventory Class
GDScript
# inventory.gd
class_name Inventory
extends Node
signal inventory_changed
signal item_added(item: ItemData, quantity: int)
signal item_removed(item: ItemData, quantity: int)
@export var capacity: int = 20
var slots: Array[InventorySlot] = []
func _ready() -> void:
slots.resize(capacity)
for i in capacity:
slots[i] = InventorySlot.new()
# Returns the number of items that could NOT be added (leftover).
func add_item(item: ItemData, quantity: int = 1) -> int:
var remaining := quantity
# Fill existing stacks first
for slot in slots:
if remaining 0:
item_added.emit(item, added)
inventory_changed.emit()
return remaining
func remove_item(item: ItemData, quantity: int = 1) -> void:
var remaining := quantity
for slot in slots:
if remaining 0:
item_removed.emit(item, actually_removed)
inventory_changed.emit()
func has_item(item: ItemData, quantity: int = 1) -> bool:
return get_item_count(item) >= quantity
func get_item_count(item: ItemData) -> int:
var total := 0
for slot in slots:
if not slot.is_empty() and slot.item == item:
total += slot.quantity
return total
C#
// Inventory.cs
using Godot;
using Godot.Collections;
public partial class Inventory : Node
{
[Signal] public delegate void InventoryChangedEventHandler();
[Signal] public delegate void ItemAddedEventHandler(ItemData item, int quantity);
[Signal] public delegate void ItemRemovedEventHandler(ItemData item, int quantity);
[Export] public int Capacity { get; set; } = 20;
public Array Slots { get; private set; } = new();
public override void _Ready()
{
for (int i = 0; i Returns the number of items that could NOT be added (leftover).
public int AddItem(ItemData item, int quantity = 1)
{
int remaining = quantity;
// Fill existing stacks first
foreach (var slot in Slots)
{
if (remaining 0)
{
EmitSignal(SignalName.ItemAdded, item, added);
EmitSignal(SignalName.InventoryChanged);
}
return remaining;
}
public void RemoveItem(ItemData item, int quantity = 1)
{
int remaining = quantity;
foreach (var slot in Slots)
{
if (remaining 0)
{
EmitSignal(SignalName.ItemRemoved, item, actuallyRemoved);
EmitSignal(SignalName.InventoryChanged);
}
}
public bool HasItem(ItemData item, int quantity = 1)
=> GetItemCount(item) >= quantity;
public int GetItemCount(ItemData item)
{
int total = 0;
foreach (var slot in Slots)
if (!slot.IsEmpty() && slot.Item == item)
total += slot.Quantity;
return total;
}
}
4. InventorySlot
InventorySlot is a lightweight object tracking an item reference and its quantity. Define it as an inner class on Inventory (GDScript) or as a standalone RefCounted subclass (C#).
GDScript
# inventory_slot.gd — or nest as inner class inside inventory.gd
class_name InventorySlot
extends RefCounted
var item: ItemData = null
var quantity: int = 0
func is_empty() -> bool:
return item == null or quantity bool:
return not is_empty() and item == new_item and quantity int:
if item == null:
push_error("InventorySlot.add_to_stack: slot has no item assigned")
return amount
var space := item.max_stack_size - quantity
var to_add := mini(amount, space)
quantity += to_add
return amount - to_add
# Removes amount from this slot. Clears the slot when quantity reaches zero.
func remove_from_stack(amount: int) -> void:
quantity -= amount
if quantity Item == null || Quantity !IsEmpty() && Item == newItem && Quantity Adds amount to this slot. Returns leftover that did not fit.
public int AddToStack(int amount)
{
if (Item == null)
{
GD.PushError("InventorySlot.AddToStack: slot has no item assigned");
return amount;
}
int space = Item.MaxStackSize - Quantity;
int toAdd = Mathf.Min(amount, space);
Quantity += toAdd;
return amount - toAdd;
}
/// Removes amount from this slot. Clears when quantity reaches zero.
public void RemoveFromStack(int amount)
{
Quantity -= amount;
if (Quantity See [references/equipment.md](references/equipment.md) for the full GDScript and C# `Equipment` class with `EquipmentSlotType` enum, equip / unequip API, and stat aggregation.
---
## 6. UI Binding
Slot-grid UI: a `GridContainer` of `Panel` slot widgets, each rendering one `InventorySlot`. Drag-and-drop uses `_get_drag_data` / `_drop_data` / `_can_drop_data` on the slot widget. The Inventory emits `inventory_changed`; the UI re-renders affected slots.
> See [references/ui-binding.md](references/ui-binding.md) for the full GDScript and C# slot widget (drag/drop, hover preview), inventory grid layout, and tooltip wiring.
---
## 7. Serialization
Persist Inventory + Equipment as a Dictionary keyed by item resource path (since ItemData lives at `res://items/.tres`). Reload by `load(path)` and reconstructing the slot list. Version field gates migration on load.
> See [references/serialization.md](references/serialization.md) for the GDScript and C# save/load implementation with `version` field and ConfigFile / JSON variants.
---
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [jame581](https://github.com/jame581)
- **Source:** [jame581/GodotPrompter](https://github.com/jame581/GodotPrompter)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.