Repository navigation
Conversation
Players could not compare the latency of public servers without joining each one (tiltedphoques#374). Add a Ping column that players can sort. The client sends each listed server the first packet of a GameNetworkingSockets connection. The server answers it without opening a connection, so this works with all running servers and needs no server change. Also align the header with its columns. It kept 1rem free for a 0.7rem scrollbar, and long names or version strings pushed the fixed-width columns out of line. Fix the "Addresse" typo in the French Connect box.
The request struct and the reply check repeated the same protocol values. Name each value once, and check `MsgLength` against the real body size in the `static_assert`, so a wrong length fails the build.
jqntn
force-pushed
the
feat/server-list-ping
branch
from
November 5, 2026 23:58
e82b776 to
a02963b
Compare
jqntn
marked this pull request as ready for review
November 5, 2026 23:58
The client read ping replies once per frame, so each value was up to one frame too high: 8 ms on average at 60 fps, more at lower frame rates. Read them on a thread that timestamps each reply when it arrives, and send the results to the UI on the next frame. Each list load or Refresh opens a new socket and thread. A setup failure or a stopped thread then lasts only until the next Refresh, and late replies to an earlier list are dropped. Log these failures, and keep reading after `WSAENETRESET`, which an expired earlier ping can cause.
The client sent a probe to every listed server at once, about 50 KB for 100 servers. On a slow upload the last probes wait behind the first ones, about 0.4 s at 1 Mbps, and their ping reads that much too high. Send one probe per frame, at most one every 10 ms. A list of 100 servers then fills in over about 1.7 s at 60 fps.
Probes go out one per frame in list order, and the list hides servers with another version by default, often most of them. Send the servers with the client's version first, so the servers the player sees get a ping within about 0.3 s instead of up to 1.4 s.
jqntn
force-pushed
the
feat/server-list-ping
branch
from
November 6, 2026 00:39
a02963b to
0ce3889
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a Ping column to the public server list, so players can find a server with a low ping before they join. Players can sort the list by ping. A server that does not answer shows no ping.
Before:

After:

2560×1440, 3840×2160, and sorted by ping
How it works:
pingServerscall, with compatible servers first. Each server gets one probe.ChallengeRequestover UDP. This is the first packet of a connection. It holds an id from the UI inconnection_idand the send time inmy_timestamp.ChallengeReply, which echoes these two values. The server does not open a connection and does not log the packet. So this works with all running servers, and the server needs no change.OverlayServicesendsserverPing(id, ms)to the UI on the next frame. Reading the replies once per frame instead made values 8 ms too high on average at 60 fps.TiltedOnlinePCH.hnow includeswinsock2.hbeforewindows.h. Without this,windows.hincludes the oldwinsock.h, and the IPv6 types fromws2tcpip.hdo not compile. No other client code used Winsock, and the client builds with the same warnings as before.Packet layout, from GameNetworkingSockets v1.4.1 (the version in
xmake.lua): message definitions, server reply. The request must be padded to 512 bytes.This also fixes three alignment bugs in the list:
1remfree for the scrollbar, but the scrollbar is0.7rem(--scrollbar-thickness). The header columns were about 5px to the left of the rows.The blue lines mark the left edge of each header cell. They are not part of the UI.
New key:
COMPONENT.SERVER_LIST.TABLE_HEADERS.PING. Most languages use "Ping". Korean uses 핑, Russian Пинг, Ukrainian Пінг and Chinese 延迟.This also fixes a typo in the French Connect box. "Addresse" is now "Adresse" in the address field and in its format hint.
Tested
WSAECONNRESET, and the thread keeps reading. A Refresh while probes are still going out reopens the socket and thread in under 0.5 ms, and no late reply from the earlier list gets through. On shutdown, the thread stops (WSAEINTR) and is joined in less than 1 ms.SkyrimTogetherClient,SkyrimImmersiveLauncherandTPProcessbuild in releasedbg with MSVC 14.51 (VS 2026). Ondev,SkyrimImmersiveLauncherdoes not compile with this MSVC (constinitinMemoryLayout.cpp). I removedconstinitlocally only, to check the link.ng serve --configuration=browser) on Chrome for Testing 141.0.7390.122. The game's CEF 141.0.11 uses Chromium 141.0.7390.123. I checked the live server list and the mock list at 6 resolutions, from 1280×720 to 3840×2160, and at 1920×1080 with all 5 font sizes. All headers line up with their columns (less than 1px), no cell overflows its width, and no name or ping is taller than its row. The Ping header fits in all 15 languages with the M and XL fonts.ng build --configuration=productionpasses.Not tested in game.
The screenshots use a mock server list with fixed ping values.
Replaces #943, after the discussion there. Part of #374.