Inventory Items cleanup

This commit is contained in:
Garry Newman 2016-12-01 12:26:53 +00:00
parent 5ac65c9fb9
commit 255e80b58d
5 changed files with 135 additions and 102 deletions

View File

@ -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 );
}
}
}
}
} }
} }

View File

@ -99,7 +99,6 @@
<Compile Include="Client\Networking.cs" /> <Compile Include="Client\Networking.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Client\Friends.cs" /> <Compile Include="Client\Friends.cs" />
<Compile Include="Server\Inventory.cs" />
<Compile Include="Server\Server.cs" /> <Compile Include="Server\Server.cs" />
<Compile Include="Server\Stats.cs" /> <Compile Include="Server\Stats.cs" />
</ItemGroup> </ItemGroup>

View File

@ -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 );
}
}
}
}
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using SteamNative;
namespace Facepunch.Steamworks namespace Facepunch.Steamworks
{ {
@ -10,27 +11,37 @@ namespace Facepunch.Steamworks
{ {
public class Result : IDisposable public class Result : IDisposable
{ {
internal static Dictionary< int, Result > Pending;
internal Inventory inventory; internal Inventory inventory;
private SteamNative.SteamInventoryResult_t Handle { get; set; } private SteamNative.SteamInventoryResult_t Handle { get; set; }
/// <summary>
/// Called when result is successfully returned
/// </summary>
public Action<Result> OnResult;
/// <summary>
/// Items that exist, or that have been created, or changed
/// </summary>
public Item[] Items { get; internal set; } public Item[] Items { get; internal set; }
/// <summary>
/// Items that have been removed or somehow destroyed
/// </summary>
public Item[] Removed { get; internal set; } public Item[] Removed { get; internal set; }
/// <summary>
/// Items that have been consumed, like in a craft or something
/// </summary>
public Item[] Consumed { get; internal set; } public Item[] Consumed { get; internal set; }
public bool IsPending /// <summary>
{ /// Returns true if this result is still pending
get /// </summary>
{ public bool IsPending { get; internal set; }
if ( Items != null ) return false;
if ( Handle == -1 ) return false;
if ( Status() == Callbacks.Result.Pending ) return true;
TryFill(); internal uint Timestamp { get; private set; }
return false;
}
}
internal bool IsSuccess internal bool IsSuccess
{ {
@ -42,40 +53,29 @@ namespace Facepunch.Steamworks
} }
} }
internal uint Timestamp { get; private set; }
internal Callbacks.Result Status() internal Callbacks.Result Status()
{ {
if ( Handle == -1 ) return Callbacks.Result.InvalidParam; if ( Handle == -1 ) return Callbacks.Result.InvalidParam;
return (Callbacks.Result)inventory.inventory.GetResultStatus( Handle ); return (Callbacks.Result)inventory.inventory.GetResultStatus( Handle );
} }
internal Result( Inventory inventory, int Handle, bool pending )
internal Result( Inventory inventory, int Handle )
{ {
this.Handle = Handle; if ( pending )
this.inventory = inventory;
TryFill();
}
public bool Block( float maxWait = 5.0f )
{
while ( IsPending )
{ {
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 ) if ( Items != null )
return; return;
if ( !IsSuccess ) this.IsPending = false;
return;
Timestamp = inventory.inventory.GetResultTimestamp( Handle ); Timestamp = inventory.inventory.GetResultTimestamp( Handle );
@ -127,7 +127,20 @@ namespace Facepunch.Steamworks
}; };
} ).ToArray(); } ).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() internal unsafe byte[] Serialize()

View File

@ -43,48 +43,76 @@ namespace Facepunch.Steamworks
IsServer = server; IsServer = server;
inventory = c; inventory = c;
Result.Pending = new Dictionary<int, Result>();
inventory.LoadItemDefinitions(); inventory.LoadItemDefinitions();
FetchItemDefinitions(); FetchItemDefinitions();
if ( !server ) if ( !server )
{ {
// SteamNative.SteamInventoryResultReady_t.RegisterCallback( steamworks, onResultReady ); SteamNative.SteamInventoryResultReady_t.RegisterCallback( steamworks, onResultReady );
SteamNative.SteamInventoryFullUpdate_t.RegisterCallback( steamworks, onFullUpdate ); SteamNative.SteamInventoryFullUpdate_t.RegisterCallback( steamworks, onFullUpdate );
//
// Get a list of our items immediately
//
Refresh(); Refresh();
} }
} }
/// <summary>
/// We've received a FULL update
/// </summary>
private void onFullUpdate( SteamInventoryFullUpdate_t data, bool error ) private void onFullUpdate( SteamInventoryFullUpdate_t data, bool error )
{ {
if ( error ) return; if ( error ) return;
onResult( data.Handle, true ); var result = new Result( this, data.Handle, false );
result.Fill();
onResult( result, true );
} }
/// <summary>
/// A generic result has returned.
/// </summary>
private void onResultReady( SteamInventoryResultReady_t data, bool error ) private void onResultReady( SteamInventoryResultReady_t data, bool error )
{ {
if ( error ) return; if ( Result.Pending.ContainsKey( data.Handle ) )
if ( data.Esult != SteamNative.Result.OK ) return; {
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 ) if ( r.IsSuccess )
{ {
//
// We only serialize FULL updates
//
if ( serialize ) if ( serialize )
{ {
//
// Only serialize if this result is newer than the last one
//
if ( r.Timestamp < LastTimestamp ) if ( r.Timestamp < LastTimestamp )
return; return;
LastTimestamp = r.Timestamp;
SerializedItems = r.Serialize(); SerializedItems = r.Serialize();
SerializedExpireTime = DateTime.Now.Add( TimeSpan.FromMinutes( 60 ) ); SerializedExpireTime = DateTime.Now.Add( TimeSpan.FromMinutes( 60 ) );
} }
LastTimestamp = r.Timestamp;
ApplyResult( r ); ApplyResult( r );
} }
@ -92,6 +120,11 @@ namespace Facepunch.Steamworks
r = null; r = null;
} }
/// <summary>
/// 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
/// </summary>
internal void ApplyResult( Result r ) internal void ApplyResult( Result r )
{ {
if ( IsServer ) return; if ( IsServer ) return;
@ -121,6 +154,8 @@ namespace Facepunch.Steamworks
Items = null; Items = null;
SerializedItems = null; SerializedItems = null;
Result.Pending = null;
} }
/// <summary> /// <summary>
@ -170,11 +205,7 @@ namespace Facepunch.Steamworks
if ( ids == null ) if ( ids == null )
return; return;
Definitions = ids.Select( x => Definitions = ids.Select( x => CreateDefinition( x ) ).ToArray();
{
return CreateDefinition( x );
} ).ToArray();
foreach ( var def in Definitions ) foreach ( var def in Definitions )
{ {
@ -241,7 +272,9 @@ namespace Facepunch.Steamworks
if ( !result || resultHandle == -1 ) if ( !result || resultHandle == -1 )
return null; 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 ) ) if ( !inventory.ExchangeItems( ref resultHandle, newItems, newItemC, 1, takeItems, takeItemsC, (uint)takeItems.Length ) )
return null; return null;
return new Result( this, resultHandle ); return new Result( this, resultHandle, true );
} }
/// <summary> /// <summary>
@ -275,7 +308,7 @@ namespace Facepunch.Steamworks
if ( !inventory.TransferItemQuantity( ref resultHandle, item.Id, (uint)quantity, ulong.MaxValue ) ) if ( !inventory.TransferItemQuantity( ref resultHandle, item.Id, (uint)quantity, ulong.MaxValue ) )
return null; return null;
return new Result( this, resultHandle ); return new Result( this, resultHandle, true );
} }
/// <summary> /// <summary>
@ -287,7 +320,7 @@ namespace Facepunch.Steamworks
if ( !inventory.TransferItemQuantity( ref resultHandle, source.Id, (uint)quantity, dest.Id ) ) if ( !inventory.TransferItemQuantity( ref resultHandle, source.Id, (uint)quantity, dest.Id ) )
return null; return null;
return new Result( this, resultHandle ); return new Result( this, resultHandle, true );
} }
} }
} }