From b509b92b38d7633be1a5e3b6fb0f6a7cc7f6b06f Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Thu, 29 Sep 2016 16:07:59 +0100 Subject: [PATCH] Broken, some garbage errors or something --- Facepunch.Steamworks.Test/Serverlist.cs | 6 + .../Facepunch.Steamworks.csproj | 4 +- Facepunch.Steamworks/Interop/ServerRules.cs | 142 ++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 Facepunch.Steamworks/Interop/ServerRules.cs diff --git a/Facepunch.Steamworks.Test/Serverlist.cs b/Facepunch.Steamworks.Test/Serverlist.cs index e0b45b0..d0c687a 100644 --- a/Facepunch.Steamworks.Test/Serverlist.cs +++ b/Facepunch.Steamworks.Test/Serverlist.cs @@ -306,7 +306,9 @@ public void Rules() for ( int i = 0; i < 1000; i++ ) { + GC.Collect(); client.Update(); + GC.Collect(); System.Threading.Thread.Sleep( 10 ); if ( query.Responded.Count > 20 ) @@ -320,13 +322,17 @@ public void Rules() foreach ( var server in query.Responded.Take( 20 ) ) { + GC.Collect(); server.FetchRules(); + GC.Collect(); int i = 0; while ( !server.HasRules ) { i++; + GC.Collect(); client.Update(); + GC.Collect(); System.Threading.Thread.Sleep( 2 ); if ( i > 100 ) diff --git a/Facepunch.Steamworks/Facepunch.Steamworks.csproj b/Facepunch.Steamworks/Facepunch.Steamworks.csproj index f32b152..d4ca9cb 100644 --- a/Facepunch.Steamworks/Facepunch.Steamworks.csproj +++ b/Facepunch.Steamworks/Facepunch.Steamworks.csproj @@ -119,6 +119,7 @@ + @@ -126,10 +127,11 @@ + - + diff --git a/Facepunch.Steamworks/Interop/ServerRules.cs b/Facepunch.Steamworks/Interop/ServerRules.cs new file mode 100644 index 0000000..5c03445 --- /dev/null +++ b/Facepunch.Steamworks/Interop/ServerRules.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Facepunch.Steamworks.Interop +{ + class ServerRules + { + private GCHandle thisPin; + private IntPtr vTablePtr; + private GCHandle vTableHandle; + + private ServerList.Server Server; + + public ServerRules( ServerList.Server server, uint address, int queryPort ) + { + Server = server; + + InstallVTable(); + + Valve.Interop.NativeEntrypoints.SteamAPI_ISteamMatchmakingServers_ServerRules( Server.Client.native.servers.GetIntPtr(), address, (short) queryPort, GetPtr() ); + } + + void InstallVTable() + { + GC.KeepAlive( Server ); + GC.SuppressFinalize( Server ); + + if ( Server.Client.UseThisCall ) + { + var t = new ThisVTable() + { + m_VTRulesResponded = ( _, k, v ) => InternalOnRulesResponded( k, v ), + m_VTRulesFailedToRespond = ( _ ) => InternalOnRulesFailedToRespond(), + m_VTRulesRefreshComplete = ( _ ) => InternalOnRulesRefreshComplete(), + }; + vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( ThisVTable ) ) ); + Marshal.StructureToPtr( t, vTablePtr, false ); + + vTableHandle = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned ); + + } + else + { + var t = new StdVTable() + { + m_VTRulesResponded = InternalOnRulesResponded, + m_VTRulesFailedToRespond = InternalOnRulesFailedToRespond, + m_VTRulesRefreshComplete = InternalOnRulesRefreshComplete + }; + vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( StdVTable ) ) ); + Marshal.StructureToPtr( t, vTablePtr, false ); + + vTableHandle = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned ); + } + } + + void Unpin() + { + if ( vTablePtr != IntPtr.Zero ) + { + Marshal.FreeHGlobal( vTablePtr ); + } + + if ( vTableHandle.IsAllocated ) + { + vTableHandle.Free(); + } + + if ( thisPin.IsAllocated ) + { + thisPin.Free(); + } + } + + private void InternalOnRulesResponded( IntPtr k, IntPtr v ) + { + // Server.Rules.Add( k, v ); + } + private void InternalOnRulesFailedToRespond() + { + Server.OnServerRulesReceiveFinished( false ); + } + private void InternalOnRulesRefreshComplete() + { + Server.OnServerRulesReceiveFinished( true ); + } + + [StructLayout( LayoutKind.Sequential )] + private class StdVTable + { + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesResponded m_VTRulesResponded; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesFailedToRespond m_VTRulesFailedToRespond; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesRefreshComplete m_VTRulesRefreshComplete; + + [UnmanagedFunctionPointer( CallingConvention.StdCall )] + public delegate void InternalRulesResponded( IntPtr pchRule, IntPtr pchValue ); + [UnmanagedFunctionPointer( CallingConvention.StdCall )] + public delegate void InternalRulesFailedToRespond(); + [UnmanagedFunctionPointer( CallingConvention.StdCall )] + public delegate void InternalRulesRefreshComplete(); + } + + [StructLayout( LayoutKind.Sequential )] + private class ThisVTable + { + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesResponded m_VTRulesResponded; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesFailedToRespond m_VTRulesFailedToRespond; + + [NonSerialized] + [MarshalAs(UnmanagedType.FunctionPtr)] + public InternalRulesRefreshComplete m_VTRulesRefreshComplete; + + [UnmanagedFunctionPointer( CallingConvention.ThisCall )] + public delegate void InternalRulesResponded( IntPtr thisptr, IntPtr pchRule, IntPtr pchValue ); + [UnmanagedFunctionPointer( CallingConvention.ThisCall )] + public delegate void InternalRulesFailedToRespond( IntPtr thisptr ); + [UnmanagedFunctionPointer( CallingConvention.ThisCall )] + public delegate void InternalRulesRefreshComplete( IntPtr thisptr ); + } + + public System.IntPtr GetPtr() + { + return vTableHandle.AddrOfPinnedObject(); + } + }; +}