@@ -24,7 +24,6 @@ public sealed partial class Player {
2424 const int SocketPollInterval = 100 ; // multiples of SleepDelay, approx. 1 second
2525 const int PingInterval = 1 ; // multiples of SocketPollInterval, approx. 3 seconds
2626 public DateTime LastZoneNotification = DateTime . UtcNow ;
27- public Stopwatch pingTimer = new Stopwatch ( ) ;
2827
2928 static Player ( ) {
3029 MaxBlockPlacementRange = 32767 ;
@@ -156,11 +155,15 @@ void IoLoop() {
156155 LeaveReason = LeaveReason . ClientQuit ;
157156 return ;
158157 }
158+
159159 if ( pingCounter > PingInterval ) {
160- writer . Write ( OpCode . Ping ) ;
161- pingTimer . Reset ( ) ;
162- pingTimer . Start ( ) ;
163- BytesSent ++ ;
160+ if ( Supports ( CpeExt . TwoWayPing ) ) {
161+ SendNow ( Packet . MakeTwoWayPing ( true , NextTwoWayPingData ( ) ) ) ;
162+ } else {
163+ writer . Write ( OpCode . Ping ) ;
164+ BytesSent ++ ;
165+ }
166+
164167 pingCounter = 0 ;
165168 MeasureBandwidthUseRates ( ) ;
166169 }
@@ -273,6 +276,10 @@ void IoLoop() {
273276 case OpCode . PlayerClick :
274277 ProcessPlayerClickPacket ( ) ;
275278 break ;
279+
280+ case OpCode . TwoWayPing :
281+ ProcessTwoWayPingPacket ( ) ;
282+ break ;
276283
277284 case OpCode . Ping :
278285 ProcessPingPacket ( ) ;
@@ -313,21 +320,29 @@ void IoLoop() {
313320 }
314321 }
315322 #endregion
323+
324+ ushort NextTwoWayPingData ( ) {
325+ // Find free ping slot
326+ for ( int i = 0 ; i < PingList . Length ; i ++ ) {
327+ if ( PingList [ i ] . TimeSent . Ticks == 0 ) continue ;
328+
329+ ushort prev = i > 0 ? PingList [ i - 1 ] . Data : ( ushort ) 0 ;
330+ PingList [ i ] . Data = ( ushort ) ( prev + 1 ) ;
331+ PingList [ i ] . TimeSent = DateTime . UtcNow ;
332+ return ( ushort ) ( prev + 1 ) ;
333+ }
334+
335+ // Remove oldest ping slot
336+ for ( int i = 0 ; i < PingList . Length - 1 ; i ++ ) {
337+ PingList [ i ] = PingList [ i + 1 ] ;
338+ }
339+
340+ PingList [ PingList . Length - 1 ] . Data ++ ;
341+ PingList [ PingList . Length - 1 ] . TimeSent = DateTime . UtcNow ;
342+ return PingList [ PingList . Length - 1 ] . Data ;
343+ }
316344
317- public void ProcessPingPacket ( ) {
318- pingTimer . Stop ( ) ;
319- int total = 0 ;
320- for ( int i = 0 ; i < 10 ; i ++ ) {
321- if ( i == 9 ) {
322- PingList [ i ] = ( int ) pingTimer . ElapsedMilliseconds ;
323- } else {
324- PingList [ i ] = PingList [ i + 1 ] ;
325- }
326- total += PingList [ i ] ;
327- }
328- if ( ! IsPlayingCTF ) {
329- Message ( ( byte ) MessageType . BottomRight3 , "&SPing: &f{0}&Sms Avg: &f{1}&Sms" , PingList [ 9 ] , PingList . Average ( ) ) ;
330- }
345+ void ProcessPingPacket ( ) {
331346 BytesReceived ++ ;
332347 }
333348
@@ -518,7 +533,7 @@ void ProcessSetBlockPacket() {
518533 }
519534
520535 PlaceBlockWithEvents ( coords , action , ( Block ) type ) ;
521- }
536+ }
522537
523538 void ProcessPlayerClickPacket ( ) {
524539 BytesReceived += 15 ;
@@ -532,6 +547,25 @@ void ProcessPlayerClickPacket() {
532547 short targetBlockZ = reader . ReadInt16 ( ) ;
533548 byte targetBlockFace = reader . ReadByte ( ) ;
534549 }
550+
551+ void ProcessTwoWayPingPacket ( ) {
552+ bool serverToClient = reader . ReadByte ( ) != 0 ;
553+ ushort data = reader . ReadUInt16 ( ) ;
554+ BytesReceived += 3 ;
555+
556+ // Client-> server ping, immediately reply.
557+ if ( ! serverToClient ) {
558+ SendNow ( Packet . MakeTwoWayPing ( false , data ) ) ;
559+ return ;
560+ }
561+
562+ // Got a response for a server->client ping, set the time received.
563+ for ( int i = 0 ; i < PingList . Length ; i ++ ) {
564+ if ( PingList [ i ] . Data != data ) continue ;
565+ PingList [ i ] . TimeReceived = DateTime . UtcNow ;
566+ break ;
567+ }
568+ }
535569
536570
537571 void Disconnect ( ) {
0 commit comments