Advertisement
Guest User

GameSpy 2 Server Query

a guest
Oct 25th, 2012
460
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Author: TR1GG3R (http://www.houseofpain.tk)
  3.    
  4.     Resources:
  5.    
  6.     http://int64.org/docs/gamestat-protocols/gamespy2.html
  7.     http://www.alexthissen.nl/wikis/gaming/gamespy-2.aspx
  8.     http://wiki.beyondunreal.com/Legacy:UdpLink
  9.     http://en.wikipedia.org/wiki/User_Datagram_Protocol#IPv4_Pseudo_Header
  10. */
  11.  
  12. class AMGameSpyV2Query extends IPDrv.UDPLink;
  13.  
  14. var int boundport;
  15. var int bytecount;
  16. var byte data[255];
  17. var() globalconfig int GameSpyV2QueryPort;
  18.  
  19. function BeginPlay()
  20. {
  21.     LinkMode = MODE_Binary;
  22.    
  23.     if ( GameSpyV2QueryPort == 0 )
  24.     {
  25.         Destroy();
  26.         return;
  27.     }
  28.  
  29.     boundport = BindPort( GameSpyV2QueryPort, true );
  30.  
  31.     if ( boundport == 0 )
  32.     {
  33.         log( "AMGameSpyV2Query: Could not bind a port" );
  34.         Destroy();
  35.         return;
  36.     }
  37.  
  38.     log( "AMGameSpyV2Query: Listening on "$boundport );
  39. }
  40.  
  41. event ReceivedBinary( IpAddr Addr, int Count, byte B[255] )
  42. {
  43.     if ( IsGameSpy2Query( B ) )
  44.     {
  45.         SetHeader( B );
  46.        
  47.         // Server information and rules
  48.         if ( B[23] == 0xFF )
  49.             SendMain( Addr );
  50.        
  51.         // Player information
  52.         if ( B[24] == 0xFF )
  53.             SendPlayers( Addr );
  54.     }
  55. }
  56.  
  57. function AddData( byte B )
  58. {
  59.     if ( bytecount < 255 )
  60.     {
  61.         data[bytecount] = B;
  62.         bytecount++;
  63.     }
  64. }
  65.  
  66. function SendData( IpAddr Addr )
  67. {
  68.     SendBinary( Addr, bytecount, data );
  69.     bytecount = 0;
  70. }
  71.  
  72. function AddNull()
  73. {
  74.     AddData( 0x00 );
  75. }
  76.  
  77. function SetHeader( byte B[255] )
  78. {
  79.     local int i;
  80.  
  81.     AddNull(); // Delimiter
  82.    
  83.     // Unique identifier (4 bytes)
  84.     for ( i = 19; i < 23; i++ )
  85.         AddData( B[i] );
  86. }
  87.  
  88. function AddString( string Str )
  89. {
  90.     local int i, j;
  91.    
  92.     j = Len( Str );
  93.    
  94.     for ( i = 0; i < j; i++ )
  95.         AddData( Asc( Mid( Str, i, 1 ) ) );
  96.  
  97.     AddNull(); // Delimiter
  98. }
  99.  
  100. function bool IsGameSpy2Query( byte B[255] )
  101. {
  102.     if ( B[16] == 0xFE && B[17] == 0xFD && B[18] == 0x00 )
  103.         return true;
  104.        
  105.     return false;
  106. }
  107.  
  108. function SendMain( IpAddr Addr )
  109. {
  110.     local int i;
  111.     local string keys[9], values[9];
  112.    
  113.     keys[0] = "hostname";
  114.     values[0] = ServerSettings(Level.CurrentServerSettings).ServerName;
  115.    
  116.     keys[1] = "numplayers";
  117.     values[1] = String(SwatGameInfo(Level.Game).NumberOfPlayersForServerBrowser());
  118.    
  119.     keys[2] = "maxplayers";
  120.     values[2] = String(ServerSettings(Level.CurrentServerSettings).MaxPlayers);
  121.    
  122.     keys[3] = "gametype";
  123.     values[3] = SwatGameInfo(Level.Game).GetGameModeName();
  124.    
  125.     keys[4] = "gamevariant";
  126.     values[4] = Level.ModName;
  127.    
  128.     keys[5] = "mapname";
  129.     values[5] = Level.Title;
  130.    
  131.     keys[6] = "hostport";
  132.     values[6] = String(SwatGameInfo(Level.Game).GetServerPort());
  133.    
  134.     keys[7] = "password";
  135.     values[7] = String(Level.Game.GameIsPasswordProtected());
  136.    
  137.     keys[8] = "gamever";
  138.     values[8] = Level.BuildVersion;
  139.    
  140.     for ( i = 0; i < 9; i++ )
  141.     {
  142.         AddString( keys[i] ); // Key
  143.         AddString( values[i] ); // Value
  144.     }
  145.    
  146.     // Empty key/value (end of key/value pairs)
  147.     AddNull();
  148.     AddNull();
  149.    
  150.     if ( bytecount > 255 )
  151.     {
  152.         log( "AMGameSpyV2Query::SendMain() failed... data > 255 bytes" );
  153.         return;
  154.     }
  155.    
  156.     SendData( Addr );
  157. }
  158.  
  159. function SendPlayers( IpAddr Addr )
  160. {
  161.     local int i;
  162.     local Array<string> keys;
  163.     local Controller controller, theLocalPlayerController;
  164.     local SwatGamePlayerController current;
  165.    
  166.     AddNull();
  167.     AddData( SwatGameInfo(Level.Game).NumberOfPlayersForServerBrowser() ); // Player count
  168.  
  169.     keys[0] = "player_";
  170.     keys[1] = "score_";
  171.     keys[2] = "ping_";
  172.    
  173.     for ( i = 0; i < keys.Length; i++ )
  174.         AddString(keys[i]);
  175.    
  176.     AddNull(); // Empty string (end of player info description)
  177.  
  178.     theLocalPlayerController = Level.GetLocalPlayerController();
  179.     for ( controller = Level.ControllerList; controller != None; controller = controller.NextController )
  180.     {
  181.         current = SwatGamePlayerController( controller );
  182.        
  183.         if ( current != None && current != theLocalPlayerController )
  184.         {
  185.             AddString( SwatGameInfo(Level.Game).GetPlayerName( current ) );
  186.             AddString( String(SwatGameInfo(Level.Game).GetPlayerScore( current )) );
  187.             AddString( String(current.PlayerReplicationInfo.Ping) );
  188.         }
  189.     }
  190.    
  191.     if ( bytecount > 255 )
  192.     {
  193.         log( "AMGameSpyV2Query::SendPlayers() failed... data > 255 bytes" );
  194.         return;
  195.     }
  196.    
  197.     SendData( Addr );
  198. }
  199.  
  200. defaultproperties
  201. {
  202.     GameSpyV2QueryPort=10481
  203. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement