mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-01-27 05:58:07 +03:00
Updated Implementation to use flat api
This commit is contained in:
parent
92b45c7596
commit
d8e5a48f65
Binary file not shown.
80
Facepunch.Steamworks/Callbacks/CallResult.cs
Normal file
80
Facepunch.Steamworks/Callbacks/CallResult.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using Steamworks.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// An awaitable version of a SteamAPICall_t
|
||||
/// </summary>
|
||||
internal struct CallResult<T> : INotifyCompletion where T : struct, ICallbackData
|
||||
{
|
||||
SteamAPICall_t call;
|
||||
|
||||
public CallResult( SteamAPICall_t call )
|
||||
{
|
||||
this.call = call;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This gets called if IsComplete returned false on the first call.
|
||||
/// The Action "continues" the async call. We pass it to the Dispatch
|
||||
/// to be called when the callback returns.
|
||||
/// </summary>
|
||||
public void OnCompleted( Action continuation )
|
||||
{
|
||||
Dispatch.OnCallComplete( call, continuation );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the result. This is called internally by the async shit.
|
||||
/// </summary>
|
||||
public T? GetResult()
|
||||
{
|
||||
if ( !SteamUtils.IsCallComplete( call, out var failed ) || failed )
|
||||
return null;
|
||||
|
||||
var t = default( T );
|
||||
var size = t.DataSize;
|
||||
var ptr = Marshal.AllocHGlobal( size );
|
||||
|
||||
try
|
||||
{
|
||||
if ( !SteamUtils.Internal.GetAPICallResult( call, ptr, size, (int) t.CallbackType, ref failed ) || failed )
|
||||
return null;
|
||||
|
||||
return ((T)Marshal.PtrToStructure( ptr, typeof( T ) ));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal( ptr );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if complete or failed
|
||||
/// </summary>
|
||||
public bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( SteamUtils.IsCallComplete( call, out var failed ) || failed )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is what makes this struct awaitable
|
||||
/// </summary>
|
||||
internal CallResult<T> GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
internal partial class Callback
|
||||
{
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate void Run( IntPtr thisptr, IntPtr pvParam );
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate void RunCall( IntPtr thisptr, IntPtr pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall );
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||
public delegate int GetCallbackSizeBytes( IntPtr thisptr );
|
||||
|
||||
internal enum Flags : byte
|
||||
{
|
||||
Registered = 0x01,
|
||||
GameServer = 0x02
|
||||
}
|
||||
|
||||
public IntPtr vTablePtr;
|
||||
public byte CallbackFlags;
|
||||
public int CallbackId;
|
||||
|
||||
//
|
||||
// These are functions that are on CCallback but are never called
|
||||
// We could just send a IntPtr.Zero but it's probably safer to throw a
|
||||
// big apeshit message if steam changes its behaviour at some point
|
||||
//
|
||||
[MonoPInvokeCallback]
|
||||
internal static void RunStub( IntPtr self, IntPtr param, bool failure, SteamAPICall_t call ) =>
|
||||
throw new System.Exception( "Something changed in the Steam API and now CCallbackBack is calling the CallResult function [Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall )]" );
|
||||
|
||||
[MonoPInvokeCallback]
|
||||
internal static int SizeStub( IntPtr self ) =>
|
||||
throw new System.Exception( "Something changed in the Steam API and now CCallbackBack is calling the GetSize function [GetCallbackSizeBytes()]" );
|
||||
};
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
using Steamworks.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
//
|
||||
// Created on registration of a callback
|
||||
//
|
||||
internal class Event : IDisposable
|
||||
{
|
||||
internal static List<IDisposable> AllClient = new List<IDisposable>();
|
||||
internal static List<IDisposable> AllServer = new List<IDisposable>();
|
||||
|
||||
internal static void DisposeAllClient()
|
||||
{
|
||||
foreach ( var a in AllClient.ToArray() )
|
||||
{
|
||||
a.Dispose();
|
||||
}
|
||||
|
||||
AllClient.Clear();
|
||||
}
|
||||
|
||||
internal static void DisposeAllServer()
|
||||
{
|
||||
foreach ( var a in AllServer.ToArray() )
|
||||
{
|
||||
a.Dispose();
|
||||
}
|
||||
|
||||
AllServer.Clear();
|
||||
}
|
||||
|
||||
internal static void Register( Callback.Run func, int size, int callbackId, bool gameserver )
|
||||
{
|
||||
var r = new Event();
|
||||
r.vTablePtr = BuildVTable( func, r.Allocations );
|
||||
|
||||
//
|
||||
// Create the callback object
|
||||
//
|
||||
var cb = new Callback();
|
||||
cb.vTablePtr = r.vTablePtr;
|
||||
cb.CallbackFlags = gameserver ? (byte)0x02 : (byte)0;
|
||||
cb.CallbackId = callbackId;
|
||||
|
||||
//
|
||||
// Pin the callback, so it doesn't get garbage collected and we can pass the pointer to native
|
||||
//
|
||||
r.PinnedCallback = GCHandle.Alloc( cb, GCHandleType.Pinned );
|
||||
|
||||
//
|
||||
// Register the callback with Steam
|
||||
//
|
||||
SteamClient.RegisterCallback( r.PinnedCallback.AddrOfPinnedObject(), cb.CallbackId );
|
||||
|
||||
r.IsAllocated = true;
|
||||
|
||||
if ( gameserver )
|
||||
Event.AllServer.Add( r );
|
||||
else
|
||||
Event.AllClient.Add( r );
|
||||
}
|
||||
|
||||
static IntPtr BuildVTable( Callback.Run run, List<GCHandle> allocations )
|
||||
{
|
||||
var RunStub = (Callback.RunCall)Callback.RunStub;
|
||||
var SizeStub = (Callback.GetCallbackSizeBytes)Callback.SizeStub;
|
||||
|
||||
allocations.Add( GCHandle.Alloc( run ) );
|
||||
allocations.Add( GCHandle.Alloc( RunStub ) );
|
||||
allocations.Add( GCHandle.Alloc( SizeStub ) );
|
||||
|
||||
var a = Marshal.GetFunctionPointerForDelegate<Callback.Run>( run );
|
||||
var b = Marshal.GetFunctionPointerForDelegate<Callback.RunCall>( RunStub );
|
||||
var c = Marshal.GetFunctionPointerForDelegate<Callback.GetCallbackSizeBytes>( SizeStub );
|
||||
|
||||
var vt = Marshal.AllocHGlobal( IntPtr.Size * 3 );
|
||||
|
||||
// Windows switches the function positions
|
||||
#if PLATFORM_WIN
|
||||
Marshal.WriteIntPtr( vt, IntPtr.Size * 0, b );
|
||||
Marshal.WriteIntPtr( vt, IntPtr.Size * 1, a );
|
||||
Marshal.WriteIntPtr( vt, IntPtr.Size * 2, c );
|
||||
#else
|
||||
Marshal.WriteIntPtr( vt, IntPtr.Size * 0, a );
|
||||
Marshal.WriteIntPtr( vt, IntPtr.Size * 1, b );
|
||||
Marshal.WriteIntPtr( vt, IntPtr.Size * 2, c );
|
||||
#endif
|
||||
|
||||
return vt;
|
||||
}
|
||||
|
||||
bool IsAllocated;
|
||||
List<GCHandle> Allocations = new List<GCHandle>();
|
||||
internal IntPtr vTablePtr;
|
||||
internal GCHandle PinnedCallback;
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if ( !IsAllocated ) return;
|
||||
IsAllocated = false;
|
||||
|
||||
if ( !PinnedCallback.IsAllocated )
|
||||
throw new System.Exception( "Callback isn't allocated!?" );
|
||||
|
||||
SteamClient.UnregisterCallback( PinnedCallback.AddrOfPinnedObject() );
|
||||
|
||||
foreach ( var a in Allocations )
|
||||
{
|
||||
if ( a.IsAllocated )
|
||||
a.Free();
|
||||
}
|
||||
|
||||
Allocations = null;
|
||||
|
||||
PinnedCallback.Free();
|
||||
|
||||
if ( vTablePtr != IntPtr.Zero )
|
||||
{
|
||||
Marshal.FreeHGlobal( vTablePtr );
|
||||
vTablePtr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
~Event()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
17
Facepunch.Steamworks/Callbacks/ICallbackData.cs
Normal file
17
Facepunch.Steamworks/Callbacks/ICallbackData.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Steamworks.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Gives us a generic way to get the CallbackId of structs
|
||||
/// </summary>
|
||||
internal interface ICallbackData
|
||||
{
|
||||
CallbackType CallbackType { get; }
|
||||
int DataSize { get; }
|
||||
}
|
||||
}
|
205
Facepunch.Steamworks/Classes/Dispatch.cs
Normal file
205
Facepunch.Steamworks/Classes/Dispatch.cs
Normal file
@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
using Steamworks;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Manually pumps Steam's message queue and dispatches those
|
||||
/// events to any waiting callbacks/callresults.
|
||||
/// </summary>
|
||||
internal static class Dispatch
|
||||
{
|
||||
#region interop
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_Init", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern void SteamAPI_ManualDispatch_Init();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_RunFrame", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern void SteamAPI_ManualDispatch_RunFrame( HSteamPipe pipe );
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_GetNextCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
internal static extern bool SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe pipe, [In, Out] ref CallbackMsg_t msg );
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_FreeLastCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
internal static extern bool SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe pipe );
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = Platform.StructPlatformPackSize )]
|
||||
internal struct CallbackMsg_t
|
||||
{
|
||||
public HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
|
||||
public CallbackType Type; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.)
|
||||
public IntPtr Data; // Points to the callback structure
|
||||
public int DataSize; // Size of the data pointed to by m_pubParam
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
internal static HSteamPipe ClientPipe { get; set; }
|
||||
internal static HSteamPipe ServerPipe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This gets called from Client/Server Init
|
||||
/// It's important to switch to the manual dipatcher
|
||||
/// </summary>
|
||||
public static void Init()
|
||||
{
|
||||
SteamAPI_ManualDispatch_Init();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calls RunFrame and processes events from this Steam Pipe
|
||||
/// </summary>
|
||||
public static void Frame( HSteamPipe pipe )
|
||||
{
|
||||
SteamAPI_ManualDispatch_RunFrame( pipe );
|
||||
|
||||
CallbackMsg_t msg = default;
|
||||
|
||||
while ( SteamAPI_ManualDispatch_GetNextCallback( pipe, ref msg ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessCallback( msg );
|
||||
}
|
||||
finally
|
||||
{
|
||||
SteamAPI_ManualDispatch_FreeLastCallback( pipe );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A callback is a general global message
|
||||
/// </summary>
|
||||
private static void ProcessCallback( CallbackMsg_t msg )
|
||||
{
|
||||
// Is this a special callback telling us that the call result is ready?
|
||||
if ( msg.Type == CallbackType.SteamAPICallCompleted )
|
||||
{
|
||||
ProcessResult( msg );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Callbacks.TryGetValue( msg.Type, out var list ) )
|
||||
{
|
||||
foreach ( var item in list )
|
||||
{
|
||||
item.action( msg.Data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A result is a reply to a specific command
|
||||
/// </summary>
|
||||
private static void ProcessResult( CallbackMsg_t msg )
|
||||
{
|
||||
var result = msg.Data.ToType<SteamAPICallCompleted_t>();
|
||||
|
||||
//
|
||||
// Do we have an entry added via OnCallComplete
|
||||
//
|
||||
if ( !ResultCallbacks.TryGetValue( result.AsyncCall, out var callbackInfo ) )
|
||||
{
|
||||
// Do we care? Should we throw errors?
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove it before we do anything, incase the continuation throws exceptions
|
||||
ResultCallbacks.Remove( result.AsyncCall );
|
||||
|
||||
// At this point whatever async routine called this
|
||||
// continues running.
|
||||
callbackInfo.continuation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pumps the queue in an async loop so we don't
|
||||
/// have to think about it. This has the advantage that
|
||||
/// you can call .Wait() on async shit and it still works.
|
||||
/// </summary>
|
||||
public static async void LoopClientAsync()
|
||||
{
|
||||
while ( ClientPipe != 0 )
|
||||
{
|
||||
Frame( ClientPipe );
|
||||
await Task.Delay( 16 );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pumps the queue in an async loop so we don't
|
||||
/// have to think about it. This has the advantage that
|
||||
/// you can call .Wait() on async shit and it still works.
|
||||
/// </summary>
|
||||
public static async void LoopServerAsync()
|
||||
{
|
||||
while ( ServerPipe != 0 )
|
||||
{
|
||||
Frame( ServerPipe );
|
||||
await Task.Delay( 32 );
|
||||
}
|
||||
}
|
||||
|
||||
struct ResultCallback
|
||||
{
|
||||
public Action continuation;
|
||||
}
|
||||
|
||||
static Dictionary<ulong, ResultCallback> ResultCallbacks = new Dictionary<ulong, ResultCallback>();
|
||||
|
||||
/// <summary>
|
||||
/// Watch for a steam api call
|
||||
/// </summary>
|
||||
internal static void OnCallComplete( SteamAPICall_t call, Action continuation )
|
||||
{
|
||||
ResultCallbacks[call.Value] = new ResultCallback
|
||||
{
|
||||
continuation = continuation
|
||||
};
|
||||
}
|
||||
|
||||
struct Callback
|
||||
{
|
||||
public Action<IntPtr> action;
|
||||
public bool server;
|
||||
}
|
||||
|
||||
static Dictionary<CallbackType, List<Callback>> Callbacks = new Dictionary<CallbackType, List<Callback>>();
|
||||
|
||||
/// <summary>
|
||||
/// Install a global callback. The passed function will get called if it's all good.
|
||||
/// </summary>
|
||||
internal static void Install<T>( Action<T> p, bool server = false ) where T : ICallbackData
|
||||
{
|
||||
var t = default( T );
|
||||
var type = t.CallbackType;
|
||||
|
||||
if ( !Callbacks.TryGetValue( type, out var list ) )
|
||||
{
|
||||
list = new List<Callback>();
|
||||
Callbacks[type] = list;
|
||||
}
|
||||
|
||||
list.Add( new Callback
|
||||
{
|
||||
action = x => p( x.ToType<T>() ),
|
||||
server = server
|
||||
} );
|
||||
}
|
||||
|
||||
internal static void Wipe()
|
||||
{
|
||||
Callbacks = new Dictionary<CallbackType, List<Callback>>();
|
||||
ResultCallbacks = new Dictionary<ulong, ResultCallback>();
|
||||
ClientPipe = 0;
|
||||
ServerPipe = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,10 +11,28 @@ namespace Steamworks
|
||||
public List<Connection> Connected = new List<Connection>();
|
||||
public Socket Socket { get; internal set; }
|
||||
|
||||
public bool Close() => Socket.Close();
|
||||
|
||||
public override string ToString() => Socket.ToString();
|
||||
|
||||
internal HSteamNetPollGroup pollGroup;
|
||||
|
||||
internal void Initialize()
|
||||
{
|
||||
pollGroup = SteamNetworkingSockets.Internal.CreatePollGroup();
|
||||
}
|
||||
|
||||
public bool Close()
|
||||
{
|
||||
if ( SteamNetworkingSockets.Internal.IsValid )
|
||||
{
|
||||
SteamNetworkingSockets.Internal.DestroyPollGroup( pollGroup );
|
||||
Socket.Close();
|
||||
}
|
||||
|
||||
pollGroup = 0;
|
||||
Socket = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void OnConnectionChanged( Connection connection, ConnectionInfo data )
|
||||
{
|
||||
switch ( data.State )
|
||||
@ -40,6 +58,8 @@ namespace Steamworks
|
||||
{
|
||||
connection.Accept();
|
||||
Connecting.Add( connection );
|
||||
|
||||
SteamNetworkingSockets.Internal.SetConnectionPollGroup( connection, pollGroup );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -67,9 +87,10 @@ namespace Steamworks
|
||||
int processed = 0;
|
||||
IntPtr messageBuffer = Marshal.AllocHGlobal( IntPtr.Size * bufferSize );
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
processed = SteamNetworkingSockets.Internal.ReceiveMessagesOnListenSocket( Socket, messageBuffer, bufferSize );
|
||||
processed = SteamNetworkingSockets.Internal.ReceiveMessagesOnPollGroup( pollGroup, messageBuffer, bufferSize );
|
||||
|
||||
for ( int i = 0; i < processed; i++ )
|
||||
{
|
||||
@ -80,6 +101,7 @@ namespace Steamworks
|
||||
{
|
||||
Marshal.FreeHGlobal( messageBuffer );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Overwhelmed our buffer, keep going
|
||||
|
50
Facepunch.Steamworks/Classes/SteamApi.cs
Normal file
50
Facepunch.Steamworks/Classes/SteamApi.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
internal static class SteamAPI
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_Init", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
public static extern bool SteamAPI_Init();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_Shutdown", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern void SteamAPI_Shutdown();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern HSteamPipe SteamAPI_GetHSteamPipe();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_RestartAppIfNecessary", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
public static extern bool SteamAPI_RestartAppIfNecessary( uint unOwnAppID );
|
||||
|
||||
}
|
||||
static internal bool Init()
|
||||
{
|
||||
return Native.SteamAPI_Init();
|
||||
}
|
||||
|
||||
static internal void Shutdown()
|
||||
{
|
||||
Native.SteamAPI_Shutdown();
|
||||
}
|
||||
|
||||
static internal HSteamPipe GetHSteamPipe()
|
||||
{
|
||||
return Native.SteamAPI_GetHSteamPipe();
|
||||
}
|
||||
|
||||
static internal bool RestartAppIfNecessary( uint unOwnAppID )
|
||||
{
|
||||
return Native.SteamAPI_RestartAppIfNecessary( unOwnAppID );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
40
Facepunch.Steamworks/Classes/SteamGameServer.cs
Normal file
40
Facepunch.Steamworks/Classes/SteamGameServer.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
internal static class SteamGameServer
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_RunCallbacks", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern void SteamGameServer_RunCallbacks();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_Shutdown", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern void SteamGameServer_Shutdown();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern HSteamPipe SteamGameServer_GetHSteamPipe();
|
||||
|
||||
}
|
||||
static internal void RunCallbacks()
|
||||
{
|
||||
Native.SteamGameServer_RunCallbacks();
|
||||
}
|
||||
|
||||
static internal void Shutdown()
|
||||
{
|
||||
Native.SteamGameServer_Shutdown();
|
||||
}
|
||||
|
||||
static internal HSteamPipe GetHSteamPipe()
|
||||
{
|
||||
return Native.SteamGameServer_GetHSteamPipe();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
24
Facepunch.Steamworks/Classes/SteamInternal.cs
Normal file
24
Facepunch.Steamworks/Classes/SteamInternal.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
internal static class SteamInternal
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamInternal_GameServer_Init", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
public static extern bool SteamInternal_GameServer_Init( uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, int eServerMode, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchVersionString );
|
||||
}
|
||||
|
||||
static internal bool GameServer_Init( uint unIP, ushort usPort, ushort usGamePort, ushort usQueryPort, int eServerMode, [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof( Utf8StringToNative ) )] string pchVersionString )
|
||||
{
|
||||
return Native.SteamInternal_GameServer_Init( unIP, usPort, usGamePort, usQueryPort, eServerMode, pchVersionString );
|
||||
}
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
/// High level connection status
|
||||
public enum ConnectionState
|
||||
{
|
||||
|
||||
/// Dummy value used to indicate an error condition in the API.
|
||||
/// Specified connection doesn't exist or has already been closed.
|
||||
None = 0,
|
||||
|
||||
/// We are trying to establish whether peers can talk to each other,
|
||||
/// whether they WANT to talk to each other, perform basic auth,
|
||||
/// and exchange crypt keys.
|
||||
///
|
||||
/// - For connections on the "client" side (initiated locally):
|
||||
/// We're in the process of trying to establish a connection.
|
||||
/// Depending on the connection type, we might not know who they are.
|
||||
/// Note that it is not possible to tell if we are waiting on the
|
||||
/// network to complete handshake packets, or for the application layer
|
||||
/// to accept the connection.
|
||||
///
|
||||
/// - For connections on the "server" side (accepted through listen socket):
|
||||
/// We have completed some basic handshake and the client has presented
|
||||
/// some proof of identity. The connection is ready to be accepted
|
||||
/// using AcceptConnection().
|
||||
///
|
||||
/// In either case, any unreliable packets sent now are almost certain
|
||||
/// to be dropped. Attempts to receive packets are guaranteed to fail.
|
||||
/// You may send messages if the send mode allows for them to be queued.
|
||||
/// but if you close the connection before the connection is actually
|
||||
/// established, any queued messages will be discarded immediately.
|
||||
/// (We will not attempt to flush the queue and confirm delivery to the
|
||||
/// remote host, which ordinarily happens when a connection is closed.)
|
||||
Connecting = 1,
|
||||
|
||||
/// Some connection types use a back channel or trusted 3rd party
|
||||
/// for earliest communication. If the server accepts the connection,
|
||||
/// then these connections switch into the rendezvous state. During this
|
||||
/// state, we still have not yet established an end-to-end route (through
|
||||
/// the relay network), and so if you send any messages unreliable, they
|
||||
/// are going to be discarded.
|
||||
FindingRoute = 2,
|
||||
|
||||
/// We've received communications from our peer (and we know
|
||||
/// who they are) and are all good. If you close the connection now,
|
||||
/// we will make our best effort to flush out any reliable sent data that
|
||||
/// has not been acknowledged by the peer. (But note that this happens
|
||||
/// from within the application process, so unlike a TCP connection, you are
|
||||
/// not totally handing it off to the operating system to deal with it.)
|
||||
Connected = 3,
|
||||
|
||||
/// Connection has been closed by our peer, but not closed locally.
|
||||
/// The connection still exists from an API perspective. You must close the
|
||||
/// handle to free up resources. If there are any messages in the inbound queue,
|
||||
/// you may retrieve them. Otherwise, nothing may be done with the connection
|
||||
/// except to close it.
|
||||
///
|
||||
/// This stats is similar to CLOSE_WAIT in the TCP state machine.
|
||||
ClosedByPeer = 4,
|
||||
|
||||
/// A disruption in the connection has been detected locally. (E.g. timeout,
|
||||
/// local internet connection disrupted, etc.)
|
||||
///
|
||||
/// The connection still exists from an API perspective. You must close the
|
||||
/// handle to free up resources.
|
||||
///
|
||||
/// Attempts to send further messages will fail. Any remaining received messages
|
||||
/// in the queue are available.
|
||||
ProblemDetectedLocally = 5,
|
||||
|
||||
//
|
||||
// The following values are used internally and will not be returned by any API.
|
||||
// We document them here to provide a little insight into the state machine that is used
|
||||
// under the hood.
|
||||
//
|
||||
|
||||
/// We've disconnected on our side, and from an API perspective the connection is closed.
|
||||
/// No more data may be sent or received. All reliable data has been flushed, or else
|
||||
/// we've given up and discarded it. We do not yet know for sure that the peer knows
|
||||
/// the connection has been closed, however, so we're just hanging around so that if we do
|
||||
/// get a packet from them, we can send them the appropriate packets so that they can
|
||||
/// know why the connection was closed (and not have to rely on a timeout, which makes
|
||||
/// it appear as if something is wrong).
|
||||
FinWait = -1,
|
||||
|
||||
/// We've disconnected on our side, and from an API perspective the connection is closed.
|
||||
/// No more data may be sent or received. From a network perspective, however, on the wire,
|
||||
/// we have not yet given any indication to the peer that the connection is closed.
|
||||
/// We are in the process of flushing out the last bit of reliable data. Once that is done,
|
||||
/// we will inform the peer that the connection has been closed, and transition to the
|
||||
/// FinWait state.
|
||||
///
|
||||
/// Note that no indication is given to the remote host that we have closed the connection,
|
||||
/// until the data has been flushed. If the remote host attempts to send us data, we will
|
||||
/// do whatever is necessary to keep the connection alive until it can be closed properly.
|
||||
/// But in fact the data will be discarded, since there is no way for the application to
|
||||
/// read it back. Typically this is not a problem, as application protocols that utilize
|
||||
/// the lingering functionality are designed for the remote host to wait for the response
|
||||
/// before sending any more data.
|
||||
Linger = -2,
|
||||
|
||||
/// Connection is completely inactive and ready to be destroyed
|
||||
Dead = -3,
|
||||
|
||||
Force32Bit = 0x7fffffff
|
||||
};
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
internal enum NetConfig : int
|
||||
{
|
||||
Invalid = 0,
|
||||
FakePacketLoss_Send = 2,
|
||||
FakePacketLoss_Recv = 3,
|
||||
FakePacketLag_Send = 4,
|
||||
FakePacketLag_Recv = 5,
|
||||
|
||||
FakePacketReorder_Send = 6,
|
||||
FakePacketReorder_Recv = 7,
|
||||
|
||||
FakePacketReorder_Time = 8,
|
||||
|
||||
FakePacketDup_Send = 26,
|
||||
FakePacketDup_Recv = 27,
|
||||
|
||||
FakePacketDup_TimeMax = 28,
|
||||
|
||||
TimeoutInitial = 24,
|
||||
|
||||
TimeoutConnected = 25,
|
||||
|
||||
SendBufferSize = 9,
|
||||
|
||||
SendRateMin = 10,
|
||||
SendRateMax = 11,
|
||||
|
||||
NagleTime = 12,
|
||||
|
||||
IP_AllowWithoutAuth = 23,
|
||||
|
||||
SDRClient_ConsecutitivePingTimeoutsFailInitial = 19,
|
||||
|
||||
SDRClient_ConsecutitivePingTimeoutsFail = 20,
|
||||
|
||||
SDRClient_MinPingsBeforePingAccurate = 21,
|
||||
|
||||
SDRClient_SingleSocket = 22,
|
||||
|
||||
SDRClient_ForceRelayCluster = 29,
|
||||
|
||||
SDRClient_DebugTicketAddress = 30,
|
||||
|
||||
SDRClient_ForceProxyAddr = 31,
|
||||
|
||||
LogLevel_AckRTT = 13,
|
||||
LogLevel_PacketDecode = 14,
|
||||
LogLevel_Message = 15,
|
||||
LogLevel_PacketGaps = 16,
|
||||
LogLevel_P2PRendezvous = 17,
|
||||
LogLevel_SDRRelayPings = 18,
|
||||
|
||||
Force32Bit = 0x7fffffff
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
enum NetConfigResult
|
||||
{
|
||||
BadValue = -1, // No such configuration value
|
||||
BadScopeObj = -2, // Bad connection handle, etc
|
||||
BufferTooSmall = -3, // Couldn't fit the result in your buffer
|
||||
OK = 1,
|
||||
OKInherited = 2, // A value was not set at this level, but the effective (inherited) value was returned.
|
||||
|
||||
Force32Bit = 0x7fffffff
|
||||
};
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
enum NetConfigType
|
||||
{
|
||||
Int32 = 1,
|
||||
Int64 = 2,
|
||||
Float = 3,
|
||||
String = 4,
|
||||
FunctionPtr = 5, // NOTE: When setting callbacks, you should put the pointer into a variable and pass a pointer to that variable.
|
||||
|
||||
Force32Bit = 0x7fffffff
|
||||
};
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
internal enum NetScope : int
|
||||
{
|
||||
Global = 1,
|
||||
SocketsInterface = 2,
|
||||
ListenSocket = 3,
|
||||
Connection = 4,
|
||||
|
||||
Force32Bit = 0x7fffffff
|
||||
}
|
||||
}
|
@ -11,27 +11,7 @@ namespace Steamworks.ServerList
|
||||
{
|
||||
|
||||
#region ISteamMatchmakingServers
|
||||
|
||||
static ISteamMatchmakingServers _internal;
|
||||
internal static ISteamMatchmakingServers Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamMatchmakingServers();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
}
|
||||
|
||||
internal static ISteamMatchmakingServers Internal => SteamMatchmakingServers.Internal;
|
||||
#endregion
|
||||
|
||||
|
||||
|
@ -11,32 +11,21 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Exposes a wide range of information and actions for applications and Downloadable Content (DLC).
|
||||
/// </summary>
|
||||
public static class SteamApps
|
||||
public class SteamApps : SteamClass
|
||||
{
|
||||
static ISteamApps _internal;
|
||||
internal static ISteamApps Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamApps();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamApps Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamApps( server );
|
||||
}
|
||||
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
DlcInstalled_t.Install( x => OnDlcInstalled?.Invoke( x.AppID ) );
|
||||
NewUrlLaunchParameters_t.Install( x => OnNewLaunchParameters?.Invoke() );
|
||||
Dispatch.Install<DlcInstalled_t>( x => OnDlcInstalled?.Invoke( x.AppID ) );
|
||||
Dispatch.Install<NewUrlLaunchParameters_t>( x => OnNewLaunchParameters?.Invoke() );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -29,76 +29,72 @@ namespace Steamworks
|
||||
|
||||
initialized = true;
|
||||
|
||||
SteamApps.InstallEvents();
|
||||
SteamUtils.InstallEvents();
|
||||
SteamParental.InstallEvents();
|
||||
SteamMusic.InstallEvents();
|
||||
SteamVideo.InstallEvents();
|
||||
SteamUser.InstallEvents();
|
||||
SteamFriends.InstallEvents();
|
||||
SteamScreenshots.InstallEvents();
|
||||
SteamUserStats.InstallEvents();
|
||||
SteamInventory.InstallEvents();
|
||||
SteamNetworking.InstallEvents();
|
||||
SteamMatchmaking.InstallEvents();
|
||||
SteamParties.InstallEvents();
|
||||
SteamNetworkingSockets.InstallEvents();
|
||||
SteamInput.InstallEvents();
|
||||
SteamUGC.InstallEvents();
|
||||
//
|
||||
// Dispatch is responsible for pumping the
|
||||
// event loop.
|
||||
//
|
||||
Dispatch.Init();
|
||||
Dispatch.ClientPipe = SteamAPI.GetHSteamPipe();
|
||||
Console.WriteLine( $"Dispatch.ClientPipe = {Dispatch.ClientPipe.Value}" );
|
||||
|
||||
AddInterface<SteamApps>();
|
||||
AddInterface<SteamFriends>();
|
||||
AddInterface<SteamInput>();
|
||||
AddInterface<SteamInventory>();
|
||||
AddInterface<SteamMatchmaking>();
|
||||
AddInterface<SteamMatchmakingServers>();
|
||||
AddInterface<SteamMusic>();
|
||||
AddInterface<SteamNetworking>();
|
||||
AddInterface<SteamNetworkingSockets>();
|
||||
AddInterface<SteamNetworkingUtils>();
|
||||
AddInterface<SteamParental>();
|
||||
AddInterface<SteamParties>();
|
||||
AddInterface<SteamRemoteStorage>();
|
||||
AddInterface<SteamScreenshots>();
|
||||
AddInterface<SteamUGC>();
|
||||
AddInterface<SteamUser>();
|
||||
AddInterface<SteamUserStats>();
|
||||
AddInterface<SteamUtils>();
|
||||
AddInterface<SteamVideo>();
|
||||
|
||||
if ( asyncCallbacks )
|
||||
{
|
||||
RunCallbacksAsync();
|
||||
//
|
||||
// This will keep looping in the background every 16 ms
|
||||
// until we shut down.
|
||||
//
|
||||
Dispatch.LoopClientAsync();
|
||||
}
|
||||
}
|
||||
|
||||
static List<SteamInterface> openIterfaces = new List<SteamInterface>();
|
||||
|
||||
internal static void WatchInterface( SteamInterface steamInterface )
|
||||
internal static void AddInterface<T>() where T : SteamClass, new()
|
||||
{
|
||||
if ( openIterfaces.Contains( steamInterface ) )
|
||||
throw new System.Exception( "openIterfaces already contains interface!" );
|
||||
|
||||
openIterfaces.Add( steamInterface );
|
||||
var t = new T();
|
||||
t.InitializeInterface( false );
|
||||
openInterfaces.Add( t );
|
||||
}
|
||||
|
||||
static List<SteamClass> openInterfaces = new List<SteamClass>();
|
||||
|
||||
internal static void ShutdownInterfaces()
|
||||
{
|
||||
foreach ( var e in openIterfaces )
|
||||
foreach ( var e in openInterfaces )
|
||||
{
|
||||
e.Shutdown();
|
||||
e.DestroyInterface();
|
||||
}
|
||||
|
||||
openIterfaces.Clear();
|
||||
openInterfaces.Clear();
|
||||
}
|
||||
|
||||
public static Action<Exception> OnCallbackException;
|
||||
|
||||
public static bool IsValid => initialized;
|
||||
|
||||
internal static async void RunCallbacksAsync()
|
||||
{
|
||||
while ( IsValid )
|
||||
{
|
||||
await Task.Delay( 16 );
|
||||
|
||||
try
|
||||
{
|
||||
RunCallbacks();
|
||||
}
|
||||
catch ( System.Exception e )
|
||||
{
|
||||
OnCallbackException?.Invoke( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
if ( !IsValid ) return;
|
||||
|
||||
SteamInput.Shutdown();
|
||||
|
||||
Cleanup();
|
||||
|
||||
SteamAPI.Shutdown();
|
||||
@ -106,45 +102,17 @@ namespace Steamworks
|
||||
|
||||
internal static void Cleanup()
|
||||
{
|
||||
Dispatch.Wipe();
|
||||
|
||||
initialized = false;
|
||||
|
||||
Event.DisposeAllClient();
|
||||
ShutdownInterfaces();
|
||||
|
||||
SteamInput.Shutdown();
|
||||
SteamApps.Shutdown();
|
||||
SteamUtils.Shutdown();
|
||||
SteamParental.Shutdown();
|
||||
SteamMusic.Shutdown();
|
||||
SteamVideo.Shutdown();
|
||||
SteamUser.Shutdown();
|
||||
SteamFriends.Shutdown();
|
||||
SteamScreenshots.Shutdown();
|
||||
SteamUserStats.Shutdown();
|
||||
SteamInventory.Shutdown();
|
||||
SteamNetworking.Shutdown();
|
||||
SteamMatchmaking.Shutdown();
|
||||
SteamParties.Shutdown();
|
||||
SteamNetworkingUtils.Shutdown();
|
||||
SteamNetworkingSockets.Shutdown();
|
||||
ServerList.Base.Shutdown();
|
||||
}
|
||||
|
||||
internal static void RegisterCallback( IntPtr intPtr, int callbackId )
|
||||
{
|
||||
SteamAPI.RegisterCallback( intPtr, callbackId );
|
||||
}
|
||||
|
||||
public static void RunCallbacks()
|
||||
{
|
||||
if ( !IsValid ) return;
|
||||
|
||||
SteamAPI.RunCallbacks();
|
||||
}
|
||||
|
||||
internal static void UnregisterCallback( IntPtr intPtr )
|
||||
{
|
||||
SteamAPI.UnregisterCallback( intPtr );
|
||||
if ( Dispatch.ClientPipe != 0 )
|
||||
Dispatch.Frame( Dispatch.ClientPipe );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -10,42 +10,29 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamFriends
|
||||
public class SteamFriends : SteamClass
|
||||
{
|
||||
static ISteamFriends _internal;
|
||||
internal static ISteamFriends Internal
|
||||
internal static ISteamFriends Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
Internal = new ISteamFriends( server );
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamFriends();
|
||||
_internal.Init();
|
||||
|
||||
richPresence = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
richPresence = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
static Dictionary<string, string> richPresence;
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
FriendStateChange_t.Install( x => OnPersonaStateChange?.Invoke( new Friend( x.SteamID ) ) );
|
||||
GameRichPresenceJoinRequested_t.Install( x => OnGameRichPresenceJoinRequested?.Invoke( new Friend( x.SteamIDFriend), x.ConnectUTF8() ) );
|
||||
GameConnectedFriendChatMsg_t.Install( OnFriendChatMessage );
|
||||
GameOverlayActivated_t.Install( x => OnGameOverlayActivated?.Invoke() );
|
||||
GameServerChangeRequested_t.Install( x => OnGameServerChangeRequested?.Invoke( x.ServerUTF8(), x.PasswordUTF8() ) );
|
||||
GameLobbyJoinRequested_t.Install( x => OnGameLobbyJoinRequested?.Invoke( new Lobby( x.SteamIDLobby ), x.SteamIDFriend ) );
|
||||
FriendRichPresenceUpdate_t.Install( x => OnFriendRichPresenceUpdate?.Invoke( new Friend( x.SteamIDFriend ) ) );
|
||||
Dispatch.Install<PersonaStateChange_t>( x => OnPersonaStateChange?.Invoke( new Friend( x.SteamID ) ) );
|
||||
Dispatch.Install<GameRichPresenceJoinRequested_t>( x => OnGameRichPresenceJoinRequested?.Invoke( new Friend( x.SteamIDFriend), x.ConnectUTF8() ) );
|
||||
Dispatch.Install<GameConnectedFriendChatMsg_t>( OnFriendChatMessage );
|
||||
Dispatch.Install<GameOverlayActivated_t>( x => OnGameOverlayActivated?.Invoke() );
|
||||
Dispatch.Install<GameServerChangeRequested_t>( x => OnGameServerChangeRequested?.Invoke( x.ServerUTF8(), x.PasswordUTF8() ) );
|
||||
Dispatch.Install<GameLobbyJoinRequested_t>( x => OnGameLobbyJoinRequested?.Invoke( new Lobby( x.SteamIDLobby ), x.SteamIDFriend ) );
|
||||
Dispatch.Install<FriendRichPresenceUpdate_t>( x => OnFriendRichPresenceUpdate?.Invoke( new Friend( x.SteamIDFriend ) ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -319,7 +306,7 @@ namespace Steamworks
|
||||
|
||||
do
|
||||
{
|
||||
if ((result = await Internal.EnumerateFollowingList((uint)resultCount)) != null)
|
||||
if ( (result = await Internal.EnumerateFollowingList((uint)resultCount)) != null)
|
||||
{
|
||||
resultCount += result.Value.ResultsReturned;
|
||||
|
||||
|
@ -3,44 +3,18 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static class SteamInput
|
||||
public class SteamInput : SteamClass
|
||||
{
|
||||
internal static ISteamInput Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
Internal = new ISteamInput( server );
|
||||
}
|
||||
|
||||
internal const int STEAM_CONTROLLER_MAX_COUNT = 16;
|
||||
|
||||
static ISteamInput _internal;
|
||||
internal static ISteamInput Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamInput();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
{
|
||||
if ( _internal != null && _internal.IsValid )
|
||||
{
|
||||
_internal.DoShutdown();
|
||||
}
|
||||
|
||||
_internal = null;
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
Internal.DoInit();
|
||||
Internal.RunFrame();
|
||||
|
||||
// None?
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// You shouldn't really need to call this because it get called by RunCallbacks on SteamClient
|
||||
|
@ -12,32 +12,23 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamInventory
|
||||
public class SteamInventory : SteamClass
|
||||
{
|
||||
static ISteamInventory _internal;
|
||||
internal static ISteamInventory Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamInventory();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamInventory Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
}
|
||||
Internal = new ISteamInventory( server );
|
||||
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
SteamInventoryFullUpdate_t.Install( x => InventoryUpdated( x ) );
|
||||
SteamInventoryDefinitionUpdate_t.Install( x => LoadDefinitions() );
|
||||
SteamInventoryDefinitionUpdate_t.Install( x => LoadDefinitions(), true );
|
||||
Dispatch.Install<SteamInventoryFullUpdate_t>( x => InventoryUpdated( x ) );
|
||||
Dispatch.Install<SteamInventoryDefinitionUpdate_t>( x => LoadDefinitions() );
|
||||
Dispatch.Install<SteamInventoryDefinitionUpdate_t>( x => LoadDefinitions(), true );
|
||||
}
|
||||
|
||||
private static void InventoryUpdated( SteamInventoryFullUpdate_t x )
|
||||
|
@ -10,48 +10,36 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Functions for clients to access matchmaking services, favorites, and to operate on game lobbies
|
||||
/// </summary>
|
||||
public static class SteamMatchmaking
|
||||
public class SteamMatchmaking : SteamClass
|
||||
{
|
||||
internal static ISteamMatchmaking Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
Internal = new ISteamMatchmaking( server );
|
||||
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of characters a lobby metadata key can be
|
||||
/// </summary>
|
||||
internal static int MaxLobbyKeyLength => 255;
|
||||
|
||||
|
||||
static ISteamMatchmaking _internal;
|
||||
|
||||
internal static ISteamMatchmaking Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamMatchmaking();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
LobbyInvite_t.Install( x => OnLobbyInvite?.Invoke( new Friend( x.SteamIDUser ), new Lobby( x.SteamIDLobby ) ) );
|
||||
Dispatch.Install<LobbyInvite_t>( x => OnLobbyInvite?.Invoke( new Friend( x.SteamIDUser ), new Lobby( x.SteamIDLobby ) ) );
|
||||
|
||||
LobbyEnter_t.Install( x => OnLobbyEntered?.Invoke( new Lobby( x.SteamIDLobby ) ) );
|
||||
Dispatch.Install<LobbyEnter_t>( x => OnLobbyEntered?.Invoke( new Lobby( x.SteamIDLobby ) ) );
|
||||
|
||||
LobbyCreated_t.Install( x => OnLobbyCreated?.Invoke( x.Result, new Lobby( x.SteamIDLobby ) ) );
|
||||
Dispatch.Install<LobbyCreated_t>( x => OnLobbyCreated?.Invoke( x.Result, new Lobby( x.SteamIDLobby ) ) );
|
||||
|
||||
LobbyGameCreated_t.Install( x => OnLobbyGameCreated?.Invoke( new Lobby( x.SteamIDLobby ), x.IP, x.Port, x.SteamIDGameServer ) );
|
||||
Dispatch.Install<LobbyGameCreated_t>( x => OnLobbyGameCreated?.Invoke( new Lobby( x.SteamIDLobby ), x.IP, x.Port, x.SteamIDGameServer ) );
|
||||
|
||||
LobbyDataUpdate_t.Install( x =>
|
||||
Dispatch.Install<LobbyDataUpdate_t>( x =>
|
||||
{
|
||||
if ( x.Success == 0 ) return;
|
||||
|
||||
@ -61,7 +49,7 @@ namespace Steamworks
|
||||
OnLobbyMemberDataChanged?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDMember ) );
|
||||
} );
|
||||
|
||||
LobbyChatUpdate_t.Install( x =>
|
||||
Dispatch.Install<LobbyChatUpdate_t>( x =>
|
||||
{
|
||||
if ( (x.GfChatMemberStateChange & (int)ChatMemberStateChange.Entered) != 0 )
|
||||
OnLobbyMemberJoined?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ) );
|
||||
@ -79,7 +67,7 @@ namespace Steamworks
|
||||
OnLobbyMemberBanned?.Invoke( new Lobby( x.SteamIDLobby ), new Friend( x.SteamIDUserChanged ), new Friend( x.SteamIDMakingChange ) );
|
||||
} );
|
||||
|
||||
LobbyChatMsg_t.Install( OnLobbyChatMessageRecievedAPI );
|
||||
Dispatch.Install<LobbyChatMsg_t>( OnLobbyChatMessageRecievedAPI );
|
||||
}
|
||||
|
||||
static private unsafe void OnLobbyChatMessageRecievedAPI( LobbyChatMsg_t callback )
|
||||
|
23
Facepunch.Steamworks/SteamMatchmakingServers.cs
Normal file
23
Facepunch.Steamworks/SteamMatchmakingServers.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Functions for clients to access matchmaking services, favorites, and to operate on game lobbies
|
||||
/// </summary>
|
||||
public class SteamMatchmakingServers : SteamClass
|
||||
{
|
||||
internal static ISteamMatchmakingServers Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
Internal = new ISteamMatchmakingServers( server );
|
||||
}
|
||||
}
|
||||
}
|
@ -13,33 +13,22 @@ namespace Steamworks
|
||||
/// when an important cut scene is shown, and start playing afterwards.
|
||||
/// Nothing uses Steam Music though so this can probably get fucked
|
||||
/// </summary>
|
||||
public static class SteamMusic
|
||||
public class SteamMusic : SteamClass
|
||||
{
|
||||
static ISteamMusic _internal;
|
||||
internal static ISteamMusic Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
internal static ISteamMusic Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamMusic();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamMusic( server );
|
||||
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
PlaybackStatusHasChanged_t.Install( x => OnPlaybackChanged?.Invoke() );
|
||||
VolumeHasChanged_t.Install( x => OnVolumeChanged?.Invoke( x.NewVolume ) );
|
||||
Dispatch.Install<PlaybackStatusHasChanged_t>( x => OnPlaybackChanged?.Invoke() );
|
||||
Dispatch.Install<VolumeHasChanged_t>( x => OnVolumeChanged?.Invoke( x.NewVolume ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -8,32 +8,22 @@ using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static class SteamNetworking
|
||||
public class SteamNetworking : SteamClass
|
||||
{
|
||||
static ISteamNetworking _internal;
|
||||
internal static ISteamNetworking Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamNetworking();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamNetworking Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamNetworking( server );
|
||||
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
P2PSessionRequest_t.Install( x => OnP2PSessionRequest?.Invoke( x.SteamIDRemote ) );
|
||||
P2PSessionConnectFail_t.Install( x => OnP2PConnectionFailed?.Invoke( x.SteamIDRemote, (P2PSessionError) x.P2PSessionError ) );
|
||||
Dispatch.Install<P2PSessionRequest_t>( x => OnP2PSessionRequest?.Invoke( x.SteamIDRemote ) );
|
||||
Dispatch.Install<P2PSessionConnectFail_t>( x => OnP2PConnectionFailed?.Invoke( x.SteamIDRemote, (P2PSessionError) x.P2PSessionError ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -8,27 +8,22 @@ using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static class SteamNetworkingSockets
|
||||
public class SteamNetworkingSockets : SteamClass
|
||||
{
|
||||
static ISteamNetworkingSockets _internal;
|
||||
internal static ISteamNetworkingSockets Internal
|
||||
internal static ISteamNetworkingSockets Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamNetworkingSockets();
|
||||
_internal.Init();
|
||||
Internal = new ISteamNetworkingSockets( server );
|
||||
|
||||
SocketInterfaces = new Dictionary<uint, SocketInterface>();
|
||||
ConnectionInterfaces = new Dictionary<uint, ConnectionInterface>();
|
||||
}
|
||||
SocketInterfaces = new Dictionary<uint, SocketInterface>();
|
||||
ConnectionInterfaces = new Dictionary<uint, ConnectionInterface>();
|
||||
|
||||
return _internal;
|
||||
}
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
#region SocketInterface
|
||||
#region SocketInterface
|
||||
|
||||
static Dictionary<uint, SocketInterface> SocketInterfaces;
|
||||
|
||||
@ -50,9 +45,9 @@ namespace Steamworks
|
||||
Console.WriteLine( $"Installing Socket For {id}" );
|
||||
SocketInterfaces[id] = iface;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region ConnectionInterface
|
||||
#region ConnectionInterface
|
||||
static Dictionary<uint, ConnectionInterface> ConnectionInterfaces;
|
||||
|
||||
|
||||
@ -72,20 +67,16 @@ namespace Steamworks
|
||||
if ( id == 0 ) throw new System.ArgumentException( "Invalid Connection" );
|
||||
ConnectionInterfaces[id] = iface;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
SocketInterfaces = null;
|
||||
ConnectionInterfaces = null;
|
||||
}
|
||||
|
||||
internal static void InstallEvents( bool server = false )
|
||||
{
|
||||
SteamNetConnectionStatusChangedCallback_t.Install( x => ConnectionStatusChanged( x ), server );
|
||||
Dispatch.Install<SteamNetConnectionStatusChangedCallback_t>( ConnectionStatusChanged, server );
|
||||
}
|
||||
|
||||
|
||||
private static void ConnectionStatusChanged( SteamNetConnectionStatusChangedCallback_t data )
|
||||
{
|
||||
//
|
||||
@ -115,7 +106,10 @@ namespace Steamworks
|
||||
public static T CreateNormalSocket<T>( NetAddress address ) where T : SocketInterface, new()
|
||||
{
|
||||
var t = new T();
|
||||
t.Socket = Internal.CreateListenSocketIP( ref address );
|
||||
var options = new NetKeyValue[0];
|
||||
t.Socket = Internal.CreateListenSocketIP( ref address, options.Length, options );
|
||||
t.Initialize();
|
||||
|
||||
SetSocketInterface( t.Socket.Id, t );
|
||||
return t;
|
||||
}
|
||||
@ -126,7 +120,8 @@ namespace Steamworks
|
||||
public static T ConnectNormal<T>( NetAddress address ) where T : ConnectionInterface, new()
|
||||
{
|
||||
var t = new T();
|
||||
t.Connection = Internal.ConnectByIPAddress( ref address );
|
||||
var options = new NetKeyValue[0];
|
||||
t.Connection = Internal.ConnectByIPAddress( ref address, options.Length, options );
|
||||
SetConnectionInterface( t.Connection.Id, t );
|
||||
return t;
|
||||
}
|
||||
@ -137,7 +132,8 @@ namespace Steamworks
|
||||
public static T CreateRelaySocket<T>( int virtualport = 0 ) where T : SocketInterface, new()
|
||||
{
|
||||
var t = new T();
|
||||
t.Socket = Internal.CreateListenSocketP2P( virtualport );
|
||||
var options = new NetKeyValue[0];
|
||||
t.Socket = Internal.CreateListenSocketP2P( virtualport, options.Length, options );
|
||||
SetSocketInterface( t.Socket.Id, t );
|
||||
return t;
|
||||
}
|
||||
@ -149,7 +145,8 @@ namespace Steamworks
|
||||
{
|
||||
var t = new T();
|
||||
NetIdentity identity = serverId;
|
||||
t.Connection = Internal.ConnectP2P( ref identity, virtualport );
|
||||
var options = new NetKeyValue[0];
|
||||
t.Connection = Internal.ConnectP2P( ref identity, virtualport, options.Length, options );
|
||||
SetConnectionInterface( t.Connection.Id, t );
|
||||
return t;
|
||||
}
|
||||
|
@ -10,26 +10,51 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamNetworkingUtils
|
||||
public class SteamNetworkingUtils : SteamClass
|
||||
{
|
||||
static ISteamNetworkingUtils _internal;
|
||||
internal static ISteamNetworkingUtils Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamNetworkingUtils();
|
||||
_internal.InitUserless();
|
||||
}
|
||||
internal static ISteamNetworkingUtils Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
Internal = new ISteamNetworkingUtils( server );
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
static void InstallCallbacks()
|
||||
{
|
||||
_internal = null;
|
||||
Dispatch.Install<SteamRelayNetworkStatus_t>( x =>
|
||||
{
|
||||
Status = x.Avail;
|
||||
} );
|
||||
}
|
||||
|
||||
public static SteamNetworkingAvailability Status { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If you know that you are going to be using the relay network (for example,
|
||||
/// because you anticipate making P2P connections), call this to initialize the
|
||||
/// relay network. If you do not call this, the initialization will
|
||||
/// be delayed until the first time you use a feature that requires access
|
||||
/// to the relay network, which will delay that first access.
|
||||
///
|
||||
/// You can also call this to force a retry if the previous attempt has failed.
|
||||
/// Performing any action that requires access to the relay network will also
|
||||
/// trigger a retry, and so calling this function is never strictly necessary,
|
||||
/// but it can be useful to call it a program launch time, if access to the
|
||||
/// relay network is anticipated.
|
||||
///
|
||||
/// Use GetRelayNetworkStatus or listen for SteamRelayNetworkStatus_t
|
||||
/// callbacks to know when initialization has completed.
|
||||
/// Typically initialization completes in a few seconds.
|
||||
///
|
||||
/// Note: dedicated servers hosted in known data centers do *not* need
|
||||
/// to call this, since they do not make routing decisions. However, if
|
||||
/// the dedicated server will be using P2P functionality, it will act as
|
||||
/// a "client" and this should be called.
|
||||
/// </summary>
|
||||
public static void InitRelayNetworkAccess()
|
||||
{
|
||||
Internal.InitRelayNetworkAccess();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -70,10 +95,12 @@ namespace Steamworks
|
||||
/// </summary>
|
||||
public static async Task WaitForPingDataAsync( float maxAgeInSeconds = 60 * 5 )
|
||||
{
|
||||
if ( Internal.CheckPingDataUpToDate( 60.0f ) )
|
||||
if ( Internal.CheckPingDataUpToDate( 120.0f ) )
|
||||
return;
|
||||
|
||||
while ( Internal.IsPingMeasurementInProgress() )
|
||||
SteamRelayNetworkStatus_t status = default;
|
||||
|
||||
while ( Internal.GetRelayNetworkStatus( ref status ) != SteamNetworkingAvailability.Current )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
}
|
||||
@ -118,12 +145,12 @@ namespace Steamworks
|
||||
set => SetConfigFloat( NetConfig.FakePacketLag_Recv, value );
|
||||
}
|
||||
|
||||
#region Config Internals
|
||||
#region Config Internals
|
||||
|
||||
internal unsafe static bool GetConfigInt( NetConfig type, int value )
|
||||
{
|
||||
int* ptr = &value;
|
||||
return Internal.SetConfigValue( type, NetScope.Global, 0, NetConfigType.Int32, (IntPtr)ptr );
|
||||
return Internal.SetConfigValue( type, NetConfigScope.Global, IntPtr.Zero, NetConfigType.Int32, (IntPtr)ptr );
|
||||
}
|
||||
|
||||
internal unsafe static int GetConfigInt( NetConfig type )
|
||||
@ -131,8 +158,8 @@ namespace Steamworks
|
||||
int value = 0;
|
||||
NetConfigType dtype = NetConfigType.Int32;
|
||||
int* ptr = &value;
|
||||
ulong size = sizeof( int );
|
||||
var result = Internal.GetConfigValue( type, NetScope.Global, 0, ref dtype, (IntPtr) ptr, ref size );
|
||||
UIntPtr size = new UIntPtr( sizeof( int ) );
|
||||
var result = Internal.GetConfigValue( type, NetConfigScope.Global, IntPtr.Zero, ref dtype, (IntPtr) ptr, ref size );
|
||||
if ( result != NetConfigResult.OK )
|
||||
return 0;
|
||||
|
||||
@ -142,7 +169,7 @@ namespace Steamworks
|
||||
internal unsafe static bool SetConfigFloat( NetConfig type, float value )
|
||||
{
|
||||
float* ptr = &value;
|
||||
return Internal.SetConfigValue( type, NetScope.Global, 0, NetConfigType.Float, (IntPtr)ptr );
|
||||
return Internal.SetConfigValue( type, NetConfigScope.Global, IntPtr.Zero, NetConfigType.Float, (IntPtr)ptr );
|
||||
}
|
||||
|
||||
internal unsafe static float GetConfigFloat( NetConfig type )
|
||||
@ -150,8 +177,8 @@ namespace Steamworks
|
||||
float value = 0;
|
||||
NetConfigType dtype = NetConfigType.Float;
|
||||
float* ptr = &value;
|
||||
ulong size = sizeof( float );
|
||||
var result = Internal.GetConfigValue( type, NetScope.Global, 0, ref dtype, (IntPtr)ptr, ref size );
|
||||
UIntPtr size = new UIntPtr( sizeof( float ) );
|
||||
var result = Internal.GetConfigValue( type, NetConfigScope.Global, IntPtr.Zero, ref dtype, (IntPtr)ptr, ref size );
|
||||
if ( result != NetConfigResult.OK )
|
||||
return 0;
|
||||
|
||||
@ -164,7 +191,7 @@ namespace Steamworks
|
||||
|
||||
fixed ( byte* ptr = bytes )
|
||||
{
|
||||
return Internal.SetConfigValue( type, NetScope.Global, 0, NetConfigType.String, (IntPtr)ptr );
|
||||
return Internal.SetConfigValue( type, NetConfigScope.Global, IntPtr.Zero, NetConfigType.String, (IntPtr)ptr );
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,6 +238,6 @@ namespace Steamworks
|
||||
}
|
||||
}*/
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,32 +10,21 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamParental
|
||||
public class SteamParental : SteamClass
|
||||
{
|
||||
static ISteamParentalSettings _internal;
|
||||
internal static ISteamParentalSettings Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
internal static ISteamParentalSettings Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamParentalSettings();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamParentalSettings( server );
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
SteamParentalSettingsChanged_t.Install( x => OnSettingsChanged?.Invoke() );
|
||||
Dispatch.Install<SteamParentalSettingsChanged_t>( x => OnSettingsChanged?.Invoke() );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -7,31 +7,21 @@ using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static class SteamParties
|
||||
public class SteamParties : SteamClass
|
||||
{
|
||||
static ISteamParties _internal;
|
||||
internal static ISteamParties Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamParties();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamParties Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamParties( server );
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
AvailableBeaconLocationsUpdated_t.Install( x => OnBeaconLocationsUpdated?.Invoke() );
|
||||
ActiveBeaconsUpdated_t.Install( x => OnActiveBeaconsUpdated?.Invoke() );
|
||||
Dispatch.Install<AvailableBeaconLocationsUpdated_t>( x => OnBeaconLocationsUpdated?.Invoke() );
|
||||
Dispatch.Install<ActiveBeaconsUpdated_t>( x => OnActiveBeaconsUpdated?.Invoke() );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -10,26 +10,14 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamRemoteStorage
|
||||
public class SteamRemoteStorage : SteamClass
|
||||
{
|
||||
static ISteamRemoteStorage _internal;
|
||||
internal static ISteamRemoteStorage Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamRemoteStorage();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamRemoteStorage Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamRemoteStorage( server );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -10,33 +10,21 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamScreenshots
|
||||
public class SteamScreenshots : SteamClass
|
||||
{
|
||||
static ISteamScreenshots _internal;
|
||||
internal static ISteamScreenshots Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
internal static ISteamScreenshots Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamScreenshots();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamScreenshots( server );
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
ScreenshotRequested_t.Install( x => OnScreenshotRequested?.Invoke() );
|
||||
ScreenshotReady_t.Install( x =>
|
||||
Dispatch.Install<ScreenshotRequested_t>( x => OnScreenshotRequested?.Invoke() );
|
||||
Dispatch.Install<ScreenshotReady_t>( x =>
|
||||
{
|
||||
if ( x.Result != Result.OK )
|
||||
OnScreenshotFailed?.Invoke( x.Result );
|
||||
|
@ -10,26 +10,18 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Provides the core of the Steam Game Servers API
|
||||
/// </summary>
|
||||
public static partial class SteamServer
|
||||
public partial class SteamServer : SteamClass
|
||||
{
|
||||
static bool initialized;
|
||||
internal static ISteamGameServer Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
static ISteamGameServer _internal;
|
||||
internal static ISteamGameServer Internal
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamGameServer( );
|
||||
_internal.InitServer();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
Internal = new ISteamGameServer( server );
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
public static bool IsValid => initialized;
|
||||
public static bool IsValid => Internal != null && Internal.IsValid;
|
||||
|
||||
|
||||
public static Action<Exception> OnCallbackException;
|
||||
@ -37,12 +29,12 @@ namespace Steamworks
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
SteamInventory.InstallEvents();
|
||||
SteamNetworkingSockets.InstallEvents(true);
|
||||
//SteamNetworkingSockets.InstallEvents(true);
|
||||
|
||||
ValidateAuthTicketResponse_t.Install( x => OnValidateAuthTicketResponse?.Invoke( x.SteamID, x.OwnerSteamID, x.AuthSessionResponse ), true );
|
||||
SteamServersConnected_t.Install( x => OnSteamServersConnected?.Invoke(), true );
|
||||
SteamServerConnectFailure_t.Install( x => OnSteamServerConnectFailure?.Invoke( x.Result, x.StillRetrying ), true );
|
||||
SteamServersDisconnected_t.Install( x => OnSteamServersDisconnected?.Invoke( x.Result ), true );
|
||||
Dispatch.Install<ValidateAuthTicketResponse_t>( x => OnValidateAuthTicketResponse?.Invoke( x.SteamID, x.OwnerSteamID, x.AuthSessionResponse ), true );
|
||||
Dispatch.Install<SteamServersConnected_t>( x => OnSteamServersConnected?.Invoke(), true );
|
||||
Dispatch.Install<SteamServerConnectFailure_t>( x => OnSteamServerConnectFailure?.Invoke( x.Result, x.StillRetrying ), true );
|
||||
Dispatch.Install<SteamServersDisconnected_t>( x => OnSteamServersDisconnected?.Invoke( x.Result ), true );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -93,7 +85,17 @@ namespace Steamworks
|
||||
throw new System.Exception( $"InitGameServer returned false ({ipaddress},{init.SteamPort},{init.GamePort},{init.QueryPort},{secure},\"{init.VersionString}\")" );
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
//
|
||||
// Dispatch is responsible for pumping the
|
||||
// event loop.
|
||||
//
|
||||
Dispatch.Init();
|
||||
Dispatch.ServerPipe = SteamGameServer.GetHSteamPipe();
|
||||
Console.WriteLine( $"Dispatch.ServerPipe = {Dispatch.ServerPipe.Value}" );
|
||||
|
||||
AddInterface<SteamServer>();
|
||||
AddInterface<SteamNetworkingUtils>();
|
||||
AddInterface<SteamNetworkingSockets>();
|
||||
|
||||
//
|
||||
// Initial settings
|
||||
@ -111,71 +113,50 @@ namespace Steamworks
|
||||
|
||||
if ( asyncCallbacks )
|
||||
{
|
||||
RunCallbacksAsync();
|
||||
//
|
||||
// This will keep looping in the background every 16 ms
|
||||
// until we shut down.
|
||||
//
|
||||
Dispatch.LoopServerAsync();
|
||||
}
|
||||
}
|
||||
|
||||
static List<SteamInterface> openIterfaces = new List<SteamInterface>();
|
||||
|
||||
internal static void WatchInterface( SteamInterface steamInterface )
|
||||
internal static void AddInterface<T>() where T : SteamClass, new()
|
||||
{
|
||||
if ( openIterfaces.Contains( steamInterface ) )
|
||||
throw new System.Exception( "openIterfaces already contains interface!" );
|
||||
|
||||
openIterfaces.Add( steamInterface );
|
||||
var t = new T();
|
||||
t.InitializeInterface( true );
|
||||
openInterfaces.Add( t );
|
||||
}
|
||||
|
||||
static List<SteamClass> openInterfaces = new List<SteamClass>();
|
||||
|
||||
internal static void ShutdownInterfaces()
|
||||
{
|
||||
foreach ( var e in openIterfaces )
|
||||
foreach ( var e in openInterfaces )
|
||||
{
|
||||
e.Shutdown();
|
||||
e.DestroyInterface();
|
||||
}
|
||||
|
||||
openIterfaces.Clear();
|
||||
openInterfaces.Clear();
|
||||
}
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
Event.DisposeAllServer();
|
||||
|
||||
initialized = false;
|
||||
|
||||
_internal = null;
|
||||
Internal = null;
|
||||
|
||||
ShutdownInterfaces();
|
||||
SteamNetworkingUtils.Shutdown();
|
||||
SteamNetworkingSockets.Shutdown();
|
||||
SteamInventory.Shutdown();
|
||||
|
||||
SteamServerStats.Shutdown();
|
||||
|
||||
SteamGameServer.Shutdown();
|
||||
}
|
||||
|
||||
internal static async void RunCallbacksAsync()
|
||||
{
|
||||
while ( IsValid )
|
||||
{
|
||||
try
|
||||
{
|
||||
RunCallbacks();
|
||||
}
|
||||
catch ( System.Exception e )
|
||||
{
|
||||
OnCallbackException?.Invoke( e );
|
||||
}
|
||||
|
||||
await Task.Delay( 16 );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the callbacks. This is also called in Async callbacks.
|
||||
/// </summary>
|
||||
public static void RunCallbacks()
|
||||
{
|
||||
SteamGameServer.RunCallbacks();
|
||||
if ( Dispatch.ServerPipe != 0 )
|
||||
{
|
||||
Dispatch.Frame( Dispatch.ServerPipe );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -315,16 +296,7 @@ namespace Steamworks
|
||||
/// current public ip address. Be aware that this is likely to return
|
||||
/// null for the first few seconds after initialization.
|
||||
/// </summary>
|
||||
public static System.Net.IPAddress PublicIp
|
||||
{
|
||||
get
|
||||
{
|
||||
var ip = Internal.GetPublicIP();
|
||||
if ( ip == 0 ) return null;
|
||||
|
||||
return Utility.Int32ToIp( ip );
|
||||
}
|
||||
}
|
||||
public static System.Net.IPAddress PublicIp => Internal.GetPublicIP();
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable heartbeats, which are sent regularly to the master server.
|
||||
|
@ -7,26 +7,14 @@ using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static class SteamServerStats
|
||||
public class SteamServerStats : SteamClass
|
||||
{
|
||||
static ISteamGameServerStats _internal;
|
||||
internal static ISteamGameServerStats Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamGameServerStats();
|
||||
_internal.InitServer();
|
||||
}
|
||||
internal static ISteamGameServerStats Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamGameServerStats( server );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -47,7 +35,7 @@ namespace Steamworks
|
||||
/// </summary>
|
||||
public static bool SetInt( SteamId steamid, string name, int stat )
|
||||
{
|
||||
return Internal.SetUserStat1( steamid, name, stat );
|
||||
return Internal.SetUserStat( steamid, name, stat );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -56,7 +44,7 @@ namespace Steamworks
|
||||
/// </summary>
|
||||
public static bool SetFloat( SteamId steamid, string name, float stat )
|
||||
{
|
||||
return Internal.SetUserStat2( steamid, name, stat );
|
||||
return Internal.SetUserStat( steamid, name, stat );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -68,7 +56,7 @@ namespace Steamworks
|
||||
{
|
||||
int data = defaultValue;
|
||||
|
||||
if ( !Internal.GetUserStat1( steamid, name, ref data ) )
|
||||
if ( !Internal.GetUserStat( steamid, name, ref data ) )
|
||||
return defaultValue;
|
||||
|
||||
return data;
|
||||
@ -83,7 +71,7 @@ namespace Steamworks
|
||||
{
|
||||
float data = defaultValue;
|
||||
|
||||
if ( !Internal.GetUserStat2( steamid, name, ref data ) )
|
||||
if ( !Internal.GetUserStat( steamid, name, ref data ) )
|
||||
return defaultValue;
|
||||
|
||||
return data;
|
||||
|
@ -12,26 +12,20 @@ namespace Steamworks
|
||||
/// Functions for accessing and manipulating Steam user information.
|
||||
/// This is also where the APIs for Steam Voice are exposed.
|
||||
/// </summary>
|
||||
public static class SteamUGC
|
||||
public class SteamUGC : SteamClass
|
||||
{
|
||||
static ISteamUGC _internal;
|
||||
internal static ISteamUGC Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamUGC();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamUGC Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
Internal = new ISteamUGC( server );
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
DownloadItemResult_t.Install( x => OnDownloadItemResult?.Invoke( x.Result ) );
|
||||
Dispatch.Install<DownloadItemResult_t>( x => OnDownloadItemResult?.Invoke( x.Result ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -39,11 +33,6 @@ namespace Steamworks
|
||||
/// </summary>
|
||||
public static event Action<Result> OnDownloadItemResult;
|
||||
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
}
|
||||
|
||||
public static async Task<bool> DeleteFileAsync( PublishedFileId fileId )
|
||||
{
|
||||
var r = await Internal.DeleteItem( fileId );
|
||||
|
@ -13,46 +13,33 @@ namespace Steamworks
|
||||
/// Functions for accessing and manipulating Steam user information.
|
||||
/// This is also where the APIs for Steam Voice are exposed.
|
||||
/// </summary>
|
||||
public static class SteamUser
|
||||
public class SteamUser : SteamClass
|
||||
{
|
||||
static ISteamUser _internal;
|
||||
internal static ISteamUser Internal
|
||||
internal static ISteamUser Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
Internal = new ISteamUser( server );
|
||||
InstallEvents();
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamUser();
|
||||
_internal.Init();
|
||||
|
||||
richPresence = new Dictionary<string, string>();
|
||||
|
||||
SampleRate = OptimalSampleRate;
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
richPresence = new Dictionary<string, string>();
|
||||
SampleRate = OptimalSampleRate;
|
||||
}
|
||||
|
||||
static Dictionary<string, string> richPresence;
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
SteamServersConnected_t.Install( x => OnSteamServersConnected?.Invoke() );
|
||||
SteamServerConnectFailure_t.Install( x => OnSteamServerConnectFailure?.Invoke() );
|
||||
SteamServersDisconnected_t.Install( x => OnSteamServersDisconnected?.Invoke() );
|
||||
ClientGameServerDeny_t.Install( x => OnClientGameServerDeny?.Invoke() );
|
||||
LicensesUpdated_t.Install( x => OnLicensesUpdated?.Invoke() );
|
||||
ValidateAuthTicketResponse_t.Install( x => OnValidateAuthTicketResponse?.Invoke( x.SteamID, x.OwnerSteamID, x.AuthSessionResponse ) );
|
||||
MicroTxnAuthorizationResponse_t.Install( x => OnMicroTxnAuthorizationResponse?.Invoke( x.AppID, x.OrderID, x.Authorized != 0 ) );
|
||||
GameWebCallback_t.Install( x => OnGameWebCallback?.Invoke( x.URLUTF8() ) );
|
||||
GetAuthSessionTicketResponse_t.Install( x => OnGetAuthSessionTicketResponse?.Invoke( x ) );
|
||||
Dispatch.Install<SteamServersConnected_t>( x => OnSteamServersConnected?.Invoke() );
|
||||
Dispatch.Install<SteamServerConnectFailure_t>( x => OnSteamServerConnectFailure?.Invoke() );
|
||||
Dispatch.Install<SteamServersDisconnected_t>( x => OnSteamServersDisconnected?.Invoke() );
|
||||
Dispatch.Install<ClientGameServerDeny_t>( x => OnClientGameServerDeny?.Invoke() );
|
||||
Dispatch.Install<LicensesUpdated_t>( x => OnLicensesUpdated?.Invoke() );
|
||||
Dispatch.Install<ValidateAuthTicketResponse_t>( x => OnValidateAuthTicketResponse?.Invoke( x.SteamID, x.OwnerSteamID, x.AuthSessionResponse ) );
|
||||
Dispatch.Install<MicroTxnAuthorizationResponse_t>( x => OnMicroTxnAuthorizationResponse?.Invoke( x.AppID, x.OrderID, x.Authorized != 0 ) );
|
||||
Dispatch.Install<GameWebCallback_t>( x => OnGameWebCallback?.Invoke( x.URLUTF8() ) );
|
||||
Dispatch.Install<GetAuthSessionTicketResponse_t>( x => OnGetAuthSessionTicketResponse?.Invoke( x ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -424,6 +411,7 @@ namespace Steamworks
|
||||
/// Requests an application ticket encrypted with the secret "encrypted app ticket key".
|
||||
/// The encryption key can be obtained from the Encrypted App Ticket Key page on the App Admin for your app.
|
||||
/// There can only be one call pending, and this call is subject to a 60 second rate limit.
|
||||
/// If you get a null result from this it's probably because you're calling it too often.
|
||||
/// This can fail if you don't have an encrypted ticket set for your app here https://partner.steamgames.com/apps/sdkauth/
|
||||
/// </summary>
|
||||
public static async Task<byte[]> RequestEncryptedAppTicketAsync( byte[] dataToInclude )
|
||||
|
@ -7,36 +7,24 @@ using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static class SteamUserStats
|
||||
public class SteamUserStats : SteamClass
|
||||
{
|
||||
static ISteamUserStats _internal;
|
||||
internal static ISteamUserStats Internal
|
||||
internal static ISteamUserStats Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
Internal = new ISteamUserStats( server );
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamUserStats();
|
||||
_internal.Init();
|
||||
|
||||
RequestCurrentStats();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
InstallEvents();
|
||||
RequestCurrentStats();
|
||||
}
|
||||
|
||||
public static bool StatsRecieved { get; internal set; }
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
UserStatsReceived_t.Install( x =>
|
||||
Dispatch.Install<UserStatsReceived_t>( x =>
|
||||
{
|
||||
if ( x.SteamIDUser == SteamClient.SteamId )
|
||||
StatsRecieved = true;
|
||||
@ -44,10 +32,10 @@ namespace Steamworks
|
||||
OnUserStatsReceived?.Invoke( x.SteamIDUser, x.Result );
|
||||
} );
|
||||
|
||||
UserStatsStored_t.Install( x => OnUserStatsStored?.Invoke( x.Result ) );
|
||||
UserAchievementStored_t.Install( x => OnAchievementProgress?.Invoke( new Achievement( x.AchievementNameUTF8() ), (int) x.CurProgress, (int)x.MaxProgress ) );
|
||||
UserStatsUnloaded_t.Install( x => OnUserStatsUnloaded?.Invoke( x.SteamIDUser ) );
|
||||
UserAchievementIconFetched_t.Install( x => OnAchievementIconFetched?.Invoke( x.AchievementNameUTF8(), x.IconHandle ) );
|
||||
Dispatch.Install<UserStatsStored_t>( x => OnUserStatsStored?.Invoke( x.Result ) );
|
||||
Dispatch.Install<UserAchievementStored_t>( x => OnAchievementProgress?.Invoke( new Achievement( x.AchievementNameUTF8() ), (int) x.CurProgress, (int)x.MaxProgress ) );
|
||||
Dispatch.Install<UserStatsUnloaded_t>( x => OnUserStatsUnloaded?.Invoke( x.SteamIDUser ) );
|
||||
Dispatch.Install<UserAchievementIconFetched_t>( x => OnAchievementIconFetched?.Invoke( x.AchievementNameUTF8(), x.IconHandle ) );
|
||||
}
|
||||
|
||||
|
||||
@ -209,7 +197,7 @@ namespace Steamworks
|
||||
/// </summary>
|
||||
public static bool SetStat( string name, int value )
|
||||
{
|
||||
return Internal.SetStat1( name, value );
|
||||
return Internal.SetStat( name, value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -218,7 +206,7 @@ namespace Steamworks
|
||||
/// </summary>
|
||||
public static bool SetStat( string name, float value )
|
||||
{
|
||||
return Internal.SetStat2( name, value );
|
||||
return Internal.SetStat( name, value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -227,7 +215,7 @@ namespace Steamworks
|
||||
public static int GetStatInt( string name )
|
||||
{
|
||||
int data = 0;
|
||||
Internal.GetStat1( name, ref data );
|
||||
Internal.GetStat( name, ref data );
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -237,7 +225,7 @@ namespace Steamworks
|
||||
public static float GetStatFloat( string name )
|
||||
{
|
||||
float data = 0;
|
||||
Internal.GetStat2( name, ref data );
|
||||
Internal.GetStat( name, ref data );
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -10,34 +10,24 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Interface which provides access to a range of miscellaneous utility functions
|
||||
/// </summary>
|
||||
public static class SteamUtils
|
||||
public class SteamUtils : SteamClass
|
||||
{
|
||||
static ISteamUtils _internal;
|
||||
internal static ISteamUtils Internal
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamUtils();
|
||||
_internal.Init();
|
||||
}
|
||||
internal static ISteamUtils Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
_internal = null;
|
||||
Internal = new ISteamUtils( server );
|
||||
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
IPCountry_t.Install( x => OnIpCountryChanged?.Invoke() );
|
||||
LowBatteryPower_t.Install( x => OnLowBatteryPower?.Invoke( x.MinutesBatteryLeft ) );
|
||||
SteamShutdown_t.Install( x => SteamClosed() );
|
||||
GamepadTextInputDismissed_t.Install( x => OnGamepadTextInputDismissed?.Invoke( x.Submitted ) );
|
||||
Dispatch.Install<IPCountry_t>( x => OnIpCountryChanged?.Invoke() );
|
||||
Dispatch.Install<LowBatteryPower_t>( x => OnLowBatteryPower?.Invoke( x.MinutesBatteryLeft ) );
|
||||
Dispatch.Install<SteamShutdown_t>( x => SteamClosed() );
|
||||
Dispatch.Install<GamepadTextInputDismissed_t>( x => OnGamepadTextInputDismissed?.Invoke( x.Submitted ) );
|
||||
}
|
||||
|
||||
private static void SteamClosed()
|
||||
|
@ -10,34 +10,22 @@ namespace Steamworks
|
||||
/// <summary>
|
||||
/// Undocumented Parental Settings
|
||||
/// </summary>
|
||||
public static class SteamVideo
|
||||
public class SteamVideo : SteamClass
|
||||
{
|
||||
static ISteamVideo _internal;
|
||||
internal static ISteamVideo Internal
|
||||
internal static ISteamVideo Internal;
|
||||
internal override SteamInterface Interface => Internal;
|
||||
|
||||
internal override void InitializeInterface( bool server )
|
||||
{
|
||||
get
|
||||
{
|
||||
SteamClient.ValidCheck();
|
||||
Internal = new ISteamVideo( server );
|
||||
|
||||
if ( _internal == null )
|
||||
{
|
||||
_internal = new ISteamVideo();
|
||||
_internal.Init();
|
||||
}
|
||||
|
||||
return _internal;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Shutdown()
|
||||
{
|
||||
_internal = null;
|
||||
InstallEvents();
|
||||
}
|
||||
|
||||
internal static void InstallEvents()
|
||||
{
|
||||
BroadcastUploadStart_t.Install( x => OnBroadcastStarted?.Invoke() );
|
||||
BroadcastUploadStop_t.Install( x => OnBroadcastStopped?.Invoke( x.Result ) );
|
||||
Dispatch.Install<BroadcastUploadStart_t>( x => OnBroadcastStarted?.Invoke() );
|
||||
Dispatch.Install<BroadcastUploadStop_t>( x => OnBroadcastStopped?.Invoke( x.Result ) );
|
||||
}
|
||||
|
||||
public static event Action OnBroadcastStarted;
|
||||
|
@ -5,9 +5,11 @@ namespace Steamworks.Data
|
||||
{
|
||||
public struct Connection
|
||||
{
|
||||
public uint Id { get; }
|
||||
public uint Id { get; set; }
|
||||
|
||||
public override string ToString() => Id.ToString();
|
||||
public static implicit operator Connection( uint value ) => new Connection() { Id = value };
|
||||
public static implicit operator uint( Connection value ) => value.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Accept an incoming connection that has been received on a listen socket.
|
||||
@ -54,7 +56,8 @@ namespace Steamworks.Data
|
||||
|
||||
public Result SendMessage( IntPtr ptr, int size, SendType sendType = SendType.Reliable )
|
||||
{
|
||||
return SteamNetworkingSockets.Internal.SendMessageToConnection( this, ptr, (uint) size, (int)sendType );
|
||||
long messageNumber = 0;
|
||||
return SteamNetworkingSockets.Internal.SendMessageToConnection( this, ptr, (uint) size, (int)sendType, ref messageNumber );
|
||||
}
|
||||
|
||||
public unsafe Result SendMessage( byte[] data, SendType sendType = SendType.Reliable )
|
||||
@ -91,27 +94,5 @@ namespace Steamworks.Data
|
||||
|
||||
return strVal;
|
||||
}
|
||||
|
||||
/*
|
||||
[ThreadStatic]
|
||||
private static SteamNetworkingMessage_t[] messageBuffer;
|
||||
|
||||
public IEnumerable<SteamNetworkingMessage_t> Messages
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( messageBuffer == null )
|
||||
messageBuffer = new SteamNetworkingMessage_t[128];
|
||||
|
||||
var num = SteamNetworkingSockets.Internal.ReceiveMessagesOnConnection( this, ref messageBuffer, messageBuffer.Length );
|
||||
|
||||
for ( int i = 0; i < num; i++)
|
||||
{
|
||||
yield return messageBuffer[i];
|
||||
messageBuffer[i].Release();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,17 +130,20 @@ namespace Steamworks
|
||||
{
|
||||
if ( Properties == null ) return DateTime.UtcNow;
|
||||
|
||||
var str = Properties["acquired"];
|
||||
if ( Properties.TryGetValue( "acquired", out var str ) )
|
||||
{
|
||||
var y = int.Parse( str.Substring( 0, 4 ) );
|
||||
var m = int.Parse( str.Substring( 4, 2 ) );
|
||||
var d = int.Parse( str.Substring( 6, 2 ) );
|
||||
|
||||
var y = int.Parse( str.Substring( 0, 4 ) );
|
||||
var m = int.Parse( str.Substring( 4, 2 ) );
|
||||
var d = int.Parse( str.Substring( 6, 2 ) );
|
||||
var h = int.Parse( str.Substring( 9, 2 ) );
|
||||
var mn = int.Parse( str.Substring( 11, 2 ) );
|
||||
var s = int.Parse( str.Substring( 13, 2 ) );
|
||||
|
||||
var h = int.Parse( str.Substring( 9, 2 ) );
|
||||
var mn = int.Parse( str.Substring( 11, 2 ) );
|
||||
var s = int.Parse( str.Substring( 13, 2 ) );
|
||||
return new DateTime( y, m, d, h, mn, s, DateTimeKind.Utc );
|
||||
}
|
||||
|
||||
return new DateTime( y, m, d, h, mn, s, DateTimeKind.Utc );
|
||||
return DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +156,11 @@ namespace Steamworks
|
||||
get
|
||||
{
|
||||
if ( Properties == null ) return null;
|
||||
return Properties["origin"];
|
||||
|
||||
if ( Properties.TryGetValue( "origin", out var str ) )
|
||||
return str;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,12 @@ namespace Steamworks.Data
|
||||
return value.steamID;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{type};{m_cbSize};{steamID}";
|
||||
public override string ToString()
|
||||
{
|
||||
var id = this;
|
||||
SteamNetworkingUtils.Internal.SteamNetworkingIdentity_ToString( ref id, out var str );
|
||||
return str;
|
||||
}
|
||||
|
||||
internal enum IdentityType
|
||||
{
|
||||
|
31
Facepunch.Steamworks/Structs/NetKeyValue.cs
Normal file
31
Facepunch.Steamworks/Structs/NetKeyValue.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Steamworks.Data;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
[StructLayout( LayoutKind.Explicit, Pack = Platform.StructPlatformPackSize )]
|
||||
internal struct NetKeyValue
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal NetConfig Value; // m_eValue ESteamNetworkingConfigValue
|
||||
|
||||
[FieldOffset( 4 )]
|
||||
internal NetConfigType DataType; // m_eDataType ESteamNetworkingConfigDataType
|
||||
|
||||
[FieldOffset( 8 )]
|
||||
internal long Int64Value; // m_int64 int64_t
|
||||
|
||||
[FieldOffset( 8 )]
|
||||
internal int Int32Value; // m_val_int32 int32_t
|
||||
|
||||
[FieldOffset( 8 )]
|
||||
internal float FloatValue; // m_val_float float
|
||||
|
||||
[FieldOffset( 8 )]
|
||||
internal IntPtr PointerValue; // m_val_functionPtr void *
|
||||
|
||||
|
||||
// TODO - support strings, maybe
|
||||
}
|
||||
}
|
@ -1,9 +1,15 @@
|
||||
namespace Steamworks.Data
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
public struct Socket
|
||||
{
|
||||
internal uint Id;
|
||||
public override string ToString() => Id.ToString();
|
||||
public static implicit operator Socket( uint value ) => new Socket() { Id = value };
|
||||
public static implicit operator uint( Socket value ) => value.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Destroy a listen socket. All the connections that were accepting on the listen
|
||||
@ -11,7 +17,7 @@
|
||||
/// </summary>
|
||||
public bool Close()
|
||||
{
|
||||
return SteamNetworkingSockets.Internal.CloseListenSocket( this );
|
||||
return SteamNetworkingSockets.Internal.CloseListenSocket( Id );
|
||||
}
|
||||
|
||||
public SocketInterface Interface
|
||||
|
@ -36,7 +36,7 @@ namespace Steamworks.Data
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
if ( SteamUserStats.Internal.GetGlobalStat2( Name, ref val ) )
|
||||
if ( SteamUserStats.Internal.GetGlobalStat( Name, ref val ) )
|
||||
return val;
|
||||
|
||||
return 0;
|
||||
@ -45,7 +45,7 @@ namespace Steamworks.Data
|
||||
public long GetGlobalInt()
|
||||
{
|
||||
long val = 0;
|
||||
SteamUserStats.Internal.GetGlobalStat1( Name, ref val );
|
||||
SteamUserStats.Internal.GetGlobalStat( Name, ref val );
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ namespace Steamworks.Data
|
||||
|
||||
var r = new long[days];
|
||||
|
||||
var rows = SteamUserStats.Internal.GetGlobalStatHistory1( Name, r, (uint) r.Length * sizeof(long) );
|
||||
var rows = SteamUserStats.Internal.GetGlobalStatHistory( Name, r, (uint) r.Length * sizeof(long) );
|
||||
|
||||
if ( days != rows )
|
||||
r = r.Take( rows ).ToArray();
|
||||
@ -71,7 +71,7 @@ namespace Steamworks.Data
|
||||
|
||||
var r = new double[days];
|
||||
|
||||
var rows = SteamUserStats.Internal.GetGlobalStatHistory2( Name, r, (uint)r.Length * sizeof( double ) );
|
||||
var rows = SteamUserStats.Internal.GetGlobalStatHistory( Name, r, (uint)r.Length * sizeof( double ) );
|
||||
|
||||
if ( days != rows )
|
||||
r = r.Take( rows ).ToArray();
|
||||
@ -85,11 +85,11 @@ namespace Steamworks.Data
|
||||
|
||||
if ( UserId > 0 )
|
||||
{
|
||||
SteamUserStats.Internal.GetUserStat2( UserId, Name, ref val );
|
||||
SteamUserStats.Internal.GetUserStat( UserId, Name, ref val );
|
||||
}
|
||||
else
|
||||
{
|
||||
SteamUserStats.Internal.GetStat2( Name, ref val );
|
||||
SteamUserStats.Internal.GetStat( Name, ref val );
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -101,11 +101,11 @@ namespace Steamworks.Data
|
||||
|
||||
if ( UserId > 0 )
|
||||
{
|
||||
SteamUserStats.Internal.GetUserStat1( UserId, Name, ref val );
|
||||
SteamUserStats.Internal.GetUserStat( UserId, Name, ref val );
|
||||
}
|
||||
else
|
||||
{
|
||||
SteamUserStats.Internal.GetStat1( Name, ref val );
|
||||
SteamUserStats.Internal.GetStat( Name, ref val );
|
||||
}
|
||||
|
||||
return val;
|
||||
@ -114,13 +114,13 @@ namespace Steamworks.Data
|
||||
public bool Set( int val )
|
||||
{
|
||||
LocalUserOnly();
|
||||
return SteamUserStats.Internal.SetStat1( Name, val );
|
||||
return SteamUserStats.Internal.SetStat( Name, val );
|
||||
}
|
||||
|
||||
public bool Set( float val )
|
||||
{
|
||||
LocalUserOnly();
|
||||
return SteamUserStats.Internal.SetStat2( Name, val );
|
||||
return SteamUserStats.Internal.SetStat( Name, val );
|
||||
}
|
||||
|
||||
public bool Add( int val )
|
||||
|
26
Facepunch.Steamworks/Structs/SteamIpAddress.cs
Normal file
26
Facepunch.Steamworks/Structs/SteamIpAddress.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
[StructLayout( LayoutKind.Explicit, Pack = Platform.StructPlatformPackSize )]
|
||||
internal struct SteamIPAddress
|
||||
{
|
||||
[FieldOffset( 0 )]
|
||||
public uint Ip4Address; // Host Order
|
||||
|
||||
[FieldOffset( 16 )]
|
||||
internal SteamIPType Type; // m_eType ESteamIPType
|
||||
|
||||
public static implicit operator System.Net.IPAddress( SteamIPAddress value )
|
||||
{
|
||||
if ( value.Type == SteamIPType.Type4 )
|
||||
return Utility.Int32ToIp( value.Ip4Address );
|
||||
|
||||
throw new System.Exception( $"Oops - can't convert SteamIPAddress to System.Net.IPAddress because no-one coded support for {value.Type} yet" );
|
||||
}
|
||||
}
|
||||
}
|
@ -7,23 +7,6 @@ namespace Steamworks.Data
|
||||
{
|
||||
delegate void FSteamNetworkingSocketsDebugOutput (DebugOutputType nType, string pszMsg );
|
||||
|
||||
public struct SteamNetworkingPOPID
|
||||
{
|
||||
public uint Value;
|
||||
|
||||
public static implicit operator SteamNetworkingPOPID( uint value )
|
||||
{
|
||||
return new SteamNetworkingPOPID { Value = value };
|
||||
}
|
||||
|
||||
public static implicit operator uint( SteamNetworkingPOPID value )
|
||||
{
|
||||
return value.Value;
|
||||
}
|
||||
|
||||
public override string ToString() => Value.ToString();
|
||||
}
|
||||
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
public struct SteamNetworkingQuickConnectionStatus
|
||||
{
|
||||
@ -49,9 +32,4 @@ namespace Steamworks.Data
|
||||
{
|
||||
// Not implemented
|
||||
};
|
||||
|
||||
struct SteamDatagramHostedAddress
|
||||
{
|
||||
// Not implemented
|
||||
}
|
||||
}
|
11
Facepunch.Steamworks/Structs/SteamNetworkingErrMsg.cs
Normal file
11
Facepunch.Steamworks/Structs/SteamNetworkingErrMsg.cs
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
|
||||
internal unsafe struct SteamNetworkingErrMsg
|
||||
{
|
||||
public fixed char Value[1024];
|
||||
}
|
||||
}
|
@ -204,7 +204,7 @@ namespace Steamworks.Ugc
|
||||
|
||||
progress?.Report( 1 );
|
||||
|
||||
var updated = updating.Result;
|
||||
var updated = updating.GetResult();
|
||||
|
||||
if ( !updated.HasValue ) return result;
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace Steamworks.Ugc
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = SteamUGC.Internal.CreateQueryAllUGCRequest1( queryType, matchingType, creatorApp.Value, consumerApp.Value, (uint)page );
|
||||
handle = SteamUGC.Internal.CreateQueryAllUGCRequest( queryType, matchingType, creatorApp.Value, consumerApp.Value, (uint)page );
|
||||
}
|
||||
|
||||
ApplyReturns(handle);
|
||||
|
@ -13,32 +13,21 @@ namespace Steamworks
|
||||
#if PLATFORM_WIN64
|
||||
public const int StructPlatformPackSize = 8;
|
||||
public const string LibraryName = "steam_api64";
|
||||
public const CallingConvention MemberConvention = CallingConvention.Cdecl;
|
||||
public const CallingConvention CC = CallingConvention.Cdecl;
|
||||
#elif PLATFORM_WIN32
|
||||
public const int StructPlatformPackSize = 8;
|
||||
public const string LibraryName = "steam_api";
|
||||
public const CallingConvention MemberConvention = CallingConvention.ThisCall;
|
||||
public const CallingConvention CC = CallingConvention.Cdecl;
|
||||
#elif PLATFORM_POSIX32
|
||||
public const int StructPlatformPackSize = 4;
|
||||
public const string LibraryName = "libsteam_api";
|
||||
public const CallingConvention MemberConvention = CallingConvention.Cdecl;
|
||||
public const CallingConvention CC = CallingConvention.Cdecl;
|
||||
#elif PLATFORM_POSIX64
|
||||
public const int StructPlatformPackSize = 4;
|
||||
public const string LibraryName = "libsteam_api";
|
||||
public const CallingConvention MemberConvention = CallingConvention.Cdecl;
|
||||
public const CallingConvention CC = CallingConvention.Cdecl;
|
||||
#endif
|
||||
|
||||
public const int StructPackSize = 4;
|
||||
|
||||
|
||||
|
||||
public static int MemoryOffset( int memLocation )
|
||||
{
|
||||
#if PLATFORM_64
|
||||
return memLocation;
|
||||
#else
|
||||
return memLocation / 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ namespace Steamworks
|
||||
return await GetRules(client);
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
catch (System.Exception)
|
||||
{
|
||||
//Console.Error.WriteLine( e.Message );
|
||||
return null;
|
||||
|
@ -11,103 +11,42 @@ namespace Steamworks
|
||||
{
|
||||
internal abstract class SteamInterface
|
||||
{
|
||||
public virtual IntPtr GetUserInterfacePointer() => IntPtr.Zero;
|
||||
public virtual IntPtr GetServerInterfacePointer() => IntPtr.Zero;
|
||||
public virtual IntPtr GetGlobalInterfacePointer() => IntPtr.Zero;
|
||||
|
||||
public IntPtr Self;
|
||||
public IntPtr VTable;
|
||||
|
||||
public virtual string InterfaceName => null;
|
||||
public bool IsValid => Self != IntPtr.Zero && VTable != IntPtr.Zero;
|
||||
public bool IsValid => Self != IntPtr.Zero;
|
||||
|
||||
public void Init()
|
||||
internal void SetupInterface( bool gameServer )
|
||||
{
|
||||
if ( SteamClient.IsValid )
|
||||
{
|
||||
InitClient();
|
||||
Self = GetGlobalInterfacePointer();
|
||||
|
||||
if ( Self != IntPtr.Zero )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( SteamServer.IsValid )
|
||||
{
|
||||
InitServer();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new System.Exception( "Trying to initialize Steam Interface but Steam not initialized" );
|
||||
if ( gameServer )
|
||||
Self = GetServerInterfacePointer();
|
||||
else
|
||||
Self = GetUserInterfacePointer();
|
||||
}
|
||||
|
||||
public void InitClient()
|
||||
{
|
||||
|
||||
//
|
||||
// There's an issue for us using FindOrCreateUserInterface on Rust.
|
||||
// We have a different appid for our staging branch, but we use Rust's
|
||||
// appid so we can still test with the live data/setup. The issue is
|
||||
// if we run the staging branch and get interfaces using FindOrCreate
|
||||
// then some callbacks don't work. I assume this is because these interfaces
|
||||
// have already been initialized using the old appid pipe, but since I
|
||||
// can't see inside Steam this is just a gut feeling. Either way using
|
||||
// CreateInterface doesn't seem to have caused any fires, so we'll just use that.
|
||||
//
|
||||
|
||||
//
|
||||
// var pipe = SteamAPI.GetHSteamPipe();
|
||||
//
|
||||
|
||||
Self = SteamInternal.CreateInterface( InterfaceName );
|
||||
|
||||
if ( Self == IntPtr.Zero )
|
||||
{
|
||||
var user = SteamAPI.GetHSteamUser();
|
||||
Self = SteamInternal.FindOrCreateUserInterface( user, InterfaceName );
|
||||
}
|
||||
|
||||
if ( Self == IntPtr.Zero )
|
||||
throw new System.Exception( $"Couldn't find interface {InterfaceName}" );
|
||||
|
||||
VTable = Marshal.ReadIntPtr( Self, 0 );
|
||||
if ( Self == IntPtr.Zero )
|
||||
throw new System.Exception( $"Invalid VTable for {InterfaceName}" );
|
||||
|
||||
InitInternals();
|
||||
SteamClient.WatchInterface( this );
|
||||
}
|
||||
|
||||
public void InitServer()
|
||||
{
|
||||
var user = SteamGameServer.GetHSteamUser();
|
||||
Self = SteamInternal.FindOrCreateGameServerInterface( user, InterfaceName );
|
||||
|
||||
if ( Self == IntPtr.Zero )
|
||||
throw new System.Exception( $"Couldn't find server interface {InterfaceName}" );
|
||||
|
||||
VTable = Marshal.ReadIntPtr( Self, 0 );
|
||||
if ( Self == IntPtr.Zero )
|
||||
throw new System.Exception( $"Invalid VTable for server {InterfaceName}" );
|
||||
|
||||
InitInternals();
|
||||
SteamServer.WatchInterface( this );
|
||||
}
|
||||
|
||||
public virtual void InitUserless()
|
||||
{
|
||||
Self = SteamInternal.FindOrCreateUserInterface( 0, InterfaceName );
|
||||
|
||||
if ( Self == IntPtr.Zero )
|
||||
throw new System.Exception( $"Couldn't find interface {InterfaceName}" );
|
||||
|
||||
VTable = Marshal.ReadIntPtr( Self, 0 );
|
||||
if ( Self == IntPtr.Zero )
|
||||
throw new System.Exception( $"Invalid VTable for {InterfaceName}" );
|
||||
|
||||
InitInternals();
|
||||
}
|
||||
|
||||
internal virtual void Shutdown()
|
||||
internal void ShutdownInterface()
|
||||
{
|
||||
Self = IntPtr.Zero;
|
||||
VTable = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SteamClass
|
||||
{
|
||||
internal abstract void InitializeInterface( bool server );
|
||||
internal virtual void DestroyInterface()
|
||||
{
|
||||
Interface.ShutdownInterface();
|
||||
}
|
||||
|
||||
public abstract void InitInternals();
|
||||
internal abstract SteamInterface Interface { get; }
|
||||
}
|
||||
|
||||
}
|
@ -3,12 +3,21 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public static partial class Utility
|
||||
{
|
||||
static internal T ToType<T>( this IntPtr ptr )
|
||||
{
|
||||
if ( ptr == IntPtr.Zero )
|
||||
return default;
|
||||
|
||||
return (T)Marshal.PtrToStructure( ptr, typeof( T ) );
|
||||
}
|
||||
|
||||
static internal uint Swap( uint x )
|
||||
{
|
||||
return ((x & 0x000000ff) << 24) +
|
||||
|
Binary file not shown.
Binary file not shown.
BIN
Facepunch.Steamworks/steam_api.dll
Normal file
BIN
Facepunch.Steamworks/steam_api.dll
Normal file
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user