예제 #1
0
        internal LobbyLogic(Widget widget, World world, OrderManager orderManager,
                            Action onExit, Action onStart, bool addBots)
        {
            lobby             = widget;
            this.orderManager = orderManager;
            this.OnGameStart  = () => { CloseWindow(); onStart(); };
            this.onExit       = onExit;

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

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

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

            UpdateCurrentMap();
            Players           = Ui.LoadWidget <ScrollPanelWidget>("LOBBY_PLAYER_BIN", lobby.Get("PLAYER_BIN_ROOT"), new WidgetArgs());
            Players.IsVisible = () => panel == PanelType.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;

            var mapPreview = lobby.Get <MapPreviewWidget>("MAP_PREVIEW");

            mapPreview.IsVisible    = () => Map != null;
            mapPreview.Map          = () => Map;
            mapPreview.OnMouseDown  = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, Map, mi);
            mapPreview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, Map);

            var mapTitle = lobby.GetOrNull <LabelWidget>("MAP_TITLE");

            if (mapTitle != null)
            {
                mapTitle.IsVisible = () => Map != null;
                mapTitle.GetText   = () => Map.Title;
            }

            var mapType = lobby.GetOrNull <LabelWidget>("MAP_TYPE");

            if (mapType != null)
            {
                mapType.IsVisible = () => Map != null;
                mapType.GetText   = () => Map.Type;
            }

            var mapAuthor = lobby.GetOrNull <LabelWidget>("MAP_AUTHOR");

            if (mapAuthor != null)
            {
                mapAuthor.IsVisible = () => Map != null;
                mapAuthor.GetText   = () => "Created by {0}".F(Map.Author);
            }

            CountryNames = Rules.Info["world"].Traits.WithInterface <CountryInfo>()
                           .Where(c => c.Selectable)
                           .ToDictionary(a => a.Race, a => a.Name);
            CountryNames.Add("random", "Any");

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

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

            if (mapButton != null)
            {
                mapButton.IsDisabled = configurationDisabled;
                mapButton.OnClick    = () =>
                {
                    var onSelect = new Action <Map>(m =>
                    {
                        orderManager.IssueOrder(Order.Command("map " + m.Uid));
                        Game.Settings.Server.Map = m.Uid;
                        Game.Settings.Save();
                    });

                    Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
                    {
                        { "initialMap", Map.Uid },
                        { "onExit", () => {} },
                        { "onSelect", onSelect }
                    });
                };
            }

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

            if (slotsButton != null)
            {
                slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
                                         !orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam);

                var aiModes = Rules.Info["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name);
                slotsButton.OnMouseDown = _ =>
                {
                    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 = aiModes.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, new WidgetArgs());

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

            var optionsButton = lobby.Get <ButtonWidget>("OPTIONS_BUTTON");

            optionsButton.IsDisabled = () => panel == PanelType.Kick;
            optionsButton.GetText    = () => panel == PanelType.Options ? "Players" : "Options";
            optionsButton.OnClick    = () => panel = (panel == PanelType.Options) ? PanelType.Players : PanelType.Options;

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

            if (startGameButton != null)
            {
                startGameButton.IsDisabled = () => configurationDisabled() ||
                                             orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
                startGameButton.OnClick = () =>
                {
                    gameStarting = true;
                    orderManager.IssueOrder(Order.Command("startgame"));
                };
            }

            // Options panel
            var allowCheats = optionsBin.GetOrNull <CheckboxWidget>("ALLOWCHEATS_CHECKBOX");

            if (allowCheats != null)
            {
                allowCheats.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
                allowCheats.IsDisabled = () => Map.Options.Cheats.HasValue || configurationDisabled();
                allowCheats.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                           "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));
            }

            var crates = optionsBin.GetOrNull <CheckboxWidget>("CRATES_CHECKBOX");

            if (crates != null)
            {
                crates.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Crates;
                crates.IsDisabled = () => Map.Options.Crates.HasValue || configurationDisabled();
                crates.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                      "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
            }

            var allybuildradius = optionsBin.GetOrNull <CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX");

            if (allybuildradius != null)
            {
                allybuildradius.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius;
                allybuildradius.IsDisabled = () => Map.Options.AllyBuildRadius.HasValue || configurationDisabled();
                allybuildradius.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                               "allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius)));
            }

            var fragileAlliance = optionsBin.GetOrNull <CheckboxWidget>("FRAGILEALLIANCES_CHECKBOX");

            if (fragileAlliance != null)
            {
                fragileAlliance.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances;
                fragileAlliance.IsDisabled = () => Map.Options.FragileAlliances.HasValue || configurationDisabled();
                fragileAlliance.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                               "fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances)));
            }

            var difficulty = optionsBin.GetOrNull <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");

            if (difficulty != null)
            {
                difficulty.IsVisible   = () => Map.Options.Difficulties.Any();
                difficulty.IsDisabled  = configurationDisabled;
                difficulty.GetText     = () => orderManager.LobbyInfo.GlobalSettings.Difficulty;
                difficulty.OnMouseDown = _ =>
                {
                    var options = Map.Options.Difficulties.Select(d => new DropDownOption
                    {
                        Title      = d,
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("difficulty {0}".F(d)))
                    });
                    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);
                    };
                    difficulty.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };

                optionsBin.Get <LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible;
            }

            var startingUnits = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON");

            if (startingUnits != null)
            {
                var classNames = new Dictionary <string, string>()
                {
                    { "none", "MCV Only" },
                    { "light", "Light Support" },
                    { "heavy", "Heavy Support" },
                };

                Func <string, string> className = c => classNames.ContainsKey(c) ? classNames[c] : c;
                var classes = Rules.Info["world"].Traits.WithInterface <MPStartUnitsInfo>()
                              .Select(a => a.Class).Distinct();

                startingUnits.IsDisabled  = () => !Map.Options.ConfigurableStartingUnits || configurationDisabled();
                startingUnits.GetText     = () => !Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
                startingUnits.OnMouseDown = _ =>
                {
                    var options = classes.Select(c => new DropDownOption
                    {
                        Title      = className(c),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass == c,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("startingunits {0}".F(c)))
                    });

                    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);
                    };

                    startingUnits.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };

                optionsBin.Get <LabelWidget>("STARTINGUNITS_DESC").IsVisible = startingUnits.IsVisible;
            }

            var startingCash = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON");

            if (startingCash != null)
            {
                startingCash.IsDisabled  = () => Map.Options.StartingCash.HasValue || configurationDisabled();
                startingCash.GetText     = () => Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
                startingCash.OnMouseDown = _ =>
                {
                    var options = Rules.Info["player"].Traits.Get <PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
                    {
                        Title      = "${0}".F(c),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingCash == c,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("startingcash {0}".F(c)))
                    });

                    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);
                    };

                    startingCash.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

            var enableShroud = optionsBin.GetOrNull <CheckboxWidget>("SHROUD_CHECKBOX");

            if (enableShroud != null)
            {
                enableShroud.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Shroud;
                enableShroud.IsDisabled = () => Map.Options.Shroud.HasValue || configurationDisabled();
                enableShroud.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                            "shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud)));
            }

            var enableFog = optionsBin.GetOrNull <CheckboxWidget>("FOG_CHECKBOX");

            if (enableFog != null)
            {
                enableFog.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Fog;
                enableFog.IsDisabled = () => Map.Options.Fog.HasValue || configurationDisabled();
                enableFog.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                         "fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog)));
            }

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

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

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

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

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

            chatTextField.OnTabKey = () =>
            {
                teamChat      ^= true;
                chatLabel.Text = (teamChat) ? "Team:" : "Chat:";
                return(true);
            };

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

            var musicButton = lobby.GetOrNull <ButtonWidget>("MUSIC_BUTTON");

            if (musicButton != null)
            {
                musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
                {
                    { "onExit", () => {} }
                });
            }

            // Add a bot on the first lobbyinfo update
            if (addBots)
            {
                Game.LobbyInfoChanged += WidgetUtils.Once(() =>
                {
                    var slot          = orderManager.LobbyInfo.FirstEmptySlot();
                    var bot           = Rules.Info["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name).FirstOrDefault();
                    var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
                    if (slot != null && bot != null)
                    {
                        orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
                    }
                });
            }
        }
예제 #2
0
        internal LobbyLogic(Widget widget, World world, OrderManager orderManager,
                            Action onExit, Action onStart, bool addBots)
        {
            var lobby = widget;

            this.orderManager = orderManager;
            this.OnGameStart  = () => { CloseWindow(); onStart(); };
            this.onExit       = onExit;

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

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

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

            UpdateCurrentMap();
            Players = lobby.Get <ScrollPanelWidget>("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;

            var mapPreview = lobby.Get <MapPreviewWidget>("MAP_PREVIEW");

            mapPreview.IsVisible    = () => Map != null;
            mapPreview.Map          = () => Map;
            mapPreview.OnMouseDown  = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, Map, mi);
            mapPreview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, Map);

            var mapTitle = lobby.GetOrNull <LabelWidget>("MAP_TITLE");

            if (mapTitle != null)
            {
                mapTitle.IsVisible = () => Map != null;
                mapTitle.GetText   = () => Map.Title;
            }

            var mapType = lobby.GetOrNull <LabelWidget>("MAP_TYPE");

            if (mapType != null)
            {
                mapType.IsVisible = () => Map != null;
                mapType.GetText   = () => Map.Type;
            }

            var mapAuthor = lobby.GetOrNull <LabelWidget>("MAP_AUTHOR");

            if (mapAuthor != null)
            {
                mapAuthor.IsVisible = () => Map != null;
                mapAuthor.GetText   = () => "Created by {0}".F(Map.Author);
            }

            CountryNames = Rules.Info["world"].Traits.WithInterface <CountryInfo>()
                           .Where(c => c.Selectable)
                           .ToDictionary(a => a.Race, a => a.Name);
            CountryNames.Add("random", "Any");

            var gameStarting = false;

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

            mapButton.OnClick = () =>
            {
                var onSelect = new Action <Map>(m =>
                {
                    orderManager.IssueOrder(Order.Command("map " + m.Uid));
                    Game.Settings.Server.Map = m.Uid;
                    Game.Settings.Save();
                });

                Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
                {
                    { "initialMap", Map.Uid },
                    { "onExit", () => {} },
                    { "onSelect", onSelect }
                });
            };
            mapButton.IsVisible = () => mapButton.Visible && Game.IsHost;

            var assignTeams = lobby.GetOrNull <DropDownButtonWidget>("ASSIGNTEAMS_DROPDOWNBUTTON");

            if (assignTeams != null)
            {
                assignTeams.IsVisible  = () => Game.IsHost;
                assignTeams.IsDisabled = () => gameStarting || orderManager.LobbyInfo.Clients.Count(c => c.Slot != null) < 2 ||
                                         orderManager.LocalClient == null || orderManager.LocalClient.IsReady;

                assignTeams.OnMouseDown = _ =>
                {
                    var options = Enumerable.Range(2, orderManager.LobbyInfo.Clients.Count(c => c.Slot != null).Clamp(2, 8) - 1).Select(d => new DropDownOption
                    {
                        Title      = "{0} Teams".F(d),
                        IsSelected = () => false,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("assignteams {0}".F(d.ToString())))
                    });
                    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);
                    };
                    assignTeams.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

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

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

            var allowCheats = lobby.Get <CheckboxWidget>("ALLOWCHEATS_CHECKBOX");

            allowCheats.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
            allowCheats.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null ||
                                     orderManager.LocalClient.IsReady;
            allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command(
                                                                    "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));

            var crates = lobby.GetOrNull <CheckboxWidget>("CRATES_CHECKBOX");

            if (crates != null)
            {
                crates.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Crates;
                crates.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null ||
                                    orderManager.LocalClient.IsReady;        // maybe disable the checkbox if a map forcefully removes CrateDrop?
                crates.OnClick = () => orderManager.IssueOrder(Order.Command(
                                                                   "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
            }

            var fragileAlliance = lobby.GetOrNull <CheckboxWidget>("FRAGILEALLIANCES_CHECKBOX");

            if (fragileAlliance != null)
            {
                fragileAlliance.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances;
                fragileAlliance.IsDisabled = () => !Game.IsHost || gameStarting ||
                                             orderManager.LocalClient == null || orderManager.LocalClient.IsReady;
                fragileAlliance.OnClick = () => orderManager.IssueOrder(Order.Command(
                                                                            "fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances)));
            }
            ;


            var difficulty = lobby.GetOrNull <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");

            if (difficulty != null)
            {
                difficulty.IsVisible   = () => Map != null && Map.Difficulties != null && Map.Difficulties.Any();
                difficulty.IsDisabled  = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null || orderManager.LocalClient.IsReady;
                difficulty.GetText     = () => orderManager.LobbyInfo.GlobalSettings.Difficulty;
                difficulty.OnMouseDown = _ =>
                {
                    var options = Map.Difficulties.Select(d => new DropDownOption
                    {
                        Title      = d,
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("difficulty {0}".F(d)))
                    });
                    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);
                    };
                    difficulty.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

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

            startGameButton.IsVisible  = () => Game.IsHost;
            startGameButton.IsDisabled = () => gameStarting ||
                                         orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
            startGameButton.OnClick = () =>
            {
                gameStarting = true;
                orderManager.IssueOrder(Order.Command("startgame"));
            };

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

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

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

            chatTextField.OnTabKey = () =>
            {
                teamChat      ^= true;
                chatLabel.Text = (teamChat) ? "Team:" : "Chat:";
                return(true);
            };

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

            var musicButton = lobby.GetOrNull <ButtonWidget>("MUSIC_BUTTON");

            if (musicButton != null)
            {
                musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
                {
                    { "onExit", () => {} }
                });
            }

            // Add a bot on the first lobbyinfo update
            if (addBots)
            {
                Game.LobbyInfoChanged += WidgetUtils.Once(() =>
                {
                    var slot          = orderManager.LobbyInfo.FirstEmptySlot();
                    var bot           = Rules.Info["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name).FirstOrDefault();
                    var botController = orderManager.LobbyInfo.Clients.Where(c => c.IsAdmin).FirstOrDefault();
                    if (slot != null && bot != null)
                    {
                        orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
                    }
                });
            }
        }
예제 #3
0
        internal LobbyLogic(Widget widget, WorldRenderer worldRenderer, OrderManager orderManager,
                            Action onExit, Action onStart, bool skirmishMode, Ruleset modRules)
        {
            lobby             = widget;
            this.orderManager = orderManager;
            this.onStart      = onStart;
            this.onExit       = onExit;
            this.skirmishMode = skirmishMode;
            this.modRules     = modRules;
            shellmapWorld     = worldRenderer.World;

            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("LOBBY_MAP_PREVIEW", lobby.Get("MAP_PREVIEW_ROOT"), new WidgetArgs
            {
                { "orderManager", orderManager },
                { "lobby", this }
            });

            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 ||
                                                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 ||
                                         Map.RuleStatus != MapRuleStatus.Cached || !orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam);

                var botNames = modRules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Name);
                slotsButton.OnMouseDown = _ =>
                {
                    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 = botNames.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.RuleStatus != MapRuleStatus.Cached || 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.RuleStatus != MapRuleStatus.Cached ||
                                             orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
                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 allowCheats = optionsBin.GetOrNull <CheckboxWidget>("ALLOWCHEATS_CHECKBOX");

            if (allowCheats != null)
            {
                allowCheats.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
                allowCheats.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Cheats.HasValue || configurationDisabled();
                allowCheats.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                           "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));
            }

            var crates = optionsBin.GetOrNull <CheckboxWidget>("CRATES_CHECKBOX");

            if (crates != null)
            {
                crates.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Crates;
                crates.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Crates.HasValue || configurationDisabled();
                crates.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                      "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
            }

            var creeps = optionsBin.GetOrNull <CheckboxWidget>("CREEPS_CHECKBOX");

            if (creeps != null)
            {
                creeps.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Creeps;
                creeps.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Creeps.HasValue || configurationDisabled();
                creeps.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                      "creeps {0}".F(!orderManager.LobbyInfo.GlobalSettings.Creeps)));
            }

            var allybuildradius = optionsBin.GetOrNull <CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX");

            if (allybuildradius != null)
            {
                allybuildradius.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius;
                allybuildradius.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.AllyBuildRadius.HasValue || configurationDisabled();
                allybuildradius.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                               "allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius)));
            }

            var fragileAlliance = optionsBin.GetOrNull <CheckboxWidget>("FRAGILEALLIANCES_CHECKBOX");

            if (fragileAlliance != null)
            {
                fragileAlliance.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances;
                fragileAlliance.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.FragileAlliances.HasValue || configurationDisabled();
                fragileAlliance.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                               "fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances)));
            }

            var shortGame = optionsBin.GetOrNull <CheckboxWidget>("SHORTGAME_CHECKBOX");

            if (shortGame != null)
            {
                shortGame.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.ShortGame;
                shortGame.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.ShortGame.HasValue || configurationDisabled();
                shortGame.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                         "shortgame {0}".F(!orderManager.LobbyInfo.GlobalSettings.ShortGame)));
            }

            var difficulty = optionsBin.GetOrNull <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");

            if (difficulty != null)
            {
                difficulty.IsVisible   = () => Map.Status == MapStatus.Available && Map.Map.Options.Difficulties.Any();
                difficulty.IsDisabled  = () => Map.Status != MapStatus.Available || configurationDisabled();
                difficulty.GetText     = () => orderManager.LobbyInfo.GlobalSettings.Difficulty;
                difficulty.OnMouseDown = _ =>
                {
                    var options = Map.Map.Options.Difficulties.Select(d => new DropDownOption
                    {
                        Title      = d,
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("difficulty {0}".F(d)))
                    });
                    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);
                    };
                    difficulty.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };

                optionsBin.Get <LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible;
            }

            var startingUnits = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON");

            if (startingUnits != null)
            {
                var startUnitsInfo = modRules.Actors["world"].TraitInfos <MPStartUnitsInfo>();
                var classes        = startUnitsInfo.Select(a => a.Class).Distinct();
                Func <string, string> className = c =>
                {
                    var selectedClass = startUnitsInfo.Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault();
                    return(selectedClass != null ? selectedClass : c);
                };

                startingUnits.IsDisabled = () => Map.Status != MapStatus.Available ||
                                           !Map.Map.Options.ConfigurableStartingUnits || configurationDisabled();
                startingUnits.GetText = () => Map.Status != MapStatus.Available ||
                                        !Map.Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
                startingUnits.OnMouseDown = _ =>
                {
                    var options = classes.Select(c => new DropDownOption
                    {
                        Title      = className(c),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass == c,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("startingunits {0}".F(c)))
                    });

                    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);
                    };

                    startingUnits.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };

                optionsBin.Get <LabelWidget>("STARTINGUNITS_DESC").IsVisible = startingUnits.IsVisible;
            }

            var startingCash = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON");

            if (startingCash != null)
            {
                startingCash.IsDisabled = () => Map.Status != MapStatus.Available ||
                                          Map.Map.Options.StartingCash.HasValue || configurationDisabled();
                startingCash.GetText = () => Map.Status != MapStatus.Available ||
                                       Map.Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
                startingCash.OnMouseDown = _ =>
                {
                    var options = modRules.Actors["player"].TraitInfo <PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
                    {
                        Title      = "${0}".F(c),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingCash == c,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("startingcash {0}".F(c)))
                    });

                    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);
                    };

                    startingCash.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

            var techLevel = optionsBin.GetOrNull <DropDownButtonWidget>("TECHLEVEL_DROPDOWNBUTTON");

            if (techLevel != null)
            {
                var techTraits = modRules.Actors["player"].TraitInfos <ProvidesTechPrerequisiteInfo>().ToList();
                techLevel.IsVisible = () => techTraits.Count > 0;

                var techLevelDescription = optionsBin.GetOrNull <LabelWidget>("TECHLEVEL_DESC");
                if (techLevelDescription != null)
                {
                    techLevelDescription.IsVisible = () => techTraits.Count > 0;
                }

                techLevel.IsDisabled = () => Map.Status != MapStatus.Available ||
                                       Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Count <= 1;
                techLevel.GetText = () => Map.Status != MapStatus.Available ||
                                    Map.Map.Options.TechLevel != null ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel);
                techLevel.OnMouseDown = _ =>
                {
                    var options = techTraits.Select(c => new DropDownOption
                    {
                        Title      = "{0}".F(c.Name),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.TechLevel == c.Name,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("techlevel {0}".F(c.Name)))
                    });

                    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);
                    };

                    techLevel.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

            var gameSpeed = optionsBin.GetOrNull <DropDownButtonWidget>("GAMESPEED_DROPDOWNBUTTON");

            if (gameSpeed != null)
            {
                var speeds = Game.ModData.Manifest.Get <GameSpeeds>().Speeds;

                gameSpeed.IsDisabled = () => Map.Status != MapStatus.Available || configurationDisabled();
                gameSpeed.GetText    = () =>
                {
                    if (Map.Status != MapStatus.Available)
                    {
                        return("Not Available");
                    }

                    GameSpeed speed;
                    if (!speeds.TryGetValue(orderManager.LobbyInfo.GlobalSettings.GameSpeedType, out speed))
                    {
                        return("Unknown");
                    }

                    return(speed.Name);
                };

                gameSpeed.OnMouseDown = _ =>
                {
                    var options = speeds.Select(s => new DropDownOption
                    {
                        Title      = s.Value.Name,
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.GameSpeedType == s.Key,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("gamespeed {0}".F(s.Key)))
                    });

                    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);
                    };

                    gameSpeed.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

            var exploredMap = optionsBin.GetOrNull <CheckboxWidget>("EXPLORED_MAP_CHECKBOX");

            if (exploredMap != null)
            {
                exploredMap.IsChecked  = () => !orderManager.LobbyInfo.GlobalSettings.Shroud;
                exploredMap.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Shroud.HasValue || configurationDisabled();
                exploredMap.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                           "shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud)));
            }

            var enableFog = optionsBin.GetOrNull <CheckboxWidget>("FOG_CHECKBOX");

            if (enableFog != null)
            {
                enableFog.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Fog;
                enableFog.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Fog.HasValue || configurationDisabled();
                enableFog.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                         "fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog)));
            }

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

            disconnectButton.OnClick = () => { 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;

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

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

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

            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)
            {
                Game.LobbyInfoChanged += WidgetUtils.Once(() =>
                {
                    var slot          = orderManager.LobbyInfo.FirstEmptyBotSlot();
                    var bot           = modRules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Name).FirstOrDefault();
                    var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
                    if (slot != null && bot != null)
                    {
                        orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
                    }
                });
            }
        }
예제 #4
0
        internal LobbyLogic(Widget widget, World world, OrderManager orderManager,
                            Action onExit, Action onStart, bool addBots)
        {
            var lobby = widget;

            this.orderManager = orderManager;
            this.OnGameStart  = () => { CloseWindow(); onStart(); };
            this.onExit       = onExit;

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

            UpdateCurrentMap();
            PlayerPalettePreview      = world.WorldActor.Trait <ColorPickerPaletteModifier>();
            PlayerPalettePreview.Ramp = Game.Settings.Player.ColorRamp;
            Players = lobby.GetWidget <ScrollPanelWidget>("PLAYERS");
            EditablePlayerTemplate       = Players.GetWidget("TEMPLATE_EDITABLE_PLAYER");
            NonEditablePlayerTemplate    = Players.GetWidget("TEMPLATE_NONEDITABLE_PLAYER");
            EmptySlotTemplate            = Players.GetWidget("TEMPLATE_EMPTY");
            EditableSpectatorTemplate    = Players.GetWidget("TEMPLATE_EDITABLE_SPECTATOR");
            NonEditableSpectatorTemplate = Players.GetWidget("TEMPLATE_NONEDITABLE_SPECTATOR");
            NewSpectatorTemplate         = Players.GetWidget("TEMPLATE_NEW_SPECTATOR");

            var mapPreview = lobby.GetWidget <MapPreviewWidget>("MAP_PREVIEW");

            mapPreview.IsVisible   = () => Map != null;
            mapPreview.Map         = () => Map;
            mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, Map, mi);
            mapPreview.SpawnColors = () => LobbyUtils.GetSpawnColors(orderManager, Map);

            var mapTitle = lobby.GetWidget <LabelWidget>("MAP_TITLE");

            if (mapTitle != null)
            {
                mapTitle.IsVisible = () => Map != null;
                mapTitle.GetText   = () => Map.Title;
            }

            CountryNames = Rules.Info["world"].Traits.WithInterface <CountryInfo>()
                           .Where(c => c.Selectable)
                           .ToDictionary(a => a.Race, a => a.Name);
            CountryNames.Add("random", "Any");

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

            mapButton.OnClick = () =>
            {
                var onSelect = new Action <Map>(m =>
                {
                    orderManager.IssueOrder(Order.Command("map " + m.Uid));
                    Game.Settings.Server.Map = m.Uid;
                    Game.Settings.Save();
                });

                Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
                {
                    { "initialMap", Map.Uid },
                    { "onExit", () => {} },
                    { "onSelect", onSelect }
                });
            };
            mapButton.IsVisible = () => mapButton.Visible && Game.IsHost;

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

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

            var gameStarting = false;

            var allowCheats = lobby.GetWidget <CheckboxWidget>("ALLOWCHEATS_CHECKBOX");

            allowCheats.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
            allowCheats.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null ||
                                     orderManager.LocalClient.IsReady;
            allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command(
                                                                    "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));

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

            startGameButton.IsVisible  = () => Game.IsHost;
            startGameButton.IsDisabled = () => gameStarting;
            startGameButton.OnClick    = () =>
            {
                gameStarting = true;
                orderManager.IssueOrder(Order.Command("startgame"));
            };

            bool teamChat      = false;
            var  chatLabel     = lobby.GetWidget <LabelWidget>("LABEL_CHATTYPE");
            var  chatTextField = lobby.GetWidget <TextFieldWidget>("CHAT_TEXTFIELD");

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

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

            chatTextField.OnTabKey = () =>
            {
                teamChat      ^= true;
                chatLabel.Text = (teamChat) ? "Team:" : "Chat:";
                return(true);
            };

            chatPanel    = lobby.GetWidget <ScrollPanelWidget>("CHAT_DISPLAY");
            chatTemplate = chatPanel.GetWidget("CHAT_TEMPLATE");
            chatPanel.RemoveChildren();

            var musicButton = lobby.GetWidget <ButtonWidget>("MUSIC_BUTTON");

            if (musicButton != null)
            {
                musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
                {
                    { "onExit", () => {} }
                });
            }

            // Add a bot on the first lobbyinfo update
            if (addBots)
            {
                Game.LobbyInfoChanged += WidgetUtils.Once(() =>
                {
                    var slot = orderManager.LobbyInfo.FirstEmptySlot();
                    var bot  = Rules.Info["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name).FirstOrDefault();
                    if (slot != null && bot != null)
                    {
                        orderManager.IssueOrder(Order.Command("slot_bot {0} {1}".F(slot, bot)));
                    }
                });
            }
        }
예제 #5
0
        internal LobbyLogic(Widget widget, WorldRenderer worldRenderer, OrderManager orderManager,
                            Action onExit, Action onStart, bool skirmishMode, Ruleset modRules)
        {
            lobby             = widget;
            this.orderManager = orderManager;
            this.onStart      = onStart;
            this.onExit       = onExit;
            this.skirmishMode = skirmishMode;
            this.modRules     = modRules;

            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("LOBBY_MAP_PREVIEW", lobby.Get("MAP_PREVIEW_ROOT"), new WidgetArgs
            {
                { "orderManager", orderManager },
                { "lobby", this }
            });

            UpdateCurrentMap();
            players           = Ui.LoadWidget <ScrollPanelWidget>("LOBBY_PLAYER_BIN", lobby.Get("PLAYER_BIN_ROOT"), new WidgetArgs());
            players.IsVisible = () => panel == PanelType.Players;

            var playerBinHeaders = lobby.GetOrNull <ContainerWidget>("LABEL_CONTAINER");

            if (playerBinHeaders != null)
            {
                playerBinHeaders.IsVisible = () => panel == PanelType.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;

            countryNames = modRules.Actors["world"].Traits.WithInterface <CountryInfo>()
                           .Where(c => c.Selectable)
                           .ToDictionary(a => a.Race, a => a.Name);
            countryNames.Add("random", "Any");

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

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

            if (mapButton != null)
            {
                mapButton.IsDisabled = configurationDisabled;
                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 },
                        { "onExit", DoNothing },
                        { "onSelect", onSelect }
                    });
                };
            }

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

            if (slotsButton != null)
            {
                slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players ||
                                         Map.RuleStatus != MapRuleStatus.Cached || !orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam);

                var botNames = modRules.Actors["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name);
                slotsButton.OnMouseDown = _ =>
                {
                    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 = botNames.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, new WidgetArgs());

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

            var optionsButton = lobby.Get <ButtonWidget>("OPTIONS_BUTTON");

            optionsButton.IsDisabled = () => Map.RuleStatus != MapRuleStatus.Cached || panel == PanelType.Kick || panel == PanelType.ForceStart;
            optionsButton.GetText    = () => panel == PanelType.Options ? "Players" : "Options";
            optionsButton.OnClick    = () => panel = (panel == PanelType.Options) ? PanelType.Players : PanelType.Options;

            // 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.RuleStatus != MapRuleStatus.Cached ||
                                             orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null);
                startGameButton.OnClick = () =>
                {
                    Func <KeyValuePair <string, Session.Slot>, bool> notReady = sl =>
                    {
                        var cl = orderManager.LobbyInfo.ClientInSlot(sl.Key);

                        // Bots and admins don't count
                        return(cl != null && !cl.IsAdmin && cl.Bot == null && !cl.IsReady);
                    };

                    if (orderManager.LobbyInfo.Slots.Any(notReady))
                    {
                        panel = PanelType.ForceStart;
                    }
                    else
                    {
                        startGame();
                    }
                };
            }

            var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby, 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 allowCheats = optionsBin.GetOrNull <CheckboxWidget>("ALLOWCHEATS_CHECKBOX");

            if (allowCheats != null)
            {
                allowCheats.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
                allowCheats.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Cheats.HasValue || configurationDisabled();
                allowCheats.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                           "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));
            }

            var crates = optionsBin.GetOrNull <CheckboxWidget>("CRATES_CHECKBOX");

            if (crates != null)
            {
                crates.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Crates;
                crates.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Crates.HasValue || configurationDisabled();
                crates.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                      "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
            }

            var allybuildradius = optionsBin.GetOrNull <CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX");

            if (allybuildradius != null)
            {
                allybuildradius.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius;
                allybuildradius.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.AllyBuildRadius.HasValue || configurationDisabled();
                allybuildradius.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                               "allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius)));
            }

            var fragileAlliance = optionsBin.GetOrNull <CheckboxWidget>("FRAGILEALLIANCES_CHECKBOX");

            if (fragileAlliance != null)
            {
                fragileAlliance.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances;
                fragileAlliance.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.FragileAlliances.HasValue || configurationDisabled();
                fragileAlliance.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                               "fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances)));
            }

            var difficulty = optionsBin.GetOrNull <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");

            if (difficulty != null)
            {
                difficulty.IsVisible   = () => Map.Status == MapStatus.Available && Map.Map.Options.Difficulties.Any();
                difficulty.IsDisabled  = () => Map.Status != MapStatus.Available || configurationDisabled();
                difficulty.GetText     = () => orderManager.LobbyInfo.GlobalSettings.Difficulty;
                difficulty.OnMouseDown = _ =>
                {
                    var options = Map.Map.Options.Difficulties.Select(d => new DropDownOption
                    {
                        Title      = d,
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("difficulty {0}".F(d)))
                    });
                    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);
                    };
                    difficulty.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };

                optionsBin.Get <LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible;
            }

            var startingUnits = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON");

            if (startingUnits != null)
            {
                var startUnitsInfo = modRules.Actors["world"].Traits.WithInterface <MPStartUnitsInfo>();
                var classes        = startUnitsInfo.Select(a => a.Class).Distinct();
                Func <string, string> className = c =>
                {
                    var selectedClass = startUnitsInfo.Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault();
                    return(selectedClass != null ? selectedClass : c);
                };

                startingUnits.IsDisabled  = () => Map.Status != MapStatus.Available || !Map.Map.Options.ConfigurableStartingUnits || configurationDisabled();
                startingUnits.GetText     = () => Map.Status != MapStatus.Available || !Map.Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
                startingUnits.OnMouseDown = _ =>
                {
                    var options = classes.Select(c => new DropDownOption
                    {
                        Title      = className(c),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass == c,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("startingunits {0}".F(c)))
                    });

                    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);
                    };

                    startingUnits.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };

                optionsBin.Get <LabelWidget>("STARTINGUNITS_DESC").IsVisible = startingUnits.IsVisible;
            }

            var startingCash = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON");

            if (startingCash != null)
            {
                startingCash.IsDisabled  = () => Map.Status != MapStatus.Available || Map.Map.Options.StartingCash.HasValue || configurationDisabled();
                startingCash.GetText     = () => Map.Status != MapStatus.Available || Map.Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
                startingCash.OnMouseDown = _ =>
                {
                    var options = modRules.Actors["player"].Traits.Get <PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
                    {
                        Title      = "${0}".F(c),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingCash == c,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("startingcash {0}".F(c)))
                    });

                    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);
                    };

                    startingCash.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

            var techLevel = optionsBin.GetOrNull <DropDownButtonWidget>("TECHLEVEL_DROPDOWNBUTTON");

            if (techLevel != null)
            {
                var techTraits = modRules.Actors["player"].Traits.WithInterface <ProvidesTechPrerequisiteInfo>().ToArray();
                techLevel.IsVisible = () => techTraits.Length > 0;
                optionsBin.GetOrNull <LabelWidget>("TECHLEVEL_DESC").IsVisible = () => techTraits.Length > 0;
                techLevel.IsDisabled  = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Length <= 1;
                techLevel.GetText     = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel);
                techLevel.OnMouseDown = _ =>
                {
                    var options = techTraits.Select(c => new DropDownOption
                    {
                        Title      = "{0}".F(c.Name),
                        IsSelected = () => orderManager.LobbyInfo.GlobalSettings.TechLevel == c.Name,
                        OnClick    = () => orderManager.IssueOrder(Order.Command("techlevel {0}".F(c.Name)))
                    });

                    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);
                    };

                    techLevel.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
                };
            }

            var enableShroud = optionsBin.GetOrNull <CheckboxWidget>("SHROUD_CHECKBOX");

            if (enableShroud != null)
            {
                enableShroud.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Shroud;
                enableShroud.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Shroud.HasValue || configurationDisabled();
                enableShroud.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                            "shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud)));
            }

            var enableFog = optionsBin.GetOrNull <CheckboxWidget>("FOG_CHECKBOX");

            if (enableFog != null)
            {
                enableFog.IsChecked  = () => orderManager.LobbyInfo.GlobalSettings.Fog;
                enableFog.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.Fog.HasValue || configurationDisabled();
                enableFog.OnClick    = () => orderManager.IssueOrder(Order.Command(
                                                                         "fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog)));
            }

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

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

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

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

            chatTextField.TakeKeyboardFocus();

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

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

                orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text));
                chatTextField.Text = "";
                return(true);
            };
            chatTextField.OnAltKey = () =>
            {
                teamChat      ^= true;
                chatLabel.Text = teamChat ? "Team:" : "Chat:";
                return(true);
            };
            chatTextField.OnTabKey = () =>
            {
                chatTextField.Text           = tabCompletion.Complete(chatTextField.Text);
                chatTextField.CursorPosition = chatTextField.Text.Length;
                return(true);
            };

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

            var musicButton = lobby.GetOrNull <ButtonWidget>("MUSIC_BUTTON");

            if (musicButton != null)
            {
                musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs
                {
                    { "onExit", DoNothing },
                    { "world", orderManager.world }
                });
            }

            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)
            {
                Game.LobbyInfoChanged += WidgetUtils.Once(() =>
                {
                    var slot          = orderManager.LobbyInfo.FirstEmptyBotSlot();
                    var bot           = modRules.Actors["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name).FirstOrDefault();
                    var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
                    if (slot != null && bot != null)
                    {
                        orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
                    }
                });
            }
        }