SDK Usage (Plain C#)
InventoryFramework.SDK is a netstandard2.1 client library that works in any .NET project (console apps, ASP.NET Core backends, test harnesses) without requiring Unity or Godot.
Installation
Add a project reference or NuGet package reference to InventoryFramework.SDK:
<PackageReference Include="InventoryFramework.SDK" Version="*" />
Creating a client
GrpcInventoryClient wraps the gRPC channel and implements IInventoryClient.
using InventoryFramework.SDK.Grpc;
using InventoryFramework.SDK.Models;
var options = new InventoryClientOptions
{
ServerAddress = "https://your-server:5001",
ApiKey = "sk-game-your-secret-key"
};
IInventoryClient client = new GrpcInventoryClient(options);
InventoryClientOptions
| Property | Type | Default | Description |
|---|---|---|---|
ServerAddress | string | required | Full URL of the gRPC server (e.g. https://localhost:5001). |
ApiKey | string | "" | API key sent in the x-api-key gRPC metadata header. Leave empty if RequireApiKey is false on the server. |
TimeoutSeconds | int | 30 | Per-call deadline in seconds. |
Common operations
Create an inventory
var result = await client.CreateInventoryAsync(ownerActorId: "player-123");
if (result.Succeeded)
Console.WriteLine($"Inventory id: {result.InventoryId}");
Get inventory
var result = await client.GetInventoryAsync(inventoryId: "inv-player-123");
foreach (var container in result.Aggregate.Containers)
{
Console.WriteLine($"Container {container.Id}: {container.Slots.Count} slots");
}
Grant items (admin key required)
var result = await client.GrantItemsAsync(
inventoryId: "inv-player-123",
containerId: "container-backpack-guid",
itemDefinitionId: "wood",
quantity: 10);
Transfer items
Moves items between two containers within the same inventory.
var result = await client.TransferItemsAsync(
inventoryId: "inv-player-123",
sourceContainerId: "container-backpack-guid",
sourceSlotIndex: 0,
targetContainerId: "container-chest-guid",
quantity: 5);
Quick-store
Automatically moves all stackable items from a source container into the best-matching slots in a target container.
var result = await client.QuickStoreItemsAsync(
inventoryId: "inv-player-123",
sourceContainerId: "container-backpack-guid",
targetContainerId: "container-chest-guid");
Lock / unlock a slot
Prevent automated operations (quick-store, sort) from touching a specific slot. Manual moves and crafting still work.
// Lock
await client.LockSlotAsync(inventoryId, containerId, slotIndex: 2, lockSlot: true);
// Unlock
await client.LockSlotAsync(inventoryId, containerId, slotIndex: 2, lockSlot: false);
Split a stack
Split some items from a slot into an adjacent empty slot. Optionally specify the destination.
var result = await client.SplitStackAsync(
inventoryId,
containerId,
sourceSlotIndex: 0,
amount: 5);
Console.WriteLine($"Split landed in slot {result.DestinationSlotIndex}");
Drop items
Remove items from a slot and discard them. The returned data lets the game spawn a world pickup.
var result = await client.DropItemsAsync(
inventoryId,
containerId,
slotIndex: 0,
amount: 3);
if (result.Succeeded)
SpawnWorldDrop(result.DroppedItemDefinitionId, result.DroppedQuantity, playerPosition);
Sort container
Rearrange all unlocked slots. Locked slots act as fixed anchors the sort routes around.
// 0 = ByNameAscending, 1 = ByWeightDescending, 2 = ByTagThenName
await client.SortContainerAsync(inventoryId, containerId, sortMode: 0);
Trade (Pro+)
Atomically swaps items between two inventories.
var result = await client.TradeItemsAsync(
sourceInventoryId: "inv-player-123",
targetInventoryId: "inv-player-456",
sourceContainerId: "container-backpack-a",
sourceSlotIndex: 0,
targetContainerId: "container-backpack-b",
targetSlotIndex: 2,
quantity: 1);
Craft items
var result = await client.CraftItemsAsync(
inventoryId: "inv-player-123",
recipeId: "plank_recipe",
craftCount: 2,
sourceContainerId: "container-backpack-guid",
targetContainerId: "container-backpack-guid");
For full crafting documentation see Crafting & Recipes.
Error handling
Every operation returns a result type that implements InventoryClientResult:
public abstract class InventoryClientResult
{
public bool Succeeded { get; }
public string ErrorCode { get; }
public string ErrorMessage { get; }
}
Common error codes:
| Code | Meaning |
|---|---|
not_found | The inventory or recipe does not exist. |
concurrency_conflict | The inventory was modified concurrently; retry after re-fetching. |
insufficient_ingredients | Not enough items to craft. |
feature_disabled | The feature is off in server config or the license tier is too low. |
unauthorized | Missing or invalid API key. |
permission_denied | The caller does not have access to this inventory. |
Dependency injection
Register GrpcInventoryClient as a singleton in an ASP.NET Core application:
builder.Services.AddSingleton<IInventoryClient>(_ =>
new GrpcInventoryClient(new InventoryClientOptions
{
ServerAddress = builder.Configuration["Inventory:ServerAddress"]!,
ApiKey = builder.Configuration["Inventory:ApiKey"]!
}));
Real-time updates
For real-time inventory change notifications subscribe to the SignalR hub. See SignalR Events.