Áƒ*žEƒ@šÃr;Êp#sO€œ-¢A€è¢ÈêºAmšƒNoneSendQueryPacketUdpServerUplink GetRulesParseNextQueryGetInfo ParseQuery GetBasic SendPlayers SendAPacket GetPlayer SendTextCoreGetPlayerProperty MasterUplinkGetGamePropertyTimer IpServer BindPort ReceivedTextSystemIpDrvEngine ValidateResumeUdpServerQueryGetLevelPropertyGetServerPort PreBeginPlayResolveTargetQueryNameMasterServerPortPostBeginPlayUpdateMinutes QueryNameHalt ResolvedConsoleCommand GetItemNameResolveFailed PlayerPawn GameName GetMultiSkin ServerName MenuName MaxPlayersLevelActor SkinNameResultP NumPlayers AdminEmail PlayerNameScorebIsABotGameRegion nextPawnEngineVersionMinNetVersion PawnList ResultSetTextPawn FaceName AdminNameReceivedSecretChecksumTeamTitleUdpLink InternetLink UdpBeaconTagClassGameReplicationInfoiIpAddr ScriptTextPortAddrValidationStringUdpServerQueryPort boundportQueryMasterServerAddressMasterServerIpAddr MinNetVerPackage TextBufferObject ReturnValueCurrentQueryNum ReplyDataOldQueryPortNumberbRestartServerOnPortSwapBeaconQueryRemaining QueryNum PacketNum Function QueryType QueryValue QueryRest bFinalPacket TempQuery ClosingSlashStruct StrPropertyStructProperty SendStringClassProperty NameProperty PlayerNumObjectProperty SendResultFloatPropertyProp BoolProperty IntProperty ByteProperty DoUplinkGetPropertyTextPlayerReplicationInfo LevelInfoHeartbeatMessage UplinkPort GameInfoSkin FinalPacket QueryStrI@@a€z€€V€€@€@@€Ž@@8@4€@:€@)•UCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIrr‹Ü•6…Ž> £YƒŽ”‰©Ù«ƒŽ”ƒŽ”ƒŽ”‰©Ù«’žtÈƒŽ”‰©Ù«’žtÈŽ> £Y“{#U¿Ž> £Y“{#U¿Ž> £YŽ> £Y“{#U¿Ž> £YŽ> £YŽ> £YŽ> £YŽ> £Y“{#U¿Ž> £YƒŽ”‰©Ù«ƒŽ”‰©Ù«'n 6ƒŽ”‰©Ù«'n 6ƒŽ”‰©Ù«'n 6ƒŽ”‰©Ù«'n 6ƒŽ”‰©Ù«'n 6ƒŽ”‰©Ù«ƒŽ”ƒŽ”‰©Ù«ƒŽ”‰©Ù«ƒŽ”‰©Ù«ƒŽ”ƒŽ”ƒŽ”ƒŽ”ƒŽ”‰©Ù«ƒŽ”ƒŽ”ƒŽ”ƒŽ”ƒŽ”‰©Ù«'n 6ƒŽ”‰©Ù«ƒŽ”‰©Ù«œ™N5ƒŽ”‰©Ù« –")-ut/@@’*€@T€@ @D(,€@f@@09<!@"@F1€@H@€@;@W@@@€6€@7€K€P@3D€@G`€@@C@H€@@&@O€@œ@Ž@@J@@y€M€N€R€5€@Z€i€S€€'@L€X€Y€@Z€@^€#€@@€@$€@d@@b€g@h@Y€@u€j€k€l€p€¹qn$R B6Ÿ6Ÿndš6Ÿ%çUdpServerUplink: Invalid master server address, aborting. çpppUdpServerUplink: Master Server is :S6©-’&š-'%çUdpServerUplink: Error binding port, aborting. çppUdpServerUplink: Port S- successfully bound. - c$ÇG-cçDoUplink is not set. Not connecting to Master Server. /a0 h``10´r*çUdpServerUplink: Could not find a UdpServerQuery object, aborting. 6|unreal.epicgames.com0ppppp\heartbeat\S\gamename\\gamever\‡˜x0ppp\heartbeat\S\gamename\6©fºzppmasterSg.gamespy.com ºo'n" IçUdpServerUplink: Failed to resolve master server address, aborting. ´r=vÇ R-= 0P-=çFailed to send heartbeat to master server. |m æAx pppp \queryid\Sl.S£kPšj& p \final\-2 m  -2 2€X„Äa?d,<' ¥veל¥)—),d)&<)$bGz$-"(O-"'š-"$e$<`z$-"(—-"'O tO÷K†-%'?—’} }5è-% O67% p 5}šK&-% O67K-% %€ €@x}ãp\gamename\pp\gamever\‡˜š‚™J‡š˜J‡˜pp\minnetver\SÄpp\minnetver\‡špp\location\S‡”® AŸJê%-a 8;-vz basic-â°z info-âëz rules-âez players?—‡—%-b-âKz status-%-%š‡—%-H-%-âŽz echo-p\echo\â z secure½—},€,Pp\validate\-PâSz level_property-â›z game_property-ââz player_property- 8 €@w ©@gz (cz€ &\~ê “} &\Gš%(\ ê “} &€ê “} ’},É„z š}&:final'ÛÛz€&\'~\ ™%,€,ê “} ’’}},,^z:final'`'e( .€@_€F iV [z (Wz€ &\~ê “} &\Gš%(_ ê “} &€ê “} ’},Äz š}&4&'ÕÕz€&\'~\™%*€*ê “} ’’}}*,Rz4&'T'Y( {E¡]p\hostname\‡”¬pp\hostport\S‡pp\maptitle\‡¶pp\mapname\€V‡~V‡.pp\gametype\&V‡°pp\numplayers\S‡—pp\maxplayers\S‡³p\gamemode\openplayingpp\gamever\‡˜‚™J‡š˜J‡˜pp\minnetver\S0pp\minnetver\‡šp‡ J> À$0`/a0 ŽGW¥;.pppppp.\>_S;\G ž>10. \€€@¥M]NÆ«¥'—',d'&9'#^Gz#-!(O-!'3% ©-!#]#93žz#-!(¦-!'^ ~[ßC¿-&Z+H@F4-&Pz+basic-&'··z+secureCp\validate\H-&[CY£XF@ ?€@BKRÔ$í‡{‡”¨pp\AdminName\‡”¨å{‡”¦pp\AdminEMail\‡”¦ TA´#/<?ppp\A\‡ žA? €@+€@§NE ?p./a0 œE%E¸10§  V 'xÖ²V ‡'eš %çUdpServerQuery: Port failed to bind. çppUdpServerQuery(crt): Port S  successfully bound.Ô-WÆ›/% 5š/ / b B€@I f '·ppp\player_S\ ›­pppp\frags_S\SD ›ªpppp\ping_S\ %GETPINGpppp\team_S\R ›»pppp\mesh_S\ ±¥r £* * IJpppp\skin_S\Ipppp\face_S\Jþpppp\skin_S\V £ppp\face_S\NoneE ›-«ppp\ngsecret_S\bot¯„ -¯ppp\ngsecret_S\true¯ppp\ngsecret_S\false Lj//============================================================================= // UdpServerUplink // // Version: 1.3 // // This uplink 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 want to adapt their own // server uplinks. // // UdpServerUplink sends a heartbeat to the specified master server // every five minutes. The heartbeat is in the form: // \heartbeat\QueryPort\gamename\unreal // // Full documentation on this class is available at http://unreal.epicgames.com/ // //============================================================================= class UdpServerUplink extends UdpLink config; // Master Uplink Config. var() config bool DoUplink; // If true, do the uplink var() config int UpdateMinutes; // Period of update (in minutes) var() config string MasterServerAddress; // Address of the master server var() config int MasterServerPort; // Optional port that the master server is listening on var() config int Region; // Region of the game server var() name TargetQueryName; // Name of the query server object to use. var IpAddr MasterServerIpAddr; // Master server's address. var string HeartbeatMessage; // The message that is sent to the master server. var UdpServerQuery Query; // The query object. var int CurrentQueryNum; // Query ID Number. // Initialize. function PreBeginPlay() { // If master server uplink isn't wanted, exit. if( !DoUplink ) { Log("DoUplink is not set. Not connecting to Master Server."); return; } /* if( Level.NetMode == NM_ListenServer ) { Log("This is a Listen server. Not connecting to Master Server."); return; } */ // Find a the server query handler. foreach AllActors(class'UdpServerQuery', Query, TargetQueryName) break; if( Query==None ) { Log("UdpServerUplink: Could not find a UdpServerQuery object, aborting."); return; } // Set heartbeat message. if( MasterServerAddress ~= "unreal.epicgames.com" ) HeartbeatMessage = "\\heartbeat\\"$Query.Port$"\\gamename\\"$Query.GameName$"\\gamever\\"$Level.EngineVersion; else HeartbeatMessage = "\\heartbeat\\"$Query.Port$"\\gamename\\"$Query.GameName; // Set the Port. MasterServerIpAddr.Port = MasterServerPort; // Resolve the Address. if( MasterServerAddress=="" ) MasterServerAddress = "master"$Region$".gamespy.com"; Resolve( MasterServerAddress ); } // When master server address is resolved. function Resolved( IpAddr Addr ) { local bool Result; local int UplinkPort; // Set the address MasterServerIpAddr.Addr = Addr.Addr; // Handle failure. if( MasterServerIpAddr.Addr == 0 ) { Log("UdpServerUplink: Invalid master server address, aborting."); return; } // Display success message. Log("UdpServerUplink: Master Server is "$MasterServerAddress$":"$MasterServerIpAddr.Port); // Bind the local port. UplinkPort = Query.Port + 1; if( BindPort(UplinkPort, true) == 0 ) { Log( "UdpServerUplink: Error binding port, aborting." ); return; } Log("UdpServerUplink: Port "$UplinkPort$" successfully bound."); // Start transmitting. Resume(); } // Host resolution failue. function ResolveFailed() { Log("UdpServerUplink: Failed to resolve master server address, aborting."); } // Notify the MasterServer we exist. function Timer() { local bool Result; Result = SendText( MasterServerIpAddr, HeartbeatMessage ); if ( !Result ) Log( "Failed to send heartbeat to master server."); } // Stop the uplink. function Halt() { SetTimer(0.0, false); } // Resume the uplink. function Resume() { SetTimer(UpdateMinutes * 60, true); Timer(); } // Received a query request. event ReceivedText( IpAddr Addr, string Text ) { local string Query; local bool QueryRemaining; local int QueryNum, PacketNum; // Assign this packet a unique value from 1 to 100 CurrentQueryNum++; if (CurrentQueryNum > 100) CurrentQueryNum = 1; QueryNum = CurrentQueryNum; Query = Text; if (Query == "") // If the string is empty, don't parse it QueryRemaining = false; else QueryRemaining = true; while (QueryRemaining) { Query = ParseQuery(Addr, Query, QueryNum, PacketNum); if (Query == "") QueryRemaining = false; else QueryRemaining = true; } } function bool ParseNextQuery( string Query, out string QueryType, out string QueryValue, out string QueryRest, out string FinalPacket ) { local string TempQuery; local int ClosingSlash; if (Query == "") return false; // Query should be: // \[type]\ if (Left(Query, 1) == "\\") { // Check to see if closed. ClosingSlash = InStr(Right(Query, Len(Query)-1), "\\"); if (ClosingSlash == 0) return false; TempQuery = Query; // Query looks like: // \[type]\ QueryType = Right(Query, Len(Query)-1); QueryType = Left(QueryType, ClosingSlash); QueryRest = Right(Query, Len(Query) - (Len(QueryType) + 2)); if ((QueryRest == "") || (Len(QueryRest) == 1)) { FinalPacket = "final"; return true; } else if (Left(QueryRest, 1) == "\\") return true; // \type\\ // Query looks like: // \type\value ClosingSlash = InStr(QueryRest, "\\"); if (ClosingSlash >= 0) QueryValue = Left(QueryRest, ClosingSlash); else QueryValue = QueryRest; QueryRest = Right(Query, Len(Query) - (Len(QueryType) + Len(QueryValue) + 3)); if (QueryRest == "") { FinalPacket = "final"; return true; } else return true; } else { return false; } } function string ParseQuery( IpAddr Addr, coerce string QueryStr, int QueryNum, out int PacketNum ) { local string QueryType, QueryValue, QueryRest, ValidationString; local bool Result; local string FinalPacket; Result = ParseNextQuery(QueryStr, QueryType, QueryValue, QueryRest, FinalPacket); if( !Result ) return ""; if( QueryType=="basic" ) { // Ignore. Result = true; } else if( QueryType=="secure" ) { ValidationString = "\\validate\\"$Validate(QueryValue, Query.GameName); Result = SendQueryPacket(Addr, ValidationString, QueryNum, ++PacketNum, FinalPacket); } return QueryRest; } // SendQueryPacket is a wrapper for SendText that allows for packet numbering. function bool SendQueryPacket(IpAddr Addr, coerce string SendString, int QueryNum, int PacketNum, string FinalPacket) { local bool Result; if (FinalPacket == "final") { SendString = SendString$"\\final\\"; } SendString = SendString$"\\queryid\\"$QueryNum$"."$PacketNum; Result = SendText(Addr, SendString); return Result; } •QSÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ RO•ú=•6…rr‹Ürr‹Ürr‹Ürr‹ÜƒŽ”rr‹Ürr‹Ü –!""ülGUô¿t'zifinalp\final\pppp\queryid\ST.SS-Q U-Q WDªJ.3Bppp\D\‡ žDB Â//============================================================================= // 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/ // //============================================================================= class UdpServerQuery extends UdpLink config; // Game Server Config. var() name QueryName; // Name to set this object's Tag to. var int CurrentQueryNum; // Query ID Number. var globalconfig string GameName; //crt var string ReplyData; var globalconfig int MinNetVer; //!! Hack to prevent port swapping var globalconfig int OldQueryPortNumber; var globalconfig bool bRestartServerOnPortSwap; // Initialize. function PreBeginPlay() { local int boundport; // Set the Tag Tag = QueryName; // Bind the listen socket boundport = BindPort(Level.Game.GetServerPort(), true); if( boundport == 0 ) { Log("UdpServerQuery: Port failed to bind."); return; } Log("UdpServerQuery(crt): Port "$boundport$" successfully bound."); if( bRestartServerOnPortSwap ) { if( OldQueryPortNumber != 0 ) assert( OldQueryPortNumber == boundport ); OldQueryPortNumber = boundport; SaveConfig(); } } function PostBeginPlay() { local UdpBeacon Beacon; foreach AllActors(class'UdpBeacon', Beacon) { Beacon.UdpServerQueryPort = Port; } Super.PostBeginPlay(); } // Received a query request. event ReceivedText( IpAddr Addr, string Text ) { local string Query; local bool QueryRemaining; local int QueryNum, PacketNum; // Assign this packet a unique value from 1 to 100 CurrentQueryNum++; if (CurrentQueryNum > 100) CurrentQueryNum = 1; QueryNum = CurrentQueryNum; Query = Text; if (Query == "") // If the string is empty, don't parse it QueryRemaining = false; else QueryRemaining = true; //crt PacketNum = 0; ReplyData = ""; while (QueryRemaining) { Query = ParseQuery(Addr, Query, QueryNum, PacketNum); if (Query == "") QueryRemaining = false; else QueryRemaining = true; } } function bool ParseNextQuery( string Query, out string QueryType, out string QueryValue, out string QueryRest, out int bFinalPacket ) { local string TempQuery; local int ClosingSlash; if (Query == "") return false; // Query should be: // \[type]\ if (Left(Query, 1) == "\\") { // Check to see if closed. ClosingSlash = InStr(Right(Query, Len(Query)-1), "\\"); if (ClosingSlash == 0) return false; TempQuery = Query; // Query looks like: // \[type]\ QueryType = Right(Query, Len(Query)-1); QueryType = Left(QueryType, ClosingSlash); QueryRest = Right(Query, Len(Query) - (Len(QueryType) + 2)); if ((QueryRest == "") || (Len(QueryRest) == 1)) { bFinalPacket = 1; return true; } else if (Left(QueryRest, 1) == "\\") return true; // \type\\ // Query looks like: // \type\value ClosingSlash = InStr(QueryRest, "\\"); if (ClosingSlash >= 0) QueryValue = Left(QueryRest, ClosingSlash); else QueryValue = QueryRest; QueryRest = Right(Query, Len(Query) - (Len(QueryType) + Len(QueryValue) + 3)); if (QueryRest == "") { bFinalPacket = 1; return true; } else return true; } else { return false; } } function string ParseQuery( IpAddr Addr, coerce string Query, int QueryNum, out int PacketNum ) { local string QueryType, QueryValue, QueryRest, ValidationString; local bool Result; local int bFinalPacket; bFinalPacket = 0; Result = ParseNextQuery(Query, QueryType, QueryValue, QueryRest, bFinalPacket); if( !Result ) return ""; //Log("Got Query: " $ QueryNum $ "." $ PacketNum $ ":" $ QueryType); if( QueryType=="basic" ) { Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="info" ) { Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="rules" ) { Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="players" ) { if( Level.Game.NumPlayers > 0 ) Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket); else Result = SendQueryPacket(Addr, "", QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="status" ) { Result = SendQueryPacket(Addr, GetBasic(), QueryNum, PacketNum, 0); Result = SendQueryPacket(Addr, GetInfo(), QueryNum, PacketNum, 0); if( Level.Game.NumPlayers == 0 ) { Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, bFinalPacket); } else { Result = SendQueryPacket(Addr, GetRules(), QueryNum, PacketNum, 0); Result = SendPlayers(Addr, QueryNum, PacketNum, bFinalPacket); } } else if( QueryType=="echo" ) { // Respond to an echo with the same string Result = SendQueryPacket(Addr, "\\echo\\"$QueryValue, QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="secure" ) { if(Len(QueryValue) > 6) QueryValue = Left(QueryValue, 6); ValidationString = "\\validate\\"$Validate(QueryValue, GameName); Result = SendQueryPacket(Addr, ValidationString, QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="level_property" ) { Result = SendQueryPacket(Addr, GetLevelProperty(QueryValue), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="game_property" ) { Result = SendQueryPacket(Addr, GetGameProperty(QueryValue), QueryNum, PacketNum, bFinalPacket); } else if( QueryType=="player_property" ) { Result = SendQueryPacket(Addr, GetPlayerProperty(QueryValue), QueryNum, PacketNum, bFinalPacket); } return QueryRest; } function bool SendAPacket(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket) { local bool Result; ReplyData = ReplyData$"\\queryid\\"$QueryNum$"."$++PacketNum; if (bFinalPacket == 1) { ReplyData = ReplyData $ "\\final\\"; } Result = SendText(Addr, ReplyData); ReplyData = ""; return Result; } // SendQueryPacket is a wrapper for SendText that allows for packet numbering. function bool SendQueryPacket(IpAddr Addr, coerce string SendString, int QueryNum, out int PacketNum, int bFinalPacket) { local bool Result; //Log("Send Query: " $ QueryNum $ "." $ PacketNum $ ":" $ bFinalPacket); result = true; if (len(ReplyData) + len(SendString) > 1000) result = SendAPacket(Addr, QueryNum, PacketNum, 0); ReplyData = ReplyData $ SendString; if (bFinalPacket == 1) result = SendAPacket(Addr, QueryNum, PacketNum, bFinalPacket); return Result; } // Return a string of basic information. function string GetBasic() { local string ResultSet; // The name of this game. ResultSet = "\\gamename\\"$GameName; // The version of this game. ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion; // The most recent network compatible version. if( MinNetVer >= Int(Level.MinNetVersion) && MinNetVer <= Int(Level.EngineVersion) ) ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer); else ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion; // The regional location of this game. ResultSet = ResultSet$"\\location\\"$Level.Game.GameReplicationInfo.Region; return ResultSet; } // Return a string of important system information. function string GetInfo() { local string ResultSet; // The server name, i.e.: Bob's Server ResultSet = "\\hostname\\"$Level.Game.GameReplicationInfo.ServerName; // The short server name //ResultSet = ResultSet$"\\shortname\\"$Level.Game.GameReplicationInfo.ShortName; // The server port. ResultSet = ResultSet$"\\hostport\\"$Level.Game.GetServerPort(); // (optional) The server IP // if (ServerIP != "") // ResultSet = ResultSet$"\\hostip\\"$ServerIP; // The map/level title ResultSet = ResultSet$"\\maptitle\\"$Level.Title; // Map name ResultSet = ResultSet$"\\mapname\\"$Left(string(Level), InStr(string(Level), ".")); // The mod or game type ResultSet = ResultSet$"\\gametype\\"$GetItemName(string(Level.Game.Class)); // The number of players ResultSet = ResultSet$"\\numplayers\\"$Level.Game.NumPlayers; // The maximum number of players ResultSet = ResultSet$"\\maxplayers\\"$Level.Game.MaxPlayers; // The game mode: openplaying ResultSet = ResultSet$"\\gamemode\\openplaying"; // The version of this game. ResultSet = ResultSet$"\\gamever\\"$Level.EngineVersion; // The most recent network compatible version. if( MinNetVer >= Int(Level.MinNetVersion) && MinNetVer <= Int(Level.EngineVersion) ) ResultSet = ResultSet$"\\minnetver\\"$string(MinNetVer); else ResultSet = ResultSet$"\\minnetver\\"$Level.MinNetVersion; ResultSet = ResultSet$Level.Game.GetInfo(); return ResultSet; } // Return a string of miscellaneous information. // Game specific information, user defined data, custom parameters for the command line. function string GetRules() { local string ResultSet; ResultSet = Level.Game.GetRules(); // Admin's Name if( Level.Game.GameReplicationInfo.AdminName != "" ) ResultSet = ResultSet$"\\AdminName\\"$Level.Game.GameReplicationInfo.AdminName; // Admin's Email if( Level.Game.GameReplicationInfo.AdminEmail != "" ) ResultSet = ResultSet$"\\AdminEMail\\"$Level.Game.GameReplicationInfo.AdminEmail; return ResultSet; } // Return a string of information on a player. function string GetPlayer( PlayerPawn P, int PlayerNum ) { local string ResultSet; local string SkinName, FaceName; // Name ResultSet = "\\player_"$PlayerNum$"\\"$P.PlayerReplicationInfo.PlayerName; // Frags ResultSet = ResultSet$"\\frags_"$PlayerNum$"\\"$int(P.PlayerReplicationInfo.Score); // Ping ResultSet = ResultSet$"\\ping_"$PlayerNum$"\\"$P.ConsoleCommand("GETPING"); // Team ResultSet = ResultSet$"\\team_"$PlayerNum$"\\"$P.PlayerReplicationInfo.Team; // Class ResultSet = ResultSet$"\\mesh_"$PlayerNum$"\\"$P.Menuname; // Skin if(P.Skin == None) { P.static.GetMultiSkin(P, SkinName, FaceName); ResultSet = ResultSet$"\\skin_"$PlayerNum$"\\"$SkinName; ResultSet = ResultSet$"\\face_"$PlayerNum$"\\"$FaceName; } else { ResultSet = ResultSet$"\\skin_"$PlayerNum$"\\"$string(P.Skin); ResultSet = ResultSet$"\\face_"$PlayerNum$"\\None"; } if( P.PlayerReplicationInfo.bIsABot ) ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\bot"; else if( P.ReceivedSecretChecksum ) ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\true"; else ResultSet = ResultSet$"\\ngsecret_"$PlayerNum$"\\false"; return ResultSet; } // Send data for each player function bool SendPlayers(IpAddr Addr, int QueryNum, out int PacketNum, int bFinalPacket) { local Pawn P; local int i; local bool Result, SendResult; Result = false; P = Level.PawnList; while( i < Level.Game.NumPlayers ) { if (P.IsA('PlayerPawn')) { if( i==Level.Game.NumPlayers-1 && bFinalPacket==1) SendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), QueryNum, PacketNum, 1); else SendResult = SendQueryPacket(Addr, GetPlayer(PlayerPawn(P), i), QueryNum, PacketNum, 0); Result = SendResult || Result; i++; } P = P.nextPawn; } return Result; } // Get an arbitrary property from the level object. function string GetLevelProperty( string Prop ) { local string ResultSet; ResultSet = "\\"$Prop$"\\"$Level.GetPropertyText(Prop); return ResultSet; } // Get an arbitrary property from the game object. function string GetGameProperty( string Prop ) { local string ResultSet; ResultSet = "\\"$Prop$"\\"$Level.Game.GetPropertyText(Prop); return ResultSet; } // Get an arbitrary property from the players. function string GetPlayerProperty( string Prop ) { local string ResultSet; local int i; local PlayerPawn P; foreach AllActors(class'PlayerPawn', P) { i++; ResultSet = ResultSet$"\\"$Prop$"_"$i$"\\"$P.GetPropertyText(Prop); } return ResultSet; } €@PL‘ô+(-((‡·–‡—a/!(·‚𓇗& šR&-1L .ŽMN&é-1L .ŽMN%-(„-1-(¥µ-( s#~z a( Q€€ X X Jÿÿÿÿ| Jþÿÿÿl Jÿÿÿÿ/ Jþÿÿÿw rûÿÿÿ. X Jÿÿÿÿ Jþÿÿÿd JøÿÿÿG Jþÿÿÿv rýÿÿÿ8 Jÿÿÿÿ( kõÿÿÿM JÿÿÿÿK Jþÿÿÿm Jÿÿÿÿ@ Jÿÿÿÿ{ r÷ÿÿÿK JøÿÿÿF JþÿÿÿZ w÷ÿÿÿ3 lýÿÿÿ; Jþÿÿÿr lýÿÿÿ< rîÿÿÿ{ JøÿÿÿH wõÿÿÿO dêÿÿÿz wñÿÿÿP dûÿÿÿ JþÿÿÿY JþÿÿÿJ rûÿÿÿ@ Jþÿÿÿp dëÿÿÿ lðÿÿÿ4 dûÿÿÿ lðÿÿÿB wñÿÿÿO tíÿÿÿ6 víÿÿÿ7 lðÿÿÿ+ líÿÿÿ5 wðÿÿÿ9 vòÿÿÿC oêÿÿÿJ lîÿÿÿ, pûÿÿÿI w÷ÿÿÿ- dûÿÿÿ rîÿÿÿ: lýÿÿÿE rýÿÿÿ= wäÿÿÿR dõÿÿÿ$ dõÿÿÿ' xíÿÿÿD„> _!„‚> l!Œ|1 x!‘|PD"†|c R"†|b _"†|h k"†q w"„T D#„~T P#„|e \#™2 h#„] u#„{> A$„|f M$„g Y$„~g e$™’T q$•a ~$†j _0†W k0„‰> w0™—2 C1†~j P1„e \1„“n h1„) u1†—L A2„~e M2„’U Y2‘’V f2†ŽS s2Œ†a 2Œwa K3„†T W3„wT c3Œx1 o3Œ‡1 {3†\ H4Œ—1 T4†’\ `4„f l4„‡e x4„~f E5†o~ Q5„ƒ> ]5†^ i5„’} v5Œ—s B6Œt1 N6††c Z6†h f6„xn s6†xb 6†xc K7„|g X7††b e7„~A q7†ƒL ~7†wb K8Œs1 X8„ƒu d8„Š> q8„‡g }8„Šu J9„”> W9„‡Q c9„”u o9™` |9„‡A I:™ƒ2 U:„‡f b:„0 o:„A |:†xh H;‘—PU;†—b c;†—c p;‘xP };„|Q J<Œ“1 V<†—h b<†“c o<†“b |<‘“P I=¤" V=Œ_ b=†‡c n=†‡b {=„‡B H>‘‡PU>„~i c>‘†Po>„†? }>„i I?†wc U?„|T a?„w? m?Œ’y y?†’! F@‘wPR@†’ `@†’9 m@¤’ z@„“A FA†th SA†tc `A†tb mA‘tPzA‘oPHBй’$nVBŒo1 DGŠ ’WPGŠº’'cgMŠ´’]JOŠ pgPŒt[ WRŠ’+cRŠ¥’~NSŠlLUŒx[ xV„|[ DWŠUPWŠr eZ„{[ WdŠ’Scd„ƒ[ vhŒ[ BiŠGOiŠGVmŠ []tŒ~[ xu„‚[ EvŠ¥FQvŠ’^Wx„Š[ uzŠ}A{ŠD~}„‰[ B„‡[ NЧ 9ZŠ ES€„”[ XƒŠ Reƒ¡’N4Wjw‹•gNöŠ’quøŠ@fú¡N4KÃfû„[ q¾ŠO}¾Š’#%LÂŒ“[ qÂŒ—[ ~Â