InventoryPlugin¶
Manages player's inventory and item collection with a visual grid overlay.
Location¶
- Implementation: src/pedre/plugins/inventory/plugin.py
- Base class: src/pedre/plugins/inventory/base.py
- Events: src/pedre/plugins/inventory/events.py
- Actions: src/pedre/plugins/inventory/actions.py
- Conditions: src/pedre/plugins/inventory/conditions.py
Configuration¶
The InventoryPlugin uses the following settings from pedre.conf.settings:
Grid Layout Settings¶
INVENTORY_GRID_COLS- Number of columns in inventory grid (default: 4)INVENTORY_GRID_ROWS- Number of rows in inventory grid (default: 3)INVENTORY_BOX_SIZE- Size of each inventory slot in pixels (default: 100)INVENTORY_BOX_SPACING- Spacing between inventory slots in pixels (default: 15)INVENTORY_BOX_BORDER_WIDTH- Border width for inventory slots in pixels (default: 3)
Capacity and Display Settings¶
INVENTORY_MAX_SPACE- Maximum number of items the inventory can hold (default: 12)INVENTORY_CAPACITY_FONT_SIZE- Font size for capacity counter (default: 14)INVENTORY_BACKGROUND_IMAGE- Path to background image (optional, default: "")
Data and Input Settings¶
INVENTORY_ITEMS_FILE- Path to JSON file with item definitions (default: "data/inventory_items.json")INVENTORY_KEY_TOGGLE- Key to open/close the inventory overlay (default: "I")INVENTORY_KEY_VIEW- Key to view selected item in detail (default: "V")INVENTORY_KEY_CONSUME- Key to consume selected item (default: "C")
Hint Text Settings¶
INVENTORY_HINT_VIEW- Hint text for viewing items (default: "[V] View")INVENTORY_HINT_CONSUME- Hint text for consuming items (default: "[C] Consume")INVENTORY_HINT_FONT_SIZE- Font size for hint text (default: 12)
These can be overridden in your project's settings.py:
# Custom inventory settings
INVENTORY_GRID_COLS = 6
INVENTORY_GRID_ROWS = 4
INVENTORY_BOX_SIZE = 80
INVENTORY_MAX_SPACE = 24
INVENTORY_ITEMS_FILE = "data/items.json"
Public API¶
Item Management¶
acquire_item¶
acquire_item(item_id: str) -> bool
Mark an item as acquired by the player.
Parameters:
item_id- Unique identifier of the item to acquire
Returns:
Trueif the item was newly acquired,Falseif the item was not found, was already acquired, or inventory is at capacity
Example:
# When player picks up an item
if inventory_plugin.acquire_item("ancient_scroll"):
# Item was newly acquired
show_notification("Found: Ancient Scroll!")
else:
# Item was already owned, doesn't exist, or inventory is full
pass
Notes:
- The method enforces inventory capacity limits
- Publishes
ItemAcquiredEventwhen item is newly acquired - Publishes
ItemAcquisitionFailedEventif acquisition fails - Returns
Falseif item doesn't exist in the registry
consume_item¶
consume_item(item_id: str) -> bool
Mark an item as consumed by the player.
Parameters:
item_id- Unique identifier of the item to consume
Returns:
Trueif the item was successfully consumed,Falseif the item doesn't exist, hasn't been acquired, or was already consumed
Example:
# When player uses a consumable item
if inventory_plugin.consume_item("health_potion"):
# Item was consumed successfully
restore_player_health(50)
else:
# Item couldn't be consumed (not available)
show_message("You don't have that item!")
Notes:
- Only works on items that have been acquired
- Consumed items no longer appear in the inventory display
- Publishes
ItemConsumedEventwhen successful
add_item¶
add_item(item: InventoryItem) -> bool
Add a new item to the inventory plugin and optionally acquire it.
Parameters:
item- TheInventoryItemto add to the plugin
Returns:
Trueif the item was successfully added,Falseif an item with that ID already exists or if adding it would exceed inventory capacity
Example:
from pedre.plugins.inventory.base import InventoryItem
import uuid
# Add a health potion that's immediately available
potion = InventoryItem(
id=str(uuid.uuid4()), # Generate unique ID
name="Health Potion",
description="Restores 50 HP",
icon_path="items/potion.png",
category="consumable",
acquired=True,
consumable=True
)
if inventory_plugin.add_item(potion):
show_notification("Found: Health Potion!")
Notes:
- Allows dynamically adding items not defined in
inventory_items.json - Useful for consumable items obtained through gameplay
- If
acquired=True, publishesItemAcquiredEvent - Checks inventory capacity before adding
has_item¶
has_item(item_id: str) -> bool
Check if the player has acquired a specific item.
Parameters:
item_id- Unique identifier of the item to check
Returns:
Trueif the player has acquired the item,Falseif the item doesn't exist or hasn't been acquired
Example:
# Check for key before allowing door interaction
if inventory_plugin.has_item("tower_key"):
unlock_door("tower_entrance")
dialog_plugin.show_dialog("Info", ["The key fits perfectly!"])
else:
dialog_plugin.show_dialog("Info", ["The door is locked."])
Notes:
- Pure query method with no side effects
- Doesn't modify state or trigger events
- Consumed items return
False
State Queries¶
has_been_accessed¶
has_been_accessed() -> bool
Check if inventory has been accessed by the player.
Returns:
Trueif the player has opened the inventory at least once,Falseotherwise
Example:
Notes:
- Used for tutorial progression
- Flag is set when inventory overlay is first opened
- Persists through save/load
Save/Load Support¶
get_save_state¶
get_save_state() -> dict[str, Any]
Return serializable state for saving.
Returns:
- Dictionary containing inventory state
Example:
save_data = {
"player_position": (x, y),
"inventory": inventory_plugin.get_save_state(),
# ... other save data
}
restore_save_state¶
restore_save_state(state: dict[str, Any]) -> None
Restore state from save data.
Parameters:
state- Dictionary containing saved inventory state
Example:
Notes:
- Restores item acquired/consumed flags and accessed state
- Dynamically added items are recreated from save data
Plugin Lifecycle¶
setup¶
setup(context: GameContext) -> None
Initialize the inventory plugin with game context.
Parameters:
context- Game context providing access to event bus
Notes:
- Called automatically by the PluginLoader
- Loads items from
INVENTORY_ITEMS_FILE
cleanup¶
cleanup() -> None
Clean up inventory resources when the scene unloads.
Notes:
- Clears all items and resets accessed flag
- Called automatically by the PluginLoader
reset¶
reset() -> None
Reset inventory state for new game.
Notes:
- Clears items, accessed flag, and overlay state
- Reloads default items from JSON
on_key_press¶
on_key_press(symbol: int, modifiers: int) -> bool
Handle key presses for inventory overlay.
Parameters:
symbol- Arcade key constantmodifiers- Modifier key bitfield
Returns:
Trueif input was consumed,Falseotherwise
Notes:
- Called automatically by the PluginLoader
- Press the configured
INVENTORY_KEY_TOGGLEkey (default:I) to open the inventory overlay - Arrow keys navigate the grid
INVENTORY_KEY_VIEW(default:V) views selected item in detailINVENTORY_KEY_CONSUME(default:C) consumes selected itemESCcloses overlay
on_draw_ui¶
on_draw_ui() -> None
Draw the inventory overlay in screen coordinates.
Notes:
- Called automatically by the PluginLoader during UI draw phase
- Renders grid, items, hints, and capacity counter
Inventory Items¶
InventoryItem Data Class¶
Items are defined using the InventoryItem dataclass:
@dataclass
class InventoryItem:
id: str # Unique identifier
name: str # Display name
description: str # Item description
image_path: str | None # Path to full-size image (optional)
icon_path: str | None # Path to icon/thumbnail (optional)
category: str # Item category (default: "general")
acquired: bool # Whether player has this item (default: False)
consumed: bool # Whether item has been used (default: False)
consumable: bool # Whether item can be consumed (default: False)
Attributes:
id- Unique identifier (e.g., "secret_key", "photo_01"). Used for lookups, save data, and script references.name- Display name shown to the player (e.g., "Rusty Key", "Family Photo")description- Flavor text or description shown when examining the itemimage_path- Optional path to full-size image file, relative toassets/. Displayed when viewing item in detail.icon_path- Optional path to icon/thumbnail, relative toassets/. Displayed in inventory grid.category- Item category for filtering (e.g., "photo", "note", "key", "potion", "general")acquired- Whether the player has collected this itemconsumed- Whether the item has been consumed/usedconsumable- Whether the item can be consumed from the inventory overlay UI
Example:
# A collectible photograph
photo = InventoryItem(
id="beach_memory",
name="Beach Day",
description="A sunny day at the coast with friends.",
image_path="photos/beach.jpg",
icon_path="photos/icons/beach_icon.png",
category="photo",
acquired=False
)
# A consumable item
potion = InventoryItem(
id="health_potion_1",
name="Health Potion",
description="Restores 50 HP",
icon_path="items/potion.png",
category="consumable",
acquired=True,
consumable=True
)
Item Definition File¶
Items are typically loaded from a JSON file specified by INVENTORY_ITEMS_FILE:
{
"items": [
{
"id": "golden_key",
"name": "Golden Key",
"description": "A shiny key that opens the tower door.",
"image_path": "items/golden_key.png",
"icon_path": "items/icons/key_icon.png",
"category": "key",
"acquired": false
},
{
"id": "beach_photo",
"name": "Beach Memory",
"description": "A sunny day at the coast.",
"image_path": "photos/beach.jpg",
"icon_path": "photos/icons/beach_icon.png",
"category": "photo",
"acquired": false
},
{
"id": "health_potion",
"name": "Health Potion",
"description": "Restores 50 HP",
"icon_path": "items/icons/potion.png",
"category": "consumable",
"acquired": false,
"consumable": true
}
]
}
Notes:
- All fields except
id,name, anddescriptionare optional - Items default to
acquired=falseandconsumable=false - Paths are relative to the assets directory
Events¶
ItemAcquiredEvent¶
Published when player acquires an inventory item for the first time.
Attributes:
item_id: str- Unique identifier of the acquired itemitem_name: str- Display name of the item
Script Trigger Example:
{
"trigger": {
"event": "item_acquired",
"item_id": "rusty_key"
},
"actions": [
{"type": "dialog", "speaker": "Narrator", "text": ["You found a key!"]}
]
}
Notes:
- Only fires when item transitions from unacquired to acquired
- Filter by
item_idis optional (omit to trigger for any item)
ItemAcquisitionFailedEvent¶
Published when an attempt to acquire an item fails.
Attributes:
item_id: str- Unique identifier of the itemreason: str- Reason for failure:"capacity","unknown_item", or"already_owned"
Script Trigger Example:
{
"trigger": {
"event": "item_acquisition_failed",
"reason": "capacity"
},
"actions": [
{"type": "dialog", "speaker": "Narrator", "text": ["Your inventory is full!"]}
]
}
Use Cases:
- Showing feedback when inventory is full
- Handling unknown item errors
- Preventing duplicate acquisition notifications
ItemConsumedEvent¶
Published when player consumes an inventory item.
Attributes:
item_id: str- Unique identifier of the consumed itemitem_name: str- Display name of the itemcategory: str- Category of the consumed item
Script Trigger Example:
{
"trigger": {
"event": "item_consumed",
"item_id": "health_potion_1"
},
"actions": [
{"type": "dialog", "speaker": "Narrator", "text": ["You feel refreshed!"]}
]
}
Filter by category:
{
"trigger": {
"event": "item_consumed",
"category": "consumable"
},
"actions": [
{"type": "play_sfx", "sound": "potion_drink.wav"}
]
}
Notes:
- Triggers when item is consumed from the inventory overlay or via script action
- Can filter by
item_id,category, or both
InventoryClosedEvent¶
Published when the inventory view is closed by the player.
Attributes:
has_been_accessed: bool- Whether inventory has been accessed before
Script Trigger Example:
{
"trigger": {
"event": "inventory_closed"
},
"conditions": [
{
"check": "inventory_accessed",
"equals": true
}
],
"actions": [
{"type": "dialog", "speaker": "Tutorial", "text": ["Good job checking your inventory!"]}
]
}
Use Cases:
- Tutorial progression
- Achievement triggers
- First-time inventory checks
Actions¶
AcquireItemAction¶
Give an item to the player's inventory.
Type: acquire_item
Parameters:
item_id: str- Unique identifier of the item to acquire
Example:
In a script after finding a treasure chest:
{
"actions": [
{"type": "dialog", "speaker": "Narrator", "text": ["You found a key!"]},
{"type": "acquire_item", "item_id": "tower_key"},
{"type": "wait_for_dialog_close"}
]
}
Notes:
- The item must already be defined in the inventory plugin
- Publishes
ItemAcquiredEventon success - Publishes
ItemAcquisitionFailedEventon failure - Returns
Falseand blocks script progression if acquisition fails
AddItemAction¶
Add a new item to the inventory plugin.
Type: add_item
Parameters:
name: str- Display name of the item (required)description: str- Description text for the item (required)item_id: str- Unique identifier (optional, auto-generates UUID if omitted)image_path: str- Path to full-size image (optional)icon_path: str- Path to icon/thumbnail (optional)category: str- Item category (default: "general")acquired: bool- Whether item is immediately acquired (default: true)consumable: bool- Whether item can be consumed (default: false)
Example without item_id (UUID auto-generated):
{
"type": "add_item",
"name": "Health Potion",
"description": "Restores 50 HP",
"icon_path": "items/potion.png",
"category": "potion",
"consumable": true,
"acquired": true
}
Example with explicit item_id:
{
"type": "add_item",
"item_id": "rusty_key",
"name": "Rusty Key",
"description": "Opens an old door",
"icon_path": "items/key.png",
"category": "key",
"acquired": true
}
Notes:
- Dynamically creates items without requiring JSON definition
- Useful for consumable items obtained through gameplay
- Auto-generates UUID if
item_idis omitted (prevents conflicts) - Publishes
ItemAcquiredEventifacquired=true
ConsumeItemAction¶
Consume an item from the player's inventory.
Type: consume_item
Parameters:
item_id: str- Unique identifier of the item to consume
Example:
In a script for using a consumable:
{
"actions": [
{"type": "consume_item", "item_id": "ancient_key"},
{"type": "dialog", "speaker": "Narrator", "text": ["The key dissolves into dust..."]},
{"type": "wait_for_dialog_close"}
]
}
Notes:
- Item must be acquired and not already consumed
- Publishes
ItemConsumedEventwhen successful - Action completes immediately regardless of success
WaitForInventoryAccessAction¶
Wait for inventory to be accessed.
Type: wait_inventory_access
Parameters: None
Example:
[
{"type": "dialog", "speaker": "martin", "text": ["Check your inventory!"]},
{"type": "wait_for_dialog_close"},
{"type": "wait_inventory_access"},
{"type": "dialog", "speaker": "martin", "text": ["Great job!"]}
]
Notes:
- Pauses script execution until player opens inventory
- Useful for tutorial sequences
- Monitors the
has_been_accessedflag
Conditions¶
inventory_accessed¶
Check if the player has opened their inventory.
Parameters:
check:"inventory_accessed"equals:trueorfalse
Example:
{
"trigger": {
"event": "inventory_closed"
},
"conditions": [
{
"check": "inventory_accessed",
"equals": true
}
]
}
Use Cases:
- Tutorial completion
- Achievement triggers
- First-time inventory checks
item_acquired¶
Check if an inventory item was acquired.
Parameters:
check:"item_acquired"item_id: Item identifier
Example:
{
"trigger": {
"event": "portal_entered",
"portal": "dungeon_gate"
},
"conditions": [
{
"check": "item_acquired",
"item_id": "dungeon_key"
}
],
"actions": [
{"type": "change_scene", "target_map": "dungeon.tmx", "spawn_waypoint": "entrance"}
]
}
Use Cases:
- Gating progression behind item collection
- Quest prerequisite checks
- Conditional NPC responses
Inventory Overlay¶
Opening the Inventory¶
Press the configured INVENTORY_KEY_TOGGLE key (default: I) to open the inventory overlay. The overlay shows:
- Grid of acquired items with icons
- Selected item name at bottom
- Hints for available actions
- Capacity counter (e.g., "8/12")
Navigation¶
- Arrow keys: Move selection in grid
V: View selected item in detail (if it has an image)C: Consume selected item (if it's consumable)ESC: Close overlay
Grid Display¶
- Filled slots: Show items with icons, solid background, white border
- Empty slots: Show semi-transparent background, dim border
- Selected slot: Yellow border (thicker than normal)
Photo Viewer¶
When viewing an item with an image_path:
- Full-screen black background
- Photo scaled to fit screen (maintains aspect ratio)
- Item name displayed below photo
- Item description below name
ESCto return to grid
Custom Inventory Implementation¶
If you need to replace the inventory plugin with a custom implementation, you can extend the InventoryBasePlugin abstract base class.
InventoryBasePlugin¶
Location: src/pedre/plugins/inventory/base.py
The InventoryBasePlugin class defines the minimum interface that any inventory plugin must implement.
Required Methods¶
Your custom inventory plugin must implement these abstract methods:
from pedre.plugins.inventory.base import InventoryBasePlugin, InventoryItem
class CustomInventoryPlugin(InventoryBasePlugin):
"""Custom inventory implementation."""
name = "inventory"
dependencies = []
def has_been_accessed(self) -> bool:
"""Check if inventory has been accessed."""
...
def has_item(self, item_id: str) -> bool:
"""Check if the player has acquired a specific item."""
...
def acquire_item(self, item_id: str) -> bool:
"""Mark an item as acquired by the player."""
...
def consume_item(self, item_id: str) -> bool:
"""Mark an item as consumed by the player."""
...
def add_item(self, item: InventoryItem) -> bool:
"""Add a new item to the inventory plugin."""
...
Registration¶
Register your custom inventory plugin using the @PluginRegistry.register decorator:
from pedre.plugins.registry import PluginRegistry
from pedre.plugins.inventory.base import InventoryBasePlugin
@PluginRegistry.register
class CustomInventoryPlugin(InventoryBasePlugin):
name = "inventory"
dependencies = []
# ... implement all abstract methods ...
Notes on Custom Implementation¶
- Your custom plugin inherits from
BasePlugin(viaInventoryBasePlugin), so you must implement the standard plugin lifecycle methods:setup(),cleanup(), andreset() - The
roleattribute is set to"inventory_plugin"in the base class - Your implementation can use any storage backend or UI plugin
- Register your custom inventory plugin in your project's
INSTALLED_PLUGINSsetting before the default"pedre.plugins.inventory"to replace it
Example Custom Implementation:
# In myproject/plugins/custom_inventory.py
from pedre.plugins.registry import PluginRegistry
from pedre.plugins.inventory.base import InventoryBasePlugin
@PluginRegistry.register
class DatabaseInventoryPlugin(InventoryBasePlugin):
"""Inventory plugin that stores items in a database."""
name = "inventory"
dependencies = []
def __init__(self):
self.db = Database()
# ... rest of initialization ...
def has_item(self, item_id: str) -> bool:
# Query database for item
return self.db.query("SELECT acquired FROM items WHERE id = ?", item_id)
# ... implement other abstract methods ...
# In myproject/settings.py
INSTALLED_PLUGINS = [
"myproject.plugins.custom_inventory", # Load custom inventory first
"pedre.plugins.camera",
"pedre.plugins.audio",
# ... rest of plugins (omit "pedre.plugins.inventory") ...
]
Usage Examples¶
Tutorial Sequence¶
{
"tutorial_inventory": {
"scene": "casa",
"trigger": {
"event": "dialog_closed",
"npc": "martin",
"dialog_level": 0
},
"actions": [
{"type": "acquire_item", "item_id": "beach_photo"},
{"type": "dialog", "speaker": "Martin", "text": ["Check your inventory (press I)!"]},
{"type": "wait_for_dialog_close"},
{"type": "wait_inventory_access"},
{"type": "dialog", "speaker": "Martin", "text": ["Great! You can view the photo by pressing V."]},
{"type": "wait_for_dialog_close"},
{"type": "advance_dialog", "npc": "martin"}
]
}
}
Quest Item Gating¶
{
"locked_door": {
"scene": "dungeon",
"trigger": {
"event": "object_interacted",
"object_name": "iron_door"
},
"conditions": [
{
"check": "item_acquired",
"item_id": "iron_key"
}
],
"actions": [
{"type": "dialog", "speaker": "Narrator", "text": ["The door opens with a creak."]},
{"type": "wait_for_dialog_close"},
{"type": "consume_item", "item_id": "iron_key"}
]
},
"door_locked": {
"scene": "dungeon",
"trigger": {
"event": "object_interacted",
"object_name": "iron_door"
},
"actions": [
{"type": "dialog", "speaker": "Narrator", "text": ["The door is locked. You need a key."]}
]
}
}
See Also¶
- DialogPlugin - Conversation plugin
- ScriptPlugin - Event-driven scripting
- Configuration Guide
- Scripting Actions
- Scripting Conditions
- Scripting Events