Merge pull request #2996 from Mailaender/serverbrowser-usability
Added filters and ping to server browser
This commit is contained in:
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace OpenRA.Network
|
namespace OpenRA.Network
|
||||||
{
|
{
|
||||||
@@ -65,5 +67,33 @@ namespace OpenRA.Network
|
|||||||
return UsefulMods.All(m => Game.CurrentMods.ContainsKey(m.Key)
|
return UsefulMods.All(m => Game.CurrentMods.ContainsKey(m.Key)
|
||||||
&& AreVersionsCompatible(m.Value, Game.CurrentMods[m.Key].Version));
|
&& 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();
|
||||||
|
pingSender.PingCompleted += new PingCompletedEventHandler(pongRecieved);
|
||||||
|
AutoResetEvent waiter = new AutoResetEvent(false);
|
||||||
|
pingSender.SendAsync(Address.Split(':')[0], waiter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pongRecieved(object sender, PingCompletedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Cancelled || e.Error != null)
|
||||||
|
Latency = -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PingReply pong = e.Reply;
|
||||||
|
if (pong != null && pong.Status == IPStatus.Success)
|
||||||
|
Latency = (int)pong.RoundtripTime;
|
||||||
|
else
|
||||||
|
Latency = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using System.Linq;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.Network;
|
using OpenRA.Network;
|
||||||
|
using OpenRA.Server;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
namespace OpenRA.Mods.RA.Widgets.Logic
|
namespace OpenRA.Mods.RA.Widgets.Logic
|
||||||
@@ -25,9 +26,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
Action OpenLobby;
|
Action OpenLobby;
|
||||||
Action OnExit;
|
Action OnExit;
|
||||||
|
|
||||||
enum SearchStatus { Fetching, Failed, NoGames, Hidden }
|
enum SearchStatus { Fetching, Failed, NoGames, Hidden, Pinging }
|
||||||
SearchStatus searchStatus = SearchStatus.Fetching;
|
SearchStatus searchStatus = SearchStatus.Fetching;
|
||||||
|
|
||||||
|
bool showWaiting = true;
|
||||||
|
bool showEmpty = true;
|
||||||
|
bool showStarted = true;
|
||||||
|
bool showIncompatible = false;
|
||||||
|
|
||||||
public string ProgressLabelText()
|
public string ProgressLabelText()
|
||||||
{
|
{
|
||||||
switch (searchStatus)
|
switch (searchStatus)
|
||||||
@@ -35,6 +41,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
case SearchStatus.Fetching: return "Fetching game list...";
|
case SearchStatus.Fetching: return "Fetching game list...";
|
||||||
case SearchStatus.Failed: return "Failed to contact master server.";
|
case SearchStatus.Failed: return "Failed to contact master server.";
|
||||||
case SearchStatus.NoGames: return "No games found.";
|
case SearchStatus.NoGames: return "No games found.";
|
||||||
|
case SearchStatus.Pinging: return "Pinging compatible servers.";
|
||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,13 +57,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
// Menu buttons
|
// Menu buttons
|
||||||
var refreshButton = panel.Get<ButtonWidget>("REFRESH_BUTTON");
|
var refreshButton = panel.Get<ButtonWidget>("REFRESH_BUTTON");
|
||||||
refreshButton.IsDisabled = () => searchStatus == SearchStatus.Fetching;
|
refreshButton.IsDisabled = () => searchStatus == SearchStatus.Fetching;
|
||||||
refreshButton.OnClick = () =>
|
refreshButton.OnClick = () => ServerList.Query(games => RefreshServerList(panel, games));
|
||||||
|
|
||||||
|
var pingButton = panel.GetOrNull<ButtonWidget>("PING_BUTTON");
|
||||||
|
if (pingButton != null)
|
||||||
{
|
{
|
||||||
searchStatus = SearchStatus.Fetching;
|
pingButton.IsDisabled = () => searchStatus == SearchStatus.Pinging ||
|
||||||
sl.RemoveChildren();
|
searchStatus == SearchStatus.Fetching || searchStatus == SearchStatus.Failed;
|
||||||
currentServer = null;
|
pingButton.OnClick = () => ServerList.Query(games => PingServerList(panel, games));
|
||||||
ServerList.Query(games => RefreshServerList(panel, games));
|
}
|
||||||
};
|
|
||||||
|
|
||||||
var join = panel.Get<ButtonWidget>("JOIN_BUTTON");
|
var join = panel.Get<ButtonWidget>("JOIN_BUTTON");
|
||||||
join.IsDisabled = () => currentServer == null || !currentServer.CanJoin();
|
join.IsDisabled = () => currentServer == null || !currentServer.CanJoin();
|
||||||
@@ -73,6 +82,34 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
progressText.IsVisible = () => searchStatus != SearchStatus.Hidden;
|
progressText.IsVisible = () => searchStatus != SearchStatus.Hidden;
|
||||||
progressText.GetText = ProgressLabelText;
|
progressText.GetText = ProgressLabelText;
|
||||||
|
|
||||||
|
var showWaitingCheckbox = panel.GetOrNull<CheckboxWidget>("WAITING_FOR_PLAYERS");
|
||||||
|
if (showWaitingCheckbox != null)
|
||||||
|
{
|
||||||
|
showWaitingCheckbox.IsChecked = () => showWaiting;
|
||||||
|
showWaitingCheckbox.OnClick = () => { showWaiting ^= true; ServerList.Query(games => RefreshServerList(panel, games)); };
|
||||||
|
}
|
||||||
|
|
||||||
|
var showEmptyCheckbox = panel.GetOrNull<CheckboxWidget>("EMPTY");
|
||||||
|
if (showEmptyCheckbox != null)
|
||||||
|
{
|
||||||
|
showEmptyCheckbox.IsChecked = () => showEmpty;
|
||||||
|
showEmptyCheckbox.OnClick = () => { showEmpty ^= true; ServerList.Query(games => RefreshServerList(panel, games)); };
|
||||||
|
}
|
||||||
|
|
||||||
|
var showAlreadyStartedCheckbox = panel.GetOrNull<CheckboxWidget>("ALREADY_STARTED");
|
||||||
|
if (showAlreadyStartedCheckbox != null)
|
||||||
|
{
|
||||||
|
showAlreadyStartedCheckbox.IsChecked = () => showStarted;
|
||||||
|
showAlreadyStartedCheckbox.OnClick = () => { showStarted ^= true; ServerList.Query(games => RefreshServerList(panel, games)); };
|
||||||
|
}
|
||||||
|
|
||||||
|
var showIncompatibleCheckbox = panel.GetOrNull<CheckboxWidget>("INCOMPATIBLE_VERSION");
|
||||||
|
if (showIncompatibleCheckbox != null)
|
||||||
|
{
|
||||||
|
showIncompatibleCheckbox.IsChecked = () => showIncompatible;
|
||||||
|
showIncompatibleCheckbox.OnClick = () => { showIncompatible ^= true; ServerList.Query(games => RefreshServerList(panel, games)); };
|
||||||
|
}
|
||||||
|
|
||||||
ServerList.Query(games => RefreshServerList(panel, games));
|
ServerList.Query(games => RefreshServerList(panel, games));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,9 +141,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
if (game == null)
|
if (game == null)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (game.State == 1) return "Waiting for players";
|
if (game.State == (int)ServerState.WaitingPlayers)
|
||||||
if (game.State == 2) return "Playing";
|
return "Waiting for players";
|
||||||
else return "Unknown";
|
if (game.State == (int)ServerState.GameStarted)
|
||||||
|
return "Playing";
|
||||||
|
if (game.State == (int)ServerState.ShuttingDown)
|
||||||
|
return "Server shutting down";
|
||||||
|
|
||||||
|
return "Unknown server state";
|
||||||
}
|
}
|
||||||
|
|
||||||
Map GetMapPreview(GameServer game)
|
Map GetMapPreview(GameServer game)
|
||||||
@@ -127,10 +169,56 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
return s.UsefulMods.Select(m => GenerateModLabel(m)).JoinWith("\n");
|
return s.UsefulMods.Select(m => GenerateModLabel(m)).JoinWith("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string GetPing(GameServer s)
|
||||||
|
{
|
||||||
|
if (s.Latency > -1)
|
||||||
|
return "Ping: {0} ms".F(s.Latency);
|
||||||
|
else
|
||||||
|
return "Ping: ? ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PingServerList(Widget panel, IEnumerable<GameServer> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Filtered(GameServer game)
|
||||||
|
{
|
||||||
|
if ((game.State == (int)ServerState.GameStarted) && !showStarted)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ((game.State == (int)ServerState.WaitingPlayers) && !showWaiting)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ((game.Players == 0) && !showEmpty)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!game.CompatibleVersion() && !showIncompatible)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void RefreshServerList(Widget panel, IEnumerable<GameServer> games)
|
public void RefreshServerList(Widget panel, IEnumerable<GameServer> games)
|
||||||
{
|
{
|
||||||
var sl = panel.Get<ScrollPanelWidget>("SERVER_LIST");
|
var sl = panel.Get<ScrollPanelWidget>("SERVER_LIST");
|
||||||
|
|
||||||
|
searchStatus = SearchStatus.Fetching;
|
||||||
|
|
||||||
sl.RemoveChildren();
|
sl.RemoveChildren();
|
||||||
currentServer = null;
|
currentServer = null;
|
||||||
|
|
||||||
@@ -186,6 +274,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
version.GetText = () => GenerateModsLabel(game);
|
version.GetText = () => GenerateModsLabel(game);
|
||||||
version.IsVisible = () => !game.CompatibleVersion();
|
version.IsVisible = () => !game.CompatibleVersion();
|
||||||
|
|
||||||
|
var ping = item.GetOrNull<LabelWidget>("PING");
|
||||||
|
if (ping != null)
|
||||||
|
{
|
||||||
|
ping.GetText = () => GetPing(game);
|
||||||
|
ping.IsVisible = () => game.CompatibleVersion();
|
||||||
|
}
|
||||||
|
|
||||||
if (!canJoin)
|
if (!canJoin)
|
||||||
{
|
{
|
||||||
title.GetColor = () => Color.Gray;
|
title.GetColor = () => Color.Gray;
|
||||||
@@ -194,8 +289,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
state.GetColor = () => Color.Gray;
|
state.GetColor = () => Color.Gray;
|
||||||
ip.GetColor = () => Color.Gray;
|
ip.GetColor = () => Color.Gray;
|
||||||
version.GetColor = () => Color.Gray;
|
version.GetColor = () => Color.Gray;
|
||||||
|
if (ping != null)
|
||||||
|
ping.GetColor = () => Color.Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Filtered(game))
|
||||||
sl.AddChild(item);
|
sl.AddChild(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,21 +3,52 @@ Background@JOINSERVER_BG:
|
|||||||
X:(WINDOW_RIGHT - WIDTH)/2
|
X:(WINDOW_RIGHT - WIDTH)/2
|
||||||
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
Y:(WINDOW_BOTTOM - HEIGHT)/2
|
||||||
Width:540
|
Width:540
|
||||||
Height:535
|
Height:505
|
||||||
Children:
|
Children:
|
||||||
Label@JOINSERVER_LABEL_TITLE:
|
Label@JOINSERVER_LABEL_TITLE:
|
||||||
X:0
|
X:0
|
||||||
Y:20
|
Y:15
|
||||||
Width:PARENT_RIGHT
|
Width:PARENT_RIGHT
|
||||||
Height:25
|
Height:25
|
||||||
Text:Join Server
|
Text:Join Server
|
||||||
Align:Center
|
Align:Center
|
||||||
Font:Bold
|
Font:Bold
|
||||||
|
Label@SHOW_LABEL_TITLE:
|
||||||
|
X:20
|
||||||
|
Y:45
|
||||||
|
Width:20
|
||||||
|
Height:25
|
||||||
|
Text:Show:
|
||||||
|
Font:Bold
|
||||||
|
Checkbox@WAITING_FOR_PLAYERS:
|
||||||
|
X:80
|
||||||
|
Y:50
|
||||||
|
Width:100
|
||||||
|
Height:20
|
||||||
|
Text:Waiting
|
||||||
|
Checkbox@EMPTY:
|
||||||
|
X:180
|
||||||
|
Y:50
|
||||||
|
Width:100
|
||||||
|
Height:20
|
||||||
|
Text:Empty
|
||||||
|
Checkbox@ALREADY_STARTED:
|
||||||
|
X:280
|
||||||
|
Y:50
|
||||||
|
Width:100
|
||||||
|
Height:20
|
||||||
|
Text:Started
|
||||||
|
Checkbox@INCOMPATIBLE_VERSION:
|
||||||
|
X:380
|
||||||
|
Y:50
|
||||||
|
Width:100
|
||||||
|
Height:20
|
||||||
|
Text:Incompatible
|
||||||
ScrollPanel@SERVER_LIST:
|
ScrollPanel@SERVER_LIST:
|
||||||
X:20
|
X:20
|
||||||
Y:50
|
Y:80
|
||||||
Width:500
|
Width:500
|
||||||
Height:425
|
Height:355
|
||||||
Children:
|
Children:
|
||||||
ScrollItem@SERVER_TEMPLATE:
|
ScrollItem@SERVER_TEMPLATE:
|
||||||
Width:PARENT_RIGHT-27
|
Width:PARENT_RIGHT-27
|
||||||
@@ -64,7 +95,12 @@ Background@JOINSERVER_BG:
|
|||||||
Y:40
|
Y:40
|
||||||
Align:Right
|
Align:Right
|
||||||
Height:25
|
Height:25
|
||||||
|
Label@PING:
|
||||||
|
Width:140
|
||||||
|
X:PARENT_RIGHT-150
|
||||||
|
Y:40
|
||||||
|
Align:Right
|
||||||
|
Height:25
|
||||||
Label@PROGRESS_LABEL:
|
Label@PROGRESS_LABEL:
|
||||||
X:(PARENT_RIGHT - WIDTH) / 2
|
X:(PARENT_RIGHT - WIDTH) / 2
|
||||||
Y:PARENT_BOTTOM / 2 - HEIGHT
|
Y:PARENT_BOTTOM / 2 - HEIGHT
|
||||||
@@ -75,14 +111,21 @@ Background@JOINSERVER_BG:
|
|||||||
Button@REFRESH_BUTTON:
|
Button@REFRESH_BUTTON:
|
||||||
X:20
|
X:20
|
||||||
Y:PARENT_BOTTOM - 45
|
Y:PARENT_BOTTOM - 45
|
||||||
Width:120
|
Width:100
|
||||||
Height:25
|
Height:25
|
||||||
Text:Refresh
|
Text:Refresh
|
||||||
Font:Bold
|
Font:Bold
|
||||||
|
Button@PING_BUTTON:
|
||||||
|
X:140
|
||||||
|
Y:PARENT_BOTTOM - 45
|
||||||
|
Width:100
|
||||||
|
Height:25
|
||||||
|
Text:Ping
|
||||||
|
Font:Bold
|
||||||
Button@JOIN_BUTTON:
|
Button@JOIN_BUTTON:
|
||||||
X:PARENT_RIGHT - 140 - 130
|
X:PARENT_RIGHT - 140 - 130
|
||||||
Y:PARENT_BOTTOM - 45
|
Y:PARENT_BOTTOM - 45
|
||||||
Width:120
|
Width:100
|
||||||
Height:25
|
Height:25
|
||||||
Text:Join
|
Text:Join
|
||||||
Font:Bold
|
Font:Bold
|
||||||
@@ -90,7 +133,7 @@ Background@JOINSERVER_BG:
|
|||||||
Button@BACK_BUTTON:
|
Button@BACK_BUTTON:
|
||||||
X:PARENT_RIGHT - 140
|
X:PARENT_RIGHT - 140
|
||||||
Y:PARENT_BOTTOM - 45
|
Y:PARENT_BOTTOM - 45
|
||||||
Width:120
|
Width:100
|
||||||
Height:25
|
Height:25
|
||||||
Text:Cancel
|
Text:Cancel
|
||||||
Font:Bold
|
Font:Bold
|
||||||
|
|||||||
Reference in New Issue
Block a user