mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-24 13:45:37 +03:00
SteamApps events
This commit is contained in:
parent
027a110c61
commit
cd30b85444
129
Facepunch.Steamworks/Callbacks/Events.cs
Normal file
129
Facepunch.Steamworks/Callbacks/Events.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SteamNative;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
//
|
||||
// Created on registration of a callback
|
||||
//
|
||||
internal class Event<T> : IDisposable where T : struct, Steamworks.ISteamCallback
|
||||
{
|
||||
public Action<T> Action;
|
||||
|
||||
List<GCHandle> Allocations = new List<GCHandle>();
|
||||
internal IntPtr vTablePtr;
|
||||
internal GCHandle PinnedCallback;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UnregisterCallback();
|
||||
|
||||
foreach ( var a in Allocations )
|
||||
{
|
||||
if ( a.IsAllocated )
|
||||
a.Free();
|
||||
}
|
||||
|
||||
Allocations.Clear();
|
||||
|
||||
if ( PinnedCallback.IsAllocated )
|
||||
PinnedCallback.Free();
|
||||
|
||||
if ( vTablePtr != IntPtr.Zero )
|
||||
{
|
||||
Marshal.FreeHGlobal( vTablePtr );
|
||||
vTablePtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnregisterCallback()
|
||||
{
|
||||
if ( !PinnedCallback.IsAllocated )
|
||||
return;
|
||||
|
||||
Steam.UnregisterCallback( PinnedCallback.AddrOfPinnedObject() );
|
||||
}
|
||||
|
||||
public virtual bool IsValid { get { return true; } }
|
||||
|
||||
T template;
|
||||
|
||||
internal Event( Action<T> onresult, bool gameserver = false )
|
||||
{
|
||||
Action = onresult;
|
||||
|
||||
template = new T();
|
||||
|
||||
//
|
||||
// Create the functions we need for the vtable
|
||||
//
|
||||
if ( Facepunch.Steamworks.Config.UseThisCall )
|
||||
{
|
||||
//
|
||||
// Create the VTable by manually allocating the memory and copying across
|
||||
//
|
||||
if ( Platform.IsWindows )
|
||||
{
|
||||
vTablePtr = Callback.VTableWinThis.GetVTable( OnResultThis, OnResultWithInfoThis, OnGetSizeThis, Allocations );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
vTablePtr = Callback.VTableThis.GetVTable( OnResultThis, OnResultWithInfoThis, OnGetSizeThis, Allocations );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Create the VTable by manually allocating the memory and copying across
|
||||
//
|
||||
if ( Platform.IsWindows )
|
||||
{
|
||||
vTablePtr = Callback.VTableWin.GetVTable( OnResult, OnResultWithInfo, OnGetSize, Allocations );
|
||||
}
|
||||
else
|
||||
{
|
||||
vTablePtr = Callback.VTable.GetVTable( OnResult, OnResultWithInfo, OnGetSize, Allocations );
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create the callback object
|
||||
//
|
||||
var cb = new Callback();
|
||||
cb.vTablePtr = vTablePtr;
|
||||
cb.CallbackFlags = gameserver ? (byte)0x02 : (byte)0;
|
||||
cb.CallbackId = template.GetCallbackId();
|
||||
|
||||
//
|
||||
// Pin the callback, so it doesn't get garbage collected and we can pass the pointer to native
|
||||
//
|
||||
PinnedCallback = GCHandle.Alloc( cb, GCHandleType.Pinned );
|
||||
|
||||
//
|
||||
// Register the callback with Steam
|
||||
//
|
||||
Steam.RegisterCallback( PinnedCallback.AddrOfPinnedObject(), cb.CallbackId );
|
||||
}
|
||||
|
||||
[MonoPInvokeCallback] internal void OnResultThis( IntPtr self, IntPtr param ) => OnResult( param );
|
||||
[MonoPInvokeCallback] internal void OnResultWithInfoThis( IntPtr self, IntPtr param, bool failure, SteamNative.SteamAPICall_t call ) => OnResultWithInfo( param, failure, call );
|
||||
[MonoPInvokeCallback] internal int OnGetSizeThis( IntPtr self ) => OnGetSize();
|
||||
[MonoPInvokeCallback] internal int OnGetSize() => template.GetStructSize();
|
||||
[MonoPInvokeCallback] internal void OnResult( IntPtr param ) => OnResultWithInfo( param, false, 0 );
|
||||
|
||||
[MonoPInvokeCallback]
|
||||
internal void OnResultWithInfo( IntPtr param, bool failure, SteamNative.SteamAPICall_t call )
|
||||
{
|
||||
if ( failure ) return;
|
||||
|
||||
var value = (T)template.Fill( param );
|
||||
|
||||
Action( value );
|
||||
}
|
||||
}
|
||||
}
|
@ -12,5 +12,14 @@ public static class SteamApi
|
||||
|
||||
[DllImport( "Steam_api64", EntryPoint = "SteamAPI_GetHSteamUser", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern int GetHSteamUser();
|
||||
|
||||
|
||||
[DllImport( "Steam_api64", EntryPoint = "SteamAPI_RunCallbacks", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern int RunCallbacks();
|
||||
|
||||
[DllImport( "Steam_api64", EntryPoint = "SteamAPI_RegisterCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern int RegisterCallback( IntPtr pCallback, int callback );
|
||||
|
||||
[DllImport( "Steam_api64", EntryPoint = "SteamAPI_UnregisterCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern int UnregisterCallback( IntPtr pCallback );
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using SteamNative;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -24,6 +25,24 @@ internal static Internal.ISteamApps steamapps
|
||||
}
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
new Event<DlcInstalled_t>( x => OnDlcInstalled( x.AppID ) );
|
||||
new Event<NewUrlLaunchParameters_t>( x => OnNewLaunchParameters() );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// posted after the user gains ownership of DLC & that DLC is installed
|
||||
/// </summary>
|
||||
public static event Action< AppId > OnDlcInstalled;
|
||||
|
||||
/// <summary>
|
||||
/// posted after the user gains executes a Steam URL with command line or query parameters
|
||||
/// such as steam://run/appid//-commandline/?param1=value1¶m2=value2¶m3=value3 etc
|
||||
/// while the game is already running. The new params can be queried
|
||||
/// with GetLaunchQueryParam and GetLaunchCommandLine
|
||||
/// </summary>
|
||||
public static event Action OnNewLaunchParameters;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the active user is subscribed to the current App ID
|
||||
|
@ -31,5 +31,15 @@ public static void Init( uint appid )
|
||||
throw new System.Exception( "GetHSteamUser returned 0" );
|
||||
}
|
||||
}
|
||||
|
||||
internal static void RegisterCallback( IntPtr intPtr, int callbackId )
|
||||
{
|
||||
SteamApi.RegisterCallback( intPtr, callbackId );
|
||||
}
|
||||
|
||||
internal static void UnregisterCallback( IntPtr intPtr )
|
||||
{
|
||||
SteamApi.UnregisterCallback( intPtr );
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using Facepunch.Steamworks;
|
||||
|
||||
namespace SteamNative
|
||||
@ -27,7 +28,27 @@ public class VTable
|
||||
public ResultD ResultA;
|
||||
public ResultWithInfoD ResultB;
|
||||
public GetSizeD GetSize;
|
||||
}
|
||||
|
||||
internal static IntPtr GetVTable( ResultD onResultThis, ResultWithInfoD onResultWithInfoThis, GetSizeD onGetSizeThis, List<GCHandle> allocations )
|
||||
{
|
||||
var vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTable ) ) );
|
||||
|
||||
var vTable = new Callback.VTable
|
||||
{
|
||||
ResultA = onResultThis,
|
||||
ResultB = onResultWithInfoThis,
|
||||
GetSize = onGetSizeThis,
|
||||
};
|
||||
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultA ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultB ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.GetSize ) );
|
||||
|
||||
Marshal.StructureToPtr( vTable, vTablePtr, false );
|
||||
|
||||
return vTablePtr;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||
public class VTableWin
|
||||
@ -39,14 +60,55 @@ public class VTableWin
|
||||
public ResultWithInfoD ResultB;
|
||||
public ResultD ResultA;
|
||||
public GetSizeD GetSize;
|
||||
}
|
||||
|
||||
internal static IntPtr GetVTable( ResultD onResultThis, ResultWithInfoD onResultWithInfoThis, GetSizeD onGetSizeThis, List<GCHandle> allocations )
|
||||
{
|
||||
var vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTableWin ) ) );
|
||||
|
||||
var vTable = new Callback.VTableWin
|
||||
{
|
||||
ResultA = onResultThis,
|
||||
ResultB = onResultWithInfoThis,
|
||||
GetSize = onGetSizeThis,
|
||||
};
|
||||
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultA ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultB ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.GetSize ) );
|
||||
|
||||
Marshal.StructureToPtr( vTable, vTablePtr, false );
|
||||
|
||||
return vTablePtr;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||
public class VTableThis
|
||||
{
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void ResultD( IntPtr thisptr, IntPtr pvParam );
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void ResultWithInfoD( IntPtr thisptr, IntPtr pvParam, bool bIOFailure, SteamNative.SteamAPICall_t hSteamAPICall );
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate int GetSizeD( IntPtr thisptr );
|
||||
|
||||
internal static IntPtr GetVTable( ResultD onResultThis, ResultWithInfoD onResultWithInfoThis, GetSizeD onGetSizeThis, List<GCHandle> allocations )
|
||||
{
|
||||
var vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTableThis ) ) );
|
||||
|
||||
var vTable = new Callback.VTableThis
|
||||
{
|
||||
ResultA = onResultThis,
|
||||
ResultB = onResultWithInfoThis,
|
||||
GetSize = onGetSizeThis,
|
||||
};
|
||||
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultA ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultB ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.GetSize ) );
|
||||
|
||||
Marshal.StructureToPtr( vTable, vTablePtr, false );
|
||||
|
||||
return vTablePtr;
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate int GetSizeD( IntPtr thisptr );
|
||||
|
||||
public ResultD ResultA;
|
||||
public ResultWithInfoD ResultB;
|
||||
@ -63,7 +125,27 @@ public class VTableWinThis
|
||||
public ResultWithInfoD ResultB;
|
||||
public ResultD ResultA;
|
||||
public GetSizeD GetSize;
|
||||
}
|
||||
|
||||
internal static IntPtr GetVTable( ResultD onResultThis, ResultWithInfoD onResultWithInfoThis, GetSizeD onGetSizeThis, List<GCHandle> allocations )
|
||||
{
|
||||
var vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTableWinThis ) ) );
|
||||
|
||||
var vTable = new Callback.VTableWinThis
|
||||
{
|
||||
ResultA = onResultThis,
|
||||
ResultB = onResultWithInfoThis,
|
||||
GetSize = onGetSizeThis,
|
||||
};
|
||||
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultA ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.ResultB ) );
|
||||
allocations.Add( GCHandle.Alloc( vTable.GetSize ) );
|
||||
|
||||
Marshal.StructureToPtr( vTable, vTablePtr, false );
|
||||
|
||||
return vTablePtr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user