mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-03-30 22:29:04 +03:00
ServerList
This commit is contained in:
parent
1f0e34cf40
commit
41dfaeb2f7
@ -4,13 +4,14 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
namespace Facepunch.Steamworks.Test
|
namespace Steamworks
|
||||||
{
|
{
|
||||||
[TestClass]
|
[TestClass]
|
||||||
[DeploymentItem( "steam_api64.dll" )]
|
[DeploymentItem( "steam_api64.dll" )]
|
||||||
public partial class ServerList
|
public partial class ServerListTest
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void IpAddressConversions()
|
public void IpAddressConversions()
|
||||||
@ -30,440 +31,115 @@ namespace Facepunch.Steamworks.Test
|
|||||||
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void InternetList()
|
public async Task ServerListInternetInterupted()
|
||||||
{
|
{
|
||||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
using ( var list = new ServerListInternet() )
|
||||||
{
|
{
|
||||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
var task = list.RunQueryAsync();
|
||||||
filter.Add( "appid", client.AppId.ToString() );
|
|
||||||
filter.Add( "gamedir", "rust" );
|
await Task.Delay( 1000 );
|
||||||
filter.Add( "secure", "1" );
|
|
||||||
|
Console.WriteLine( $"Querying.." );
|
||||||
var query = client.ServerList.Internet( filter );
|
|
||||||
|
list.Cancel();
|
||||||
for ( int i = 0; i < 1000; i++ )
|
|
||||||
{
|
foreach ( var s in list.Responsive )
|
||||||
client.Update();
|
{
|
||||||
System.Threading.Thread.Sleep( 100 );
|
Console.WriteLine( $"{s.Address} {s.Name}" );
|
||||||
|
}
|
||||||
foreach ( var s in query.Responded )
|
|
||||||
{
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
Assert.AreEqual( s.AppId, client.AppId );
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
Assert.AreEqual( s.GameDir, "rust" );
|
Console.WriteLine( $"task.IsCompleted {task.IsCompleted}" );
|
||||||
}
|
|
||||||
|
}
|
||||||
if ( query.Finished )
|
}
|
||||||
break;
|
|
||||||
}
|
[TestMethod]
|
||||||
|
public async Task ServerListInternet()
|
||||||
Assert.IsTrue( query.Responded.Count > 0 );
|
{
|
||||||
|
using ( var list = new ServerListInternet() )
|
||||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
{
|
||||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
var success = await list.RunQueryAsync();
|
||||||
|
|
||||||
foreach ( var server in query.Responded.Take( 20 ) )
|
Console.WriteLine( $"success {success}" );
|
||||||
{
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
Console.WriteLine( "{0} {1}", server.Address, server.Name );
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
query.Dispose();
|
|
||||||
|
[TestMethod]
|
||||||
for ( int i = 0; i < 100; i++ )
|
public async Task ServerListLan()
|
||||||
{
|
{
|
||||||
client.Update();
|
using ( var list = new ServerListLan() )
|
||||||
System.Threading.Thread.Sleep( 1 );
|
{
|
||||||
}
|
var success = await list.RunQueryAsync();
|
||||||
}
|
|
||||||
}
|
Console.WriteLine( $"success {success}" );
|
||||||
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
[TestMethod]
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
public void MultipleInternetList()
|
}
|
||||||
{
|
}
|
||||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
|
||||||
{
|
[TestMethod]
|
||||||
var queries = new List<Facepunch.Steamworks.ServerList.Request>();
|
public async Task ServerListFavourites()
|
||||||
|
{
|
||||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
using ( var list = new ServerListFavourites() )
|
||||||
filter.Add( "map", "barren" );
|
{
|
||||||
|
var success = await list.RunQueryAsync();
|
||||||
for ( int i = 0; i < 10; i++ )
|
|
||||||
queries.Add( client.ServerList.Internet( filter ) );
|
Console.WriteLine( $"success {success}" );
|
||||||
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
for ( int i = 0; i < 100; i++ )
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
{
|
}
|
||||||
client.Update();
|
}
|
||||||
System.Threading.Thread.Sleep( 5 );
|
|
||||||
|
[TestMethod]
|
||||||
if ( queries.Any( x => x.Finished ) )
|
public async Task ServerListFriends()
|
||||||
break;
|
{
|
||||||
}
|
using ( var list = new ServerListFriends() )
|
||||||
|
{
|
||||||
foreach ( var query in queries )
|
var success = await list.RunQueryAsync();
|
||||||
{
|
|
||||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
Console.WriteLine( $"success {success}" );
|
||||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
client.Update();
|
}
|
||||||
query.Dispose();
|
}
|
||||||
client.Update();
|
|
||||||
}
|
[TestMethod]
|
||||||
}
|
public async Task ServerListHistory()
|
||||||
}
|
{
|
||||||
|
using ( var list = new ServerListHistory() )
|
||||||
[TestMethod]
|
{
|
||||||
public void Filters()
|
var success = await list.RunQueryAsync();
|
||||||
{
|
|
||||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
Console.WriteLine( $"success {success}" );
|
||||||
{
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
filter.Add( "map", "barren" );
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var query = client.ServerList.Internet( filter );
|
[TestMethod]
|
||||||
|
public async Task FilterByMap()
|
||||||
while ( true )
|
{
|
||||||
{
|
using ( var list = new ServerListInternet() )
|
||||||
client.Update();
|
{
|
||||||
System.Threading.Thread.Sleep( 2 );
|
list.AddFilter( "map", "de_dust" );
|
||||||
|
|
||||||
if ( query.Finished )
|
var success = await list.RunQueryAsync();
|
||||||
break;
|
|
||||||
}
|
Console.WriteLine( $"success {success}" );
|
||||||
|
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||||
foreach ( var x in query.Responded )
|
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||||
{
|
|
||||||
Assert.AreEqual( x.Map.ToLower(), "barren" );
|
foreach ( var server in list.Responsive )
|
||||||
}
|
{
|
||||||
|
Assert.AreEqual( server.Map.ToLower(), "de_dust" );
|
||||||
query.Dispose();
|
|
||||||
|
Console.WriteLine( $"[{server.Map}] - {server.Name}" );
|
||||||
for ( int i = 0; i < 100; i++ )
|
}
|
||||||
{
|
}
|
||||||
client.Update();
|
}
|
||||||
System.Threading.Thread.Sleep( 1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void HistoryList()
|
|
||||||
{
|
|
||||||
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.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 )
|
|
||||||
{
|
|
||||||
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 CustomList()
|
|
||||||
{
|
|
||||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
|
||||||
{
|
|
||||||
var servers = new List<string>();
|
|
||||||
|
|
||||||
servers.Add( "158.85.101.20:28015" );
|
|
||||||
servers.Add( "158.85.101.20:28022" );
|
|
||||||
servers.Add( "173.192.176.171:28615" );
|
|
||||||
servers.Add( "109.95.212.35:28215" );
|
|
||||||
servers.Add( "109.95.212.35:28115" );
|
|
||||||
servers.Add( "27.50.72.176:28015" );
|
|
||||||
servers.Add( "109.95.212.40:28015" );
|
|
||||||
servers.Add( "212.38.168.149:28215" );
|
|
||||||
servers.Add( "27.50.72.167:28215" );
|
|
||||||
servers.Add( "85.236.105.7:28215" );
|
|
||||||
servers.Add( "107.182.233.216:28215" );
|
|
||||||
servers.Add( "85.236.105.11:28215" );
|
|
||||||
servers.Add( "109.95.211.198:28215" );
|
|
||||||
servers.Add( "8.26.94.190:28015" );
|
|
||||||
servers.Add( "221.121.151.37:28215" );
|
|
||||||
servers.Add( "161.202.144.216:28215" );
|
|
||||||
servers.Add( "107.182.230.181:28215" );
|
|
||||||
servers.Add( "107.182.231.134:27101" );
|
|
||||||
servers.Add( "107.182.233.181:27101" );
|
|
||||||
servers.Add( "78.129.153.47:27101" );
|
|
||||||
servers.Add( "109.95.211.206:27101" );
|
|
||||||
servers.Add( "169.57.142.73:27101" );
|
|
||||||
servers.Add( "221.121.154.147:27101" );
|
|
||||||
servers.Add( "31.216.52.44:30015" );
|
|
||||||
servers.Add( "109.169.94.17:28215" );
|
|
||||||
servers.Add( "109.169.94.17:28315" );
|
|
||||||
servers.Add( "109.169.94.17:28015" );
|
|
||||||
servers.Add( "41.0.11.167:27141" );
|
|
||||||
servers.Add( "78.129.153.47:27131" );
|
|
||||||
servers.Add( "109.95.211.206:27111" );
|
|
||||||
servers.Add( "107.182.231.134:27111" );
|
|
||||||
servers.Add( "198.27.70.162:28015" );
|
|
||||||
servers.Add( "198.27.70.162:28215" );
|
|
||||||
servers.Add( "198.27.70.162:28115" );
|
|
||||||
servers.Add( "169.57.142.73:27111" );
|
|
||||||
servers.Add( "221.121.154.147:27111" );
|
|
||||||
servers.Add( "107.182.233.181:27111" );
|
|
||||||
servers.Add( "78.129.153.47:27111" );
|
|
||||||
servers.Add( "109.95.211.215:28015" );
|
|
||||||
servers.Add( "50.23.131.208:28015" );
|
|
||||||
servers.Add( "50.23.131.208:28115" );
|
|
||||||
servers.Add( "50.23.131.208:28215" );
|
|
||||||
servers.Add( "63.251.114.37:28215" );
|
|
||||||
servers.Add( "63.251.114.37:28115" );
|
|
||||||
servers.Add( "63.251.114.37:28015" );
|
|
||||||
servers.Add( "149.202.89.85:27101" );
|
|
||||||
servers.Add( "149.202.89.85:27111" );
|
|
||||||
servers.Add( "149.202.89.85:27131" );
|
|
||||||
servers.Add( "8.26.94.147:27101" );
|
|
||||||
servers.Add( "8.26.94.147:27111" );
|
|
||||||
servers.Add( "8.26.94.147:27121" );
|
|
||||||
servers.Add( "159.8.147.197:28025" );
|
|
||||||
servers.Add( "162.248.88.203:27038" );
|
|
||||||
servers.Add( "162.248.88.203:28091" );
|
|
||||||
servers.Add( "74.91.119.142:28069" );
|
|
||||||
servers.Add( "162.248.88.203:25063" );
|
|
||||||
servers.Add( "64.251.7.189:28115" );
|
|
||||||
servers.Add( "64.251.7.189:28015" );
|
|
||||||
servers.Add( "216.52.0.170:28215" );
|
|
||||||
servers.Add( "217.147.91.80:28215" );
|
|
||||||
servers.Add( "63.251.112.121:28215" );
|
|
||||||
servers.Add( "162.248.88.203:28074" );
|
|
||||||
servers.Add( "74.91.119.142:27095" );
|
|
||||||
servers.Add( "95.172.92.176:28065" );
|
|
||||||
servers.Add( "192.223.26.55:26032" );
|
|
||||||
servers.Add( "40.114.199.6:28085" );
|
|
||||||
servers.Add( "95.172.92.176:27095" );
|
|
||||||
servers.Add( "216.52.0.172:28015" );
|
|
||||||
servers.Add( "216.52.0.171:28115" );
|
|
||||||
servers.Add( "27.50.72.179:28015" );
|
|
||||||
servers.Add( "27.50.72.180:28115" );
|
|
||||||
servers.Add( "221.121.158.203:28015" );
|
|
||||||
servers.Add( "63.251.242.246:28015" );
|
|
||||||
servers.Add( "85.236.105.51:28015" );
|
|
||||||
servers.Add( "85.236.105.47:28015" );
|
|
||||||
servers.Add( "209.95.60.216:28015" );
|
|
||||||
servers.Add( "212.38.168.14:28015" );
|
|
||||||
servers.Add( "217.147.91.138:28015" );
|
|
||||||
servers.Add( "31.216.52.42:28015" );
|
|
||||||
servers.Add( "107.182.226.225:28015" );
|
|
||||||
servers.Add( "109.95.211.69:28015" );
|
|
||||||
servers.Add( "209.95.56.13:28015" );
|
|
||||||
servers.Add( "173.244.192.101:28015" );
|
|
||||||
servers.Add( "221.121.158.201:28115" );
|
|
||||||
servers.Add( "63.251.242.245:28115" );
|
|
||||||
servers.Add( "85.236.105.50:28115" );
|
|
||||||
servers.Add( "85.236.105.46:28115" );
|
|
||||||
servers.Add( "209.95.60.217:28115" );
|
|
||||||
servers.Add( "212.38.168.13:28115" );
|
|
||||||
servers.Add( "217.147.91.139:28115" );
|
|
||||||
servers.Add( "107.182.226.224:28115" );
|
|
||||||
servers.Add( "109.95.211.14:28115" );
|
|
||||||
servers.Add( "109.95.211.16:28115" );
|
|
||||||
servers.Add( "109.95.211.17:28115" );
|
|
||||||
servers.Add( "209.95.56.14:28115" );
|
|
||||||
servers.Add( "173.244.192.100:28115" );
|
|
||||||
servers.Add( "209.95.60.218:28215" );
|
|
||||||
servers.Add( "109.95.211.13:28215" );
|
|
||||||
servers.Add( "109.95.211.15:28215" );
|
|
||||||
servers.Add( "31.216.52.41:29015" );
|
|
||||||
|
|
||||||
var query = client.ServerList.Custom( servers );
|
|
||||||
|
|
||||||
for ( int i = 0; i < 1000; i++ )
|
|
||||||
{
|
|
||||||
client.Update();
|
|
||||||
System.Threading.Thread.Sleep( 20 );
|
|
||||||
|
|
||||||
if ( query.Finished )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
|
||||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
|
||||||
|
|
||||||
foreach ( var s in query.Responded )
|
|
||||||
{
|
|
||||||
Console.WriteLine( "{0} - {1}", s.Address, s.Name );
|
|
||||||
|
|
||||||
Assert.IsTrue( servers.Contains( $"{s.Address}:{s.QueryPort}" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
query.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void Rules()
|
|
||||||
{
|
|
||||||
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" );
|
|
||||||
|
|
||||||
filter.Add( "addr", "185.97.254.146" );
|
|
||||||
|
|
||||||
using ( var query = client.ServerList.Internet( filter ) )
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < 1000; i++ )
|
|
||||||
{
|
|
||||||
GC.Collect();
|
|
||||||
client.Update();
|
|
||||||
GC.Collect();
|
|
||||||
System.Threading.Thread.Sleep( 10 );
|
|
||||||
|
|
||||||
// if ( query.Responded.Count > 20 )
|
|
||||||
// break;
|
|
||||||
|
|
||||||
if ( query.Finished )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
query.Dispose();
|
|
||||||
|
|
||||||
var servers = query.Responded.Take( 100 );
|
|
||||||
|
|
||||||
foreach ( var server in servers )
|
|
||||||
{
|
|
||||||
server.FetchRules();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while ( !server.HasRules )
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
client.Update();
|
|
||||||
System.Threading.Thread.Sleep( 10 );
|
|
||||||
|
|
||||||
if ( i > 100 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( server.HasRules )
|
|
||||||
{
|
|
||||||
Console.WriteLine( "" );
|
|
||||||
Console.WriteLine( "" );
|
|
||||||
Console.WriteLine( server.Address );
|
|
||||||
Console.WriteLine( "" );
|
|
||||||
|
|
||||||
foreach ( var rule in server.Rules )
|
|
||||||
{
|
|
||||||
Console.WriteLine( rule.Key + " = " + rule.Value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine( "SERVER HAS NO RULES :(" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,13 +148,6 @@ namespace Facepunch.Steamworks
|
|||||||
{
|
{
|
||||||
CallResults[i].Try();
|
CallResults[i].Try();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// The SourceServerQuery's happen in another thread, so we
|
|
||||||
// query them to see if they're finished, and if so post a callback
|
|
||||||
// in our main thread. This will all suck less once we have async.
|
|
||||||
//
|
|
||||||
Facepunch.Steamworks.SourceServerQuery.Cycle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,232 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Facepunch.Steamworks
|
|
||||||
{
|
|
||||||
public partial class ServerList
|
|
||||||
{
|
|
||||||
public class Request : IDisposable
|
|
||||||
{
|
|
||||||
internal Client client;
|
|
||||||
|
|
||||||
internal List<SubRequest> Requests = new List<SubRequest>();
|
|
||||||
|
|
||||||
internal class SubRequest
|
|
||||||
{
|
|
||||||
internal IntPtr Request;
|
|
||||||
internal int Pointer = 0;
|
|
||||||
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 )
|
|
||||||
{
|
|
||||||
if ( Request == IntPtr.Zero )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if ( Timer.Elapsed.TotalSeconds < 0.5f )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Timer.Reset();
|
|
||||||
Timer.Start();
|
|
||||||
|
|
||||||
bool changes = false;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add any servers we're not watching to our watch list
|
|
||||||
//
|
|
||||||
var count = servers.GetServerCount( Request );
|
|
||||||
if ( count != Pointer )
|
|
||||||
{
|
|
||||||
for ( int i = Pointer; i < count; i++ )
|
|
||||||
{
|
|
||||||
WatchList.Add( i );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Pointer = count;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Remove any servers that respond successfully
|
|
||||||
//
|
|
||||||
WatchList.RemoveAll( x =>
|
|
||||||
{
|
|
||||||
var info = servers.GetServerDetails( Request, x );
|
|
||||||
if ( info.HadSuccessfulResponse )
|
|
||||||
{
|
|
||||||
OnServer( info );
|
|
||||||
changes = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} );
|
|
||||||
|
|
||||||
//
|
|
||||||
// If we've finished refreshing
|
|
||||||
//
|
|
||||||
if ( servers.IsRefreshing( Request ) == false )
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Put any other servers on the 'no response' list
|
|
||||||
//
|
|
||||||
WatchList.RemoveAll( x =>
|
|
||||||
{
|
|
||||||
var info = servers.GetServerDetails( Request, x );
|
|
||||||
OnServer( info );
|
|
||||||
return true;
|
|
||||||
} );
|
|
||||||
|
|
||||||
servers.CancelQuery( Request );
|
|
||||||
Request = IntPtr.Zero;
|
|
||||||
changes = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( changes && OnUpdate != null )
|
|
||||||
OnUpdate();
|
|
||||||
|
|
||||||
return Request == IntPtr.Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action OnUpdate;
|
|
||||||
public Action<Server> OnServerResponded;
|
|
||||||
public Action OnFinished;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of servers that responded. If you're only interested in servers that responded since you
|
|
||||||
/// last updated, then simply clear this list.
|
|
||||||
/// </summary>
|
|
||||||
public List<Server> Responded = new List<Server>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list of servers that were in the master list but didn't respond.
|
|
||||||
/// </summary>
|
|
||||||
public List<Server> Unresponsive = new List<Server>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True when we have finished
|
|
||||||
/// </summary>
|
|
||||||
public bool Finished = false;
|
|
||||||
|
|
||||||
internal Request( Client c )
|
|
||||||
{
|
|
||||||
client = c;
|
|
||||||
|
|
||||||
client.OnUpdate += Update;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Request()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerable<string> ServerList { get; set; }
|
|
||||||
internal Filter Filter { get; set; }
|
|
||||||
|
|
||||||
internal void StartCustomQuery()
|
|
||||||
{
|
|
||||||
if ( ServerList == null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
int blockSize = 16;
|
|
||||||
int Pointer = 0;
|
|
||||||
|
|
||||||
while ( true )
|
|
||||||
{
|
|
||||||
var sublist = ServerList.Skip( Pointer ).Take( blockSize );
|
|
||||||
|
|
||||||
if ( sublist.Count() == 0 )
|
|
||||||
break;
|
|
||||||
|
|
||||||
Pointer += sublist.Count();
|
|
||||||
|
|
||||||
var filter = new Filter();
|
|
||||||
filter.Add( "or", sublist.Count().ToString() );
|
|
||||||
|
|
||||||
foreach ( var server in sublist )
|
|
||||||
{
|
|
||||||
filter.Add( "gameaddr", server );
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.Start();
|
|
||||||
var id = client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, (uint)filter.Count, IntPtr.Zero );
|
|
||||||
filter.Free();
|
|
||||||
|
|
||||||
AddRequest( id );
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerList = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddRequest( IntPtr id )
|
|
||||||
{
|
|
||||||
Requests.Add( new SubRequest() { Request = id } );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
if ( Requests.Count == 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
for( int i=0; i< Requests.Count(); i++ )
|
|
||||||
{
|
|
||||||
if ( Requests[i].Update( client.native.servers, OnServer, OnUpdate ) )
|
|
||||||
{
|
|
||||||
Requests.RemoveAt( i );
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( Requests.Count == 0 )
|
|
||||||
{
|
|
||||||
Finished = true;
|
|
||||||
client.OnUpdate -= Update;
|
|
||||||
|
|
||||||
OnFinished?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnServer( SteamNative.gameserveritem_t info )
|
|
||||||
{
|
|
||||||
if ( info.HadSuccessfulResponse )
|
|
||||||
{
|
|
||||||
if ( Filter != null && !Filter.Test( info ) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
var s = Server.FromSteam( client, info );
|
|
||||||
Responded.Add( s );
|
|
||||||
|
|
||||||
OnServerResponded?.Invoke( s );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Unresponsive.Add( Server.FromSteam( client, info ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposing will end the query
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if ( client.IsValid )
|
|
||||||
client.OnUpdate -= Update;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Cancel the query if it's still running
|
|
||||||
//
|
|
||||||
foreach( var subRequest in Requests )
|
|
||||||
{
|
|
||||||
if ( client.IsValid )
|
|
||||||
client.native.servers.CancelQuery( subRequest.Request );
|
|
||||||
}
|
|
||||||
Requests.Clear();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Facepunch.Steamworks
|
|
||||||
{
|
|
||||||
public partial class ServerList
|
|
||||||
{
|
|
||||||
public class Server
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public int Ping { get; set; }
|
|
||||||
public string GameDir { get; set; }
|
|
||||||
public string Map { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public uint AppId { get; set; }
|
|
||||||
public int Players { get; set; }
|
|
||||||
public int MaxPlayers { get; set; }
|
|
||||||
public int BotPlayers { get; set; }
|
|
||||||
public bool Passworded { get; set; }
|
|
||||||
public bool Secure { get; set; }
|
|
||||||
public uint LastTimePlayed { get; set; }
|
|
||||||
public int Version { get; set; }
|
|
||||||
public string[] Tags { get; set; }
|
|
||||||
public ulong SteamId { get; set; }
|
|
||||||
public IPAddress Address { get; set; }
|
|
||||||
public int ConnectionPort { 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 static Server FromSteam( Client client, SteamNative.gameserveritem_t item )
|
|
||||||
{
|
|
||||||
return new Server()
|
|
||||||
{
|
|
||||||
Client = client,
|
|
||||||
Address = Utility.Int32ToIp( item.NetAdr.IP ),
|
|
||||||
ConnectionPort = item.NetAdr.ConnectionPort,
|
|
||||||
QueryPort = item.NetAdr.QueryPort,
|
|
||||||
Name = item.ServerName,
|
|
||||||
Ping = item.Ping,
|
|
||||||
GameDir = item.GameDir,
|
|
||||||
Map = item.Map,
|
|
||||||
Description = item.GameDescription,
|
|
||||||
AppId = item.AppID,
|
|
||||||
Players = item.Players,
|
|
||||||
MaxPlayers = item.MaxPlayers,
|
|
||||||
BotPlayers = item.BotPlayers,
|
|
||||||
Passworded = item.Password,
|
|
||||||
Secure = item.Secure,
|
|
||||||
LastTimePlayed = item.TimeLastPlayed,
|
|
||||||
Version = item.ServerVersion,
|
|
||||||
Tags = item.GameTags == null ? null : item.GameTags.Split( ',' ),
|
|
||||||
SteamId = item.SteamID
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Callback when rules are receieved.
|
|
||||||
/// The bool is true if server responded properly.
|
|
||||||
/// </summary>
|
|
||||||
public Action<bool> OnReceivedRules;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of server rules. Use HasRules to see if this is safe to access.
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, string> Rules;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns true if this server has rules
|
|
||||||
/// </summary>
|
|
||||||
public bool HasRules { get { return Rules != null && Rules.Count > 0; } }
|
|
||||||
|
|
||||||
internal SourceServerQuery RulesRequest;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Populates Rules for this server
|
|
||||||
/// </summary>
|
|
||||||
public void FetchRules()
|
|
||||||
{
|
|
||||||
if ( RulesRequest != null )
|
|
||||||
return;
|
|
||||||
|
|
||||||
Rules = null;
|
|
||||||
RulesRequest = new SourceServerQuery( this, Address, QueryPort );
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void OnServerRulesReceiveFinished( Dictionary<string, string> rules, bool Success )
|
|
||||||
{
|
|
||||||
RulesRequest = null;
|
|
||||||
|
|
||||||
if ( Success )
|
|
||||||
{
|
|
||||||
Rules = rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( OnReceivedRules != null )
|
|
||||||
{
|
|
||||||
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, Utility.IpToInt32( 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, Utility.IpToInt32( 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, Utility.IpToInt32( 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, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite );
|
|
||||||
Client.ServerList.UpdateFavouriteList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -41,11 +41,11 @@ namespace Facepunch.Steamworks
|
|||||||
encoded = encoded << 32;
|
encoded = encoded << 32;
|
||||||
encoded = encoded | (uint)conPort;
|
encoded = encoded | (uint)conPort;
|
||||||
|
|
||||||
if ( ( flags & Server.k_unFavoriteFlagFavorite ) == Server.k_unFavoriteFlagFavorite )
|
// if ( ( flags & Server.k_unFavoriteFlagFavorite ) == Server.k_unFavoriteFlagFavorite )
|
||||||
FavouriteHash.Add( encoded );
|
// FavouriteHash.Add( encoded );
|
||||||
|
|
||||||
if ( ( flags & Server.k_unFavoriteFlagFavorite ) == Server.k_unFavoriteFlagFavorite )
|
// if ( ( flags & Server.k_unFavoriteFlagFavorite ) == Server.k_unFavoriteFlagFavorite )
|
||||||
HistoryHash.Add( encoded );
|
// HistoryHash.Add( encoded );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +113,6 @@ namespace Facepunch.Steamworks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[StructLayout( LayoutKind.Sequential )]
|
[StructLayout( LayoutKind.Sequential )]
|
||||||
private struct MatchPair
|
private struct MatchPair
|
||||||
{
|
{
|
||||||
@ -123,145 +121,5 @@ namespace Facepunch.Steamworks
|
|||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
public string value;
|
public string value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Request Internet( Filter filter = null )
|
|
||||||
{
|
|
||||||
if ( filter == null )
|
|
||||||
{
|
|
||||||
filter = new Filter();
|
|
||||||
filter.Add( "appid", client.AppId.ToString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.Start();
|
|
||||||
|
|
||||||
var request = new Request( client );
|
|
||||||
request.Filter = filter;
|
|
||||||
request.AddRequest( client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, (uint) filter.Count, IntPtr.Zero ) );
|
|
||||||
|
|
||||||
filter.Free();
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Query a list of addresses. No filters applied.
|
|
||||||
/// </summary>
|
|
||||||
public Request Custom( IEnumerable<string> serverList )
|
|
||||||
{
|
|
||||||
var request = new Request( client );
|
|
||||||
request.ServerList = serverList;
|
|
||||||
request.StartCustomQuery();
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request a list of servers we've been on. History isn't applied automatically
|
|
||||||
/// You need to call server.AddtoHistoryList() when you join a server etc.
|
|
||||||
/// </summary>
|
|
||||||
public Request History( Filter filter = null )
|
|
||||||
{
|
|
||||||
if ( filter == null )
|
|
||||||
{
|
|
||||||
filter = new Filter();
|
|
||||||
filter.Add( "appid", client.AppId.ToString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.Start();
|
|
||||||
|
|
||||||
var request = new Request( client );
|
|
||||||
request.Filter = filter;
|
|
||||||
request.AddRequest( client.native.servers.RequestHistoryServerList( client.AppId, filter.NativeArray, (uint)filter.Count, IntPtr.Zero ) );
|
|
||||||
|
|
||||||
filter.Free();
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request a list of servers we've favourited
|
|
||||||
/// </summary>
|
|
||||||
public Request Favourites( Filter filter = null )
|
|
||||||
{
|
|
||||||
if ( filter == null )
|
|
||||||
{
|
|
||||||
filter = new Filter();
|
|
||||||
filter.Add( "appid", client.AppId.ToString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.Start();
|
|
||||||
|
|
||||||
var request = new Request( client );
|
|
||||||
request.Filter = filter;
|
|
||||||
request.AddRequest( client.native.servers.RequestFavoritesServerList( client.AppId, filter.NativeArray, (uint)filter.Count, IntPtr.Zero ) );
|
|
||||||
|
|
||||||
filter.Free();
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request a list of servers that our friends are on
|
|
||||||
/// </summary>
|
|
||||||
public Request Friends( Filter filter = null )
|
|
||||||
{
|
|
||||||
if ( filter == null )
|
|
||||||
{
|
|
||||||
filter = new Filter();
|
|
||||||
filter.Add( "appid", client.AppId.ToString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request a list of servers that are running on our LAN
|
|
||||||
/// </summary>
|
|
||||||
public Request Local( Filter filter = null )
|
|
||||||
{
|
|
||||||
if ( filter == null )
|
|
||||||
{
|
|
||||||
filter = new Filter();
|
|
||||||
filter.Add( "appid", client.AppId.ToString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.Start();
|
|
||||||
|
|
||||||
var request = new Request( client );
|
|
||||||
request.Filter = filter;
|
|
||||||
request.AddRequest( client.native.servers.RequestLANServerList( client.AppId, IntPtr.Zero ) );
|
|
||||||
|
|
||||||
filter.Free();
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal bool IsFavourite( Server server )
|
|
||||||
{
|
|
||||||
ulong encoded = Utility.IpToInt32( server.Address );
|
|
||||||
encoded = encoded << 32;
|
|
||||||
encoded = encoded | (uint)server.ConnectionPort;
|
|
||||||
|
|
||||||
return FavouriteHash.Contains( encoded );
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool IsHistory( Server server )
|
|
||||||
{
|
|
||||||
ulong encoded = Utility.IpToInt32( server.Address );
|
|
||||||
encoded = encoded << 32;
|
|
||||||
encoded = encoded | (uint)server.ConnectionPort;
|
|
||||||
|
|
||||||
return HistoryHash.Contains( encoded );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,13 +111,13 @@ namespace Steamworks.Internal
|
|||||||
|
|
||||||
#region FunctionMeta
|
#region FunctionMeta
|
||||||
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
|
||||||
public delegate gameserveritem_t GetServerDetailsDelegate( IntPtr self, HServerListRequest hRequest, int iServer );
|
public delegate IntPtr GetServerDetailsDelegate( IntPtr self, HServerListRequest hRequest, int iServer );
|
||||||
private GetServerDetailsDelegate GetServerDetailsDelegatePointer;
|
private GetServerDetailsDelegate GetServerDetailsDelegatePointer;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
public gameserveritem_t GetServerDetails( HServerListRequest hRequest, int iServer )
|
public gameserveritem_t GetServerDetails( HServerListRequest hRequest, int iServer )
|
||||||
{
|
{
|
||||||
return GetServerDetailsDelegatePointer( Self, hRequest, iServer );
|
return new gameserveritem_t().Fill( GetServerDetailsDelegatePointer( Self, hRequest, iServer ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
#region FunctionMeta
|
#region FunctionMeta
|
||||||
|
@ -22,4 +22,6 @@ public static class SteamApi
|
|||||||
[DllImport( "Steam_api64", EntryPoint = "SteamAPI_UnregisterCallback", CallingConvention = CallingConvention.Cdecl )]
|
[DllImport( "Steam_api64", EntryPoint = "SteamAPI_UnregisterCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||||
public static extern int UnregisterCallback( IntPtr pCallback );
|
public static extern int UnregisterCallback( IntPtr pCallback );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
199
Facepunch.Steamworks/Redux/ServerList/BaseServerList.cs
Normal file
199
Facepunch.Steamworks/Redux/ServerList/BaseServerList.cs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not for reuse by newbs
|
||||||
|
/// </summary>
|
||||||
|
public abstract class BaseServerList : IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
#region ISteamMatchmakingServers
|
||||||
|
|
||||||
|
static Internal.ISteamMatchmakingServers _internal;
|
||||||
|
internal static Internal.ISteamMatchmakingServers Internal
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ( _internal == null )
|
||||||
|
_internal = new Internal.ISteamMatchmakingServers();
|
||||||
|
|
||||||
|
return _internal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Which app we're querying. Defaults to the current app.
|
||||||
|
/// </summary>
|
||||||
|
public AppId AppId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When a new server is added, this function will get called
|
||||||
|
/// </summary>
|
||||||
|
public event Action OnChanges;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called for every responsive server
|
||||||
|
/// </summary>
|
||||||
|
public event Action<ServerInfo> OnResponsiveServer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of servers that responded. If you're only interested in servers that responded since you
|
||||||
|
/// last updated, then simply clear this list.
|
||||||
|
/// </summary>
|
||||||
|
public List<ServerInfo> Responsive = new List<ServerInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of servers that were in the master list but didn't respond.
|
||||||
|
/// </summary>
|
||||||
|
public List<ServerInfo> Unresponsive = new List<ServerInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
public BaseServerList()
|
||||||
|
{
|
||||||
|
AppId = Utils.AppId; // Default AppId is this
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query the server list. Task result will be true when finished
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<bool> RunQueryAsync()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
LaunchQuery();
|
||||||
|
|
||||||
|
var thisRequest = request;
|
||||||
|
|
||||||
|
while ( IsRefreshing )
|
||||||
|
{
|
||||||
|
await Task.Delay( 33 );
|
||||||
|
|
||||||
|
//
|
||||||
|
// The request has been cancelled or changed in some way
|
||||||
|
//
|
||||||
|
if ( request == IntPtr.Zero || thisRequest.Value != request.Value )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var r = Responsive.Count;
|
||||||
|
|
||||||
|
UpdatePending();
|
||||||
|
UpdateResponsive();
|
||||||
|
|
||||||
|
if ( r != Responsive.Count )
|
||||||
|
{
|
||||||
|
OnChanges?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MovePendingToUnresponsive();
|
||||||
|
OnChanges?.Invoke();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cancel() => Internal.CancelQuery( request );
|
||||||
|
|
||||||
|
// Overrides
|
||||||
|
internal abstract void LaunchQuery();
|
||||||
|
|
||||||
|
protected HServerListRequest request;
|
||||||
|
|
||||||
|
#region Filters
|
||||||
|
|
||||||
|
internal List<MatchMakingKeyValuePair_t> filters = new List<MatchMakingKeyValuePair_t>();
|
||||||
|
internal MatchMakingKeyValuePair_t[] GetFilters() => filters.ToArray();
|
||||||
|
|
||||||
|
public void AddFilter( string key, string value )
|
||||||
|
{
|
||||||
|
filters.Add( new MatchMakingKeyValuePair_t { Key = key, Value = value } );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
internal int Count => Internal.GetServerCount( request );
|
||||||
|
internal bool IsRefreshing => request != IntPtr.Zero && Internal.IsRefreshing( request );
|
||||||
|
internal List<int> watchList = new List<int>();
|
||||||
|
internal int LastCount = 0;
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
ReleaseQuery();
|
||||||
|
LastCount = 0;
|
||||||
|
watchList.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseQuery()
|
||||||
|
{
|
||||||
|
if ( request.Value != IntPtr.Zero )
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
Internal.ReleaseRequest( request );
|
||||||
|
request = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ReleaseQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatePending()
|
||||||
|
{
|
||||||
|
var count = Count;
|
||||||
|
if ( count == LastCount ) return;
|
||||||
|
|
||||||
|
for ( int i = LastCount; i < count; i++ )
|
||||||
|
{
|
||||||
|
watchList.Add( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
LastCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateResponsive()
|
||||||
|
{
|
||||||
|
watchList.RemoveAll( x =>
|
||||||
|
{
|
||||||
|
var info = Internal.GetServerDetails( request, x );
|
||||||
|
if ( info.HadSuccessfulResponse )
|
||||||
|
{
|
||||||
|
OnServer( ServerInfo.From( info ), info.HadSuccessfulResponse );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovePendingToUnresponsive()
|
||||||
|
{
|
||||||
|
watchList.RemoveAll( x =>
|
||||||
|
{
|
||||||
|
var info = Internal.GetServerDetails( request, x );
|
||||||
|
OnServer( ServerInfo.From( info ), info.HadSuccessfulResponse );
|
||||||
|
return true;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnServer( ServerInfo serverInfo, bool responded )
|
||||||
|
{
|
||||||
|
if ( responded )
|
||||||
|
{
|
||||||
|
Responsive.Add( serverInfo );
|
||||||
|
OnResponsiveServer?.Invoke( serverInfo );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unresponsive.Add( serverInfo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not for reuse by newbs
|
||||||
|
/// </summary>
|
||||||
|
public class ServerListFavourites : BaseServerList
|
||||||
|
{
|
||||||
|
internal override void LaunchQuery()
|
||||||
|
{
|
||||||
|
var filters = GetFilters();
|
||||||
|
request = Internal.RequestFavoritesServerList( AppId.Value, filters, (uint)filters.Length, IntPtr.Zero );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
Facepunch.Steamworks/Redux/ServerList/ServerListFriends.cs
Normal file
21
Facepunch.Steamworks/Redux/ServerList/ServerListFriends.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not for reuse by newbs
|
||||||
|
/// </summary>
|
||||||
|
public class ServerListFriends : BaseServerList
|
||||||
|
{
|
||||||
|
internal override void LaunchQuery()
|
||||||
|
{
|
||||||
|
var filters = GetFilters();
|
||||||
|
request = Internal.RequestFriendsServerList( AppId.Value, filters, (uint)filters.Length, IntPtr.Zero );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
Facepunch.Steamworks/Redux/ServerList/ServerListHistory.cs
Normal file
21
Facepunch.Steamworks/Redux/ServerList/ServerListHistory.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not for reuse by newbs
|
||||||
|
/// </summary>
|
||||||
|
public class ServerListHistory : BaseServerList
|
||||||
|
{
|
||||||
|
internal override void LaunchQuery()
|
||||||
|
{
|
||||||
|
var filters = GetFilters();
|
||||||
|
request = Internal.RequestHistoryServerList( AppId.Value, filters, (uint)filters.Length, IntPtr.Zero );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
Facepunch.Steamworks/Redux/ServerList/ServerListInternet.cs
Normal file
22
Facepunch.Steamworks/Redux/ServerList/ServerListInternet.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not for reuse by newbs
|
||||||
|
/// </summary>
|
||||||
|
public class ServerListInternet : BaseServerList
|
||||||
|
{
|
||||||
|
internal override void LaunchQuery()
|
||||||
|
{
|
||||||
|
var filters = GetFilters();
|
||||||
|
|
||||||
|
request = Internal.RequestInternetServerList( AppId.Value, filters, (uint)filters.Length, IntPtr.Zero );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
Facepunch.Steamworks/Redux/ServerList/ServerListLan.cs
Normal file
20
Facepunch.Steamworks/Redux/ServerList/ServerListLan.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not for reuse by newbs
|
||||||
|
/// </summary>
|
||||||
|
public class ServerListLan : BaseServerList
|
||||||
|
{
|
||||||
|
internal override void LaunchQuery()
|
||||||
|
{
|
||||||
|
request = Internal.RequestLANServerList( AppId.Value, IntPtr.Zero );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
Facepunch.Steamworks/Redux/ServerList/ServerListSpectator.cs
Normal file
20
Facepunch.Steamworks/Redux/ServerList/ServerListSpectator.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SteamNative;
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
public class ServerListSpectator : BaseServerList
|
||||||
|
{
|
||||||
|
internal override void LaunchQuery()
|
||||||
|
{
|
||||||
|
var filters = GetFilters();
|
||||||
|
request = Internal.RequestSpectatorServerList( AppId.Value, filters, (uint)filters.Length, IntPtr.Zero );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
@ -37,6 +37,24 @@ namespace Steamworks
|
|||||||
Music.InstallEvents();
|
Music.InstallEvents();
|
||||||
Video.InstallEvents();
|
Video.InstallEvents();
|
||||||
User.InstallEvents();
|
User.InstallEvents();
|
||||||
|
|
||||||
|
RunCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async void RunCallbacks()
|
||||||
|
{
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
await Task.Delay( 16 );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SteamApi.RunCallbacks();
|
||||||
|
}
|
||||||
|
catch ( System.Exception )
|
||||||
|
{
|
||||||
|
// TODO - error outputs
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RegisterCallback( IntPtr intPtr, int callbackId )
|
internal static void RegisterCallback( IntPtr intPtr, int callbackId )
|
||||||
@ -44,6 +62,11 @@ namespace Steamworks
|
|||||||
SteamApi.RegisterCallback( intPtr, callbackId );
|
SteamApi.RegisterCallback( intPtr, callbackId );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Update()
|
||||||
|
{
|
||||||
|
SteamApi.RunCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
internal static void UnregisterCallback( IntPtr intPtr )
|
internal static void UnregisterCallback( IntPtr intPtr )
|
||||||
{
|
{
|
||||||
SteamApi.UnregisterCallback( intPtr );
|
SteamApi.UnregisterCallback( intPtr );
|
||||||
|
94
Facepunch.Steamworks/Redux/Structs/Server.cs
Normal file
94
Facepunch.Steamworks/Redux/Structs/Server.cs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
using Facepunch.Steamworks;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Steamworks
|
||||||
|
{
|
||||||
|
public struct ServerInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Ping { get; set; }
|
||||||
|
public string GameDir { get; set; }
|
||||||
|
public string Map { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public uint AppId { get; set; }
|
||||||
|
public int Players { get; set; }
|
||||||
|
public int MaxPlayers { get; set; }
|
||||||
|
public int BotPlayers { get; set; }
|
||||||
|
public bool Passworded { get; set; }
|
||||||
|
public bool Secure { get; set; }
|
||||||
|
public uint LastTimePlayed { get; set; }
|
||||||
|
public int Version { get; set; }
|
||||||
|
public string Tags { get; set; }
|
||||||
|
public ulong SteamId { get; set; }
|
||||||
|
public IPAddress Address { get; set; }
|
||||||
|
public int ConnectionPort { get; set; }
|
||||||
|
public int QueryPort { get; set; }
|
||||||
|
|
||||||
|
internal static ServerInfo From( SteamNative.gameserveritem_t item )
|
||||||
|
{
|
||||||
|
return new ServerInfo()
|
||||||
|
{
|
||||||
|
Address = Utility.Int32ToIp( item.NetAdr.IP ),
|
||||||
|
ConnectionPort = item.NetAdr.ConnectionPort,
|
||||||
|
QueryPort = item.NetAdr.QueryPort,
|
||||||
|
Name = item.ServerName,
|
||||||
|
Ping = item.Ping,
|
||||||
|
GameDir = item.GameDir,
|
||||||
|
Map = item.Map,
|
||||||
|
Description = item.GameDescription,
|
||||||
|
AppId = item.AppID,
|
||||||
|
Players = item.Players,
|
||||||
|
MaxPlayers = item.MaxPlayers,
|
||||||
|
BotPlayers = item.BotPlayers,
|
||||||
|
Passworded = item.Password,
|
||||||
|
Secure = item.Secure,
|
||||||
|
LastTimePlayed = item.TimeLastPlayed,
|
||||||
|
Version = item.ServerVersion,
|
||||||
|
Tags = item.GameTags,
|
||||||
|
SteamId = item.SteamID
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory, (uint)Utility.Epoch.Current );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove this server from our history list
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveFromHistory()
|
||||||
|
{
|
||||||
|
//Client.native.matchmaking.RemoveFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagHistory );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add this server to our favourite list
|
||||||
|
/// </summary>
|
||||||
|
public void AddToFavourites()
|
||||||
|
{
|
||||||
|
//Client.native.matchmaking.AddFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite, (uint)Utility.Epoch.Current );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove this server from our favourite list
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveFromFavourites()
|
||||||
|
{
|
||||||
|
//Client.native.matchmaking.RemoveFavoriteGame( AppId, Utility.IpToInt32( Address ), (ushort)ConnectionPort, (ushort)QueryPort, k_unFavoriteFlagFavorite );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,206 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace Facepunch.Steamworks
|
|
||||||
{
|
|
||||||
|
|
||||||
internal class SourceServerQuery : IDisposable
|
|
||||||
{
|
|
||||||
public static List<SourceServerQuery> Current = new List<SourceServerQuery>();
|
|
||||||
|
|
||||||
public static void Cycle()
|
|
||||||
{
|
|
||||||
if ( Current.Count == 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
for( int i = Current.Count; i>0; i-- )
|
|
||||||
{
|
|
||||||
Current[i-1].Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly byte[] A2S_SERVERQUERY_GETCHALLENGE = { 0x55, 0xFF, 0xFF, 0xFF, 0xFF };
|
|
||||||
// private static readonly byte A2S_PLAYER = 0x55;
|
|
||||||
private static readonly byte A2S_RULES = 0x56;
|
|
||||||
|
|
||||||
public volatile bool IsRunning;
|
|
||||||
public volatile bool IsSuccessful;
|
|
||||||
|
|
||||||
private ServerList.Server Server;
|
|
||||||
private UdpClient udpClient;
|
|
||||||
private IPEndPoint endPoint;
|
|
||||||
private System.Threading.Thread thread;
|
|
||||||
private byte[] _challengeBytes;
|
|
||||||
|
|
||||||
private Dictionary<string, string> rules = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
public SourceServerQuery( ServerList.Server server, IPAddress address, int queryPort )
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
endPoint = new IPEndPoint( address, queryPort );
|
|
||||||
|
|
||||||
Current.Add( this );
|
|
||||||
|
|
||||||
IsRunning = true;
|
|
||||||
IsSuccessful = false;
|
|
||||||
thread = new System.Threading.Thread( ThreadedStart );
|
|
||||||
thread.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
if ( !IsRunning )
|
|
||||||
{
|
|
||||||
Current.Remove( this );
|
|
||||||
Server.OnServerRulesReceiveFinished( rules, IsSuccessful );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThreadedStart( object obj )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using ( udpClient = new UdpClient() )
|
|
||||||
{
|
|
||||||
udpClient.Client.SendTimeout = 3000;
|
|
||||||
udpClient.Client.ReceiveTimeout = 3000;
|
|
||||||
udpClient.Connect( endPoint );
|
|
||||||
|
|
||||||
GetRules();
|
|
||||||
|
|
||||||
IsSuccessful = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( System.Exception )
|
|
||||||
{
|
|
||||||
IsSuccessful = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
udpClient = null;
|
|
||||||
IsRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetRules()
|
|
||||||
{
|
|
||||||
GetChallengeData();
|
|
||||||
|
|
||||||
_challengeBytes[0] = A2S_RULES;
|
|
||||||
Send( _challengeBytes );
|
|
||||||
var ruleData = Receive();
|
|
||||||
|
|
||||||
using ( var br = new BinaryReader( new MemoryStream( ruleData ) ) )
|
|
||||||
{
|
|
||||||
if ( br.ReadByte() != 0x45 )
|
|
||||||
throw new Exception( "Invalid data received in response to A2S_RULES request" );
|
|
||||||
|
|
||||||
var numRules = br.ReadUInt16();
|
|
||||||
for ( int index = 0; index < numRules; index++ )
|
|
||||||
{
|
|
||||||
rules.Add( br.ReadNullTerminatedUTF8String( readBuffer ), br.ReadNullTerminatedUTF8String( readBuffer ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] readBuffer = new byte[1024 * 4];
|
|
||||||
|
|
||||||
private byte[] Receive()
|
|
||||||
{
|
|
||||||
byte[][] packets = null;
|
|
||||||
byte packetNumber = 0, packetCount = 1;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var result = udpClient.Receive( ref endPoint );
|
|
||||||
|
|
||||||
using ( var br = new BinaryReader( new MemoryStream( result ) ) )
|
|
||||||
{
|
|
||||||
var header = br.ReadInt32();
|
|
||||||
|
|
||||||
if ( header == -1 )
|
|
||||||
{
|
|
||||||
var unsplitdata = new byte[result.Length - br.BaseStream.Position];
|
|
||||||
Buffer.BlockCopy( result, (int)br.BaseStream.Position, unsplitdata, 0, unsplitdata.Length );
|
|
||||||
return unsplitdata;
|
|
||||||
}
|
|
||||||
else if ( header == -2 )
|
|
||||||
{
|
|
||||||
int requestId = br.ReadInt32();
|
|
||||||
packetNumber = br.ReadByte();
|
|
||||||
packetCount = br.ReadByte();
|
|
||||||
int splitSize = br.ReadInt32();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new System.Exception( "Invalid Header" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( packets == null ) packets = new byte[packetCount][];
|
|
||||||
|
|
||||||
var data = new byte[result.Length - br.BaseStream.Position];
|
|
||||||
Buffer.BlockCopy( result, (int)br.BaseStream.Position, data, 0, data.Length );
|
|
||||||
packets[packetNumber] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ( packets.Any( p => p == null ) );
|
|
||||||
|
|
||||||
var combinedData = Combine( packets );
|
|
||||||
return combinedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GetChallengeData()
|
|
||||||
{
|
|
||||||
if ( _challengeBytes != null ) return;
|
|
||||||
|
|
||||||
Send( A2S_SERVERQUERY_GETCHALLENGE );
|
|
||||||
|
|
||||||
var challengeData = Receive();
|
|
||||||
|
|
||||||
if ( challengeData[0] != 0x41 )
|
|
||||||
throw new Exception( "Invalid Challenge" );
|
|
||||||
|
|
||||||
_challengeBytes = challengeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] sendBuffer = new byte[1024];
|
|
||||||
|
|
||||||
private void Send( byte[] message )
|
|
||||||
{
|
|
||||||
sendBuffer[0] = 0xFF;
|
|
||||||
sendBuffer[1] = 0xFF;
|
|
||||||
sendBuffer[2] = 0xFF;
|
|
||||||
sendBuffer[3] = 0xFF;
|
|
||||||
|
|
||||||
Buffer.BlockCopy( message, 0, sendBuffer, 4, message.Length );
|
|
||||||
|
|
||||||
udpClient.Send( sendBuffer, message.Length + 4 );
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] Combine( byte[][] arrays )
|
|
||||||
{
|
|
||||||
var rv = new byte[arrays.Sum( a => a.Length )];
|
|
||||||
int offset = 0;
|
|
||||||
foreach ( byte[] array in arrays )
|
|
||||||
{
|
|
||||||
Buffer.BlockCopy( array, 0, rv, offset, array.Length );
|
|
||||||
offset += array.Length;
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if ( thread != null && thread.IsAlive )
|
|
||||||
{
|
|
||||||
thread.Abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
thread = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -69,6 +69,18 @@ internal class StructType : BaseType
|
|||||||
public string StructName;
|
public string StructName;
|
||||||
|
|
||||||
public override string TypeName => StructName;
|
public override string TypeName => StructName;
|
||||||
|
|
||||||
|
public override string TypeNameFrom => NativeType.EndsWith( "*" ) ? "IntPtr" : base.ReturnType;
|
||||||
|
|
||||||
|
public override string Return( string varname )
|
||||||
|
{
|
||||||
|
if ( NativeType.EndsWith( "*" ) )
|
||||||
|
{
|
||||||
|
return $"return new {TypeName}().Fill( {varname} );";
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.Return( varname );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class SteamApiCallType : BaseType
|
internal class SteamApiCallType : BaseType
|
||||||
|
Loading…
x
Reference in New Issue
Block a user