Added ServerList favourites/history/LAN/friends

This commit is contained in:
Garry Newman 2016-11-11 11:09:28 +00:00
parent aeec6f59ef
commit 01dbec678c
5 changed files with 270 additions and 36 deletions

View File

@ -134,7 +134,90 @@ namespace Facepunch.Steamworks.Test
{ {
using ( var client = new Facepunch.Steamworks.Client( 252490 ) ) using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
{ {
var query = client.ServerList.History(); var filter = new Facepunch.Steamworks.ServerList.Filter();
filter.Add( "appid", client.AppId.ToString() );
filter.Add( "gamedir", "rust" );
filter.Add( "secure", "1" );
var query = client.ServerList.History( filter );
while ( true )
{
client.Update();
System.Threading.Thread.Sleep( 2 );
if ( query.Finished )
break;
}
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
foreach ( var x in query.Responded )
{
Console.WriteLine( x.Map );
}
query.Dispose();
for ( int i = 0; i < 100; i++ )
{
client.Update();
System.Threading.Thread.Sleep( 1 );
}
}
}
[TestMethod]
public void FavouriteList()
{
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
{
var filter = new Facepunch.Steamworks.ServerList.Filter();
filter.Add( "appid", client.AppId.ToString() );
filter.Add( "gamedir", "rust" );
filter.Add( "secure", "1" );
var query = client.ServerList.Favourites( filter );
while ( true )
{
client.Update();
System.Threading.Thread.Sleep( 2 );
if ( query.Finished )
break;
}
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
foreach ( var x in query.Responded )
{
Console.WriteLine( x.Map );
}
query.Dispose();
for ( int i = 0; i < 100; i++ )
{
client.Update();
System.Threading.Thread.Sleep( 1 );
}
}
}
[TestMethod]
public void LocalList()
{
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
{
var filter = new Facepunch.Steamworks.ServerList.Filter();
filter.Add( "appid", client.AppId.ToString() );
filter.Add( "gamedir", "rust" );
filter.Add( "secure", "1" );
var query = client.ServerList.Local( filter );
while ( true ) while ( true )
{ {

View File

@ -20,7 +20,8 @@ namespace Facepunch.Steamworks
/// </summary> /// </summary>
public string BetaName { get; private set; } public string BetaName { get; private set; }
public Voice Voice { get; internal set; } public Voice Voice { get; private set; }
public ServerList ServerList { get; private set; }
public Client( uint appId ) public Client( uint appId )
{ {
@ -45,6 +46,7 @@ namespace Facepunch.Steamworks
// Client only interfaces // Client only interfaces
// //
Voice = new Voice( this ); Voice = new Voice( this );
ServerList = new ServerList( this );
Workshop.friends = Friends; Workshop.friends = Friends;
@ -89,6 +91,12 @@ namespace Facepunch.Steamworks
Voice = null; Voice = null;
} }
if ( ServerList != null )
{
ServerList.Dispose();
ServerList = null;
}
base.Dispose(); base.Dispose();
} }
} }

View File

@ -19,12 +19,19 @@ namespace Facepunch.Steamworks
internal IntPtr Request; internal IntPtr Request;
internal int Pointer = 0; internal int Pointer = 0;
internal List<int> WatchList = new List<int>(); internal List<int> WatchList = new List<int>();
internal System.Diagnostics.Stopwatch Timer = System.Diagnostics.Stopwatch.StartNew();
internal bool Update( SteamNative.SteamMatchmakingServers servers, Action<SteamNative.gameserveritem_t> OnServer, Action OnUpdate ) internal bool Update( SteamNative.SteamMatchmakingServers servers, Action<SteamNative.gameserveritem_t> OnServer, Action OnUpdate )
{ {
if ( Request == IntPtr.Zero ) if ( Request == IntPtr.Zero )
return true; return true;
if ( Timer.Elapsed.TotalSeconds < 0.5f )
return false;
Timer.Reset();
Timer.Start();
bool changes = false; bool changes = false;
// //
@ -114,7 +121,7 @@ namespace Facepunch.Steamworks
} }
internal IEnumerable<string> ServerList { get; set; } internal IEnumerable<string> ServerList { get; set; }
internal Filter Filter { get; set; }
internal void StartCustomQuery() internal void StartCustomQuery()
{ {
@ -181,6 +188,9 @@ namespace Facepunch.Steamworks
{ {
if ( info.HadSuccessfulResponse ) if ( info.HadSuccessfulResponse )
{ {
if ( Filter != null && !Filter.Test( info ) )
return;
Responded.Add( Server.FromSteam( client, info ) ); Responded.Add( Server.FromSteam( client, info ) );
} }
else else

View File

@ -29,6 +29,17 @@ namespace Facepunch.Steamworks
public int ConnectionPort { get; set; } public int ConnectionPort { get; set; }
public int QueryPort { get; set; } public int QueryPort { get; set; }
/// <summary>
/// Returns true if this server is in the favourites list
/// </summary>
public bool Favourite
{
get
{
return Client.ServerList.IsFavourite( this );
}
}
internal Client Client; internal Client Client;
public string AddressString public string AddressString
@ -111,6 +122,47 @@ namespace Facepunch.Steamworks
if ( OnReceivedRules != null ) if ( OnReceivedRules != null )
OnReceivedRules( Success ); OnReceivedRules( Success );
} }
internal const uint k_unFavoriteFlagNone = 0x00;
internal const uint k_unFavoriteFlagFavorite = 0x01; // this game favorite entry is for the favorites list
internal const uint k_unFavoriteFlagHistory = 0x02; // this game favorite entry is for the history list
/// <summary>
/// Add this server to our history list
/// If we're already in the history list, weill set the last played time to now
/// </summary>
public void AddToHistory()
{
Client.native.matchmaking.AddFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory, (uint)Utility.Epoch.Current );
Client.ServerList.UpdateFavouriteList();
}
/// <summary>
/// Remove this server from our history list
/// </summary>
public void RemoveFromHistory()
{
Client.native.matchmaking.RemoveFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory );
Client.ServerList.UpdateFavouriteList();
}
/// <summary>
/// Add this server to our favourite list
/// </summary>
public void AddToFavourites()
{
Client.native.matchmaking.AddFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite, (uint)Utility.Epoch.Current );
Client.ServerList.UpdateFavouriteList();
}
/// <summary>
/// Remove this server from our favourite list
/// </summary>
public void RemoveFromFavourites()
{
Client.native.matchmaking.RemoveFavoriteGame( AppId, Address, (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite );
Client.ServerList.UpdateFavouriteList();
}
} }
} }
} }

View File

@ -3,27 +3,56 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using SteamNative;
namespace Facepunch.Steamworks namespace Facepunch.Steamworks
{ {
public partial class Client : IDisposable public partial class ServerList : IDisposable
{ {
private ServerList _serverlist; internal Client client;
public ServerList ServerList internal ServerList( Client client )
{ {
get this.client = client;
{
if ( _serverlist == null )
_serverlist = new ServerList { client = this };
return _serverlist; UpdateFavouriteList();
} }
HashSet<ulong> FavouriteHash = new HashSet<ulong>();
HashSet<ulong> HistoryHash = new HashSet<ulong>();
internal void UpdateFavouriteList()
{
FavouriteHash.Clear();
HistoryHash.Clear();
for ( int i=0; i< client.native.matchmaking.GetFavoriteGameCount(); i++ )
{
AppId_t appid = 0;
uint ip;
ushort conPort;
ushort queryPort;
uint lastplayed;
uint flags;
client.native.matchmaking.GetFavoriteGame( i, ref appid, out ip, out conPort, out queryPort, out flags, out lastplayed );
ulong encoded = ip;
encoded = encoded << 32;
encoded = encoded | (uint)conPort;
if ( ( flags & Server.k_unFavoriteFlagFavorite ) == Server.k_unFavoriteFlagFavorite )
FavouriteHash.Add( encoded );
if ( ( flags & Server.k_unFavoriteFlagFavorite ) == Server.k_unFavoriteFlagFavorite )
HistoryHash.Add( encoded );
} }
} }
public partial class ServerList public void Dispose()
{ {
client = null;
}
public class Filter : List<KeyValuePair<string, string>> public class Filter : List<KeyValuePair<string, string>>
{ {
@ -35,16 +64,19 @@ namespace Facepunch.Steamworks
internal IntPtr NativeArray; internal IntPtr NativeArray;
private IntPtr m_pArrayEntries; private IntPtr m_pArrayEntries;
private int AppId = 0;
internal void Start() internal void Start()
{ {
var filters = this.Select( x => var filters = this.Select( x =>
{ {
if ( x.Key == "appid" ) AppId = int.Parse( x.Value );
return new SteamNative.MatchMakingKeyValuePair_t() return new SteamNative.MatchMakingKeyValuePair_t()
{ {
Key = x.Key, Key = x.Key,
Value = x.Value Value = x.Value
}; };
} ).ToArray(); } ).ToArray();
int sizeOfMMKVP = Marshal.SizeOf(typeof(SteamNative.MatchMakingKeyValuePair_t)); int sizeOfMMKVP = Marshal.SizeOf(typeof(SteamNative.MatchMakingKeyValuePair_t));
@ -71,9 +103,17 @@ namespace Facepunch.Steamworks
Marshal.FreeHGlobal( NativeArray ); Marshal.FreeHGlobal( NativeArray );
} }
} }
internal bool Test( gameserveritem_t info )
{
if ( AppId != 0 && AppId != info.AppID )
return false;
return true;
}
} }
internal Client client;
[StructLayout( LayoutKind.Sequential )] [StructLayout( LayoutKind.Sequential )]
private struct MatchPair private struct MatchPair
@ -84,11 +124,14 @@ namespace Facepunch.Steamworks
public string value; public string value;
} }
public Request Internet( Filter filter ) public Request Internet( Filter filter )
{ {
filter.Start(); filter.Start();
var request = new Request( client ); var request = new Request( client );
request.Filter = filter;
request.AddRequest( client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, (uint) filter.Count, IntPtr.Zero ) ); request.AddRequest( client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, (uint) filter.Count, IntPtr.Zero ) );
filter.Free(); filter.Free();
@ -96,6 +139,9 @@ namespace Facepunch.Steamworks
return request; return request;
} }
/// <summary>
/// Query a list of addresses. No filters applied.
/// </summary>
public Request Custom( IEnumerable<string> serverList ) public Request Custom( IEnumerable<string> serverList )
{ {
var request = new Request( client ); var request = new Request( client );
@ -105,52 +151,87 @@ namespace Facepunch.Steamworks
} }
/// <summary> /// <summary>
/// History filters don't seem to work, so we don't bother. /// Request a list of servers we've been on. History isn't applied automatically
/// You should apply them post process'dly /// You need to call server.AddtoHistoryList() when you join a server etc.
/// </summary> /// </summary>
public Request History() public Request History( Filter filter )
{ {
filter.Start();
var request = new Request( client ); var request = new Request( client );
request.AddRequest( client.native.servers.RequestHistoryServerList( client.AppId, IntPtr.Zero, 0, IntPtr.Zero ) ); request.Filter = filter;
request.AddRequest( client.native.servers.RequestHistoryServerList( client.AppId, filter.NativeArray, (uint)filter.Count, IntPtr.Zero ) );
filter.Free();
return request; return request;
} }
/// <summary> /// <summary>
/// Favourite filters don't seem to work, so we don't bother. /// Request a list of servers we've favourited
/// You should apply them post process'dly
/// </summary> /// </summary>
public Request Favourites() public Request Favourites( Filter filter )
{ {
filter.Start();
var request = new Request( client ); var request = new Request( client );
request.AddRequest( client.native.servers.RequestFavoritesServerList( client.AppId, IntPtr.Zero, 0, IntPtr.Zero ) ); request.Filter = filter;
request.AddRequest( client.native.servers.RequestFavoritesServerList( client.AppId, filter.NativeArray, (uint)filter.Count, IntPtr.Zero ) );
filter.Free();
return request; return request;
} }
public void AddToHistory( Server server ) /// <summary>
/// Request a list of servers that our friends are on
/// </summary>
public Request Friends( Filter filter )
{ {
// client.native.matchmaking filter.Start();
var request = new Request( client );
request.Filter = filter;
request.AddRequest( client.native.servers.RequestFriendsServerList( client.AppId, filter.NativeArray, (uint)filter.Count, IntPtr.Zero ) );
filter.Free();
return request;
} }
public void RemoveFromHistory( Server server ) /// <summary>
/// Request a list of servers that are running on our LAN
/// </summary>
public Request Local( Filter filter )
{ {
// filter.Start();
var request = new Request( client );
request.Filter = filter;
request.AddRequest( client.native.servers.RequestLANServerList( client.AppId, IntPtr.Zero ) );
filter.Free();
return request;
} }
public void AddToFavourite( Server server )
internal bool IsFavourite( Server server )
{ {
// client.native.matchmaking ulong encoded = server.Address;
encoded = encoded << 32;
encoded = encoded | (uint)server.ConnectionPort;
return FavouriteHash.Contains( encoded );
} }
public void RemoveFromFavourite( Server server ) internal bool IsHistory( Server server )
{ {
// ulong encoded = server.Address;
} encoded = encoded << 32;
encoded = encoded | (uint)server.ConnectionPort;
public bool IsFavourite( Server server ) return HistoryHash.Contains( encoded );
{
return false;
} }
} }
} }