diff --git a/Facepunch.Steamworks.Test/ServerlistTest.cs b/Facepunch.Steamworks.Test/ServerlistTest.cs
index a6a45c2..2568564 100644
--- a/Facepunch.Steamworks.Test/ServerlistTest.cs
+++ b/Facepunch.Steamworks.Test/ServerlistTest.cs
@@ -165,5 +165,65 @@ namespace Steamworks
}
}
}
- }
+
+ [TestMethod]
+ public async Task ServerListIps()
+ {
+ var ips = new string[]
+ {
+ "31.186.251.76",
+ "31.186.251.76",
+ "31.186.251.76",
+ "31.186.251.76",
+ "31.186.251.76",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "139.99.144.70",
+ "139.99.144.70",
+ "139.99.144.70",
+ "139.99.144.70",
+ "139.99.144.70",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "74.91.119.142",
+ "95.172.92.176",
+ "95.172.92.176",
+ "95.172.92.176",
+ "95.172.92.176",
+ "95.172.92.176",
+ "164.132.205.154",
+ "164.132.205.154",
+ "164.132.205.154",
+ "164.132.205.154",
+ "164.132.205.154",
+ };
+
+ using ( var list = new ServerList.IpList( ips ) )
+ {
+ var success = await list.RunQueryAsync();
+
+ Console.WriteLine( $"success {success}" );
+ Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
+ Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
+
+ Assert.AreNotEqual( list.Responsive.Count, 0 );
+
+ foreach ( var server in list.Responsive )
+ {
+ Console.WriteLine( $"[{server.Address}:{server.ConnectionPort}] - {server.Name}" );
+ }
+ }
+ }
+ }
}
diff --git a/Facepunch.Steamworks/ServerList/Base.cs b/Facepunch.Steamworks/ServerList/Base.cs
index 1c883ed..36318ee 100644
--- a/Facepunch.Steamworks/ServerList/Base.cs
+++ b/Facepunch.Steamworks/ServerList/Base.cs
@@ -66,7 +66,7 @@ namespace Steamworks.ServerList
/// Query the server list. Task result will be true when finished
///
///
- public async Task RunQueryAsync( float timeoutSeconds = 10 )
+ public virtual async Task RunQueryAsync( float timeoutSeconds = 10 )
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
@@ -92,7 +92,7 @@ namespace Steamworks.ServerList
if ( r != Responsive.Count )
{
- OnChanges?.Invoke();
+ InvokeChanges();
}
if ( stopwatch.Elapsed.TotalSeconds > timeoutSeconds )
@@ -100,12 +100,12 @@ namespace Steamworks.ServerList
}
MovePendingToUnresponsive();
- OnChanges?.Invoke();
+ InvokeChanges();
return true;
}
- public void Cancel() => Internal.CancelQuery( request );
+ public virtual void Cancel() => Internal.CancelQuery( request );
// Overrides
internal abstract void LaunchQuery();
@@ -115,7 +115,7 @@ namespace Steamworks.ServerList
#region Filters
internal List filters = new List();
- internal MatchMakingKeyValuePair_t[] GetFilters() => filters.ToArray();
+ internal virtual MatchMakingKeyValuePair_t[] GetFilters() => filters.ToArray();
public void AddFilter( string key, string value )
{
@@ -151,6 +151,11 @@ namespace Steamworks.ServerList
ReleaseQuery();
}
+ internal void InvokeChanges()
+ {
+ OnChanges?.Invoke();
+ }
+
void UpdatePending()
{
var count = Count;
diff --git a/Facepunch.Steamworks/ServerList/IpList.cs b/Facepunch.Steamworks/ServerList/IpList.cs
new file mode 100644
index 0000000..c76e88c
--- /dev/null
+++ b/Facepunch.Steamworks/ServerList/IpList.cs
@@ -0,0 +1,72 @@
+using Steamworks.Data;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Steamworks.ServerList
+{
+ public class IpList : Internet
+ {
+ public List Ips = new List();
+ bool wantsCancel;
+
+ public IpList( IEnumerable list )
+ {
+ Ips.AddRange( list );
+ }
+
+ public IpList( params string[] list )
+ {
+ Ips.AddRange( list );
+ }
+
+ public override async Task RunQueryAsync( float timeoutSeconds = 10 )
+ {
+ int blockSize = 16;
+ int pointer = 0;
+
+ var ips = Ips.ToArray();
+
+ while ( true )
+ {
+ var sublist = ips.Skip( pointer ).Take( blockSize );
+ if ( sublist.Count() == 0 )
+ break;
+
+ using ( var list = new ServerList.Internet() )
+ {
+ list.AddFilter( "or", sublist.Count().ToString() );
+
+ foreach ( var server in sublist )
+ {
+ list.AddFilter( "gameaddr", server );
+ }
+
+ await list.RunQueryAsync( timeoutSeconds );
+
+ if ( wantsCancel )
+ return false;
+
+ Responsive.AddRange( list.Responsive );
+ Responsive = Responsive.Distinct().ToList();
+ Unresponsive.AddRange( list.Unresponsive );
+ Unresponsive = Unresponsive.Distinct().ToList();
+ }
+
+ pointer += sublist.Count();
+
+ InvokeChanges();
+ }
+
+ return true;
+ }
+
+ public override void Cancel()
+ {
+ wantsCancel = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Facepunch.Steamworks/Structs/Server.cs b/Facepunch.Steamworks/Structs/Server.cs
index 0c470d5..df5c620 100644
--- a/Facepunch.Steamworks/Structs/Server.cs
+++ b/Facepunch.Steamworks/Structs/Server.cs
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Steamworks.Data
{
- public struct ServerInfo
+ public struct ServerInfo : IEquatable
{
public string Name { get; set; }
public int Ping { get; set; }
@@ -118,5 +118,15 @@ namespace Steamworks.Data
{
//Client.native.matchmaking.RemoveFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite );
}
+
+ public bool Equals( ServerInfo other )
+ {
+ return this.GetHashCode() == other.GetHashCode();
+ }
+
+ public override int GetHashCode()
+ {
+ return Address.GetHashCode() + SteamId.GetHashCode() + ConnectionPort.GetHashCode() + QueryPort.GetHashCode();
+ }
}
}
\ No newline at end of file