mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-25 14:15:47 +03:00
Pin the SererRules functions so they don't get collected etc
This commit is contained in:
parent
01c8083869
commit
0cf2761166
@ -127,6 +127,7 @@
|
|||||||
<Compile Include="Client\Screenshots.cs" />
|
<Compile Include="Client\Screenshots.cs" />
|
||||||
<Compile Include="Client\Stats.cs" />
|
<Compile Include="Client\Stats.cs" />
|
||||||
<Compile Include="Client\Voice.cs" />
|
<Compile Include="Client\Voice.cs" />
|
||||||
|
<Compile Include="Config.cs" />
|
||||||
<Compile Include="Interop\ServerRules.cs" />
|
<Compile Include="Interop\ServerRules.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="steam_api_interop.cs" />
|
<Compile Include="steam_api_interop.cs" />
|
||||||
|
@ -8,52 +8,83 @@ namespace Facepunch.Steamworks.Interop
|
|||||||
{
|
{
|
||||||
class ServerRules
|
class ServerRules
|
||||||
{
|
{
|
||||||
private GCHandle thisPin;
|
// Pins and pointers for the created vtable
|
||||||
|
private GCHandle vTablePin;
|
||||||
private IntPtr vTablePtr;
|
private IntPtr vTablePtr;
|
||||||
private GCHandle vTableHandle;
|
|
||||||
|
|
||||||
|
// Pins for the functions
|
||||||
|
private GCHandle RulesRespondPin;
|
||||||
|
private GCHandle FailedRespondPin;
|
||||||
|
private GCHandle CompletePin;
|
||||||
|
|
||||||
|
// The server that called us
|
||||||
private ServerList.Server Server;
|
private ServerList.Server Server;
|
||||||
|
|
||||||
public ServerRules( ServerList.Server server, uint address, int queryPort )
|
public ServerRules( ServerList.Server server, uint address, int queryPort )
|
||||||
{
|
{
|
||||||
Server = server;
|
Server = server;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a fake VTable to pass to c++
|
||||||
|
//
|
||||||
InstallVTable();
|
InstallVTable();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Ask Steam to get the server rules, respond to our fake vtable
|
||||||
|
//
|
||||||
Valve.Interop.NativeEntrypoints.SteamAPI_ISteamMatchmakingServers_ServerRules( Server.Client.native.servers.GetIntPtr(), address, (short) queryPort, GetPtr() );
|
Valve.Interop.NativeEntrypoints.SteamAPI_ISteamMatchmakingServers_ServerRules( Server.Client.native.servers.GetIntPtr(), address, (short) queryPort, GetPtr() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallVTable()
|
void InstallVTable()
|
||||||
{
|
{
|
||||||
GC.KeepAlive( Server );
|
|
||||||
GC.SuppressFinalize( Server );
|
|
||||||
|
|
||||||
if ( Server.Client.UseThisCall )
|
//
|
||||||
|
// Depending on platform, we either use ThisCall or stdcall.
|
||||||
|
// This is a bit of a fuckabout but you need to define Client.UseThisCall
|
||||||
|
//
|
||||||
|
|
||||||
|
if ( Config.UseThisCall )
|
||||||
{
|
{
|
||||||
|
ThisVTable.InternalRulesResponded da = ( _, k, v ) => InternalOnRulesResponded( k, v );
|
||||||
|
ThisVTable.InternalRulesFailedToRespond db = ( _ ) => InternalOnRulesFailedToRespond();
|
||||||
|
ThisVTable.InternalRulesRefreshComplete dc = ( _ ) => InternalOnRulesRefreshComplete();
|
||||||
|
|
||||||
|
RulesRespondPin = GCHandle.Alloc( da );
|
||||||
|
FailedRespondPin = GCHandle.Alloc( db );
|
||||||
|
CompletePin = GCHandle.Alloc( dc );
|
||||||
|
|
||||||
var t = new ThisVTable()
|
var t = new ThisVTable()
|
||||||
{
|
{
|
||||||
m_VTRulesResponded = ( _, k, v ) => InternalOnRulesResponded( k, v ),
|
m_VTRulesResponded = da,
|
||||||
m_VTRulesFailedToRespond = ( _ ) => InternalOnRulesFailedToRespond(),
|
m_VTRulesFailedToRespond = db,
|
||||||
m_VTRulesRefreshComplete = ( _ ) => InternalOnRulesRefreshComplete(),
|
m_VTRulesRefreshComplete = dc,
|
||||||
};
|
};
|
||||||
vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( ThisVTable ) ) );
|
vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( ThisVTable ) ) );
|
||||||
Marshal.StructureToPtr( t, vTablePtr, false );
|
Marshal.StructureToPtr( t, vTablePtr, false );
|
||||||
|
|
||||||
vTableHandle = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
vTablePin = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
StdVTable.InternalRulesResponded da = InternalOnRulesResponded;
|
||||||
|
StdVTable.InternalRulesFailedToRespond db = InternalOnRulesFailedToRespond;
|
||||||
|
StdVTable.InternalRulesRefreshComplete dc = InternalOnRulesRefreshComplete;
|
||||||
|
|
||||||
|
RulesRespondPin = GCHandle.Alloc( da );
|
||||||
|
FailedRespondPin = GCHandle.Alloc( db );
|
||||||
|
CompletePin = GCHandle.Alloc( dc );
|
||||||
|
|
||||||
var t = new StdVTable()
|
var t = new StdVTable()
|
||||||
{
|
{
|
||||||
m_VTRulesResponded = InternalOnRulesResponded,
|
m_VTRulesResponded = da,
|
||||||
m_VTRulesFailedToRespond = InternalOnRulesFailedToRespond,
|
m_VTRulesFailedToRespond = db,
|
||||||
m_VTRulesRefreshComplete = InternalOnRulesRefreshComplete
|
m_VTRulesRefreshComplete = dc
|
||||||
};
|
};
|
||||||
vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( StdVTable ) ) );
|
vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( StdVTable ) ) );
|
||||||
Marshal.StructureToPtr( t, vTablePtr, false );
|
Marshal.StructureToPtr( t, vTablePtr, false );
|
||||||
|
|
||||||
vTableHandle = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
vTablePin = GCHandle.Alloc( vTablePtr, GCHandleType.Pinned );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,22 +93,26 @@ void Unpin()
|
|||||||
if ( vTablePtr != IntPtr.Zero )
|
if ( vTablePtr != IntPtr.Zero )
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal( vTablePtr );
|
Marshal.FreeHGlobal( vTablePtr );
|
||||||
|
vTablePtr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( vTableHandle.IsAllocated )
|
if ( vTablePin.IsAllocated )
|
||||||
{
|
vTablePin.Free();
|
||||||
vTableHandle.Free();
|
|
||||||
|
if ( RulesRespondPin.IsAllocated )
|
||||||
|
vTablePin.Free();
|
||||||
|
|
||||||
|
if ( FailedRespondPin.IsAllocated )
|
||||||
|
vTablePin.Free();
|
||||||
|
|
||||||
|
if ( CompletePin.IsAllocated )
|
||||||
|
vTablePin.Free();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( thisPin.IsAllocated )
|
private void InternalOnRulesResponded( string k, string v )
|
||||||
{
|
{
|
||||||
thisPin.Free();
|
Server.Rules.Add( k, v );
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InternalOnRulesResponded( IntPtr k, IntPtr v )
|
|
||||||
{
|
|
||||||
// Server.Rules.Add( k, v );
|
|
||||||
}
|
}
|
||||||
private void InternalOnRulesFailedToRespond()
|
private void InternalOnRulesFailedToRespond()
|
||||||
{
|
{
|
||||||
@ -91,20 +126,17 @@ private void InternalOnRulesRefreshComplete()
|
|||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
private class StdVTable
|
private class StdVTable
|
||||||
{
|
{
|
||||||
[NonSerialized]
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
public InternalRulesResponded m_VTRulesResponded;
|
public InternalRulesResponded m_VTRulesResponded;
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
|
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
|
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
|
||||||
|
|
||||||
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
||||||
public delegate void InternalRulesResponded( IntPtr pchRule, IntPtr pchValue );
|
public delegate void InternalRulesResponded( string pchRule, string pchValue );
|
||||||
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
||||||
public delegate void InternalRulesFailedToRespond();
|
public delegate void InternalRulesFailedToRespond();
|
||||||
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
||||||
@ -114,20 +146,17 @@ private class StdVTable
|
|||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
private class ThisVTable
|
private class ThisVTable
|
||||||
{
|
{
|
||||||
[NonSerialized]
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
public InternalRulesResponded m_VTRulesResponded;
|
public InternalRulesResponded m_VTRulesResponded;
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
|
public InternalRulesFailedToRespond m_VTRulesFailedToRespond;
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
||||||
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
|
public InternalRulesRefreshComplete m_VTRulesRefreshComplete;
|
||||||
|
|
||||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||||
public delegate void InternalRulesResponded( IntPtr thisptr, IntPtr pchRule, IntPtr pchValue );
|
public delegate void InternalRulesResponded( IntPtr thisptr, string pchRule, string pchValue );
|
||||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||||
public delegate void InternalRulesFailedToRespond( IntPtr thisptr );
|
public delegate void InternalRulesFailedToRespond( IntPtr thisptr );
|
||||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||||
@ -136,7 +165,7 @@ private class ThisVTable
|
|||||||
|
|
||||||
public System.IntPtr GetPtr()
|
public System.IntPtr GetPtr()
|
||||||
{
|
{
|
||||||
return vTableHandle.AddrOfPinnedObject();
|
return vTablePin.AddrOfPinnedObject();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user