using System.Threading.Tasks; using System.Collections.Generic; namespace Steamworks.Data { public struct LobbyQuery { // TODO FILTERS // AddRequestLobbyListStringFilter // - WithoutKeyValue #region Distance Filter internal LobbyDistanceFilter? distance; /// /// only lobbies in the same immediate region will be returned /// public LobbyQuery FilterDistanceClose() { distance = LobbyDistanceFilter.Close; return this; } /// /// only lobbies in the same immediate region will be returned /// public LobbyQuery FilterDistanceFar() { distance = LobbyDistanceFilter.Far; return this; } /// /// only lobbies in the same immediate region will be returned /// public LobbyQuery FilterDistanceWorldwide() { distance = LobbyDistanceFilter.Worldwide; return this; } #endregion #region String key/value filter internal Dictionary stringFilters; internal Dictionary> stringFiltersExclude; /// /// Filter by specified key/value pair; string parameters /// public LobbyQuery WithKeyValue(string key, string value) { if (string.IsNullOrEmpty(key)) throw new System.ArgumentException("Key string provided for LobbyQuery filter is null or empty", nameof(key)); if (key.Length > SteamMatchmaking.MaxLobbyKeyLength) throw new System.ArgumentException($"Key length is longer than {SteamMatchmaking.MaxLobbyKeyLength}", nameof(key)); if (stringFilters == null) stringFilters = new Dictionary(); stringFilters.Add(key, value); return this; } public LobbyQuery WithoutKeyValue(string key, string value) { if (string.IsNullOrEmpty(key)) throw new System.ArgumentException("Key string provided for LobbyQuery filter is null or empty", nameof(key)); if (key.Length > SteamMatchmaking.MaxLobbyKeyLength) throw new System.ArgumentException($"Key length is longer than {SteamMatchmaking.MaxLobbyKeyLength}", nameof(key)); if (stringFiltersExclude == null) stringFiltersExclude = new Dictionary>(); if (!stringFiltersExclude.ContainsKey(key)) { stringFiltersExclude.Add(key, new List()); } stringFiltersExclude[key].Add(value); return this; } #endregion #region Numerical filters internal List numericalFilters; /// /// Numerical filter where value is less than the value provided /// public LobbyQuery WithLower( string key, int value ) { AddNumericalFilter( key, value, LobbyComparison.LessThan ); return this; } /// /// Numerical filter where value is greater than the value provided /// public LobbyQuery WithHigher( string key, int value ) { AddNumericalFilter( key, value, LobbyComparison.GreaterThan ); return this; } /// /// Numerical filter where value must be equal to the value provided /// public LobbyQuery WithEqual( string key, int value ) { AddNumericalFilter( key, value, LobbyComparison.Equal ); return this; } /// /// Numerical filter where value must not equal the value provided /// public LobbyQuery WithNotEqual( string key, int value ) { AddNumericalFilter( key, value, LobbyComparison.NotEqual ); return this; } /// /// Test key, initialize numerical filter list if necessary, then add new numerical filter /// internal void AddNumericalFilter( string key, int value, LobbyComparison compare ) { if ( string.IsNullOrEmpty( key ) ) throw new System.ArgumentException( "Key string provided for LobbyQuery filter is null or empty", nameof( key ) ); if ( key.Length > SteamMatchmaking.MaxLobbyKeyLength ) throw new System.ArgumentException( $"Key length is longer than {SteamMatchmaking.MaxLobbyKeyLength}", nameof( key ) ); if ( numericalFilters == null ) numericalFilters = new List(); numericalFilters.Add( new NumericalFilter( key, value, compare ) ); } #endregion #region Near value filter internal Dictionary nearValFilters; /// /// Order filtered results according to key/values nearest the provided key/value pair. /// Can specify multiple near value filters; each successive filter is lower priority than the previous. /// public LobbyQuery OrderByNear( string key, int value ) { if ( string.IsNullOrEmpty( key ) ) throw new System.ArgumentException( "Key string provided for LobbyQuery filter is null or empty", nameof( key ) ); if ( key.Length > SteamMatchmaking.MaxLobbyKeyLength ) throw new System.ArgumentException( $"Key length is longer than {SteamMatchmaking.MaxLobbyKeyLength}", nameof( key ) ); if ( nearValFilters == null ) nearValFilters = new Dictionary(); nearValFilters.Add( key, value ); return this; } #endregion #region Slots Filter internal int? slotsAvailable; /// /// returns only lobbies with the specified number of slots available /// public LobbyQuery WithSlotsAvailable( int minSlots ) { slotsAvailable = minSlots; return this; } #endregion #region Max results filter internal int? maxResults; /// /// sets how many results to return, the lower the count the faster it is to download the lobby results /// public LobbyQuery WithMaxResults( int max ) { maxResults = max; return this; } #endregion void ApplyFilters() { if (SteamMatchmaking.Internal is null) { return; } if ( distance.HasValue ) { SteamMatchmaking.Internal.AddRequestLobbyListDistanceFilter( distance.Value ); } if ( slotsAvailable.HasValue ) { SteamMatchmaking.Internal.AddRequestLobbyListFilterSlotsAvailable( slotsAvailable.Value ); } if (stringFilters != null) { foreach (var k in stringFilters) { SteamMatchmaking.Internal.AddRequestLobbyListStringFilter(k.Key, k.Value, LobbyComparison.Equal); } } if (stringFiltersExclude != null) { foreach (var k in stringFiltersExclude) { foreach (var v in k.Value) { SteamMatchmaking.Internal.AddRequestLobbyListStringFilter(k.Key, v, LobbyComparison.NotEqual); } } } if ( numericalFilters != null ) { foreach ( var n in numericalFilters ) { SteamMatchmaking.Internal.AddRequestLobbyListNumericalFilter( n.Key, n.Value, n.Comparer ); } } if( nearValFilters != null ) { foreach (var v in nearValFilters ) { SteamMatchmaking.Internal.AddRequestLobbyListNearValueFilter( v.Key, v.Value ); } } if (maxResults.HasValue) { SteamMatchmaking.Internal.AddRequestLobbyListResultCountFilter(maxResults.Value); } } /// /// Run the query, get the matching lobbies /// public async Task RequestAsync() { if (SteamMatchmaking.Internal is null) { return null; } await Task.Yield(); ApplyFilters(); LobbyMatchList_t? list = await SteamMatchmaking.Internal.RequestLobbyList(); if ( !list.HasValue || list.Value.LobbiesMatching == 0 ) { return null; } Lobby[] lobbies = new Lobby[list.Value.LobbiesMatching]; for ( int i = 0; i < list.Value.LobbiesMatching; i++ ) { lobbies[i] = new Lobby { Id = SteamMatchmaking.Internal.GetLobbyByIndex( i ) }; } return lobbies; } } }