mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-16 02:09:20 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
164 lines
3.7 KiB
C#
164 lines
3.7 KiB
C#
using Sandbox.Engine;
|
|
using System.Net;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Sandbox.Services;
|
|
|
|
public class ServerList : List<ServerList.Entry>, IDisposable, IWeakInteropHandle
|
|
{
|
|
CServerList serverlist;
|
|
|
|
public ServerList()
|
|
{
|
|
Sandbox.InteropSystem.AllocWeak( this );
|
|
|
|
serverlist = CServerList.Create( this );
|
|
serverlist.AddFilter( "gametagsand", $"protocol:{Protocol.Network}" );
|
|
}
|
|
|
|
~ServerList()
|
|
{
|
|
Dispose();
|
|
}
|
|
|
|
public bool IsQuerying { get; private set; }
|
|
uint IWeakInteropHandle.InteropHandle { get; set; }
|
|
|
|
public void Query()
|
|
{
|
|
serverlist.StartQuery();
|
|
}
|
|
|
|
public void AddFilter( string key, string value )
|
|
{
|
|
serverlist.AddFilter( key, value );
|
|
}
|
|
|
|
internal unsafe void OnServerResponded( IntPtr ptr, ulong steamid )
|
|
{
|
|
var item = Unsafe.Read<gameserveritem_t>( (void*)ptr );
|
|
var tags = Marshal.PtrToStringUTF8( (IntPtr)item.m_szGameTags );
|
|
var ipAddress = new IPAddress( BitConverter.GetBytes( IPAddress.HostToNetworkOrder( (int)item.m_unIP ) ) ).ToString();
|
|
|
|
var entry = new Entry
|
|
{
|
|
IPAddressAndPort = $"{ipAddress}:{item.m_usConnectionPort}",
|
|
SteamId = steamid,
|
|
Map = Marshal.PtrToStringUTF8( (IntPtr)item.m_szMap ),
|
|
Name = Marshal.PtrToStringUTF8( (IntPtr)item.m_szServerName ),
|
|
Players = item.m_nPlayers,
|
|
MaxPlayers = item.m_nMaxPlayers - item.m_nBotPlayers,
|
|
Ping = item.m_nPing,
|
|
Game = Marshal.PtrToStringUTF8( (IntPtr)item.m_szGameDescription ),
|
|
Tick = 0
|
|
};
|
|
|
|
var tagParts = tags.Split( "," ).ToList();
|
|
|
|
foreach ( var tag in tagParts.ToArray() )
|
|
{
|
|
if ( !tag.Contains( ':' ) ) continue;
|
|
var parts = tag.Split( ':' );
|
|
if ( parts.Length != 2 ) continue;
|
|
|
|
switch ( parts[0] )
|
|
{
|
|
case "game":
|
|
entry.Game = parts[1].ToLower();
|
|
break;
|
|
|
|
case "gameversion":
|
|
if ( int.TryParse( parts[1], out var x ) )
|
|
entry.GameVersion = x;
|
|
break;
|
|
|
|
case "tick":
|
|
if ( int.TryParse( parts[1], out var i ) )
|
|
entry.Tick = i;
|
|
break;
|
|
|
|
default:
|
|
continue;
|
|
|
|
}
|
|
|
|
tagParts.Remove( tag );
|
|
}
|
|
|
|
entry.Tags = tagParts.ToArray();
|
|
|
|
Add( entry );
|
|
}
|
|
|
|
internal void OnFinished()
|
|
{
|
|
IsQuerying = false;
|
|
}
|
|
|
|
internal void OnStarted()
|
|
{
|
|
Clear();
|
|
IsQuerying = true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
serverlist.Destroy();
|
|
serverlist = default;
|
|
|
|
InteropSystem.Free( this );
|
|
GC.SuppressFinalize( this );
|
|
}
|
|
|
|
/// <summary>
|
|
/// This is a cleaned up version of gameserveritem_t.
|
|
/// </summary>
|
|
public struct Entry
|
|
{
|
|
public string IPAddressAndPort { get; set; }
|
|
public ulong SteamId { get; set; }
|
|
public string Map { get; set; }
|
|
public string Game { get; set; }
|
|
public int GameVersion { get; set; }
|
|
public string Name { get; set; }
|
|
public string[] Tags { get; set; }
|
|
public int Players { get; set; }
|
|
public int MaxPlayers { get; set; }
|
|
public int Ping { get; set; }
|
|
public int Tick { get; set; }
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Data from c++
|
|
/// We skip the steamid because there's some class padding fuckery going on.
|
|
/// We pass that in manually to make life easier.
|
|
/// </summary>
|
|
internal unsafe struct gameserveritem_t
|
|
{
|
|
#pragma warning disable 0649
|
|
public ushort m_usConnectionPort;
|
|
public ushort m_usQueryPort;
|
|
public uint m_unIP;
|
|
public int m_nPing;
|
|
|
|
public byte m_bHadSuccessfulResponse;
|
|
public byte m_bDoNotRefresh;
|
|
public fixed byte m_szGameDir[32];
|
|
public fixed byte m_szMap[32];
|
|
public fixed byte m_szGameDescription[64];
|
|
public uint m_nAppID;
|
|
public int m_nPlayers;
|
|
public int m_nMaxPlayers;
|
|
public int m_nBotPlayers;
|
|
public byte m_bPassword;
|
|
public byte m_bSecure;
|
|
public uint m_ulTimeLastPlayed;
|
|
public int m_nServerVersion;
|
|
public fixed byte m_szServerName[64];
|
|
public fixed byte m_szGameTags[128];
|
|
#pragma warning restore 0649
|
|
};
|