diff --git a/Facepunch.Steamworks.Test/Client/Inventory.cs b/Facepunch.Steamworks.Test/Client/Inventory.cs
index d9c65c2..b076046 100644
--- a/Facepunch.Steamworks.Test/Client/Inventory.cs
+++ b/Facepunch.Steamworks.Test/Client/Inventory.cs
@@ -113,5 +113,46 @@ namespace Facepunch.Steamworks.Test
}
}
}
+
+ [TestMethod]
+ public void Deserialize()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ Assert.IsTrue( client.IsValid );
+
+ client.Inventory.Refresh();
+
+ //
+ // Block until we have the items
+ //
+ while ( client.Inventory.SerializedItems == null )
+ {
+ client.Update();
+ }
+
+ Assert.IsNotNull( client.Inventory.SerializedItems );
+ Assert.IsTrue( client.Inventory.SerializedItems.Length > 4 );
+
+ using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) )
+ {
+ server.LogOnAnonymous();
+ Assert.IsTrue( server.IsValid );
+
+ var result = server.Inventory.Deserialize( client.Inventory.SerializedItems );
+
+ server.UpdateWhile( () => result.IsPending );
+
+ Assert.IsFalse( result.IsPending );
+ Assert.IsNotNull( result.Items );
+
+ foreach ( var item in result.Items )
+ {
+ Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
+ Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
+ }
+ }
+ }
+ }
}
}
diff --git a/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj b/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
index 250379b..f38be94 100644
--- a/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
+++ b/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
@@ -99,7 +99,6 @@
-
diff --git a/Facepunch.Steamworks.Test/Server/Inventory.cs b/Facepunch.Steamworks.Test/Server/Inventory.cs
deleted file mode 100644
index 9d8445c..0000000
--- a/Facepunch.Steamworks.Test/Server/Inventory.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.Text;
-using System.Threading;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Linq;
-
-namespace Facepunch.Steamworks.Test
-{
- public partial class Server
- {
- [TestMethod]
- public void InventoryDeserialize()
- {
- using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
- {
- Assert.IsTrue( client.IsValid );
-
- Assert.IsNull( client.Inventory.SerializedItems );
-
- client.Inventory.Refresh();
-
- //
- // Block until we have the items
- //
- while ( client.Inventory.SerializedItems == null )
- {
- client.Update();
- }
-
- Assert.IsNotNull( client.Inventory.SerializedItems );
- Assert.IsTrue( client.Inventory.SerializedItems.Length > 4 );
-
- using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) )
- {
- server.LogOnAnonymous();
- Assert.IsTrue( server.IsValid );
-
- var result = server.Inventory.Deserialize( client.Inventory.SerializedItems );
-
- Assert.IsTrue( result.Block() );
- Assert.IsNotNull( result.Items );
-
- foreach ( var item in result.Items )
- {
- Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
- Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
- }
- }
- }
- }
-
- }
-}
diff --git a/Facepunch.Steamworks/Interfaces/Inventory.Result.cs b/Facepunch.Steamworks/Interfaces/Inventory.Result.cs
index fce45fc..2931297 100644
--- a/Facepunch.Steamworks/Interfaces/Inventory.Result.cs
+++ b/Facepunch.Steamworks/Interfaces/Inventory.Result.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
+using SteamNative;
namespace Facepunch.Steamworks
{
@@ -10,27 +11,37 @@ namespace Facepunch.Steamworks
{
public class Result : IDisposable
{
+ internal static Dictionary< int, Result > Pending;
internal Inventory inventory;
private SteamNative.SteamInventoryResult_t Handle { get; set; }
+
+ ///
+ /// Called when result is successfully returned
+ ///
+ public Action OnResult;
+
+ ///
+ /// Items that exist, or that have been created, or changed
+ ///
public Item[] Items { get; internal set; }
+ ///
+ /// Items that have been removed or somehow destroyed
+ ///
public Item[] Removed { get; internal set; }
+ ///
+ /// Items that have been consumed, like in a craft or something
+ ///
public Item[] Consumed { get; internal set; }
- public bool IsPending
- {
- get
- {
- if ( Items != null ) return false;
- if ( Handle == -1 ) return false;
- if ( Status() == Callbacks.Result.Pending ) return true;
+ ///
+ /// Returns true if this result is still pending
+ ///
+ public bool IsPending { get; internal set; }
- TryFill();
- return false;
- }
- }
+ internal uint Timestamp { get; private set; }
internal bool IsSuccess
{
@@ -42,40 +53,29 @@ namespace Facepunch.Steamworks
}
}
- internal uint Timestamp { get; private set; }
-
internal Callbacks.Result Status()
{
if ( Handle == -1 ) return Callbacks.Result.InvalidParam;
return (Callbacks.Result)inventory.inventory.GetResultStatus( Handle );
}
-
- internal Result( Inventory inventory, int Handle )
+ internal Result( Inventory inventory, int Handle, bool pending )
{
- this.Handle = Handle;
- this.inventory = inventory;
-
- TryFill();
- }
-
- public bool Block( float maxWait = 5.0f )
- {
- while ( IsPending )
+ if ( pending )
{
- System.Threading.Thread.Sleep( 5 );
+ Pending.Add( Handle, this );
}
- return IsSuccess;
+ this.Handle = Handle;
+ this.inventory = inventory;
}
- internal void TryFill()
+ internal void Fill()
{
if ( Items != null )
return;
- if ( !IsSuccess )
- return;
+ this.IsPending = false;
Timestamp = inventory.inventory.GetResultTimestamp( Handle );
@@ -127,7 +127,20 @@ namespace Facepunch.Steamworks
};
} ).ToArray();
- inventory.ApplyResult( this );
+ if ( OnResult != null )
+ {
+ OnResult( this );
+ }
+ }
+
+ internal void OnSteamResult( SteamInventoryResultReady_t data, bool error )
+ {
+ var success = data.Esult == SteamNative.Result.OK && !error;
+
+ if ( success )
+ {
+ Fill();
+ }
}
internal unsafe byte[] Serialize()
diff --git a/Facepunch.Steamworks/Interfaces/Inventory.cs b/Facepunch.Steamworks/Interfaces/Inventory.cs
index 43c7593..ef643c3 100644
--- a/Facepunch.Steamworks/Interfaces/Inventory.cs
+++ b/Facepunch.Steamworks/Interfaces/Inventory.cs
@@ -43,48 +43,76 @@ namespace Facepunch.Steamworks
IsServer = server;
inventory = c;
+ Result.Pending = new Dictionary();
+
inventory.LoadItemDefinitions();
FetchItemDefinitions();
if ( !server )
{
- // SteamNative.SteamInventoryResultReady_t.RegisterCallback( steamworks, onResultReady );
+ SteamNative.SteamInventoryResultReady_t.RegisterCallback( steamworks, onResultReady );
SteamNative.SteamInventoryFullUpdate_t.RegisterCallback( steamworks, onFullUpdate );
+
+ //
+ // Get a list of our items immediately
+ //
Refresh();
}
}
+ ///
+ /// We've received a FULL update
+ ///
private void onFullUpdate( SteamInventoryFullUpdate_t data, bool error )
{
if ( error ) return;
- onResult( data.Handle, true );
+ var result = new Result( this, data.Handle, false );
+ result.Fill();
+
+ onResult( result, true );
}
+ ///
+ /// A generic result has returned.
+ ///
private void onResultReady( SteamInventoryResultReady_t data, bool error )
{
- if ( error ) return;
- if ( data.Esult != SteamNative.Result.OK ) return;
+ if ( Result.Pending.ContainsKey( data.Handle ) )
+ {
+ var result = Result.Pending[data.Handle];
- onResult( data.Handle, false );
+ result.OnSteamResult( data, error );
+
+ if ( !error && data.Esult == SteamNative.Result.OK )
+ {
+ onResult( result, false );
+ }
+
+ Result.Pending.Remove( data.Handle );
+ }
}
- private void onResult( int Handle, bool serialize )
+ private void onResult( Result r, bool serialize )
{
- var r = new Result( this, Handle );
if ( r.IsSuccess )
{
+ //
+ // We only serialize FULL updates
+ //
if ( serialize )
{
+ //
+ // Only serialize if this result is newer than the last one
+ //
if ( r.Timestamp < LastTimestamp )
return;
- LastTimestamp = r.Timestamp;
-
SerializedItems = r.Serialize();
SerializedExpireTime = DateTime.Now.Add( TimeSpan.FromMinutes( 60 ) );
}
+ LastTimestamp = r.Timestamp;
ApplyResult( r );
}
@@ -92,6 +120,11 @@ namespace Facepunch.Steamworks
r = null;
}
+ ///
+ /// Apply this result to our current stack of Items
+ /// Here we're trying to keep our stack up to date with whatever happens
+ /// with the crafting, stacking etc
+ ///
internal void ApplyResult( Result r )
{
if ( IsServer ) return;
@@ -121,6 +154,8 @@ namespace Facepunch.Steamworks
Items = null;
SerializedItems = null;
+
+ Result.Pending = null;
}
///
@@ -170,11 +205,7 @@ namespace Facepunch.Steamworks
if ( ids == null )
return;
- Definitions = ids.Select( x =>
- {
- return CreateDefinition( x );
-
- } ).ToArray();
+ Definitions = ids.Select( x => CreateDefinition( x ) ).ToArray();
foreach ( var def in Definitions )
{
@@ -241,7 +272,9 @@ namespace Facepunch.Steamworks
if ( !result || resultHandle == -1 )
return null;
- return new Result( this, resultHandle );
+ var r = new Result( this, resultHandle, false );
+ r.Fill();
+ return r;
}
}
@@ -263,7 +296,7 @@ namespace Facepunch.Steamworks
if ( !inventory.ExchangeItems( ref resultHandle, newItems, newItemC, 1, takeItems, takeItemsC, (uint)takeItems.Length ) )
return null;
- return new Result( this, resultHandle );
+ return new Result( this, resultHandle, true );
}
///
@@ -275,7 +308,7 @@ namespace Facepunch.Steamworks
if ( !inventory.TransferItemQuantity( ref resultHandle, item.Id, (uint)quantity, ulong.MaxValue ) )
return null;
- return new Result( this, resultHandle );
+ return new Result( this, resultHandle, true );
}
///
@@ -287,7 +320,7 @@ namespace Facepunch.Steamworks
if ( !inventory.TransferItemQuantity( ref resultHandle, source.Id, (uint)quantity, dest.Id ) )
return null;
- return new Result( this, resultHandle );
+ return new Result( this, resultHandle, true );
}
}
}