diff --git a/Facepunch.Steamworks.Test/Client.Stats.cs b/Facepunch.Steamworks.Test/Client.Stats.cs
deleted file mode 100644
index 20c170c..0000000
--- a/Facepunch.Steamworks.Test/Client.Stats.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using System.Text;
-using System.Threading;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Facepunch.Steamworks.Test
-{
- public partial class Client
- {
- [TestMethod]
- public void UpdateStats()
- {
- using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
- {
- client.Stats.UpdateStats();
- }
- }
-
- [TestMethod]
- public void UpdateSUpdateGlobalStatstats()
- {
- using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
- {
- client.Stats.UpdateGlobalStats( 1 );
- client.Stats.UpdateGlobalStats( 3 );
- client.Stats.UpdateGlobalStats( 7 );
- }
- }
- }
-}
diff --git a/Facepunch.Steamworks.Test/Client.cs b/Facepunch.Steamworks.Test/Client.cs
index ab34b1c..91fb38b 100644
--- a/Facepunch.Steamworks.Test/Client.cs
+++ b/Facepunch.Steamworks.Test/Client.cs
@@ -111,26 +111,7 @@ public void GetVoice()
}
}
- [TestMethod]
- public void GetServers()
- {
- using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
- {
- var query = client.ServerList.Test();
- for ( int i = 0; i < 100 ; i++ )
- {
- client.Update();
- System.Threading.Thread.Sleep( 5 );
-
- if ( query.Finished )
- break;
- }
-
- Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
- Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
- }
- }
[TestMethod]
public void InventoryDefinitions()
diff --git a/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj b/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
index 9794db4..4ddfa31 100644
--- a/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
+++ b/Facepunch.Steamworks.Test/Facepunch.Steamworks.Test.csproj
@@ -87,7 +87,7 @@
-
+
@@ -97,7 +97,8 @@
-
+
+
diff --git a/Facepunch.Steamworks.Test/Client.Networking.cs b/Facepunch.Steamworks.Test/Networking.cs
similarity index 89%
rename from Facepunch.Steamworks.Test/Client.Networking.cs
rename to Facepunch.Steamworks.Test/Networking.cs
index 948b0b2..49442e4 100644
--- a/Facepunch.Steamworks.Test/Client.Networking.cs
+++ b/Facepunch.Steamworks.Test/Networking.cs
@@ -5,7 +5,10 @@
namespace Facepunch.Steamworks.Test
{
- public partial class Client
+ [TestClass]
+ [DeploymentItem( "FacepunchSteamworksApi.dll" )]
+ [DeploymentItem( "steam_appid.txt" )]
+ public partial class Networking
{
[TestMethod]
public void PeerToPeerSend()
diff --git a/Facepunch.Steamworks.Test/Serverlist.cs b/Facepunch.Steamworks.Test/Serverlist.cs
new file mode 100644
index 0000000..af08fa4
--- /dev/null
+++ b/Facepunch.Steamworks.Test/Serverlist.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Facepunch.Steamworks.Test
+{
+ [TestClass]
+ [DeploymentItem( "FacepunchSteamworksApi.dll" )]
+ [DeploymentItem( "steam_appid.txt" )]
+ public partial class ServerList
+ {
+ [TestMethod]
+ public void InternetList()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var query = client.ServerList.Test();
+
+ for ( int i = 0; i < 100; i++ )
+ {
+ client.Update();
+ System.Threading.Thread.Sleep( 10 );
+
+ if ( query.Finished )
+ break;
+ }
+
+ Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
+ Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
+
+ query.Dispose();
+
+ for ( int i = 0; i < 100; i++ )
+ {
+ client.Update();
+ System.Threading.Thread.Sleep( 1 );
+ }
+ }
+ }
+
+ [TestMethod]
+ public void MultipleInternetList()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var queries = new List< Facepunch.Steamworks.ServerList.Request >();
+
+ for ( int i = 0; i < 10; i++ )
+ queries.Add( client.ServerList.Test() );
+
+ for ( int i = 0; i < 100; i++ )
+ {
+ client.Update();
+ System.Threading.Thread.Sleep( 5 );
+
+ if ( queries.Any( x => x.Finished ) )
+ break;
+ }
+
+ foreach ( var query in queries )
+ {
+ Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
+ Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
+
+ client.Update();
+ query.Dispose();
+ client.Update();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void HistoryList()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var query = client.ServerList.History( new Dictionary() );
+
+ while ( true )
+ {
+ client.Update();
+ System.Threading.Thread.Sleep( 2 );
+
+ if ( query.Finished )
+ break;
+ }
+
+ Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
+ Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
+
+ query.Dispose();
+
+ for ( int i = 0; i < 100; i++ )
+ {
+ client.Update();
+ System.Threading.Thread.Sleep( 1 );
+ }
+ }
+ }
+ }
+}
diff --git a/Facepunch.Steamworks.Test/Stats.cs b/Facepunch.Steamworks.Test/Stats.cs
new file mode 100644
index 0000000..21fa433
--- /dev/null
+++ b/Facepunch.Steamworks.Test/Stats.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Text;
+using System.Threading;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Facepunch.Steamworks.Test
+{
+ [TestClass]
+ [DeploymentItem( "FacepunchSteamworksApi.dll" )]
+ [DeploymentItem( "steam_appid.txt" )]
+ public class Stats
+ {
+ [TestMethod]
+ public void UpdateStats()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ client.Stats.UpdateStats();
+ }
+ }
+
+ [TestMethod]
+ public void UpdateSUpdateGlobalStatstats()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ client.Stats.UpdateGlobalStats( 1 );
+ client.Stats.UpdateGlobalStats( 3 );
+ client.Stats.UpdateGlobalStats( 7 );
+ }
+ }
+
+ [TestMethod]
+ public void GetClientFloat()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var v = client.Stats.GetFloat( "deaths" );
+ Console.WriteLine( v );
+ }
+ }
+
+ [TestMethod]
+ public void GetClientInt()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var v = client.Stats.GetInt( "deaths" );
+ Console.WriteLine( v );
+ }
+ }
+
+ [TestMethod]
+ public void GetGlobalFloat()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var v = client.Stats.GetGlobalFloat( "deaths" );
+ Console.WriteLine( v );
+ }
+ }
+
+ [TestMethod]
+ public void GetGlobalInt()
+ {
+ using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
+ {
+ var v = client.Stats.GetGlobalInt( "deaths" );
+ Console.WriteLine( v );
+ }
+ }
+ }
+}
diff --git a/Facepunch.Steamworks/Client.ServerList.Request.cs b/Facepunch.Steamworks/Client.ServerList.Request.cs
index e91232e..5bd5637 100644
--- a/Facepunch.Steamworks/Client.ServerList.Request.cs
+++ b/Facepunch.Steamworks/Client.ServerList.Request.cs
@@ -14,9 +14,6 @@ public class Request : IDisposable
internal Client client;
internal IntPtr Id;
- private IntPtr m_pVTable;
- private GCHandle m_pGCHandle;
-
public struct Server
{
public string Name { get; set; }
@@ -56,8 +53,6 @@ public string ConnectionAddress
}
}
-
-
internal static Server FromSteam( gameserveritem_t item )
{
return new Server()
@@ -100,21 +95,11 @@ internal static Server FromSteam( gameserveritem_t item )
///
public bool Finished = false;
- internal Request()
+ internal Request( Client c )
{
- //
- // Create a fake vtable for Steam to respond to
- //
- var vt = new VTable()
- {
- responded = OnServerResponded,
- nonresponsive = NonResponsive,
- complete = Complete
- };
+ client = c;
- m_pVTable = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( VTable ) ) );
- Marshal.StructureToPtr( vt, m_pVTable, false );
- m_pGCHandle = GCHandle.Alloc( m_pVTable, GCHandleType.Pinned );
+ client.OnUpdate += Update;
}
~Request()
@@ -122,88 +107,98 @@ internal Request()
Dispose();
}
+ int lastCount = 0;
+
+ internal List watchlist = new List();
+
+ private void Update()
+ {
+ if ( Id == IntPtr.Zero )
+ return;
+
+ //
+ // Add any servers we're not watching to our watch list
+ //
+ var count = client.native.servers.GetServerCount( Id );
+ if ( count != lastCount )
+ {
+ for ( int i = lastCount; i < count; i++ )
+ {
+ watchlist.Add( i );
+ }
+
+ lastCount = count;
+ }
+
+ //
+ // Remove any servers that respond successfully
+ //
+ watchlist.RemoveAll( x =>
+ {
+ var info = client.native.servers.GetServerDetails( Id, x );
+ if ( info.m_bHadSuccessfulResponse )
+ {
+ OnServer( info );
+ return true;
+ }
+
+ return false;
+ } );
+
+ //
+ // If we've finished refreshing
+ //
+ if ( client.native.servers.IsRefreshing( Id ) == false )
+ {
+ //
+ // Put any other servers on the 'no response' list
+ //
+ watchlist.RemoveAll( x =>
+ {
+ var info = client.native.servers.GetServerDetails( Id, x );
+ OnServer( info );
+ return true;
+ } );
+
+ Finished = true;
+ client.OnUpdate -= Update;
+ client.native.servers.CancelQuery( Id );
+ Id = IntPtr.Zero;
+ }
+ }
+
+ private void OnServer( gameserveritem_t info )
+ {
+ if ( info.m_bHadSuccessfulResponse )
+ {
+ Responded.Add( Server.FromSteam( info ) );
+ }
+ else
+ {
+ Unresponsive.Add( Server.FromSteam( info ) );
+ }
+
+ }
+
///
/// Disposing will end the query
///
public void Dispose()
{
+ client.OnUpdate -= Update;
+
//
// Cancel the query if it's still running
//
- if ( !Finished && Id != IntPtr.Zero )
+ if ( Id != IntPtr.Zero )
{
if ( client.Valid )
client.native.servers.CancelQuery( Id );
Id = IntPtr.Zero;
}
-
- //
- // Release the pinned GC resources
- //
- if ( m_pVTable != IntPtr.Zero )
- {
- Marshal.FreeHGlobal( m_pVTable );
- m_pVTable = IntPtr.Zero;
- }
-
- if ( m_pGCHandle.IsAllocated )
- {
- m_pGCHandle.Free();
- }
}
- private void Complete( IntPtr thisptr, IntPtr RequestId, int response )
- {
- if ( RequestId != Id )
- throw new Exception( "Request ID is invalid!" );
-
- Finished = true;
- Id = IntPtr.Zero;
- }
-
- private void NonResponsive( IntPtr thisptr, IntPtr RequestId, int iServer )
- {
- if ( RequestId != Id )
- throw new Exception( "Request ID is invalid!" );
-
- var info = client.native.servers.GetServerDetails( Id, iServer );
- Unresponsive.Add( Server.FromSteam( info ) );
- }
-
- private void OnServerResponded( IntPtr thisptr, IntPtr RequestId, int iServer )
- {
- if ( RequestId != Id )
- throw new Exception( "Request ID is invalid!" );
-
- var info = client.native.servers.GetServerDetails( Id, iServer );
- Responded.Add( Server.FromSteam( info ) );
-
- System.Diagnostics.Debug.WriteLine( info.m_szServerName );
- }
-
- internal IntPtr GetVTablePointer()
- {
- return m_pGCHandle.AddrOfPinnedObject();
- }
-
- [StructLayout( LayoutKind.Sequential )]
- internal class VTable
- {
- [UnmanagedFunctionPointer( CallingConvention.ThisCall )]
- internal delegate void InternalServerResponded( IntPtr thisptr, IntPtr hRequest, int iServer );
- [UnmanagedFunctionPointer( CallingConvention.ThisCall )]
- internal delegate void InternalServerFailedToRespond( IntPtr thisptr, IntPtr hRequest, int iServer );
- [UnmanagedFunctionPointer( CallingConvention.ThisCall )]
- internal delegate void InternalRefreshComplete( IntPtr thisptr, IntPtr hRequest, int response );
-
- [NonSerialized, MarshalAs(UnmanagedType.FunctionPtr)]
- internal InternalServerResponded responded;
- [NonSerialized, MarshalAs(UnmanagedType.FunctionPtr)]
- internal InternalServerFailedToRespond nonresponsive;
- [NonSerialized, MarshalAs(UnmanagedType.FunctionPtr)]
- internal InternalRefreshComplete complete;
- }
}
}
}
diff --git a/Facepunch.Steamworks/Client.ServerList.cs b/Facepunch.Steamworks/Client.ServerList.cs
index 7c651af..2f113a3 100644
--- a/Facepunch.Steamworks/Client.ServerList.cs
+++ b/Facepunch.Steamworks/Client.ServerList.cs
@@ -48,25 +48,41 @@ public unsafe Request Test()
//fixed ( void* a = array )
{
- var request = new Request()
- {
- client = client
- };
+ var request = new Request( client );
- request.Id = client.native.servers.RequestInternetServerList( client.AppId, new IntPtr[] { }, request.GetVTablePointer() );
+ request.Id = client.native.servers.RequestInternetServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero );
return request;
}
}
+ class ResponseClass : ISteamMatchmakingServerListResponse
+ {
+ internal override IntPtr GetIntPtr()
+ {
+ return IntPtr.Zero;
+ }
+
+ internal override void RefreshComplete( uint hRequest, uint response )
+ {
+ throw new NotImplementedException();
+ }
+
+ internal override void ServerFailedToRespond( uint hRequest, int iServer )
+ {
+ throw new NotImplementedException();
+ }
+
+ internal override void ServerResponded( uint hRequest, int iServer )
+ {
+ throw new NotImplementedException();
+ }
+ }
+
public unsafe Request History( Dictionary< string, string > filter )
{
- var request = new Request()
- {
- client = client
- };
-
- request.Id = client.native.servers.RequestHistoryServerList( client.AppId, new IntPtr[] { }, request.GetVTablePointer() );
+ var request = new Request( client );
+ request.Id = client.native.servers.RequestHistoryServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero );
return request;
}
diff --git a/Facepunch.Steamworks/Client.cs b/Facepunch.Steamworks/Client.cs
index de3b14d..e23ee1a 100644
--- a/Facepunch.Steamworks/Client.cs
+++ b/Facepunch.Steamworks/Client.cs
@@ -139,7 +139,7 @@ public Client( uint appId )
public void Dispose()
{
- if ( native != null)
+ if ( native != null)
{
native.Dispose();
native = null;
@@ -157,15 +157,23 @@ private void InternalOnWarning( int nSeverity, System.Text.StringBuilder text )
}
}
+ internal event Action OnUpdate;
+
///
/// Should be called at least once every frame
///
public void Update()
{
+ if ( native == null )
+ return;
+
Valve.Steamworks.SteamAPI.RunCallbacks();
Voice.Update();
Inventory.Update();
Networking.Update();
+
+ if ( OnUpdate != null )
+ OnUpdate();
}
public bool Valid
diff --git a/Facepunch.Steamworks/Client/Stats.cs b/Facepunch.Steamworks/Client/Stats.cs
index 6a55211..8d0ff39 100644
--- a/Facepunch.Steamworks/Client/Stats.cs
+++ b/Facepunch.Steamworks/Client/Stats.cs
@@ -44,22 +44,30 @@ public void UpdateGlobalStats( int days = 1 )
public int GetInt( string name )
{
- return 0;
+ int data = 0;
+ client.native.userstats.GetStat( name, ref data );
+ return data;
}
- public int GetGlobalInt( string name )
+ public long GetGlobalInt( string name )
{
- return 0;
+ long data = 0;
+ client.native.userstats.GetGlobalStat( name, ref data );
+ return data;
}
- public int GetFloat( string name )
+ public float GetFloat( string name )
{
- return 0;
+ float data = 0;
+ client.native.userstats.GetStat0( name, ref data );
+ return data;
}
- public int GetGlobalFloat( string name )
+ public double GetGlobalFloat( string name )
{
- return 0;
+ double data = 0;
+ client.native.userstats.GetGlobalStat0( name, ref data );
+ return data;
}
}