void ShowProgressbar(string title, Func <string> getMessage) { visible = Mode.Progress; titleLabel.Text = title; progressBar.IsIndeterminate = () => true; var font = Game.Renderer.Fonts[progressLabel.Font]; var status = new CachedTransform <string, string>(s => WidgetUtils.TruncateText(s, progressLabel.Bounds.Width, font)); progressLabel.GetText = () => status.Update(getMessage()); primaryButton.Bounds.Y += progressContainer.Bounds.Height - panel.Bounds.Height; secondaryButton.Bounds.Y += progressContainer.Bounds.Height - panel.Bounds.Height; panel.Bounds.Y -= (progressContainer.Bounds.Height - panel.Bounds.Height) / 2; panel.Bounds.Height = progressContainer.Bounds.Height; }
public static void SetupEditableSlotWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, WorldRenderer worldRenderer, MapPreview map) { var slot = parent.Get <DropDownButtonWidget>("SLOT_OPTIONS"); slot.IsVisible = () => true; slot.IsDisabled = () => orderManager.LocalClient.IsReady; var truncated = new CachedTransform <string, string>(name => WidgetUtils.TruncateText(name, slot.Bounds.Width - slot.Bounds.Height - slot.LeftMargin - slot.RightMargin, Game.Renderer.Fonts[slot.Font])); slot.GetText = () => truncated.Update(c != null ? c.Name : s.Closed ? "Closed" : "Open"); slot.OnMouseDown = _ => ShowSlotDropDown(slot, s, c, orderManager, map); // Ensure Name selector (if present) is hidden HideChildWidget(parent, "NAME"); }
void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices) { var i = 0; var options = devices.ToDictionary(d => (i++).ToString(), d => d); Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (o, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => soundDevice == options[o], () => soundDevice = options[o]); var deviceLabel = item.Get <LabelWidget>("LABEL"); var font = Game.Renderer.Fonts[deviceLabel.Font]; var label = WidgetUtils.TruncateText(options[o].Label, deviceLabel.Bounds.Width, font); deviceLabel.GetText = () => label; return(item); }; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); }
public static void SetupPlayerActionWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, WorldRenderer worldRenderer, Widget lobby, Action before, Action after) { var slot = parent.Get <DropDownButtonWidget>("PLAYER_ACTION"); slot.IsVisible = () => Game.IsHost && c.Index != orderManager.LocalClient.Index; slot.IsDisabled = () => orderManager.LocalClient.IsReady; var truncated = new CachedTransform <string, string>(name => WidgetUtils.TruncateText(name, slot.Bounds.Width - slot.Bounds.Height - slot.LeftMargin - slot.RightMargin, Game.Renderer.Fonts[slot.Font])); slot.GetText = () => truncated.Update(c != null ? c.Name : string.Empty); slot.OnMouseDown = _ => ShowPlayerActionDropDown(slot, s, c, orderManager, lobby, before, after); SetupProfileWidget(slot, c, orderManager, worldRenderer); // Ensure Name selector (if present) is hidden HideChildWidget(parent, "NAME"); }
public PlayerProfileBadgesLogic(Widget widget, PlayerProfile profile, Func <int, int> negotiateWidth) { var showBadges = profile.Badges.Any(); widget.IsVisible = () => showBadges; var badgeTemplate = widget.Get("BADGE_TEMPLATE"); widget.RemoveChild(badgeTemplate); var width = 0; var badgeOffset = badgeTemplate.Bounds.Y; foreach (var badge in profile.Badges) { var b = badgeTemplate.Clone(); var icon = b.Get <SpriteWidget>("ICON"); icon.GetSprite = () => badge.Icon24; var label = b.Get <LabelWidget>("LABEL"); var labelFont = Game.Renderer.Fonts[label.Font]; var labelText = WidgetUtils.TruncateText(badge.Label, label.Bounds.Width, labelFont); label.GetText = () => labelText; width = Math.Max(width, label.Bounds.Left + labelFont.Measure(labelText).X + icon.Bounds.X); b.Bounds.Y = badgeOffset; widget.AddChild(b); badgeOffset += badgeTemplate.Bounds.Height; } if (badgeOffset > badgeTemplate.Bounds.Y) { badgeOffset += 5; } widget.Bounds.Width = negotiateWidth(width); widget.Bounds.Height = badgeOffset; }
void SetupWidgets(Widget parent, Func <MapPreview> getMap, Action <MapPreviewWidget, MapPreview, MouseInput> onMouseDown, Func <Dictionary <int, SpawnOccupant> > getSpawnOccupants, Func <HashSet <int> > getDisabledSpawnPoints, bool showUnoccupiedSpawnpoints) { var preview = parent.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => getMap(); preview.OnMouseDown = mi => onMouseDown(preview, getMap(), mi); preview.SpawnOccupants = getSpawnOccupants; preview.DisabledSpawnPoints = getDisabledSpawnPoints; preview.ShowUnoccupiedSpawnpoints = showUnoccupiedSpawnpoints; var titleLabel = parent.GetOrNull <LabelWithTooltipWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.IsVisible = () => getMap() != MapCache.UnknownMap; var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(getMap()); titleLabel.GetTooltipText = () => getMap().Title; } var typeLabel = parent.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => m.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(getMap()); } var authorLabel = parent.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform <MapPreview, string>( m => WidgetUtils.TruncateText("Created by {0}".F(m.Author), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(getMap()); } }
public DownloadPackageLogic(Widget widget, ModContent.ModDownload download, Action onSuccess) { this.download = download; this.onSuccess = onSuccess; Log.AddChannel("install", "install.log"); panel = widget.Get("PACKAGE_DOWNLOAD_PANEL"); progressBar = panel.Get <ProgressBarWidget>("PROGRESS_BAR"); var statusLabel = panel.Get <LabelWidget>("STATUS_LABEL"); var statusFont = Game.Renderer.Fonts[statusLabel.Font]; var status = new CachedTransform <string, string>(s => WidgetUtils.TruncateText(s, statusLabel.Bounds.Width, statusFont)); statusLabel.GetText = () => status.Update(getStatusText()); var text = "Downloading {0}".F(download.Title); panel.Get <LabelWidget>("TITLE").Text = text; ShowDownloadDialog(); }
public AnonymousProfileTooltipLogic(Widget widget, OrderManager orderManager, Session.Client client) { var nameLabel = widget.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; widget.Bounds.Width = nameFont.Measure(nameLabel.Text).X + 2 * nameLabel.Bounds.Left; var locationLabel = widget.Get <LabelWidget>("LOCATION"); var ipLabel = widget.Get <LabelWidget>("IP"); var adminLabel = widget.Get("GAME_ADMIN"); if (client.Location != null) { var locationFont = Game.Renderer.Fonts[locationLabel.Font]; var locationWidth = widget.Bounds.Width - 2 * locationLabel.Bounds.X; var location = WidgetUtils.TruncateText(client.Location, locationWidth, locationFont); locationLabel.IsVisible = () => true; locationLabel.GetText = () => location; widget.Bounds.Height += locationLabel.Bounds.Height; ipLabel.Bounds.Y += locationLabel.Bounds.Height; adminLabel.Bounds.Y += locationLabel.Bounds.Height; } if (client.AnonymizedIPAddress != null) { ipLabel.IsVisible = () => true; ipLabel.GetText = () => client.AnonymizedIPAddress; widget.Bounds.Height += ipLabel.Bounds.Height; adminLabel.Bounds.Y += locationLabel.Bounds.Height; } if (client.IsAdmin) { adminLabel.IsVisible = () => true; widget.Bounds.Height += adminLabel.Bounds.Height; } }
void SelectServer(GameServer server) { currentServer = server; currentMap = server != null ? modData.MapCache[server.Map] : null; if (server == null || !server.Clients.Any()) { if (joinButton != null) { joinButton.Bounds.Y = joinButtonY; } return; } if (joinButton != null) { joinButton.Bounds.Y = clientContainer.Bounds.Bottom; } // Can only show factions if the server is running the same mod var disableFactionDisplay = server.Mod != modData.Manifest.Id; if (server != null && 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; } if (clientList == null) { return; } clientList.RemoveChildren(); 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)); } 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); // Force spectator color to prevent spoofing by the server var color = o.IsSpectator ? Color.White : o.Color.RGB; label.GetText = () => name; label.GetColor = () => color; } clientList.AddChild(item); } } }
internal LobbyMapPreviewLogic(Widget widget, ModData modData, OrderManager orderManager, LobbyLogic lobby) { var available = widget.GetOrNull("MAP_AVAILABLE"); if (available != null) { available.IsVisible = () => lobby.Map.Status == MapStatus.Available && (!lobby.Map.RulesLoaded || !lobby.Map.InvalidCustomRules); var preview = available.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = available.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(lobby.Map); } var typeLabel = available.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } var authorLabel = available.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform <MapPreview, string>( m => WidgetUtils.TruncateText("Created by {0}".F(lobby.Map.Author), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(lobby.Map); } } var invalid = widget.GetOrNull("MAP_INVALID"); if (invalid != null) { invalid.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.InvalidCustomRules; var preview = invalid.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = invalid.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.GetText = () => lobby.Map.Title; } var typeLabel = invalid.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } } var download = widget.GetOrNull("MAP_DOWNLOADABLE"); if (download != null) { download.IsVisible = () => lobby.Map.Status == MapStatus.DownloadAvailable; var preview = download.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = download.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.GetText = () => lobby.Map.Title; } var typeLabel = download.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } var authorLabel = download.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { authorLabel.GetText = () => "Created by {0}".F(lobby.Map.Author); } var install = download.GetOrNull <ButtonWidget>("MAP_INSTALL"); if (install != null) { install.OnClick = () => lobby.Map.Install(() => { lobby.Map.PreloadRules(); Game.RunAfterTick(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)))); }); install.IsHighlighted = () => installHighlighted; } } var progress = widget.GetOrNull("MAP_PROGRESS"); if (progress != null) { progress.IsVisible = () => lobby.Map.Status != MapStatus.Available && lobby.Map.Status != MapStatus.DownloadAvailable; var preview = progress.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = progress.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.GetText = () => lobby.Map.Title; } var typeLabel = progress.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } } var statusSearching = progress.GetOrNull("MAP_STATUS_SEARCHING"); if (statusSearching != null) { statusSearching.IsVisible = () => lobby.Map.Status == MapStatus.Searching; } var statusUnavailable = progress.GetOrNull("MAP_STATUS_UNAVAILABLE"); if (statusUnavailable != null) { statusUnavailable.IsVisible = () => lobby.Map.Status == MapStatus.Unavailable; } var statusError = progress.GetOrNull("MAP_STATUS_ERROR"); if (statusError != null) { statusError.IsVisible = () => lobby.Map.Status == MapStatus.DownloadError; } var statusDownloading = progress.GetOrNull <LabelWidget>("MAP_STATUS_DOWNLOADING"); if (statusDownloading != null) { statusDownloading.IsVisible = () => lobby.Map.Status == MapStatus.Downloading; statusDownloading.GetText = () => { if (lobby.Map.DownloadBytes == 0) { return("Connecting..."); } // Server does not provide the total file length if (lobby.Map.DownloadPercentage == 0) { return("Downloading {0} kB".F(lobby.Map.DownloadBytes / 1024)); } return("Downloading {0} kB ({1}%)".F(lobby.Map.DownloadBytes / 1024, lobby.Map.DownloadPercentage)); }; } var retry = progress.GetOrNull <ButtonWidget>("MAP_RETRY"); if (retry != null) { retry.IsVisible = () => (lobby.Map.Status == MapStatus.DownloadError || lobby.Map.Status == MapStatus.Unavailable) && lobby.Map != MapCache.UnknownMap; retry.OnClick = () => { if (lobby.Map.Status == MapStatus.DownloadError) { lobby.Map.Install(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)))); } else if (lobby.Map.Status == MapStatus.Unavailable) { modData.MapCache.QueryRemoteMapDetails(new[] { lobby.Map.Uid }); } }; retry.GetText = () => lobby.Map.Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search"; } var progressbar = progress.GetOrNull <ProgressBarWidget>("MAP_PROGRESSBAR"); if (progressbar != null) { progressbar.IsIndeterminate = () => lobby.Map.DownloadPercentage == 0; progressbar.GetPercentage = () => lobby.Map.DownloadPercentage; progressbar.IsVisible = () => !retry.IsVisible(); } } }
void RefreshServerListInner(IEnumerable <GameServer> 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 <Widget>(); foreach (var modGames in mods) { if (modGames.All(Filtered)) { continue; } var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); var headerTitle = modGames.First().ModLabel; header.Get <LabelWidget>("LABEL").GetText = () => headerTitle; rows.Add(header); foreach (var loop in modGames.OrderByDescending(g => g.IsJoinable).ThenByDescending(g => g.Players)) { var game = loop; if (game == null || Filtered(game)) { continue; } var canJoin = game.IsJoinable; var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => Join(game)); var title = item.GetOrNull <LabelWidget>("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 <ImageWidget>("PASSWORD_PROTECTED"); if (password != null) { password.IsVisible = () => game.Protected; password.GetImageName = () => canJoin ? "protected" : "protected-disabled"; } var players = item.GetOrNull <LabelWidget>("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 <LabelWidget>("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 <LabelWidget>("LOCATION"); if (location != null) { var cachedServerLocation = GeoIP.LookupCountry(game.Address.Split(':')[0]); location.GetText = () => cachedServerLocation; location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor; } if (currentServer != null && game.Address == currentServer.Address) { nextServerRow = item; } rows.Add(item); } } Game.RunAfterTick(() => { serverList.RemoveChildren(); SelectServer(null); if (games == null) { searchStatus = SearchStatus.Failed; return; } if (!rows.Any()) { searchStatus = SearchStatus.NoGames; return; } searchStatus = SearchStatus.Hidden; // Search for any unknown maps if (Game.Settings.Game.AllowDownloading) { Game.ModData.MapCache.QueryRemoteMapDetails(games.Where(g => !Filtered(g)).Select(g => g.Map)); } foreach (var row in rows) { serverList.AddChild(row); } if (nextServerRow != null) { nextServerRow.OnClick(); } }); }
void SelectReplay(ReplayMetadata replay) { selectedReplay = replay; selectedSpawns = (selectedReplay != null) ? LobbyUtils.GetSpawnOccupants(selectedReplay.GameInfo.Players, selectedReplay.GameInfo.MapPreview) : new Dictionary <CPos, SpawnOccupant>(); if (replay == null) { return; } try { var players = replay.GameInfo.Players .GroupBy(p => p.Team) .OrderBy(g => g.Key); var teams = new Dictionary <string, IEnumerable <GameInformation.Player> >(); 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); } playerList.RemoveChildren(); foreach (var kv in teams) { var group = kv.Key; if (group.Length > 0) { var header = ScrollItemWidget.Setup(playerHeader, () => true, () => { }); header.Get <LabelWidget>("LABEL").GetText = () => group; playerList.AddChild(header); } foreach (var option in kv.Value) { var o = option; var color = o.Color.RGB; var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { }); 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 = () => color; var flag = item.Get <ImageWidget>("FLAG"); flag.GetImageCollection = () => "flags"; flag.GetImageName = () => o.FactionId; playerList.AddChild(item); } } } catch (Exception e) { Log.Write("debug", "Exception while parsing replay: {0}", e); SelectReplay(null); } }
void EnumerateMaps(MapClassification tab, ScrollItemWidget template) { int playerCountFilter; if (!int.TryParse(mapFilter, out playerCountFilter)) { playerCountFilter = -1; } var maps = tabMaps[tab] .Where(m => category == null || m.Categories.Contains(category)) .Where(m => mapFilter == null || (m.Title != null && m.Title.IndexOf(mapFilter, StringComparison.OrdinalIgnoreCase) >= 0) || (m.Author != null && m.Author.IndexOf(mapFilter, StringComparison.OrdinalIgnoreCase) >= 0) || m.PlayerCount == playerCountFilter) .OrderBy(m => m.PlayerCount) .ThenBy(m => m.Title); scrollpanels[tab].RemoveChildren(); foreach (var loop in maps) { var preview = loop; // Access the minimap to trigger async generation of the minimap. preview.GetMinimap(); Action dblClick = () => { if (onSelect != null) { Ui.CloseWindow(); onSelect(preview.Uid); } }; var item = ScrollItemWidget.Setup(preview.Uid, template, () => selectedUid == preview.Uid, () => selectedUid = preview.Uid, dblClick); item.IsVisible = () => item.RenderBounds.IntersectsWith(scrollpanels[tab].RenderBounds); var titleLabel = item.Get <LabelWidget>("TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = WidgetUtils.TruncateText(preview.Title, titleLabel.Bounds.Width, font); titleLabel.GetText = () => title; } var previewWidget = item.Get <MapPreviewWidget>("PREVIEW"); previewWidget.Preview = () => preview; var detailsWidget = item.GetOrNull <LabelWidget>("DETAILS"); if (detailsWidget != null) { var type = preview.Categories.FirstOrDefault(); var details = ""; if (type != null) { details = type + " "; } details += "({0} players)".F(preview.PlayerCount); detailsWidget.GetText = () => details; } var authorWidget = item.GetOrNull <LabelWidget>("AUTHOR"); if (authorWidget != null) { var font = Game.Renderer.Fonts[authorWidget.Font]; var author = WidgetUtils.TruncateText("Created by {0}".F(preview.Author), authorWidget.Bounds.Width, font); authorWidget.GetText = () => author; } var sizeWidget = item.GetOrNull <LabelWidget>("SIZE"); if (sizeWidget != null) { var size = preview.Bounds.Width + "x" + preview.Bounds.Height; var numberPlayableCells = preview.Bounds.Width * preview.Bounds.Height; if (numberPlayableCells >= 120 * 120) { size += " (Huge)"; } else if (numberPlayableCells >= 90 * 90) { size += " (Large)"; } else if (numberPlayableCells >= 60 * 60) { size += " (Medium)"; } else { size += " (Small)"; } sizeWidget.GetText = () => size; } scrollpanels[tab].AddChild(item); } if (tab == currentTab) { visibleMaps = maps.Select(m => m.Uid).ToArray(); SetupGameModeDropdown(currentTab, gameModeDropdown, template); } if (visibleMaps.Contains(selectedUid)) { scrollpanels[tab].ScrollToItem(selectedUid); } }
void SelectReplay(ReplayMetadata replay) { selectedReplay = replay; map = selectedReplay != null ? selectedReplay.GameInfo.MapPreview : MapCache.UnknownMap; if (replay == null) { return; } try { if (map.Status != MapStatus.Available) { if (map.Status == MapStatus.DownloadAvailable) { LoadMapPreviewRules(map); } else if (Game.Settings.Game.AllowDownloading) { modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { map.Uid }, LoadMapPreviewRules); } } var players = replay.GameInfo.Players .GroupBy(p => p.Team) .OrderBy(g => g.Key); var teams = new Dictionary <string, IEnumerable <GameInformation.Player> >(); 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); } playerList.RemoveChildren(); foreach (var kv in teams) { var group = kv.Key; if (group.Length > 0) { var header = ScrollItemWidget.Setup(playerHeader, () => true, () => { }); header.Get <LabelWidget>("LABEL").GetText = () => group; playerList.AddChild(header); } foreach (var option in kv.Value) { var o = option; var color = o.Color; var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { }); 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 = () => color; var flag = item.Get <ImageWidget>("FLAG"); flag.GetImageCollection = () => "flags"; var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos <FactionInfo>(); flag.GetImageName = () => (factionInfo != null && factionInfo.Any(f => f.InternalName == o.FactionId)) ? o.FactionId : "Random"; playerList.AddChild(item); } } } catch (Exception e) { Log.Write("debug", "Exception while parsing replay: {0}", e); SelectReplay(null); } }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer, Action <bool> hideMenu) { var player = world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); var spectatorTemplate = playerPanel.Get("SPECTATOR_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); var scoreCache = new CachedTransform <int, string>(s => s.ToString()); var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience); teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum()); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.Player; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); WidgetUtils.BindPlayerNameAndStatus(nameLabel, pp); nameLabel.GetColor = () => pp.Color; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.RelationshipWith(pp) == PlayerRelationship.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; var factionName = pp.Faction.Name != pp.DisplayFaction.Name ? "{0} ({1})".F(pp.DisplayFaction.Name, pp.Faction.Name) : pp.Faction.Name; item.Get <LabelWidget>("FACTION").GetText = () => factionName; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var scoreCache = new CachedTransform <int, string>(s => s.ToString()); item.Get <LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.PlayerStatistics?.Experience ?? 0); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = spectatorTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <(string Name, string Suffix), string>(c => WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - suffixLength.Update(c.Suffix), nameFont) + c.Suffix); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; return(name.Update((client.Name, suffix))); }; var kickButton = item.Get <ButtonWidget>("KICK"); kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index && client.State != Session.ClientState.Disconnected; kickButton.OnClick = () => { hideMenu(true); ConfirmationDialogs.ButtonPrompt( title: "Kick {0}?".F(client.Name), text: "They will not be able to rejoin this game.", onConfirm: () => { orderManager.IssueOrder(Order.Command("kick {0} {1}".F(client.Index, false))); hideMenu(false); }, onCancel: () => hideMenu(false), confirmText: "Kick"); }; playerPanel.AddChild(item); } } }
void RefreshServerListInner(List <GameServer> 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 <Widget>(); foreach (var modGames in mods) { if (modGames.All(Filtered)) { continue; } var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); var headerTitle = modGames.First().ModLabel; header.Get <LabelWidget>("LABEL").GetText = () => headerTitle; rows.Add(header); Func <GameServer, int> listOrder = g => { // Servers waiting for players are always first if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0) { return(0); } // 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)) { if (Filtered(game)) { continue; } var canJoin = game.IsJoinable; var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => Join(game)); var title = item.GetOrNull <LabelWidget>("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 <ImageWidget>("PASSWORD_PROTECTED"); if (password != null) { password.IsVisible = () => game.Protected; password.GetImageName = () => canJoin ? "protected" : "protected-disabled"; } var players = item.GetOrNull <LabelWidget>("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 <LabelWidget>("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 <LabelWidget>("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); } } } Game.RunAfterTick(() => { serverList.RemoveChildren(); SelectServer(null); if (games == null) { searchStatus = SearchStatus.Failed; return; } if (!rows.Any()) { searchStatus = SearchStatus.NoGames; return; } searchStatus = SearchStatus.Hidden; // Search for any unknown maps if (Game.Settings.Game.AllowDownloading) { modData.MapCache.QueryRemoteMapDetails(services.MapRepository, games.Where(g => !Filtered(g)).Select(g => g.Map)); } foreach (var row in rows) { serverList.AddChild(row); } if (nextServerRow != null) { nextServerRow.OnClick(); } }); }
public ConnectionSwitchModLogic(Widget widget, OrderManager orderManager, Action onAbort, Action <string> onRetry) { var panel = widget; var abortButton = panel.Get <ButtonWidget>("ABORT_BUTTON"); var switchButton = panel.Get <ButtonWidget>("SWITCH_BUTTON"); var modTitle = orderManager.ServerExternalMod.Title; var modVersion = orderManager.ServerExternalMod.Version; var modIcon = orderManager.ServerExternalMod.Icon; switchButton.OnClick = () => { var launchCommand = "Launch.Connect=" + orderManager.Host + ":" + orderManager.Port; Game.SwitchToExternalMod(orderManager.ServerExternalMod, new[] { launchCommand }, () => { orderManager.ServerError = "Failed to switch mod."; Ui.CloseWindow(); Ui.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() { { "orderManager", orderManager }, { "onAbort", onAbort }, { "onRetry", onRetry } }); }); }; abortButton.Visible = onAbort != null; abortButton.OnClick = () => { Ui.CloseWindow(); onAbort(); }; var width = 0; var title = panel.GetOrNull <LabelWidget>("MOD_TITLE"); if (title != null) { var font = Game.Renderer.Fonts[title.Font]; var label = WidgetUtils.TruncateText(modTitle, title.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, title.Bounds.X + labelWidth); title.Bounds.Width = labelWidth; title.GetText = () => label; } var version = panel.GetOrNull <LabelWidget>("MOD_VERSION"); if (version != null) { var font = Game.Renderer.Fonts[version.Font]; var label = WidgetUtils.TruncateText(modVersion, version.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, version.Bounds.X + labelWidth); version.Bounds.Width = labelWidth; version.GetText = () => label; } var logo = panel.GetOrNull <RGBASpriteWidget>("MOD_ICON"); if (logo != null && modIcon != null) { logo.GetSprite = () => modIcon; } if (logo != null && modIcon == null) { // Hide the logo and center just the text if (title != null) { title.Bounds.Offset(logo.Bounds.Left - title.Bounds.Left, 0); } if (version != null) { version.Bounds.Offset(logo.Bounds.Left - version.Bounds.Left, 0); } width -= logo.Bounds.Width; } else { // Add an equal logo margin on the right of the text width += logo.Bounds.Width; } var container = panel.GetOrNull("MOD_CONTAINER"); if (container != null) { container.Bounds.Offset((container.Bounds.Width - width) / 2, 0); container.Bounds.Width = width; } }
public GameInfoStatsLogic(Widget widget, World world) { var lp = world.LocalPlayer; var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); checkbox.IsChecked = () => lp.WinState != WinState.Undefined; checkbox.GetCheckType = () => lp.WinState == WinState.Won ? "checked" : "crossed"; if (lp.HasObjectives) { var mo = lp.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); statusLabel.GetText = () => lp.WinState == WinState.Won ? "Accomplished" : lp.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => lp.WinState == WinState.Won ? Color.LimeGreen : lp.WinState == WinState.Lost ? Color.Red : Color.White; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); foreach (var p in world.Players.Where(a => !a.NonCombatant)) { var pp = p; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Network.Session.ClientState.Disconnected) { suffix = " (Gone)"; } var sl = suffixLength.Update(suffix); return(name.Update(Pair.New(pp.PlayerName, sl)) + suffix); }; nameLabel.GetColor = () => pp.Color.RGB; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (lp.Stances[pp] == Stance.Ally || lp.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var team = item.Get <LabelWidget>("TEAM"); var teamNumber = pp.PlayerReference.Playable ? ((client == null) ? 0 : client.Team) : pp.PlayerReference.Team; team.GetText = () => (teamNumber == 0) ? "-" : teamNumber.ToString(); playerPanel.AddChild(item); var stats = pp.PlayerActor.TraitOrDefault <PlayerStatistics>(); if (stats == null) { break; } var totalKills = stats.UnitsKilled + stats.BuildingsKilled; var totalDeaths = stats.UnitsDead + stats.BuildingsDead; item.Get <LabelWidget>("KILLS").GetText = () => totalKills.ToString(); item.Get <LabelWidget>("DEATHS").GetText = () => totalDeaths.ToString(); } }
public ServerCreationLogic(Widget widget, ModData modData, Action onExit, Action openLobby) { panel = widget; onCreate = openLobby; this.onExit = onExit; var settings = Game.Settings; preview = modData.MapCache[modData.MapCache.ChooseInitialMap(Game.Settings.Server.Map, Game.CosmeticRandom)]; panel.Get <ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin; var mapButton = panel.GetOrNull <ButtonWidget>("MAP_BUTTON"); if (mapButton != null) { panel.Get <ButtonWidget>("MAP_BUTTON").OnClick = () => { Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", preview.Uid }, { "initialTab", MapClassification.System }, { "onExit", () => { } }, { "onSelect", (Action <string>)(uid => preview = modData.MapCache[uid]) }, { "filter", MapVisibility.Lobby }, { "onStart", () => { } } }); }; panel.Get <MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview; var mapTitle = panel.Get <LabelWidget>("MAP_NAME"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(preview); } } var serverName = panel.Get <TextFieldWidget>("SERVER_NAME"); serverName.Text = Settings.SanitizedServerName(settings.Server.Name); serverName.OnEnterKey = () => { serverName.YieldKeyboardFocus(); return(true); }; serverName.OnLoseFocus = () => { serverName.Text = Settings.SanitizedServerName(serverName.Text); settings.Server.Name = serverName.Text; }; panel.Get <TextFieldWidget>("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); advertiseOnline = Game.Settings.Server.AdvertiseOnline; var externalPort = panel.Get <TextFieldWidget>("EXTERNAL_PORT"); externalPort.Text = settings.Server.ExternalPort.ToString(); externalPort.IsDisabled = () => !advertiseOnline; var advertiseCheckbox = panel.Get <CheckboxWidget>("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => advertiseOnline ^= true; allowPortForward = Game.Settings.Server.AllowPortForward; var checkboxUPnP = panel.Get <CheckboxWidget>("UPNP_CHECKBOX"); checkboxUPnP.IsChecked = () => allowPortForward; checkboxUPnP.OnClick = () => allowPortForward ^= true; checkboxUPnP.IsDisabled = () => !Game.Settings.Server.AllowPortForward; var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); if (passwordField != null) { passwordField.Text = Game.Settings.Server.Password; } }
public ReplayBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart) { panel = widget; this.modData = modData; this.onStart = onStart; Game.BeforeGameStart += OnGameStart; playerList = panel.Get <ScrollPanelWidget>("PLAYER_LIST"); playerHeader = playerList.Get <ScrollItemWidget>("HEADER"); playerTemplate = playerList.Get <ScrollItemWidget>("TEMPLATE"); playerList.RemoveChildren(); panel.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => { cancelLoadingReplays = true; Ui.CloseWindow(); onExit(); }; replayList = panel.Get <ScrollPanelWidget>("REPLAY_LIST"); var template = panel.Get <ScrollItemWidget>("REPLAY_TEMPLATE"); var mod = modData.Manifest.Mod; var dir = Platform.ResolvePath("^", "Replays", mod.Id, mod.Version); if (Directory.Exists(dir)) { ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template)); } var watch = panel.Get <ButtonWidget>("WATCH_BUTTON"); watch.IsDisabled = () => selectedReplay == null || selectedReplay.GameInfo.MapPreview.Status != MapStatus.Available; watch.OnClick = () => { WatchReplay(); }; panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null; var preview = panel.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.SpawnOccupants = () => selectedSpawns; preview.Preview = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview : null; var titleLabel = panel.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.IsVisible = () => selectedReplay != null; var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(selectedReplay.GameInfo.MapPreview); } var type = panel.GetOrNull <LabelWidget>("MAP_TYPE"); if (type != null) { var mapType = new CachedTransform <MapPreview, string>(m => m.Categories.FirstOrDefault() ?? ""); type.GetText = () => mapType.Update(selectedReplay.GameInfo.MapPreview); } panel.Get <LabelWidget>("DURATION").GetText = () => WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds); SetupFilters(); SetupManagement(); }
Action InitAudioPanel(Widget panel) { var ss = Game.Settings.Sound; BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks"); BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute"); BindSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume"); BindSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume"); BindSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume"); var muteCheckbox = panel.Get <CheckboxWidget>("MUTE_SOUND"); var muteCheckboxOnClick = muteCheckbox.OnClick; var muteCheckboxIsChecked = muteCheckbox.IsChecked; muteCheckbox.IsChecked = () => muteCheckboxIsChecked() || Game.Sound.DummyEngine; muteCheckbox.IsDisabled = () => Game.Sound.DummyEngine; muteCheckbox.OnClick = () => { muteCheckboxOnClick(); if (ss.Mute) { Game.Sound.MuteAudio(); } else { Game.Sound.UnmuteAudio(); } }; // Replace controls with a warning label if sound is disabled var noDeviceLabel = panel.GetOrNull("NO_AUDIO_DEVICE"); if (noDeviceLabel != null) { noDeviceLabel.Visible = Game.Sound.DummyEngine; } var controlsContainer = panel.GetOrNull("AUDIO_CONTROLS"); if (controlsContainer != null) { controlsContainer.Visible = !Game.Sound.DummyEngine; } var soundVolumeSlider = panel.Get <SliderWidget>("SOUND_VOLUME"); soundVolumeSlider.OnChange += x => Game.Sound.SoundVolume = x; var musicVolumeSlider = panel.Get <SliderWidget>("MUSIC_VOLUME"); musicVolumeSlider.OnChange += x => Game.Sound.MusicVolume = x; var videoVolumeSlider = panel.Get <SliderWidget>("VIDEO_VOLUME"); videoVolumeSlider.OnChange += x => Game.Sound.VideoVolume = x; var devices = Game.Sound.AvailableDevices(); soundDevice = devices.FirstOrDefault(d => d.Device == ss.Device) ?? devices.First(); var audioDeviceDropdown = panel.Get <DropDownButtonWidget>("AUDIO_DEVICE"); audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices); var deviceFont = Game.Renderer.Fonts[audioDeviceDropdown.Font]; var deviceLabel = new CachedTransform <SoundDevice, string>( s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont)); audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice); return(() => { ss.Device = soundDevice.Device; }); }
public IngameScoreScreenLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer) { var spawner = world.WorldActor.Trait <SpawnSSUnit>(); var closeButton = widget.Get <ButtonWidget>("CLOSE_STATS"); var openButton = widget.Get <ButtonWidget>("OPEN_STATS"); var stats = widget.Get <ContainerWidget>("STATS_HEADERS"); var player = world.RenderPlayer ?? world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); closeButton.OnClick = () => { stats.Visible = false; playerPanel.Visible = false; teamTemplate.Visible = false; playerTemplate.Visible = false; closeButton.Visible = false; openButton.Visible = true; }; openButton.OnClick = () => { stats.Visible = true; playerPanel.Visible = true; teamTemplate.Visible = true; playerTemplate.Visible = true; closeButton.Visible = true; openButton.Visible = false; }; var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics != null ? gg.PlayerStatistics.Experience : 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); var scoreCache = new CachedTransform <int, string>(s => s.ToString()); var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience); teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum()); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.Player; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <(string Name, WinState WinState, Session.ClientState ClientState), string>(c => { var suffix = ""; if (pp.WinState == WinState.Lost) { suffix = " (L)"; } else if (pp.WinState == WinState.Won) { suffix = " (W)"; } if (client != null && client.State == Session.ClientState.Disconnected) { suffix = " (G)"; } return(WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix); }); nameLabel.GetText = () => { var clientState = client != null ? client.State : Session.ClientState.Ready; return(name.Update((pp.PlayerName, pp.WinState, clientState))); }; // nameLabel.GetColor = () => pp.Color; nameLabel.GetColor = () => Color.White; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.RelationshipWith(pp) == PlayerRelationship.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => spawner.Classes[pp]; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; } var scoreCache = new CachedTransform <int, string>(s => s.ToString()); item.Get <LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = playerTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <(string Name, string Suffix), string>(c => WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - suffixLength.Update(c.Suffix), nameFont) + c.Suffix); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (G)" : ""; return(name.Update((client.Name, suffix))); }; item.Get <ImageWidget>("FACTIONFLAG").IsVisible = () => false; playerPanel.AddChild(item); } } }
List <Widget> LoadGameRows(List <GameServer> games, out ScrollItemWidget nextServerRow) { nextServerRow = null; var rows = new List <Widget>(); var mods = games.GroupBy(g => g.ModLabel) .OrderByDescending(g => GroupSortOrder(g.First())) .ThenByDescending(g => g.Count()); foreach (var modGames in mods) { if (modGames.All(Filtered)) { continue; } var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); var headerTitle = modGames.First().ModLabel; header.Get <LabelWidget>("LABEL").GetText = () => headerTitle; rows.Add(header); Func <GameServer, int> listOrder = g => { // Servers waiting for players are always first if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0) { return(0); } // 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)) { if (Filtered(game)) { continue; } var canJoin = game.IsJoinable; var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => onJoin(game)); var title = item.GetOrNull <LabelWidget>("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 <ImageWidget>("PASSWORD_PROTECTED"); if (password != null) { password.IsVisible = () => game.Protected; password.GetImageName = () => canJoin ? "protected" : "protected-disabled"; } var players = item.GetOrNull <LabelWithTooltipWidget>("PLAYERS"); if (players != null) { var label = "{0} / {1}".F(game.Players + game.Bots, game.MaxPlayers + game.Bots) + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : ""); var color = canJoin ? players.TextColor : incompatibleGameColor; players.GetText = () => label; players.GetColor = () => color; if (game.Clients.Any()) { var displayClients = game.Clients.Select(c => c.Name); if (game.Clients.Length > 10) { displayClients = displayClients .Take(9) .Append("+ {0} other players".F(game.Clients.Length - 9)); } var tooltip = displayClients.JoinWith("\n"); players.GetTooltipText = () => tooltip; } else { players.GetTooltipText = null; } } var state = item.GetOrNull <LabelWidget>("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 <LabelWidget>("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); } } } return(rows); }
public override void Tick() { if (actorIDStatus != nextActorIDStatus) { if ((actorIDStatus & nextActorIDStatus) == 0) { var offset = actorIDErrorLabel.Bounds.Height; if (nextActorIDStatus == ActorIDStatus.Normal) { offset *= -1; } actorEditPanel.Bounds.Height += offset; initContainer.Bounds.Y += offset; buttonContainer.Bounds.Y += offset; } actorIDStatus = nextActorIDStatus; } var actor = editor.DefaultBrush.SelectedActor; if (actor != null) { var origin = worldRenderer.Viewport.WorldToViewPx(new int2(actor.Bounds.Right, actor.Bounds.Top)); // If we scrolled, hide the edit box for a moment if (lastScrollPosition.X != origin.X || lastScrollPosition.Y != origin.Y) { lastScrollTime = Game.RunTime; lastScrollPosition = origin; } // If we changed actor, move widgets if (CurrentActor != actor) { lastScrollTime = 0; // Ensure visible CurrentActor = actor; editActorPreview = new EditActorPreview(CurrentActor); initialActorID = actorIDField.Text = actor.ID; var font = Game.Renderer.Fonts[typeLabel.Font]; var truncatedType = WidgetUtils.TruncateText(actor.DescriptiveName, typeLabel.Bounds.Width, font); typeLabel.Text = truncatedType; actorIDField.CursorPosition = actor.ID.Length; nextActorIDStatus = ActorIDStatus.Normal; // Remove old widgets var oldInitHeight = initContainer.Bounds.Height; initContainer.Bounds.Height = 0; initContainer.RemoveChildren(); // Add owner dropdown var ownerContainer = dropdownOptionTemplate.Clone(); ownerContainer.Get <LabelWidget>("LABEL").GetText = () => "Owner"; var ownerDropdown = ownerContainer.Get <DropDownButtonWidget>("OPTION"); var selectedOwner = actor.Owner; Action <EditorActorPreview, PlayerReference> updateOwner = (preview, reference) => { preview.Owner = reference; preview.ReplaceInit(new OwnerInit(reference.Name)); }; var ownerHandler = new EditorActorOptionActionHandle <PlayerReference>(updateOwner, actor.Owner); editActorPreview.Add(ownerHandler); Func <PlayerReference, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, () => selectedOwner == option, () => { selectedOwner = option; updateOwner(CurrentActor, selectedOwner); ownerHandler.OnChange(option); }); item.Get <LabelWidget>("LABEL").GetText = () => option.Name; item.GetColor = () => option.Color; return(item); }; ownerDropdown.GetText = () => selectedOwner.Name; ownerDropdown.GetColor = () => selectedOwner.Color; ownerDropdown.OnClick = () => { var owners = editorActorLayer.Players.Players.Values.OrderBy(p => p.Name); ownerDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, owners, setupItem); }; initContainer.Bounds.Height += ownerContainer.Bounds.Height; initContainer.AddChild(ownerContainer); // Add new children for inits var options = actor.Info.TraitInfos <IEditorActorOptions>() .SelectMany(t => t.ActorOptions(actor.Info, worldRenderer.World)) .OrderBy(o => o.DisplayOrder); foreach (var o in options) { if (o is EditorActorCheckbox) { var co = (EditorActorCheckbox)o; var checkboxContainer = checkboxOptionTemplate.Clone(); checkboxContainer.Bounds.Y = initContainer.Bounds.Height; initContainer.Bounds.Height += checkboxContainer.Bounds.Height; var checkbox = checkboxContainer.Get <CheckboxWidget>("OPTION"); checkbox.GetText = () => co.Name; var editorActionHandle = new EditorActorOptionActionHandle <bool>(co.OnChange, co.GetValue(actor)); editActorPreview.Add(editorActionHandle); checkbox.IsChecked = () => co.GetValue(actor); checkbox.OnClick = () => { var newValue = co.GetValue(actor) ^ true; co.OnChange(actor, newValue); editorActionHandle.OnChange(newValue); }; initContainer.AddChild(checkboxContainer); } else if (o is EditorActorSlider) { var so = (EditorActorSlider)o; var sliderContainer = sliderOptionTemplate.Clone(); sliderContainer.Bounds.Y = initContainer.Bounds.Height; initContainer.Bounds.Height += sliderContainer.Bounds.Height; sliderContainer.Get <LabelWidget>("LABEL").GetText = () => so.Name; var slider = sliderContainer.Get <SliderWidget>("OPTION"); slider.MinimumValue = so.MinValue; slider.MaximumValue = so.MaxValue; slider.Ticks = so.Ticks; var editorActionHandle = new EditorActorOptionActionHandle <float>(so.OnChange, so.GetValue(actor)); editActorPreview.Add(editorActionHandle); slider.GetValue = () => so.GetValue(actor); slider.OnChange += value => so.OnChange(actor, value); slider.OnChange += value => editorActionHandle.OnChange(value); initContainer.AddChild(sliderContainer); } else if (o is EditorActorDropdown) { var ddo = (EditorActorDropdown)o; var dropdownContainer = dropdownOptionTemplate.Clone(); dropdownContainer.Bounds.Y = initContainer.Bounds.Height; initContainer.Bounds.Height += dropdownContainer.Bounds.Height; dropdownContainer.Get <LabelWidget>("LABEL").GetText = () => ddo.Name; var editorActionHandle = new EditorActorOptionActionHandle <string>(ddo.OnChange, ddo.GetValue(actor)); editActorPreview.Add(editorActionHandle); var dropdown = dropdownContainer.Get <DropDownButtonWidget>("OPTION"); Func <KeyValuePair <string, string>, ScrollItemWidget, ScrollItemWidget> dropdownSetup = (option, template) => { var item = ScrollItemWidget.Setup(template, () => ddo.GetValue(actor) == option.Key, () => { ddo.OnChange(actor, option.Key); editorActionHandle.OnChange(option.Key); }); item.Get <LabelWidget>("LABEL").GetText = () => option.Value; return(item); }; dropdown.GetText = () => ddo.Labels[ddo.GetValue(actor)]; dropdown.OnClick = () => dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, ddo.Labels, dropdownSetup); initContainer.AddChild(dropdownContainer); } } actorEditPanel.Bounds.Height += initContainer.Bounds.Height - oldInitHeight; buttonContainer.Bounds.Y += initContainer.Bounds.Height - oldInitHeight; } // Set the edit panel to the right of the selection border. actorEditPanel.Bounds.X = origin.X + editPanelPadding; actorEditPanel.Bounds.Y = origin.Y; } else { // Selected actor is null, hide the border and edit panel. actorIDField.YieldKeyboardFocus(); CurrentActor = null; } }
public ServerListLogic(Widget widget, ModData modData, Action <GameServer> onJoin) { this.modData = modData; this.onJoin = onJoin; services = modData.Manifest.Get <WebServices>(); incompatibleVersionColor = ChromeMetrics.Get <Color>("IncompatibleVersionColor"); incompatibleGameColor = ChromeMetrics.Get <Color>("IncompatibleGameColor"); incompatibleProtectedGameColor = ChromeMetrics.Get <Color>("IncompatibleProtectedGameColor"); protectedGameColor = ChromeMetrics.Get <Color>("ProtectedGameColor"); waitingGameColor = ChromeMetrics.Get <Color>("WaitingGameColor"); incompatibleWaitingGameColor = ChromeMetrics.Get <Color>("IncompatibleWaitingGameColor"); gameStartedColor = ChromeMetrics.Get <Color>("GameStartedColor"); incompatibleGameStartedColor = ChromeMetrics.Get <Color>("IncompatibleGameStartedColor"); serverList = widget.Get <ScrollPanelWidget>("SERVER_LIST"); headerTemplate = serverList.Get <ScrollItemWidget>("HEADER_TEMPLATE"); serverTemplate = serverList.Get <ScrollItemWidget>("SERVER_TEMPLATE"); noticeContainer = widget.GetOrNull("NOTICE_CONTAINER"); if (noticeContainer != null) { noticeContainer.IsVisible = () => showNotices; noticeContainer.Get("OUTDATED_VERSION_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.Outdated; noticeContainer.Get("UNKNOWN_VERSION_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.Unknown; noticeContainer.Get("PLAYTEST_AVAILABLE_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.PlaytestAvailable; } var noticeWatcher = widget.Get <LogicTickerWidget>("NOTICE_WATCHER"); if (noticeWatcher != null && noticeContainer != null) { var containerHeight = noticeContainer.Bounds.Height; noticeWatcher.OnTick = () => { var show = services.ModVersionStatus != ModVersionStatus.NotChecked && services.ModVersionStatus != ModVersionStatus.Latest; if (show != showNotices) { var dir = show ? 1 : -1; serverList.Bounds.Y += dir * containerHeight; serverList.Bounds.Height -= dir * containerHeight; showNotices = show; } }; } joinButton = widget.GetOrNull <ButtonWidget>("JOIN_BUTTON"); if (joinButton != null) { joinButton.IsVisible = () => currentServer != null; joinButton.IsDisabled = () => !currentServer.IsJoinable; joinButton.OnClick = () => onJoin(currentServer); joinButtonY = joinButton.Bounds.Y; } // Display the progress label over the server list // The text is only visible when the list is empty var progressText = widget.Get <LabelWidget>("PROGRESS_LABEL"); progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; progressText.GetText = ProgressLabelText; var gs = Game.Settings.Game; Action <MPGameFilters> toggleFilterFlag = f => { gs.MPGameFilters ^= f; Game.Settings.Save(); RefreshServerList(); }; var filtersButton = widget.GetOrNull <DropDownButtonWidget>("FILTERS_DROPDOWNBUTTON"); if (filtersButton != null) { // HACK: MULTIPLAYER_FILTER_PANEL doesn't follow our normal procedure for dropdown creation // but we still need to be able to set the dropdown width based on the parent // The yaml should use PARENT_RIGHT instead of DROPDOWN_WIDTH var filtersPanel = Ui.LoadWidget("MULTIPLAYER_FILTER_PANEL", filtersButton, new WidgetArgs()); filtersButton.Children.Remove(filtersPanel); var showWaitingCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("WAITING_FOR_PLAYERS"); if (showWaitingCheckbox != null) { showWaitingCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Waiting); showWaitingCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Waiting); } var showEmptyCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("EMPTY"); if (showEmptyCheckbox != null) { showEmptyCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Empty); showEmptyCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Empty); } var showAlreadyStartedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("ALREADY_STARTED"); if (showAlreadyStartedCheckbox != null) { showAlreadyStartedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Started); showAlreadyStartedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Started); } var showProtectedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("PASSWORD_PROTECTED"); if (showProtectedCheckbox != null) { showProtectedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Protected); showProtectedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Protected); } var showIncompatibleCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("INCOMPATIBLE_VERSION"); if (showIncompatibleCheckbox != null) { showIncompatibleCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Incompatible); showIncompatibleCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Incompatible); } filtersButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; filtersButton.OnMouseDown = _ => { filtersButton.RemovePanel(); filtersButton.AttachPanel(filtersPanel); }; } var reloadButton = widget.GetOrNull <ButtonWidget>("RELOAD_BUTTON"); if (reloadButton != null) { reloadButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; reloadButton.OnClick = RefreshServerList; var reloadIcon = reloadButton.GetOrNull <ImageWidget>("IMAGE_RELOAD"); if (reloadIcon != null) { var disabledFrame = 0; var disabledImage = "disabled-" + disabledFrame.ToString(); reloadIcon.GetImageName = () => searchStatus == SearchStatus.Fetching ? disabledImage : reloadIcon.ImageName; var reloadTicker = reloadIcon.Get <LogicTickerWidget>("ANIMATION"); if (reloadTicker != null) { reloadTicker.OnTick = () => { disabledFrame = searchStatus == SearchStatus.Fetching ? (disabledFrame + 1) % 12 : 0; disabledImage = "disabled-" + disabledFrame.ToString(); }; } } } var playersLabel = widget.GetOrNull <LabelWidget>("PLAYER_COUNT"); if (playersLabel != null) { var playersText = new CachedTransform <int, string>(c => c == 1 ? "1 Player Online" : c.ToString() + " Players Online"); playersLabel.IsVisible = () => playerCount != 0; playersLabel.GetText = () => playersText.Update(playerCount); } mapPreview = widget.GetOrNull <MapPreviewWidget>("SELECTED_MAP_PREVIEW"); if (mapPreview != null) { mapPreview.Preview = () => currentMap; } var mapTitle = widget.GetOrNull <LabelWidget>("SELECTED_MAP"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform <MapPreview, string>(m => m == null ? "No Server Selected" : WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(currentMap); } var ip = widget.GetOrNull <LabelWidget>("SELECTED_IP"); if (ip != null) { ip.IsVisible = () => currentServer != null; ip.GetText = () => currentServer.Address; } var status = widget.GetOrNull <LabelWidget>("SELECTED_STATUS"); if (status != null) { status.IsVisible = () => currentServer != null; status.GetText = () => GetStateLabel(currentServer); status.GetColor = () => GetStateColor(currentServer, status); } var modVersion = widget.GetOrNull <LabelWidget>("SELECTED_MOD_VERSION"); if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; var font = Game.Renderer.Fonts[modVersion.Font]; var version = new CachedTransform <GameServer, string>(s => WidgetUtils.TruncateText(s.ModLabel, modVersion.Bounds.Width, font)); modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull <LabelWidget>("SELECTED_PLAYERS"); if (players != null) { players.IsVisible = () => currentServer != null && (clientContainer == null || !currentServer.Clients.Any()); players.GetText = () => PlayersLabel(currentServer); } clientContainer = widget.GetOrNull("CLIENT_LIST_CONTAINER"); if (clientContainer != null) { 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(); } lanGameLocations = new List <BeaconLocation>(); try { lanGameProbe = new Probe("OpenRALANGame"); lanGameProbe.BeaconsUpdated += locations => lanGameLocations = locations; lanGameProbe.Start(); } catch (Exception ex) { Log.Write("debug", "BeaconLib.Probe: " + ex.Message); } RefreshServerList(); }
public ServerCreationLogic(Widget widget, ModData modData, Action onExit, Action openLobby) { panel = widget; onCreate = openLobby; this.onExit = onExit; var settings = Game.Settings; preview = modData.MapCache[modData.MapCache.ChooseInitialMap(Game.Settings.Server.Map, Game.CosmeticRandom)]; panel.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); }; panel.Get <ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin; var mapButton = panel.GetOrNull <ButtonWidget>("MAP_BUTTON"); if (mapButton != null) { panel.Get <ButtonWidget>("MAP_BUTTON").OnClick = () => { Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", preview.Uid }, { "initialTab", MapClassification.System }, { "onExit", () => { } }, { "onSelect", (Action <string>)(uid => preview = modData.MapCache[uid]) }, { "filter", MapVisibility.Lobby }, { "onStart", () => { } } }); }; panel.Get <MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview; var titleLabel = panel.GetOrNull <LabelWithTooltipWidget>("MAP_TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(preview); titleLabel.GetTooltipText = () => preview.Title; } var typeLabel = panel.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => m.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(preview); } var authorLabel = panel.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform <MapPreview, string>( m => WidgetUtils.TruncateText("Created by {0}".F(m.Author), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(preview); } } var serverName = panel.Get <TextFieldWidget>("SERVER_NAME"); serverName.Text = Settings.SanitizedServerName(settings.Server.Name); serverName.OnEnterKey = () => { serverName.YieldKeyboardFocus(); return(true); }; serverName.OnLoseFocus = () => { serverName.Text = Settings.SanitizedServerName(serverName.Text); settings.Server.Name = serverName.Text; }; panel.Get <TextFieldWidget>("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); advertiseOnline = Game.Settings.Server.AdvertiseOnline; var advertiseCheckbox = panel.Get <CheckboxWidget>("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => { advertiseOnline ^= true; BuildNotices(); }; var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); if (passwordField != null) { passwordField.Text = Game.Settings.Server.Password; } noticesLabelA = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_A"); noticesLabelB = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_B"); noticesLabelC = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_C"); var noticesNoUPnP = panel.GetOrNull("NOTICES_NO_UPNP"); if (noticesNoUPnP != null) { noticesNoUPnP.IsVisible = () => advertiseOnline && (Nat.Status == NatStatus.NotSupported || Nat.Status == NatStatus.Disabled); var settingsA = noticesNoUPnP.GetOrNull("SETTINGS_A"); if (settingsA != null) { settingsA.IsVisible = () => Nat.Status == NatStatus.Disabled; } var settingsB = noticesNoUPnP.GetOrNull("SETTINGS_B"); if (settingsB != null) { settingsB.IsVisible = () => Nat.Status == NatStatus.Disabled; } } var noticesUPnP = panel.GetOrNull("NOTICES_UPNP"); if (noticesUPnP != null) { noticesUPnP.IsVisible = () => advertiseOnline && Nat.Status == NatStatus.Enabled; } var noticesLAN = panel.GetOrNull("NOTICES_LAN"); if (noticesLAN != null) { noticesLAN.IsVisible = () => !advertiseOnline; } BuildNotices(); }
public ConnectionSwitchModLogic(Widget widget, OrderManager orderManager, NetworkConnection connection, Action onAbort, Action <string> onRetry) { var panel = widget; var abortButton = panel.Get <ButtonWidget>("ABORT_BUTTON"); var switchButton = panel.Get <ButtonWidget>("SWITCH_BUTTON"); var mod = CurrentServerSettings.ServerExternalMod; var modTitle = mod.Title; var modVersion = mod.Version; switchButton.OnClick = () => { var launchCommand = $"Launch.URI={new UriBuilder("tcp", connection.EndPoint.Address.ToString(), connection.EndPoint.Port)}"; Game.SwitchToExternalMod(CurrentServerSettings.ServerExternalMod, new[] { launchCommand }, () => { orderManager.ServerError = "Failed to switch mod."; Ui.CloseWindow(); Ui.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() { { "orderManager", orderManager }, { "onAbort", onAbort }, { "onRetry", onRetry } }); }); }; abortButton.Visible = onAbort != null; abortButton.OnClick = () => { Ui.CloseWindow(); onAbort(); }; var width = 0; var title = panel.GetOrNull <LabelWidget>("MOD_TITLE"); if (title != null) { var font = Game.Renderer.Fonts[title.Font]; var label = WidgetUtils.TruncateText(modTitle, title.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, title.Bounds.X + labelWidth); title.Bounds.Width = labelWidth; title.GetText = () => label; } var version = panel.GetOrNull <LabelWidget>("MOD_VERSION"); if (version != null) { var font = Game.Renderer.Fonts[version.Font]; var label = WidgetUtils.TruncateText(modVersion, version.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, version.Bounds.X + labelWidth); version.Bounds.Width = labelWidth; version.GetText = () => label; } var logo = panel.GetOrNull <RGBASpriteWidget>("MOD_ICON"); if (logo != null) { logo.GetSprite = () => { var ws = Game.Renderer.WindowScale; if (ws > 2 && mod.Icon3x != null) { return(mod.Icon3x); } if (ws > 1 && mod.Icon2x != null) { return(mod.Icon2x); } return(mod.Icon); }; if (mod.Icon == null) { // Hide the logo and center just the text if (title != null) { title.Bounds.X = logo.Bounds.X; } if (version != null) { version.Bounds.X = logo.Bounds.X; } width -= logo.Bounds.Width; } else { // Add an equal logo margin on the right of the text width += logo.Bounds.Width; } } var container = panel.GetOrNull("MOD_CONTAINER"); if (container != null) { container.Bounds.X += (container.Bounds.Width - width) / 2; container.Bounds.Width = width; } }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager) { var player = world.RenderPlayer ?? world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => new Pair <Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); teamRating.GetText = () => t.Sum(gg => gg.Second != null ? gg.Second.Experience : 0).ToString(); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.First; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Session.ClientState.Disconnected) { suffix = " (Gone)"; } var sl = suffixLength.Update(suffix); return(name.Update(Pair.New(pp.PlayerName, sl)) + suffix); }; nameLabel.GetColor = () => pp.Color.RGB; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.Stances[pp] == Stance.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var experience = p.Second != null ? p.Second.Experience : 0; item.Get <LabelWidget>("SCORE").GetText = () => experience.ToString(); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; var sl = suffixLength.Update(suffix); return(name.Update(Pair.New(client.Name, sl)) + suffix); }; item.Get <ImageWidget>("FACTIONFLAG").IsVisible = () => false; playerPanel.AddChild(item); } } }
void LoadBrowserPanel(Widget widget) { var browserPanel = Game.LoadWidget(null, "MULTIPLAYER_BROWSER_PANEL", widget.Get("TOP_PANELS_ROOT"), new WidgetArgs()); browserPanel.IsVisible = () => panel == PanelType.Browser; serverList = browserPanel.Get <ScrollPanelWidget>("SERVER_LIST"); headerTemplate = serverList.Get <ScrollItemWidget>("HEADER_TEMPLATE"); serverTemplate = serverList.Get <ScrollItemWidget>("SERVER_TEMPLATE"); var join = widget.Get <ButtonWidget>("JOIN_BUTTON"); join.IsDisabled = () => currentServer == null || !currentServer.IsJoinable; join.OnClick = () => Join(currentServer); // Display the progress label over the server list // The text is only visible when the list is empty var progressText = widget.Get <LabelWidget>("PROGRESS_LABEL"); progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; progressText.GetText = ProgressLabelText; var gs = Game.Settings.Game; Action <MPGameFilters> toggleFilterFlag = f => { gs.MPGameFilters ^= f; Game.Settings.Save(); RefreshServerList(); }; var filtersPanel = Ui.LoadWidget("MULTIPLAYER_FILTER_PANEL", null, new WidgetArgs()); var showWaitingCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("WAITING_FOR_PLAYERS"); if (showWaitingCheckbox != null) { showWaitingCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Waiting); showWaitingCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Waiting); } var showEmptyCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("EMPTY"); if (showEmptyCheckbox != null) { showEmptyCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Empty); showEmptyCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Empty); } var showAlreadyStartedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("ALREADY_STARTED"); if (showAlreadyStartedCheckbox != null) { showAlreadyStartedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Started); showAlreadyStartedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Started); } var showProtectedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("PASSWORD_PROTECTED"); if (showProtectedCheckbox != null) { showProtectedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Protected); showProtectedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Protected); } var showIncompatibleCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("INCOMPATIBLE_VERSION"); if (showIncompatibleCheckbox != null) { showIncompatibleCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Incompatible); showIncompatibleCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Incompatible); } var filtersButton = widget.GetOrNull <DropDownButtonWidget>("FILTERS_DROPDOWNBUTTON"); if (filtersButton != null) { filtersButton.OnMouseDown = _ => { filtersButton.RemovePanel(); filtersButton.AttachPanel(filtersPanel); }; } var refreshButton = widget.Get <ButtonWidget>("REFRESH_BUTTON"); refreshButton.GetText = () => searchStatus == SearchStatus.Fetching ? "Refreshing..." : "Refresh"; refreshButton.OnClick = RefreshServerList; var mapPreview = widget.GetOrNull <MapPreviewWidget>("SELECTED_MAP_PREVIEW"); if (mapPreview != null) { mapPreview.Preview = () => currentMap; } var mapTitle = widget.GetOrNull <LabelWidget>("SELECTED_MAP"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform <MapPreview, string>(m => m == null ? "No Server Selected" : WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(currentMap); } var ip = widget.GetOrNull <LabelWidget>("SELECTED_IP"); if (ip != null) { ip.IsVisible = () => currentServer != null; ip.GetText = () => currentServer.Address; } var status = widget.GetOrNull <LabelWidget>("SELECTED_STATUS"); if (status != null) { status.IsVisible = () => currentServer != null; status.GetText = () => GetStateLabel(currentServer); status.GetColor = () => GetStateColor(currentServer, status); } var modVersion = widget.GetOrNull <LabelWidget>("SELECTED_MOD_VERSION"); if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; var font = Game.Renderer.Fonts[modVersion.Font]; var version = new CachedTransform <GameServer, string>(s => WidgetUtils.TruncateText(s.ModLabel, mapTitle.Bounds.Width, font)); modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull <LabelWidget>("SELECTED_PLAYERS"); if (players != null) { players.IsVisible = () => currentServer != null; players.GetText = () => PlayersLabel(currentServer); } }
static void AddPlayerFlagAndName(ScrollItemWidget template, Player player) { var flag = template.Get <ImageWidget>("FLAG"); flag.GetImageCollection = () => "flags"; flag.GetImageName = () => player.Faction.InternalName; var client = player.World.LobbyInfo.ClientWithIndex(player.ClientIndex); var playerName = template.Get <LabelWidget>("PLAYER"); var playerNameFont = Game.Renderer.Fonts[playerName.Font]; var suffixLength = new CachedTransform <string, int>(s => playerNameFont.Measure(s).X); var name = new CachedTransform <(string Name, int Width), string>(c => WidgetUtils.TruncateText(c.Name, playerName.Bounds.Width - c.Width, playerNameFont)); playerName.GetText = () => { var suffix = player.WinState == WinState.Undefined ? "" : " (" + player.WinState + ")"; if (client != null && client.State == Session.ClientState.Disconnected) { suffix = " (Gone)"; } var sl = suffixLength.Update(suffix); return(name.Update((player.PlayerName, sl)) + suffix); }; playerName.GetColor = () => player.Color; }