Fix serverlist query allocating a large amount of memory when a large amount of servers are pending

This commit is contained in:
Jake Rich 2024-08-12 20:46:16 -04:00
parent 4463739be5
commit d18086a1b8
3 changed files with 33 additions and 7 deletions

View File

@ -106,7 +106,24 @@ namespace Steamworks
var returnValue = _GetServerDetails( Self, hRequest, iServer );
return returnValue.ToType<gameserveritem_t>();
}
/// <summary>
/// Read gameserveritem_t.m_bHadSuccessfulResponse without allocating the struct on the heap
/// </summary>
/// <param name="hRequest"></param>
/// <param name="iServer"></param>
/// <returns></returns>
internal bool HasServerResponded( HServerListRequest hRequest, int iServer )
{
IntPtr returnValue = _GetServerDetails( Self, hRequest, iServer );
// Return false if steam returned null
if ( returnValue == IntPtr.Zero ) return false;
// first 8 bytes is IPAddress, next 4 bytes is ping, next 1 byte is m_bHadSuccessfulResponse
return Marshal.ReadByte( IntPtr.Add( returnValue, 12 ) ) == 1;
}
#region FunctionMeta
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ISteamMatchmakingServers_CancelQuery", CallingConvention = Platform.CC)]
private static extern void _CancelQuery( IntPtr self, HServerListRequest hRequest );

View File

@ -25,14 +25,17 @@ namespace Steamworks.Data
internal uint IP; // m_unIP uint32
}
[StructLayout( LayoutKind.Sequential, Pack = Platform.StructPackSize )]
internal partial struct gameserveritem_t
{
internal servernetadr_t NetAdr; // m_NetAdr servernetadr_t
internal int Ping; // m_nPing int
// NOTE: If you add fields above this you must change offset inISteamMatchmakingServers.HasServerResponded()
[MarshalAs(UnmanagedType.I1)]
internal bool HadSuccessfulResponse; // m_bHadSuccessfulResponse bool
[MarshalAs(UnmanagedType.I1)]
internal bool DoNotRefresh; // m_bDoNotRefresh bool
internal string GameDirUTF8() => System.Text.Encoding.UTF8.GetString( GameDir, 0, System.Array.IndexOf<byte>( GameDir, 0 ) );

View File

@ -161,11 +161,17 @@ namespace Steamworks.ServerList
{
watchList.RemoveAll( x =>
{
var info = Internal.GetServerDetails( request, x );
if ( info.HadSuccessfulResponse )
// First check if the server has responded without allocating server info
bool hasResponded = Internal.HasServerResponded( request, x );
if ( hasResponded )
{
OnServer( ServerInfo.From( info ), info.HadSuccessfulResponse );
return true;
// Now get all server info
var info = Internal.GetServerDetails( request, x );
if ( info.HadSuccessfulResponse )
{
OnServer( ServerInfo.From( info ), info.HadSuccessfulResponse );
return true;
}
}
return false;
@ -194,4 +200,4 @@ namespace Steamworks.ServerList
Unresponsive.Add( serverInfo );
}
}
}
}