44import dsns .betterhud .util .CustomText ;
55import dsns .betterhud .util .ModSettings ;
66import net .minecraft .client .MinecraftClient ;
7- import net .minecraft .entity .player .PlayerEntity ;
7+ import net .minecraft .client .network .ServerAddress ;
8+ import net .minecraft .client .network .ServerInfo ;
9+
10+ import java .io .*;
11+ import java .net .InetSocketAddress ;
12+ import java .net .Socket ;
13+ import java .util .concurrent .CompletableFuture ;
814
915public class Ping implements BaseMod {
1016
1117 private static final ModSettings SETTINGS = new ModSettings ("top-left" );
12-
1318 private static long lastPingSent = 0 ;
1419 private static long lastPingValue = -1 ;
1520 private static final long PING_INTERVAL_MS = 10000 ;
@@ -32,9 +37,12 @@ public CustomText onStartTick(MinecraftClient client) {
3237 long currentTime = System .currentTimeMillis ();
3338
3439 if (currentTime - lastPingSent >= PING_INTERVAL_MS ) {
35- lastPingSent = now ;
36- client .getNetworkHandler ().sendPacket (
37- new net .minecraft .network .packet .c2s .query .PingRequestC2SPacket (currentTime ));
40+ lastPingSent = currentTime ;
41+
42+ ServerInfo serverData = client .getCurrentServerEntry ();
43+ if (serverData != null ) {
44+ fetchManualPing (serverData .address );
45+ }
3846 }
3947
4048 if (lastPingValue == -1 ) {
@@ -44,8 +52,82 @@ public CustomText onStartTick(MinecraftClient client) {
4452 return new CustomText (lastPingValue + " ms" , getModSettings ());
4553 }
4654
47- // Called when server responds
48- public static void handlePingResponse (long sentTime ) {
49- lastPingValue = System .currentTimeMillis () - sentTime ;
55+ private void fetchManualPing (String addressStr ) {
56+ CompletableFuture .runAsync (() -> {
57+ try {
58+ ServerAddress address = ServerAddress .parse (addressStr );
59+ try (Socket socket = new Socket ()) {
60+ socket .connect (new InetSocketAddress (address .getAddress (), address .getPort ()), 3000 );
61+ DataOutputStream out = new DataOutputStream (socket .getOutputStream ());
62+ DataInputStream in = new DataInputStream (socket .getInputStream ());
63+
64+ // 1. Handshake Packet (ID 0x00, State 1)
65+ ByteArrayOutputStream b = new ByteArrayOutputStream ();
66+ DataOutputStream handshake = new DataOutputStream (b );
67+ writeVarInt (handshake , 0x00 );
68+ writeVarInt (handshake , 765 ); // Protocol version for 1.20.4+
69+ writeString (handshake , address .getAddress ());
70+ handshake .writeShort (address .getPort ());
71+ writeVarInt (handshake , 1 );
72+ writePacket (out , b );
73+
74+ // 2. Status Request Packet (ID 0x00)
75+ b .reset ();
76+ writeVarInt (handshake , 0x00 );
77+ writePacket (out , b );
78+
79+ // 3. Ping Packet (ID 0x01)
80+ long startTime = System .currentTimeMillis ();
81+ b .reset ();
82+ writeVarInt (handshake , 0x01 );
83+ handshake .writeLong (startTime );
84+ writePacket (out , b );
85+
86+ // 4. Read Response
87+ readVarInt (in ); // Size of packet
88+ int packetId = readVarInt (in );
89+ if (packetId == 0x01 ) {
90+ long echoedTime = in .readLong ();
91+ lastPingValue = System .currentTimeMillis () - echoedTime ;
92+ }
93+ }
94+ } catch (Exception e ) {
95+ // Server might be blocking rapid pings or connection timed out
96+ lastPingValue = -2 ; // Indicator for "Timed Out/Error"
97+ }
98+ });
99+ }
100+
101+ private void writeVarInt (DataOutputStream out , int value ) throws IOException {
102+ while ((value & -128 ) != 0 ) {
103+ out .writeByte (value & 127 | 128 );
104+ value >>>= 7 ;
105+ }
106+ out .writeByte (value );
107+ }
108+
109+ private int readVarInt (DataInputStream in ) throws IOException {
110+ int i = 0 ;
111+ int j = 0 ;
112+ while (true ) {
113+ byte b = in .readByte ();
114+ i |= (b & 127 ) << j ++ * 7 ;
115+ if (j > 5 )
116+ throw new RuntimeException ("VarInt too big" );
117+ if ((b & 128 ) != 128 )
118+ break ;
119+ }
120+ return i ;
121+ }
122+
123+ private void writeString (DataOutputStream out , String s ) throws IOException {
124+ byte [] bytes = s .getBytes ("UTF-8" );
125+ writeVarInt (out , bytes .length );
126+ out .write (bytes );
127+ }
128+
129+ private void writePacket (DataOutputStream out , ByteArrayOutputStream b ) throws IOException {
130+ writeVarInt (out , b .size ());
131+ out .write (b .toByteArray ());
50132 }
51- }
133+ }
0 commit comments