ScrollItemWidget CombatStats(Player player)
        {
            combatStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var playerName = template.Get <LabelWidget>("PLAYER");

            playerName.GetColor = () => Color.White;

            var playerColor    = template.Get <ColorBlockWidget>("PLAYER_COLOR");
            var playerGradient = template.Get <GradientColorBlockWidget>("PLAYER_GRADIENT");

            SetupPlayerColor(player, template, playerColor, playerGradient);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("UNITS_KILLED").GetText     = () => stats.UnitsKilled.ToString();
            template.Get <LabelWidget>("UNITS_DEAD").GetText       = () => stats.UnitsDead.ToString();
            template.Get <LabelWidget>("BUILDINGS_KILLED").GetText = () => stats.BuildingsKilled.ToString();
            template.Get <LabelWidget>("BUILDINGS_DEAD").GetText   = () => stats.BuildingsDead.ToString();
            template.Get <LabelWidget>("ARMY_VALUE").GetText       = () => "$" + stats.ArmyValue.ToString();

            return(template);
        }
        ScrollItemWidget BasicStats(Player player)
        {
            basicStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(basicPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res = player.PlayerActor.Trait <PlayerResources>();

            template.Get <LabelWidget>("CASH").GetText       = () => "$" + (res.Cash + res.Resources);
            template.Get <LabelWidget>("EARNED_MIN").GetText = () => AverageEarnedPerMinute(res.Earned);

            var powerRes = player.PlayerActor.Trait <PowerManager>();
            var power    = template.Get <LabelWidget>("POWER");

            power.GetText  = () => powerRes.PowerDrained + "/" + powerRes.PowerProvided;
            power.GetColor = () => GetPowerColor(powerRes.PowerState);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS").GetText            = () => (stats.UnitsKilled + stats.BuildingsKilled).ToString();
            template.Get <LabelWidget>("DEATHS").GetText           = () => (stats.UnitsDead + stats.BuildingsDead).ToString();
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("EXPERIENCE").GetText       = () => stats.Experience.ToString();
            template.Get <LabelWidget>("ACTIONS_MIN").GetText      = () => AverageOrdersPerMinute(stats.OrderCount);

            return(template);
        }
Example #3
0
        public AnonymousProfileTooltipLogic(Widget widget, OrderManager orderManager, Session.Client client)
        {
            var address             = LobbyUtils.GetExternalIP(client, orderManager);
            var cachedDescriptiveIP = address ?? "Unknown IP";

            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 ipLabel = widget.Get <LabelWidget>("IP");

            ipLabel.GetText = () => cachedDescriptiveIP;

            var locationLabel       = widget.Get <LabelWidget>("LOCATION");
            var cachedCountryLookup = GeoIP.LookupCountry(address);

            locationLabel.GetText = () => cachedCountryLookup;

            if (client.IsAdmin)
            {
                var adminLabel = widget.Get("GAME_ADMIN");
                adminLabel.IsVisible  = () => client.IsAdmin;
                widget.Bounds.Height += adminLabel.Bounds.Height;
            }
        }
        ScrollItemWidget EconomyStats(Player player)
        {
            economyStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(economyPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res   = player.PlayerActor.Trait <PlayerResources>();
            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }

            template.Get <LabelWidget>("CASH").GetText            = () => "$" + (res.Cash + res.Resources);
            template.Get <LabelWidget>("EARNED_MIN").GetText      = () => AverageEarnedPerMinute(res.Earned);
            template.Get <LabelWidget>("EARNED_THIS_MIN").GetText = () => "$" + stats.EarnedThisMinute;
            template.Get <LabelWidget>("EARNED").GetText          = () => "$" + res.Earned;
            template.Get <LabelWidget>("SPENT").GetText           = () => "$" + res.Spent;

            var assets = template.Get <LabelWidget>("ASSETS");

            assets.GetText = () => "$" + world.ActorsHavingTrait <Valued>()
                             .Where(a => a.Owner == player && !a.IsDead)
                             .Sum(a => a.Info.TraitInfos <ValuedInfo>().First().Cost);

            var harvesters = template.Get <LabelWidget>("HARVESTERS");

            harvesters.GetText = () => world.ActorsHavingTrait <Harvester>().Count(a => a.Owner == player && !a.IsDead).ToString();

            return(template);
        }
Example #5
0
        Widget MakeHistoryWidget(object o)
        {
            var message = (ChatMessage)o;
            var from    = message.Type == ChatMessageType.Notification ? "Battlefield Control" : message.Nick;
            var color   = message.Type == ChatMessageType.Notification ? ChromeMetrics.Get <Color>("GlobalChatNotificationColor")
                                : ChromeMetrics.Get <Color>("GlobalChatPlayerNameColor");
            var template = (ContainerWidget)chatTemplate.Clone();

            LobbyUtils.SetupChatLine(template, color, message.Time, from, message.Message);

            template.Id = message.UID;
            return(template);
        }
        ScrollItemWidget ProductionStats(Player player)
        {
            productionStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(productionPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            template.Get <ObserverProductionIconsWidget>("PRODUCTION_ICONS").GetPlayer      = () => player;
            template.Get <ObserverSupportPowerIconsWidget>("SUPPORT_POWER_ICONS").GetPlayer = () => player;
            template.IgnoreChildMouseOver = false;

            return(template);
        }
Example #7
0
        void AddChatLine(string name, Color nameColor, string text, Color textColor)
        {
            var template = (ContainerWidget)chatTemplate.Clone();

            LobbyUtils.SetupChatLine(template, DateTime.Now, name, nameColor, text, textColor);

            var scrolledToBottom = lobbyChatPanel.ScrolledToBottom;

            lobbyChatPanel.AddChild(template);
            if (scrolledToBottom)
            {
                lobbyChatPanel.ScrollToBottom(smooth: true);
            }

            Game.Sound.PlayNotification(modRules, null, "Sounds", chatLineSound, null);
        }
        void AddChatLine(Color c, string from, string text)
        {
            var template = (ContainerWidget)chatTemplate.Clone();

            LobbyUtils.SetupChatLine(template, c, DateTime.Now, from, text);

            var scrolledToBottom = lobbyChatPanel.ScrolledToBottom;

            lobbyChatPanel.AddChild(template);
            if (scrolledToBottom)
            {
                lobbyChatPanel.ScrollToBottom(smooth: true);
            }

            Game.Sound.PlayNotification(modRules, null, "Sounds", "ChatLine", null);
        }
        ScrollItemWidget ProductionStats(Player player)
        {
            productionStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(productionPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var playerName = template.Get <LabelWidget>("PLAYER");

            playerName.GetColor = () => Color.White;

            var playerColor    = template.Get <ColorBlockWidget>("PLAYER_COLOR");
            var playerGradient = template.Get <GradientColorBlockWidget>("PLAYER_GRADIENT");

            SetupPlayerColor(player, template, playerColor, playerGradient);

            template.Get <ObserverProductionIconsWidget>("PRODUCTION_ICONS").GetPlayer = () => player;
            template.IgnoreChildMouseOver = false;

            return(template);
        }
        ScrollItemWidget SupportPowerStats(Player player)
        {
            supportPowerStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(supportPowersPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var playerName = template.Get <LabelWidget>("PLAYER");

            playerName.GetColor = () => Color.White;

            var playerColor    = template.Get <ColorBlockWidget>("PLAYER_COLOR");
            var playerGradient = template.Get <GradientColorBlockWidget>("PLAYER_GRADIENT");

            SetupPlayerColor(player, template, playerColor, playerGradient);

            template.Get <ObserverSupportPowerIconsWidget>("SUPPORT_POWER_ICONS").GetPlayer = () => player;
            template.IgnoreChildMouseOver = false;

            return(template);
        }
Example #11
0
        public LatencyTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, OrderManager orderManager, Session.Client client)
        {
            var latencyPrefix     = widget.Get <LabelWidget>("LATENCY_PREFIX");
            var latencyPrefixFont = Game.Renderer.Fonts[latencyPrefix.Font];
            var latency           = widget.Get <LabelWidget>("LATENCY");
            var latencyFont       = Game.Renderer.Fonts[latency.Font];
            var rightMargin       = widget.Bounds.Width;

            latency.Bounds.X = latencyPrefix.Bounds.X + latencyPrefixFont.Measure(latencyPrefix.Text + " ").X;

            widget.IsVisible = () => client != null;
            tooltipContainer.BeforeRender = () =>
            {
                if (widget.IsVisible())
                {
                    widget.Bounds.Width = latency.Bounds.X + latencyFont.Measure(latency.GetText()).X + rightMargin;
                }
            };

            latency.GetText  = () => LobbyUtils.LatencyDescription(client);
            latency.GetColor = () => LobbyUtils.LatencyColor(client);
        }
        ScrollItemWidget CombatStats(Player player)
        {
            combatStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("UNITS_KILLED").GetText     = () => stats.UnitsKilled.ToString();
            template.Get <LabelWidget>("UNITS_DEAD").GetText       = () => stats.UnitsDead.ToString();
            template.Get <LabelWidget>("BUILDINGS_KILLED").GetText = () => stats.BuildingsKilled.ToString();
            template.Get <LabelWidget>("BUILDINGS_DEAD").GetText   = () => stats.BuildingsDead.ToString();

            return(template);
        }
Example #13
0
        public ClientTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, OrderManager orderManager, int clientIndex)
        {
            var admin     = widget.Get <LabelWidget>("ADMIN");
            var adminFont = Game.Renderer.Fonts[admin.Font];

            var latency = widget.GetOrNull <LabelWidget>("LATENCY");

            if (latency != null)
            {
                latencyFont = Game.Renderer.Fonts[latency.Font];
            }

            var latencyPrefix = widget.GetOrNull <LabelWidget>("LATENCY_PREFIX");

            if (latencyPrefix != null)
            {
                latencyPrefixFont = Game.Renderer.Fonts[latencyPrefix.Font];
            }

            var ip          = widget.Get <LabelWidget>("IP");
            var addressFont = Game.Renderer.Fonts[ip.Font];

            var location     = widget.Get <LabelWidget>("LOCATION");
            var locationFont = Game.Renderer.Fonts[location.Font];

            var locationOffset = location.Bounds.Y;
            var addressOffset  = ip.Bounds.Y;
            var latencyOffset  = latency == null ? 0 : latency.Bounds.Y;
            var tooltipHeight  = widget.Bounds.Height;

            var margin = widget.Bounds.Width;

            widget.IsVisible = () => (orderManager.LobbyInfo.ClientWithIndex(clientIndex) != null);
            tooltipContainer.BeforeRender = () =>
            {
                if (!widget.IsVisible())
                {
                    return;
                }

                var latencyPrefixSize = latencyPrefix == null ? 0 : latencyPrefix.Bounds.X + latencyPrefixFont.Measure(latencyPrefix.GetText() + " ").X;
                var locationWidth     = locationFont.Measure(location.GetText()).X;
                var adminWidth        = adminFont.Measure(admin.GetText()).X;
                var addressWidth      = addressFont.Measure(ip.GetText()).X;
                var latencyWidth      = latencyFont == null ? 0 : latencyPrefixSize + latencyFont.Measure(latency.GetText()).X;
                var width             = Math.Max(locationWidth, Math.Max(adminWidth, Math.Max(addressWidth, latencyWidth)));
                widget.Bounds.Width = width + 2 * margin;
                if (latency != null)
                {
                    latency.Bounds.Width = widget.Bounds.Width;
                }
                ip.Bounds.Width       = widget.Bounds.Width;
                admin.Bounds.Width    = widget.Bounds.Width;
                location.Bounds.Width = widget.Bounds.Width;

                ip.Bounds.Y = addressOffset;
                if (latency != null)
                {
                    latency.Bounds.Y = latencyOffset;
                }
                location.Bounds.Y    = locationOffset;
                widget.Bounds.Height = tooltipHeight;

                if (admin.IsVisible())
                {
                    ip.Bounds.Y += admin.Bounds.Height;
                    if (latency != null)
                    {
                        latency.Bounds.Y += admin.Bounds.Height;
                    }
                    location.Bounds.Y    += admin.Bounds.Height;
                    widget.Bounds.Height += admin.Bounds.Height;
                }

                if (latencyPrefix != null)
                {
                    latencyPrefix.Bounds.Y = latency.Bounds.Y;
                }
                if (latency != null)
                {
                    latency.Bounds.X = latencyPrefixSize;
                }
            };

            admin.IsVisible = () => orderManager.LobbyInfo.ClientWithIndex(clientIndex).IsAdmin;
            var client = orderManager.LobbyInfo.ClientWithIndex(clientIndex);
            var ping   = orderManager.LobbyInfo.PingFromClient(client);

            if (latency != null)
            {
                latency.GetText  = () => LobbyUtils.LatencyDescription(ping);
                latency.GetColor = () => LobbyUtils.LatencyColor(ping);
            }

            var address             = LobbyUtils.GetExternalIP(clientIndex, orderManager);
            var cachedDescriptiveIP = LobbyUtils.DescriptiveIpAddress(address);

            ip.GetText = () => cachedDescriptiveIP;
            var cachedCountryLookup = GeoIP.LookupCountry(address);

            location.GetText = () => cachedCountryLookup;
        }
Example #14
0
        public DiplomacyLogic(Widget widget, Action onExit, World world)
        {
            this.world = world;

            diplomacyPanel = widget.Get <ScrollPanelWidget>("DIPLOMACY_PANEL");

            LayoutPlayers();

            var close = widget.GetOrNull <ButtonWidget>("CLOSE");

            if (close != null)
            {
                close.OnClick = () =>
                {
                    Ui.CloseWindow();
                    Ui.Root.RemoveChild(widget);
                    onExit();
                }
            }
            ;
        }

        void LayoutPlayers()
        {
            var teamTemplate = diplomacyPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE");
            var players      = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant);
            var teams        = players.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.ClientIndex) ?? new Session.Client()).Team).OrderBy(g => g.Key);

            foreach (var t in teams)
            {
                var team = t;
                var tt   = ScrollItemWidget.Setup(teamTemplate, () => false, () => { });
                tt.IgnoreMouseOver = true;
                tt.Get <LabelWidget>("TEAM").GetText = () => team.Key == 0 ? "No Team" : "Team " + team.Key;
                diplomacyPanel.AddChild(tt);
                foreach (var p in team)
                {
                    var player = p;
                    diplomacyPanel.AddChild(DiplomaticStatus(player));
                }
            }
        }

        ScrollItemWidget DiplomaticStatus(Player player)
        {
            var playerTemplate = diplomacyPanel.Get <ScrollItemWidget>("PLAYER_TEMPLATE");
            var pt             = ScrollItemWidget.Setup(playerTemplate, () => false, () => { });

            pt.IgnoreMouseOver = true;
            LobbyUtils.AddPlayerFlagAndName(pt, player);
            pt.Get <LabelWidget>("THEIR_STANCE").GetText = () => player.Stances[world.LocalPlayer].ToString();
            var myStance = pt.Get <DropDownButtonWidget>("MY_STANCE");

            myStance.GetText     = () => world.LocalPlayer.Stances[player].ToString();
            myStance.IsDisabled  = () => !world.LobbyInfo.GlobalSettings.FragileAlliances;
            myStance.OnMouseDown = mi => ShowDropDown(player, myStance);
            return(pt);
        }

        void ShowDropDown(Player p, DropDownButtonWidget dropdown)
        {
            var stances = Enum <Stance> .GetValues();

            Func <Stance, ScrollItemWidget, ScrollItemWidget> setupItem = (s, template) =>
            {
                var item = ScrollItemWidget.Setup(template,
                                                  () => s == world.LocalPlayer.Stances[p],
                                                  () => SetStance(dropdown, p, s));

                item.Get <LabelWidget>("LABEL").GetText = () => s.ToString();
                return(item);
            };

            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, stances, setupItem);
        }

        void SetStance(ButtonWidget bw, Player p, Stance ss)
        {
            if (!p.World.LobbyInfo.GlobalSettings.FragileAlliances)
            {
                return;                 // stance changes are banned
            }
            world.IssueOrder(new Order("SetStance", world.LocalPlayer.PlayerActor, false)
            {
                ExtraData    = (uint)ss,
                TargetString = p.InternalName,
            });

            bw.Text = ss.ToString();
        }
    }
Example #15
0
        public ObserverStatsLogic(World world, WorldRenderer worldRenderer, Widget widget, Action onExit)
        {
            this.world         = world;
            this.worldRenderer = worldRenderer;
            players            = world.Players.Where(p => !p.NonCombatant);

            basicStatsHeaders            = widget.Get <ContainerWidget>("BASIC_STATS_HEADERS");
            economyStatsHeaders          = widget.Get <ContainerWidget>("ECONOMY_STATS_HEADERS");
            productionStatsHeaders       = widget.Get <ContainerWidget>("PRODUCTION_STATS_HEADERS");
            combatStatsHeaders           = widget.Get <ContainerWidget>("COMBAT_STATS_HEADERS");
            earnedThisMinuteGraphHeaders = widget.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_HEADERS");

            playerStatsPanel        = widget.Get <ScrollPanelWidget>("PLAYER_STATS_PANEL");
            playerStatsPanel.Layout = new GridLayout(playerStatsPanel);

            basicPlayerTemplate           = playerStatsPanel.Get <ScrollItemWidget>("BASIC_PLAYER_TEMPLATE");
            economyPlayerTemplate         = playerStatsPanel.Get <ScrollItemWidget>("ECONOMY_PLAYER_TEMPLATE");
            productionPlayerTemplate      = playerStatsPanel.Get <ScrollItemWidget>("PRODUCTION_PLAYER_TEMPLATE");
            combatPlayerTemplate          = playerStatsPanel.Get <ScrollItemWidget>("COMBAT_PLAYER_TEMPLATE");
            earnedThisMinuteGraphTemplate = playerStatsPanel.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_TEMPLATE");

            teamTemplate = playerStatsPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE");

            statsDropDown             = widget.Get <DropDownButtonWidget>("STATS_DROPDOWN");
            statsDropDown.GetText     = () => "Basic";
            statsDropDown.OnMouseDown = _ =>
            {
                var options = new List <StatsDropDownOption>
                {
                    new StatsDropDownOption
                    {
                        Title      = "Basic",
                        IsSelected = () => basicStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Basic";
                            DisplayStats(BasicStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Economy",
                        IsSelected = () => economyStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Economy";
                            DisplayStats(EconomyStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Production",
                        IsSelected = () => productionStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Production";
                            DisplayStats(ProductionStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Combat",
                        IsSelected = () => combatStatsHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Combat";
                            DisplayStats(CombatStats);
                        }
                    },
                    new StatsDropDownOption
                    {
                        Title      = "Earnings (graph)",
                        IsSelected = () => earnedThisMinuteGraphHeaders.Visible,
                        OnClick    = () =>
                        {
                            ClearStats();
                            statsDropDown.GetText = () => "Earnings (graph)";
                            EarnedThisMinuteGraph();
                        }
                    }
                };
                Func <StatsDropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                {
                    var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
                    item.Get <LabelWidget>("LABEL").GetText = () => option.Title;
                    return(item);
                };
                statsDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, options, setupItem);
            };

            ClearStats();
            DisplayStats(BasicStats);

            var close = widget.GetOrNull <ButtonWidget>("CLOSE");

            if (close != null)
            {
                close.OnClick = () =>
                {
                    Ui.CloseWindow();
                    Ui.Root.RemoveChild(widget);
                    onExit();
                }
            }
            ;
        }

        void ClearStats()
        {
            playerStatsPanel.Children.Clear();
            basicStatsHeaders.Visible            = false;
            economyStatsHeaders.Visible          = false;
            productionStatsHeaders.Visible       = false;
            combatStatsHeaders.Visible           = false;
            earnedThisMinuteGraphHeaders.Visible = false;
        }

        void EarnedThisMinuteGraph()
        {
            earnedThisMinuteGraphHeaders.Visible = true;
            var template = earnedThisMinuteGraphTemplate.Clone();

            var graph = template.Get <LineGraphWidget>("EARNED_THIS_MIN_GRAPH");

            graph.GetSeries = () =>
                              players.Select(p => new LineGraphSeries(
                                                 p.PlayerName,
                                                 p.Color.RGB,
                                                 (p.PlayerActor.TraitOrDefault <PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).EarnedSamples.Select(s => (float)s)));

            playerStatsPanel.AddChild(template);
        }

        void DisplayStats(Func <Player, ScrollItemWidget> createItem)
        {
            var teams = players.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.ClientIndex) ?? new Session.Client()).Team).OrderBy(g => g.Key);

            foreach (var t in teams)
            {
                var team = t;
                var tt   = ScrollItemWidget.Setup(teamTemplate, () => false, () => { });
                tt.IgnoreMouseOver = true;
                tt.Get <LabelWidget>("TEAM").GetText = () => team.Key == 0 ? "No Team" : "Team " + team.Key;
                playerStatsPanel.AddChild(tt);
                foreach (var p in team)
                {
                    var player = p;
                    playerStatsPanel.AddChild(createItem(player));
                }
            }
        }

        ScrollItemWidget CombatStats(Player player)
        {
            combatStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS_COST").GetText       = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("DEATHS_COST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("UNITS_KILLED").GetText     = () => stats.UnitsKilled.ToString();
            template.Get <LabelWidget>("UNITS_DEAD").GetText       = () => stats.UnitsDead.ToString();
            template.Get <LabelWidget>("BUILDINGS_KILLED").GetText = () => stats.BuildingsKilled.ToString();
            template.Get <LabelWidget>("BUILDINGS_DEAD").GetText   = () => stats.BuildingsDead.ToString();

            return(template);
        }

        ScrollItemWidget ProductionStats(Player player)
        {
            productionStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(productionPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            template.Get <ObserverProductionIconsWidget>("PRODUCTION_ICONS").GetPlayer      = () => player;
            template.Get <ObserverSupportPowerIconsWidget>("SUPPORT_POWER_ICONS").GetPlayer = () => player;

            return(template);
        }

        ScrollItemWidget EconomyStats(Player player)
        {
            economyStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(economyPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res   = player.PlayerActor.Trait <PlayerResources>();
            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }

            template.Get <LabelWidget>("CASH").GetText            = () => "$" + (res.DisplayCash + res.DisplayResources);
            template.Get <LabelWidget>("EARNED_MIN").GetText      = () => AverageEarnedPerMinute(res.Earned);
            template.Get <LabelWidget>("EARNED_THIS_MIN").GetText = () => "$" + stats.EarnedThisMinute;
            template.Get <LabelWidget>("EARNED").GetText          = () => "$" + res.Earned;
            template.Get <LabelWidget>("SPENT").GetText           = () => "$" + res.Spent;

            var assets = template.Get <LabelWidget>("ASSETS");

            assets.GetText = () => "$" + world.Actors
                             .Where(a => a.Owner == player && !a.IsDead && a.Info.HasTraitInfo <ValuedInfo>())
                             .Sum(a => a.Info.TraitInfos <ValuedInfo>().First().Cost);

            var harvesters = template.Get <LabelWidget>("HARVESTERS");

            harvesters.GetText = () => world.Actors.Count(a => a.Owner == player && !a.IsDead && a.Info.HasTraitInfo <HarvesterInfo>()).ToString();

            return(template);
        }

        ScrollItemWidget BasicStats(Player player)
        {
            basicStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(basicPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res = player.PlayerActor.Trait <PlayerResources>();

            template.Get <LabelWidget>("CASH").GetText       = () => "$" + (res.DisplayCash + res.DisplayResources);
            template.Get <LabelWidget>("EARNED_MIN").GetText = () => AverageEarnedPerMinute(res.Earned);

            var powerRes = player.PlayerActor.Trait <PowerManager>();
            var power    = template.Get <LabelWidget>("POWER");

            power.GetText  = () => powerRes.PowerDrained + "/" + powerRes.PowerProvided;
            power.GetColor = () => GetPowerColor(powerRes.PowerState);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS").GetText       = () => (stats.UnitsKilled + stats.BuildingsKilled).ToString();
            template.Get <LabelWidget>("DEATHS").GetText      = () => (stats.UnitsDead + stats.BuildingsDead).ToString();
            template.Get <LabelWidget>("KD_RATIO").GetText    = () => KillDeathRatio(stats.UnitsKilled + stats.BuildingsKilled, stats.UnitsDead + stats.BuildingsDead);
            template.Get <LabelWidget>("ACTIONS_MIN").GetText = () => AverageOrdersPerMinute(stats.OrderCount);

            return(template);
        }

        ScrollItemWidget SetupPlayerScrollItemWidget(ScrollItemWidget template, Player player)
        {
            return(ScrollItemWidget.Setup(template, () => false, () =>
            {
                var playerBase = world.Actors.FirstOrDefault(a => !a.IsDead && a.Info.HasTraitInfo <BaseBuildingInfo>() && a.Owner == player);
                if (playerBase != null)
                {
                    worldRenderer.Viewport.Center(playerBase.CenterPosition);
                }
            }));
        }
Example #16
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());

            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 compatible = game.IsCompatible;

                    var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => currentServer = game, () => Join(game));

                    var map     = Game.ModData.MapCache[game.Map];
                    var preview = item.GetOrNull <MapPreviewWidget>("MAP_PREVIEW");
                    if (preview != null)
                    {
                        preview.Preview = () => map;
                    }

                    var title = item.GetOrNull <LabelWidget>("TITLE");
                    if (title != null)
                    {
                        title.GetText  = () => game.Name;
                        title.GetColor = () => !compatible ? Color.DarkGray : !canJoin ? Color.LightGray : title.TextColor;
                    }

                    var maptitle = item.GetOrNull <LabelWidget>("MAP");
                    if (title != null)
                    {
                        maptitle.GetText  = () => map.Title;
                        maptitle.GetColor = () => !compatible ? Color.DarkGray : !canJoin ? Color.LightGray : maptitle.TextColor;
                    }

                    var players = item.GetOrNull <LabelWidget>("PLAYERS");
                    if (players != null)
                    {
                        players.GetText = () => "{0} / {1}".F(game.Players, game.MaxPlayers)
                                          + (game.Spectators > 0 ? "  ({0} Spectator{1})".F(game.Spectators, game.Spectators > 1 ? "s" : "") : "");
                        players.GetColor = () => !compatible ? Color.DarkGray : !canJoin ? Color.LightGray : players.TextColor;
                    }

                    var state = item.GetOrNull <LabelWidget>("STATE");
                    if (state != null)
                    {
                        state.GetText  = () => GetStateLabel(game);
                        state.GetColor = () => GetStateColor(game, state, !compatible || !canJoin);
                    }

                    var ip = item.GetOrNull <LabelWidget>("IP");
                    if (ip != null)
                    {
                        ip.GetText  = () => game.Address;
                        ip.GetColor = () => !compatible ? Color.DarkGray : !canJoin ? Color.LightGray : ip.TextColor;
                    }

                    var location = item.GetOrNull <LabelWidget>("LOCATION");
                    if (location != null)
                    {
                        var cachedServerLocation = LobbyUtils.LookupCountry(game.Address.Split(':')[0]);
                        location.GetText  = () => cachedServerLocation;
                        location.GetColor = () => !compatible ? Color.DarkGray : !canJoin ? Color.LightGray : location.TextColor;
                    }

                    rows.Add(item);
                }
            }

            Game.RunAfterTick(() =>
            {
                serverList.RemoveChildren();
                currentServer = null;

                if (games == null)
                {
                    searchStatus = SearchStatus.Failed;
                    return;
                }

                if (!games.Any())
                {
                    searchStatus = SearchStatus.NoGames;
                    return;
                }

                currentServer = games.FirstOrDefault();
                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);
                }
            });
        }
Example #17
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();
                }
            }
        }
Example #18
0
        public ObserverStatsLogic(World world, ModData modData, WorldRenderer worldRenderer, Widget widget,
                                  Action onExit, ObserverStatsPanel activePanel, Dictionary <string, MiniYaml> logicArgs)
        {
            this.world         = world;
            this.worldRenderer = worldRenderer;

            MiniYaml yaml;

            string[] keyNames     = Enum.GetNames(typeof(ObserverStatsPanel));
            var      statsHotkeys = new HotkeyReference[keyNames.Length];

            for (var i = 0; i < keyNames.Length; i++)
            {
                statsHotkeys[i] = logicArgs.TryGetValue("Statistics" + keyNames[i] + "Key", out yaml) ? modData.Hotkeys[yaml.Value] : new HotkeyReference();
            }

            players = world.Players.Where(p => !p.NonCombatant);

            basicStatsHeaders            = widget.Get <ContainerWidget>("BASIC_STATS_HEADERS");
            economyStatsHeaders          = widget.Get <ContainerWidget>("ECONOMY_STATS_HEADERS");
            productionStatsHeaders       = widget.Get <ContainerWidget>("PRODUCTION_STATS_HEADERS");
            combatStatsHeaders           = widget.Get <ContainerWidget>("COMBAT_STATS_HEADERS");
            earnedThisMinuteGraphHeaders = widget.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_HEADERS");

            playerStatsPanel        = widget.Get <ScrollPanelWidget>("PLAYER_STATS_PANEL");
            playerStatsPanel.Layout = new GridLayout(playerStatsPanel);

            basicPlayerTemplate           = playerStatsPanel.Get <ScrollItemWidget>("BASIC_PLAYER_TEMPLATE");
            economyPlayerTemplate         = playerStatsPanel.Get <ScrollItemWidget>("ECONOMY_PLAYER_TEMPLATE");
            productionPlayerTemplate      = playerStatsPanel.Get <ScrollItemWidget>("PRODUCTION_PLAYER_TEMPLATE");
            combatPlayerTemplate          = playerStatsPanel.Get <ScrollItemWidget>("COMBAT_PLAYER_TEMPLATE");
            earnedThisMinuteGraphTemplate = playerStatsPanel.Get <ContainerWidget>("EARNED_THIS_MIN_GRAPH_TEMPLATE");

            teamTemplate = playerStatsPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE");

            var statsDropDown = widget.Get <DropDownButtonWidget>("STATS_DROPDOWN");
            Func <string, ContainerWidget, Action, StatsDropDownOption> createStatsOption = (title, headers, a) =>
            {
                return(new StatsDropDownOption
                {
                    Title = title,
                    IsSelected = () => headers.Visible,
                    OnClick = () =>
                    {
                        ClearStats();
                        statsDropDown.GetText = () => title;
                        a();
                    }
                });
            };

            var statsDropDownOptions = new StatsDropDownOption[]
            {
                createStatsOption("Basic", basicStatsHeaders, () => DisplayStats(BasicStats)),
                createStatsOption("Economy", economyStatsHeaders, () => DisplayStats(EconomyStats)),
                createStatsOption("Production", productionStatsHeaders, () => DisplayStats(ProductionStats)),
                createStatsOption("Combat", combatStatsHeaders, () => DisplayStats(CombatStats)),
                createStatsOption("Earnings (graph)", earnedThisMinuteGraphHeaders, () => EarnedThisMinuteGraph())
            };

            Func <StatsDropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
            {
                var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
                item.Get <LabelWidget>("LABEL").GetText = () => option.Title;
                return(item);
            };

            statsDropDown.OnMouseDown = _ => statsDropDown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, statsDropDownOptions, setupItem);
            statsDropDownOptions[(int)activePanel].OnClick();

            var close = widget.GetOrNull <ButtonWidget>("CLOSE");

            if (close != null)
            {
                close.OnClick = () =>
                {
                    Ui.CloseWindow();
                    Ui.Root.RemoveChild(widget);
                    onExit();
                }
            }
            ;

            var keyListener = statsDropDown.Get <LogicKeyListenerWidget>("STATS_DROPDOWN_KEYHANDLER");

            keyListener.AddHandler(e =>
            {
                if (e.Event == KeyInputEvent.Down && !e.IsRepeat)
                {
                    for (var i = 0; i < statsHotkeys.Length; i++)
                    {
                        if (statsHotkeys[i].IsActivatedBy(e))
                        {
                            Game.Sound.PlayNotification(modData.DefaultRules, null, "Sounds", "ClickSound", null);
                            statsDropDownOptions[i].OnClick();
                            return(true);
                        }
                    }
                }

                return(false);
            });
        }

        void ClearStats()
        {
            playerStatsPanel.Children.Clear();
            basicStatsHeaders.Visible            = false;
            economyStatsHeaders.Visible          = false;
            productionStatsHeaders.Visible       = false;
            combatStatsHeaders.Visible           = false;
            earnedThisMinuteGraphHeaders.Visible = false;
        }

        void EarnedThisMinuteGraph()
        {
            earnedThisMinuteGraphHeaders.Visible = true;
            var template = earnedThisMinuteGraphTemplate.Clone();

            var graph = template.Get <LineGraphWidget>("EARNED_THIS_MIN_GRAPH");

            graph.GetSeries = () =>
                              players.Select(p => new LineGraphSeries(
                                                 p.PlayerName,
                                                 p.Color.RGB,
                                                 (p.PlayerActor.TraitOrDefault <PlayerStatistics>() ?? new PlayerStatistics(p.PlayerActor)).EarnedSamples.Select(s => (float)s)));

            playerStatsPanel.AddChild(template);
            playerStatsPanel.ScrollToTop();
        }

        void DisplayStats(Func <Player, ScrollItemWidget> createItem)
        {
            var teams = players.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.ClientIndex) ?? new Session.Client()).Team).OrderBy(g => g.Key);

            foreach (var t in teams)
            {
                var team = t;
                var tt   = ScrollItemWidget.Setup(teamTemplate, () => false, () => { });
                tt.IgnoreMouseOver = true;
                tt.Get <LabelWidget>("TEAM").GetText = () => team.Key == 0 ? "No Team" : "Team " + team.Key;
                playerStatsPanel.AddChild(tt);
                foreach (var p in team)
                {
                    var player = p;
                    playerStatsPanel.AddChild(createItem(player));
                }
            }
        }

        ScrollItemWidget CombatStats(Player player)
        {
            combatStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(combatPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("UNITS_KILLED").GetText     = () => stats.UnitsKilled.ToString();
            template.Get <LabelWidget>("UNITS_DEAD").GetText       = () => stats.UnitsDead.ToString();
            template.Get <LabelWidget>("BUILDINGS_KILLED").GetText = () => stats.BuildingsKilled.ToString();
            template.Get <LabelWidget>("BUILDINGS_DEAD").GetText   = () => stats.BuildingsDead.ToString();

            return(template);
        }

        ScrollItemWidget ProductionStats(Player player)
        {
            productionStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(productionPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            template.Get <ObserverProductionIconsWidget>("PRODUCTION_ICONS").GetPlayer      = () => player;
            template.Get <ObserverSupportPowerIconsWidget>("SUPPORT_POWER_ICONS").GetPlayer = () => player;
            template.IgnoreChildMouseOver = false;

            return(template);
        }

        ScrollItemWidget EconomyStats(Player player)
        {
            economyStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(economyPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res   = player.PlayerActor.Trait <PlayerResources>();
            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }

            template.Get <LabelWidget>("CASH").GetText            = () => "$" + (res.Cash + res.Resources);
            template.Get <LabelWidget>("EARNED_MIN").GetText      = () => AverageEarnedPerMinute(res.Earned);
            template.Get <LabelWidget>("EARNED_THIS_MIN").GetText = () => "$" + stats.EarnedThisMinute;
            template.Get <LabelWidget>("EARNED").GetText          = () => "$" + res.Earned;
            template.Get <LabelWidget>("SPENT").GetText           = () => "$" + res.Spent;

            var assets = template.Get <LabelWidget>("ASSETS");

            assets.GetText = () => "$" + world.ActorsHavingTrait <Valued>()
                             .Where(a => a.Owner == player && !a.IsDead)
                             .Sum(a => a.Info.TraitInfos <ValuedInfo>().First().Cost);

            var harvesters = template.Get <LabelWidget>("HARVESTERS");

            harvesters.GetText = () => world.ActorsHavingTrait <Harvester>().Count(a => a.Owner == player && !a.IsDead).ToString();

            return(template);
        }

        ScrollItemWidget BasicStats(Player player)
        {
            basicStatsHeaders.Visible = true;
            var template = SetupPlayerScrollItemWidget(basicPlayerTemplate, player);

            LobbyUtils.AddPlayerFlagAndName(template, player);

            var res = player.PlayerActor.Trait <PlayerResources>();

            template.Get <LabelWidget>("CASH").GetText       = () => "$" + (res.Cash + res.Resources);
            template.Get <LabelWidget>("EARNED_MIN").GetText = () => AverageEarnedPerMinute(res.Earned);

            var powerRes = player.PlayerActor.Trait <PowerManager>();
            var power    = template.Get <LabelWidget>("POWER");

            power.GetText  = () => powerRes.PowerDrained + "/" + powerRes.PowerProvided;
            power.GetColor = () => GetPowerColor(powerRes.PowerState);

            var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>();

            if (stats == null)
            {
                return(template);
            }
            template.Get <LabelWidget>("KILLS").GetText            = () => (stats.UnitsKilled + stats.BuildingsKilled).ToString();
            template.Get <LabelWidget>("DEATHS").GetText           = () => (stats.UnitsDead + stats.BuildingsDead).ToString();
            template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => "$" + stats.KillsCost;
            template.Get <LabelWidget>("ASSETS_LOST").GetText      = () => "$" + stats.DeathsCost;
            template.Get <LabelWidget>("EXPERIENCE").GetText       = () => stats.Experience.ToString();
            template.Get <LabelWidget>("ACTIONS_MIN").GetText      = () => AverageOrdersPerMinute(stats.OrderCount);

            return(template);
        }

        ScrollItemWidget SetupPlayerScrollItemWidget(ScrollItemWidget template, Player player)
        {
            return(ScrollItemWidget.Setup(template, () => false, () =>
            {
                var playerBase = world.ActorsHavingTrait <BaseBuilding>().FirstOrDefault(a => !a.IsDead && a.Owner == player);
                if (playerBase != null)
                {
                    worldRenderer.Viewport.Center(playerBase.CenterPosition);
                }
            }));
        }
        internal LobbyLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, OrderManager orderManager,
                            Action onExit, Action onStart, bool skirmishMode)
        {
            map                = MapCache.UnknownMap;
            lobby              = widget;
            this.modData       = modData;
            this.orderManager  = orderManager;
            this.worldRenderer = worldRenderer;
            this.onStart       = onStart;
            this.onExit        = onExit;
            this.skirmishMode  = skirmishMode;

            // TODO: This needs to be reworked to support per-map tech levels, bots, etc.
            this.modRules = modData.DefaultRules;
            shellmapWorld = worldRenderer.World;

            services = modData.Manifest.Get <WebServices>();

            orderManager.AddChatLine    += AddChatLine;
            Game.LobbyInfoChanged       += UpdateCurrentMap;
            Game.LobbyInfoChanged       += UpdatePlayerList;
            Game.BeforeGameStart        += OnGameStart;
            Game.ConnectionStateChanged += ConnectionStateChanged;

            var name = lobby.GetOrNull <LabelWidget>("SERVER_NAME");

            if (name != null)
            {
                name.GetText = () => orderManager.LobbyInfo.GlobalSettings.ServerName;
            }

            var mapContainer = Ui.LoadWidget("MAP_PREVIEW", lobby.Get("MAP_PREVIEW_ROOT"), new WidgetArgs
            {
                { "orderManager", orderManager },
                { "getMap", (Func <MapPreview>)(() => map) },
                { "onMouseDown", (Action <MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) =>
                                                                                     LobbyUtils.SelectSpawnPoint(orderManager, preview, mapPreview, mi)) },
                { "getSpawnOccupants", (Func <MapPreview, Dictionary <CPos, SpawnOccupant> >)(mapPreview => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, mapPreview)) },
                { "showUnoccupiedSpawnpoints", true },
            });

            mapContainer.IsVisible = () => panel != PanelType.Servers;

            UpdateCurrentMap();

            var playerBin = Ui.LoadWidget("LOBBY_PLAYER_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs());

            playerBin.IsVisible = () => panel == PanelType.Players;

            players = playerBin.Get <ScrollPanelWidget>("LOBBY_PLAYERS");
            editablePlayerTemplate       = players.Get("TEMPLATE_EDITABLE_PLAYER");
            nonEditablePlayerTemplate    = players.Get("TEMPLATE_NONEDITABLE_PLAYER");
            emptySlotTemplate            = players.Get("TEMPLATE_EMPTY");
            editableSpectatorTemplate    = players.Get("TEMPLATE_EDITABLE_SPECTATOR");
            nonEditableSpectatorTemplate = players.Get("TEMPLATE_NONEDITABLE_SPECTATOR");
            newSpectatorTemplate         = players.Get("TEMPLATE_NEW_SPECTATOR");
            colorPreview       = lobby.Get <ColorPreviewManagerWidget>("COLOR_MANAGER");
            colorPreview.Color = Game.Settings.Player.Color;

            foreach (var f in modRules.Actors["world"].TraitInfos <FactionInfo>())
            {
                factions.Add(f.InternalName, new LobbyFaction {
                    Selectable = f.Selectable, Name = f.Name, Side = f.Side, Description = f.Description
                });
            }

            var         gameStarting          = false;
            Func <bool> configurationDisabled = () => !Game.IsHost || gameStarting ||
                                                panel == PanelType.Kick || panel == PanelType.ForceStart ||
                                                !map.RulesLoaded || map.InvalidCustomRules ||
                                                orderManager.LocalClient == null || orderManager.LocalClient.IsReady;

            var mapButton = lobby.GetOrNull <ButtonWidget>("CHANGEMAP_BUTTON");

            if (mapButton != null)
            {
                mapButton.IsVisible  = () => panel != PanelType.Servers;
                mapButton.IsDisabled = () => gameStarting || panel == PanelType.Kick || panel == PanelType.ForceStart ||
                                       orderManager.LocalClient == null || orderManager.LocalClient.IsReady;
                mapButton.OnClick = () =>
                {
                    var onSelect = new Action <string>(uid =>
                    {
                        // Don't select the same map again
                        if (uid == map.Uid)
                        {
                            return;
                        }

                        orderManager.IssueOrder(Order.Command("map " + uid));
                        Game.Settings.Server.Map = uid;
                        Game.Settings.Save();
                    });

                    Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
                    {
                        { "initialMap", map.Uid },
                        { "initialTab", MapClassification.System },
                        { "onExit", DoNothing },
                        { "onSelect", Game.IsHost ? onSelect : null },
                        { "filter", MapVisibility.Lobby },
                    });
                };
            }

            var slotsButton = lobby.GetOrNull <DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON");

            if (slotsButton != null)
            {
                slotsButton.IsVisible  = () => panel != PanelType.Servers;
                slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
                                         (orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) &&
                                          orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0);

                slotsButton.OnMouseDown = _ =>
                {
                    var botTypes = map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Type);
                    var options  = new Dictionary <string, IEnumerable <DropDownOption> >();

                    var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
                    if (orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots))
                    {
                        var botOptions = new List <DropDownOption>()
                        {
                            new DropDownOption()
                            {
                                Title      = "Add",
                                IsSelected = () => false,
                                OnClick    = () =>
                                {
                                    foreach (var slot in orderManager.LobbyInfo.Slots)
                                    {
                                        var bot = botTypes.Random(Game.CosmeticRandom);
                                        var c   = orderManager.LobbyInfo.ClientInSlot(slot.Key);
                                        if (slot.Value.AllowBots == true && (c == null || c.Bot != null))
                                        {
                                            orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot.Key, botController.Index, bot)));
                                        }
                                    }
                                }
                            }
                        };

                        if (orderManager.LobbyInfo.Clients.Any(c => c.Bot != null))
                        {
                            botOptions.Add(new DropDownOption()
                            {
                                Title      = "Remove",
                                IsSelected = () => false,
                                OnClick    = () =>
                                {
                                    foreach (var slot in orderManager.LobbyInfo.Slots)
                                    {
                                        var c = orderManager.LobbyInfo.ClientInSlot(slot.Key);
                                        if (c != null && c.Bot != null)
                                        {
                                            orderManager.IssueOrder(Order.Command("slot_open " + slot.Value.PlayerReference));
                                        }
                                    }
                                }
                            });
                        }

                        options.Add("Configure Bots", botOptions);
                    }

                    var teamCount = (orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) + 1) / 2;
                    if (teamCount >= 1)
                    {
                        var teamOptions = Enumerable.Range(2, teamCount - 1).Reverse().Select(d => new DropDownOption
                        {
                            Title      = "{0} Teams".F(d),
                            IsSelected = () => false,
                            OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams {0}".F(d.ToString())))
                        }).ToList();

                        if (orderManager.LobbyInfo.Slots.Any(s => s.Value.AllowBots))
                        {
                            teamOptions.Add(new DropDownOption
                            {
                                Title      = "Humans vs Bots",
                                IsSelected = () => false,
                                OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams 1"))
                            });
                        }

                        teamOptions.Add(new DropDownOption
                        {
                            Title      = "Free for all",
                            IsSelected = () => false,
                            OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams 0"))
                        });

                        options.Add("Configure Teams", teamOptions);
                    }

                    Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                    {
                        var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
                        item.Get <LabelWidget>("LABEL").GetText = () => option.Title;
                        return(item);
                    };
                    slotsButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 175, options, setupItem);
                };
            }

            var optionsBin = Ui.LoadWidget("LOBBY_OPTIONS_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs()
            {
                { "orderManager", orderManager },
                { "getMap", (Func <MapPreview>)(() => map) },
                { "configurationDisabled", configurationDisabled }
            });

            optionsBin.IsVisible = () => panel == PanelType.Options;

            var musicBin = Ui.LoadWidget("LOBBY_MUSIC_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs
            {
                { "onExit", DoNothing },
                { "world", worldRenderer.World }
            });

            musicBin.IsVisible = () => panel == PanelType.Music;

            ServerListLogic serverListLogic = null;

            if (!skirmishMode)
            {
                Action <GameServer> doNothingWithServer = _ => { };

                var serversBin = Ui.LoadWidget("LOBBY_SERVERS_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs
                {
                    { "onJoin", doNothingWithServer },
                });

                serverListLogic      = serversBin.LogicObjects.Select(l => l as ServerListLogic).FirstOrDefault(l => l != null);
                serversBin.IsVisible = () => panel == PanelType.Servers;
            }

            var tabContainer = skirmishMode ? lobby.Get("SKIRMISH_TABS") : lobby.Get("MULTIPLAYER_TABS");

            tabContainer.IsVisible = () => true;

            var optionsTab = tabContainer.Get <ButtonWidget>("OPTIONS_TAB");

            optionsTab.IsHighlighted = () => panel == PanelType.Options;
            optionsTab.IsDisabled    = OptionsTabDisabled;
            optionsTab.OnClick       = () => panel = PanelType.Options;
            optionsTab.GetText       = () => !map.RulesLoaded ? "Loading..." : optionsTab.Text;

            var playersTab = tabContainer.Get <ButtonWidget>("PLAYERS_TAB");

            playersTab.IsHighlighted = () => panel == PanelType.Players;
            playersTab.IsDisabled    = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
            playersTab.OnClick       = () => panel = PanelType.Players;

            var musicTab = tabContainer.Get <ButtonWidget>("MUSIC_TAB");

            musicTab.IsHighlighted = () => panel == PanelType.Music;
            musicTab.IsDisabled    = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
            musicTab.OnClick       = () => panel = PanelType.Music;

            var serversTab = tabContainer.GetOrNull <ButtonWidget>("SERVERS_TAB");

            if (serversTab != null)
            {
                serversTab.IsHighlighted = () => panel == PanelType.Servers;
                serversTab.IsDisabled    = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
                serversTab.OnClick       = () =>
                {
                    // Refresh the list when switching to the servers tab
                    if (serverListLogic != null && panel != PanelType.Servers)
                    {
                        serverListLogic.RefreshServerList();
                    }

                    panel = PanelType.Servers;
                };
            }

            // Force start panel
            Action startGame = () =>
            {
                gameStarting = true;
                orderManager.IssueOrder(Order.Command("startgame"));
            };

            var startGameButton = lobby.GetOrNull <ButtonWidget>("START_GAME_BUTTON");

            if (startGameButton != null)
            {
                startGameButton.IsDisabled = () => configurationDisabled() || map.Status != MapStatus.Available ||
                                             orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) ||
                                             (!orderManager.LobbyInfo.GlobalSettings.EnableSingleplayer && orderManager.LobbyInfo.NonBotPlayers.Count() < 2);

                startGameButton.OnClick = () =>
                {
                    // Bots and admins don't count
                    if (orderManager.LobbyInfo.Clients.Any(c => c.Slot != null && !c.IsAdmin && c.Bot == null && !c.IsReady))
                    {
                        panel = PanelType.ForceStart;
                    }
                    else
                    {
                        startGame();
                    }
                };
            }

            var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs());

            forceStartBin.IsVisible = () => panel == PanelType.ForceStart;
            forceStartBin.Get("KICK_WARNING").IsVisible               = () => orderManager.LobbyInfo.Clients.Any(c => c.IsInvalid);
            forceStartBin.Get <ButtonWidget>("OK_BUTTON").OnClick     = startGame;
            forceStartBin.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players;

            var disconnectButton = lobby.Get <ButtonWidget>("DISCONNECT_BUTTON");

            disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); };

            if (skirmishMode)
            {
                disconnectButton.Text = "Back";
            }

            chatLabel = lobby.Get <LabelWidget>("LABEL_CHATTYPE");
            var chatTextField = lobby.Get <TextFieldWidget>("CHAT_TEXTFIELD");

            chatTextField.MaxLength = UnitOrders.ChatMessageMaxLength;

            chatTextField.TakeKeyboardFocus();
            chatTextField.OnEnterKey = () =>
            {
                if (chatTextField.Text.Length == 0)
                {
                    return(true);
                }

                // Always scroll to bottom when we've typed something
                lobbyChatPanel.ScrollToBottom();

                orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text));
                chatTextField.Text = "";
                return(true);
            };

            chatTextField.OnTabKey = () =>
            {
                var previousText = chatTextField.Text;
                chatTextField.Text           = tabCompletion.Complete(chatTextField.Text);
                chatTextField.CursorPosition = chatTextField.Text.Length;

                if (chatTextField.Text == previousText)
                {
                    return(SwitchTeamChat());
                }
                else
                {
                    return(true);
                }
            };

            chatTextField.OnEscKey = () => { chatTextField.Text = ""; return(true); };

            lobbyChatPanel = lobby.Get <ScrollPanelWidget>("CHAT_DISPLAY");
            chatTemplate   = lobbyChatPanel.Get("CHAT_TEMPLATE");
            lobbyChatPanel.RemoveChildren();

            var settingsButton = lobby.GetOrNull <ButtonWidget>("SETTINGS_BUTTON");

            if (settingsButton != null)
            {
                settingsButton.OnClick = () => Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs
                {
                    { "onExit", DoNothing },
                    { "worldRenderer", worldRenderer }
                });
            }

            // Add a bot on the first lobbyinfo update
            if (skirmishMode)
            {
                addBotOnMapLoad = true;
            }
        }
Example #20
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 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();
                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 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();
            }
        }
Example #21
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);
                }
            }
        }
Example #22
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);
            }
        }
        void UpdatePlayerList()
        {
            if (orderManager.LocalClient == null)
            {
                return;
            }

            var isHost = Game.IsHost;
            var idx    = 0;

            foreach (var kv in orderManager.LobbyInfo.Slots)
            {
                var    key      = kv.Key;
                var    slot     = kv.Value;
                var    client   = orderManager.LobbyInfo.ClientInSlot(key);
                Widget template = null;

                // get template for possible reuse
                if (idx < players.Children.Count)
                {
                    template = players.Children[idx];
                }

                if (client == null)
                {
                    // Empty slot
                    if (template == null || template.Id != emptySlotTemplate.Id)
                    {
                        template = emptySlotTemplate.Clone();
                    }

                    if (isHost)
                    {
                        LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, worldRenderer, map);
                    }
                    else
                    {
                        LobbyUtils.SetupSlotWidget(template, slot, client);
                    }

                    var join = template.Get <ButtonWidget>("JOIN");
                    join.IsVisible  = () => !slot.Closed;
                    join.IsDisabled = () => orderManager.LocalClient.IsReady;
                    join.OnClick    = () => orderManager.IssueOrder(Order.Command("slot " + key));
                }
                else if ((client.Index == orderManager.LocalClient.Index) ||
                         (client.Bot != null && isHost))
                {
                    // Editable player in slot
                    if (template == null || template.Id != editablePlayerTemplate.Id)
                    {
                        template = editablePlayerTemplate.Clone();
                    }

                    LobbyUtils.SetupLatencyWidget(template, client, orderManager);

                    if (client.Bot != null)
                    {
                        LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, worldRenderer, map);
                    }
                    else
                    {
                        LobbyUtils.SetupEditableNameWidget(template, slot, client, orderManager, worldRenderer);
                    }

                    LobbyUtils.SetupEditableColorWidget(template, slot, client, orderManager, shellmapWorld, colorPreview);
                    LobbyUtils.SetupEditableFactionWidget(template, slot, client, orderManager, factions);
                    LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map);
                    LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map);
                    LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager, map);
                }
                else
                {
                    // Non-editable player in slot
                    if (template == null || template.Id != nonEditablePlayerTemplate.Id)
                    {
                        template = nonEditablePlayerTemplate.Clone();
                    }

                    LobbyUtils.SetupLatencyWidget(template, client, orderManager);
                    LobbyUtils.SetupColorWidget(template, slot, client);
                    LobbyUtils.SetupFactionWidget(template, slot, client, factions);

                    if (isHost)
                    {
                        LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map);
                        LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map);
                        LobbyUtils.SetupPlayerActionWidget(template, slot, client, orderManager, worldRenderer,
                                                           lobby, () => panel = PanelType.Kick, () => panel = PanelType.Players);
                    }
                    else
                    {
                        LobbyUtils.SetupNameWidget(template, slot, client, orderManager, worldRenderer);
                        LobbyUtils.SetupTeamWidget(template, slot, client);
                        LobbyUtils.SetupSpawnWidget(template, slot, client);
                    }

                    LobbyUtils.SetupReadyWidget(template, slot, client);
                }

                template.IsVisible = () => true;

                if (idx >= players.Children.Count)
                {
                    players.AddChild(template);
                }
                else if (players.Children[idx].Id != template.Id)
                {
                    players.ReplaceChild(players.Children[idx], template);
                }

                idx++;
            }

            // Add spectators
            foreach (var client in orderManager.LobbyInfo.Clients.Where(client => client.Slot == null))
            {
                Widget template = null;
                var    c        = client;

                // get template for possible reuse
                if (idx < players.Children.Count)
                {
                    template = players.Children[idx];
                }

                // Editable spectator
                if (c.Index == orderManager.LocalClient.Index)
                {
                    if (template == null || template.Id != editableSpectatorTemplate.Id)
                    {
                        template = editableSpectatorTemplate.Clone();
                    }

                    LobbyUtils.SetupEditableNameWidget(template, null, c, orderManager, worldRenderer);

                    if (client.IsAdmin)
                    {
                        LobbyUtils.SetupEditableReadyWidget(template, null, client, orderManager, map);
                    }
                    else
                    {
                        LobbyUtils.HideReadyWidgets(template);
                    }
                }
                else
                {
                    // Non-editable spectator
                    if (template == null || template.Id != nonEditableSpectatorTemplate.Id)
                    {
                        template = nonEditableSpectatorTemplate.Clone();
                    }

                    if (isHost)
                    {
                        LobbyUtils.SetupPlayerActionWidget(template, null, client, orderManager, worldRenderer,
                                                           lobby, () => panel = PanelType.Kick, () => panel = PanelType.Players);
                    }
                    else
                    {
                        LobbyUtils.SetupNameWidget(template, null, client, orderManager, worldRenderer);
                    }

                    if (client.IsAdmin)
                    {
                        LobbyUtils.SetupReadyWidget(template, null, client);
                    }
                    else
                    {
                        LobbyUtils.HideReadyWidgets(template);
                    }
                }

                LobbyUtils.SetupLatencyWidget(template, c, orderManager);
                template.IsVisible = () => true;

                if (idx >= players.Children.Count)
                {
                    players.AddChild(template);
                }
                else if (players.Children[idx].Id != template.Id)
                {
                    players.ReplaceChild(players.Children[idx], template);
                }

                idx++;
            }

            // Spectate button
            if (orderManager.LocalClient.Slot != null)
            {
                Widget spec = null;
                if (idx < players.Children.Count)
                {
                    spec = players.Children[idx];
                }
                if (spec == null || spec.Id != newSpectatorTemplate.Id)
                {
                    spec = newSpectatorTemplate.Clone();
                }

                LobbyUtils.SetupKickSpectatorsWidget(spec, orderManager, lobby,
                                                     () => panel = PanelType.Kick, () => panel = PanelType.Players, skirmishMode);

                var btn = spec.Get <ButtonWidget>("SPECTATE");
                btn.OnClick    = () => orderManager.IssueOrder(Order.Command("spectate"));
                btn.IsDisabled = () => orderManager.LocalClient.IsReady;
                btn.IsVisible  = () => orderManager.LobbyInfo.GlobalSettings.AllowSpectators ||
                                 orderManager.LocalClient.IsAdmin;

                spec.IsVisible = () => true;

                if (idx >= players.Children.Count)
                {
                    players.AddChild(spec);
                }
                else if (players.Children[idx].Id != spec.Id)
                {
                    players.ReplaceChild(players.Children[idx], spec);
                }

                idx++;
            }

            while (players.Children.Count > idx)
            {
                players.RemoveChild(players.Children[idx]);
            }

            tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
        }
Example #24
0
        internal LobbyLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, OrderManager orderManager,
                            Action onExit, Action onStart, bool skirmishMode)
        {
            map               = MapCache.UnknownMap;
            lobby             = widget;
            this.modData      = modData;
            this.orderManager = orderManager;
            this.onStart      = onStart;
            this.onExit       = onExit;
            this.skirmishMode = skirmishMode;

            // TODO: This needs to be reworked to support per-map tech levels, bots, etc.
            this.modRules = modData.DefaultRules;
            shellmapWorld = worldRenderer.World;

            services = modData.Manifest.Get <WebServices>();

            orderManager.AddChatLine    += AddChatLine;
            Game.LobbyInfoChanged       += UpdateCurrentMap;
            Game.LobbyInfoChanged       += UpdatePlayerList;
            Game.BeforeGameStart        += OnGameStart;
            Game.ConnectionStateChanged += ConnectionStateChanged;

            var name = lobby.GetOrNull <LabelWidget>("SERVER_NAME");

            if (name != null)
            {
                name.GetText = () => orderManager.LobbyInfo.GlobalSettings.ServerName;
            }

            Ui.LoadWidget("MAP_PREVIEW", lobby.Get("MAP_PREVIEW_ROOT"), new WidgetArgs
            {
                { "orderManager", orderManager },
                { "getMap", (Func <MapPreview>)(() => map) },
                { "onMouseDown", (Action <MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) =>
                                                                                     LobbyUtils.SelectSpawnPoint(orderManager, preview, mapPreview, mi)) },
                { "getSpawnOccupants", (Func <MapPreview, Dictionary <CPos, SpawnOccupant> >)(mapPreview => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, mapPreview)) },
                { "showUnoccupiedSpawnpoints", true },
            });

            UpdateCurrentMap();

            var playerBin = Ui.LoadWidget("LOBBY_PLAYER_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs());

            playerBin.IsVisible = () => panel == PanelType.Players;

            players = playerBin.Get <ScrollPanelWidget>("LOBBY_PLAYERS");
            editablePlayerTemplate       = players.Get("TEMPLATE_EDITABLE_PLAYER");
            nonEditablePlayerTemplate    = players.Get("TEMPLATE_NONEDITABLE_PLAYER");
            emptySlotTemplate            = players.Get("TEMPLATE_EMPTY");
            editableSpectatorTemplate    = players.Get("TEMPLATE_EDITABLE_SPECTATOR");
            nonEditableSpectatorTemplate = players.Get("TEMPLATE_NONEDITABLE_SPECTATOR");
            newSpectatorTemplate         = players.Get("TEMPLATE_NEW_SPECTATOR");
            colorPreview       = lobby.Get <ColorPreviewManagerWidget>("COLOR_MANAGER");
            colorPreview.Color = Game.Settings.Player.Color;

            foreach (var f in modRules.Actors["world"].TraitInfos <FactionInfo>())
            {
                factions.Add(f.InternalName, new LobbyFaction {
                    Selectable = f.Selectable, Name = f.Name, Side = f.Side, Description = f.Description
                });
            }

            var         gameStarting          = false;
            Func <bool> configurationDisabled = () => !Game.IsHost || gameStarting ||
                                                panel == PanelType.Kick || panel == PanelType.ForceStart ||
                                                !map.RulesLoaded || map.InvalidCustomRules ||
                                                orderManager.LocalClient == null || orderManager.LocalClient.IsReady;

            var mapButton = lobby.GetOrNull <ButtonWidget>("CHANGEMAP_BUTTON");

            if (mapButton != null)
            {
                mapButton.IsDisabled = () => gameStarting || panel == PanelType.Kick || panel == PanelType.ForceStart ||
                                       orderManager.LocalClient == null || orderManager.LocalClient.IsReady;
                mapButton.OnClick = () =>
                {
                    var onSelect = new Action <string>(uid =>
                    {
                        // Don't select the same map again
                        if (uid == map.Uid)
                        {
                            return;
                        }

                        orderManager.IssueOrder(Order.Command("map " + uid));
                        Game.Settings.Server.Map = uid;
                        Game.Settings.Save();
                    });

                    Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
                    {
                        { "initialMap", map.Uid },
                        { "initialTab", MapClassification.System },
                        { "onExit", DoNothing },
                        { "onSelect", Game.IsHost ? onSelect : null },
                        { "filter", MapVisibility.Lobby },
                    });
                };
            }

            var slotsButton = lobby.GetOrNull <DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON");

            if (slotsButton != null)
            {
                slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
                                         (orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) &&
                                          orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0);

                slotsButton.OnMouseDown = _ =>
                {
                    var botTypes = map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Type);
                    var options  = new Dictionary <string, IEnumerable <DropDownOption> >();

                    var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
                    if (orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots))
                    {
                        var botOptions = new List <DropDownOption>()
                        {
                            new DropDownOption()
                            {
                                Title      = "Add",
                                IsSelected = () => false,
                                OnClick    = () =>
                                {
                                    foreach (var slot in orderManager.LobbyInfo.Slots)
                                    {
                                        var bot = botTypes.Random(Game.CosmeticRandom);
                                        var c   = orderManager.LobbyInfo.ClientInSlot(slot.Key);
                                        if (slot.Value.AllowBots == true && (c == null || c.Bot != null))
                                        {
                                            orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot.Key, botController.Index, bot)));
                                        }
                                    }
                                }
                            }
                        };

                        if (orderManager.LobbyInfo.Clients.Any(c => c.Bot != null))
                        {
                            botOptions.Add(new DropDownOption()
                            {
                                Title      = "Remove",
                                IsSelected = () => false,
                                OnClick    = () =>
                                {
                                    foreach (var slot in orderManager.LobbyInfo.Slots)
                                    {
                                        var c = orderManager.LobbyInfo.ClientInSlot(slot.Key);
                                        if (c != null && c.Bot != null)
                                        {
                                            orderManager.IssueOrder(Order.Command("slot_open " + slot.Value.PlayerReference));
                                        }
                                    }
                                }
                            });
                        }

                        options.Add("Configure Bots", botOptions);
                    }

                    var teamCount = (orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) + 1) / 2;
                    if (teamCount >= 1)
                    {
                        var teamOptions = Enumerable.Range(2, teamCount - 1).Reverse().Select(d => new DropDownOption
                        {
                            Title      = "{0} Teams".F(d),
                            IsSelected = () => false,
                            OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams {0}".F(d.ToString())))
                        }).ToList();

                        if (orderManager.LobbyInfo.Slots.Any(s => s.Value.AllowBots))
                        {
                            teamOptions.Add(new DropDownOption
                            {
                                Title      = "Humans vs Bots",
                                IsSelected = () => false,
                                OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams 1"))
                            });
                        }

                        teamOptions.Add(new DropDownOption
                        {
                            Title      = "Free for all",
                            IsSelected = () => false,
                            OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams 0"))
                        });

                        options.Add("Configure Teams", teamOptions);
                    }

                    Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                    {
                        var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
                        item.Get <LabelWidget>("LABEL").GetText = () => option.Title;
                        return(item);
                    };
                    slotsButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 175, options, setupItem);
                };
            }

            var optionsBin = Ui.LoadWidget("LOBBY_OPTIONS_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs());

            optionsBin.IsVisible = () => panel == PanelType.Options;

            var musicBin = Ui.LoadWidget("LOBBY_MUSIC_BIN", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs
            {
                { "onExit", DoNothing },
                { "world", worldRenderer.World }
            });

            musicBin.IsVisible = () => panel == PanelType.Music;

            var optionsTab = lobby.Get <ButtonWidget>("OPTIONS_TAB");

            optionsTab.IsHighlighted = () => panel == PanelType.Options;
            optionsTab.IsDisabled    = () => !map.RulesLoaded || map.InvalidCustomRules || panel == PanelType.Kick || panel == PanelType.ForceStart;
            optionsTab.OnClick       = () => panel = PanelType.Options;

            var playersTab = lobby.Get <ButtonWidget>("PLAYERS_TAB");

            playersTab.IsHighlighted = () => panel == PanelType.Players;
            playersTab.IsDisabled    = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
            playersTab.OnClick       = () => panel = PanelType.Players;

            var musicTab = lobby.Get <ButtonWidget>("MUSIC_TAB");

            musicTab.IsHighlighted = () => panel == PanelType.Music;
            musicTab.IsDisabled    = () => panel == PanelType.Kick || panel == PanelType.ForceStart;
            musicTab.OnClick       = () => panel = PanelType.Music;

            // Force start panel
            Action startGame = () =>
            {
                gameStarting = true;
                orderManager.IssueOrder(Order.Command("startgame"));
            };

            var startGameButton = lobby.GetOrNull <ButtonWidget>("START_GAME_BUTTON");

            if (startGameButton != null)
            {
                startGameButton.IsDisabled = () => configurationDisabled() || map.Status != MapStatus.Available ||
                                             orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) ||
                                             (!orderManager.LobbyInfo.GlobalSettings.EnableSingleplayer && orderManager.LobbyInfo.NonBotPlayers.Count() < 2);

                startGameButton.OnClick = () =>
                {
                    // Bots and admins don't count
                    if (orderManager.LobbyInfo.Clients.Any(c => c.Slot != null && !c.IsAdmin && c.Bot == null && !c.IsReady))
                    {
                        panel = PanelType.ForceStart;
                    }
                    else
                    {
                        startGame();
                    }
                };
            }

            var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs());

            forceStartBin.IsVisible = () => panel == PanelType.ForceStart;
            forceStartBin.Get("KICK_WARNING").IsVisible               = () => orderManager.LobbyInfo.Clients.Any(c => c.IsInvalid);
            forceStartBin.Get <ButtonWidget>("OK_BUTTON").OnClick     = startGame;
            forceStartBin.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players;

            // Options panel
            var optionCheckboxes = new Dictionary <string, string>()
            {
                { "EXPLORED_MAP_CHECKBOX", "explored" },
                { "CRATES_CHECKBOX", "crates" },
                { "SHORTGAME_CHECKBOX", "shortgame" },
                { "FOG_CHECKBOX", "fog" },
                { "ALLYBUILDRADIUS_CHECKBOX", "allybuild" },
                { "ALLOWCHEATS_CHECKBOX", "cheats" },
                { "CREEPS_CHECKBOX", "creeps" },
            };

            foreach (var kv in optionCheckboxes)
            {
                var checkbox = optionsBin.GetOrNull <CheckboxWidget>(kv.Key);
                if (checkbox != null)
                {
                    var option = new CachedTransform <Session.Global, Session.LobbyOptionState>(
                        gs => gs.LobbyOptions[kv.Value]);

                    var visible = new CachedTransform <Session.Global, bool>(
                        gs => gs.LobbyOptions.ContainsKey(kv.Value));

                    checkbox.IsVisible  = () => visible.Update(orderManager.LobbyInfo.GlobalSettings);
                    checkbox.IsChecked  = () => option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled;
                    checkbox.IsDisabled = () => configurationDisabled() ||
                                          option.Update(orderManager.LobbyInfo.GlobalSettings).Locked;
                    checkbox.OnClick = () => orderManager.IssueOrder(Order.Command(
                                                                         "option {0} {1}".F(kv.Value, !option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled)));
                }
            }

            var optionDropdowns = new Dictionary <string, string>()
            {
                { "TECHLEVEL", "techlevel" },
                { "STARTINGUNITS", "startingunits" },
                { "STARTINGCASH", "startingcash" },
                { "DIFFICULTY", "difficulty" },
                { "GAMESPEED", "gamespeed" }
            };

            var allOptions = new CachedTransform <MapPreview, LobbyOption[]>(
                mapPreview => mapPreview.Rules.Actors["player"].TraitInfos <ILobbyOptions>()
                .Concat(mapPreview.Rules.Actors["world"].TraitInfos <ILobbyOptions>())
                .SelectMany(t => t.LobbyOptions(mapPreview.Rules))
                .ToArray());

            foreach (var kv in optionDropdowns)
            {
                var dropdown = optionsBin.GetOrNull <DropDownButtonWidget>(kv.Key + "_DROPDOWNBUTTON");
                if (dropdown != null)
                {
                    var optionValue = new CachedTransform <Session.Global, Session.LobbyOptionState>(
                        gs => gs.LobbyOptions[kv.Value]);

                    var option = new CachedTransform <MapPreview, LobbyOption>(
                        mapPreview => allOptions.Update(mapPreview).FirstOrDefault(o => o.Id == kv.Value));

                    var getOptionLabel = new CachedTransform <string, string>(id =>
                    {
                        string value;
                        if (id == null || !option.Update(map).Values.TryGetValue(id, out value))
                        {
                            return("Not Available");
                        }

                        return(value);
                    });

                    dropdown.GetText    = () => getOptionLabel.Update(optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value);
                    dropdown.IsVisible  = () => option.Update(map) != null;
                    dropdown.IsDisabled = () => configurationDisabled() ||
                                          optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Locked;

                    dropdown.OnMouseDown = _ =>
                    {
                        Func <KeyValuePair <string, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (c, template) =>
                        {
                            Func <bool> isSelected = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value == c.Key;
                            Action      onClick    = () => orderManager.IssueOrder(Order.Command("option {0} {1}".F(kv.Value, c.Key)));

                            var item = ScrollItemWidget.Setup(template, isSelected, onClick);
                            item.Get <LabelWidget>("LABEL").GetText = () => c.Value;
                            return(item);
                        };

                        var options = option.Update(map).Values;
                        dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                    };

                    var label = optionsBin.GetOrNull(kv.Key + "_DESC");
                    if (label != null)
                    {
                        label.IsVisible = () => option.Update(map) != null;
                    }
                }
            }

            var disconnectButton = lobby.Get <ButtonWidget>("DISCONNECT_BUTTON");

            disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); };

            if (skirmishMode)
            {
                disconnectButton.Text = "Back";
            }

            var globalChat      = Game.LoadWidget(null, "LOBBY_GLOBALCHAT_PANEL", lobby.Get("GLOBALCHAT_ROOT"), new WidgetArgs());
            var globalChatInput = globalChat.Get <TextFieldWidget>("CHAT_TEXTFIELD");

            globalChat.IsVisible = () => chatPanel == ChatPanelType.Global;

            var globalChatTab = lobby.Get <ButtonWidget>("GLOBALCHAT_TAB");

            globalChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Global;
            globalChatTab.OnClick       = () =>
            {
                chatPanel = ChatPanelType.Global;
                globalChatInput.TakeKeyboardFocus();
            };

            var globalChatLabel = globalChatTab.Text;

            globalChatTab.GetText = () =>
            {
                if (globalChatUnreadMessages == 0 || chatPanel == ChatPanelType.Global)
                {
                    return(globalChatLabel);
                }

                return(globalChatLabel + " ({0})".F(globalChatUnreadMessages));
            };

            globalChatLastReadMessages = Game.GlobalChat.History.Count(m => m.Type == ChatMessageType.Message);

            var lobbyChat = lobby.Get("LOBBYCHAT");

            lobbyChat.IsVisible = () => chatPanel == ChatPanelType.Lobby;

            chatLabel = lobby.Get <LabelWidget>("LABEL_CHATTYPE");
            var chatTextField = lobby.Get <TextFieldWidget>("CHAT_TEXTFIELD");

            chatTextField.MaxLength = UnitOrders.ChatMessageMaxLength;

            chatTextField.TakeKeyboardFocus();
            chatTextField.OnEnterKey = () =>
            {
                if (chatTextField.Text.Length == 0)
                {
                    return(true);
                }

                // Always scroll to bottom when we've typed something
                lobbyChatPanel.ScrollToBottom();

                orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text));
                chatTextField.Text = "";
                return(true);
            };

            chatTextField.OnTabKey = () =>
            {
                var previousText = chatTextField.Text;
                chatTextField.Text           = tabCompletion.Complete(chatTextField.Text);
                chatTextField.CursorPosition = chatTextField.Text.Length;

                if (chatTextField.Text == previousText)
                {
                    return(SwitchTeamChat());
                }
                else
                {
                    return(true);
                }
            };

            chatTextField.OnEscKey = () => { chatTextField.Text = ""; return(true); };

            var lobbyChatTab = lobby.Get <ButtonWidget>("LOBBYCHAT_TAB");

            lobbyChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Lobby;
            lobbyChatTab.OnClick       = () =>
            {
                chatPanel = ChatPanelType.Lobby;
                chatTextField.TakeKeyboardFocus();
            };

            var lobbyChatLabel = lobbyChatTab.Text;

            lobbyChatTab.GetText = () =>
            {
                if (lobbyChatUnreadMessages == 0 || chatPanel == ChatPanelType.Lobby)
                {
                    return(lobbyChatLabel);
                }

                return(lobbyChatLabel + " ({0})".F(lobbyChatUnreadMessages));
            };

            lobbyChatPanel = lobby.Get <ScrollPanelWidget>("CHAT_DISPLAY");
            chatTemplate   = lobbyChatPanel.Get("CHAT_TEMPLATE");
            lobbyChatPanel.RemoveChildren();

            var settingsButton = lobby.GetOrNull <ButtonWidget>("SETTINGS_BUTTON");

            if (settingsButton != null)
            {
                settingsButton.OnClick = () => Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs
                {
                    { "onExit", DoNothing },
                    { "worldRenderer", worldRenderer }
                });
            }

            // Add a bot on the first lobbyinfo update
            if (skirmishMode)
            {
                addBotOnMapLoad = true;
            }
        }
Example #25
0
        public ReplayBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart)
        {
            map   = MapCache.UnknownMap;
            panel = widget;

            services              = modData.Manifest.Get <WebServices>();
            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;
            var dir = Platform.ResolvePath(Platform.SupportDirPrefix, "Replays", mod.Id, mod.Metadata.Version);

            if (Directory.Exists(dir))
            {
                ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template));
            }

            var watch = panel.Get <ButtonWidget>("WATCH_BUTTON");

            watch.IsDisabled = () => selectedReplay == null || map.Status != MapStatus.Available;
            watch.OnClick    = () => { WatchReplay(); };

            var mapPreviewRoot = panel.Get("MAP_PREVIEW_ROOT");

            mapPreviewRoot.IsVisible           = () => selectedReplay != null;
            panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null;

            Ui.LoadWidget("MAP_PREVIEW", mapPreviewRoot, new WidgetArgs
            {
                { "orderManager", null },
                { "getMap", (Func <MapPreview>)(() => map) },
                { "onMouseDown", (Action <MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) => { }) },
                {
                    "getSpawnOccupants", (Func <MapPreview, Dictionary <CPos, SpawnOccupant> >)(mapPreview =>
                                                                                                LobbyUtils.GetSpawnOccupants(selectedReplay.GameInfo.Players, mapPreview))
                },
                { "showUnoccupiedSpawnpoints", false },
            });

            var replayDuration = new CachedTransform <ReplayMetadata, string>(r =>
                                                                              "Duration: {0}".F(WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds)));

            panel.Get <LabelWidget>("DURATION").GetText = () => replayDuration.Update(selectedReplay);

            SetupFilters();
            SetupManagement();
        }
Example #26
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);
                }
            }
        }
Example #27
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);
                }
            }
        }
        internal LobbyMapPreviewLogic(Widget widget, OrderManager orderManager, LobbyLogic lobby)
        {
            var available = widget.GetOrNull("MAP_AVAILABLE");

            if (available != null)
            {
                available.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.RuleStatus == MapRuleStatus.Cached;

                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 title = available.GetOrNull <LabelWidget>("MAP_TITLE");
                if (title != null)
                {
                    title.GetText = () => lobby.Map.Title;
                }

                var type = available.GetOrNull <LabelWidget>("MAP_TYPE");
                if (type != null)
                {
                    type.GetText = () => lobby.Map.Type;
                }

                var author = available.GetOrNull <LabelWidget>("MAP_AUTHOR");
                if (author != null)
                {
                    author.GetText = () => "Created by {0}".F(lobby.Map.Author);
                }
            }

            var invalid = widget.GetOrNull("MAP_INVALID");

            if (invalid != null)
            {
                invalid.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.RuleStatus == MapRuleStatus.Invalid;

                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 title = invalid.GetOrNull <LabelWidget>("MAP_TITLE");
                if (title != null)
                {
                    title.GetText = () => lobby.Map.Title;
                }

                var type = invalid.GetOrNull <LabelWidget>("MAP_TYPE");
                if (type != null)
                {
                    type.GetText = () => lobby.Map.Type;
                }
            }

            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 title = download.GetOrNull <LabelWidget>("MAP_TITLE");
                if (title != null)
                {
                    title.GetText = () => lobby.Map.Title;
                }

                var type = download.GetOrNull <LabelWidget>("MAP_TYPE");
                if (type != null)
                {
                    type.GetText = () => lobby.Map.Type;
                }

                var author = download.GetOrNull <LabelWidget>("MAP_AUTHOR");
                if (author != null)
                {
                    author.GetText = () => "Created by {0}".F(lobby.Map.Author);
                }

                var install = download.GetOrNull <ButtonWidget>("MAP_INSTALL");
                if (install != null)
                {
                    install.OnClick = () => lobby.Map.Install();
                }
            }

            var progress = widget.GetOrNull("MAP_PROGRESS");

            if (progress != null)
            {
                progress.IsVisible = () =>
                                     (lobby.Map.Status != MapStatus.Available || lobby.Map.RuleStatus == MapRuleStatus.Unknown) &&
                                     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 title = progress.GetOrNull <LabelWidget>("MAP_TITLE");
                if (title != null)
                {
                    title.GetText = () => lobby.Map.Title;
                }

                var type = progress.GetOrNull <LabelWidget>("MAP_TYPE");
                if (type != null)
                {
                    type.GetText = () => lobby.Map.Type;
                }

                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();
                        }
                        else if (lobby.Map.Status == MapStatus.Unavailable)
                        {
                            Game.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();
                }
            }
        }