Merge pull request #2996 from Mailaender/serverbrowser-usability

Added filters and ping to server browser
This commit is contained in:
Chris Forbes
2013-04-13 00:55:41 -07:00
3 changed files with 191 additions and 20 deletions

View File

@@ -10,6 +10,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
namespace OpenRA.Network
{
@@ -65,5 +67,33 @@ 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();
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;
}
}
}
}

View File

@@ -14,6 +14,7 @@ using System.Linq;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Network;
using OpenRA.Server;
using OpenRA.Widgets;
namespace OpenRA.Mods.RA.Widgets.Logic
@@ -25,9 +26,14 @@ 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;
bool showEmpty = true;
bool showStarted = true;
bool showIncompatible = false;
public string ProgressLabelText()
{
switch (searchStatus)
@@ -35,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 "";
}
}
@@ -50,13 +57,15 @@ namespace OpenRA.Mods.RA.Widgets.Logic
// Menu buttons
var refreshButton = panel.Get<ButtonWidget>("REFRESH_BUTTON");
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;
sl.RemoveChildren();
currentServer = null;
ServerList.Query(games => RefreshServerList(panel, games));
};
pingButton.IsDisabled = () => searchStatus == SearchStatus.Pinging ||
searchStatus == SearchStatus.Fetching || searchStatus == SearchStatus.Failed;
pingButton.OnClick = () => ServerList.Query(games => PingServerList(panel, games));
}
var join = panel.Get<ButtonWidget>("JOIN_BUTTON");
join.IsDisabled = () => currentServer == null || !currentServer.CanJoin();
@@ -73,6 +82,34 @@ namespace OpenRA.Mods.RA.Widgets.Logic
progressText.IsVisible = () => searchStatus != SearchStatus.Hidden;
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));
}
@@ -104,9 +141,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (game == null)
return "";
if (game.State == 1) return "Waiting for players";
if (game.State == 2) return "Playing";
else return "Unknown";
if (game.State == (int)ServerState.WaitingPlayers)
return "Waiting for players";
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)
@@ -127,10 +169,56 @@ namespace OpenRA.Mods.RA.Widgets.Logic
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)
{
var sl = panel.Get<ScrollPanelWidget>("SERVER_LIST");
searchStatus = SearchStatus.Fetching;
sl.RemoveChildren();
currentServer = null;
@@ -186,6 +274,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
version.GetText = () => GenerateModsLabel(game);
version.IsVisible = () => !game.CompatibleVersion();
var ping = item.GetOrNull<LabelWidget>("PING");
if (ping != null)
{
ping.GetText = () => GetPing(game);
ping.IsVisible = () => game.CompatibleVersion();
}
if (!canJoin)
{
title.GetColor = () => Color.Gray;
@@ -194,8 +289,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
state.GetColor = () => Color.Gray;
ip.GetColor = () => Color.Gray;
version.GetColor = () => Color.Gray;
if (ping != null)
ping.GetColor = () => Color.Gray;
}
if (!Filtered(game))
sl.AddChild(item);
}
}

View File

@@ -3,21 +3,52 @@ Background@JOINSERVER_BG:
X:(WINDOW_RIGHT - WIDTH)/2
Y:(WINDOW_BOTTOM - HEIGHT)/2
Width:540
Height:535
Height:505
Children:
Label@JOINSERVER_LABEL_TITLE:
X:0
Y:20
Y:15
Width:PARENT_RIGHT
Height:25
Text:Join Server
Align:Center
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:
X:20
Y:50
Y:80
Width:500
Height:425
Height:355
Children:
ScrollItem@SERVER_TEMPLATE:
Width:PARENT_RIGHT-27
@@ -64,7 +95,12 @@ 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
@@ -75,14 +111,21 @@ Background@JOINSERVER_BG:
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
@@ -90,7 +133,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