void UpdatePlayerList() { if (orderManager.LocalClient == null) { return; } var isHost = Game.IsHost; var idx = 0; foreach (var kv in orderManager.LobbyInfo.Slots) { var key = kv.Key; var slot = kv.Value; var client = orderManager.LobbyInfo.ClientInSlot(key); Widget template = null; // get template for possible reuse if (idx < players.Children.Count) { template = players.Children[idx]; } if (client == null) { // Empty slot if (template == null || template.Id != emptySlotTemplate.Id) { template = emptySlotTemplate.Clone(); } if (isHost) { LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, worldRenderer, map); } else { LobbyUtils.SetupSlotWidget(template, slot, client); } var join = template.Get <ButtonWidget>("JOIN"); join.IsVisible = () => !slot.Closed; join.IsDisabled = () => orderManager.LocalClient.IsReady; join.OnClick = () => orderManager.IssueOrder(Order.Command("slot " + key)); } else if ((client.Index == orderManager.LocalClient.Index) || (client.Bot != null && isHost)) { // Editable player in slot if (template == null || template.Id != editablePlayerTemplate.Id) { template = editablePlayerTemplate.Clone(); } LobbyUtils.SetupLatencyWidget(template, client, orderManager); if (client.Bot != null) { LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, worldRenderer, map); } else { LobbyUtils.SetupEditableNameWidget(template, slot, client, orderManager, worldRenderer); } LobbyUtils.SetupEditableColorWidget(template, slot, client, orderManager, shellmapWorld, colorPreview); LobbyUtils.SetupEditableFactionWidget(template, slot, client, orderManager, factions); LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map); LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map); LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager, map); } else { // Non-editable player in slot if (template == null || template.Id != nonEditablePlayerTemplate.Id) { template = nonEditablePlayerTemplate.Clone(); } LobbyUtils.SetupLatencyWidget(template, client, orderManager); LobbyUtils.SetupColorWidget(template, slot, client); LobbyUtils.SetupFactionWidget(template, slot, client, factions); if (isHost) { LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map); LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map); LobbyUtils.SetupPlayerActionWidget(template, slot, client, orderManager, worldRenderer, lobby, () => panel = PanelType.Kick, () => panel = PanelType.Players); } else { LobbyUtils.SetupNameWidget(template, slot, client, orderManager, worldRenderer); LobbyUtils.SetupTeamWidget(template, slot, client); LobbyUtils.SetupSpawnWidget(template, slot, client); } LobbyUtils.SetupReadyWidget(template, slot, client); } template.IsVisible = () => true; if (idx >= players.Children.Count) { players.AddChild(template); } else if (players.Children[idx].Id != template.Id) { players.ReplaceChild(players.Children[idx], template); } idx++; } // Add spectators foreach (var client in orderManager.LobbyInfo.Clients.Where(client => client.Slot == null)) { Widget template = null; var c = client; // get template for possible reuse if (idx < players.Children.Count) { template = players.Children[idx]; } // Editable spectator if (c.Index == orderManager.LocalClient.Index) { if (template == null || template.Id != editableSpectatorTemplate.Id) { template = editableSpectatorTemplate.Clone(); } LobbyUtils.SetupEditableNameWidget(template, null, c, orderManager, worldRenderer); if (client.IsAdmin) { LobbyUtils.SetupEditableReadyWidget(template, null, client, orderManager, map); } else { LobbyUtils.HideReadyWidgets(template); } } else { // Non-editable spectator if (template == null || template.Id != nonEditableSpectatorTemplate.Id) { template = nonEditableSpectatorTemplate.Clone(); } if (isHost) { LobbyUtils.SetupPlayerActionWidget(template, null, client, orderManager, worldRenderer, lobby, () => panel = PanelType.Kick, () => panel = PanelType.Players); } else { LobbyUtils.SetupNameWidget(template, null, client, orderManager, worldRenderer); } if (client.IsAdmin) { LobbyUtils.SetupReadyWidget(template, null, client); } else { LobbyUtils.HideReadyWidgets(template); } } LobbyUtils.SetupLatencyWidget(template, c, orderManager); template.IsVisible = () => true; if (idx >= players.Children.Count) { players.AddChild(template); } else if (players.Children[idx].Id != template.Id) { players.ReplaceChild(players.Children[idx], template); } idx++; } // Spectate button if (orderManager.LocalClient.Slot != null) { Widget spec = null; if (idx < players.Children.Count) { spec = players.Children[idx]; } if (spec == null || spec.Id != newSpectatorTemplate.Id) { spec = newSpectatorTemplate.Clone(); } LobbyUtils.SetupKickSpectatorsWidget(spec, orderManager, lobby, () => panel = PanelType.Kick, () => panel = PanelType.Players, skirmishMode); var btn = spec.Get <ButtonWidget>("SPECTATE"); btn.OnClick = () => orderManager.IssueOrder(Order.Command("spectate")); btn.IsDisabled = () => orderManager.LocalClient.IsReady; btn.IsVisible = () => orderManager.LobbyInfo.GlobalSettings.AllowSpectators || orderManager.LocalClient.IsAdmin; spec.IsVisible = () => true; if (idx >= players.Children.Count) { players.AddChild(spec); } else if (players.Children[idx].Id != spec.Id) { players.ReplaceChild(players.Children[idx], spec); } idx++; } while (players.Children.Count > idx) { players.RemoveChild(players.Children[idx]); } tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList(); }