SteamApiCallback to result

This commit is contained in:
Garry Newman 2019-04-13 22:02:52 +01:00
parent 76c82bff25
commit 173a132d6e
10 changed files with 205 additions and 27 deletions

View File

@ -17,6 +17,11 @@ public static void AssemblyInit( TestContext context )
Steamworks.Steam.Init( 4000 );
}
static void OnNewUrlLaunchParameters()
{
// Wow!
}
[TestMethod]
public void GameLangauge()
{

View File

@ -0,0 +1,11 @@
using System;
namespace Steamworks
{
public interface ISteamCallback
{
int GetCallbackId();
int GetStructSize();
ISteamCallback Fill( IntPtr ptr, int size );
}
}

View File

@ -7,11 +7,14 @@
namespace Steamworks
{
public struct SteamApiCallback<T> where T : struct, ISteamCallback
/// <summary>
/// Results are Steam Callbacks that are direct responses to function calls
/// </summary>
public struct Result<T> where T : struct, ISteamCallback
{
public ulong CallHandle;
public SteamApiCallback( ulong callbackHandle )
public Result( ulong callbackHandle )
{
CallHandle = callbackHandle;
}
@ -36,11 +39,4 @@ public bool IsComplete( out bool failed )
return Utils.GetResult<T>( CallHandle );
}
}
public interface ISteamCallback
{
int GetCallbackId();
int GetStructSize();
ISteamCallback Fill( IntPtr ptr, int size );
}
}

View File

@ -17,7 +17,7 @@ internal App( Client c )
client.RegisterCallback<SteamNative.DlcInstalled_t>( DlcInstalled );
}
public delegate void DlcInstalledDelegate( uint appid );
public delegate void DlcInstalledDelegate( uint appid );
/// <summary>
/// Triggered after the current user gains ownership of DLC and that DLC is installed.

View File

@ -340,7 +340,7 @@ public void RequestAllProofOfPurchaseKeys()
#endregion
public async Task<FileDetailsResult_t?> GetFileDetails( string pszFileName )
{
return await (new SteamApiCallback<FileDetailsResult_t>( GetFileDetailsDelegatePointer( Self, pszFileName ) )).GetResult();
return await (new Result<FileDetailsResult_t>( GetFileDetailsDelegatePointer( Self, pszFileName ) )).GetResult();
}
#region FunctionMeta

View File

@ -269,7 +269,7 @@ public bool BOverlayNeedsPresent()
#endregion
public async Task<CheckFileSignature_t?> CheckFileSignature( string szFileName )
{
return await (new SteamApiCallback<CheckFileSignature_t>( CheckFileSignatureDelegatePointer( Self, szFileName ) )).GetResult();
return await (new Result<CheckFileSignature_t>( CheckFileSignatureDelegatePointer( Self, szFileName ) )).GetResult();
}
#region FunctionMeta

View File

@ -24,6 +24,7 @@ internal static Internal.ISteamApps steamapps
}
}
/// <summary>
/// Checks if the active user is subscribed to the current App ID
/// </summary>

View File

@ -31481,6 +31481,171 @@ internal static void OnResultWithInfo( IntPtr param, bool failure, SteamNative.S
}
}
public struct NewUrlLaunchParameters_t : Steamworks.ISteamCallback
{
internal const int CallbackId = CallbackIdentifiers.SteamApps + 14;
public int GetCallbackId() => CallbackId;
public int GetStructSize() => StructSize();
public Steamworks.ISteamCallback Fill( IntPtr p, int size)
{
return FromPointer( p ); // TODO - USE SIZE HERE SOMEHOW
}
//
// Read this struct from a pointer, usually from Native. It will automatically do the awesome stuff.
//
internal static NewUrlLaunchParameters_t FromPointer( IntPtr p ) =>
Platform.PackSmall ? ((NewUrlLaunchParameters_t)(Pack4) Marshal.PtrToStructure( p, typeof(Pack4) )) : ((NewUrlLaunchParameters_t)(Pack8) Marshal.PtrToStructure( p, typeof(Pack8) ));
//
// Get the size of the structure we're going to be using.
//
internal static int StructSize()
{
return System.Runtime.InteropServices.Marshal.SizeOf( Platform.PackSmall ? typeof(Pack4) : typeof(Pack8) );
}
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
public struct Pack4
{
public static implicit operator NewUrlLaunchParameters_t ( NewUrlLaunchParameters_t.Pack4 d ) => new NewUrlLaunchParameters_t{ };
}
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
public struct Pack8
{
public static implicit operator NewUrlLaunchParameters_t ( NewUrlLaunchParameters_t.Pack8 d ) => new NewUrlLaunchParameters_t{ };
}
internal static void Register( Facepunch.Steamworks.BaseSteamworks steamworks )
{
var handle = new CallbackHandle( steamworks );
//
// 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 )
{
handle.vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTableWinThis ) ) );
var vTable = new Callback.VTableWinThis
{
ResultA = OnResultThis,
ResultB = OnResultWithInfoThis,
GetSize = OnGetSizeThis,
};
handle.FuncA = GCHandle.Alloc( vTable.ResultA );
handle.FuncB = GCHandle.Alloc( vTable.ResultB );
handle.FuncC = GCHandle.Alloc( vTable.GetSize );
Marshal.StructureToPtr( vTable, handle.vTablePtr, false );
}
else
{
handle.vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTableThis ) ) );
var vTable = new Callback.VTableThis
{
ResultA = OnResultThis,
ResultB = OnResultWithInfoThis,
GetSize = OnGetSizeThis,
};
handle.FuncA = GCHandle.Alloc( vTable.ResultA );
handle.FuncB = GCHandle.Alloc( vTable.ResultB );
handle.FuncC = GCHandle.Alloc( vTable.GetSize );
Marshal.StructureToPtr( vTable, handle.vTablePtr, false );
}
}
else
{
//
// Create the VTable by manually allocating the memory and copying across
//
if ( Platform.IsWindows )
{
handle.vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTableWin ) ) );
var vTable = new Callback.VTableWin
{
ResultA = OnResult,
ResultB = OnResultWithInfo,
GetSize = OnGetSize,
};
handle.FuncA = GCHandle.Alloc( vTable.ResultA );
handle.FuncB = GCHandle.Alloc( vTable.ResultB );
handle.FuncC = GCHandle.Alloc( vTable.GetSize );
Marshal.StructureToPtr( vTable, handle.vTablePtr, false );
}
else
{
handle.vTablePtr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback.VTable ) ) );
var vTable = new Callback.VTable
{
ResultA = OnResult,
ResultB = OnResultWithInfo,
GetSize = OnGetSize,
};
handle.FuncA = GCHandle.Alloc( vTable.ResultA );
handle.FuncB = GCHandle.Alloc( vTable.ResultB );
handle.FuncC = GCHandle.Alloc( vTable.GetSize );
Marshal.StructureToPtr( vTable, handle.vTablePtr, false );
}
}
//
// Create the callback object
//
var cb = new Callback();
cb.vTablePtr = handle.vTablePtr;
cb.CallbackFlags = steamworks.IsGameServer ? (byte) SteamNative.Callback.Flags.GameServer : (byte) 0;
cb.CallbackId = CallbackId;
//
// Pin the callback, so it doesn't get garbage collected and we can pass the pointer to native
//
handle.PinnedCallback = GCHandle.Alloc( cb, GCHandleType.Pinned );
//
// Register the callback with Steam
//
steamworks.native.api.SteamAPI_RegisterCallback( handle.PinnedCallback.AddrOfPinnedObject(), CallbackId );
steamworks.RegisterCallbackHandle( handle );
}
[MonoPInvokeCallback]
internal static void OnResultThis( IntPtr self, IntPtr param ){ OnResult( param ); }
[MonoPInvokeCallback]
internal static void OnResultWithInfoThis( IntPtr self, IntPtr param, bool failure, SteamNative.SteamAPICall_t call ){ OnResultWithInfo( param, failure, call ); }
[MonoPInvokeCallback]
internal static int OnGetSizeThis( IntPtr self ){ return OnGetSize(); }
[MonoPInvokeCallback]
internal static int OnGetSize(){ return StructSize(); }
[MonoPInvokeCallback]
internal static void OnResult( IntPtr param )
{
OnResultWithInfo( param, false, 0 );
}
[MonoPInvokeCallback]
internal static void OnResultWithInfo( IntPtr param, bool failure, SteamNative.SteamAPICall_t call )
{
if ( failure ) return;
var value = FromPointer( param );
if ( Facepunch.Steamworks.Client.Instance != null )
Facepunch.Steamworks.Client.Instance.OnCallback<NewUrlLaunchParameters_t>( value );
if ( Facepunch.Steamworks.Server.Instance != null )
Facepunch.Steamworks.Server.Instance.OnCallback<NewUrlLaunchParameters_t>( value );
}
}
public struct ItemInstalled_t : Steamworks.ISteamCallback
{
internal const int CallbackId = CallbackIdentifiers.ClientUGC + 5;
@ -33670,6 +33835,7 @@ internal static void RegisterCallbacks( Facepunch.Steamworks.BaseSteamworks stea
GSStatsReceived_t.Register( steamworks );
GSStatsStored_t.Register( steamworks );
GSStatsUnloaded_t.Register( steamworks );
NewUrlLaunchParameters_t.Register( steamworks );
ItemInstalled_t.Register( steamworks );
SteamInventoryDefinitionUpdate_t.Register( steamworks );
SteamParentalSettingsChanged_t.Register( steamworks );

View File

@ -73,7 +73,7 @@ internal class SteamApiCallType : BaseType
{
public string CallResult;
public override string TypeName => "SteamAPICall_t";
public override string Return( string varname ) => $"return await (new SteamApiCallback<{CallResult}>( {varname} )).GetResult();";
public override string Return( string varname ) => $"return await (new Result<{CallResult}>( {varname} )).GetResult();";
public override string ReturnType => $"async Task<{CallResult}?>";
}

View File

@ -1,10 +1,14 @@
{
"structs":
[
"structs": [
{
"struct": "NewUrlLaunchParameters_t",
"fields": [
]
},
{
"struct": "ItemInstalled_t",
"fields":
[
"fields": [
{
"fieldname": "m_unAppID",
"fieldtype": "AppId_t"
@ -18,8 +22,7 @@
{
"struct": "InputAnalogActionData_t",
"fields":
[
"fields": [
{
"fieldname": "eMode",
"fieldtype": "EInputSourceMode"
@ -41,8 +44,7 @@
{
"struct": "InputMotionData_t",
"fields":
[
"fields": [
{
"fieldname": "rotQuatX",
"fieldtype": "float"
@ -98,8 +100,7 @@
{
"struct": "InputDigitalActionData_t",
"fields":
[
"fields": [
{
"fieldname": "bState",
"fieldtype": "bool"
@ -128,8 +129,7 @@
{
"struct": "GCMessageAvailable_t",
"fields":
[
"fields": [
{
"fieldname": "m_nMessageSize",
"fieldtype": "uint32"
@ -153,8 +153,7 @@
},
{
"struct": "IPCFailure_t",
"fields":
[
"fields": [
{
"fieldname": "m_eFailureType",
"fieldtype": "uint8"