diff --git a/src/main/java/org/nethergames/proxytransport/impl/TransportClientConnection.java b/src/main/java/org/nethergames/proxytransport/impl/TransportClientConnection.java index 11d1800..d689654 100644 --- a/src/main/java/org/nethergames/proxytransport/impl/TransportClientConnection.java +++ b/src/main/java/org/nethergames/proxytransport/impl/TransportClientConnection.java @@ -10,6 +10,11 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.epoll.EpollSocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.incubator.codec.quic.QuicChannel; +import io.netty.incubator.codec.quic.QuicConnectionStats; +import io.netty.util.concurrent.Future; import lombok.NonNull; import lombok.extern.log4j.Log4j2; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; @@ -56,7 +61,7 @@ public TransportClientConnection(ProxiedPlayer player, ServerInfo serverInfo, Ch this.channel = channel; this.channel.closeFuture().addListener(future -> cleanActiveChannels()); - scheduledTasks.add(channel.eventLoop().scheduleAtFixedRate(this::sendAcknowledge, PING_CYCLE_TIME, PING_CYCLE_TIME, TimeUnit.SECONDS)); + scheduledTasks.add(channel.eventLoop().scheduleAtFixedRate(this::collectStats, PING_CYCLE_TIME, PING_CYCLE_TIME, TimeUnit.SECONDS)); scheduledTasks.add(channel.eventLoop().scheduleAtFixedRate(() -> packetSendingLimit.set(0), 1, 1, TimeUnit.SECONDS)); } @@ -100,7 +105,8 @@ private void onBedrockBatch(@NonNull BedrockBatchWrapper batch) { wrapper.release(); // release batch.modify(); - receiveAcknowledge(); + this.latency = (System.currentTimeMillis() - this.lastPingTimestamp) / 2; + this.broadcastPing(); } } } @@ -165,25 +171,37 @@ public long getPing() { return latency; } - public void sendAcknowledge() { + public void collectStats() { var connection = getPlayer().getDownstreamConnection(); if (connection instanceof TransportClientConnection && connection.getServerInfo().getServerName().equalsIgnoreCase(getServerInfo().getServerName())) { - NetworkStackLatencyPacket packet = new NetworkStackLatencyPacket(); - packet.setTimestamp(0L); - packet.setFromServer(true); - - sendPacket(packet); - - lastPingTimestamp = System.currentTimeMillis(); + if (this.channel instanceof NioSocketChannel) { + NetworkStackLatencyPacket packet = new NetworkStackLatencyPacket(); + packet.setTimestamp(0L); + packet.setFromServer(true); + + sendPacket(packet); + + this.lastPingTimestamp = System.currentTimeMillis(); + } else if (this.channel instanceof EpollSocketChannel epollChannel) { + this.latency = epollChannel.tcpInfo().rtt() / 2; + this.broadcastPing(); + } else if (this.channel instanceof QuicChannel quicChannel) { + quicChannel.collectStats().addListener((Future future) -> { + if (future.isSuccess()) { + QuicConnectionStats stats = future.getNow(); + + this.latency = stats.recv(); + this.broadcastPing(); + } + }); + } } } - private void receiveAcknowledge() { - latency = (System.currentTimeMillis() - lastPingTimestamp) / 2; - + private void broadcastPing() { TickSyncPacket latencyPacket = new TickSyncPacket(); latencyPacket.setRequestTimestamp(getPlayer().getPing()); - latencyPacket.setResponseTimestamp(latency); + latencyPacket.setResponseTimestamp(this.latency); sendPacket(latencyPacket); }