diff --git a/OpenRA.Game/Network/GameServer.cs b/OpenRA.Game/Network/GameServer.cs index fed810d5fb..c31e2a01cd 100644 --- a/OpenRA.Game/Network/GameServer.cs +++ b/OpenRA.Game/Network/GameServer.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; +using System.Net.NetworkInformation; namespace OpenRA.Network { @@ -65,5 +66,21 @@ namespace OpenRA.Network return UsefulMods.All(m => Game.CurrentMods.ContainsKey(m.Key) && AreVersionsCompatible(m.Value, Game.CurrentMods[m.Key].Version)); } + + public int Latency = -1; + bool hasBeenPinged; + public void Ping() + { + if (!hasBeenPinged) + { + hasBeenPinged = true; + var pingSender = new Ping(); + PingReply reply = pingSender.Send(Address.Split(':')[0]); + if (reply != null && reply.Status == IPStatus.Success) + Latency = (int)reply.RoundtripTime; + else + Latency = -1; + } + } } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs index 10cc1e79bc..5301818b52 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs @@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic Action OpenLobby; Action OnExit; - enum SearchStatus { Fetching, Failed, NoGames, Hidden } + enum SearchStatus { Fetching, Failed, NoGames, Hidden, Pinging } SearchStatus searchStatus = SearchStatus.Fetching; bool showWaiting = true; @@ -41,6 +41,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic case SearchStatus.Fetching: return "Fetching game list..."; case SearchStatus.Failed: return "Failed to contact master server."; case SearchStatus.NoGames: return "No games found."; + case SearchStatus.Pinging: return "Pinging compatible servers."; default: return ""; } } @@ -58,6 +59,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic refreshButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; refreshButton.OnClick = () => ServerList.Query(games => RefreshServerList(panel, games)); + var pingButton = panel.Get("PING_BUTTON"); + pingButton.IsDisabled = () => searchStatus == SearchStatus.Pinging || + searchStatus == SearchStatus.Fetching || searchStatus == SearchStatus.Failed; + pingButton.OnClick = () => ServerList.Query(games => PingServerList(panel, games)); + var join = panel.Get("JOIN_BUTTON"); join.IsDisabled = () => currentServer == null || !currentServer.CanJoin(); join.OnClick = () => Join(currentServer); @@ -147,6 +153,33 @@ namespace OpenRA.Mods.RA.Widgets.Logic return s.UsefulMods.Select(m => GenerateModLabel(m)).JoinWith("\n"); } + public static string GetPing(GameServer s) + { + if (s.Latency > -1) + return "Ping: {0} ms".F(s.Latency); + else + return "Ping: ? ms"; + } + + public void PingServerList(Widget panel, IEnumerable games) + { + searchStatus = SearchStatus.Pinging; + + foreach (var loop in games.Where(g => g.CanJoin())) + { + var game = loop; + + if (game == null) + continue; + + game.Ping(); + } + + searchStatus = SearchStatus.Hidden; + + RefreshServerList(panel, games); + } + public void RefreshServerList(Widget panel, IEnumerable games) { var sl = panel.Get("SERVER_LIST"); @@ -229,6 +262,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic version.GetText = () => GenerateModsLabel(game); version.IsVisible = () => !game.CompatibleVersion(); + var ping = item.Get("PING"); + ping.GetText = () => GetPing(game); + ping.IsVisible = () => game.CompatibleVersion(); + + // TODO: Display game.Location once https://github.com/OpenRA/OpenRAMasterServer/pull/12 is merged + if (!canJoin) { title.GetColor = () => Color.Gray; diff --git a/mods/ra/chrome/serverbrowser.yaml b/mods/ra/chrome/serverbrowser.yaml index 2c5efdc514..0271d38dbe 100644 --- a/mods/ra/chrome/serverbrowser.yaml +++ b/mods/ra/chrome/serverbrowser.yaml @@ -101,25 +101,37 @@ Background@JOINSERVER_BG: Y:40 Align:Right Height:25 - + Label@PING: + Width:140 + X:PARENT_RIGHT-150 + Y:40 + Align:Right + Height:25 Label@PROGRESS_LABEL: X:(PARENT_RIGHT - WIDTH) / 2 Y:PARENT_BOTTOM / 2 - HEIGHT Width:150 Height:30 Text:Fetching games... - Align:Center + Align:Center Button@REFRESH_BUTTON: X:20 Y:PARENT_BOTTOM - 45 - Width:120 + Width:100 Height:25 Text:Refresh Font:Bold + Button@PING_BUTTON: + X:140 + Y:PARENT_BOTTOM - 45 + Width:100 + Height:25 + Text:Ping + Font:Bold Button@JOIN_BUTTON: X:PARENT_RIGHT - 140 - 130 Y:PARENT_BOTTOM - 45 - Width:120 + Width:100 Height:25 Text:Join Font:Bold @@ -127,7 +139,7 @@ Background@JOINSERVER_BG: Button@BACK_BUTTON: X:PARENT_RIGHT - 140 Y:PARENT_BOTTOM - 45 - Width:120 + Width:100 Height:25 Text:Cancel Font:Bold