diff --git a/Facepunch.Steamworks.Test/AppTest.cs b/Facepunch.Steamworks.Test/AppTest.cs index bf216aa..bdfbc88 100644 --- a/Facepunch.Steamworks.Test/AppTest.cs +++ b/Facepunch.Steamworks.Test/AppTest.cs @@ -15,6 +15,13 @@ namespace Steamworks [AssemblyInitialize] public static void AssemblyInit( TestContext context ) { + Steamworks.Dispatch.OnDebugCallback = ( type, str, server ) => + { + Console.WriteLine( $"[Callback {type} {(server ? "server" : "client")}]" ); + Console.WriteLine( str ); + Console.WriteLine( $"" ); + }; + Steamworks.SteamClient.OnCallbackException = ( e ) => { Console.Error.WriteLine( e.Message ); diff --git a/Facepunch.Steamworks/Classes/Dispatch.cs b/Facepunch.Steamworks/Classes/Dispatch.cs index bfa3675..26b32cd 100644 --- a/Facepunch.Steamworks/Classes/Dispatch.cs +++ b/Facepunch.Steamworks/Classes/Dispatch.cs @@ -9,11 +9,24 @@ using System.Linq; namespace Steamworks { /// - /// Manually pumps Steam's message queue and dispatches those + /// Responsible for all callback/callresult handling + /// + /// This manually pumps Steam's message queue and dispatches those /// events to any waiting callbacks/callresults. /// - internal static class Dispatch + public static class Dispatch { + /// + /// If set then we'll call this function every time a callback is generated. + /// + /// This is SLOW!! - it's for debugging - don't keep it on all the time. If you want to access a specific + /// callback then please create an issue on github and I'll add it! + /// + /// Params are : [Callback Type] [Callback Contents] [server] + /// + /// + public static Action OnDebugCallback; + #region interop [DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_Init", CallingConvention = CallingConvention.Cdecl )] internal static extern void SteamAPI_ManualDispatch_Init(); @@ -45,9 +58,9 @@ namespace Steamworks /// /// This gets called from Client/Server Init - /// It's important to switch to the manual dipatcher + /// It's important to switch to the manual dispatcher /// - public static void Init() + internal static void Init() { SteamAPI_ManualDispatch_Init(); } @@ -56,7 +69,7 @@ namespace Steamworks /// /// Calls RunFrame and processes events from this Steam Pipe /// - public static void Frame( HSteamPipe pipe ) + internal static void Frame( HSteamPipe pipe ) { SteamAPI_ManualDispatch_RunFrame( pipe ); SteamNetworkingUtils.OutputDebugMessages(); @@ -88,6 +101,11 @@ namespace Steamworks return; } + if ( OnDebugCallback != null ) + { + OnDebugCallback( msg.Type, CallbackToString( msg ), isServer ); + } + if ( Callbacks.TryGetValue( msg.Type, out var list ) ) { foreach ( var item in list ) @@ -100,6 +118,28 @@ namespace Steamworks } } + /// + /// Given a callback, try to turn it into a string + /// + private static string CallbackToString( CallbackMsg_t msg ) + { + if ( !CallbackTypeFactory.All.TryGetValue( msg.Type, out var t ) ) + return "[not in sdk]"; + + var strct = msg.Data.ToType( t ); + if ( strct == null ) + return "[null]"; + + var str = ""; + + foreach ( var field in t.GetFields( System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic ) ) + { + str += $"{field.Name}: \"{field.GetValue( strct )}\"\n"; + } + + return str.Trim( '\n' ); + } + /// /// A result is a reply to a specific command /// @@ -129,7 +169,7 @@ namespace Steamworks /// have to think about it. This has the advantage that /// you can call .Wait() on async shit and it still works. /// - public static async void LoopClientAsync() + internal static async void LoopClientAsync() { while ( ClientPipe != 0 ) { @@ -143,7 +183,7 @@ namespace Steamworks /// have to think about it. This has the advantage that /// you can call .Wait() on async shit and it still works. /// - public static async void LoopServerAsync() + internal static async void LoopServerAsync() { while ( ServerPipe != 0 ) { diff --git a/Facepunch.Steamworks/Generated/CustomEnums.cs b/Facepunch.Steamworks/Generated/CustomEnums.cs index 1145b2a..00928cc 100644 --- a/Facepunch.Steamworks/Generated/CustomEnums.cs +++ b/Facepunch.Steamworks/Generated/CustomEnums.cs @@ -86,9 +86,9 @@ namespace Steamworks UserAchievementIconFetched = 1109, GlobalAchievementPercentagesReady = 1110, LeaderboardUGCSet = 1111, - PS3TrophiesInstalled = 1112, + // PS3TrophiesInstalled = 1112, GlobalStatsReceived = 1112, - SocketStatusCallback = 1201, + // SocketStatusCallback = 1201, P2PSessionRequest = 1202, P2PSessionConnectFail = 1203, SteamNetConnectionStatusChangedCallback = 1221, @@ -292,12 +292,12 @@ namespace Steamworks { CallbackType.LeaderboardScoreUploaded, typeof( LeaderboardScoreUploaded_t )}, { CallbackType.NumberOfCurrentPlayers, typeof( NumberOfCurrentPlayers_t )}, { CallbackType.UserStatsUnloaded, typeof( UserStatsUnloaded_t )}, - { CallbackType.GSStatsUnloaded, typeof( GSStatsUnloaded_t )}, + // { CallbackType.GSStatsUnloaded, typeof( GSStatsUnloaded_t )}, { CallbackType.UserAchievementIconFetched, typeof( UserAchievementIconFetched_t )}, { CallbackType.GlobalAchievementPercentagesReady, typeof( GlobalAchievementPercentagesReady_t )}, { CallbackType.LeaderboardUGCSet, typeof( LeaderboardUGCSet_t )}, - { CallbackType.PS3TrophiesInstalled, typeof( PS3TrophiesInstalled_t )}, - { CallbackType.GlobalStatsReceived, typeof( GlobalStatsReceived_t )}, + // { CallbackType.PS3TrophiesInstalled, typeof( PS3TrophiesInstalled_t )}, + // { CallbackType.GlobalStatsReceived, typeof( GlobalStatsReceived_t )}, // { CallbackType.SocketStatusCallback, typeof( SocketStatusCallback_t )}, { CallbackType.P2PSessionRequest, typeof( P2PSessionRequest_t )}, { CallbackType.P2PSessionConnectFail, typeof( P2PSessionConnectFail_t )}, diff --git a/Facepunch.Steamworks/Utility/Utility.cs b/Facepunch.Steamworks/Utility/Utility.cs index 645f501..3365d2f 100644 --- a/Facepunch.Steamworks/Utility/Utility.cs +++ b/Facepunch.Steamworks/Utility/Utility.cs @@ -18,6 +18,14 @@ namespace Steamworks return (T)Marshal.PtrToStructure( ptr, typeof( T ) ); } + static internal object ToType( this IntPtr ptr, System.Type t ) + { + if ( ptr == IntPtr.Zero ) + return default; + + return Marshal.PtrToStructure( ptr, t ); + } + static internal uint Swap( uint x ) { return ((x & 0x000000ff) << 24) + diff --git a/Generator/CodeWriter/CustomEnums.cs b/Generator/CodeWriter/CustomEnums.cs index 8dbe0b5..c8c92e4 100644 --- a/Generator/CodeWriter/CustomEnums.cs +++ b/Generator/CodeWriter/CustomEnums.cs @@ -13,18 +13,25 @@ namespace Generator StartBlock( "public enum CallbackType" ); foreach ( var c in def.callback_structs.OrderBy( x => x.CallbackId ) ) { + if ( Cleanup.IsDeprecated( c.Name ) ) + Write( "// " ); + WriteLine( $"{c.Name.Replace( "_t", "" ) } = {c.CallbackId}," ); } EndBlock(); + int last = -1; + StartBlock( "internal static partial class CallbackTypeFactory" ); StartBlock( "internal static System.Collections.Generic.Dictionary All = new System.Collections.Generic.Dictionary" ); foreach ( var c in def.callback_structs.OrderBy( x => x.CallbackId ) ) { - if ( Cleanup.IsDeprecated( c.Name ) ) + if ( Cleanup.IsDeprecated( c.Name ) || last == c.CallbackId ) Write( "// " ); WriteLine( $"{{ CallbackType.{c.Name.Replace( "_t", "" ) }, typeof( {Cleanup.ConvertType(c.Name)} )}}," ); + + last = c.CallbackId; } EndBlock( ";" ); EndBlock();