(965c31410a) Unstable v0.10.4.0

This commit is contained in:
Juan Pablo Arce
2020-07-21 08:57:50 -03:00
parent 4f8bd39789
commit 33d3a41104
546 changed files with 45952 additions and 25762 deletions
@@ -75,12 +75,12 @@ namespace Steamworks.Data
var ident = Identifier;
bool gotCallback = false;
Action<string, int> f = ( x, icon ) =>
void f( string x, int icon )
{
if ( x != ident ) return;
i = icon;
gotCallback = true;
};
}
try
{
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Steamworks
{
public struct Clan
{
public SteamId Id;
public Clan(SteamId id)
{
Id = id;
}
public string Name => SteamFriends.Internal.GetClanName(Id);
public string Tag => SteamFriends.Internal.GetClanTag(Id);
public int ChatMemberCount => SteamFriends.Internal.GetClanChatMemberCount(Id);
public Friend Owner => new Friend(SteamFriends.Internal.GetClanOwner(Id));
public bool Public => SteamFriends.Internal.IsClanPublic(Id);
/// <summary>
/// Is the clan an official game group?
/// </summary>
public bool Official => SteamFriends.Internal.IsClanOfficialGameGroup(Id);
/// <summary>
/// Asynchronously fetches the officer list for a given clan
/// </summary>
/// <returns>Whether the request was successful or not</returns>
public async Task<bool> RequestOfficerList()
{
var req = await SteamFriends.Internal.RequestClanOfficerList(Id);
return req.HasValue && req.Value.Success != 0x0;
}
public IEnumerable<Friend> GetOfficers()
{
for (int i = 0; i < SteamFriends.Internal.GetClanOfficerCount(Id); i++)
{
yield return new Friend(SteamFriends.Internal.GetClanOfficerByIndex(Id, i));
}
}
}
}
@@ -1,117 +0,0 @@
using System;
using System.Collections.Generic;
namespace Steamworks.Data
{
public struct Connection
{
internal uint Id;
public override string ToString() => Id.ToString();
/// <summary>
/// Accept an incoming connection that has been received on a listen socket.
/// </summary>
public Result Accept()
{
return SteamNetworkingSockets.Internal.AcceptConnection( this );
}
/// <summary>
/// Disconnects from the remote host and invalidates the connection handle. Any unread data on the connection is discarded..
/// reasonCode is defined and used by you.
/// </summary>
public bool Close( bool linger = false, int reasonCode = 0, string debugString = "Closing Connection" )
{
return SteamNetworkingSockets.Internal.CloseConnection( this, reasonCode, debugString, linger );
}
/// <summary>
/// Get/Set connection user data
/// </summary>
public long UserData
{
get => SteamNetworkingSockets.Internal.GetConnectionUserData( this );
set => SteamNetworkingSockets.Internal.SetConnectionUserData( this, value );
}
/// <summary>
/// A name for the connection, used mostly for debugging
/// </summary>
public string ConnectionName
{
get
{
if ( !SteamNetworkingSockets.Internal.GetConnectionName( this, out var strVal ) )
return "ERROR";
return strVal;
}
set => SteamNetworkingSockets.Internal.SetConnectionName( this, value );
}
public Result SendMessage( IntPtr ptr, int size, SendType sendType = SendType.Reliable )
{
return SteamNetworkingSockets.Internal.SendMessageToConnection( this, ptr, (uint) size, (int)sendType );
}
public unsafe Result SendMessage( byte[] data, SendType sendType = SendType.Reliable )
{
fixed ( byte* ptr = data )
{
return SendMessage( (IntPtr)ptr, data.Length, sendType );
}
}
public unsafe Result SendMessage( byte[] data, int offset, int length, SendType sendType = SendType.Reliable )
{
fixed ( byte* ptr = data )
{
return SendMessage( (IntPtr)ptr + offset, length, sendType );
}
}
public unsafe Result SendMessage( string str, SendType sendType = SendType.Reliable )
{
var bytes = System.Text.Encoding.UTF8.GetBytes( str );
return SendMessage( bytes, sendType );
}
/// <summary>
/// Flush any messages waiting on the Nagle timer and send them at the next transmission opportunity (often that means right now).
/// </summary>
public Result Flush() => SteamNetworkingSockets.Internal.FlushMessagesOnConnection( this );
public string DetailedStatus()
{
if ( SteamNetworkingSockets.Internal.GetDetailedConnectionStatus( this, out var strVal ) != 0 )
return null;
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();
}
}
}*/
}
}
@@ -1,25 +0,0 @@
using System.Runtime.InteropServices;
namespace Steamworks.Data
{
[StructLayout( LayoutKind.Sequential, Size = 696 )]
public struct ConnectionInfo
{
internal NetIdentity identity;
internal long userData;
internal Socket listenSocket;
internal NetAddress address;
internal ushort pad;
internal SteamNetworkingPOPID popRemote;
internal SteamNetworkingPOPID popRelay;
internal ConnectionState state;
internal int endReason;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 128 )]
internal string endDebug;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst = 128 )]
internal string connectionDescription;
public ConnectionState State => state;
public SteamId SteamId => identity.steamID;
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Steamworks.Data
{
/// <summary>
/// Sent for games with enabled anti indulgence / duration control, for enabled users.
/// Lets the game know whether persistent rewards or XP should be granted at normal rate, half rate, or zero rate.
/// </summary>
public struct DurationControl
{
internal DurationControl_t _inner;
/// <summary>
/// appid generating playtime
/// </summary>
public AppId Appid => _inner.Appid;
/// <summary>
/// is duration control applicable to user + game combination
/// </summary>
public bool Applicable => _inner.Applicable;
/// <summary>
/// playtime since most recent 5 hour gap in playtime, only counting up to regulatory limit of playtime, in seconds
/// </summary>
internal TimeSpan PlaytimeInLastFiveHours => TimeSpan.FromSeconds( _inner.CsecsLast5h );
/// <summary>
/// playtime on current calendar day
/// </summary>
internal TimeSpan PlaytimeToday => TimeSpan.FromSeconds( _inner.CsecsLast5h );
/// <summary>
/// recommended progress
/// </summary>
internal DurationControlProgress Progress => _inner.Progress;
}
}
@@ -51,7 +51,7 @@ namespace Steamworks
/// Sometimes we don't know the user's name. This will wait until we have
/// downloaded the information on this user.
/// </summary>
public async Task RequestInfoAsync( int timeout = 5000 )
public async Task RequestInfoAsync()
{
await SteamFriends.CacheUserInformationAsync( Id, true );
}
@@ -99,7 +99,7 @@ namespace Steamworks
{
get
{
FriendGameInfo_t gameInfo = default( FriendGameInfo_t );
FriendGameInfo_t gameInfo = default;
if ( !SteamFriends.Internal.GetFriendGamePlayed( Id, ref gameInfo ) )
return null;
@@ -184,5 +184,80 @@ namespace Steamworks
return SteamFriends.Internal.ReplyToFriendMessage( Id, message );
}
/// <summary>
/// Tries to get download the latest user stats
/// </summary>
/// <returns>True if successful, False if failure</returns>
public async Task<bool> RequestUserStatsAsync()
{
var result = await SteamUserStats.Internal.RequestUserStats( Id );
return result.HasValue && result.Value.Result == Result.OK;
}
/// <summary>
/// Gets a user stat. Must call RequestUserStats first.
/// </summary>
/// <param name="statName">The name of the stat you want to get</param>
/// <param name="defult">Will return this value if not available</param>
/// <returns>The value, or defult if not available</returns>
public float GetStatFloat( string statName, float defult = 0 )
{
var val = defult;
if ( !SteamUserStats.Internal.GetUserStat( Id, statName, ref val ) )
return defult;
return val;
}
/// <summary>
/// Gets a user stat. Must call RequestUserStats first.
/// </summary>
/// <param name="statName">The name of the stat you want to get</param>
/// <param name="defult">Will return this value if not available</param>
/// <returns>The value, or defult if not available</returns>
public int GetStatInt( string statName, int defult = 0 )
{
var val = defult;
if ( !SteamUserStats.Internal.GetUserStat( Id, statName, ref val ) )
return defult;
return val;
}
/// <summary>
/// Gets a user achievement state. Must call RequestUserStats first.
/// </summary>
/// <param name="statName">The name of the achievement you want to get</param>
/// <param name="defult">Will return this value if not available</param>
/// <returns>The value, or defult if not available</returns>
public bool GetAchievement( string statName, bool defult = false )
{
var val = defult;
if ( !SteamUserStats.Internal.GetUserAchievement( Id, statName, ref val ) )
return defult;
return val;
}
/// <summary>
/// Gets a the time this achievement was unlocked.
/// </summary>
/// <param name="statName">The name of the achievement you want to get</param>
/// <returns>The time unlocked. If it wasn't unlocked, or you haven't downloaded the stats yet - will return DateTime.MinValue</returns>
public DateTime GetAchievementUnlockTime( string statName )
{
bool val = false;
uint time = 0;
if ( !SteamUserStats.Internal.GetUserAchievementAndUnlockTime( Id, statName, ref val, ref time ) || !val )
return DateTime.MinValue;
return Epoch.ToDateTime( time );
}
}
}
@@ -98,11 +98,14 @@ namespace Steamworks
if ( _properties!= null && _properties.TryGetValue( name, out string val ) )
return val;
uint _ = (uint)Helpers.MaxStringSize;
uint _ = (uint)Helpers.MemoryBufferSize;
if ( !SteamInventory.Internal.GetItemDefinitionProperty( Id, name, out var vl, ref _ ) )
return null;
if (name == null) //return keys string
return vl;
if ( _properties == null )
_properties = new Dictionary<string, string>();
@@ -132,7 +135,7 @@ namespace Steamworks
string val = GetProperty( name );
if ( string.IsNullOrEmpty( val ) )
return default( T );
return default;
try
{
@@ -140,7 +143,7 @@ namespace Steamworks
}
catch ( System.Exception )
{
return default( T );
return default;
}
}
@@ -235,4 +238,4 @@ namespace Steamworks
}
}
}
}
@@ -53,7 +53,7 @@ namespace Steamworks
/// </summary>
public async Task<InventoryResult?> ConsumeAsync( int amount = 1 )
{
var sresult = default( SteamInventoryResult_t );
var sresult = Defines.k_SteamInventoryResultInvalid;
if ( !SteamInventory.Internal.ConsumeItem( ref sresult, Id, (uint)amount ) )
return null;
@@ -65,7 +65,7 @@ namespace Steamworks
/// </summary>
public async Task<InventoryResult?> SplitStackAsync( int quantity = 1 )
{
var sresult = default( SteamInventoryResult_t );
var sresult = Defines.k_SteamInventoryResultInvalid;
if ( !SteamInventory.Internal.TransferItemQuantity( ref sresult, Id, (uint)quantity, ulong.MaxValue ) )
return null;
@@ -77,7 +77,7 @@ namespace Steamworks
/// </summary>
public async Task<InventoryResult?> AddAsync( InventoryItem add, int quantity = 1 )
{
var sresult = default( SteamInventoryResult_t );
var sresult = Defines.k_SteamInventoryResultInvalid;
if ( !SteamInventory.Internal.TransferItemQuantity( ref sresult, add.Id, (uint)quantity, Id ) )
return null;
@@ -100,7 +100,7 @@ namespace Steamworks
internal static Dictionary<string, string> GetProperties( SteamInventoryResult_t result, int index )
{
var strlen = (uint) Helpers.MaxStringSize;
var strlen = (uint) Helpers.MemoryBufferSize;
if ( !SteamInventory.Internal.GetResultItemProperty( result, (uint)index, null, out var propNames, ref strlen ) )
return null;
@@ -109,7 +109,7 @@ namespace Steamworks
foreach ( var propertyName in propNames.Split( ',' ) )
{
strlen = (uint)Helpers.MaxStringSize;
strlen = (uint)Helpers.MemoryBufferSize;
if ( SteamInventory.Internal.GetResultItemProperty( result, (uint)index, propertyName, out var strVal, ref strlen ) )
{
@@ -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;
}
}
@@ -17,9 +17,10 @@ namespace Steamworks.Data
public string Name => SteamUserStats.Internal.GetLeaderboardName( Id );
public LeaderboardSort Sort => SteamUserStats.Internal.GetLeaderboardSortMethod( Id );
public LeaderboardDisplay Display => SteamUserStats.Internal.GetLeaderboardDisplayType( Id );
public int EntryCount => SteamUserStats.Internal.GetLeaderboardEntryCount(Id);
static int[] detailsBuffer = new int[64];
static int[] noDetails = new int[0];
static int[] noDetails = Array.Empty<int>();
/// <summary>
/// Submit your score and replace your old score even if it was better
@@ -58,6 +59,21 @@ namespace Steamworks.Data
return r.Value.Result;
}
/// <summary>
/// Fetches leaderboard entries for an arbitrary set of users on a specified leaderboard.
/// </summary>
public async Task<LeaderboardEntry[]> GetScoresForUsersAsync( SteamId[] users )
{
if ( users == null || users.Length == 0 )
return null;
var r = await SteamUserStats.Internal.DownloadLeaderboardEntriesForUsers( Id, users, users.Length );
if ( !r.HasValue )
return null;
return await LeaderboardResultToEntries( r.Value );
}
/// <summary>
/// Used to query for a sequential range of leaderboard entries by leaderboard Sort.
/// </summary>
@@ -65,7 +81,7 @@ namespace Steamworks.Data
{
if ( offset <= 0 ) throw new System.ArgumentException( "Should be 1+", nameof( offset ) );
var r = await SteamUserStats.Internal.DownloadLeaderboardEntries( Id, LeaderboardDataRequest.Global, offset, offset + count );
var r = await SteamUserStats.Internal.DownloadLeaderboardEntries( Id, LeaderboardDataRequest.Global, offset, offset + count - 1 );
if ( !r.HasValue )
return null;
@@ -121,7 +137,7 @@ namespace Steamworks.Data
return output;
}
internal async Task WaitForUserNames( LeaderboardEntry[] entries)
internal static async Task WaitForUserNames( LeaderboardEntry[] entries)
{
bool gotAll = false;
while ( !gotAll )
@@ -10,7 +10,7 @@ namespace Steamworks.Data
public SteamId Id { get; internal set; }
internal Lobby( SteamId id )
public Lobby( SteamId id )
{
Id = id;
}
@@ -123,7 +123,7 @@ namespace Steamworks.Data
/// <summary>
/// Sets per-user metadata (for the local user implicitly)
/// </summary>
public void SetMemberData( Friend member, string key, string value )
public void SetMemberData( string key, string value )
{
SteamMatchmaking.Internal.SetLobbyMemberData( Id, key, value );
}
@@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
namespace Steamworks.Data
{
[StructLayout( LayoutKind.Sequential, Pack = Platform.StructPackSize )]
internal struct MatchMakingKeyValuePair
internal partial struct MatchMakingKeyValuePair
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
internal string Key;
@@ -1,107 +0,0 @@
using System.Net;
using System.Runtime.InteropServices;
namespace Steamworks.Data
{
[StructLayout( LayoutKind.Explicit, Size = 18, Pack = 1 )]
public struct NetAddress
{
[FieldOffset( 0 )]
internal IPV4 ip;
[FieldOffset( 16 )]
internal ushort port;
internal struct IPV4
{
internal ulong m_8zeros;
internal ushort m_0000;
internal ushort m_ffff;
internal byte ip0;
internal byte ip1;
internal byte ip2;
internal byte ip3;
}
/// <summary>
/// Any IP, specific port
/// </summary>
public static NetAddress AnyIp( ushort port )
{
return new NetAddress
{
ip = new IPV4
{
m_8zeros = 0,
m_0000 = 0,
m_ffff = 0,
ip0 = 0,
ip1 = 0,
ip2 = 0,
ip3 = 0,
},
port = port
};
}
/// <summary>
/// Localhost IP, specific port
/// </summary>
public static NetAddress LocalHost( ushort port )
{
return new NetAddress
{
ip = new IPV4
{
m_8zeros = 0,
m_0000 = 0,
m_ffff = 0,
ip0 = 0,
ip1 = 0,
ip2 = 0,
ip3 = 1,
},
port = port
};
}
/// <summary>
/// Specific IP, specific port
/// </summary>
public static NetAddress From( string addrStr, ushort port )
{
return From( IPAddress.Parse( addrStr ), port );
}
/// <summary>
/// Specific IP, specific port
/// </summary>
public static NetAddress From( IPAddress address, ushort port )
{
var addr = address.GetAddressBytes();
if ( addr.Length == 4 )
{
return new NetAddress
{
ip = new IPV4
{
m_8zeros = 0,
m_0000 = 0,
m_ffff = 0xffff,
ip0 = addr[0],
ip1 = addr[1],
ip2 = addr[2],
ip3 = addr[3],
},
port = port
};
}
throw new System.NotImplementedException( "Oops - no IPV6 support yet?" );
}
}
}
@@ -1,38 +0,0 @@
using System.Runtime.InteropServices;
namespace Steamworks.Data
{
[StructLayout( LayoutKind.Explicit, Size = 136, Pack = 1 )]
public struct NetIdentity
{
[FieldOffset( 0 )]
internal IdentityType type;
[FieldOffset( 4 )]
internal int m_cbSize;
[FieldOffset( 8 )]
internal SteamId steamID;
public static implicit operator NetIdentity( SteamId value )
{
return new NetIdentity { steamID = value, type = IdentityType.SteamID, m_cbSize = 8 };
}
public static implicit operator SteamId( NetIdentity value )
{
return value.steamID;
}
public override string ToString() => $"{type};{m_cbSize};{steamID}";
internal enum IdentityType
{
Invalid = 0,
IPAddress = 1,
GenericString = 2,
GenericBytes = 3,
SteamID = 16
}
}
}
@@ -1,33 +0,0 @@
using Steamworks.Data;
using System;
using System.Runtime.InteropServices;
namespace Steamworks.Data
{
[StructLayout( LayoutKind.Sequential )]
internal struct NetMsg
{
internal IntPtr DataPtr;
internal int DataSize;
internal Connection Connection;
internal NetIdentity Identity;
internal long ConnectionUserData;
internal long RecvTime;
internal long MessageNumber;
internal IntPtr FreeDataPtr;
internal IntPtr ReleasePtr;
internal int Channel;
internal delegate void ReleaseDelegate( IntPtr msg );
public void Release( IntPtr data )
{
//
// I think this function might be a static global, so we could probably
// cache this release call.
//
var d = Marshal.GetDelegateForFunctionPointer<ReleaseDelegate>( ReleasePtr );
d( data );
}
}
}
@@ -0,0 +1,31 @@
using Steamworks.Data;
using System;
using System.Collections.Generic;
using System.Text;
namespace Steamworks
{
public struct P2PSessionState
{
public byte ConnectionActive;
public byte Connecting;
public P2PSessionError P2PSessionError;
public byte UsingRelay;
public int BytesQueuedForSend;
public int PacketsQueuedForSend;
public uint RemoteIP;
public ushort RemotePort;
internal P2PSessionState(P2PSessionState_t s)
{
this.ConnectionActive = s.ConnectionActive;
this.Connecting = s.Connecting;
this.P2PSessionError = (P2PSessionError)s.P2PSessionError;
this.UsingRelay = s.UsingRelay;
this.BytesQueuedForSend = s.BytesQueuedForSend;
this.PacketsQueuedForSend = s.PacketsQueuedForSend;
this.RemoteIP = s.RemoteIP;
this.RemotePort = s.RemotePort;
}
}
}
@@ -18,7 +18,7 @@ namespace Steamworks
{
var owner = default( SteamId );
var location = default( SteamPartyBeaconLocation_t );
Internal.GetBeaconDetails( Id, ref owner, ref location, out var strVal );
Internal.GetBeaconDetails( Id, ref owner, ref location, out _ );
return owner;
}
}
@@ -32,7 +32,7 @@ namespace Steamworks
{
var owner = default( SteamId );
var location = default( SteamPartyBeaconLocation_t );
Internal.GetBeaconDetails( Id, ref owner, ref location, out var strVal );
_ = Internal.GetBeaconDetails( Id, ref owner, ref location, out var strVal );
return strVal;
}
}
@@ -1,67 +0,0 @@
using System.Runtime.InteropServices;
namespace Steamworks.Data
{
/// <summary>
///
/// Object that describes a "location" on the Internet with sufficient
/// detail that we can reasonably estimate an upper bound on the ping between
/// the two hosts, even if a direct route between the hosts is not possible,
/// and the connection must be routed through the Steam Datagram Relay network.
/// This does not contain any information that identifies the host. Indeed,
/// if two hosts are in the same building or otherwise have nearly identical
/// networking characteristics, then it's valid to use the same location
/// object for both of them.
///
/// NOTE: This object should only be used in the same process! Do not serialize it,
/// send it over the wire, or persist it in a file or database! If you need
/// to do that, convert it to a string representation using the methods in
/// ISteamNetworkingUtils().
///
/// </summary>
[StructLayout( LayoutKind.Explicit, Size = 512 )]
public struct PingLocation
{
public static PingLocation? TryParseFromString( string str )
{
var result = default( PingLocation );
if ( !SteamNetworkingUtils.Internal.ParsePingLocationString( str, ref result ) )
return null;
return result;
}
public override string ToString()
{
SteamNetworkingUtils.Internal.ConvertPingLocationToString( ref this, out var strVal );
return strVal;
}
/// Estimate the round-trip latency between two arbitrary locations, in
/// milliseconds. This is a conservative estimate, based on routing through
/// the relay network. For most basic relayed connections, this ping time
/// will be pretty accurate, since it will be based on the route likely to
/// be actually used.
///
/// If a direct IP route is used (perhaps via NAT traversal), then the route
/// will be different, and the ping time might be better. Or it might actually
/// be a bit worse! Standard IP routing is frequently suboptimal!
///
/// But even in this case, the estimate obtained using this method is a
/// reasonable upper bound on the ping time. (Also it has the advantage
/// of returning immediately and not sending any packets.)
///
/// In a few cases we might not able to estimate the route. In this case
/// a negative value is returned. k_nSteamNetworkingPing_Failed means
/// the reason was because of some networking difficulty. (Failure to
/// ping, etc) k_nSteamNetworkingPing_Unknown is returned if we cannot
/// currently answer the question for some other reason.
///
/// Do you need to be able to do this from a backend/matchmaking server?
/// You are looking for the "ticketgen" library.
public int EstimatePingTo( PingLocation target )
{
return SteamNetworkingUtils.Internal.EstimatePingTimeBetweenTwoLocations( ref this, ref target );
}
}
}
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
namespace Steamworks.Data
{
/// <summary>
/// Represents a RemotePlaySession from the SteamRemotePlay interface
/// </summary>
public struct RemotePlaySession
{
public uint Id { get; set; }
public override string ToString() => Id.ToString();
public static implicit operator RemotePlaySession( uint value ) => new RemotePlaySession() { Id = value };
public static implicit operator uint( RemotePlaySession value ) => value.Id;
/// <summary>
/// Returns true if this session was valid when created. This will stay true even
/// after disconnection - so be sure to watch SteamRemotePlay.OnSessionDisconnected
/// </summary>
public bool IsValid => Id > 0;
/// <summary>
/// Get the SteamID of the connected user
/// </summary>
public SteamId SteamId => SteamRemotePlay.Internal.GetSessionSteamID( Id );
/// <summary>
/// Get the name of the session client device
/// </summary>
public string ClientName => SteamRemotePlay.Internal.GetSessionClientName( Id );
/// <summary>
/// Get the name of the session client device
/// </summary>
public SteamDeviceFormFactor FormFactor => SteamRemotePlay.Internal.GetSessionClientFormFactor( Id );
}
}
@@ -9,8 +9,6 @@ namespace Steamworks.Data
{
public struct ServerInfo : IEquatable<ServerInfo>
{
static ISteamMatchmakingServers Internal => Steamworks.ServerList.Base.Internal;
public string Name { get; set; }
public int Ping { get; set; }
public string GameDir { get; set; }
@@ -1,23 +0,0 @@
namespace Steamworks.Data
{
public struct Socket
{
internal uint Id;
public override string ToString() => Id.ToString();
/// <summary>
/// Destroy a listen socket. All the connections that were accepting on the listen
/// socket are closed ungracefully.
/// </summary>
public bool Close()
{
return SteamNetworkingSockets.Internal.CloseListenSocket( this );
}
public SocketInterface Interface
{
get => SteamNetworkingSockets.GetSocketInterface( Id );
set => SteamNetworkingSockets.SetSocketInterface( Id, value );
}
}
}
+10 -10
View File
@@ -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 )
@@ -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 partial 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" );
}
}
}
@@ -1,58 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Steamworks.Data
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public 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
{
public ConnectionState state;
public int ping;
public float connectionQualityLocal;
public float connectionQualityRemote;
public float outPacketsPerSecond;
public float outBytesPerSecond;
public float inPacketsPerSecond;
public float inBytesPerSecond;
public int sendRateBytesPerSecond;
public int pendingUnreliable;
public int pendingReliable;
public int sentUnackedReliable;
public long queueTime;
[MarshalAs( UnmanagedType.ByValArray, SizeConst = 16 )]
uint[] reserved;
}
struct SteamDatagramRelayAuthTicket
{
// Not implemented
};
struct SteamDatagramHostedAddress
{
// Not implemented
}
}
@@ -1,9 +1,13 @@
using System.Linq;
#pragma warning disable 649
namespace Steamworks.Data
{
public struct Ugc
{
internal UGCHandle_t Handle;
}
}
}
#pragma warning restore 649
@@ -14,29 +14,36 @@ namespace Steamworks.Ugc
public PublishedFileId FileId { get; private set; }
bool creatingNew;
WorkshopFileType creatingType;
AppId consumerAppId;
internal Editor(WorkshopFileType filetype) : this()
{
this.creatingNew = true;
this.creatingType = filetype;
}
WorkshopFileType creatingType;
AppId consumerAppId;
public Editor(PublishedFileId fileId) : this()
{
this.FileId = fileId;
}
internal Editor( WorkshopFileType filetype ) : this()
{
this.creatingNew = true;
this.creatingType = filetype;
}
/// <summary>
/// Create a Normal Workshop item that can be subscribed to
/// </summary>
public static Editor CreateCommunityFile() { return new Editor(WorkshopFileType.Community); }
public Editor( PublishedFileId fileId ) : this()
{
this.FileId = fileId;
}
/// <summary>
/// Workshop item that is meant to be voted on for the purpose of selling in-game
/// </summary>
public static Editor CreateMicrotransactionFile() { return new Editor(WorkshopFileType.Microtransaction ); }
/// <summary>
/// Create a Normal Workshop item that can be subscribed to
/// </summary>
public static Editor NewCommunityFile => new Editor( WorkshopFileType.Community );
/// <summary>
/// Create a Collection
/// Add items using Item.AddDependency()
/// </summary>
public static Editor NewCollection => new Editor( WorkshopFileType.Collection );
/// <summary>
/// Workshop item that is meant to be voted on for the purpose of selling in-game
/// </summary>
public static Editor NewMicrotransactionFile => new Editor( WorkshopFileType.Microtransaction );
public Editor ForAppId( AppId id ) { this.consumerAppId = id; return this; }
@@ -68,11 +75,14 @@ namespace Steamworks.Ugc
public Editor WithFriendsOnlyVisibility() { Visibility = RemoteStoragePublishedFileVisibility.FriendsOnly; return this; }
public Editor WithPrivateVisibility() { Visibility = RemoteStoragePublishedFileVisibility.Private; return this; }
public List<string> Tags { get; private set; }
Dictionary<string, List<string>> KeyValueTags;
HashSet<string> KeyValueTagsToRemove;
public bool IsPublic => Visibility == RemoteStoragePublishedFileVisibility.Public;
public bool IsFriendsOnly => Visibility == RemoteStoragePublishedFileVisibility.FriendsOnly;
public bool IsPrivate => Visibility == RemoteStoragePublishedFileVisibility.Private;
public List<string> Tags { get; private set; }
public Editor WithTag( string tag )
{
if ( Tags == null ) Tags = new List<string>();
@@ -82,22 +92,56 @@ namespace Steamworks.Ugc
return this;
}
public Editor WithTags( IEnumerable<string> tags )
{
if (Tags == null) Tags = new List<string>();
public Editor WithTags(IEnumerable<string> tags)
{
if (Tags == null) Tags = new List<string>();
Tags.AddRange(tags);
Tags.AddRange(tags);
return this;
}
return this;
}
public Editor WithoutTag( string tag )
public Editor WithoutTag(string tag)
{
if (Tags != null && Tags.Contains(tag)) Tags.Remove(tag);
return this;
}
/// <summary>
/// Adds a key-value tag pair to an item.
/// Keys can map to multiple different values (1-to-many relationship).
/// Key names are restricted to alpha-numeric characters and the '_' character.
/// Both keys and values cannot exceed 255 characters in length. Key-value tags are searchable by exact match only.
/// To replace all values associated to one key use RemoveKeyValueTags then AddKeyValueTag.
/// </summary>
public Editor AddKeyValueTag(string key, string value)
{
if (KeyValueTags == null)
KeyValueTags = new Dictionary<string, List<string>>();
if ( KeyValueTags.TryGetValue( key, out var list ) )
list.Add( value );
else
KeyValueTags[key] = new List<string>() { value };
return this;
}
/// <summary>
/// Removes a key and all values associated to it.
/// You can remove up to 100 keys per item update.
/// If you need remove more tags than that you'll need to make subsequent item updates.
/// </summary>
public Editor RemoveKeyValueTags(string key)
{
if (KeyValueTagsToRemove == null)
KeyValueTagsToRemove = new HashSet<string>();
KeyValueTagsToRemove.Add(key);
return this;
}
public bool HasTag( string tag )
{
if (Tags != null && Tags.Contains(tag)) { return true; }
@@ -114,6 +158,19 @@ namespace Steamworks.Ugc
if ( consumerAppId == 0 )
consumerAppId = SteamClient.AppId;
//
// Checks
//
if ( ContentFolder != null )
{
if ( !System.IO.Directory.Exists( ContentFolder.FullName ) )
throw new System.Exception( $"UgcEditor - Content Folder doesn't exist ({ContentFolder.FullName})" );
if ( !ContentFolder.EnumerateFiles( "*", System.IO.SearchOption.AllDirectories ).Any() )
throw new System.Exception( $"UgcEditor - Content Folder is empty" );
}
//
// Item Create
//
@@ -160,6 +217,22 @@ namespace Steamworks.Ugc
}
}
if ( KeyValueTagsToRemove != null)
{
foreach ( var key in KeyValueTagsToRemove )
SteamUGC.Internal.RemoveItemKeyValueTags( handle, key );
}
if ( KeyValueTags != null )
{
foreach ( var keyWithValues in KeyValueTags )
{
var key = keyWithValues.Key;
foreach ( var value in keyWithValues.Value )
SteamUGC.Internal.AddItemKeyValueTag( handle, key, value );
}
}
result.Result = Steamworks.Result.Fail;
if ( ChangeLog == null )
@@ -197,7 +270,7 @@ namespace Steamworks.Ugc
}
case ItemUpdateStatus.UploadingPreviewFile:
{
progress?.Report( 8f );
progress?.Report( 0.8f );
break;
}
case ItemUpdateStatus.CommittingChanges:
@@ -213,7 +286,7 @@ namespace Steamworks.Ugc
progress?.Report( 1 );
var updated = updating.Result;
var updated = updating.GetResult();
if ( !updated.HasValue ) return result;
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Steamworks.Data;
@@ -38,6 +39,11 @@ namespace Steamworks.Ugc
/// </summary>
public string[] Tags { get; internal set; }
/// <summary>
/// A dictionary of key value tags for this item, only available from queries WithKeyValueTags(true)
/// </summary>
public Dictionary<string,string> KeyValueTags { get; internal set; }
/// <summary>
/// App Id of the app that created this item
/// </summary>
@@ -125,7 +131,7 @@ namespace Steamworks.Ugc
/// <summary>
/// Start downloading this item.
/// If this returns false the item isn#t getting downloaded.
/// If this returns false the item isn't getting downloaded.
/// </summary>
public bool Download( Action onInstalled = null, bool highPriority = false )
{
@@ -182,8 +188,7 @@ namespace Steamworks.Ugc
ulong size = 0;
uint ts = 0;
if ( !SteamUGC.Internal.GetItemInstallInfo( Id, ref size, out var strVal, ref ts ) )
if ( !SteamUGC.Internal.GetItemInstallInfo( Id, ref size, out _, ref ts ) )
return 0;
return (long) size;
@@ -197,7 +202,9 @@ namespace Steamworks.Ugc
{
get
{
if ( !NeedsUpdate ) return 1;
//changed from NeedsUpdate as it's false when validating and redownloading ugc
//possibly similar properties should also be changed
if ( !IsDownloading ) return 1;
ulong downloaded = 0;
ulong total = 0;
@@ -215,10 +222,18 @@ namespace Steamworks.Ugc
public static async Task<Item?> GetAsync( PublishedFileId id, int maxageseconds = 60 * 30 )
{
var result = await SteamUGC.Internal.RequestUGCDetails( id, (uint) maxageseconds );
if ( !result.HasValue ) return null;
var file = await Steamworks.Ugc.Query.All
.WithFileId( id )
.WithLongDescription( true )
.GetPageAsync( 1 );
return From( result.Value.Details );
if ( !file.HasValue ) return null;
using ( file.Value )
{
if ( file.Value.ResultCount == 0 ) return null;
return file.Value.Entries.First();
}
}
internal static Item From( SteamUGCDetails_t details )
@@ -254,28 +269,67 @@ namespace Steamworks.Ugc
return result?.Result == Result.OK;
}
/// <summary>
/// Allows the user to unsubscribe from this item
/// </summary>
public async Task<bool> Unsubscribe ()
/// <summary>
/// Allows the user to subscribe to download this item asyncronously
/// If CancellationToken is default then there is 60 seconds timeout
/// Progress will be set to 0-1
/// </summary>
public async Task<bool> DownloadAsync( Action<float> progress = null, int milisecondsUpdateDelay = 60, CancellationToken ct = default )
{
return await SteamUGC.DownloadAsync( Id, progress, milisecondsUpdateDelay, ct );
}
/// <summary>
/// Allows the user to unsubscribe from this item
/// </summary>
public async Task<bool> Unsubscribe ()
{
var result = await SteamUGC.Internal.UnsubscribeItem( _id );
return result?.Result == Result.OK;
}
/// <summary>
/// Adds item to user favorite list
/// </summary>
public async Task<bool> AddFavorite()
{
var result = await SteamUGC.Internal.AddItemToFavorites(details.ConsumerAppID, _id);
return result?.Result == Result.OK;
}
/// <summary>
/// Removes item from user favorite list
/// </summary>
public async Task<bool> RemoveFavorite()
{
var result = await SteamUGC.Internal.RemoveItemFromFavorites(details.ConsumerAppID, _id);
return result?.Result == Result.OK;
}
/// <summary>
/// Allows the user to rate a workshop item up or down.
/// </summary>
public async Task<bool> Vote( bool up )
public async Task<Result?> Vote( bool up )
{
var r = await SteamUGC.Internal.SetUserItemVote( Id, up );
return r?.Result == Result.OK;
return r?.Result;
}
/// <summary>
/// Return a URL to view this item online
/// </summary>
public string Url => $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={Id}";
/// <summary>
/// Gets the current users vote on the item
/// </summary>
public async Task<UserItemVote?> GetUserVote()
{
var result = await SteamUGC.Internal.GetUserItemVote(_id);
if (!result.HasValue)
return null;
return UserItemVote.From(result.Value);
}
/// <summary>
/// Return a URL to view this item online
/// </summary>
public string Url => $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={Id}";
/// <summary>
/// The URl to view this item's changelog
@@ -311,10 +365,15 @@ namespace Steamworks.Ugc
public ulong NumSecondsPlayedDuringTimePeriod { get; internal set; }
public ulong NumPlaytimeSessionsDuringTimePeriod { get; internal set; }
/// <summary>
/// The URL to the preview image for this item
/// </summary>
public string PreviewImageUrl { get; internal set; }
/// <summary>
/// The URL to the preview image for this item
/// </summary>
public string PreviewImageUrl { get; internal set; }
/// <summary>
/// The metadata string for this item, only available from queries WithMetadata(true)
/// </summary>
public string Metadata { get; internal set; }
/// <summary>
/// Edit this item
@@ -323,6 +382,7 @@ namespace Steamworks.Ugc
{
return new Ugc.Editor( Id );
}
public Result Result => details.Result;
}
}
}
@@ -137,9 +137,16 @@ 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);
if (maxCacheAge.HasValue)
{
SteamUGC.Internal.SetAllowCachedResponse(handle, (uint)maxCacheAge.Value);
}
ApplyConstraints( handle );
var result = await SteamUGC.Internal.SendQueryUGCRequest( handle );
@@ -154,29 +161,15 @@ namespace Steamworks.Ugc
Handle = result.Value.Handle,
ResultCount = (int) result.Value.NumResultsReturned,
TotalCount = (int)result.Value.TotalMatchingResults,
CachedData = result.Value.CachedData
CachedData = result.Value.CachedData,
ReturnsKeyValueTags = WantsReturnKeyValueTags ?? false,
ReturnsDefaultStats = WantsDefaultStats ?? true, //true by default
ReturnsMetadata = WantsReturnMetadata ?? false,
};
}
#region SharedConstraints
#region SharedConstraints
public QueryType WithType( UgcType type ) { matchingType = type; return this; }
bool? WantsReturnOnlyIDs;
public QueryType WithOnlyIDs( bool b ) { WantsReturnOnlyIDs = b; return this; }
bool? WantsReturnKeyValueTags;
public QueryType WithKeyValueTag( bool b ) { WantsReturnKeyValueTags = b; return this; }
bool? WantsReturnLongDescription;
public QueryType WithLongDescription( bool b ) { WantsReturnLongDescription = b; return this; }
bool? WantsReturnMetadata;
public QueryType WithMetadata( bool b ) { WantsReturnMetadata = b; return this; }
bool? WantsReturnChildren;
public QueryType WithChildren( bool b ) { WantsReturnChildren = b; return this; }
bool? WantsReturnAdditionalPreviews;
public QueryType WithAdditionalPreviews( bool b ) { WantsReturnAdditionalPreviews = b; return this; }
bool? WantsReturnTotalOnly;
public QueryType WithTotalOnly( bool b ) { WantsReturnTotalOnly = b; return this; }
bool? WantsReturnPlaytimeStats;
public QueryType WithPlaytimeStats( bool b ) { WantsReturnPlaytimeStats = b; return this; }
int? maxCacheAge;
public QueryType AllowCachedResponse( int maxSecondsAge ) { maxCacheAge = maxSecondsAge; return this; }
string language;
@@ -221,6 +214,13 @@ namespace Steamworks.Ugc
return this;
}
public QueryType AddRequiredKeyValueTag(string key, string value)
{
if (requiredKv == null) requiredKv = new Dictionary<string, string>();
requiredKv.Add(key, value);
return this;
}
void ApplyConstraints( UGCQueryHandle_t handle )
{
if ( requiredTags != null )
@@ -259,7 +259,82 @@ namespace Steamworks.Ugc
SteamUGC.Internal.SetReturnLongDescription( handle, returnLongDescription );
}
#endregion
#endregion
#region ReturnValues
bool? WantsReturnOnlyIDs;
public QueryType WithOnlyIDs(bool b) { WantsReturnOnlyIDs = b; return this; }
bool? WantsReturnKeyValueTags;
public QueryType WithKeyValueTags(bool b) { WantsReturnKeyValueTags = b; return this; }
[Obsolete( "Renamed to WithKeyValueTags" )]
public QueryType WithKeyValueTag(bool b) { WantsReturnKeyValueTags = b; return this; }
bool? WantsReturnLongDescription;
public QueryType WithLongDescription(bool b) { WantsReturnLongDescription = b; return this; }
bool? WantsReturnMetadata;
public QueryType WithMetadata(bool b) { WantsReturnMetadata = b; return this; }
bool? WantsReturnChildren;
public QueryType WithChildren(bool b) { WantsReturnChildren = b; return this; }
bool? WantsReturnAdditionalPreviews;
public QueryType WithAdditionalPreviews(bool b) { WantsReturnAdditionalPreviews = b; return this; }
bool? WantsReturnTotalOnly;
public QueryType WithTotalOnly(bool b) { WantsReturnTotalOnly = b; return this; }
uint? WantsReturnPlaytimeStats;
public QueryType WithPlaytimeStats(uint unDays) { WantsReturnPlaytimeStats = unDays; return this; }
private void ApplyReturns(UGCQueryHandle_t handle)
{
if (WantsReturnOnlyIDs.HasValue)
{
SteamUGC.Internal.SetReturnOnlyIDs(handle, WantsReturnOnlyIDs.Value);
}
if (WantsReturnKeyValueTags.HasValue)
{
SteamUGC.Internal.SetReturnKeyValueTags(handle, WantsReturnKeyValueTags.Value);
}
if (WantsReturnLongDescription.HasValue)
{
SteamUGC.Internal.SetReturnLongDescription(handle, WantsReturnLongDescription.Value);
}
if (WantsReturnMetadata.HasValue)
{
SteamUGC.Internal.SetReturnMetadata(handle, WantsReturnMetadata.Value);
}
if (WantsReturnChildren.HasValue)
{
SteamUGC.Internal.SetReturnChildren(handle, WantsReturnChildren.Value);
}
if (WantsReturnAdditionalPreviews.HasValue)
{
SteamUGC.Internal.SetReturnAdditionalPreviews(handle, WantsReturnAdditionalPreviews.Value);
}
if (WantsReturnTotalOnly.HasValue)
{
SteamUGC.Internal.SetReturnTotalOnly(handle, WantsReturnTotalOnly.Value);
}
if (WantsReturnPlaytimeStats.HasValue)
{
SteamUGC.Internal.SetReturnPlaytimeStats(handle, WantsReturnPlaytimeStats.Value);
}
}
#endregion
#region LoadingBehaviour
bool? WantsDefaultStats; //true by default
/// <summary>
/// Set to false to disable, by default following stats are loaded: NumSubscriptions, NumFavorites, NumFollowers, NumUniqueSubscriptions, NumUniqueFavorites, NumUniqueFollowers, NumUniqueWebsiteViews, ReportScore, NumSecondsPlayed, NumPlaytimeSessions, NumComments, NumSecondsPlayedDuringTimePeriod, NumPlaytimeSessionsDuringTimePeriod
/// </summary>
public QueryType WithDefaultStats( bool b ) { WantsDefaultStats = b; return this; }
#endregion
}
}
@@ -12,6 +12,10 @@ namespace Steamworks.Ugc
public bool CachedData;
internal bool ReturnsKeyValueTags;
internal bool ReturnsDefaultStats;
internal bool ReturnsMetadata;
public IEnumerable<Item> Entries
{
get
@@ -24,30 +28,53 @@ namespace Steamworks.Ugc
{
var item = Item.From( details );
item.NumSubscriptions = GetStat( i, ItemStatistic.NumSubscriptions );
item.NumFavorites = GetStat( i, ItemStatistic.NumFavorites );
item.NumFollowers = GetStat( i, ItemStatistic.NumFollowers );
item.NumUniqueSubscriptions = GetStat( i, ItemStatistic.NumUniqueSubscriptions );
item.NumUniqueFavorites = GetStat( i, ItemStatistic.NumUniqueFavorites );
item.NumUniqueFollowers = GetStat( i, ItemStatistic.NumUniqueFollowers );
item.NumUniqueWebsiteViews = GetStat( i, ItemStatistic.NumUniqueWebsiteViews );
item.ReportScore = GetStat( i, ItemStatistic.ReportScore );
item.NumSecondsPlayed = GetStat( i, ItemStatistic.NumSecondsPlayed );
item.NumPlaytimeSessions = GetStat( i, ItemStatistic.NumPlaytimeSessions );
item.NumComments = GetStat( i, ItemStatistic.NumComments );
item.NumSecondsPlayedDuringTimePeriod = GetStat( i, ItemStatistic.NumSecondsPlayedDuringTimePeriod );
item.NumPlaytimeSessionsDuringTimePeriod = GetStat( i, ItemStatistic.NumPlaytimeSessionsDuringTimePeriod );
if ( ReturnsDefaultStats )
{
item.NumSubscriptions = GetStat( i, ItemStatistic.NumSubscriptions );
item.NumFavorites = GetStat( i, ItemStatistic.NumFavorites );
item.NumFollowers = GetStat( i, ItemStatistic.NumFollowers );
item.NumUniqueSubscriptions = GetStat( i, ItemStatistic.NumUniqueSubscriptions );
item.NumUniqueFavorites = GetStat( i, ItemStatistic.NumUniqueFavorites );
item.NumUniqueFollowers = GetStat( i, ItemStatistic.NumUniqueFollowers );
item.NumUniqueWebsiteViews = GetStat( i, ItemStatistic.NumUniqueWebsiteViews );
item.ReportScore = GetStat( i, ItemStatistic.ReportScore );
item.NumSecondsPlayed = GetStat( i, ItemStatistic.NumSecondsPlayed );
item.NumPlaytimeSessions = GetStat( i, ItemStatistic.NumPlaytimeSessions );
item.NumComments = GetStat( i, ItemStatistic.NumComments );
item.NumSecondsPlayedDuringTimePeriod = GetStat( i, ItemStatistic.NumSecondsPlayedDuringTimePeriod );
item.NumPlaytimeSessionsDuringTimePeriod = GetStat( i, ItemStatistic.NumPlaytimeSessionsDuringTimePeriod );
}
if ( SteamUGC.Internal.GetQueryUGCPreviewURL( Handle, i, out string preview ) )
{
item.PreviewImageUrl = preview;
}
if ( ReturnsKeyValueTags )
{
var keyValueTagsCount = SteamUGC.Internal.GetQueryUGCNumKeyValueTags( Handle, i );
item.KeyValueTags = new Dictionary<string, string>( (int)keyValueTagsCount );
for ( uint j = 0; j < keyValueTagsCount; j++ )
{
string key, value;
if ( SteamUGC.Internal.GetQueryUGCKeyValueTag( Handle, i, j, out key, out value ) )
item.KeyValueTags[key] = value;
}
}
if (ReturnsMetadata)
{
string metadata;
if (SteamUGC.Internal.GetQueryUGCMetadata(Handle, i, out metadata))
{
item.Metadata = metadata;
}
}
// TODO GetQueryUGCAdditionalPreview
// TODO GetQueryUGCChildren
// TODO GetQueryUGCKeyValueTag
// TODO GetQueryUGCMetadata
yield return item;
}
@@ -0,0 +1,21 @@
using Steamworks.Data;
namespace Steamworks.Ugc
{
public struct UserItemVote
{
public bool VotedUp;
public bool VotedDown;
public bool VoteSkipped;
internal static UserItemVote? From(GetUserItemVoteResult_t result)
{
return new UserItemVote
{
VotedUp = result.VotedUp,
VotedDown = result.VotedDown,
VoteSkipped = result.VoteSkipped
};
}
}
}