diff --git a/Facepunch.Steamworks/Generated/Interfaces/ISteamNetworking.cs b/Facepunch.Steamworks/Generated/Interfaces/ISteamNetworking.cs
index 794851a..049c3cf 100644
--- a/Facepunch.Steamworks/Generated/Interfaces/ISteamNetworking.cs
+++ b/Facepunch.Steamworks/Generated/Interfaces/ISteamNetworking.cs
@@ -44,11 +44,11 @@ public override void InitInternals()
#region FunctionMeta
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
[return: MarshalAs( UnmanagedType.I1 )]
- private delegate bool FSendP2PPacket( IntPtr self, SteamId steamIDRemote, [In,Out] IntPtr[] pubData, uint cubData, P2PSend eP2PSendType, int nChannel );
+ private delegate bool FSendP2PPacket( IntPtr self, SteamId steamIDRemote, IntPtr pubData, uint cubData, P2PSend eP2PSendType, int nChannel );
private FSendP2PPacket _SendP2PPacket;
#endregion
- internal bool SendP2PPacket( SteamId steamIDRemote, [In,Out] IntPtr[] pubData, uint cubData, P2PSend eP2PSendType, int nChannel )
+ internal bool SendP2PPacket( SteamId steamIDRemote, IntPtr pubData, uint cubData, P2PSend eP2PSendType, int nChannel )
{
return _SendP2PPacket( Self, steamIDRemote, pubData, cubData, eP2PSendType, nChannel );
}
@@ -68,11 +68,11 @@ internal bool IsP2PPacketAvailable( ref uint pcubMsgSize, int nChannel )
#region FunctionMeta
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
[return: MarshalAs( UnmanagedType.I1 )]
- private delegate bool FReadP2PPacket( IntPtr self, [In,Out] IntPtr[] pubDest, uint cubDest, ref uint pcubMsgSize, ref SteamId psteamIDRemote, int nChannel );
+ private delegate bool FReadP2PPacket( IntPtr self, IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref SteamId psteamIDRemote, int nChannel );
private FReadP2PPacket _ReadP2PPacket;
#endregion
- internal bool ReadP2PPacket( [In,Out] IntPtr[] pubDest, uint cubDest, ref uint pcubMsgSize, ref SteamId psteamIDRemote, int nChannel )
+ internal bool ReadP2PPacket( IntPtr pubDest, uint cubDest, ref uint pcubMsgSize, ref SteamId psteamIDRemote, int nChannel )
{
return _ReadP2PPacket( Self, pubDest, cubDest, ref pcubMsgSize, ref psteamIDRemote, nChannel );
}
diff --git a/Facepunch.Steamworks/Generated/SteamEnums.cs b/Facepunch.Steamworks/Generated/SteamEnums.cs
index 69b336e..ddf03bf 100644
--- a/Facepunch.Steamworks/Generated/SteamEnums.cs
+++ b/Facepunch.Steamworks/Generated/SteamEnums.cs
@@ -946,7 +946,7 @@ internal enum P2PSessionError : int
//
// EP2PSend
//
- internal enum P2PSend : int
+ public enum P2PSend : int
{
Unreliable = 0,
UnreliableNoDelay = 1,
diff --git a/Facepunch.Steamworks/SteamClient.cs b/Facepunch.Steamworks/SteamClient.cs
index 550eb71..abed587 100644
--- a/Facepunch.Steamworks/SteamClient.cs
+++ b/Facepunch.Steamworks/SteamClient.cs
@@ -40,6 +40,7 @@ public static void Init( uint appid )
SteamScreenshots.InstallEvents();
SteamUserStats.InstallEvents();
SteamInventory.InstallEvents();
+ SteamNetworking.InstallEvents();
RunCallbacksAsync();
}
diff --git a/Facepunch.Steamworks/SteamNetworking.cs b/Facepunch.Steamworks/SteamNetworking.cs
new file mode 100644
index 0000000..a5db69a
--- /dev/null
+++ b/Facepunch.Steamworks/SteamNetworking.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Steamworks.Data;
+
+namespace Steamworks
+{
+ public static class SteamNetworking
+ {
+ static ISteamNetworking _internal;
+ internal static ISteamNetworking Internal
+ {
+ get
+ {
+ if ( _internal == null )
+ _internal = new ISteamNetworking();
+
+ return _internal;
+ }
+ }
+
+ internal static void InstallEvents()
+ {
+ P2PSessionRequest_t.Install( x => OnP2PSessionRequest?.Invoke( x.SteamIDRemote ) );
+ P2PSessionConnectFail_t.Install( x => OnP2PConnectionFailed?.Invoke( x.SteamIDRemote ) );
+ }
+
+ ///
+ /// This SteamId wants to send you a message. You should respond by calling AcceptP2PSessionWithUser
+ /// if you want to recieve their messages
+ ///
+ public static Action OnP2PSessionRequest;
+
+ ///
+ /// Called when packets can't get through to the specified user.
+ /// All queued packets unsent at this point will be dropped, further attempts
+ /// to send will retry making the connection (but will be dropped if we fail again).
+ ///
+ public static Action OnP2PConnectionFailed;
+
+ ///
+ /// This should be called in response to a OnP2PSessionRequest
+ ///
+ public static bool AcceptP2PSessionWithUser( SteamId user ) => Internal.AcceptP2PSessionWithUser( user );
+
+ ///
+ /// This should be called when you're done communicating with a user, as this will
+ /// free up all of the resources allocated for the connection under-the-hood.
+ /// If the remote user tries to send data to you again, a new OnP2PSessionRequest
+ /// callback will be posted
+ ///
+ public static bool CloseP2PSessionWithUser( SteamId user ) => Internal.CloseP2PSessionWithUser( user );
+
+ ///
+ /// Checks if a P2P packet is available to read, and gets the size of the message if there is one.
+ ///
+ public static bool IsP2PPacketAvailable( int channel = 0 )
+ {
+ uint _ = 0;
+ return Internal.IsP2PPacketAvailable( ref _, channel );
+ }
+
+ ///
+ /// Reads in a packet that has been sent from another user via SendP2PPacket..
+ ///
+ public unsafe static P2Packet? ReadP2PPacket( int channel = 0 )
+ {
+ uint size = 0;
+
+ if ( !Internal.IsP2PPacketAvailable( ref size, channel ) )
+ return null;
+
+ var buffer = Helpers.TakeBuffer( (int) size );
+
+ fixed ( byte* p = buffer )
+ {
+ SteamId steamid = 1;
+ if ( !Internal.ReadP2PPacket( (IntPtr)p, (uint) buffer.Length, ref size, ref steamid, channel ) || size == 0 )
+ return null;
+
+ var data = new byte[size];
+ Array.Copy( buffer, 0, data, 0, size );
+
+ return new P2Packet
+ {
+ SteamId = steamid,
+ Data = data
+ };
+ }
+ }
+
+ ///
+ /// Sends a P2P packet to the specified user.
+ /// This is a session-less API which automatically establishes NAT-traversing or Steam relay server connections.
+ /// NOTE: The first packet send may be delayed as the NAT-traversal code runs.
+ ///
+ public static unsafe bool SendP2PPacket( SteamId steamid, byte[] data, int length = -1, int nChannel = 0, P2PSend sendType = P2PSend.Reliable )
+ {
+ if ( length <= 0 )
+ length = data.Length;
+
+ fixed ( byte* p = data )
+ {
+ return Internal.SendP2PPacket( steamid, (IntPtr)p, (uint)length, (P2PSend)sendType, nChannel );
+ }
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/Facepunch.Steamworks/Structs/P2Packet.cs b/Facepunch.Steamworks/Structs/P2Packet.cs
new file mode 100644
index 0000000..ca85773
--- /dev/null
+++ b/Facepunch.Steamworks/Structs/P2Packet.cs
@@ -0,0 +1,8 @@
+namespace Steamworks.Data
+{
+ public struct P2Packet
+ {
+ public SteamId SteamId;
+ public byte[] Data;
+ }
+}
\ No newline at end of file
diff --git a/Generator/Cleanup.cs b/Generator/Cleanup.cs
index e4cf013..915bce5 100644
--- a/Generator/Cleanup.cs
+++ b/Generator/Cleanup.cs
@@ -58,6 +58,7 @@ internal static string Expose( string name )
if ( name == "UgcType" ) return "public";
if ( name == "InventoryItemId" ) return "public";
if ( name == "InventoryDefId" ) return "public";
+ if ( name == "P2PSend" ) return "public";
return "internal";
}
diff --git a/Generator/CodeWriter/Types/BaseType.cs b/Generator/CodeWriter/Types/BaseType.cs
index 6076e8c..8d3ebac 100644
--- a/Generator/CodeWriter/Types/BaseType.cs
+++ b/Generator/CodeWriter/Types/BaseType.cs
@@ -60,6 +60,9 @@ public virtual bool IsVector
{
get
{
+ if ( Func == "ReadP2PPacket" ) return false;
+ if ( Func == "SendP2PPacket" ) return false;
+
if ( VarName == "pOut" ) return false;
if ( VarName == "pOutBuffer" ) return false;
if ( VarName == "pubRGB" ) return false;