TheChest.Inventories is a library for managing inventories and slots in generic item collections. It provides a flexible and extensible framework for inventory systems, with support for stackable items, event-driven operations, and lazy-loaded inventory management.
- Key Features
- Project Structure
- Installation
- Quick Start
- Architecture
- Usage Example
- Features
- Extension and Customization
- Contributing
- Additional Resources
- Future Plans
- Generic inventory support: Works with any generic item type for maximum flexibility
- Slot-based system: Stores items in single-item or stackable slots
- Three inventory types:
- Standard
Inventory<T>for single-item slots StackInventory<T>for stackable itemsLazyStackInventory<T>for lazy-loaded stackable items
- Standard
- Event system: Comprehensive events for add, remove, move, and replace operations
- Extensible interfaces: Enable custom inventory implementations
- Core operations: Add, remove, move, and retrieve items with flexible APIs
- Validation: Built-in methods to check operations before execution
-
Inventory<T>- Generic inventory implementation using single-item slots
- Uses
InventorySlot<T>to represent each slot - Best for: Game inventories with single-item slots, fixed-size collections
- Learn more
-
StackInventory<T>- Generic inventory for stackable items
- Uses
InventoryStackSlot<T>to represent slots holding multiple units of the same item - Best for: Resource management, currency systems, consumable items
- Learn more
-
LazyStackInventory<T>- Stackable inventory with lazy item loading
- Uses
InventoryLazyStackSlot<T>to represent slots that can return items on demand - Best for: Large collections, on-demand item generation, performance optimization
- Learn more
Add the NuGet package source:
nuget source add -n TheChest https://nuget.pkg.github.com/The-Chest/index.jsonInstall the package:
nuget install TheChest.InventoriesYou can also download the DLL directly and reference it in your project.
using TheChest.Inventories.Containers;
using TheChest.Inventories.Slots.Interfaces;
// Create slots
var slots = new IInventorySlot<string>[10];
for (int i = 0; i < slots.Length; i++)
{
slots[i] = new InventorySlot<string>();
}
// Create inventory
var inventory = new Inventory<string>(slots);
// Add an item
if (inventory.CanAdd("Item1"))
{
inventory.Add("Item1");
}Detailed documentation on the event system for each inventory type:
A basic inventory for items that occupy one slot each:
using TheChest.Inventories.Containers;
using TheChest.Inventories.Slots.Interfaces;
// Initialize slots
var slots = new IInventorySlot<string>[10];
for (int i = 0; i < slots.Length; i++)
{
slots[i] = new InventorySlot<string>();
}
// Create inventory
var inventory = new Inventory<string>(slots);
// Add items
inventory.Add("Sword");
inventory.Add("Shield");
// Retrieve items
var item = inventory.Get(0);
// Check inventory
int count = inventory.Count("Sword");Listen to inventory changes through events:
using TheChest.Inventories.Containers;
using TheChest.Inventories.Slots.Interfaces;
var slots = new IInventorySlot<string>[10];
for (int i = 0; i < slots.Length; i++)
{
slots[i] = new InventorySlot<string>();
}
var inventory = new Inventory<string>(slots);
// Subscribe to add events
inventory.OnAdd += (sender, args) =>
{
foreach (var action in args.Data)
{
Console.WriteLine($"Item {action.Item} added to slot {action.Index}");
}
};
// Subscribe to get events
inventory.OnGet += (sender, args) =>
{
foreach (var action in args.Data)
{
Console.WriteLine($"Item {action.Item} retrieved from slot {action.Index}");
}
};
// Subscribe to move events
inventory.OnMove += (sender, args) =>
{
Console.WriteLine($"Item moved from {args.Data.Origin} to {args.Data.Target}");
};
// Subscribe to replace events
inventory.OnReplace += (sender, args) =>
{
Console.WriteLine($"Item replaced at slot {args.Data.Index}");
};
// Operations will now trigger events
inventory.Add("Sword");
var item = inventory.Get(0);Always validate operations before executing:
using TheChest.Inventories.Containers;
using TheChest.Inventories.Slots.Interfaces;
var slots = new IInventorySlot<string>[10];
for (int i = 0; i < slots.Length; i++)
{
slots[i] = new InventorySlot<string>();
}
var inventory = new Inventory<string>(slots);
// Check if we can add before adding
if (inventory.CanAdd("Item"))
{
inventory.Add("Item");
}
else
{
Console.WriteLine("Inventory is full!");
}
// Check if we can move before moving
if (inventory.CanMove(0, 5))
{
inventory.Move(0, 5);
}
else
{
Console.WriteLine("Cannot move item to that slot");
}
// Use Try methods for safer operations
if (inventory.TryReplace("NewItem", 0, out var oldItem))
{
Console.WriteLine($"Replaced {oldItem} with NewItem");
}
else
{
Console.WriteLine("Failed to replace item");
}All inventory types support a comprehensive event system:
OnGet- Fires when items are retrievedOnAdd- Fires when items are addedOnMove- Fires when items are moved between slotsOnReplace- Fires when items are replaced
See Inventory Events for detailed examples.
Different inventory types handle stacking differently:
- Inventory: One item per slot
- StackInventory: Multiple items per slot with a defined max stack
- LazyStackInventory: Multiple items per slot, loaded on demand
- Use
Inventory<T>for simple, single-item slot scenarios - Use
StackInventory<T>for smaller collections with stackable items - Use
LazyStackInventory<T>when working with large collections that don't need to be fully loaded - Always use
CanXmethods to validate operations before executing them - Subscribe to events selectively to avoid performance overhead
You can extend the built-in inventory classes to add custom functionality:
Create fully custom implementations by implementing the interfaces:
- Implementing Custom Inventory
- Implementing Custom Stack Inventory
- Implementing Custom Lazy Stack Inventory
Future version plans are available on the GitHub Project Board.