mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-04-16 14:22:27 +03:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
19e64429c4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -211,7 +211,7 @@ namespace Steamworks
|
|||||||
//
|
//
|
||||||
// EUserHasLicenseForAppResult
|
// EUserHasLicenseForAppResult
|
||||||
//
|
//
|
||||||
internal enum UserHasLicenseForAppResult : int
|
public enum UserHasLicenseForAppResult : int
|
||||||
{
|
{
|
||||||
HasLicense = 0,
|
HasLicense = 0,
|
||||||
DoesNotHaveLicense = 1,
|
DoesNotHaveLicense = 1,
|
||||||
@ -585,7 +585,7 @@ namespace Steamworks
|
|||||||
//
|
//
|
||||||
// EFriendFlags
|
// EFriendFlags
|
||||||
//
|
//
|
||||||
internal enum FriendFlags : int
|
public enum FriendFlags : int
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Blocked = 1,
|
Blocked = 1,
|
||||||
|
@ -112,20 +112,22 @@ namespace Steamworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Friend> GetFriendsWithFlag(FriendFlags flag)
|
||||||
|
{
|
||||||
|
for ( int i=0; i<Internal.GetFriendCount( (int)flag); i++ )
|
||||||
|
{
|
||||||
|
yield return new Friend( Internal.GetFriendByIndex( i, (int)flag ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<Friend> GetFriends()
|
public static IEnumerable<Friend> GetFriends()
|
||||||
{
|
{
|
||||||
for ( int i=0; i<Internal.GetFriendCount( (int) FriendFlags.Immediate ); i++ )
|
return GetFriendsWithFlag(FriendFlags.Immediate);
|
||||||
{
|
|
||||||
yield return new Friend( Internal.GetFriendByIndex( i, (int)FriendFlags.Immediate ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<Friend> GetBlocked()
|
public static IEnumerable<Friend> GetBlocked()
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < Internal.GetFriendCount( (int)FriendFlags.Blocked ); i++ )
|
return GetFriendsWithFlag(FriendFlags.Blocked);
|
||||||
{
|
|
||||||
yield return new Friend( Internal.GetFriendByIndex( i, (int)FriendFlags.Blocked) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<Friend> GetPlayedWith()
|
public static IEnumerable<Friend> GetPlayedWith()
|
||||||
|
@ -107,6 +107,24 @@ namespace Steamworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads in a packet that has been sent from another user via SendP2PPacket..
|
||||||
|
/// </summary>
|
||||||
|
public unsafe static bool ReadP2PPacket( byte[] buffer, ref uint size, ref SteamId steamid, int channel = 0 )
|
||||||
|
{
|
||||||
|
fixed (byte* p = buffer) {
|
||||||
|
return Internal.ReadP2PPacket( (IntPtr)p, (uint)buffer.Length, ref size, ref steamid, channel );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads in a packet that has been sent from another user via SendP2PPacket..
|
||||||
|
/// </summary>
|
||||||
|
public unsafe static bool ReadP2PPacket( byte* buffer, uint cbuf, ref uint size, ref SteamId steamid, int channel = 0 )
|
||||||
|
{
|
||||||
|
return Internal.ReadP2PPacket( (IntPtr)buffer, cbuf, ref size, ref steamid, channel );
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a P2P packet to the specified user.
|
/// Sends a P2P packet to the specified user.
|
||||||
/// This is a session-less API which automatically establishes NAT-traversing or Steam relay server connections.
|
/// This is a session-less API which automatically establishes NAT-traversing or Steam relay server connections.
|
||||||
@ -123,6 +141,15 @@ namespace Steamworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public static unsafe bool SendP2PPacket( SteamId steamid, byte* data, uint length, int nChannel = 1, P2PSend sendType = P2PSend.Reliable )
|
||||||
|
{
|
||||||
|
return Internal.SendP2PPacket( steamid, (IntPtr)data, (uint)length, (P2PSend)sendType, nChannel );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -465,5 +465,13 @@ namespace Steamworks
|
|||||||
{
|
{
|
||||||
Internal.HandleIncomingPacket( ptr, size, address, port );
|
Internal.HandleIncomingPacket( ptr, size, address, port );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does the user own this app (which could be DLC)
|
||||||
|
/// </summary>
|
||||||
|
public static UserHasLicenseForAppResult UserHasLicenseForApp( SteamId steamid, AppId appid )
|
||||||
|
{
|
||||||
|
return Internal.UserHasLicenseForApp( steamid, appid );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Steamworks.Data;
|
using Steamworks.Data;
|
||||||
|
|
||||||
@ -254,6 +255,42 @@ namespace Steamworks.Ugc
|
|||||||
return result?.Result == Result.OK;
|
return result?.Result == Result.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows the user to subscribe to this item and wait for it to be downloaded
|
||||||
|
/// If CancellationToken is default then there is 60 seconds timeout
|
||||||
|
/// Progress will be set to 0-1
|
||||||
|
/// </summary>
|
||||||
|
public async Task<bool> SubscribeDownloadAsync( Action<float> progress = null, CancellationToken ct = default, int milisecondsUpdateDelay = 60 )
|
||||||
|
{
|
||||||
|
if ( ct == default )
|
||||||
|
ct = new CancellationTokenSource( TimeSpan.FromSeconds( 60 ) ).Token;
|
||||||
|
|
||||||
|
progress?.Invoke( 0 );
|
||||||
|
|
||||||
|
var subResult = await SteamUGC.Internal.SubscribeItem( _id );
|
||||||
|
if ( subResult?.Result != Result.OK )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var downloading = Download( true );
|
||||||
|
if ( !downloading )
|
||||||
|
return State.HasFlag( ItemState.Installed );
|
||||||
|
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
if ( ct.IsCancellationRequested )
|
||||||
|
break;
|
||||||
|
|
||||||
|
progress?.Invoke( DownloadAmount );
|
||||||
|
|
||||||
|
if ( !IsDownloading && State.HasFlag( ItemState.Installed ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
await Task.Delay( milisecondsUpdateDelay );
|
||||||
|
}
|
||||||
|
|
||||||
|
return State.HasFlag( ItemState.Installed );
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows the user to unsubscribe from this item
|
/// Allows the user to unsubscribe from this item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,12 +15,39 @@ namespace Steamworks
|
|||||||
// private static readonly byte A2S_PLAYER = 0x55;
|
// private static readonly byte A2S_PLAYER = 0x55;
|
||||||
private static readonly byte A2S_RULES = 0x56;
|
private static readonly byte A2S_RULES = 0x56;
|
||||||
|
|
||||||
internal static async Task<Dictionary<string, string>> GetRules( ServerInfo server )
|
private static readonly Dictionary<IPEndPoint, Task<Dictionary<string, string>>> PendingQueries =
|
||||||
{
|
new Dictionary<IPEndPoint, Task<Dictionary<string, string>>>();
|
||||||
try
|
|
||||||
|
internal static Task<Dictionary<string, string>> GetRules( ServerInfo server )
|
||||||
{
|
{
|
||||||
var endpoint = new IPEndPoint(server.Address, server.QueryPort);
|
var endpoint = new IPEndPoint(server.Address, server.QueryPort);
|
||||||
|
|
||||||
|
lock (PendingQueries)
|
||||||
|
{
|
||||||
|
if (PendingQueries.TryGetValue(endpoint, out var pending))
|
||||||
|
return pending;
|
||||||
|
|
||||||
|
var task = GetRulesImpl(endpoint, server)
|
||||||
|
.ContinueWith(t =>
|
||||||
|
{
|
||||||
|
lock (PendingQueries)
|
||||||
|
{
|
||||||
|
PendingQueries.Remove(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
})
|
||||||
|
.Unwrap();
|
||||||
|
|
||||||
|
PendingQueries.Add(endpoint, task);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<Dictionary<string, string>> GetRulesImpl( IPEndPoint endpoint, ServerInfo server )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
using (var client = new UdpClient())
|
using (var client = new UdpClient())
|
||||||
{
|
{
|
||||||
client.Client.SendTimeout = 3000;
|
client.Client.SendTimeout = 3000;
|
||||||
@ -32,7 +59,7 @@ namespace Steamworks
|
|||||||
}
|
}
|
||||||
catch (System.Exception e)
|
catch (System.Exception e)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine( e.Message );
|
//Console.Error.WriteLine( e.Message );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,14 +81,14 @@ namespace Steamworks
|
|||||||
var numRules = br.ReadUInt16();
|
var numRules = br.ReadUInt16();
|
||||||
for ( int index = 0; index < numRules; index++ )
|
for ( int index = 0; index < numRules; index++ )
|
||||||
{
|
{
|
||||||
rules.Add( br.ReadNullTerminatedUTF8String( readBuffer ), br.ReadNullTerminatedUTF8String( readBuffer ) );
|
rules.Add( br.ReadNullTerminatedUTF8String(), br.ReadNullTerminatedUTF8String() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] readBuffer = new byte[1024 * 8];
|
|
||||||
|
|
||||||
static async Task<byte[]> Receive( UdpClient client )
|
static async Task<byte[]> Receive( UdpClient client )
|
||||||
{
|
{
|
||||||
@ -120,10 +147,10 @@ namespace Steamworks
|
|||||||
return challengeData;
|
return challengeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] sendBuffer = new byte[1024];
|
|
||||||
|
|
||||||
static async Task Send( UdpClient client, byte[] message )
|
static async Task Send( UdpClient client, byte[] message )
|
||||||
{
|
{
|
||||||
|
var sendBuffer = new byte[message.Length + 4];
|
||||||
|
|
||||||
sendBuffer[0] = 0xFF;
|
sendBuffer[0] = 0xFF;
|
||||||
sendBuffer[1] = 0xFF;
|
sendBuffer[1] = 0xFF;
|
||||||
sendBuffer[2] = 0xFF;
|
sendBuffer[2] = 0xFF;
|
||||||
|
@ -80,20 +80,22 @@ namespace Steamworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ReadNullTerminatedUTF8String( this BinaryReader br, byte[] buffer = null )
|
static byte[] readBuffer = new byte[1024 * 8];
|
||||||
{
|
|
||||||
if ( buffer == null )
|
|
||||||
buffer = new byte[1024];
|
|
||||||
|
|
||||||
|
public static string ReadNullTerminatedUTF8String( this BinaryReader br )
|
||||||
|
{
|
||||||
|
lock ( readBuffer )
|
||||||
|
{
|
||||||
byte chr;
|
byte chr;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( (chr = br.ReadByte()) != 0 && i < buffer.Length )
|
while ( (chr = br.ReadByte()) != 0 && i < readBuffer.Length )
|
||||||
{
|
{
|
||||||
buffer[i] = chr;
|
readBuffer[i] = chr;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Encoding.UTF8.GetString( buffer, 0, i );
|
return Encoding.UTF8.GetString( readBuffer, 0, i );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ public static class Cleanup
|
|||||||
internal static string Expose( string name )
|
internal static string Expose( string name )
|
||||||
{
|
{
|
||||||
if ( name == "FriendState" ) return "public";
|
if ( name == "FriendState" ) return "public";
|
||||||
|
if (name == "FriendFlags") return "public";
|
||||||
if ( name == "MusicStatus" ) return "public";
|
if ( name == "MusicStatus" ) return "public";
|
||||||
if ( name == "ParentalFeature" ) return "public";
|
if ( name == "ParentalFeature" ) return "public";
|
||||||
if ( name == "AuthResponse" ) return "public";
|
if ( name == "AuthResponse" ) return "public";
|
||||||
@ -86,6 +87,7 @@ public static class Cleanup
|
|||||||
if ( name == "P2PSessionError" ) return "public";
|
if ( name == "P2PSessionError" ) return "public";
|
||||||
if ( name == "InputType" ) return "public";
|
if ( name == "InputType" ) return "public";
|
||||||
if ( name == "InputSourceMode" ) return "public";
|
if ( name == "InputSourceMode" ) return "public";
|
||||||
|
if ( name == "UserHasLicenseForAppResult" ) return "public";
|
||||||
|
|
||||||
return "internal";
|
return "internal";
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user