feat(server): kernel TCP RTT for Player.getPing()

This commit is contained in:
itsRevela 2026-04-25 23:26:13 -05:00
parent 0708120ae8
commit 70a610fd2c
2 changed files with 33 additions and 3 deletions

View file

@ -109,10 +109,12 @@ public class Player : HumanEntity, OfflinePlayer, CommandSender
public ulong getRawOfflineXUID() => _playerRawOfflineXUID;
/// <summary>
/// Gets the player's estimated ping in milliseconds.
/// This value represents a weighted average of the response time to application layer ping packets sent. This value does not represent the network round trip time and as such may have less granularity and be impacted by other sources. For these reasons it should not be used for anti-cheat purposes. Its recommended use is only as a qualitative indicator of connection quality.
/// Gets the player's network round trip time in milliseconds.
/// On the dedicated Windows server this reads the kernel TCP RTT directly
/// (microsecond precision, untouched by tick scheduler delay). If the OS
/// query fails it falls back to a smoothed application keepalive value.
/// </summary>
/// <returns>The player's estimated ping in milliseconds.</returns>
/// <returns>The player's RTT in milliseconds, or -1 if unavailable.</returns>
public int getPing()
{
if (NativeBridge.GetPlayerLatency == null)

View file

@ -19,6 +19,7 @@
#include "../Minecraft.World/Biome.h"
#include "../Minecraft.World/LightLayer.h"
#include "../Minecraft.Client/Windows64/Network/WinsockNetLayer.h"
#include <mstcpip.h>
#include "../Minecraft.World/AbstractContainerMenu.h"
#include "../Minecraft.World/AddGlobalEntityPacket.h"
#include "../Minecraft.World/ArrayWithLength.h"
@ -643,6 +644,33 @@ int __cdecl NativeGetPlayerLatency(int entityId)
auto player = FindPlayer(entityId);
if (!player) return -1;
// Prefer the kernel's TCP round trip when available. Microsecond precision
// and free of the application-layer tick scheduler delay that smooths
// player->latency upward by ~one tick interval per direction.
if (player->connection && player->connection->connection &&
player->connection->connection->getSocket())
{
unsigned char smallId = player->connection->connection->getSocket()->getSmallId();
if (smallId != 0)
{
SOCKET sock = WinsockNetLayer::GetSocketForSmallId(smallId);
if (sock != INVALID_SOCKET)
{
TCP_INFO_v0 info = {};
DWORD infoVersion = 0;
DWORD bytesReturned = 0;
int rc = WSAIoctl(sock, SIO_TCP_INFO,
&infoVersion, sizeof(infoVersion),
&info, sizeof(info),
&bytesReturned, NULL, NULL);
if (rc == 0 && bytesReturned == sizeof(info))
{
return (int)(info.RttUs / 1000);
}
}
}
}
return player->latency;
}