@@ -34,7 +34,9 @@ public class CodRConConnection : IRConConnection
3434 private readonly ILogger _log ;
3535 private readonly Encoding _gameEncoding ;
3636 private readonly int _retryAttempts ;
37- private static readonly Server . Game [ ] RconDelayGames = [ Server . Game . IW3 , Server . Game . T4 , Server . Game . T5 , Server . Game . T6 ] ;
37+
38+ private static readonly Server . Game [ ] RconDelayGames =
39+ [ Server . Game . IW3 , Server . Game . T4 , Server . Game . T5 , Server . Game . T6 ] ;
3840
3941 public CodRConConnection ( IPEndPoint ipEndpoint , string password , ILogger < CodRConConnection > log ,
4042 Encoding gameEncoding , int retryAttempts )
@@ -168,7 +170,8 @@ string ConvertEncoding(string text)
168170 break ;
169171 case StaticHelpers . QueryType . GET_STATUS :
170172 waitForResponse = true ;
171- payload = ( _config . CommandPrefixes . RConGetStatus + '\0 ' ) . Select ( Helpers . SafeConversion ) . ToArray ( ) ;
173+ payload = ( _config . CommandPrefixes . RConGetStatus + '\0 ' ) . Select ( Helpers . SafeConversion )
174+ . ToArray ( ) ;
172175 break ;
173176 case StaticHelpers . QueryType . GET_INFO :
174177 waitForResponse = true ;
@@ -197,13 +200,11 @@ string ConvertEncoding(string text)
197200 byte [ ] [ ] response ;
198201
199202 retrySend :
200- using ( var socket = new Socket ( AddressFamily . InterNetwork , SocketType . Dgram , ProtocolType . Udp )
201- {
202- DontFragment = false ,
203- Ttl = 100 ,
204- ExclusiveAddressUse = true ,
205- } )
203+ using ( var socket = new Socket ( AddressFamily . InterNetwork , SocketType . Dgram , ProtocolType . Udp ) )
206204 {
205+ socket . DontFragment = false ;
206+ socket . Ttl = 100 ;
207+ socket . ExclusiveAddressUse = true ;
207208 if ( ! token . IsCancellationRequested )
208209 {
209210 connectionState . ConnectionAttempts ++ ;
@@ -309,7 +310,7 @@ string ConvertEncoding(string text)
309310 {
310311 _log . LogDebug ( "Received empty response for RCon request {@Query}" ,
311312 new { endpoint = Endpoint . ToString ( ) , type , parameters } ) ;
312- return Array . Empty < string > ( ) ;
313+ return [ ] ;
313314 }
314315
315316 var responseString = type == StaticHelpers . QueryType . COMMAND_STATUS
@@ -370,7 +371,7 @@ private async Task<byte[][]> SendPayloadAsync(Socket rconSocket, byte[] payload,
370371
371372 if ( ! waitForResponse )
372373 {
373- return Array . Empty < byte [ ] > ( ) ;
374+ return [ ] ;
374375 }
375376
376377 _log . LogDebug ( "Waiting to asynchronously receive data on attempt #{ConnectionAttempts}" ,
@@ -380,7 +381,7 @@ private async Task<byte[][]> SendPayloadAsync(Socket rconSocket, byte[] payload,
380381
381382 if ( RconDelayGames . Contains ( _parser . GameName ) )
382383 {
383- await Task . Delay ( 100 , token ) ;
384+ await Task . Delay ( 100 , token ) ;
384385 }
385386
386387 while ( rconSocket . Available > 0 )
@@ -447,7 +448,7 @@ private string[] ValidateResponse(StaticHelpers.QueryType type, string responseS
447448
448449 if ( headerSplit . Length == 2 )
449450 {
450- return headerSplit . Last ( ) . Split ( new [ ] { '\n ' } , StringSplitOptions . RemoveEmptyEntries )
451+ return headerSplit . Last ( ) . Split ( [ '\n ' ] , StringSplitOptions . RemoveEmptyEntries )
451452 . Select ( line => line . StartsWith ( "^7" ) ? line [ 2 ..] : line ) . ToArray ( ) ;
452453 }
453454
@@ -462,31 +463,75 @@ private string[] ValidateResponse(StaticHelpers.QueryType type, string responseS
462463
463464 /// <summary>
464465 /// reassembles broken status segments into the 'correct' ordering
465- /// <remarks>this is primarily for T7, and is really only reliable for 2 segments</remarks>
466+ /// <remarks>this is primarily for T7, CoD4x, and T6. Really only reliable for 3 segments</remarks>
466467 /// </summary>
467468 /// <param name="segments">array of segmented byte arrays</param>
468469 /// <returns></returns>
469470 private string ReassembleSegmentedStatus ( IEnumerable < byte [ ] > segments )
470471 {
471- var splitStatusStrings = new List < string > ( ) ;
472+ var segmentStrings = segments
473+ . Select ( seg => _gameEncoding . GetString ( seg , 0 , seg . Length ) . TrimEnd ( '\0 ' ) )
474+ . ToList ( ) ;
475+
476+ if ( segmentStrings . Count <= 1 )
477+ {
478+ return string . Join ( "" , segmentStrings ) ;
479+ }
480+
481+ var headerIndex = segmentStrings . FindIndex ( s => _config . StatusHeader . PatternMatcher . Match ( s ) . Success ) ;
472482
473- foreach ( var segment in segments )
483+ // when there's no header it'll likely fail anyway so we'll keep the original order
484+ if ( headerIndex == - 1 )
474485 {
475- var responseString = _gameEncoding . GetString ( segment , 0 , segment . Length ) ;
476- var statusHeaderMatch = _config . StatusHeader . PatternMatcher . Match ( responseString ) ;
477- if ( statusHeaderMatch . Success )
486+ return string . Join ( "" , segmentStrings . Select ( s => s . Replace ( _config . CommandPrefixes . RConResponse , "" ) ) ) ;
487+ }
488+
489+ var reassembledSegments = new List < string > ( ) ;
490+
491+ // for T6 status the last packet contains a double new line
492+ var hasDefinitiveLastSegment = segmentStrings . Any ( s => s . EndsWith ( "\n \n " ) ) ;
493+
494+ if ( hasDefinitiveLastSegment )
495+ {
496+ // T6 behavior
497+ var firstSegment = segmentStrings [ headerIndex ] ;
498+ string lastSegment = null ;
499+ var middleSegments = new List < string > ( ) ;
500+
501+ for ( var i = 0 ; i < segmentStrings . Count ; i ++ )
478502 {
479- splitStatusStrings . Insert ( 0 , responseString . TrimEnd ( '\0 ' ) ) ;
503+ if ( i == headerIndex )
504+ continue ;
505+
506+ var currentSegment = segmentStrings [ i ] ;
507+
508+ if ( currentSegment . EndsWith ( "\n \n " ) && lastSegment == null )
509+ {
510+ lastSegment = currentSegment . Replace ( _config . CommandPrefixes . RConResponse , "" ) ;
511+ }
512+ else
513+ {
514+ middleSegments . Add ( currentSegment . Replace ( _config . CommandPrefixes . RConResponse , "" ) ) ;
515+ }
480516 }
481517
482- else
518+ reassembledSegments . Add ( firstSegment ) ;
519+ reassembledSegments . AddRange ( middleSegments ) ;
520+
521+ if ( lastSegment != null )
483522 {
484- splitStatusStrings . Add ( responseString . Replace ( _config . CommandPrefixes . RConResponse , "" )
485- . TrimEnd ( '\0 ' ) ) ;
523+ reassembledSegments . Add ( lastSegment ) ;
486524 }
487525 }
526+ else
527+ {
528+ // other game (default) behavior
529+ reassembledSegments . Add ( segmentStrings [ headerIndex ] ) ;
530+ reassembledSegments . AddRange ( segmentStrings . Where ( ( _ , i ) => i != headerIndex )
531+ . Select ( t => t . Replace ( _config . CommandPrefixes . RConResponse , "" ) ) ) ;
532+ }
488533
489- return string . Join ( "" , splitStatusStrings ) ;
534+ return string . Join ( "" , reassembledSegments ) ;
490535 }
491536
492537 /// <summary>
0 commit comments