## IpDrv
Class UdpServerQuery

source: C:\XIII\IpDrv\Classes\UDPSERVERQUERY.UC

    Core.Object
       |
       +--Engine.Actor
          |
          +--Engine.Info
             |
             +--Engine.InternetInfo
                |
                +--IpDrv.InternetLink
                   |
                   +--IpDrv.UdpLink
                      |
                      +--IpDrv.UdpServerQuery

Direct Known Subclasses:None

class UdpServerQuery
extends IpDrv.UdpLink

    //=============================================================================
    // UdpServerQuery
    //
    // Version: 1.5
    //
    // This query server is compliant with the GameSpy Uplink Specification.
    // The specification is available at http://www.gamespy.com/developer
    // and might be of use to progammers who are writing or maintaining
    // their own stat gathering/game querying software.
    //
    // Note: Currently, SendText returns false if successful.
    //
    // Full documentation on this class is available at http://unreal.epicgames.com/
    //
    //=============================================================================

Variables
`int` | `CurrentQueryNum` Query ID Number.
`string` | `GameName` Query ID Number.
`int` | `MinNetVer` Query ID Number.
`name` | `QueryName` Name to set this object's Tag to.
`string` | `ReplyData` Query ID Number.

Function Summary
`string` | `GetBasic()`
    // Return a string of basic information.
`string` | `GetGameProperty(string Prop)`
    // Get an arbitrary property from the game object.
`string` | `GetInfo()`
    // Return a string of important system information.
`string` | `GetLevelProperty(string Prop)`
    // Get an arbitrary property from the level object.
`string` | `GetPlayer(Controller P, int PlayerNum)`
    // Return a string of information on a player.
`string` | `GetPlayerProperty(string Prop)`
    // Get an arbitrary property from the players.
`string` | `GetRules()`
    // Return a string of miscellaneous information.
    // Game specific information, user defined data, custom parameters for the command line.
`bool` | `ParseNextQuery(string Query, out string, out string, out string, out int)`
`string` | `ParseQuery(IpAddr Addr, string Query, int QueryNum, out int)`
`void` | `PostBeginPlay()`
`void` | `PreBeginPlay()`
    // Initialize.
`bool` | `SendAPacket(IpAddr Addr, int QueryNum, out int, int bFinalPacket)`
`bool` | `SendPlayers(IpAddr Addr, int QueryNum, out int, int bFinalPacket)`
    // Send data for each player
`bool` | `SendQueryPacket(IpAddr Addr, string SendString, int QueryNum, out int, int bFinalPacket)`
    // SendQueryPacket is a wrapper for SendText that allows for packet numbering.

Source Code

    00001	//=============================================================================
    00002	// UdpServerQuery
    00003	//
    00004	// Version: 1.5
    00005	//
    00006	// This query server is compliant with the GameSpy Uplink Specification.
    00007	// The specification is available at http://www.gamespy.com/developer
    00008	// and might be of use to progammers who are writing or maintaining
    00009	// their own stat gathering/game querying software.
    00010	//
    00011	// Note: Currently, SendText returns false if successful.
    00012	//
    00013	// Full documentation on this class is available at http://unreal.epicgames.com/
    00014	//
    00015	//=============================================================================
    00016	class UdpServerQuery extends UdpLink config;
    00017
    00018	// Game Server Config.
    00019	var() name                         QueryName;               // Name to set this object's Tag to.
    00020	var int                             CurrentQueryNum;     // Query ID Number.
    00021	var globalconfig string          GameName;
    00022	//crt
    00023	var string ReplyData;
    00024
    00025	var globalconfig int          MinNetVer;
    00026
    00027	// Initialize.
    00028	function PreBeginPlay()
    00029	{
    00030	     local int boundport;
    00031
    00032	     // Set the Tag
    00033	     Tag = QueryName;
    00034
    00035	     // Bind the listen socket
    00036	     //boundport = BindPort(Level.Game.GetServerPort(), true);
    00037	     boundport = BindPort(7099, false);
    00038	     if( boundport == 0 )
    00039	     {
    00040	          Log("UdpServerQuery: Port failed to bind.");
    00041	          return;
    00042	     }
    00043	     Log("UdpServerQuery(crt): Port "$boundport$" successfully bound.");
    00044	}
    00045
    00046	function PostBeginPlay()
    00047	{
    00048	     local UdpBeacon     Beacon;
    00049
    00050	     foreach AllActors(class'UdpBeacon', Beacon)
    00051	     {
    00052	          Beacon.UdpServerQueryPort = Port;
    00053	     }
    00054	     Super.PostBeginPlay();
    00055	}
    00056
    00057	// Received a query request.
    00058	event ReceivedText( IpAddr Addr, string Text )
    00059	{
    00060	     local string Query;
    00061	     local bool QueryRemaining;
    00062	     local int  QueryNum, PacketNum;
    00063
    00064	     // Assign this packet a unique value from 1 to 100
    00065	     CurrentQueryNum++;
    00066	     if (CurrentQueryNum > 100)
    00067	          CurrentQueryNum = 1;
    00068	     QueryNum = CurrentQueryNum;
    00069
    00070	     Query = Text;
    00071	     if (Query == "")          // If the string is empty, don't parse it
    00072	          QueryRemaining = false;
    00073	     else
    00074	          QueryRemaining = true;
    00075	     //crt
    00076	     PacketNum =  0;
    00077	     ReplyData = "";
    00078	     while (QueryRemaining)
    00079	     {
    00080	          Query = ParseQuery(Addr, Query, QueryNum, PacketNum);
    00081	          if (Query == "")
    00082	               QueryRemaining = false;
    00083	          else
    00084	               QueryRemaining = true;
    00085	     }
    00086	}
    00087
    00088	function bool ParseNextQuery( string Query, out string QueryType, out string QueryValue, out string QueryRest, out int bFinalPacket )
    00089	{
    00090	     local string TempQuery;
    00091	     local int ClosingSlash;
    00092
    00093	     if (Query == "")
    00094	          return false;
    00095
    00096	     // Query should be:
    00097	     //   \[type]\<value>
    00098	     if (Left(Query, 1) == "\\")
    00099	     {
    00100	          // Check to see if closed.
    00101	          ClosingSlash = InStr(Right(Query, Len(Query)-1), "\\");
    00102	          if (ClosingSlash == 0)
    00103	               return false;
    00104
    00105	          TempQuery = Query;
    00106
    00107	          // Query looks like:
    00108	          //  \[type]\
    00109	          QueryType = Right(Query, Len(Query)-1);
    00110	          QueryType = Left(QueryType, ClosingSlash);
    00111
    00112	          QueryRest = Right(Query, Len(Query) - (Len(QueryType) + 2));
    00113
    00114	          if ((QueryRest == "") || (Len(QueryRest) == 1))
    00115	          {
    00116	               bFinalPacket = 1;
    00117	               return true;
    00118	          } else if (Left(QueryRest, 1) == "\\")
    00119	               return true;     // \type\\
    00120
    00121	          // Query looks like:
    00122	          //  \type\value
    00123	          ClosingSlash = InStr(QueryRest, "\\");
    00124	          if (ClosingSlash >= 0)
    00125	               QueryValue = Left(QueryRest, ClosingSlash);
    00126	          else
    00127	               QueryValue = QueryRest;
    00128
    00129	          QueryRest = Right(Query, Len(Query) - (Len(QueryType) + Len(QueryValue) + 3));
    00130	          if (QueryRest == "")
    00131	          {
    00132	               bFinalPacket = 1;
    00133	               return true;
    00134	          } else
    00135	               return true;
    00136	     } else {
    00137	          return false;
    00138	     }
    00139	}
    00140
    00141	function string ParseQuery( IpAddr Addr, coerce string Query, int QueryNum, out int PacketNum )
    00142	{
    00143	     local string QueryType, QueryValue, QueryRest, ValidationString;
    00144	     local bool Result;
    00145	     local int bFinalPacket;
    00146
    00147	     bFinalPacket = 0;
    00148	     Result = ParseNextQuery(Query, QueryType, QueryValue, QueryRest, bFinalPacket);
    00149	     if( !Result )
    00150	          return "";
    00151
    00152	     //Log("Got  Query: "  $ QueryNum $ "." $ PacketNum $ ":" $ QueryType);
    00153
    00154	     /*
    00155	     if( QueryType=="basic" )
    00156	     {
    00157	          Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, bFinalPacket);
    00158	     }
    00159	     else*/ if( QueryType=="info" )
    00160	     {
    00161	          Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, bFinalPacket);
    00162	     }
    00163	     /*
    00164	     else if( QueryType=="rules" )
    00165	     {
    00166	          Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket);
    00167	     }
    00168	     else if( QueryType=="players" )
    00169	     {
    00170	          if( Level.Game.NumPlayers > 0 )
    00171	               Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket);
    00172	          else
    00173	               Result = SendQueryPacket(Addr, "", QueryNum, PacketNum, bFinalPacket);
    00174	     }
    00175	     else if( QueryType=="status" )
    00176	     {
    00177	          Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, 0);
    00178	          Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, 0);
    00179	          if( Level.Game.NumPlayers == 0 )
    00180	          {
    00181	               Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket);
    00182	          }
    00183	          else
    00184	          {
    00185	               Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, 0);
    00186	               Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket);
    00187	          }
    00188	     }
    00189	     else if( QueryType=="echo" )
    00190	     {
    00191	          // Respond to an echo with the same string
    00192	          Result = SendQueryPacket(Addr, "\\echo\\"$QueryValue, QueryNum, PacketNum, bFinalPacket);
    00193	     }
    00194	     else if( QueryType=="secure" )
    00195	     {
    00196	          ValidationString = "\\validate\\"$Validate(QueryValue, GameName);
    00197	          Result = SendQueryPacket(Addr, ValidationString, QueryNum, PacketNum, bFinalPacket);
    00198	     }
    00199	     else if( QueryType=="level_property" )
    00200	     {
    00201	          Result = SendQueryPacket(Addr, GetLevelProperty(QueryValue), QueryNum, PacketNum, bFinalPacket);
    00202	     }
    00203	     else if( QueryType=="game_property" )
    00204	     {
    00205	               Result = SendQueryPacket(Addr, GetGameProperty(QueryValue), QueryNum, PacketNum, bFinalPacket);
    00206	     }
    00207	     else if( QueryType=="player_property" )
    00208	     {
    00209	          Result = SendQueryPacket(Addr, GetPlayerProperty(QueryValue), QueryNum, PacketNum, bFinalPacket);
    00210	     }
    00211	     else
    00212	     {
    00213	          Log("UdpServerQuery: Unknown query: "$QueryType);
    00214	     }
    00215	     */
    00216	     if( !Result )
    00217	          Log("UdpServerQuery: Error responding to query.");
    00218	     return QueryRest;
    00219	}
    00220
    00221	function bool SendAPacket(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket)
    00222	{
    00223	     local bool Result;
    00224
    00225	     ReplyData = ReplyData$"\\queryid\\"$QueryNum$"."$++PacketNum;
    00226	     if (bFinalPacket == 1) {
    00227	          ReplyData = ReplyData $ "\\final\\";
    00228	     }
    00229	     Result = SendText(Addr, ReplyData);
    00230	     ReplyData = "";
    00231
    00232	     return Result;
    00233
    00234	}
    00235
    00236	// SendQueryPacket is a wrapper for SendText that allows for packet numbering.
    00237	function bool SendQueryPacket(IpAddr Addr, coerce string SendString, int QueryNum, out int PacketNum, int bFinalPacket)
    00238	{
    00239	     local bool Result;
    00240
    00241	     //Log("Send Query: "  $ QueryNum $ "." $ PacketNum $ ":" $ bFinalPacket);
    00242	     result = true;
    00243	     if (len(ReplyData) + len(SendString) > 1000)
    00244	          result = SendAPacket(Addr, QueryNum, PacketNum, 0);
    00245
00246 ReplyData = ReplyData $ SendString; 00247 00248 if (bFinalPacket == 1) 00249 result = SendAPacket(Addr, QueryNum, PacketNum, bFinalPacket); 00250 00251 return Result; 00252 } 00253 00254 // Return a string of basic information. 00255 function string GetBasic() { 00256 local string ResultSet; 00257 00258 // The name of this game. 00259 ResultSet = "\\gamename\\"$GameName; 00260 00261 // The version of this game. 00262 ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion; 00263 00264 // The most recent network compatible version. 00265 if( MinNetVer >= Int(Level.MinNetVersion) && 00266 MinNetVer <= Int(Level.EngineVersion) ) 00267 ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer); 00268 else 00269 ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion; 00270 00271 // The regional location of this game. 00272 ResultSet = ResultSet$"\\location\\"$Level.Game.GameReplicationInfo.Region; 00273 00274 return ResultSet; 00275 } 00276 00277 // Return a string of important system information. 00278 function string GetInfo() 00279 { 00280 local string ResultSet; 00281 00282 ResultSet = "Pong"; 00283 /* 00284 // The server name, i.e.: Bob's Server 00285 ResultSet = "\\hostname\\"$Level.Game.GameReplicationInfo.ServerName; 00286 00287 // The short server name 00288 //ResultSet = ResultSet$"\\shortname\\"$Level.Game.GameReplicationInfo.ShortName; 00289 00290 // The server port. 00291 ResultSet = ResultSet$"\\hostport\\"$Level.Game.GetServerPort(); 00292 00293 // (optional) The server IP 00294 // if (ServerIP != "") 00295 // ResultSet = ResultSet$"\\hostip\\"$ServerIP; 00296 00297 // The map/level title 00298 ResultSet = ResultSet$"\\maptitle\\"$Level.Title; 00299 00300 // Map name 00301 ResultSet = ResultSet$"\\mapname\\"$Left(string(Level), InStr(string(Level), ".")); 00302 00303 // The mod or game type 00304 ResultSet = ResultSet$"\\gametype\\"$GetItemName(string(Level.Game.Class)); 00305 00306 // The number of players 00307 ResultSet = ResultSet$"\\numplayers\\"$Level.Game.NumPlayers; 00308 00309 // The maximum number of players 00310 ResultSet = ResultSet$"\\maxplayers\\"$Level.Game.MaxPlayers; 00311 00312 // The game mode: openplaying 00313 ResultSet = ResultSet$"\\gamemode\\openplaying"; 00314 00315 // The version of this game. 00316 ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion; 00317 00318 // The most recent network compatible version. 00319 if( MinNetVer >= Int(Level.MinNetVersion) && 00320 MinNetVer <= Int(Level.EngineVersion) ) 00321 ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer); 00322 else 00323 ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion; 00324 00325 ResultSet = ResultSet$Level.Game.GetInfo(); 00326 */ 00327 00328 return ResultSet; 00329 } 00330 00331 /* 00332 // Return a string of miscellaneous information. 00333 // Game specific information, user defined data, custom parameters for the command line. 00334 function string GetRules() 00335 { 00336 local string ResultSet; 00337 00338 ResultSet = Level.Game.GetRules(); 00339 00340 // Admin's Name 00341 if( Level.Game.GameReplicationInfo.AdminName != "" ) 00342 ResultSet = ResultSet$"\\AdminName\\"$Level.Game.GameReplicationInfo.AdminName; 00343 00344 // Admin's Email 00345 if( Level.Game.GameReplicationInfo.AdminEmail != "" ) 00346 ResultSet = ResultSet$"\\AdminEMail\\"$Level.Game.GameReplicationInfo.AdminEmail; 00347 00348 return ResultSet; 00349 } 00350 00351 // Return a string of information on a player. 00352 function string GetPlayer( Controller P, int PlayerNum ) 00353 { 00354 local string ResultSet; 00355 local string SkinName, FaceName; 00356 00357 // Name 00358 ResultSet = "\\player_"$PlayerNum$"\\"$P.PlayerReplicationInfo.PlayerName; 00359 00360 // Frags 00361 ResultSet = ResultSet$"\\frags_"$PlayerNum$"\\"$int(P.PlayerReplicationInfo.Score); 00362 00363 // Ping 00364 ResultSet = ResultSet$"\\ping_"$PlayerNum$"\\"$P.ConsoleCommand("GETPING"); 00365 00366 // Team 00367 ResultSet = ResultSet$"\\team_"$PlayerNum$"\\"$P.PlayerReplicationInfo.Team; 00368 00369 // Class 00370 // ResultSet = ResultSet$"\\mesh_"$PlayerNum$"\\"$P.Menuname; 00371 00372 // Skin 00373 //if(P.Skin == None) 00374 //{ 00375 // P.static.GetMultiSkin(P, SkinName, FaceName); 00376 // ResultSet = ResultSet$"\\skin_"$PlayerNum$"\\"$SkinName; 00377 // ResultSet = ResultSet$"\\face_"$PlayerNum$"\\"$FaceName; 00378 //} 00379 //else 00380 //{ 00381 // ResultSet = ResultSet$"\\skin_"$PlayerNum$"\\"$string(P.Skin); 00382 // ResultSet = ResultSet$"\\face_"$PlayerNum$"\\None"; 00383 //} 00384 //if( P.PlayerReplicationInfo.bIsABot ) 00385 // ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\bot"; 00386 //else 00387 //if( P.ReceivedSecretChecksum ) 00388 // ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\true"; 00389 //else 00390 // ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\false"; 00391 00392 return ResultSet; 00393 } 00394 00395 // Send data for each player 00396 function bool SendPlayers(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket) 00397 { 00398 local Controller P; 00399 local int i; 00400 local bool Result, SendResult; 00401 00402 Result = false; 00403 00404 P = Level.ControllerList; 00405 while( i < Level.Game.NumPlayers ) 00406 { 00407 if (P.IsA('PlayerPawn')) 00408 { 00409 if( i==Level.Game.NumPlayers-1 && bFinalPacket==1) 00410 SendResult = SendQueryPacket(Addr, GetPlayer(P, i), QueryNum, PacketNum, 1); 00411 else 00412 SendResult = SendQueryPacket(Addr, GetPlayer(P, i), QueryNum, PacketNum, 0); 00413 Result = SendResult || Result; 00414 i++; 00415 } 00416 P = P.nextController; 00417 } 00418 00419 return Result; 00420 } 00421 00422 // Get an arbitrary property from the level object. 00423 function string GetLevelProperty( string Prop ) 00424 { 00425 local string ResultSet; 00426 00427 ResultSet = "\\"$Prop$"\\"$Level.GetPropertyText(Prop); 00428 00429 return ResultSet; 00430 } 00431 00432 // Get an arbitrary property from the game object. 00433 function string GetGameProperty( string Prop ) 00434 { 00435 local string ResultSet; 00436 00437 ResultSet = "\\"$Prop$"\\"$Level.Game.GetPropertyText(Prop); 00438 00439 return ResultSet; 00440 } 00441 00442 // Get an arbitrary property from the players. 00443 function string GetPlayerProperty( string Prop ) 00444 { 00445 local string ResultSet; 00446 local int i; 00447 local Controller P; 00448 00449 foreach AllActors(class'Controller', P) { 00450 i++; 00451 ResultSet = ResultSet$"\\"$Prop$"_"$i$"\\"$P.GetPropertyText(Prop); 00452 } 00453 00454 return ResultSet; 00455 } 00456 */ 00457 00458 defaultproperties 00459 { 00460 QueryName="MasterUplink" 00461 GameName="XIII" 00462 RemoteRole=ROLE_None 00463 }

End Source Code