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;
        }
예제 #2
0
        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");
        }
예제 #3
0
        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);
        }
예제 #4
0
        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");
        }
예제 #5
0
        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;
        }
예제 #6
0
        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());
            }
        }
예제 #7
0
        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();
        }
예제 #8
0
        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;
            }
        }
예제 #9
0
        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);
                }
            }
        }
예제 #10
0
        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();
                }
            }
        }
예제 #11
0
        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();
                }
            });
        }
예제 #12
0
        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);
            }
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        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);
                }
            }
        }
예제 #16
0
        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();
                }
            });
        }
예제 #17
0
        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;
            }
        }
예제 #18
0
        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();
            }
        }
예제 #19
0
        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;
            }
        }
예제 #20
0
        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();
        }
예제 #21
0
        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;
            });
        }
예제 #22
0
        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);
                }
            }
        }
예제 #23
0
        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);
        }
예제 #24
0
        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;
            }
        }
예제 #25
0
        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();
        }
예제 #26
0
        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();
        }
예제 #27
0
        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;
            }
        }
예제 #28
0
        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);
                }
            }
        }
예제 #29
0
        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;
        }