Add a player list to the MP server browser.

This commit is contained in:
Paul Chote
2017-12-25 13:20:13 +00:00
committed by reaperrr
parent 3ba610b535
commit bccc0f8f17
11 changed files with 383 additions and 104 deletions

View File

@@ -18,6 +18,7 @@ using System.Text;
using BeaconLib;
using OpenRA.Network;
using OpenRA.Server;
using OpenRA.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
@@ -37,13 +38,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly ModData modData;
readonly WebServices services;
readonly Probe lanGameProbe;
readonly ScrollItemWidget serverTemplate;
readonly ScrollItemWidget headerTemplate;
readonly Widget clientContainer;
readonly ScrollPanelWidget clientList;
readonly ScrollItemWidget clientTemplate, clientHeader;
readonly MapPreviewWidget mapPreview;
readonly ButtonWidget joinButton;
readonly int joinButtonY;
GameServer currentServer;
MapPreview currentMap;
ScrollItemWidget serverTemplate;
ScrollItemWidget headerTemplate;
Action onStart;
Action onExit;
@@ -85,10 +91,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
headerTemplate = serverList.Get<ScrollItemWidget>("HEADER_TEMPLATE");
serverTemplate = serverList.Get<ScrollItemWidget>("SERVER_TEMPLATE");
var join = widget.Get<ButtonWidget>("JOIN_BUTTON");
join.IsVisible = () => currentServer != null;
join.IsDisabled = () => !currentServer.IsJoinable;
join.OnClick = () => Join(currentServer);
joinButton = widget.Get<ButtonWidget>("JOIN_BUTTON");
joinButton.IsVisible = () => currentServer != null;
joinButton.IsDisabled = () => !currentServer.IsJoinable;
joinButton.OnClick = () => Join(currentServer);
joinButtonY = joinButton.Bounds.Y;
// Display the progress label over the server list
// The text is only visible when the list is empty
@@ -159,7 +166,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
refreshButton.OnClick = RefreshServerList;
}
var mapPreview = widget.GetOrNull<MapPreviewWidget>("SELECTED_MAP_PREVIEW");
mapPreview = widget.GetOrNull<MapPreviewWidget>("SELECTED_MAP_PREVIEW");
if (mapPreview != null)
mapPreview.Preview = () => currentMap;
@@ -201,10 +208,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var players = widget.GetOrNull<LabelWidget>("SELECTED_PLAYERS");
if (players != null)
{
players.IsVisible = () => currentServer != null;
players.IsVisible = () => currentServer != null && !currentServer.Clients.Any();
players.GetText = () => PlayersLabel(currentServer);
}
clientContainer = widget.Get("CLIENT_LIST_CONTAINER");
clientList = Ui.LoadWidget("MULTIPLAYER_CLIENT_LIST", clientContainer, new WidgetArgs()) as ScrollPanelWidget;
clientList.IsVisible = () => currentServer != null && currentServer.Clients.Any();
clientHeader = clientList.Get<ScrollItemWidget>("HEADER");
clientTemplate = clientList.Get<ScrollItemWidget>("TEMPLATE");
clientList.RemoveChildren();
var directConnectButton = widget.Get<ButtonWidget>("DIRECTCONNECT_BUTTON");
directConnectButton.OnClick = () =>
{
@@ -361,6 +375,86 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
currentServer = server;
currentMap = server != null ? modData.MapCache[server.Map] : null;
clientList.RemoveChildren();
if (server == null || !server.Clients.Any())
{
joinButton.Bounds.Y = joinButtonY;
return;
}
joinButton.Bounds.Y = clientContainer.Bounds.Bottom;
var players = server.Clients
.Where(c => !c.IsSpectator)
.GroupBy(p => p.Team)
.OrderBy(g => g.Key);
var teams = new Dictionary<string, IEnumerable<GameClient>>();
var noTeams = players.Count() == 1;
foreach (var p in players)
{
var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : "Team {0}".F(p.Key);
teams.Add(label, p);
}
if (server.Clients.Any(c => c.IsSpectator))
teams.Add("Spectators", server.Clients.Where(c => c.IsSpectator));
// Can only show factions if the server is running the same mod
var disableFactionDisplay = server.Mod != modData.Manifest.Id;
if (mapPreview != null)
{
var spawns = currentMap.SpawnPoints;
var occupants = server.Clients
.Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Length))
.ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c, disableFactionDisplay));
mapPreview.SpawnOccupants = () => occupants;
}
var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos<FactionInfo>();
foreach (var kv in teams)
{
var group = kv.Key;
if (group.Length > 0)
{
var header = ScrollItemWidget.Setup(clientHeader, () => true, () => { });
header.Get<LabelWidget>("LABEL").GetText = () => group;
clientList.AddChild(header);
}
foreach (var option in kv.Value)
{
var o = option;
var item = ScrollItemWidget.Setup(clientTemplate, () => false, () => { });
if (!o.IsSpectator && !disableFactionDisplay)
{
var label = item.Get<LabelWidget>("LABEL");
var font = Game.Renderer.Fonts[label.Font];
var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font);
label.GetText = () => name;
label.GetColor = () => o.Color.RGB;
var flag = item.Get<ImageWidget>("FLAG");
flag.IsVisible = () => true;
flag.GetImageCollection = () => "flags";
flag.GetImageName = () => (factionInfo != null && factionInfo.Any(f => f.InternalName == o.Faction)) ? o.Faction : "Random";
}
else
{
var label = item.Get<LabelWidget>("NOFLAG_LABEL");
var font = Game.Renderer.Fonts[label.Font];
var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font);
label.GetText = () => name;
label.GetColor = () => o.Color.RGB;
}
clientList.AddChild(item);
}
}
}
void RefreshServerListInner(List<GameServer> games)

View File

@@ -22,7 +22,6 @@ namespace OpenRA.Mods.Common.Widgets
public class SpawnOccupant
{
public readonly HSLColor Color;
public readonly int ClientIndex;
public readonly string PlayerName;
public readonly int Team;
public readonly string Faction;
@@ -31,7 +30,6 @@ namespace OpenRA.Mods.Common.Widgets
public SpawnOccupant(Session.Client client)
{
Color = client.Color;
ClientIndex = client.Index;
PlayerName = client.Name;
Team = client.Team;
Faction = client.Faction;
@@ -41,12 +39,20 @@ namespace OpenRA.Mods.Common.Widgets
public SpawnOccupant(GameInformation.Player player)
{
Color = player.Color;
ClientIndex = player.ClientIndex;
PlayerName = player.Name;
Team = player.Team;
Faction = player.FactionId;
SpawnPoint = player.SpawnPoint;
}
public SpawnOccupant(GameClient player, bool suppressFaction)
{
Color = player.Color;
PlayerName = player.Name;
Team = player.Team;
Faction = !suppressFaction ? player.Faction : null;
SpawnPoint = player.SpawnPoint;
}
}
public class MapPreviewWidget : Widget

View File

@@ -118,6 +118,7 @@ Container@MULTIPLAYER_PANEL:
Y: 1
Width: PARENT_RIGHT - 2
Height: PARENT_BOTTOM - 2
TooltipContainer: TOOLTIP_CONTAINER
Label@SELECTED_MAP:
Y: 172
Width: PARENT_RIGHT
@@ -148,6 +149,10 @@ Container@MULTIPLAYER_PANEL:
Height: 25
Font: TinyBold
Align: Center
Container@CLIENT_LIST_CONTAINER:
Y: 240
Width: PARENT_RIGHT
Height: 230
Button@JOIN_BUTTON:
Key: return
Y: 255
@@ -185,49 +190,4 @@ Container@MULTIPLAYER_PANEL:
Width: 140
Height: 35
Text: Back
TooltipContainer@TOOLTIP_CONTAINER:
ScrollPanel@MULTIPLAYER_FILTER_PANEL:
Width: 147
Height: 130
Background: panel-black
Children:
Checkbox@WAITING_FOR_PLAYERS:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 20
Text: Waiting
TextColor: 32CD32
Font: Regular
Checkbox@EMPTY:
X: 5
Y: 30
Width: PARENT_RIGHT - 29
Height: 20
Text: Empty
Font: Regular
Checkbox@PASSWORD_PROTECTED:
X: 5
Y: 55
Width: PARENT_RIGHT - 29
Height: 20
Text: Protected
TextColor: FF0000
Font: Regular
Checkbox@ALREADY_STARTED:
X: 5
Y: 80
Width: PARENT_RIGHT - 29
Height: 20
Text: Started
TextColor: FFA500
Font: Regular
Checkbox@INCOMPATIBLE_VERSION:
X: 5
Y: 105
Width: PARENT_RIGHT - 29
Height: 20
Text: Incompatible
TextColor: BEBEBE
Font: Regular
TooltipContainer@TOOLTIP_CONTAINER:

View File

@@ -0,0 +1,85 @@
ScrollPanel@MULTIPLAYER_CLIENT_LIST:
Width: PARENT_RIGHT
Height: 225
IgnoreChildMouseOver: true
Children:
ScrollItem@HEADER:
Width: PARENT_RIGHT - 27
Height: 13
X: 2
Y: 0
Visible: false
Children:
Label@LABEL:
Font: TinyBold
Width: PARENT_RIGHT
Height: 10
Align: Center
ScrollItem@TEMPLATE:
Width: PARENT_RIGHT - 27
Height: 25
X: 2
Y: 0
Visible: false
Children:
Image@FLAG:
X: 4
Y: 5
Width: 32
Height: 16
Visible: False
Label@LABEL:
X: 40
Width: PARENT_RIGHT - 50
Height: 23
Shadow: True
Label@NOFLAG_LABEL:
X: 5
Width: PARENT_RIGHT
Height: 23
Shadow: True
ScrollPanel@MULTIPLAYER_FILTER_PANEL:
Width: 147
Height: 130
Background: panel-black
Children:
Checkbox@WAITING_FOR_PLAYERS:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 20
Text: Waiting
TextColor: 32CD32
Font: Regular
Checkbox@EMPTY:
X: 5
Y: 30
Width: PARENT_RIGHT - 29
Height: 20
Text: Empty
Font: Regular
Checkbox@PASSWORD_PROTECTED:
X: 5
Y: 55
Width: PARENT_RIGHT - 29
Height: 20
Text: Protected
TextColor: FF0000
Font: Regular
Checkbox@ALREADY_STARTED:
X: 5
Y: 80
Width: PARENT_RIGHT - 29
Height: 20
Text: Started
TextColor: FFA500
Font: Regular
Checkbox@INCOMPATIBLE_VERSION:
X: 5
Y: 105
Width: PARENT_RIGHT - 29
Height: 20
Text: Incompatible
TextColor: BEBEBE
Font: Regular

View File

@@ -90,6 +90,7 @@ Assemblies:
ChromeLayout:
cnc|chrome/mainmenu.yaml
cnc|chrome/multiplayer-browser.yaml
cnc|chrome/multiplayer-browserpanels.yaml
cnc|chrome/multiplayer-createserver.yaml
cnc|chrome/multiplayer-directconnect.yaml
cnc|chrome/lobby.yaml

View File

@@ -3,7 +3,7 @@ Background@MULTIPLAYER_PANEL:
X: (WINDOW_RIGHT - WIDTH) / 2
Y: (WINDOW_BOTTOM - HEIGHT) / 2
Width: 808
Height: 600
Height: 550
Children:
Label@TITLE:
Y: 15
@@ -114,6 +114,7 @@ Background@MULTIPLAYER_PANEL:
Y: 1
Width: PARENT_RIGHT - 2
Height: PARENT_BOTTOM - 2
TooltipContainer: TOOLTIP_CONTAINER
Label@SELECTED_MAP:
Y: 172
Width: PARENT_RIGHT
@@ -144,6 +145,10 @@ Background@MULTIPLAYER_PANEL:
Height: 25
Font: TinyBold
Align: Center
Container@CLIENT_LIST_CONTAINER:
Y: 240
Width: PARENT_RIGHT
Height: 166
Button@JOIN_BUTTON:
Key: return
Y: 255
@@ -187,48 +192,4 @@ Background@MULTIPLAYER_PANEL:
Height: 25
Text: Back
Font: Bold
TooltipContainer@TOOLTIP_CONTAINER:
ScrollPanel@MULTIPLAYER_FILTER_PANEL:
Width: 158
Height: 130
Children:
Checkbox@WAITING_FOR_PLAYERS:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 20
Text: Waiting
TextColor: 32CD32
Font: Regular
Checkbox@EMPTY:
X: 5
Y: 30
Width: PARENT_RIGHT - 29
Height: 20
Text: Empty
Font: Regular
Checkbox@PASSWORD_PROTECTED:
X: 5
Y: 55
Width: PARENT_RIGHT - 29
Height: 20
Text: Protected
TextColor: FF0000
Font: Regular
Checkbox@ALREADY_STARTED:
X: 5
Y: 80
Width: PARENT_RIGHT - 29
Height: 20
Text: Started
TextColor: FFA500
Font: Regular
Checkbox@INCOMPATIBLE_VERSION:
X: 5
Y: 105
Width: PARENT_RIGHT - 29
Height: 20
Text: Incompatible
TextColor: BEBEBE
Font: Regular
TooltipContainer@TOOLTIP_CONTAINER:

View File

@@ -0,0 +1,85 @@
ScrollPanel@MULTIPLAYER_CLIENT_LIST:
Width: PARENT_RIGHT
Height: 159
IgnoreChildMouseOver: true
Children:
ScrollItem@HEADER:
BaseName: scrollheader
Width: PARENT_RIGHT - 27
Height: 13
X: 2
Y: 0
Visible: false
Children:
Label@LABEL:
Font: TinyBold
Width: PARENT_RIGHT
Height: 10
Align: Center
ScrollItem@TEMPLATE:
Width: PARENT_RIGHT - 27
Height: 25
X: 2
Y: 0
Visible: false
Children:
Image@FLAG:
X: 4
Y: 6
Width: 32
Height: 16
Visible: False
Label@LABEL:
X: 40
Width: PARENT_RIGHT - 50
Height: 23
Shadow: True
Label@NOFLAG_LABEL:
X: 5
Width: PARENT_RIGHT
Height: 23
Shadow: True
ScrollPanel@MULTIPLAYER_FILTER_PANEL:
Width: 158
Height: 130
Children:
Checkbox@WAITING_FOR_PLAYERS:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 20
Text: Waiting
TextColor: 32CD32
Font: Regular
Checkbox@EMPTY:
X: 5
Y: 30
Width: PARENT_RIGHT - 29
Height: 20
Text: Empty
Font: Regular
Checkbox@PASSWORD_PROTECTED:
X: 5
Y: 55
Width: PARENT_RIGHT - 29
Height: 20
Text: Protected
TextColor: FF0000
Font: Regular
Checkbox@ALREADY_STARTED:
X: 5
Y: 80
Width: PARENT_RIGHT - 29
Height: 20
Text: Started
TextColor: FFA500
Font: Regular
Checkbox@INCOMPATIBLE_VERSION:
X: 5
Y: 105
Width: PARENT_RIGHT - 29
Height: 20
Text: Incompatible
TextColor: BEBEBE
Font: Regular

View File

@@ -0,0 +1,84 @@
ScrollPanel@MULTIPLAYER_CLIENT_LIST:
Width: PARENT_RIGHT
Height: 159
IgnoreChildMouseOver: true
Children:
ScrollItem@HEADER:
BaseName: scrollheader
Width: PARENT_RIGHT - 27
Height: 13
X: 2
Y: 0
Visible: false
Children:
Label@LABEL:
Font: TinyBold
Width: PARENT_RIGHT
Height: 10
Align: Center
ScrollItem@TEMPLATE:
Width: PARENT_RIGHT - 27
Height: 25
X: 2
Y: 0
Visible: false
Children:
Image@FLAG:
X: 4
Y: 2
Width: 32
Height: 16
Visible: False
Label@LABEL:
X: 35
Width: PARENT_RIGHT - 45
Height: 23
Shadow: True
Label@NOFLAG_LABEL:
X: 5
Width: PARENT_RIGHT
Height: 23
ScrollPanel@MULTIPLAYER_FILTER_PANEL:
Width: 158
Height: 130
Children:
Checkbox@WAITING_FOR_PLAYERS:
X: 5
Y: 5
Width: PARENT_RIGHT - 29
Height: 20
Text: Waiting
TextColor: 32CD32
Font: Regular
Checkbox@EMPTY:
X: 5
Y: 30
Width: PARENT_RIGHT - 29
Height: 20
Text: Empty
Font: Regular
Checkbox@PASSWORD_PROTECTED:
X: 5
Y: 55
Width: PARENT_RIGHT - 29
Height: 20
Text: Protected
TextColor: FF0000
Font: Regular
Checkbox@ALREADY_STARTED:
X: 5
Y: 80
Width: PARENT_RIGHT - 29
Height: 20
Text: Started
TextColor: FFA500
Font: Regular
Checkbox@INCOMPATIBLE_VERSION:
X: 5
Y: 105
Width: PARENT_RIGHT - 29
Height: 20
Text: Incompatible
TextColor: BEBEBE
Font: Regular

View File

@@ -91,6 +91,7 @@ ChromeLayout:
common|chrome/color-picker.yaml
common|chrome/map-chooser.yaml
common|chrome/multiplayer-browser.yaml
d2k|chrome/multiplayer-browserpanels.yaml
common|chrome/multiplayer-createserver.yaml
common|chrome/multiplayer-directconnect.yaml
common|chrome/connection.yaml

View File

@@ -106,6 +106,7 @@ ChromeLayout:
common|chrome/color-picker.yaml
common|chrome/map-chooser.yaml
common|chrome/multiplayer-browser.yaml
common|chrome/multiplayer-browserpanels.yaml
common|chrome/multiplayer-createserver.yaml
common|chrome/multiplayer-directconnect.yaml
common|chrome/connection.yaml

View File

@@ -154,6 +154,7 @@ ChromeLayout:
ts|chrome/color-picker.yaml
common|chrome/map-chooser.yaml
common|chrome/multiplayer-browser.yaml
common|chrome/multiplayer-browserpanels.yaml
common|chrome/multiplayer-createserver.yaml
common|chrome/multiplayer-directconnect.yaml
common|chrome/connection.yaml