diff --git a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs index 680ae5fb94..71601ab564 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MultiplayerLogic.cs @@ -358,7 +358,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic lanGames = lanGames.GroupBy(gs => gs.Address).Select(g => g.Last()).ToList(); - Game.RunAfterTick(() => RefreshServerListInner(games.Concat(lanGames).ToList())); + Game.RunAfterTick(() => RefreshServerListInner(games == null ? (lanGames.Count == 0 ? null : lanGames.ToList()) : games.Concat(lanGames).ToList())); }; var queryURL = services.ServerList + "games?version={0}&mod={1}&modversion={2}".F( @@ -391,105 +391,105 @@ namespace OpenRA.Mods.Common.Widgets.Logic void RefreshServerListInner(List games) { - if (games == null) - return; - - var mods = games.GroupBy(g => g.Mods) - .OrderByDescending(g => GroupSortOrder(g.First())) - .ThenByDescending(g => g.Count()); - ScrollItemWidget nextServerRow = null; var rows = new List(); - foreach (var modGames in mods) + + if (games != null) { - if (modGames.All(Filtered)) - continue; - - var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); - - var headerTitle = modGames.First().ModLabel; - header.Get("LABEL").GetText = () => headerTitle; - rows.Add(header); - - Func listOrder = g => + var mods = games.GroupBy(g => g.Mods) + .OrderByDescending(g => GroupSortOrder(g.First())) + .ThenByDescending(g => g.Count()); + foreach (var modGames in mods) { - // Servers waiting for players are always first - if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0) - return 0; + if (modGames.All(Filtered)) + continue; - // Then servers with spectators - if (g.State == (int)ServerState.WaitingPlayers && g.Spectators > 0) - return 1; + var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); - // Then active games - if (g.State >= (int)ServerState.GameStarted) - return 2; + var headerTitle = modGames.First().ModLabel; + header.Get("LABEL").GetText = () => headerTitle; + rows.Add(header); - // Empty servers are shown at the end because a flood of empty servers - // at the top of the game list make the community look dead - return 3; - }; - - foreach (var modGamesByState in modGames.GroupBy(listOrder).OrderBy(g => g.Key)) - { - // Sort 'Playing' games by Started, others by number of players - foreach (var game in modGamesByState.Key == 2 ? modGamesByState.OrderByDescending(g => g.Started) : modGamesByState.OrderByDescending(g => g.Players)) + Func listOrder = g => { - if (Filtered(game)) - continue; + // Servers waiting for players are always first + if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0) + return 0; - var canJoin = game.IsJoinable; - var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => Join(game)); - var title = item.GetOrNull("TITLE"); - if (title != null) + // Then servers with spectators + if (g.State == (int)ServerState.WaitingPlayers && g.Spectators > 0) + return 1; + + // Then active games + if (g.State >= (int)ServerState.GameStarted) + return 2; + + // Empty servers are shown at the end because a flood of empty servers + // at the top of the game list make the community look dead + return 3; + }; + + foreach (var modGamesByState in modGames.GroupBy(listOrder).OrderBy(g => g.Key)) + { + // Sort 'Playing' games by Started, others by number of players + foreach (var game in modGamesByState.Key == 2 ? modGamesByState.OrderByDescending(g => g.Started) : modGamesByState.OrderByDescending(g => g.Players)) { - var font = Game.Renderer.Fonts[title.Font]; - var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font); - title.GetText = () => label; - title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor; + if (Filtered(game)) + continue; + + var canJoin = game.IsJoinable; + var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => Join(game)); + var title = item.GetOrNull("TITLE"); + if (title != null) + { + var font = Game.Renderer.Fonts[title.Font]; + var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font); + title.GetText = () => label; + title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor; + } + + var password = item.GetOrNull("PASSWORD_PROTECTED"); + if (password != null) + { + password.IsVisible = () => game.Protected; + password.GetImageName = () => canJoin ? "protected" : "protected-disabled"; + } + + var players = item.GetOrNull("PLAYERS"); + if (players != null) + { + players.GetText = () => "{0} / {1}".F(game.Players, game.MaxPlayers) + + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : ""); + + players.GetColor = () => canJoin ? players.TextColor : incompatibleGameColor; + } + + var state = item.GetOrNull("STATUS"); + if (state != null) + { + var label = game.State >= (int)ServerState.GameStarted ? + "Playing" : "Waiting"; + state.GetText = () => label; + + var color = GetStateColor(game, state, !canJoin); + state.GetColor = () => color; + } + + var location = item.GetOrNull("LOCATION"); + if (location != null) + { + var font = Game.Renderer.Fonts[location.Font]; + var cachedServerLocation = game.Id != -1 ? GeoIP.LookupCountry(game.Address.Split(':')[0]) : "Local Network"; + var label = WidgetUtils.TruncateText(cachedServerLocation, location.Bounds.Width, font); + location.GetText = () => label; + location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor; + } + + if (currentServer != null && game.Address == currentServer.Address) + nextServerRow = item; + + rows.Add(item); } - - var password = item.GetOrNull("PASSWORD_PROTECTED"); - if (password != null) - { - password.IsVisible = () => game.Protected; - password.GetImageName = () => canJoin ? "protected" : "protected-disabled"; - } - - var players = item.GetOrNull("PLAYERS"); - if (players != null) - { - players.GetText = () => "{0} / {1}".F(game.Players, game.MaxPlayers) - + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : ""); - - players.GetColor = () => canJoin ? players.TextColor : incompatibleGameColor; - } - - var state = item.GetOrNull("STATUS"); - if (state != null) - { - var label = game.State >= (int)ServerState.GameStarted ? - "Playing" : "Waiting"; - state.GetText = () => label; - - var color = GetStateColor(game, state, !canJoin); - state.GetColor = () => color; - } - - var location = item.GetOrNull("LOCATION"); - if (location != null) - { - var font = Game.Renderer.Fonts[location.Font]; - var cachedServerLocation = game.Id != -1 ? GeoIP.LookupCountry(game.Address.Split(':')[0]) : "Local Network"; - var label = WidgetUtils.TruncateText(cachedServerLocation, location.Bounds.Width, font); - location.GetText = () => label; - location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor; - } - - if (currentServer != null && game.Address == currentServer.Address) - nextServerRow = item; - - rows.Add(item); } } }