SetNet.Inventory
1.2.0
dotnet add package SetNet.Inventory --version 1.2.0
NuGet\Install-Package SetNet.Inventory -Version 1.2.0
<PackageReference Include="SetNet.Inventory" Version="1.2.0" />
<PackageVersion Include="SetNet.Inventory" Version="1.2.0" />
<PackageReference Include="SetNet.Inventory" />
paket add SetNet.Inventory --version 1.2.0
#r "nuget: SetNet.Inventory, 1.2.0"
#:package SetNet.Inventory@1.2.0
#addin nuget:?package=SetNet.Inventory&version=1.2.0
#tool nuget:?package=SetNet.Inventory&version=1.2.0
<p align="center"> <img src="https://raw.githubusercontent.com/Povstalez/SetNet/master/assets/icon.png" alt="SetNet" width="96"> </p>
SetNet.Inventory
Server-authoritative player inventory for SetNet.
The server owns every item. Game logic grants and revokes stackable items by player key (online or not); connected clients can read their inventory and subscribe to changes but never mutate it directly. The atomic take-if-enough primitive (TryRevokeAsync) is what makes safe trading and mail attachments possible — SetNet.Trade and SetNet.Mail move items through this same hub. Added by composition — no base class.
Install
dotnet add package SetNet
dotnet add package SetNet.Inventory
Usage
Call InventoryRuntime.Enable() once at startup on both ends (before handler discovery).
Server — the authority:
InventoryRuntime.Enable();
var inventory = server.UseInventory(); // + optional IInventoryStore / InventoryOptions
// from game logic (a quest reward, a purchase, a drop):
await inventory.GrantAsync(playerKey, "gold", 100);
bool paid = await inventory.TryRevokeAsync(playerKey, "gold", 100); // false if they can't afford it
Client — read and react:
InventoryRuntime.Enable();
var inventory = client.UseInventory();
inventory.Changed += stacks => Redraw(stacks);
foreach (var s in await inventory.GetAsync())
Console.WriteLine($"{s.Count} × {s.ItemId}");
API
Server: server.UseInventory(IInventoryStore?, InventoryOptions?) → InventoryServer
| Member | Purpose |
|---|---|
GrantAsync(playerKey, itemId, count) |
add items (pushes a snapshot if the player is online) |
Task<bool> TryRevokeAsync(playerKey, itemId, count) |
atomic remove; false if insufficient |
GetAsync(playerKey) |
current stacks |
KeyOf(peer) / PeerFor(playerKey) / PushAsync(playerKey) |
identity + online helpers (used by trade/mail) |
Store |
the backing IInventoryStore |
Client: var inventory = client.UseInventory() → InventoryClient — GetAsync(), event Changed.
Options: InventoryOptions.PlayerKey maps a peer to its stable key (default = connection id — override to the authenticated account id so inventories survive reconnects).
InventoryRuntime.Enable() — one-time bootstrap.
Notes
- Rides the unified SetNet.Protocol messaging layer on the
Channels.Inventorychannel (all modules share one envelope wire type,65447) — no per-module wire ids to reserve. Serializer-agnostic: the control protocol is hand-framedbyte[], your payloads use yourSetNetSerializer. - Stackable by item id. A stack is
(ItemId, Count). Per-instance data (unique weapons, durability) is out of scope — encode it into the item id ("sword#<uuid>") so each instance is its own non-stacking stack. - Use a stable player key. The default key is the connection id, which changes on reconnect. With
SetNet.Auth, setPlayerKeyto the authenticated account id so inventories persist and follow the player across nodes. - Persistence. The default
MemoryInventoryStoreis per-process. ImplementIInventoryStoreover Redis/SQL for durability and cluster sharing — keepTryRevokeAsyncatomic (it's the anti-dupe guarantee).
Documentation & source
- 🐙 https://github.com/Povstalez/SetNet — full module catalog in docs/MODULES.md
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- SetNet (>= 1.2.0)
NuGet packages (10)
Showing the top 5 NuGet packages that depend on SetNet.Inventory:
| Package | Downloads |
|---|---|
|
SetNet.Trade
Player-to-player item trading for SetNet: server-authoritative two-party escrow with a two-phase (ready → confirm) lock that stops last-second offer swaps, and an atomic cross-swap through SetNet.Inventory that rolls back if either side's holdings changed. server.UseTrade(inventory) + client.UseTrade(). Depends on SetNet + SetNet.Inventory. |
|
|
SetNet.Loot
Server-authoritative weighted loot tables for SetNet: define drop tables (guaranteed + weighted draws), roll them server-side (clients never see weights/RNG), and grant results through SetNet.Inventory. server.UseLoot(inventory).Define(table).RollAndGrantAsync(...); gated client OpenAsync for loot boxes. Depends on SetNet + SetNet.Inventory. |
|
|
SetNet.Crafting
Server-authoritative crafting for SetNet: register recipes (inputs → outputs); clients request a craft and the server atomically consumes ingredients and grants results through SetNet.Inventory (rollback on shortfall). server.UseCrafting(inventory).Define(recipe) + client.UseCrafting(). Depends on SetNet + SetNet.Inventory. |
|
|
SetNet.Marketplace
Continuous double-sided order-book marketplace for SetNet: post limit buy/sell orders (items/currency escrowed), crossing orders match instantly at the resting price with price-time priority and the rest rests on the book. Settled through SetNet.Inventory + SetNet.Wallet (no dupes; buyer refunded price improvement). server.UseMarketplace(inventory, wallet) + client.UseMarketplace(). Depends on SetNet + SetNet.Inventory + SetNet.Wallet. |
|
|
SetNet.Mail
In-game mail for SetNet: send messages with item attachments to players who may be offline; attachments are escrowed from the sender's inventory at send time and granted to the recipient on claim (no dupes, no loss). server.UseMail(store, inventory) + client.UseMail() → send/list/read/claim/delete + push on arrival. Pluggable IMailStore. Depends on SetNet + SetNet.Inventory. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.0 | 359 | 8/5/2026 |