mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-25 14:15:47 +03:00
Struct packing, first pass
This commit is contained in:
parent
f0e09d4331
commit
dfbbaaae47
@ -72,10 +72,15 @@ public enum MessageType : int
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Global callback type
|
/// Global callback type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
internal void AddCallback<T, TSmall>( Action<T> Callback, int id )
|
||||||
|
{
|
||||||
|
var callback = new Callback<T, TSmall>( IsGameServer, id, Callback );
|
||||||
|
Disposables.Add( callback );
|
||||||
|
}
|
||||||
|
|
||||||
internal void AddCallback<T>( Action<T> Callback, int id )
|
internal void AddCallback<T>( Action<T> Callback, int id )
|
||||||
{
|
{
|
||||||
var callback = new Callback<T>( IsGameServer, id, Callback );
|
AddCallback<T, T>( Callback, id );
|
||||||
Disposables.Add( callback );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action OnUpdate;
|
public Action OnUpdate;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace Facepunch.Steamworks.Callbacks.Networking
|
namespace Facepunch.Steamworks.Callbacks.Networking
|
||||||
{
|
{
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
internal class P2PSessionRequest
|
internal class P2PSessionRequest
|
||||||
{
|
{
|
||||||
public ulong SteamID;
|
public ulong SteamID;
|
||||||
@ -14,7 +14,7 @@ internal class P2PSessionRequest
|
|||||||
public const int CallbackId = Index.Networking + 2;
|
public const int CallbackId = Index.Networking + 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
internal class P2PSessionConnectFail
|
internal class P2PSessionConnectFail
|
||||||
{
|
{
|
||||||
public ulong SteamID;
|
public ulong SteamID;
|
||||||
|
@ -6,9 +6,15 @@
|
|||||||
|
|
||||||
namespace Facepunch.Steamworks.Callbacks.User
|
namespace Facepunch.Steamworks.Callbacks.User
|
||||||
{
|
{
|
||||||
[StructLayout( LayoutKind.Explicit )]
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||||
internal struct ValidateAuthTicketResponse
|
internal struct ValidateAuthTicketResponse
|
||||||
{
|
{
|
||||||
|
public ulong SteamID;
|
||||||
|
public int AuthResponse;
|
||||||
|
public ulong OwnerSteamID;
|
||||||
|
|
||||||
|
public const int CallbackId = Index.User + 43;
|
||||||
|
|
||||||
public enum Response : int
|
public enum Response : int
|
||||||
{
|
{
|
||||||
Okay = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused.
|
Okay = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused.
|
||||||
@ -22,15 +28,6 @@ public enum Response : int
|
|||||||
AuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam.
|
AuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam.
|
||||||
PublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC
|
PublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC
|
||||||
};
|
};
|
||||||
|
|
||||||
[FieldOffset(0)]
|
|
||||||
public ulong SteamID;
|
|
||||||
[FieldOffset(8)]
|
|
||||||
public Response AuthResponse;
|
|
||||||
[FieldOffset(12)]
|
|
||||||
public ulong OwnerSteamID;
|
|
||||||
|
|
||||||
public const int CallbackId = Index.User + 43;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,70 +4,104 @@
|
|||||||
namespace Facepunch.Steamworks.Callbacks.Workshop
|
namespace Facepunch.Steamworks.Callbacks.Workshop
|
||||||
{
|
{
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Explicit )]
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
internal class ItemInstalled
|
internal struct ItemInstalled
|
||||||
{
|
{
|
||||||
[FieldOffset(0)]
|
|
||||||
public uint AppId;
|
public uint AppId;
|
||||||
[FieldOffset(4)]
|
|
||||||
public ulong FileId;
|
public ulong FileId;
|
||||||
|
|
||||||
public const int CallbackId = Index.UGC + 5;
|
public const int CallbackId = Index.UGC + 5;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
public uint AppId;
|
||||||
|
public ulong FileId;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Explicit )]
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
internal class DownloadResult
|
internal struct DownloadResult
|
||||||
{
|
{
|
||||||
[FieldOffset(0)]
|
|
||||||
public uint AppId;
|
public uint AppId;
|
||||||
[FieldOffset(4)]
|
|
||||||
public ulong FileId;
|
public ulong FileId;
|
||||||
[FieldOffset(12)]
|
|
||||||
public Result Result;
|
public Result Result;
|
||||||
|
|
||||||
public const int CallbackId = Index.UGC + 6;
|
public const int CallbackId = Index.UGC + 6;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
public uint AppId;
|
||||||
|
public ulong FileId;
|
||||||
|
public Result Result;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
internal class QueryCompleted : CallResult<QueryCompleted.Data>
|
|
||||||
|
internal class QueryCompleted : CallResult<QueryCompleted.Data, QueryCompleted.Data.Small>
|
||||||
{
|
{
|
||||||
public override int CallbackId { get { return Index.UGC + 1; } }
|
public override int CallbackId { get { return Index.UGC + 1; } }
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
internal struct Data
|
internal struct Data
|
||||||
{
|
{
|
||||||
internal ulong Handle;
|
internal ulong Handle;
|
||||||
internal int Result;
|
internal int Result;
|
||||||
internal uint m_unNumResultsReturned;
|
internal uint NumResultsReturned;
|
||||||
internal uint m_unTotalMatchingResults;
|
internal uint TotalMatchingResults;
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
internal bool CachedData;
|
||||||
internal bool m_bCachedData; // indicates whether this data was retrieved from the local on-disk cache
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
internal ulong Handle;
|
||||||
|
internal int Result;
|
||||||
|
internal uint NumResultsReturned;
|
||||||
|
internal uint TotalMatchingResults;
|
||||||
|
internal bool CachedData;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class CreateItem : CallResult<CreateItem.Data>
|
internal class CreateItem : CallResult<CreateItem.Data, CreateItem.Data.Small>
|
||||||
{
|
{
|
||||||
public override int CallbackId { get { return Index.UGC + 3; } }
|
public override int CallbackId { get { return Index.UGC + 3; } }
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
internal struct Data
|
internal struct Data
|
||||||
{
|
{
|
||||||
internal Result Result;
|
internal Result Result;
|
||||||
internal ulong FileId;
|
internal ulong FileId;
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
internal bool NeedsLegalAgreement;
|
||||||
internal bool NeedsLegalAgreement;
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal ulong FileId;
|
||||||
|
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class SubmitItemUpdate : CallResult<SubmitItemUpdate.Data>
|
internal class SubmitItemUpdate : CallResult<SubmitItemUpdate.Data, SubmitItemUpdate.Data.Small>
|
||||||
{
|
{
|
||||||
public override int CallbackId { get { return Index.UGC + 4; } }
|
public override int CallbackId { get { return Index.UGC + 4; } }
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||||
internal struct Data
|
internal struct Data
|
||||||
{
|
{
|
||||||
internal Result Result;
|
internal Result Result;
|
||||||
[MarshalAs(UnmanagedType.I1)]
|
|
||||||
internal bool NeedsLegalAgreement;
|
internal bool NeedsLegalAgreement;
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||||
|
internal struct Small
|
||||||
|
{
|
||||||
|
internal Result Result;
|
||||||
|
internal bool NeedsLegalAgreement;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,11 @@ public static class Config
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool UseThisCall { get; set; } = true;
|
public static bool UseThisCall { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set this to true on Linux and OSX
|
||||||
|
/// </summary>
|
||||||
|
public static bool PackSmall { get; set; } = false;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Native dll to look for. This is the steam_api.dll renamed.
|
/// The Native dll to look for. This is the steam_api.dll renamed.
|
||||||
|
@ -65,6 +65,7 @@ public void Download( bool highPriority = true )
|
|||||||
|
|
||||||
private void OnFileDownloaded( ulong fileid, Callbacks.Result result )
|
private void OnFileDownloaded( ulong fileid, Callbacks.Result result )
|
||||||
{
|
{
|
||||||
|
if ( fileid != Id ) return;
|
||||||
|
|
||||||
workshop.OnFileDownloaded -= OnFileDownloaded;
|
workshop.OnFileDownloaded -= OnFileDownloaded;
|
||||||
UpdateState();
|
UpdateState();
|
||||||
@ -75,6 +76,7 @@ private void OnFileDownloaded( ulong fileid, Callbacks.Result result )
|
|||||||
|
|
||||||
private void OnItemInstalled( ulong fileid )
|
private void OnItemInstalled( ulong fileid )
|
||||||
{
|
{
|
||||||
|
if ( fileid != Id ) return;
|
||||||
|
|
||||||
workshop.OnItemInstalled -= OnItemInstalled;
|
workshop.OnItemInstalled -= OnItemInstalled;
|
||||||
UpdateState();
|
UpdateState();
|
||||||
|
@ -86,8 +86,8 @@ public unsafe void Run()
|
|||||||
|
|
||||||
void OnResult( QueryCompleted.Data data )
|
void OnResult( QueryCompleted.Data data )
|
||||||
{
|
{
|
||||||
Items = new Item[data.m_unNumResultsReturned];
|
Items = new Item[data.NumResultsReturned];
|
||||||
for ( int i = 0; i < data.m_unNumResultsReturned; i++ )
|
for ( int i = 0; i < data.NumResultsReturned; i++ )
|
||||||
{
|
{
|
||||||
SteamUGCDetails_t details = new SteamUGCDetails_t();
|
SteamUGCDetails_t details = new SteamUGCDetails_t();
|
||||||
workshop.ugc.GetQueryUGCResult( data.Handle, (uint)i, ref details );
|
workshop.ugc.GetQueryUGCResult( data.Handle, (uint)i, ref details );
|
||||||
@ -95,7 +95,7 @@ void OnResult( QueryCompleted.Data data )
|
|||||||
Items[i] = Item.From( details, workshop );
|
Items[i] = Item.From( details, workshop );
|
||||||
}
|
}
|
||||||
|
|
||||||
TotalResults = (int)data.m_unTotalMatchingResults;
|
TotalResults = (int)data.TotalMatchingResults;
|
||||||
|
|
||||||
Callback.Dispose();
|
Callback.Dispose();
|
||||||
Callback = null;
|
Callback = null;
|
||||||
|
@ -22,8 +22,8 @@ internal Workshop( BaseSteamworks steamworks, ISteamUGC ugc, ISteamRemoteStorage
|
|||||||
this.steamworks = steamworks;
|
this.steamworks = steamworks;
|
||||||
this.remoteStorage = remoteStorage;
|
this.remoteStorage = remoteStorage;
|
||||||
|
|
||||||
steamworks.AddCallback<DownloadResult>( onDownloadResult, DownloadResult.CallbackId );
|
steamworks.AddCallback<DownloadResult, DownloadResult.Small>( onDownloadResult, DownloadResult.CallbackId );
|
||||||
steamworks.AddCallback<ItemInstalled>( onItemInstalled, ItemInstalled.CallbackId );
|
steamworks.AddCallback<ItemInstalled, DownloadResult.Small>( onItemInstalled, ItemInstalled.CallbackId );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Valve.Steamworks;
|
using Valve.Steamworks;
|
||||||
@ -19,14 +20,19 @@ public void Dispose()
|
|||||||
internal abstract void Run( ISteamUtils utils );
|
internal abstract void Run( ISteamUtils utils );
|
||||||
}
|
}
|
||||||
|
|
||||||
internal unsafe abstract class CallResult<T> : CallResult
|
internal unsafe abstract class CallResult<T, TSmall> : CallResult where T: new()
|
||||||
{
|
{
|
||||||
|
public static FieldInfo[] SourceFields = typeof( TSmall ).GetFields();
|
||||||
|
public static FieldInfo[] DestFields = typeof( T ).GetFields();
|
||||||
|
|
||||||
public abstract int CallbackId { get; }
|
public abstract int CallbackId { get; }
|
||||||
public Action<T> OnResult;
|
public Action<T> OnResult;
|
||||||
|
|
||||||
internal override void Run( ISteamUtils utils )
|
internal override void Run( ISteamUtils utils )
|
||||||
{
|
{
|
||||||
var datasize = Marshal.SizeOf( typeof( T ) );
|
var packSmall = Config.PackSmall;
|
||||||
|
|
||||||
|
var datasize = packSmall ? Marshal.SizeOf( typeof( TSmall ) ) : Marshal.SizeOf( typeof( T ) );
|
||||||
var data = stackalloc byte[ datasize ];
|
var data = stackalloc byte[ datasize ];
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
@ -36,10 +42,28 @@ internal override void Run( ISteamUtils utils )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataObject = (T)Marshal.PtrToStructure( (IntPtr) data, typeof( T ) );
|
if ( packSmall )
|
||||||
|
{
|
||||||
|
var dataTarget = new T();
|
||||||
|
var dataObject = (TSmall)Marshal.PtrToStructure( (IntPtr) data, typeof( TSmall ) );
|
||||||
|
|
||||||
|
for ( int i=0; i<SourceFields.Length; i++ )
|
||||||
|
{
|
||||||
|
DestFields[i].SetValue( dataTarget, SourceFields[i].GetValue( dataObject ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( OnResult != null )
|
||||||
|
OnResult( dataTarget );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dataObject = (T)Marshal.PtrToStructure( (IntPtr) data, typeof( T ) );
|
||||||
|
|
||||||
|
if ( OnResult != null )
|
||||||
|
OnResult( dataObject );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( OnResult != null )
|
|
||||||
OnResult( dataObject );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,37 +9,28 @@ namespace Facepunch.Steamworks.Interop.VTable.This
|
|||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
internal struct Callback
|
internal struct Callback
|
||||||
{
|
{
|
||||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate void Result( IntPtr thisptr, IntPtr pvParam );
|
||||||
public delegate void Result( IntPtr thisptr, IntPtr pvParam );
|
[UnmanagedFunctionPointer( CallingConvention.ThisCall )] public delegate int GetSize( IntPtr thisptr );
|
||||||
|
|
||||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
[MarshalAs(UnmanagedType.FunctionPtr)] public Result RunCallResult;
|
||||||
public delegate int GetSize( IntPtr thisptr );
|
[MarshalAs(UnmanagedType.FunctionPtr)] public Result RunCallback;
|
||||||
|
[MarshalAs(UnmanagedType.FunctionPtr)] public GetSize GetCallbackSizeBytes;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
internal static IntPtr Get( Action<IntPtr, IntPtr> onRunCallback, int size, Interop.Callback cb )
|
||||||
public Result m_RunCallback;
|
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
|
||||||
public Result m_RunCallResult;
|
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.FunctionPtr)]
|
|
||||||
public GetSize m_GetCallbackSizeBytes;
|
|
||||||
|
|
||||||
internal static IntPtr Get( Action<IntPtr> onRunCallback, Func<int> getSize, Interop.Callback cb )
|
|
||||||
{
|
{
|
||||||
var size = Marshal.SizeOf( typeof( Callback ) );
|
var ptr = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Callback ) ) );
|
||||||
var ptr = Marshal.AllocHGlobal( size );
|
|
||||||
|
|
||||||
Callback.Result da = ( _, p ) => onRunCallback( p );
|
Callback.Result da = ( _, p ) => { onRunCallback( _, p ); Console.WriteLine( "Callback.Result: {0}", _.ToInt64() ); };
|
||||||
Callback.GetSize dc = ( _ ) => getSize();
|
Callback.GetSize dc = ( _ ) => { return size; };
|
||||||
|
|
||||||
cb.AddHandle( GCHandle.Alloc( da ) );
|
cb.AddHandle( GCHandle.Alloc( da ) );
|
||||||
cb.AddHandle( GCHandle.Alloc( dc ) );
|
cb.AddHandle( GCHandle.Alloc( dc ) );
|
||||||
|
|
||||||
var table = new Callback()
|
var table = new Callback()
|
||||||
{
|
{
|
||||||
m_RunCallResult = da,
|
RunCallback = da,
|
||||||
m_RunCallback = da,
|
RunCallResult = da,
|
||||||
m_GetCallbackSizeBytes = dc
|
GetCallbackSizeBytes = dc
|
||||||
};
|
};
|
||||||
|
|
||||||
Marshal.StructureToPtr( table, ptr, false );
|
Marshal.StructureToPtr( table, ptr, false );
|
||||||
|
@ -48,7 +48,7 @@ internal void AddHandle( GCHandle gCHandle )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal partial class Callback<T> : Callback
|
internal partial class Callback<T, TSmall> : Callback
|
||||||
{
|
{
|
||||||
public int CallbackId = 0;
|
public int CallbackId = 0;
|
||||||
public bool GameServer = false;
|
public bool GameServer = false;
|
||||||
@ -87,10 +87,13 @@ public override void Dispose()
|
|||||||
base.Dispose();
|
base.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRunCallback( IntPtr ptr )
|
private void OnRunCallback( IntPtr thisObject, IntPtr ptr )
|
||||||
{
|
{
|
||||||
if ( callbackPin == null ) throw new System.Exception( "Callback wasn't pinned!" );
|
if ( callbackPin == null ) throw new System.Exception( "Callback wasn't pinned!" );
|
||||||
if ( vTablePtr == IntPtr.Zero ) throw new System.Exception( "vTablePtr wasn't pinned!" );
|
if ( vTablePtr == IntPtr.Zero ) throw new System.Exception( "vTablePtr wasn't pinned!" );
|
||||||
|
if ( thisObject != IntPtr.Zero && thisObject != callbackPin.AddrOfPinnedObject() ) throw new System.Exception( "This wasn't valid!" );
|
||||||
|
|
||||||
|
if ( Config.PackSmall && typeof(T) != typeof( TSmall ) ) throw new System.Exception( "Callback should use PackSmall" );
|
||||||
|
|
||||||
T data = (T) Marshal.PtrToStructure( ptr, typeof(T) );
|
T data = (T) Marshal.PtrToStructure( ptr, typeof(T) );
|
||||||
Function( data );
|
Function( data );
|
||||||
@ -121,7 +124,7 @@ void InitVTable()
|
|||||||
{
|
{
|
||||||
if ( Config.UseThisCall )
|
if ( Config.UseThisCall )
|
||||||
{
|
{
|
||||||
vTablePtr = VTable.This.Callback.Get( OnRunCallback, GetSize, this );
|
vTablePtr = VTable.This.Callback.Get( OnRunCallback, Marshal.SizeOf( typeof( T ) ), this );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user