123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- // This file is provided under The MIT License as part of Steamworks.NET.
- // Copyright (c) 2013-2019 Riley Labrecque
- // Please see the included LICENSE.txt for additional information.
- // This file is automatically generated.
- // Changes to this file will be reverted when you update Steamworks.NET
- #if UNITY_ANDROID || UNITY_IOS || UNITY_TIZEN || UNITY_TVOS || UNITY_WEBGL || UNITY_WSA || UNITY_PS4 || UNITY_WII || UNITY_XBOXONE || UNITY_SWITCH
- #define DISABLESTEAMWORKS
- #endif
- #if !DISABLESTEAMWORKS
- #if UNITY_3_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6
- #error Unsupported Unity platform. Steamworks.NET requires Unity 4.7 or higher.
- #elif UNITY_4_7 || UNITY_5 || UNITY_2017 || UNITY_2017_1_OR_NEWER
- #if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)
- #define WINDOWS_BUILD
- #endif
- #elif STEAMWORKS_WIN
- #define WINDOWS_BUILD
- #elif STEAMWORKS_LIN_OSX
- // So that we don't enter the else block below.
- #else
- #error You need to define STEAMWORKS_WIN, or STEAMWORKS_LIN_OSX. Refer to the readme for more details.
- #endif
- // Unity 32bit Mono on Windows crashes with ThisCall/Cdecl for some reason, StdCall without the 'this' ptr is the only thing that works..?
- #if (UNITY_EDITOR_WIN && !UNITY_EDITOR_64) || (!UNITY_EDITOR && UNITY_STANDALONE_WIN && !UNITY_64)
- #define STDCALL
- #elif STEAMWORKS_WIN
- #define THISCALL
- #endif
- // Calling Conventions:
- // Unity x86 Windows - StdCall (No this pointer)
- // Unity x86 Linux - Cdecl
- // Unity x86 OSX - Cdecl
- // Unity x64 Windows - Cdecl
- // Unity x64 Linux - Cdecl
- // Unity x64 OSX - Cdecl
- // Microsoft x86 Windows - ThisCall
- // Microsoft x64 Windows - ThisCall
- // Mono x86 Linux - Cdecl
- // Mono x86 OSX - Cdecl
- // Mono x64 Linux - Cdecl
- // Mono x64 OSX - Cdecl
- // Mono on Windows is probably not supported.
- using System;
- using System.Runtime.InteropServices;
- namespace Steamworks {
- public static class CallbackDispatcher {
- // We catch exceptions inside callbacks and reroute them here.
- // For some reason throwing an exception causes RunCallbacks() to break otherwise.
- // If you have a custom ExceptionHandler in your engine you can register it here manually until we get something more elegant hooked up.
- public static void ExceptionHandler(Exception e) {
- #if UNITY_STANDALONE
- UnityEngine.Debug.LogException(e);
- #elif STEAMWORKS_WIN || STEAMWORKS_LIN_OSX
- Console.WriteLine(e.Message);
- #endif
- }
- }
- public sealed class Callback<T> : IDisposable {
- private CCallbackBaseVTable m_CallbackBaseVTable;
- private IntPtr m_pVTable = IntPtr.Zero;
- private CCallbackBase m_CCallbackBase;
- private GCHandle m_pCCallbackBase;
- public delegate void DispatchDelegate(T param);
- private event DispatchDelegate m_Func;
- private bool m_bGameServer;
- private readonly int m_size = Marshal.SizeOf(typeof(T));
- private bool m_bDisposed = false;
- /// <summary>
- /// Creates a new Callback. You must be calling SteamAPI.RunCallbacks() to retrieve the callbacks.
- /// <para>Returns a handle to the Callback.</para>
- /// <para>This MUST be assigned to a member variable to prevent the GC from cleaning it up.</para>
- /// </summary>
- public static Callback<T> Create(DispatchDelegate func) {
- return new Callback<T>(func, bGameServer: false);
- }
- /// <summary>
- /// Creates a new GameServer Callback. You must be calling GameServer.RunCallbacks() to retrieve the callbacks.
- /// <para>Returns a handle to the Callback.</para>
- /// <para>This MUST be assigned to a member variable to prevent the GC from cleaning it up.</para>
- /// </summary>
- public static Callback<T> CreateGameServer(DispatchDelegate func) {
- return new Callback<T>(func, bGameServer: true);
- }
- public Callback(DispatchDelegate func, bool bGameServer = false) {
- m_bGameServer = bGameServer;
- BuildCCallbackBase();
- Register(func);
- }
- ~Callback() {
- Dispose();
- }
- public void Dispose() {
- if (m_bDisposed) {
- return;
- }
- GC.SuppressFinalize(this);
- Unregister();
- if (m_pVTable != IntPtr.Zero) {
- Marshal.FreeHGlobal(m_pVTable);
- }
- if (m_pCCallbackBase.IsAllocated) {
- m_pCCallbackBase.Free();
- }
- m_bDisposed = true;
- }
- // Manual registration of the callback
- public void Register(DispatchDelegate func) {
- if (func == null) {
- throw new Exception("Callback function must not be null.");
- }
- if ((m_CCallbackBase.m_nCallbackFlags & CCallbackBase.k_ECallbackFlagsRegistered) == CCallbackBase.k_ECallbackFlagsRegistered) {
- Unregister();
- }
- if (m_bGameServer) {
- SetGameserverFlag();
- }
- m_Func = func;
- // k_ECallbackFlagsRegistered is set by SteamAPI_RegisterCallback.
- NativeMethods.SteamAPI_RegisterCallback(m_pCCallbackBase.AddrOfPinnedObject(), CallbackIdentities.GetCallbackIdentity(typeof(T)));
- }
- public void Unregister() {
- // k_ECallbackFlagsRegistered is removed by SteamAPI_UnregisterCallback.
- NativeMethods.SteamAPI_UnregisterCallback(m_pCCallbackBase.AddrOfPinnedObject());
- }
- public void SetGameserverFlag() {
- m_CCallbackBase.m_nCallbackFlags |= CCallbackBase.k_ECallbackFlagsGameServer;
- }
- private void OnRunCallback(
- #if !STDCALL
- IntPtr thisptr,
- #endif
- IntPtr pvParam) {
- try {
- m_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)));
- }
- catch (Exception e) {
- CallbackDispatcher.ExceptionHandler(e);
- }
- }
- // Shouldn't ever get called here, but this is what C++ Steamworks does!
- private void OnRunCallResult(
- #if !STDCALL
- IntPtr thisptr,
- #endif
- IntPtr pvParam, bool bFailed, ulong hSteamAPICall) {
- try {
- m_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)));
- }
- catch (Exception e) {
- CallbackDispatcher.ExceptionHandler(e);
- }
- }
- private int OnGetCallbackSizeBytes(
- #if !STDCALL
- IntPtr thisptr
- #endif
- ) {
- return m_size;
- }
- // Steamworks.NET Specific
- private void BuildCCallbackBase() {
- m_CallbackBaseVTable = new CCallbackBaseVTable() {
- m_RunCallResult = OnRunCallResult,
- m_RunCallback = OnRunCallback,
- m_GetCallbackSizeBytes = OnGetCallbackSizeBytes
- };
- m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CCallbackBaseVTable)));
- Marshal.StructureToPtr(m_CallbackBaseVTable, m_pVTable, false);
- m_CCallbackBase = new CCallbackBase() {
- m_vfptr = m_pVTable,
- m_nCallbackFlags = 0,
- m_iCallback = CallbackIdentities.GetCallbackIdentity(typeof(T))
- };
- m_pCCallbackBase = GCHandle.Alloc(m_CCallbackBase, GCHandleType.Pinned);
- }
- }
- public sealed class CallResult<T> : IDisposable {
- private CCallbackBaseVTable m_CallbackBaseVTable;
- private IntPtr m_pVTable = IntPtr.Zero;
- private CCallbackBase m_CCallbackBase;
- private GCHandle m_pCCallbackBase;
- public delegate void APIDispatchDelegate(T param, bool bIOFailure);
- private event APIDispatchDelegate m_Func;
- private SteamAPICall_t m_hAPICall = SteamAPICall_t.Invalid;
- public SteamAPICall_t Handle { get { return m_hAPICall; } }
- private readonly int m_size = Marshal.SizeOf(typeof(T));
- private bool m_bDisposed = false;
- /// <summary>
- /// Creates a new async CallResult. You must be calling SteamAPI.RunCallbacks() to retrieve the callback.
- /// <para>Returns a handle to the CallResult.</para>
- /// <para>This MUST be assigned to a member variable to prevent the GC from cleaning it up.</para>
- /// </summary>
- public static CallResult<T> Create(APIDispatchDelegate func = null) {
- return new CallResult<T>(func);
- }
- public CallResult(APIDispatchDelegate func = null) {
- m_Func = func;
- BuildCCallbackBase();
- }
- ~CallResult() {
- Dispose();
- }
- public void Dispose() {
- if (m_bDisposed) {
- return;
- }
- GC.SuppressFinalize(this);
- Cancel();
- if (m_pVTable != IntPtr.Zero) {
- Marshal.FreeHGlobal(m_pVTable);
- }
- if (m_pCCallbackBase.IsAllocated) {
- m_pCCallbackBase.Free();
- }
- m_bDisposed = true;
- }
- public void Set(SteamAPICall_t hAPICall, APIDispatchDelegate func = null) {
- // Unlike the official SDK we let the user assign a single function during creation,
- // and allow them to skip having to do so every time that they call .Set()
- if (func != null) {
- m_Func = func;
- }
- if (m_Func == null) {
- throw new Exception("CallResult function was null, you must either set it in the CallResult Constructor or via Set()");
- }
- if (m_hAPICall != SteamAPICall_t.Invalid) {
- NativeMethods.SteamAPI_UnregisterCallResult(m_pCCallbackBase.AddrOfPinnedObject(), (ulong)m_hAPICall);
- }
- m_hAPICall = hAPICall;
- if (hAPICall != SteamAPICall_t.Invalid) {
- NativeMethods.SteamAPI_RegisterCallResult(m_pCCallbackBase.AddrOfPinnedObject(), (ulong)hAPICall);
- }
- }
- public bool IsActive() {
- return (m_hAPICall != SteamAPICall_t.Invalid);
- }
- public void Cancel() {
- if (m_hAPICall != SteamAPICall_t.Invalid) {
- NativeMethods.SteamAPI_UnregisterCallResult(m_pCCallbackBase.AddrOfPinnedObject(), (ulong)m_hAPICall);
- m_hAPICall = SteamAPICall_t.Invalid;
- }
- }
- public void SetGameserverFlag() {
- m_CCallbackBase.m_nCallbackFlags |= CCallbackBase.k_ECallbackFlagsGameServer;
- }
- // Shouldn't ever get called here, but this is what C++ Steamworks does!
- private void OnRunCallback(
- #if !STDCALL
- IntPtr thisptr,
- #endif
- IntPtr pvParam) {
- m_hAPICall = SteamAPICall_t.Invalid; // Caller unregisters for us
- try {
- m_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)), false);
- }
- catch (Exception e) {
- CallbackDispatcher.ExceptionHandler(e);
- }
- }
- private void OnRunCallResult(
- #if !STDCALL
- IntPtr thisptr,
- #endif
- IntPtr pvParam, bool bFailed, ulong hSteamAPICall_) {
- SteamAPICall_t hSteamAPICall = (SteamAPICall_t)hSteamAPICall_;
- if (hSteamAPICall == m_hAPICall) {
- m_hAPICall = SteamAPICall_t.Invalid; // Caller unregisters for us
- try {
- m_Func((T)Marshal.PtrToStructure(pvParam, typeof(T)), bFailed);
- }
- catch (Exception e) {
- CallbackDispatcher.ExceptionHandler(e);
- }
- }
- }
- private int OnGetCallbackSizeBytes(
- #if !STDCALL
- IntPtr thisptr
- #endif
- ) {
- return m_size;
- }
- // Steamworks.NET Specific
- private void BuildCCallbackBase() {
- m_CallbackBaseVTable = new CCallbackBaseVTable() {
- m_RunCallback = OnRunCallback,
- m_RunCallResult = OnRunCallResult,
- m_GetCallbackSizeBytes = OnGetCallbackSizeBytes
- };
- m_pVTable = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CCallbackBaseVTable)));
- Marshal.StructureToPtr(m_CallbackBaseVTable, m_pVTable, false);
- m_CCallbackBase = new CCallbackBase() {
- m_vfptr = m_pVTable,
- m_nCallbackFlags = 0,
- m_iCallback = CallbackIdentities.GetCallbackIdentity(typeof(T))
- };
- m_pCCallbackBase = GCHandle.Alloc(m_CCallbackBase, GCHandleType.Pinned);
- }
- }
- [StructLayout(LayoutKind.Sequential)]
- internal class CCallbackBase {
- public const byte k_ECallbackFlagsRegistered = 0x01;
- public const byte k_ECallbackFlagsGameServer = 0x02;
- public IntPtr m_vfptr;
- public byte m_nCallbackFlags;
- public int m_iCallback;
- }
- [StructLayout(LayoutKind.Sequential)]
- internal class CCallbackBaseVTable {
- #if STDCALL
- private const CallingConvention cc = CallingConvention.StdCall;
- [UnmanagedFunctionPointer(cc)]
- public delegate void RunCBDel(IntPtr pvParam);
- [UnmanagedFunctionPointer(cc)]
- public delegate void RunCRDel(IntPtr pvParam, [MarshalAs(UnmanagedType.I1)] bool bIOFailure, ulong hSteamAPICall);
- [UnmanagedFunctionPointer(cc)]
- public delegate int GetCallbackSizeBytesDel();
- #else
- #if THISCALL
- private const CallingConvention cc = CallingConvention.ThisCall;
- #else
- private const CallingConvention cc = CallingConvention.Cdecl;
- #endif
- [UnmanagedFunctionPointer(cc)]
- public delegate void RunCBDel(IntPtr thisptr, IntPtr pvParam);
- [UnmanagedFunctionPointer(cc)]
- public delegate void RunCRDel(IntPtr thisptr, IntPtr pvParam, [MarshalAs(UnmanagedType.I1)] bool bIOFailure, ulong hSteamAPICall);
- [UnmanagedFunctionPointer(cc)]
- public delegate int GetCallbackSizeBytesDel(IntPtr thisptr);
- #endif
- // RunCallback and RunCallResult are swapped in MSVC ABI
- #if WINDOWS_BUILD
- [NonSerialized]
- [MarshalAs(UnmanagedType.FunctionPtr)]
- public RunCRDel m_RunCallResult;
- #endif
- [NonSerialized]
- [MarshalAs(UnmanagedType.FunctionPtr)]
- public RunCBDel m_RunCallback;
- #if !WINDOWS_BUILD
- [NonSerialized]
- [MarshalAs(UnmanagedType.FunctionPtr)]
- public RunCRDel m_RunCallResult;
- #endif
- [NonSerialized]
- [MarshalAs(UnmanagedType.FunctionPtr)]
- public GetCallbackSizeBytesDel m_GetCallbackSizeBytes;
- }
- }
- #endif // !DISABLESTEAMWORKS
|