public static void AddPlayerFlagAndName(ScrollItemWidget template, Player player) { var flag = template.Get<ImageWidget>("FLAG"); flag.GetImageCollection = () => "flags"; if (player.World.RenderPlayer != null && player.World.RenderPlayer.Stances[player] != Stance.Ally) flag.GetImageName = () => player.DisplayFaction.InternalName; else flag.GetImageName = () => player.Faction.InternalName; var client = player.World.LobbyInfo.ClientWithIndex(player.ClientIndex); var playerName = template.Get<LabelWidget>("PLAYER"); var playerNameFont = Game.Renderer.Fonts[playerName.Font]; var suffixLength = new CachedTransform<string, int>(s => playerNameFont.Measure(s).X); var name = new CachedTransform<Pair<string, int>, string>(c => WidgetUtils.TruncateText(c.First, playerName.Bounds.Width - c.Second, playerNameFont)); playerName.GetText = () => { var suffix = player.WinState == WinState.Undefined ? "" : " (" + player.WinState + ")"; if (client != null && client.State == Session.ClientState.Disconnected) suffix = " (Gone)"; var sl = suffixLength.Update(suffix); return name.Update(Pair.New(player.PlayerName, sl)) + suffix; }; playerName.GetColor = () => player.Color.RGB; }
public ReplayBrowserLogic(Widget widget, Action onExit, Action onStart) { panel = widget; this.onStart = onStart; playerList = panel.Get<ScrollPanelWidget>("PLAYER_LIST"); playerHeader = playerList.Get<ScrollItemWidget>("HEADER"); playerTemplate = playerList.Get<ScrollItemWidget>("TEMPLATE"); playerList.RemoveChildren(); panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => { cancelLoadingReplays = true; Ui.CloseWindow(); onExit(); }; replayList = panel.Get<ScrollPanelWidget>("REPLAY_LIST"); var template = panel.Get<ScrollItemWidget>("REPLAY_TEMPLATE"); var mod = Game.ModData.Manifest.Mod; var dir = Platform.ResolvePath("^", "Replays", mod.Id, mod.Version); if (Directory.Exists(dir)) ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template)); var watch = panel.Get<ButtonWidget>("WATCH_BUTTON"); watch.IsDisabled = () => selectedReplay == null || selectedReplay.GameInfo.MapPreview.Status != MapStatus.Available; watch.OnClick = () => { WatchReplay(); }; panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null; var preview = panel.Get<MapPreviewWidget>("MAP_PREVIEW"); preview.SpawnOccupants = () => selectedSpawns; preview.Preview = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview : null; var titleLabel = panel.GetOrNull<LabelWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.IsVisible = () => selectedReplay != null; var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform<MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(selectedReplay.GameInfo.MapPreview); } var type = panel.GetOrNull<LabelWidget>("MAP_TYPE"); if (type != null) type.GetText = () => selectedReplay.GameInfo.MapPreview.Type; panel.Get<LabelWidget>("DURATION").GetText = () => WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds); SetupFilters(); SetupManagement(); }
public SimpleProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Player player, Func <ProductionIcon> getTooltipIcon) { var world = player.World; var mapRules = world.Map.Rules; widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Actor != null; var nameLabel = widget.Get <LabelWidget>("NAME"); var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY"); var requiresLabel = widget.Get <LabelWidget>("REQUIRES"); var timeLabel = widget.Get <LabelWidget>("TIME"); var timeIcon = widget.Get <ImageWidget>("TIME_ICON"); var descLabel = widget.Get <LabelWidget>("DESC"); var iconMargin = timeIcon.Bounds.X; var font = Game.Renderer.Fonts[nameLabel.Font]; var descFont = Game.Renderer.Fonts[descLabel.Font]; var requiresFont = Game.Renderer.Fonts[requiresLabel.Font]; var formatBuildTime = new CachedTransform <int, string>(time => WidgetUtils.FormatTime(time, world.Timestep)); var requiresFormat = requiresLabel.Text; ActorInfo lastActor = null; Hotkey lastHotkey = Hotkey.Invalid; var descLabelY = descLabel.Bounds.Y; var descLabelPadding = descLabel.Bounds.Height; tooltipContainer.BeforeRender = () => { var tooltipIcon = getTooltipIcon(); if (tooltipIcon == null) { return; } var actor = tooltipIcon.Actor; if (actor == null) { return; } var hotkey = tooltipIcon.Hotkey != null?tooltipIcon.Hotkey.GetValue() : Hotkey.Invalid; if (actor == lastActor && hotkey == lastHotkey) { return; } var tooltip = actor.TraitInfos <TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault); var name = tooltip != null ? tooltip.Name : actor.Name; var buildable = actor.TraitInfo <BuildableInfo>(); var cost = 0; if (tooltipIcon.ProductionQueue != null) { cost = tooltipIcon.ProductionQueue.GetProductionCost(actor); } else { var valued = actor.TraitInfoOrDefault <ValuedInfo>(); if (valued != null) { cost = valued.Cost; } } nameLabel.Text = name; var nameSize = font.Measure(name); var hotkeyWidth = 0; hotkeyLabel.Visible = hotkey.IsValid(); if (hotkeyLabel.Visible) { var hotkeyText = "({0})".F(hotkey.DisplayString()); hotkeyWidth = font.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; hotkeyLabel.Text = hotkeyText; hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X; } var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a)) .Where(s => !s.StartsWith("~", StringComparison.Ordinal) && !s.StartsWith("!", StringComparison.Ordinal)); var requiresSize = int2.Zero; if (prereqs.Any()) { requiresLabel.Text = requiresFormat.F(prereqs.JoinWith(", ")); requiresSize = requiresFont.Measure(requiresLabel.Text); requiresLabel.Visible = true; descLabel.Bounds.Y = descLabelY + requiresLabel.Bounds.Height; } else { requiresLabel.Visible = false; descLabel.Bounds.Y = descLabelY; } var buildTime = tooltipIcon.ProductionQueue == null ? 0 : tooltipIcon.ProductionQueue.GetBuildTime(actor, buildable); var timeModifier = tooltipIcon.ProductionQueue.Info.LowPowerModifier; timeLabel.Text = formatBuildTime.Update(buildTime * timeModifier / 100); timeLabel.TextColor = tooltipIcon.ProductionQueue.Info.LowPowerModifier > 100 ? Color.Red : Color.White; var timeSize = font.Measure(timeLabel.Text); descLabel.Text = buildable.Description.Replace("\\n", "\n"); var descSize = descFont.Measure(descLabel.Text); descLabel.Bounds.Width = descSize.X; descLabel.Bounds.Height = descSize.Y + descLabelPadding; var leftWidth = new[] { nameSize.X + hotkeyWidth, requiresSize.X, descSize.X }.Aggregate(Math.Max); var rightWidth = new[] { timeSize.X }.Aggregate(Math.Max); timeIcon.Bounds.X = leftWidth + 2 * nameLabel.Bounds.X; timeLabel.Bounds.X = timeIcon.Bounds.Right + iconMargin; widget.Bounds.Width = leftWidth + rightWidth + 3 * nameLabel.Bounds.X + timeIcon.Bounds.Width + iconMargin; // Set the bottom margin to match the left margin var leftHeight = descLabel.Bounds.Bottom + descLabel.Bounds.X; // Set the bottom margin to match the top margin var rightHeight = timeIcon.Bounds.Bottom; widget.Bounds.Height = Math.Max(leftHeight, rightHeight); lastActor = actor; lastHotkey = hotkey; }; }
ScrollItemWidget BasicStats(Player player) { basicStatsHeaders.Visible = true; var template = SetupPlayerScrollItemWidget(basicPlayerTemplate, player); AddPlayerFlagAndName(template, player); var playerName = template.Get <LabelWidget>("PLAYER"); playerName.GetColor = () => Color.White; var playerColor = template.Get <ColorBlockWidget>("PLAYER_COLOR"); var playerGradient = template.Get <GradientColorBlockWidget>("PLAYER_GRADIENT"); SetupPlayerColor(player, template, playerColor, playerGradient); var res = player.PlayerActor.Trait <PlayerResources>(); var cashText = new CachedTransform <int, string>(i => "$" + i); template.Get <LabelWidget>("CASH").GetText = () => cashText.Update(res.Cash + res.Resources); var powerRes = player.PlayerActor.TraitOrDefault <PowerManager>(); if (powerRes != null) { var power = template.Get <LabelWidget>("POWER"); var powerText = new CachedTransform <Pair <int, int>, string>(p => p.First + "/" + p.Second); power.GetText = () => powerText.Update(new Pair <int, int>(powerRes.PowerDrained, powerRes.PowerProvided)); power.GetColor = () => GetPowerColor(powerRes.PowerState); } var stats = player.PlayerActor.TraitOrDefault <PlayerStatistics>(); if (stats == null) { return(template); } var killsText = new CachedTransform <int, string>(i => i.ToString()); template.Get <LabelWidget>("KILLS").GetText = () => killsText.Update(stats.UnitsKilled + stats.BuildingsKilled); var deathsText = new CachedTransform <int, string>(i => i.ToString()); template.Get <LabelWidget>("DEATHS").GetText = () => deathsText.Update(stats.UnitsDead + stats.BuildingsDead); var destroyedText = new CachedTransform <int, string>(i => "$" + i); template.Get <LabelWidget>("ASSETS_DESTROYED").GetText = () => destroyedText.Update(stats.KillsCost); var lostText = new CachedTransform <int, string>(i => "$" + i); template.Get <LabelWidget>("ASSETS_LOST").GetText = () => lostText.Update(stats.DeathsCost); var experienceText = new CachedTransform <int, string>(i => i.ToString()); template.Get <LabelWidget>("EXPERIENCE").GetText = () => experienceText.Update(stats.Experience); var actionsText = new CachedTransform <double, string>(d => AverageOrdersPerMinute(d)); template.Get <LabelWidget>("ACTIONS_MIN").GetText = () => actionsText.Update(stats.OrderCount); return(template); }
void RebuildOptions() { if (mapPreview == null || mapPreview.Rules == null || mapPreview.InvalidCustomRules) { return; } optionsContainer.RemoveChildren(); optionsContainer.Bounds.Height = 0; var allOptions = mapPreview.Rules.Actors["player"].TraitInfos <ILobbyOptions>() .Concat(mapPreview.Rules.Actors["world"].TraitInfos <ILobbyOptions>()) .SelectMany(t => t.LobbyOptions(mapPreview.Rules)) .Where(o => o.IsVisible) .OrderBy(o => o.DisplayOrder) .ToArray(); Widget row = null; var checkboxColumns = new Queue <CheckboxWidget>(); var dropdownColumns = new Queue <DropDownButtonWidget>(); foreach (var option in allOptions.Where(o => o is LobbyBooleanOption)) { if (!checkboxColumns.Any()) { row = checkboxRowTemplate.Clone(); row.Bounds.Y = optionsContainer.Bounds.Height; optionsContainer.Bounds.Height += row.Bounds.Height; foreach (var child in row.Children) { if (child is CheckboxWidget) { checkboxColumns.Enqueue((CheckboxWidget)child); } } optionsContainer.AddChild(row); } var checkbox = checkboxColumns.Dequeue(); var optionValue = new CachedTransform <Session.Global, Session.LobbyOptionState>( gs => gs.LobbyOptions[option.Id]); checkbox.GetText = () => option.Name; if (option.Description != null) { checkbox.GetTooltipText = () => option.Description; } checkbox.IsVisible = () => true; checkbox.IsChecked = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsEnabled; checkbox.IsDisabled = () => configurationDisabled() || optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsLocked; checkbox.OnClick = () => orderManager.IssueOrder(Order.Command( "option {0} {1}".F(option.Id, !optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsEnabled))); } foreach (var option in allOptions.Where(o => !(o is LobbyBooleanOption))) { if (!dropdownColumns.Any()) { row = dropdownRowTemplate.Clone() as Widget; row.Bounds.Y = optionsContainer.Bounds.Height; optionsContainer.Bounds.Height += row.Bounds.Height; foreach (var child in row.Children) { if (child is DropDownButtonWidget) { dropdownColumns.Enqueue((DropDownButtonWidget)child); } } optionsContainer.AddChild(row); } var dropdown = dropdownColumns.Dequeue(); var optionValue = new CachedTransform <Session.Global, Session.LobbyOptionState>( gs => gs.LobbyOptions[option.Id]); var getOptionLabel = new CachedTransform <string, string>(id => { string value; if (id == null || !option.Values.TryGetValue(id, out value)) { return("Not Available"); } return(value); }); dropdown.GetText = () => getOptionLabel.Update(optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value); if (option.Description != null) { dropdown.GetTooltipText = () => option.Description; } dropdown.IsVisible = () => true; dropdown.IsDisabled = () => configurationDisabled() || optionValue.Update(orderManager.LobbyInfo.GlobalSettings).IsLocked; dropdown.OnMouseDown = _ => { Func <KeyValuePair <string, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (c, template) => { Func <bool> isSelected = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value == c.Key; Action onClick = () => orderManager.IssueOrder(Order.Command("option {0} {1}".F(option.Id, c.Key))); var item = ScrollItemWidget.Setup(template, isSelected, onClick); item.Get <LabelWidget>("LABEL").GetText = () => c.Value; return(item); }; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", option.Values.Count() * 30, option.Values, setupItem); }; var label = row.GetOrNull <LabelWidget>(dropdown.Id + "_DESC"); if (label != null) { label.GetText = () => option.Name; label.IsVisible = () => true; } } panel.ContentHeight = yMargin + optionsContainer.Bounds.Height; optionsContainer.Bounds.Y = yMargin; if (panel.ContentHeight < panel.Bounds.Height) { optionsContainer.Bounds.Y += (panel.Bounds.Height - panel.ContentHeight) / 2; } panel.ScrollToTop(); }
public IntroductionPromptLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, Action onComplete) { var ps = Game.Settings.Player; var ds = Game.Settings.Graphics; var gs = Game.Settings.Game; var escPressed = false; var nameTextfield = widget.Get <TextFieldWidget>("PLAYERNAME"); nameTextfield.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name); nameTextfield.OnLoseFocus = () => { if (escPressed) { escPressed = false; return; } nameTextfield.Text = nameTextfield.Text.Trim(); if (nameTextfield.Text.Length == 0) { nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name); } else { nameTextfield.Text = Settings.SanitizedPlayerName(nameTextfield.Text); ps.Name = nameTextfield.Text; } }; nameTextfield.OnEnterKey = () => { nameTextfield.YieldKeyboardFocus(); return(true); }; nameTextfield.OnEscKey = () => { nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name); escPressed = true; nameTextfield.YieldKeyboardFocus(); return(true); }; var colorPreview = widget.Get <ColorPreviewManagerWidget>("COLOR_MANAGER"); colorPreview.Color = ps.Color; var mouseControlDescClassic = widget.Get("MOUSE_CONTROL_DESC_CLASSIC"); mouseControlDescClassic.IsVisible = () => gs.UseClassicMouseStyle; var mouseControlDescModern = widget.Get("MOUSE_CONTROL_DESC_MODERN"); mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle; var mouseControlDropdown = widget.Get <DropDownButtonWidget>("MOUSE_CONTROL_DROPDOWN"); mouseControlDropdown.OnMouseDown = _ => InputSettingsLogic.ShowMouseControlDropdown(mouseControlDropdown, gs); mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern }) { var classicScrollRight = container.Get("DESC_SCROLL_RIGHT"); classicScrollRight.IsVisible = () => gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton; var classicScrollMiddle = container.Get("DESC_SCROLL_MIDDLE"); classicScrollMiddle.IsVisible = () => !gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton; var zoomDesc = container.Get("DESC_ZOOM"); zoomDesc.IsVisible = () => gs.ZoomModifier == Modifiers.None; var zoomDescModifier = container.Get <LabelWidget>("DESC_ZOOM_MODIFIER"); zoomDescModifier.IsVisible = () => gs.ZoomModifier != Modifiers.None; var zoomDescModifierTemplate = zoomDescModifier.Text; var zoomDescModifierLabel = new CachedTransform <Modifiers, string>( mod => zoomDescModifierTemplate.Replace("MODIFIER", mod.ToString())); zoomDescModifier.GetText = () => zoomDescModifierLabel.Update(gs.ZoomModifier); var edgescrollDesc = container.Get <LabelWidget>("DESC_EDGESCROLL"); edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll; } SettingsUtils.BindCheckboxPref(widget, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll"); var colorDropdown = widget.Get <DropDownButtonWidget>("PLAYERCOLOR"); colorDropdown.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, worldRenderer.World); colorDropdown.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => ps.Color; var viewportSizes = modData.Manifest.Get <WorldViewportSizes>(); var battlefieldCameraDropDown = widget.Get <DropDownButtonWidget>("BATTLEFIELD_CAMERA_DROPDOWN"); var battlefieldCameraLabel = new CachedTransform <WorldViewport, string>(vs => DisplaySettingsLogic.ViewportSizeNames[vs]); battlefieldCameraDropDown.OnMouseDown = _ => DisplaySettingsLogic.ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); var uiScaleDropdown = widget.Get <DropDownButtonWidget>("UI_SCALE_DROPDOWN"); var uiScaleLabel = new CachedTransform <float, string>(s => "{0}%".F((int)(100 * s))); uiScaleDropdown.OnMouseDown = _ => DisplaySettingsLogic.ShowUIScaleDropdown(uiScaleDropdown, ds); uiScaleDropdown.GetText = () => uiScaleLabel.Update(ds.UIScale); var minResolution = viewportSizes.MinEffectiveResolution; var resolution = Game.Renderer.Resolution; var disableUIScale = worldRenderer.World.Type != WorldType.Shellmap || resolution.Width * ds.UIScale < 1.25f * minResolution.Width || resolution.Height * ds.UIScale < 1.25f * minResolution.Height; uiScaleDropdown.IsDisabled = () => disableUIScale; SettingsUtils.BindCheckboxPref(widget, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble"); widget.Get <ButtonWidget>("CONTINUE_BUTTON").OnClick = () => { Game.Settings.Game.IntroductionPromptVersion = IntroductionVersion; Game.Settings.Save(); Ui.CloseWindow(); onComplete(); }; }
internal LobbyLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, OrderManager orderManager, Action onExit, Action onStart, bool skirmishMode) { Map = MapCache.UnknownMap; lobby = widget; this.modData = modData; this.orderManager = orderManager; this.onStart = onStart; this.onExit = onExit; this.skirmishMode = skirmishMode; // TODO: This needs to be reworked to support per-map tech levels, bots, etc. this.modRules = modData.DefaultRules; shellmapWorld = worldRenderer.World; 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 || !Map.RulesLoaded || Map.InvalidCustomRules || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; var mapButton = lobby.GetOrNull <ButtonWidget>("CHANGEMAP_BUTTON"); if (mapButton != null) { mapButton.IsDisabled = () => gameStarting || panel == PanelType.Kick || panel == PanelType.ForceStart || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; mapButton.OnClick = () => { var onSelect = new Action <string>(uid => { // Don't select the same map again if (uid == Map.Uid) { return; } orderManager.IssueOrder(Order.Command("map " + uid)); Game.Settings.Server.Map = uid; Game.Settings.Save(); }); Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", Map.Uid }, { "initialTab", MapClassification.System }, { "onExit", DoNothing }, { "onSelect", Game.IsHost ? onSelect : null }, { "filter", MapVisibility.Lobby }, }); }; } var slotsButton = lobby.GetOrNull <DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON"); if (slotsButton != null) { slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players || (orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) && orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0); slotsButton.OnMouseDown = _ => { var botNames = Map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Name); 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.RulesLoaded || Map.InvalidCustomRules || panel == PanelType.Kick || panel == PanelType.ForceStart; optionsTab.OnClick = () => panel = PanelType.Options; var playersTab = lobby.Get <ButtonWidget>("PLAYERS_TAB"); playersTab.IsHighlighted = () => panel == PanelType.Players; playersTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; playersTab.OnClick = () => panel = PanelType.Players; var musicTab = lobby.Get <ButtonWidget>("MUSIC_TAB"); musicTab.IsHighlighted = () => panel == PanelType.Music; musicTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; musicTab.OnClick = () => panel = PanelType.Music; // Force start panel Action startGame = () => { gameStarting = true; orderManager.IssueOrder(Order.Command("startgame")); }; var startGameButton = lobby.GetOrNull <ButtonWidget>("START_GAME_BUTTON"); if (startGameButton != null) { startGameButton.IsDisabled = () => configurationDisabled() || Map.Status != MapStatus.Available || orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) || (!orderManager.LobbyInfo.GlobalSettings.EnableSingleplayer && orderManager.LobbyInfo.IsSinglePlayer); startGameButton.OnClick = () => { // Bots and admins don't count if (orderManager.LobbyInfo.Clients.Any(c => c.Slot != null && !c.IsAdmin && c.Bot == null && !c.IsReady)) { panel = PanelType.ForceStart; } else { startGame(); } }; } var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs()); forceStartBin.IsVisible = () => panel == PanelType.ForceStart; forceStartBin.Get("KICK_WARNING").IsVisible = () => orderManager.LobbyInfo.Clients.Any(c => c.IsInvalid); forceStartBin.Get <ButtonWidget>("OK_BUTTON").OnClick = startGame; forceStartBin.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players; // Options panel var optionCheckboxes = new Dictionary <string, string>() { { "EXPLORED_MAP_CHECKBOX", "explored" }, { "CRATES_CHECKBOX", "crates" }, { "SHORTGAME_CHECKBOX", "shortgame" }, { "FOG_CHECKBOX", "fog" }, { "ALLYBUILDRADIUS_CHECKBOX", "allybuild" }, { "ALLOWCHEATS_CHECKBOX", "cheats" }, { "CREEPS_CHECKBOX", "creeps" }, }; foreach (var kv in optionCheckboxes) { var checkbox = optionsBin.GetOrNull <CheckboxWidget>(kv.Key); if (checkbox != null) { var option = new CachedTransform <Session.Global, Session.LobbyOptionState>( gs => gs.LobbyOptions[kv.Value]); var visible = new CachedTransform <Session.Global, bool>( gs => gs.LobbyOptions.ContainsKey(kv.Value)); checkbox.IsVisible = () => visible.Update(orderManager.LobbyInfo.GlobalSettings); checkbox.IsChecked = () => option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled; checkbox.IsDisabled = () => configurationDisabled() || option.Update(orderManager.LobbyInfo.GlobalSettings).Locked; checkbox.OnClick = () => orderManager.IssueOrder(Order.Command( "option {0} {1}".F(kv.Value, !option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled))); } } var optionDropdowns = new Dictionary <string, string>() { { "TECHLEVEL", "techlevel" }, { "STARTINGUNITS", "startingunits" }, { "STARTINGCASH", "startingcash" }, { "DIFFICULTY", "difficulty" }, { "GAMESPEED", "gamespeed" } }; var allOptions = new CachedTransform <MapPreview, LobbyOption[]>( map => map.Rules.Actors["player"].TraitInfos <ILobbyOptions>() .Concat(map.Rules.Actors["world"].TraitInfos <ILobbyOptions>()) .SelectMany(t => t.LobbyOptions(map.Rules)) .ToArray()); foreach (var kv in optionDropdowns) { var dropdown = optionsBin.GetOrNull <DropDownButtonWidget>(kv.Key + "_DROPDOWNBUTTON"); if (dropdown != null) { var optionValue = new CachedTransform <Session.Global, Session.LobbyOptionState>( gs => gs.LobbyOptions[kv.Value]); var option = new CachedTransform <MapPreview, LobbyOption>( map => allOptions.Update(map).FirstOrDefault(o => o.Id == kv.Value)); var getOptionLabel = new CachedTransform <string, string>(id => { string value; if (id == null || !option.Update(Map).Values.TryGetValue(id, out value)) { return("Not Available"); } return(value); }); dropdown.GetText = () => getOptionLabel.Update(optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value); dropdown.IsVisible = () => option.Update(Map) != null; dropdown.IsDisabled = () => configurationDisabled() || optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Locked; dropdown.OnMouseDown = _ => { Func <KeyValuePair <string, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (c, template) => { Func <bool> isSelected = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value == c.Key; Action onClick = () => orderManager.IssueOrder(Order.Command("option {0} {1}".F(kv.Value, c.Key))); var item = ScrollItemWidget.Setup(template, isSelected, onClick); item.Get <LabelWidget>("LABEL").GetText = () => c.Value; return(item); }; var options = option.Update(Map).Values; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; var label = optionsBin.GetOrNull(kv.Key + "_DESC"); if (label != null) { label.IsVisible = () => option.Update(Map) != null; } } } var disconnectButton = lobby.Get <ButtonWidget>("DISCONNECT_BUTTON"); disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); }; if (skirmishMode) { disconnectButton.Text = "Back"; } var globalChat = Game.LoadWidget(null, "LOBBY_GLOBALCHAT_PANEL", lobby.Get("GLOBALCHAT_ROOT"), new WidgetArgs()); var globalChatInput = globalChat.Get <TextFieldWidget>("CHAT_TEXTFIELD"); globalChat.IsVisible = () => chatPanel == ChatPanelType.Global; var globalChatTab = lobby.Get <ButtonWidget>("GLOBALCHAT_TAB"); globalChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Global; globalChatTab.OnClick = () => { chatPanel = ChatPanelType.Global; globalChatInput.TakeKeyboardFocus(); }; var globalChatLabel = globalChatTab.Text; globalChatTab.GetText = () => { if (globalChatUnreadMessages == 0 || chatPanel == ChatPanelType.Global) { return(globalChatLabel); } return(globalChatLabel + " ({0})".F(globalChatUnreadMessages)); }; globalChatLastReadMessages = Game.GlobalChat.History.Count(m => m.Type == ChatMessageType.Message); var lobbyChat = lobby.Get("LOBBYCHAT"); lobbyChat.IsVisible = () => chatPanel == ChatPanelType.Lobby; chatLabel = lobby.Get <LabelWidget>("LABEL_CHATTYPE"); var chatTextField = lobby.Get <TextFieldWidget>("CHAT_TEXTFIELD"); chatTextField.TakeKeyboardFocus(); chatTextField.OnEnterKey = () => { if (chatTextField.Text.Length == 0) { return(true); } // Always scroll to bottom when we've typed something lobbyChatPanel.ScrollToBottom(); orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); chatTextField.Text = ""; return(true); }; chatTextField.OnTabKey = () => { var previousText = chatTextField.Text; chatTextField.Text = tabCompletion.Complete(chatTextField.Text); chatTextField.CursorPosition = chatTextField.Text.Length; if (chatTextField.Text == previousText) { return(SwitchTeamChat()); } else { return(true); } }; chatTextField.OnEscKey = () => { chatTextField.Text = ""; return(true); }; var lobbyChatTab = lobby.Get <ButtonWidget>("LOBBYCHAT_TAB"); lobbyChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Lobby; lobbyChatTab.OnClick = () => { chatPanel = ChatPanelType.Lobby; chatTextField.TakeKeyboardFocus(); }; var lobbyChatLabel = lobbyChatTab.Text; lobbyChatTab.GetText = () => { if (lobbyChatUnreadMessages == 0 || chatPanel == ChatPanelType.Lobby) { return(lobbyChatLabel); } return(lobbyChatLabel + " ({0})".F(lobbyChatUnreadMessages)); }; lobbyChatPanel = lobby.Get <ScrollPanelWidget>("CHAT_DISPLAY"); chatTemplate = lobbyChatPanel.Get("CHAT_TEMPLATE"); lobbyChatPanel.RemoveChildren(); var settingsButton = lobby.GetOrNull <ButtonWidget>("SETTINGS_BUTTON"); if (settingsButton != null) { settingsButton.OnClick = () => Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs { { "onExit", DoNothing }, { "worldRenderer", worldRenderer } }); } // Add a bot on the first lobbyinfo update if (skirmishMode) { addBotOnMapLoad = true; } }
public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer) { world = worldRenderer.World; this.modData = modData; panel = widget; var colorPickerPalettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserColorPickerPalettes>() .SelectMany(p => p.ColorPickerPaletteNames) .ToArray(); palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>() .SelectMany(p => p.PaletteNames) .Concat(colorPickerPalettes) .ToArray(); var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER"); if (ticker != null) { ticker.OnTick = () => { if (animateFrames && currentSprites != null) { SelectNextFrame(); } }; } var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR"); if (sourceDropdown != null) { sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown); var sourceName = new CachedTransform <IReadOnlyPackage, string>(GetSourceDisplayName); sourceDropdown.GetText = () => sourceName.Update(assetSource); } var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE"); if (spriteWidget != null) { spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null; currentPalette = spriteWidget.Palette; spriteScale = spriteWidget.Scale; spriteWidget.GetPalette = () => currentPalette; spriteWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentSprites != null; spriteWidget.GetScale = () => spriteScale; } var playerWidget = panel.GetOrNull <VideoPlayerWidget>("PLAYER"); if (playerWidget != null) { playerWidget.IsVisible = () => isVideoLoaded && !isLoadError; } var modelWidget = panel.GetOrNull <ModelWidget>("VOXEL"); if (modelWidget != null) { modelWidget.GetVoxel = () => currentVoxel; currentPalette = modelWidget.Palette; modelScale = modelWidget.Scale; modelWidget.GetPalette = () => currentPalette; modelWidget.GetPlayerPalette = () => currentPalette; modelWidget.GetRotation = () => modelOrientation; modelWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentVoxel != null; modelWidget.GetScale = () => modelScale; } var errorLabelWidget = panel.GetOrNull("ERROR"); if (errorLabelWidget != null) { errorLabelWidget.IsVisible = () => isLoadError; } var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR"); if (paletteDropDown != null) { paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown); paletteDropDown.GetText = () => currentPalette; paletteDropDown.IsVisible = () => currentSprites != null || currentVoxel != null; panel.GetOrNull <LabelWidget>("PALETTE_DESC").IsVisible = () => currentSprites != null || currentVoxel != null; } var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>(); colorManager.Color = Game.Settings.Player.Color; var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR"); if (colorDropdown != null) { colorDropdown.IsDisabled = () => !colorPickerPalettes.Contains(currentPalette); colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorManager, worldRenderer); colorDropdown.IsVisible = () => currentSprites != null || currentVoxel != null; panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => colorManager.Color; } filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT"); filenameInput.OnTextEdited = () => ApplyFilter(); filenameInput.OnEscKey = _ => { if (string.IsNullOrEmpty(filenameInput.Text)) { filenameInput.YieldKeyboardFocus(); } else { filenameInput.Text = ""; filenameInput.OnTextEdited(); } return(true); }; var frameContainer = panel.GetOrNull("FRAME_SELECTOR"); if (frameContainer != null) { frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) || (isVideoLoaded && player != null && player.Video != null && player.Video.FrameCount > 1) || currentSoundFormat != null; } frameSlider = panel.GetOrNull <SliderWidget>("FRAME_SLIDER"); if (frameSlider != null) { frameSlider.OnChange += x => { if (!isVideoLoaded) { currentFrame = (int)Math.Round(x); } }; frameSlider.GetValue = () => { if (isVideoLoaded) { return(player.Video.CurrentFrameIndex); } if (currentSound != null) { return(currentSound.SeekPosition * currentSoundFormat.SampleRate); } return(currentFrame); }; frameSlider.IsDisabled = () => isVideoLoaded || currentSoundFormat != null; } var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT"); if (frameText != null) { frameText.GetText = () => { if (isVideoLoaded) { return($"{player.Video.CurrentFrameIndex + 1} / {player.Video.FrameCount}"); } if (currentSoundFormat != null) { return($"{Math.Round(currentSoundFormat.LengthInSeconds, 3)} sec"); } return($"{currentFrame} / {currentSprites.Length - 1}"); }; } var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY"); if (playButton != null) { playButton.OnClick = () => { if (isVideoLoaded) { player.Play(); } else if (currentSoundFormat != null) { if (currentSound != null) { Game.Sound.StopSound(currentSound); } currentSound = Game.Sound.Play(currentSoundFormat, Game.Sound.SoundVolume); } else { animateFrames = true; } }; playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames || currentSoundFormat != null; } var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE"); if (pauseButton != null) { pauseButton.OnClick = () => { if (isVideoLoaded) { player.Pause(); } else { animateFrames = false; } }; pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : (animateFrames && currentSoundFormat == null); } var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP"); if (stopButton != null) { stopButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } else if (currentSound != null) { Game.Sound.StopSound(currentSound); } else { currentFrame = 0; animateFrames = false; } if (frameSlider != null) { frameSlider.Value = 0; } }; } var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT"); if (nextButton != null) { nextButton.OnClick = () => { if (!isVideoLoaded) { nextButton.OnClick = SelectNextFrame; } }; nextButton.IsVisible = () => !isVideoLoaded && currentSoundFormat == null; } var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV"); if (prevButton != null) { prevButton.OnClick = () => { if (!isVideoLoaded) { SelectPreviousFrame(); } }; prevButton.IsVisible = () => !isVideoLoaded && currentSoundFormat == null; } var spriteScaleSlider = panel.GetOrNull <SliderWidget>("SPRITE_SCALE_SLIDER"); if (spriteScaleSlider != null) { spriteScaleSlider.OnChange += x => spriteScale = x; spriteScaleSlider.GetValue = () => spriteScale; spriteScaleSlider.IsVisible = () => currentSprites != null; panel.GetOrNull <LabelWidget>("SPRITE_SCALE").IsVisible = () => currentSprites != null; } var voxelContainer = panel.GetOrNull("VOXEL_SELECTOR"); if (voxelContainer != null) { voxelContainer.IsVisible = () => currentVoxel != null; } var rollSlider = panel.GetOrNull <SliderWidget>("ROLL_SLIDER"); if (rollSlider != null) { rollSlider.OnChange += x => { var roll = (int)x; modelOrientation = modelOrientation.WithRoll(new WAngle(roll)); }; rollSlider.GetValue = () => modelOrientation.Roll.Angle; } var pitchSlider = panel.GetOrNull <SliderWidget>("PITCH_SLIDER"); if (pitchSlider != null) { pitchSlider.OnChange += x => { var pitch = (int)x; modelOrientation = modelOrientation.WithPitch(new WAngle(pitch)); }; pitchSlider.GetValue = () => modelOrientation.Pitch.Angle; } var yawSlider = panel.GetOrNull <SliderWidget>("YAW_SLIDER"); if (yawSlider != null) { yawSlider.OnChange += x => { var yaw = (int)x; modelOrientation = modelOrientation.WithYaw(new WAngle(yaw)); }; yawSlider.GetValue = () => modelOrientation.Yaw.Angle; } var modelScaleSlider = panel.GetOrNull <SliderWidget>("MODEL_SCALE_SLIDER"); if (modelScaleSlider != null) { modelScaleSlider.OnChange += x => modelScale = x; modelScaleSlider.GetValue = () => modelScale; modelScaleSlider.IsVisible = () => currentVoxel != null; panel.GetOrNull <LabelWidget>("MODEL_SCALE").IsVisible = () => currentVoxel != null; } var assetBrowserModData = modData.Manifest.Get <AssetBrowser>(); allowedSpriteExtensions = assetBrowserModData.SpriteExtensions; allowedModelExtensions = assetBrowserModData.ModelExtensions; allowedAudioExtensions = assetBrowserModData.AudioExtensions; allowedVideoExtensions = assetBrowserModData.VideoExtensions; allowedExtensions = allowedSpriteExtensions .Union(allowedModelExtensions) .Union(allowedAudioExtensions) .Union(allowedVideoExtensions) .ToArray(); acceptablePackages = modData.ModFiles.MountedPackages.Where(p => p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant()))); assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST"); template = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE"); PopulateAssetList(); var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON"); if (closeButton != null) { closeButton.OnClick = () => { ClearLoadedAssets(); Ui.CloseWindow(); onExit(); } } ; } void SelectNextFrame() { currentFrame++; if (currentFrame >= currentSprites.Length) { currentFrame = 0; } } void SelectPreviousFrame() { currentFrame--; if (currentFrame < 0) { currentFrame = currentSprites.Length - 1; } }
void ShowProgressbar(string title, Func<string> getMessage) { visible = Mode.Progress; titleLabel.Text = title; progressBar.IsIndeterminate = () => true; var font = Game.Renderer.Fonts[progressLabel.Font]; var status = new CachedTransform<string, string>(s => WidgetUtils.TruncateText(s, progressLabel.Bounds.Width, font)); progressLabel.GetText = () => status.Update(getMessage()); primaryButton.Bounds.Y += progressContainer.Bounds.Height - panel.Bounds.Height; secondaryButton.Bounds.Y += progressContainer.Bounds.Height - panel.Bounds.Height; panel.Bounds.Y -= (progressContainer.Bounds.Height - panel.Bounds.Height) / 2; panel.Bounds.Height = progressContainer.Bounds.Height; }
public ColorPickerLogic(Widget widget, ModData modData, World world, Color initialColor, string initialFaction, Action <Color> onChange, Dictionary <string, MiniYaml> logicArgs) { var mixer = widget.Get <ColorMixerWidget>("MIXER"); // Set the initial state // All users need to use the same TraitInfo instance, chosen as the default mod rules var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>(); mixer.SetColorLimits(colorManager.HsvSaturationRange[0], colorManager.HsvSaturationRange[1], colorManager.V); mixer.OnChange += () => onChange(mixer.Color); mixer.Set(initialColor); var randomButton = widget.GetOrNull <ButtonWidget>("RANDOM_BUTTON"); if (randomButton != null) { var terrainColors = modData.DefaultTerrainInfo .SelectMany(t => t.Value.RestrictedPlayerColors) .Distinct() .ToList(); var playerColors = Enumerable.Empty <Color>(); randomButton.OnClick = () => mixer.Set(colorManager.RandomValidColor(world.LocalRandom, terrainColors, playerColors)); } if (initialFaction == null || !colorManager.FactionPreviewActors.TryGetValue(initialFaction, out var actorType)) { actorType = colorManager.PreviewActor; } if (actorType == null) { var message = "ColorPickerManager does not define a preview actor"; if (initialFaction != null) { message += " for faction " + initialFaction; } message += "!"; throw new YamlException(message); } var preview = widget.GetOrNull <ActorPreviewWidget>("PREVIEW"); var actor = world.Map.Rules.Actors[actorType]; var td = new TypeDictionary { new OwnerInit(world.WorldActor.Owner), new FactionInit(world.WorldActor.Owner.PlayerReference.Faction) }; foreach (var api in actor.TraitInfos <IActorPreviewInitInfo>()) { foreach (var o in api.ActorPreviewInits(actor, ActorPreviewType.ColorPicker)) { td.Add(o); } } preview?.SetPreview(actor, td); // HACK: the value returned from the color mixer will generally not // be equal to the given initialColor due to its internal RGB -> HSL -> RGB // conversion. This conversion can sometimes convert a valid initial value // into an invalid (too close to terrain / another player) color. // We use the original colour here instead of the mixer color to make sure // that we keep the player's previous colour value if they don't change anything onChange(initialColor); // Setup tab controls var mixerTab = widget.Get("MIXER_TAB"); var paletteTab = widget.Get("PALETTE_TAB"); var paletteTabPanel = widget.Get("PALETTE_TAB_PANEL"); var mixerTabButton = widget.Get <ButtonWidget>("MIXER_TAB_BUTTON"); var paletteTabButton = widget.Get <ButtonWidget>("PALETTE_TAB_BUTTON"); var presetArea = paletteTabPanel.Get <ContainerWidget>("PRESET_AREA"); var customArea = paletteTabPanel.Get <ContainerWidget>("CUSTOM_AREA"); var presetColorTemplate = paletteTabPanel.Get <ColorBlockWidget>("COLORPRESET"); var customColorTemplate = paletteTabPanel.Get <ColorBlockWidget>("COLORCUSTOM"); mixerTab.IsVisible = () => !paletteTabOpenedLast; mixerTabButton.OnClick = () => paletteTabOpenedLast = false; mixerTabButton.IsHighlighted = mixerTab.IsVisible; paletteTab.IsVisible = () => paletteTabOpenedLast; paletteTabButton.OnClick = () => paletteTabOpenedLast = true; paletteTabButton.IsHighlighted = () => paletteTab.IsVisible() || paletteTabHighlighted > 0; var paletteCols = 8; var palettePresetRows = 2; var paletteCustomRows = 1; if (logicArgs.TryGetValue("PaletteColumns", out var yaml)) { if (!int.TryParse(yaml.Value, out paletteCols)) { throw new YamlException($"Invalid value for PaletteColumns: {yaml.Value}"); } } if (logicArgs.TryGetValue("PalettePresetRows", out yaml)) { if (!int.TryParse(yaml.Value, out palettePresetRows)) { throw new YamlException($"Invalid value for PalettePresetRows: {yaml.Value}"); } } if (logicArgs.TryGetValue("PaletteCustomRows", out yaml)) { if (!int.TryParse(yaml.Value, out paletteCustomRows)) { throw new YamlException($"Invalid value for PaletteCustomRows: {yaml.Value}"); } } var presetColors = colorManager.PresetColors().ToList(); for (var j = 0; j < palettePresetRows; j++) { for (var i = 0; i < paletteCols; i++) { var colorIndex = j * paletteCols + i; if (colorIndex >= presetColors.Count) { break; } var color = presetColors[colorIndex]; var newSwatch = (ColorBlockWidget)presetColorTemplate.Clone(); newSwatch.GetColor = () => color; newSwatch.IsVisible = () => true; newSwatch.Bounds.X = i * newSwatch.Bounds.Width; newSwatch.Bounds.Y = j * newSwatch.Bounds.Height; newSwatch.OnMouseUp = m => { mixer.Set(color); onChange(color); }; presetArea.AddChild(newSwatch); } } for (var j = 0; j < paletteCustomRows; j++) { for (var i = 0; i < paletteCols; i++) { var colorIndex = j * paletteCols + i; var newSwatch = (ColorBlockWidget)customColorTemplate.Clone(); var getColor = new CachedTransform <Color, Color>(c => colorManager.MakeValid(c, world.LocalRandom, Enumerable.Empty <Color>(), Enumerable.Empty <Color>())); newSwatch.GetColor = () => getColor.Update(Game.Settings.Player.CustomColors[colorIndex]); newSwatch.IsVisible = () => Game.Settings.Player.CustomColors.Length > colorIndex; newSwatch.Bounds.X = i * newSwatch.Bounds.Width; newSwatch.Bounds.Y = j * newSwatch.Bounds.Height; newSwatch.OnMouseUp = m => { var color = newSwatch.GetColor(); mixer.Set(color); onChange(color); }; customArea.AddChild(newSwatch); } } // Store color button var storeButton = widget.Get <ButtonWidget>("STORE_BUTTON"); if (storeButton != null) { storeButton.OnClick = () => { // Update the custom color list: // - Remove any duplicates of the new color // - Add the new color to the end // - Save the last N colors Game.Settings.Player.CustomColors = Game.Settings.Player.CustomColors .Where(c => c != mixer.Color) .Append(mixer.Color) .Reverse().Take(paletteCustomRows * paletteCols).Reverse() .ToArray(); Game.Settings.Save(); // Flash the palette tab to show players that something has happened if (!paletteTabOpenedLast) { paletteTabHighlighted = 4; } }; } }
Func <bool> InitPanel(Widget panel) { hotkeyList = panel.Get <ScrollPanelWidget>("HOTKEY_LIST"); hotkeyList.Layout = new GridLayout(hotkeyList); headerTemplate = hotkeyList.Get("HEADER"); template = hotkeyList.Get("TEMPLATE"); emptyListMessage = panel.Get("HOTKEY_EMPTY_LIST"); remapDialog = panel.Get("HOTKEY_REMAP_DIALOG"); foreach (var hd in modData.Hotkeys.Definitions) { contexts.UnionWith(hd.Contexts); } filterInput = panel.Get <TextFieldWidget>("FILTER_INPUT"); filterInput.OnTextEdited = () => InitHotkeyList(); filterInput.OnEscKey = _ => { if (string.IsNullOrEmpty(filterInput.Text)) { filterInput.YieldKeyboardFocus(); } else { filterInput.Text = ""; filterInput.OnTextEdited(); } return(true); }; var contextDropdown = panel.GetOrNull <DropDownButtonWidget>("CONTEXT_DROPDOWN"); if (contextDropdown != null) { contextDropdown.OnMouseDown = _ => ShowContextDropdown(contextDropdown); var contextName = new CachedTransform <string, string>(GetContextDisplayName); contextDropdown.GetText = () => contextName.Update(currentContext); } if (logicArgs.TryGetValue("HotkeyGroups", out var hotkeyGroupsYaml)) { foreach (var hg in hotkeyGroupsYaml.Nodes) { var typesNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Types"); if (typesNode != null) { hotkeyGroups.Add(hg.Key, FieldLoader.GetValue <HashSet <string> >("Types", typesNode.Value.Value)); } } InitHotkeyRemapDialog(panel); InitHotkeyList(); } return(() => { hotkeyEntryWidget.Key = selectedHotkeyDefinition != null ? modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue() : Hotkey.Invalid; hotkeyEntryWidget.ForceYieldKeyboardFocus(); return false; }); }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager) { var lp = world.LocalPlayer; var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); checkbox.IsChecked = () => lp.WinState != WinState.Undefined; checkbox.GetCheckType = () => lp.WinState == WinState.Won ? "checked" : "crossed"; if (lp.HasObjectives) { var mo = lp.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); statusLabel.GetText = () => lp.WinState == WinState.Won ? "Accomplished" : lp.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => lp.WinState == WinState.Won ? Color.LimeGreen : lp.WinState == WinState.Lost ? Color.Red : Color.White; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); foreach (var p in world.Players.Where(a => !a.NonCombatant)) { var pp = p; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client.Bot == null); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Network.Session.ClientState.Disconnected) { suffix = " (Gone)"; } var sl = suffixLength.Update(suffix); return(name.Update(Pair.New(pp.PlayerName, sl)) + suffix); }; nameLabel.GetColor = () => pp.Color.RGB; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (lp.Stances[pp] == Stance.Ally || lp.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var team = item.Get <LabelWidget>("TEAM"); var teamNumber = pp.PlayerReference.Playable ? ((client == null) ? 0 : client.Team) : pp.PlayerReference.Team; team.GetText = () => (teamNumber == 0) ? "-" : teamNumber.ToString(); playerPanel.AddChild(item); var stats = pp.PlayerActor.TraitOrDefault <PlayerStatistics>(); if (stats == null) { break; } var totalKills = stats.UnitsKilled + stats.BuildingsKilled; var totalDeaths = stats.UnitsDead + stats.BuildingsDead; item.Get <LabelWidget>("KILLS").GetText = () => totalKills.ToString(); item.Get <LabelWidget>("DEATHS").GetText = () => totalDeaths.ToString(); } }
Func <bool> InitPanel(Widget panel) { var gs = Game.Settings.Game; SettingsUtils.BindCheckboxPref(panel, "ALTERNATE_SCROLL_CHECKBOX", gs, "UseAlternateScrollButton"); SettingsUtils.BindCheckboxPref(panel, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll"); SettingsUtils.BindCheckboxPref(panel, "LOCKMOUSE_CHECKBOX", gs, "LockMouseWindow"); SettingsUtils.BindSliderPref(panel, "ZOOMSPEED_SLIDER", gs, "ZoomSpeed"); SettingsUtils.BindSliderPref(panel, "SCROLLSPEED_SLIDER", gs, "ViewportEdgeScrollStep"); SettingsUtils.BindSliderPref(panel, "UI_SCROLLSPEED_SLIDER", gs, "UIScrollSpeed"); var mouseControlDropdown = panel.Get <DropDownButtonWidget>("MOUSE_CONTROL_DROPDOWN"); mouseControlDropdown.OnMouseDown = _ => ShowMouseControlDropdown(mouseControlDropdown, gs); mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; var mouseScrollDropdown = panel.Get <DropDownButtonWidget>("MOUSE_SCROLL_TYPE_DROPDOWN"); mouseScrollDropdown.OnMouseDown = _ => ShowMouseScrollDropdown(mouseScrollDropdown, gs); mouseScrollDropdown.GetText = () => gs.MouseScroll.ToString(); var mouseControlDescClassic = panel.Get("MOUSE_CONTROL_DESC_CLASSIC"); mouseControlDescClassic.IsVisible = () => gs.UseClassicMouseStyle; var mouseControlDescModern = panel.Get("MOUSE_CONTROL_DESC_MODERN"); mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle; foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern }) { var classicScrollRight = container.Get("DESC_SCROLL_RIGHT"); classicScrollRight.IsVisible = () => gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton; var classicScrollMiddle = container.Get("DESC_SCROLL_MIDDLE"); classicScrollMiddle.IsVisible = () => !gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton; var zoomDesc = container.Get("DESC_ZOOM"); zoomDesc.IsVisible = () => gs.ZoomModifier == Modifiers.None; var zoomDescModifier = container.Get <LabelWidget>("DESC_ZOOM_MODIFIER"); zoomDescModifier.IsVisible = () => gs.ZoomModifier != Modifiers.None; var zoomDescModifierTemplate = zoomDescModifier.Text; var zoomDescModifierLabel = new CachedTransform <Modifiers, string>( mod => zoomDescModifierTemplate.Replace("MODIFIER", mod.ToString())); zoomDescModifier.GetText = () => zoomDescModifierLabel.Update(gs.ZoomModifier); var edgescrollDesc = container.Get <LabelWidget>("DESC_EDGESCROLL"); edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll; } // Apply mouse focus preferences immediately var lockMouseCheckbox = panel.Get <CheckboxWidget>("LOCKMOUSE_CHECKBOX"); var oldOnClick = lockMouseCheckbox.OnClick; lockMouseCheckbox.OnClick = () => { // Still perform the old behaviour for clicking the checkbox, before // applying the changes live. oldOnClick(); MakeMouseFocusSettingsLive(); }; var zoomModifierDropdown = panel.Get <DropDownButtonWidget>("ZOOM_MODIFIER"); zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(zoomModifierDropdown, gs); zoomModifierDropdown.GetText = () => gs.ZoomModifier.ToString(); return(() => false); }
Func <bool> InitPanel(Widget panel) { var musicPlaylist = worldRenderer.World.WorldActor.Trait <MusicPlaylist>(); var ss = Game.Settings.Sound; var scrollPanel = panel.Get <ScrollPanelWidget>("SETTINGS_SCROLLPANEL"); SettingsUtils.BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks"); SettingsUtils.BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute"); SettingsUtils.BindCheckboxPref(panel, "MUTE_BACKGROUND_MUSIC", ss, "MuteBackgroundMusic"); SettingsUtils.BindSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume"); SettingsUtils.BindSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume"); SettingsUtils.BindSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume"); var muteCheckbox = panel.Get <CheckboxWidget>("MUTE_SOUND"); var muteCheckboxOnClick = muteCheckbox.OnClick; var muteCheckboxIsChecked = muteCheckbox.IsChecked; muteCheckbox.IsChecked = () => muteCheckboxIsChecked() || Game.Sound.DummyEngine; muteCheckbox.IsDisabled = () => Game.Sound.DummyEngine; muteCheckbox.OnClick = () => { muteCheckboxOnClick(); if (ss.Mute) { Game.Sound.MuteAudio(); } else { Game.Sound.UnmuteAudio(); } }; var muteBackgroundMusicCheckbox = panel.Get <CheckboxWidget>("MUTE_BACKGROUND_MUSIC"); var muteBackgroundMusicCheckboxOnClick = muteBackgroundMusicCheckbox.OnClick; muteBackgroundMusicCheckbox.OnClick = () => { muteBackgroundMusicCheckboxOnClick(); if (!musicPlaylist.AllowMuteBackgroundMusic) { return; } if (musicPlaylist.CurrentSongIsBackground) { musicPlaylist.Stop(); } }; // Replace controls with a warning label if sound is disabled var noDeviceLabel = panel.GetOrNull("NO_AUDIO_DEVICE_CONTAINER"); if (noDeviceLabel != null) { noDeviceLabel.Visible = Game.Sound.DummyEngine; } panel.Get("CASH_TICKS_CONTAINER").Visible = !Game.Sound.DummyEngine; panel.Get("MUTE_SOUND_CONTAINER").Visible = !Game.Sound.DummyEngine; panel.Get("MUTE_BACKGROUND_MUSIC_CONTAINER").Visible = !Game.Sound.DummyEngine; panel.Get("SOUND_VOLUME_CONTAINER").Visible = !Game.Sound.DummyEngine; panel.Get("MUSIC_VOLUME_CONTAINER").Visible = !Game.Sound.DummyEngine; panel.Get("VIDEO_VOLUME_CONTAINER").Visible = !Game.Sound.DummyEngine; var soundVolumeSlider = panel.Get <SliderWidget>("SOUND_VOLUME"); soundVolumeSlider.OnChange += x => Game.Sound.SoundVolume = x; var musicVolumeSlider = panel.Get <SliderWidget>("MUSIC_VOLUME"); musicVolumeSlider.OnChange += x => Game.Sound.MusicVolume = x; var videoVolumeSlider = panel.Get <SliderWidget>("VIDEO_VOLUME"); videoVolumeSlider.OnChange += x => Game.Sound.VideoVolume = x; var devices = Game.Sound.AvailableDevices(); soundDevice = devices.FirstOrDefault(d => d.Device == ss.Device) ?? devices.First(); var audioDeviceDropdown = panel.Get <DropDownButtonWidget>("AUDIO_DEVICE"); audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices, scrollPanel); var deviceFont = Game.Renderer.Fonts[audioDeviceDropdown.Font]; var deviceLabel = new CachedTransform <SoundDevice, string>( s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont)); audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice); var restartDesc = panel.Get("RESTART_REQUIRED_DESC"); restartDesc.IsVisible = () => soundDevice.Device != OriginalSoundDevice; SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel); return(() => { ss.Device = soundDevice.Device; return ss.Device != OriginalSoundDevice; }); }
internal LobbyMapPreviewLogic(Widget widget, ModData modData, OrderManager orderManager, LobbyLogic lobby) { var available = widget.GetOrNull("MAP_AVAILABLE"); if (available != null) { available.IsVisible = () => lobby.Map.Status == MapStatus.Available && (!lobby.Map.RulesLoaded || !lobby.Map.InvalidCustomRules); var preview = available.Get<MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = available.GetOrNull<LabelWidget>("MAP_TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform<MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(lobby.Map); } var typeLabel = available.GetOrNull<LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform<MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } var authorLabel = available.GetOrNull<LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform<MapPreview, string>( m => WidgetUtils.TruncateText("Created by {0}".F(lobby.Map.Author), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(lobby.Map); } } var invalid = widget.GetOrNull("MAP_INVALID"); if (invalid != null) { invalid.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.InvalidCustomRules; var preview = invalid.Get<MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = invalid.GetOrNull<LabelWidget>("MAP_TITLE"); if (titleLabel != null) titleLabel.GetText = () => lobby.Map.Title; var typeLabel = invalid.GetOrNull<LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform<MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } } var download = widget.GetOrNull("MAP_DOWNLOADABLE"); if (download != null) { download.IsVisible = () => lobby.Map.Status == MapStatus.DownloadAvailable; var preview = download.Get<MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = download.GetOrNull<LabelWidget>("MAP_TITLE"); if (titleLabel != null) titleLabel.GetText = () => lobby.Map.Title; var typeLabel = download.GetOrNull<LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform<MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } var authorLabel = download.GetOrNull<LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) authorLabel.GetText = () => "Created by {0}".F(lobby.Map.Author); var install = download.GetOrNull<ButtonWidget>("MAP_INSTALL"); if (install != null) { install.OnClick = () => lobby.Map.Install(() => { lobby.Map.PreloadRules(); Game.RunAfterTick(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)))); }); install.IsHighlighted = () => installHighlighted; } } var progress = widget.GetOrNull("MAP_PROGRESS"); if (progress != null) { progress.IsVisible = () => lobby.Map.Status != MapStatus.Available && lobby.Map.Status != MapStatus.DownloadAvailable; var preview = progress.Get<MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = progress.GetOrNull<LabelWidget>("MAP_TITLE"); if (titleLabel != null) titleLabel.GetText = () => lobby.Map.Title; var typeLabel = progress.GetOrNull<LabelWidget>("MAP_TYPE"); if (typeLabel != null) if (typeLabel != null) { var type = new CachedTransform<MapPreview, string>(m => lobby.Map.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(lobby.Map); } var statusSearching = progress.GetOrNull("MAP_STATUS_SEARCHING"); if (statusSearching != null) statusSearching.IsVisible = () => lobby.Map.Status == MapStatus.Searching; var statusUnavailable = progress.GetOrNull("MAP_STATUS_UNAVAILABLE"); if (statusUnavailable != null) statusUnavailable.IsVisible = () => lobby.Map.Status == MapStatus.Unavailable; var statusError = progress.GetOrNull("MAP_STATUS_ERROR"); if (statusError != null) statusError.IsVisible = () => lobby.Map.Status == MapStatus.DownloadError; var statusDownloading = progress.GetOrNull<LabelWidget>("MAP_STATUS_DOWNLOADING"); if (statusDownloading != null) { statusDownloading.IsVisible = () => lobby.Map.Status == MapStatus.Downloading; statusDownloading.GetText = () => { if (lobby.Map.DownloadBytes == 0) return "Connecting..."; // Server does not provide the total file length if (lobby.Map.DownloadPercentage == 0) return "Downloading {0} kB".F(lobby.Map.DownloadBytes / 1024); return "Downloading {0} kB ({1}%)".F(lobby.Map.DownloadBytes / 1024, lobby.Map.DownloadPercentage); }; } var retry = progress.GetOrNull<ButtonWidget>("MAP_RETRY"); if (retry != null) { retry.IsVisible = () => (lobby.Map.Status == MapStatus.DownloadError || lobby.Map.Status == MapStatus.Unavailable) && lobby.Map != MapCache.UnknownMap; retry.OnClick = () => { if (lobby.Map.Status == MapStatus.DownloadError) lobby.Map.Install(() => orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)))); else if (lobby.Map.Status == MapStatus.Unavailable) modData.MapCache.QueryRemoteMapDetails(new[] { lobby.Map.Uid }); }; retry.GetText = () => lobby.Map.Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search"; } var progressbar = progress.GetOrNull<ProgressBarWidget>("MAP_PROGRESSBAR"); if (progressbar != null) { progressbar.IsIndeterminate = () => lobby.Map.DownloadPercentage == 0; progressbar.GetPercentage = () => lobby.Map.DownloadPercentage; progressbar.IsVisible = () => !retry.IsVisible(); } } }
Func <bool> InitPanel(Widget panel) { var ds = Game.Settings.Graphics; var gs = Game.Settings.Game; SettingsUtils.BindCheckboxPref(panel, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble"); SettingsUtils.BindCheckboxPref(panel, "VSYNC_CHECKBOX", ds, "VSync"); SettingsUtils.BindCheckboxPref(panel, "FRAME_LIMIT_CHECKBOX", ds, "CapFramerate"); SettingsUtils.BindIntSliderPref(panel, "FRAME_LIMIT_SLIDER", ds, "MaxFramerate"); SettingsUtils.BindCheckboxPref(panel, "PLAYER_STANCE_COLORS_CHECKBOX", gs, "UsePlayerStanceColors"); if (panel.GetOrNull <CheckboxWidget>("PAUSE_SHELLMAP_CHECKBOX") != null) { SettingsUtils.BindCheckboxPref(panel, "PAUSE_SHELLMAP_CHECKBOX", gs, "PauseShellmap"); } var windowModeDropdown = panel.Get <DropDownButtonWidget>("MODE_DROPDOWN"); windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds); windowModeDropdown.GetText = () => ds.Mode == WindowMode.Windowed ? "Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen (Legacy)" : "Fullscreen"; var displaySelectionDropDown = panel.Get <DropDownButtonWidget>("DISPLAY_SELECTION_DROPDOWN"); displaySelectionDropDown.OnMouseDown = _ => ShowDisplaySelectionDropdown(displaySelectionDropDown, ds); var displaySelectionLabel = new CachedTransform <int, string>(i => $"Display {i + 1}"); displaySelectionDropDown.GetText = () => displaySelectionLabel.Update(ds.VideoDisplay); displaySelectionDropDown.IsDisabled = () => Game.Renderer.DisplayCount < 2; var glProfileLabel = new CachedTransform <GLProfile, string>(p => p.ToString()); var glProfileDropdown = panel.Get <DropDownButtonWidget>("GL_PROFILE_DROPDOWN"); var disableProfile = Game.Renderer.SupportedGLProfiles.Length < 2 && ds.GLProfile == GLProfile.Automatic; glProfileDropdown.OnMouseDown = _ => ShowGLProfileDropdown(glProfileDropdown, ds); glProfileDropdown.GetText = () => glProfileLabel.Update(ds.GLProfile); glProfileDropdown.IsDisabled = () => disableProfile; var statusBarsDropDown = panel.Get <DropDownButtonWidget>("STATUS_BAR_DROPDOWN"); statusBarsDropDown.OnMouseDown = _ => ShowStatusBarsDropdown(statusBarsDropDown, gs); statusBarsDropDown.GetText = () => gs.StatusBars == StatusBarsType.Standard ? "Standard" : gs.StatusBars == StatusBarsType.DamageShow ? "Show On Damage" : "Always Show"; var targetLinesDropDown = panel.Get <DropDownButtonWidget>("TARGET_LINES_DROPDOWN"); targetLinesDropDown.OnMouseDown = _ => ShowTargetLinesDropdown(targetLinesDropDown, gs); targetLinesDropDown.GetText = () => gs.TargetLines == TargetLinesType.Automatic ? "Automatic" : gs.TargetLines == TargetLinesType.Manual ? "Manual" : "Disabled"; var battlefieldCameraDropDown = panel.Get <DropDownButtonWidget>("BATTLEFIELD_CAMERA_DROPDOWN"); var battlefieldCameraLabel = new CachedTransform <WorldViewport, string>(vs => ViewportSizeNames[vs]); battlefieldCameraDropDown.OnMouseDown = _ => ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); BindTextNotificationPoolFilterSettings(panel, gs); // Update vsync immediately var vsyncCheckbox = panel.Get <CheckboxWidget>("VSYNC_CHECKBOX"); var vsyncOnClick = vsyncCheckbox.OnClick; vsyncCheckbox.OnClick = () => { vsyncOnClick(); Game.Renderer.SetVSyncEnabled(ds.VSync); }; var uiScaleDropdown = panel.Get <DropDownButtonWidget>("UI_SCALE_DROPDOWN"); var uiScaleLabel = new CachedTransform <float, string>(s => $"{(int)(100 * s)}%"); uiScaleDropdown.OnMouseDown = _ => ShowUIScaleDropdown(uiScaleDropdown, ds); uiScaleDropdown.GetText = () => uiScaleLabel.Update(ds.UIScale); var minResolution = viewportSizes.MinEffectiveResolution; var resolution = Game.Renderer.Resolution; var disableUIScale = worldRenderer.World.Type != WorldType.Shellmap || resolution.Width * ds.UIScale < 1.25f * minResolution.Width || resolution.Height * ds.UIScale < 1.25f * minResolution.Height; uiScaleDropdown.IsDisabled = () => disableUIScale; panel.Get("DISPLAY_SELECTION").IsVisible = () => ds.Mode != WindowMode.Windowed; panel.Get("WINDOW_RESOLUTION").IsVisible = () => ds.Mode == WindowMode.Windowed; var windowWidth = panel.Get <TextFieldWidget>("WINDOW_WIDTH"); var origWidthText = windowWidth.Text = ds.WindowedSize.X.ToString(); var windowHeight = panel.Get <TextFieldWidget>("WINDOW_HEIGHT"); var origHeightText = windowHeight.Text = ds.WindowedSize.Y.ToString(); windowHeight.Text = ds.WindowedSize.Y.ToString(); var restartDesc = panel.Get("RESTART_REQUIRED_DESC"); restartDesc.IsVisible = () => ds.Mode != OriginalGraphicsMode || ds.VideoDisplay != OriginalVideoDisplay || ds.GLProfile != OriginalGLProfile || (ds.Mode == WindowMode.Windowed && (origWidthText != windowWidth.Text || origHeightText != windowHeight.Text)); var frameLimitCheckbox = panel.Get <CheckboxWidget>("FRAME_LIMIT_CHECKBOX"); var frameLimitOrigLabel = frameLimitCheckbox.Text; var frameLimitLabel = new CachedTransform <int, string>(fps => frameLimitOrigLabel + $" ({fps} FPS)"); frameLimitCheckbox.GetText = () => frameLimitLabel.Update(ds.MaxFramerate); // Player profile var ps = Game.Settings.Player; var escPressed = false; var nameTextfield = panel.Get <TextFieldWidget>("PLAYERNAME"); nameTextfield.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name); nameTextfield.OnLoseFocus = () => { if (escPressed) { escPressed = false; return; } nameTextfield.Text = nameTextfield.Text.Trim(); if (nameTextfield.Text.Length == 0) { nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name); } else { nameTextfield.Text = Settings.SanitizedPlayerName(nameTextfield.Text); ps.Name = nameTextfield.Text; } }; nameTextfield.OnEnterKey = _ => { nameTextfield.YieldKeyboardFocus(); return(true); }; nameTextfield.OnEscKey = _ => { nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name); escPressed = true; nameTextfield.YieldKeyboardFocus(); return(true); }; var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>(); colorManager.Color = ps.Color; var colorDropdown = panel.Get <DropDownButtonWidget>("PLAYERCOLOR"); colorDropdown.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorManager, worldRenderer, () => { Game.Settings.Player.Color = colorManager.Color; Game.Settings.Save(); }); colorDropdown.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => ps.Color; return(() => { Exts.TryParseIntegerInvariant(windowWidth.Text, out var x); Exts.TryParseIntegerInvariant(windowHeight.Text, out var y); ds.WindowedSize = new int2(x, y); nameTextfield.YieldKeyboardFocus(); return ds.Mode != OriginalGraphicsMode || ds.VideoDisplay != OriginalVideoDisplay || ds.WindowedSize != OriginalGraphicsWindowedSize || ds.FullscreenSize != OriginalGraphicsFullscreenSize || ds.GLProfile != OriginalGLProfile; }); }
Action InitAudioPanel(Widget panel) { var ss = Game.Settings.Sound; BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks"); BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute"); BindSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume"); BindSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume"); BindSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume"); var muteCheckbox = panel.Get<CheckboxWidget>("MUTE_SOUND"); var muteCheckboxOnClick = muteCheckbox.OnClick; muteCheckbox.OnClick = () => { muteCheckboxOnClick(); if (ss.Mute) Game.Sound.MuteAudio(); else Game.Sound.UnmuteAudio(); }; if (!ss.Mute) { panel.Get<SliderWidget>("SOUND_VOLUME").OnChange += x => Game.Sound.SoundVolume = x; panel.Get<SliderWidget>("MUSIC_VOLUME").OnChange += x => Game.Sound.MusicVolume = x; panel.Get<SliderWidget>("VIDEO_VOLUME").OnChange += x => Game.Sound.VideoVolume = x; } var devices = Game.Sound.AvailableDevices(); soundDevice = devices.FirstOrDefault(d => d.Engine == ss.Engine && d.Device == ss.Device) ?? devices.First(); var audioDeviceDropdown = panel.Get<DropDownButtonWidget>("AUDIO_DEVICE"); audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices); var deviceFont = Game.Renderer.Fonts[audioDeviceDropdown.Font]; var deviceLabel = new CachedTransform<SoundDevice, string>( s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont)); audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice); return () => { ss.Device = soundDevice.Device; ss.Engine = soundDevice.Engine; }; }
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Player player, Func <ProductionIcon> getTooltipIcon) { var world = player.World; var mapRules = world.Map.Rules; var pm = player.PlayerActor.TraitOrDefault <PowerManager>(); var pr = player.PlayerActor.Trait <PlayerResources>(); widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Actor != null; var nameLabel = widget.Get <LabelWidget>("NAME"); var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY"); var requiresLabel = widget.Get <LabelWidget>("REQUIRES"); var powerLabel = widget.Get <LabelWidget>("POWER"); var powerIcon = widget.Get <ImageWidget>("POWER_ICON"); var timeLabel = widget.Get <LabelWidget>("TIME"); var timeIcon = widget.Get <ImageWidget>("TIME_ICON"); var costLabel = widget.Get <LabelWidget>("COST"); var costIcon = widget.Get <ImageWidget>("COST_ICON"); var descLabel = widget.Get <LabelWidget>("DESC"); var iconMargin = timeIcon.Bounds.X; var font = Game.Renderer.Fonts[nameLabel.Font]; var descFont = Game.Renderer.Fonts[descLabel.Font]; var requiresFont = Game.Renderer.Fonts[requiresLabel.Font]; var formatBuildTime = new CachedTransform <int, string>(time => WidgetUtils.FormatTime(time, world.Timestep)); var requiresFormat = requiresLabel.Text; ActorInfo lastActor = null; Hotkey lastHotkey = Hotkey.Invalid; var lastPowerState = pm?.PowerState ?? PowerState.Normal; var descLabelY = descLabel.Bounds.Y; var descLabelPadding = descLabel.Bounds.Height; tooltipContainer.BeforeRender = () => { var tooltipIcon = getTooltipIcon(); var actor = tooltipIcon?.Actor; if (actor == null) { return; } var hotkey = tooltipIcon.Hotkey?.GetValue() ?? Hotkey.Invalid; if (actor == lastActor && hotkey == lastHotkey && (pm == null || pm.PowerState == lastPowerState)) { return; } var tooltip = actor.TraitInfos <TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault); var name = tooltip?.Name ?? actor.Name; var buildable = actor.TraitInfo <BuildableInfo>(); var cost = 0; if (tooltipIcon.ProductionQueue != null) { cost = tooltipIcon.ProductionQueue.GetProductionCost(actor); } else { var valued = actor.TraitInfoOrDefault <ValuedInfo>(); if (valued != null) { cost = valued.Cost; } } nameLabel.Text = name; var nameSize = font.Measure(name); var hotkeyWidth = 0; hotkeyLabel.Visible = hotkey.IsValid(); if (hotkeyLabel.Visible) { var hotkeyText = "({0})".F(hotkey.DisplayString()); hotkeyWidth = font.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; hotkeyLabel.Text = hotkeyText; hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X; } var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a)) .Where(s => !s.StartsWith("~", StringComparison.Ordinal) && !s.StartsWith("!", StringComparison.Ordinal)); var requiresSize = int2.Zero; if (prereqs.Any()) { requiresLabel.Text = requiresFormat.F(prereqs.JoinWith(", ")); requiresSize = requiresFont.Measure(requiresLabel.Text); requiresLabel.Visible = true; descLabel.Bounds.Y = descLabelY + requiresLabel.Bounds.Height; } else { requiresLabel.Visible = false; descLabel.Bounds.Y = descLabelY; } var powerSize = new int2(0, 0); if (pm != null) { var power = actor.TraitInfos <PowerInfo>().Where(i => i.EnabledByDefault).Sum(i => i.Amount); powerLabel.Text = power.ToString(); powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0) ? Color.White : Color.Red; powerLabel.Visible = power != 0; powerIcon.Visible = power != 0; powerSize = font.Measure(powerLabel.Text); } var buildTime = tooltipIcon.ProductionQueue?.GetBuildTime(actor, buildable) ?? 0; var timeModifier = pm != null && pm.PowerState != PowerState.Normal ? tooltipIcon.ProductionQueue.Info.LowPowerModifier : 100; timeLabel.Text = formatBuildTime.Update((buildTime * timeModifier) / 100); timeLabel.TextColor = (pm != null && pm.PowerState != PowerState.Normal && tooltipIcon.ProductionQueue.Info.LowPowerModifier > 100) ? Color.Red : Color.White; var timeSize = font.Measure(timeLabel.Text); costLabel.Text = cost.ToString(); costLabel.GetColor = () => pr.Cash + pr.Resources >= cost ? Color.White : Color.Red; var costSize = font.Measure(costLabel.Text); descLabel.Text = buildable.Description.Replace("\\n", "\n"); var descSize = descFont.Measure(descLabel.Text); descLabel.Bounds.Width = descSize.X; descLabel.Bounds.Height = descSize.Y + descLabelPadding; var leftWidth = new[] { nameSize.X + hotkeyWidth, requiresSize.X, descSize.X }.Aggregate(Math.Max); var rightWidth = new[] { powerSize.X, timeSize.X, costSize.X }.Aggregate(Math.Max); timeIcon.Bounds.X = powerIcon.Bounds.X = costIcon.Bounds.X = leftWidth + 2 * nameLabel.Bounds.X; timeLabel.Bounds.X = powerLabel.Bounds.X = costLabel.Bounds.X = timeIcon.Bounds.Right + iconMargin; widget.Bounds.Width = leftWidth + rightWidth + 3 * nameLabel.Bounds.X + timeIcon.Bounds.Width + iconMargin; // Set the bottom margin to match the left margin var leftHeight = descLabel.Bounds.Bottom + descLabel.Bounds.X; // Set the bottom margin to match the top margin var rightHeight = (powerLabel.Visible ? powerIcon.Bounds.Bottom : timeIcon.Bounds.Bottom) + costIcon.Bounds.Top; widget.Bounds.Height = Math.Max(leftHeight, rightHeight); lastActor = actor; lastHotkey = hotkey; if (pm != null) { lastPowerState = pm.PowerState; } }; }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager) { var player = world.RenderPlayer ?? world.LocalPlayer; var playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get<CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get<LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait<MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get<ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => new Pair<Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault<PlayerStatistics>())) .OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get<LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get<LabelWidget>("TEAM_SCORE"); teamRating.GetText = () => t.Sum(gg => gg.Second != null ? gg.Second.Experience : 0).ToString(); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.First; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null); var nameLabel = item.Get<LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform<string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform<Pair<string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Session.ClientState.Disconnected) suffix = " (Gone)"; var sl = suffixLength.Update(suffix); return name.Update(Pair.New(pp.PlayerName, sl)) + suffix; }; nameLabel.GetColor = () => pp.Color.RGB; var flag = item.Get<ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.Stances[pp] == Stance.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get<LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get<LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var experience = p.Second != null ? p.Second.Experience : 0; item.Get<LabelWidget>("SCORE").GetText = () => experience.ToString(); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get<LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null); var nameLabel = item.Get<LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform<string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform<Pair<string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; var sl = suffixLength.Update(suffix); return name.Update(Pair.New(client.Name, sl)) + suffix; }; item.Get<ImageWidget>("FACTIONFLAG").IsVisible = () => false; playerPanel.AddChild(item); } } }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager) { var player = world.RenderPlayer ?? world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => new Pair <Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); teamRating.GetText = () => t.Sum(gg => gg.Second != null ? gg.Second.Experience : 0).ToString(); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.First; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Session.ClientState.Disconnected) { suffix = " (Gone)"; } var sl = suffixLength.Update(suffix); return(name.Update(Pair.New(pp.PlayerName, sl)) + suffix); }; nameLabel.GetColor = () => pp.Color.RGB; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.Stances[pp] == Stance.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var experience = p.Second != null ? p.Second.Experience : 0; item.Get <LabelWidget>("SCORE").GetText = () => experience.ToString(); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = playerTemplate.Clone(); LobbyUtils.SetupClientWidget(item, client, orderManager, client != null && client.Bot == null); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; var sl = suffixLength.Update(suffix); return(name.Update(Pair.New(client.Name, sl)) + suffix); }; item.Get <ImageWidget>("FACTIONFLAG").IsVisible = () => false; playerPanel.AddChild(item); } } }
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Player player, Func <ProductionIcon> getTooltipIcon) { var world = player.World; var mapRules = world.Map.Rules; var pm = player.PlayerActor.Trait <PowerManager>(); var pr = player.PlayerActor.Trait <PlayerResources>(); widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Actor != null; var nameLabel = widget.Get <LabelWidget>("NAME"); var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY"); var requiresLabel = widget.Get <LabelWidget>("REQUIRES"); var powerLabel = widget.Get <LabelWidget>("POWER"); var powerIcon = widget.Get <ImageWidget>("POWER_ICON"); var timeLabel = widget.Get <LabelWidget>("TIME"); var timeIcon = widget.Get <ImageWidget>("TIME_ICON"); var costLabel = widget.Get <LabelWidget>("COST"); var costIcon = widget.Get <ImageWidget>("COST_ICON"); var descLabel = widget.Get <LabelWidget>("DESC"); var iconMargin = timeIcon.Bounds.X; var font = Game.Renderer.Fonts[nameLabel.Font]; var descFont = Game.Renderer.Fonts[descLabel.Font]; var requiresFont = Game.Renderer.Fonts[requiresLabel.Font]; var formatBuildTime = new CachedTransform <int, string>(time => WidgetUtils.FormatTime(time, world.Timestep)); var requiresFormat = requiresLabel.Text; ActorInfo lastActor = null; Hotkey lastHotkey = Hotkey.Invalid; var lastPowerState = pm.PowerState; tooltipContainer.BeforeRender = () => { var tooltipIcon = getTooltipIcon(); if (tooltipIcon == null) { return; } var actor = tooltipIcon.Actor; if (actor == null) { return; } var hotkey = tooltipIcon.Hotkey != null?tooltipIcon.Hotkey.GetValue() : Hotkey.Invalid; if (actor == lastActor && hotkey == lastHotkey && pm.PowerState == lastPowerState) { return; } var tooltip = actor.TraitInfos <TooltipInfo>().FirstOrDefault(Exts.IsTraitEnabled); var name = tooltip != null ? tooltip.Name : actor.Name; var buildable = actor.TraitInfo <BuildableInfo>(); var cost = actor.TraitInfo <ValuedInfo>().Cost; nameLabel.Text = name; var nameSize = font.Measure(name); var hotkeyWidth = 0; hotkeyLabel.Visible = hotkey.IsValid(); if (hotkeyLabel.Visible) { var hotkeyText = "({0})".F(hotkey.DisplayString()); hotkeyWidth = font.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; hotkeyLabel.Text = hotkeyText; hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X; } var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a)).Where(s => !s.StartsWith("~", StringComparison.Ordinal)); requiresLabel.Text = prereqs.Any() ? requiresFormat.F(prereqs.JoinWith(", ")) : ""; var requiresSize = requiresFont.Measure(requiresLabel.Text); var power = actor.TraitInfos <PowerInfo>().Where(i => i.EnabledByDefault).Sum(i => i.Amount); powerLabel.Text = power.ToString(); powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0) ? Color.White : Color.Red; powerLabel.Visible = power != 0; powerIcon.Visible = power != 0; var powerSize = font.Measure(powerLabel.Text); var buildTime = tooltipIcon.ProductionQueue == null ? 0 : tooltipIcon.ProductionQueue.GetBuildTime(actor, buildable); var timeMultiplier = pm.PowerState != PowerState.Normal ? tooltipIcon.ProductionQueue.Info.LowPowerSlowdown : 1; timeLabel.Text = formatBuildTime.Update(buildTime * timeMultiplier); timeLabel.TextColor = pm.PowerState != PowerState.Normal ? Color.Red : Color.White; var timeSize = font.Measure(timeLabel.Text); costLabel.Text = cost.ToString(); costLabel.GetColor = () => pr.Cash + pr.Resources >= cost ? Color.White : Color.Red; var costSize = font.Measure(costLabel.Text); descLabel.Text = buildable.Description.Replace("\\n", "\n"); var descSize = descFont.Measure(descLabel.Text); var leftWidth = new[] { nameSize.X + hotkeyWidth, requiresSize.X, descSize.X }.Aggregate(Math.Max); var rightWidth = new[] { powerSize.X, timeSize.X, costSize.X }.Aggregate(Math.Max); timeIcon.Bounds.X = powerIcon.Bounds.X = costIcon.Bounds.X = leftWidth + 2 * nameLabel.Bounds.X; timeLabel.Bounds.X = powerLabel.Bounds.X = costLabel.Bounds.X = timeIcon.Bounds.Right + iconMargin; widget.Bounds.Width = leftWidth + rightWidth + 3 * nameLabel.Bounds.X + timeIcon.Bounds.Width + iconMargin; var leftHeight = nameSize.Y + requiresSize.Y + descSize.Y; var rightHeight = powerSize.Y + timeSize.Y + costSize.Y; widget.Bounds.Height = Math.Max(leftHeight, rightHeight) * 3 / 2 + 3 * nameLabel.Bounds.Y; lastActor = actor; lastHotkey = hotkey; lastPowerState = pm.PowerState; }; }
public GameInfoStatsLogic(Widget widget, World world) { var lp = world.LocalPlayer; var checkbox = widget.Get<CheckboxWidget>("STATS_CHECKBOX"); checkbox.IsChecked = () => lp.WinState != WinState.Undefined; checkbox.GetCheckType = () => lp.WinState == WinState.Won ? "checked" : "crossed"; if (lp.HasObjectives) { var mo = lp.PlayerActor.Trait<MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } var statusLabel = widget.Get<LabelWidget>("STATS_STATUS"); statusLabel.GetText = () => lp.WinState == WinState.Won ? "Accomplished" : lp.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => lp.WinState == WinState.Won ? Color.LimeGreen : lp.WinState == WinState.Lost ? Color.Red : Color.White; var playerPanel = widget.Get<ScrollPanelWidget>("PLAYER_LIST"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); playerPanel.RemoveChildren(); foreach (var p in world.Players.Where(a => !a.NonCombatant)) { var pp = p; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); var nameLabel = item.Get<LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform<string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform<Pair<string, int>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - c.Second, nameFont)); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Network.Session.ClientState.Disconnected) suffix = " (Gone)"; var sl = suffixLength.Update(suffix); return name.Update(Pair.New(pp.PlayerName, sl)) + suffix; }; nameLabel.GetColor = () => pp.Color.RGB; var flag = item.Get<ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (lp.Stances[pp] == Stance.Ally || lp.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get<LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get<LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var team = item.Get<LabelWidget>("TEAM"); var teamNumber = pp.PlayerReference.Playable ? ((client == null) ? 0 : client.Team) : pp.PlayerReference.Team; team.GetText = () => (teamNumber == 0) ? "-" : teamNumber.ToString(); playerPanel.AddChild(item); var stats = pp.PlayerActor.TraitOrDefault<PlayerStatistics>(); if (stats == null) break; var totalKills = stats.UnitsKilled + stats.BuildingsKilled; var totalDeaths = stats.UnitsDead + stats.BuildingsDead; item.Get<LabelWidget>("KILLS").GetText = () => totalKills.ToString(); item.Get<LabelWidget>("DEATHS").GetText = () => totalDeaths.ToString(); } }
public ReplayBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart) { map = MapCache.UnknownMap; panel = widget; services = modData.Manifest.Get <WebServices>(); this.modData = modData; this.onStart = onStart; Game.BeforeGameStart += OnGameStart; playerList = panel.Get <ScrollPanelWidget>("PLAYER_LIST"); playerHeader = playerList.Get <ScrollItemWidget>("HEADER"); playerTemplate = playerList.Get <ScrollItemWidget>("TEMPLATE"); playerList.RemoveChildren(); panel.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => { cancelLoadingReplays = true; Ui.CloseWindow(); onExit(); }; replayList = panel.Get <ScrollPanelWidget>("REPLAY_LIST"); var template = panel.Get <ScrollItemWidget>("REPLAY_TEMPLATE"); var mod = modData.Manifest; var dir = Path.Combine(Platform.SupportDir, "Replays", mod.Id, mod.Metadata.Version); if (Directory.Exists(dir)) { ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template)); } var watch = panel.Get <ButtonWidget>("WATCH_BUTTON"); watch.IsDisabled = () => selectedReplay == null || map.Status != MapStatus.Available; watch.OnClick = () => { WatchReplay(); }; var mapPreviewRoot = panel.Get("MAP_PREVIEW_ROOT"); mapPreviewRoot.IsVisible = () => selectedReplay != null; panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null; var spawnOccupants = new CachedTransform <ReplayMetadata, Dictionary <int, SpawnOccupant> >(r => { // Avoid using .ToDictionary to improve robustness against replays defining duplicate spawn assignments var occupants = new Dictionary <int, SpawnOccupant>(); foreach (var p in r.GameInfo.Players) { if (p.SpawnPoint != 0) { occupants[p.SpawnPoint] = new SpawnOccupant(p); } } return(occupants); }); var noSpawns = new HashSet <int>(); var disabledSpawnPoints = new CachedTransform <ReplayMetadata, HashSet <int> >(r => r.GameInfo.DisabledSpawnPoints ?? noSpawns); Ui.LoadWidget("MAP_PREVIEW", mapPreviewRoot, new WidgetArgs { { "orderManager", null }, { "getMap", (Func <MapPreview>)(() => map) }, { "onMouseDown", (Action <MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) => { }) }, { "getSpawnOccupants", (Func <Dictionary <int, SpawnOccupant> >)(() => spawnOccupants.Update(selectedReplay)) }, { "getDisabledSpawnPoints", (Func <HashSet <int> >)(() => disabledSpawnPoints.Update(selectedReplay)) }, { "showUnoccupiedSpawnpoints", false }, }); var replayDuration = new CachedTransform <ReplayMetadata, string>(r => "Duration: {0}".F(WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds))); panel.Get <LabelWidget>("DURATION").GetText = () => replayDuration.Update(selectedReplay); SetupFilters(); SetupManagement(); }
public ServerCreationLogic(Widget widget, ModData modData, Action onExit, Action openLobby) { panel = widget; onCreate = openLobby; this.onExit = onExit; var settings = Game.Settings; preview = modData.MapCache[modData.MapCache.ChooseInitialMap(Game.Settings.Server.Map, Game.CosmeticRandom)]; panel.Get <ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin; var mapButton = panel.GetOrNull <ButtonWidget>("MAP_BUTTON"); if (mapButton != null) { panel.Get <ButtonWidget>("MAP_BUTTON").OnClick = () => { Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", preview.Uid }, { "initialTab", MapClassification.System }, { "onExit", () => { } }, { "onSelect", (Action <string>)(uid => preview = modData.MapCache[uid]) }, { "filter", MapVisibility.Lobby }, { "onStart", () => { } } }); }; panel.Get <MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview; var mapTitle = panel.Get <LabelWidget>("MAP_NAME"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(preview); } } var serverName = panel.Get <TextFieldWidget>("SERVER_NAME"); serverName.Text = Settings.SanitizedServerName(settings.Server.Name); serverName.OnEnterKey = () => { serverName.YieldKeyboardFocus(); return(true); }; serverName.OnLoseFocus = () => { serverName.Text = Settings.SanitizedServerName(serverName.Text); settings.Server.Name = serverName.Text; }; panel.Get <TextFieldWidget>("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); advertiseOnline = Game.Settings.Server.AdvertiseOnline; var externalPort = panel.Get <TextFieldWidget>("EXTERNAL_PORT"); externalPort.Text = settings.Server.ExternalPort.ToString(); externalPort.IsDisabled = () => !advertiseOnline; var advertiseCheckbox = panel.Get <CheckboxWidget>("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => advertiseOnline ^= true; allowPortForward = Game.Settings.Server.AllowPortForward; var checkboxUPnP = panel.Get <CheckboxWidget>("UPNP_CHECKBOX"); checkboxUPnP.IsChecked = () => allowPortForward; checkboxUPnP.OnClick = () => allowPortForward ^= true; checkboxUPnP.IsDisabled = () => !Game.Settings.Server.AllowPortForward; var labelUPnP = panel.GetOrNull <LabelWidget>("UPNP_NOTICE"); if (labelUPnP != null) { labelUPnP.IsVisible = () => !Game.Settings.Server.DiscoverNatDevices; } var labelUPnPUnsupported = panel.GetOrNull <LabelWidget>("UPNP_UNSUPPORTED_NOTICE"); if (labelUPnPUnsupported != null) { labelUPnPUnsupported.IsVisible = () => Game.Settings.Server.DiscoverNatDevices && !Game.Settings.Server.AllowPortForward; } var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); if (passwordField != null) { passwordField.Text = Game.Settings.Server.Password; } }
void LoadBrowserPanel(Widget widget) { var browserPanel = Game.LoadWidget(null, "MULTIPLAYER_BROWSER_PANEL", widget.Get("TOP_PANELS_ROOT"), new WidgetArgs()); browserPanel.IsVisible = () => panel == PanelType.Browser; serverList = browserPanel.Get <ScrollPanelWidget>("SERVER_LIST"); headerTemplate = serverList.Get <ScrollItemWidget>("HEADER_TEMPLATE"); serverTemplate = serverList.Get <ScrollItemWidget>("SERVER_TEMPLATE"); var join = widget.Get <ButtonWidget>("JOIN_BUTTON"); join.IsDisabled = () => currentServer == null || !currentServer.IsJoinable; join.OnClick = () => Join(currentServer); // Display the progress label over the server list // The text is only visible when the list is empty var progressText = widget.Get <LabelWidget>("PROGRESS_LABEL"); progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; progressText.GetText = ProgressLabelText; var filtersPanel = Ui.LoadWidget("MULTIPLAYER_FILTER_PANEL", null, new WidgetArgs()); var showWaitingCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("WAITING_FOR_PLAYERS"); if (showWaitingCheckbox != null) { showWaitingCheckbox.IsChecked = () => showWaiting; showWaitingCheckbox.OnClick = () => { showWaiting ^= true; RefreshServerList(); }; } var showEmptyCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("EMPTY"); if (showEmptyCheckbox != null) { showEmptyCheckbox.IsChecked = () => showEmpty; showEmptyCheckbox.OnClick = () => { showEmpty ^= true; RefreshServerList(); }; } var showAlreadyStartedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("ALREADY_STARTED"); if (showAlreadyStartedCheckbox != null) { showAlreadyStartedCheckbox.IsChecked = () => showStarted; showAlreadyStartedCheckbox.OnClick = () => { showStarted ^= true; RefreshServerList(); }; } var showProtectedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("PASSWORD_PROTECTED"); if (showProtectedCheckbox != null) { showProtectedCheckbox.IsChecked = () => showProtected; showProtectedCheckbox.OnClick = () => { showProtected ^= true; RefreshServerList(); }; } var showIncompatibleCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("INCOMPATIBLE_VERSION"); if (showIncompatibleCheckbox != null) { showIncompatibleCheckbox.IsChecked = () => showIncompatible; showIncompatibleCheckbox.OnClick = () => { showIncompatible ^= true; RefreshServerList(); }; } var filtersButton = widget.GetOrNull <DropDownButtonWidget>("FILTERS_DROPDOWNBUTTON"); if (filtersButton != null) { filtersButton.OnMouseDown = _ => { filtersButton.RemovePanel(); filtersButton.AttachPanel(filtersPanel); }; } var refreshButton = widget.Get <ButtonWidget>("REFRESH_BUTTON"); refreshButton.GetText = () => searchStatus == SearchStatus.Fetching ? "Refreshing..." : "Refresh"; refreshButton.OnClick = RefreshServerList; var mapPreview = widget.GetOrNull <MapPreviewWidget>("SELECTED_MAP_PREVIEW"); if (mapPreview != null) { mapPreview.Preview = () => currentMap; } var mapTitle = widget.GetOrNull <LabelWidget>("SELECTED_MAP"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform <MapPreview, string>(m => m == null ? "No Server Selected" : WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(currentMap); } var ip = widget.GetOrNull <LabelWidget>("SELECTED_IP"); if (ip != null) { ip.IsVisible = () => currentServer != null; ip.GetText = () => currentServer.Address; } var status = widget.GetOrNull <LabelWidget>("SELECTED_STATUS"); if (status != null) { status.IsVisible = () => currentServer != null; status.GetText = () => GetStateLabel(currentServer); status.GetColor = () => GetStateColor(currentServer, status); } var modVersion = widget.GetOrNull <LabelWidget>("SELECTED_MOD_VERSION"); if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; var font = Game.Renderer.Fonts[modVersion.Font]; var version = new CachedTransform <GameServer, string>(s => WidgetUtils.TruncateText(s.ModLabel, mapTitle.Bounds.Width, font)); modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull <LabelWidget>("SELECTED_PLAYERS"); if (players != null) { players.IsVisible = () => currentServer != null; players.GetText = () => PlayersLabel(currentServer); } }
public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, World world, Dictionary <string, MiniYaml> logicArgs) { this.world = world; this.modData = modData; panel = widget; var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER"); if (ticker != null) { ticker.OnTick = () => { if (animateFrames) { SelectNextFrame(); } }; } var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR"); if (sourceDropdown != null) { sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown); var sourceName = new CachedTransform <IReadOnlyPackage, string>(GetSourceDisplayName); sourceDropdown.GetText = () => sourceName.Update(assetSource); } var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE"); if (spriteWidget != null) { spriteWidget.GetSprite = () => currentSprites != null ? currentSprites[currentFrame] : null; currentPalette = spriteWidget.Palette; spriteWidget.GetPalette = () => currentPalette; spriteWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentSprites != null; } var playerWidget = panel.GetOrNull <VideoPlayerWidget>("PLAYER"); if (playerWidget != null) { playerWidget.IsVisible = () => isVideoLoaded && !isLoadError; } var modelWidget = panel.GetOrNull <ModelWidget>("VOXEL"); if (modelWidget != null) { modelWidget.GetVoxel = () => currentVoxel; currentPalette = modelWidget.Palette; modelWidget.GetPalette = () => currentPalette; modelWidget.GetPlayerPalette = () => currentPalette; modelWidget.GetRotation = () => modelOrientation; modelWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentVoxel != null; } var errorLabelWidget = panel.GetOrNull("ERROR"); if (errorLabelWidget != null) { errorLabelWidget.IsVisible = () => isLoadError; } var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR"); if (paletteDropDown != null) { paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world); paletteDropDown.GetText = () => currentPalette; } var colorPreview = panel.GetOrNull <ColorPreviewManagerWidget>("COLOR_MANAGER"); if (colorPreview != null) { colorPreview.Color = Game.Settings.Player.Color; } var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR"); if (colorDropdown != null) { colorDropdown.IsDisabled = () => currentPalette != colorPreview.PaletteName; colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, world); panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color; } filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT"); filenameInput.OnTextEdited = () => ApplyFilter(); filenameInput.OnEscKey = filenameInput.YieldKeyboardFocus; var frameContainer = panel.GetOrNull("FRAME_SELECTOR"); if (frameContainer != null) { frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) || (isVideoLoaded && player != null && player.Video != null && player.Video.Frames > 1); } frameSlider = panel.GetOrNull <SliderWidget>("FRAME_SLIDER"); if (frameSlider != null) { frameSlider.OnChange += x => { if (!isVideoLoaded) { currentFrame = (int)Math.Round(x); } }; frameSlider.GetValue = () => isVideoLoaded ? player.Video.CurrentFrame : currentFrame; frameSlider.IsDisabled = () => isVideoLoaded; } var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT"); if (frameText != null) { frameText.GetText = () => isVideoLoaded ? $"{player.Video.CurrentFrame + 1} / {player.Video.Frames}" : $"{currentFrame} / {currentSprites.Length - 1}"; } var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY"); if (playButton != null) { playButton.OnClick = () => { if (isVideoLoaded) { player.Play(); } else { animateFrames = true; } }; playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames; } var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE"); if (pauseButton != null) { pauseButton.OnClick = () => { if (isVideoLoaded) { player.Pause(); } else { animateFrames = false; } }; pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : animateFrames; } var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP"); if (stopButton != null) { stopButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } else { if (frameSlider != null) { frameSlider.Value = 0; } currentFrame = 0; animateFrames = false; } }; } var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT"); if (nextButton != null) { nextButton.OnClick = () => { if (!isVideoLoaded) { nextButton.OnClick = SelectNextFrame; } }; nextButton.IsVisible = () => !isVideoLoaded; } var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV"); if (prevButton != null) { prevButton.OnClick = () => { if (!isVideoLoaded) { SelectPreviousFrame(); } }; prevButton.IsVisible = () => !isVideoLoaded; } var voxelContainer = panel.GetOrNull("VOXEL_SELECTOR"); if (voxelContainer != null) { voxelContainer.IsVisible = () => currentVoxel != null; } var rollSlider = panel.GetOrNull <SliderWidget>("ROLL_SLIDER"); if (rollSlider != null) { rollSlider.OnChange += x => { var roll = (int)x; modelOrientation = modelOrientation.WithRoll(new WAngle(roll)); }; rollSlider.GetValue = () => modelOrientation.Roll.Angle; } var pitchSlider = panel.GetOrNull <SliderWidget>("PITCH_SLIDER"); if (pitchSlider != null) { pitchSlider.OnChange += x => { var pitch = (int)x; modelOrientation = modelOrientation.WithPitch(new WAngle(pitch)); }; pitchSlider.GetValue = () => modelOrientation.Pitch.Angle; } var yawSlider = panel.GetOrNull <SliderWidget>("YAW_SLIDER"); if (yawSlider != null) { yawSlider.OnChange += x => { var yaw = (int)x; modelOrientation = modelOrientation.WithYaw(new WAngle(yaw)); }; yawSlider.GetValue = () => modelOrientation.Yaw.Angle; } var assetBrowserModData = modData.Manifest.Get <AssetBrowser>(); allowedExtensions = assetBrowserModData.SupportedExtensions; acceptablePackages = modData.ModFiles.MountedPackages.Where(p => p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant()))); assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST"); template = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE"); PopulateAssetList(); var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON"); if (closeButton != null) { closeButton.OnClick = () => { if (isVideoLoaded) { player.Stop(); } Ui.CloseWindow(); onExit(); } } ; } void SelectNextFrame() { currentFrame++; if (currentFrame >= currentSprites.Length) { currentFrame = 0; } } void SelectPreviousFrame() { currentFrame--; if (currentFrame < 0) { currentFrame = currentSprites.Length - 1; } } Dictionary <string, bool> assetVisByName = new Dictionary <string, bool>(); bool FilterAsset(string filename) { var filter = filenameInput.Text; if (string.IsNullOrWhiteSpace(filter)) { return(true); } if (filename.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0) { return(true); } return(false); } void ApplyFilter() { assetVisByName.Clear(); assetList.Layout.AdjustChildren(); assetList.ScrollToTop(); // Select the first visible var firstVisible = assetVisByName.FirstOrDefault(kvp => kvp.Value); if (firstVisible.Key != null && modData.DefaultFileSystem.TryGetPackageContaining(firstVisible.Key, out var package, out var filename)) { LoadAsset(package, filename); } } void AddAsset(ScrollPanelWidget list, string filepath, IReadOnlyPackage package, ScrollItemWidget template) { var item = ScrollItemWidget.Setup(template, () => currentFilename == filepath && currentPackage == package, () => { LoadAsset(package, filepath); }); var label = item.Get <LabelWithTooltipWidget>("TITLE"); WidgetUtils.TruncateLabelToTooltip(label, filepath); item.IsVisible = () => { if (assetVisByName.TryGetValue(filepath, out var visible)) { return(visible); } visible = FilterAsset(filepath); assetVisByName.Add(filepath, visible); return(visible); }; list.AddChild(item); } bool LoadAsset(IReadOnlyPackage package, string filename) { if (isVideoLoaded) { player.Stop(); player = null; isVideoLoaded = false; } if (string.IsNullOrEmpty(filename)) { return(false); } if (!package.Contains(filename)) { return(false); } isLoadError = false; try { currentPackage = package; currentFilename = filename; var prefix = ""; if (modData.DefaultFileSystem is OpenRA.FileSystem.FileSystem fs) { prefix = fs.GetPrefix(package); if (prefix != null) { prefix += "|"; } } var video = VideoLoader.GetVideo(Game.ModData.DefaultFileSystem.Open(filename), Game.ModData.VideoLoaders); if (video != null) { player = panel.Get <VideoPlayerWidget>("PLAYER"); player.Load(prefix + filename); player.DrawOverlay = false; isVideoLoaded = true; if (frameSlider != null) { frameSlider.MaximumValue = (float)player.Video.Frames - 1; frameSlider.Ticks = 0; } return(true); } if (Path.GetExtension(filename.ToLowerInvariant()) == ".vxl") { var voxelName = Path.GetFileNameWithoutExtension(filename); currentVoxel = world.ModelCache.GetModel(voxelName); currentSprites = null; } else { currentSprites = world.Map.Rules.Sequences.SpriteCache[prefix + filename]; currentFrame = 0; if (frameSlider != null) { frameSlider.MaximumValue = (float)currentSprites.Length - 1; frameSlider.Ticks = currentSprites.Length; } currentVoxel = null; } } catch (Exception ex) { isLoadError = true; Log.AddChannel("assetbrowser", "assetbrowser.log"); Log.Write("assetbrowser", "Error reading {0}:{3} {1}{3}{2}", filename, ex.Message, ex.StackTrace, Environment.NewLine); return(false); } return(true); } bool ShowSourceDropdown(DropDownButtonWidget dropdown) { var sourceName = new CachedTransform <IReadOnlyPackage, string>(GetSourceDisplayName); Func <IReadOnlyPackage, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => assetSource == source, () => { assetSource = source; PopulateAssetList(); }); item.Get <LabelWidget>("LABEL").GetText = () => sourceName.Update(source); return(item); }; var sources = new[] { (IReadOnlyPackage)null }.Concat(acceptablePackages); dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem); return(true); } void PopulateAssetList() { assetList.RemoveChildren(); var files = new SortedList <string, List <IReadOnlyPackage> >(); if (assetSource != null) { foreach (var content in assetSource.Contents) { files.Add(content, new List <IReadOnlyPackage> { assetSource }); } } else { foreach (var mountedPackage in modData.ModFiles.MountedPackages) { foreach (var content in mountedPackage.Contents) { if (!files.ContainsKey(content)) { files.Add(content, new List <IReadOnlyPackage> { mountedPackage }); } else { files[content].Add(mountedPackage); } } } } foreach (var file in files.OrderBy(s => s.Key)) { if (!allowedExtensions.Any(ext => file.Key.EndsWith(ext, true, CultureInfo.InvariantCulture))) { continue; } foreach (var package in file.Value) { AddAsset(assetList, file.Key, package, template); } } } bool ShowPaletteDropdown(DropDownButtonWidget dropdown, World world) { Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (name, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => currentPalette == name, () => currentPalette = name); item.Get <LabelWidget>("LABEL").GetText = () => name; return(item); }; var palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>() .SelectMany(p => p.PaletteNames); dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, palettes, setupItem); return(true); } string GetSourceDisplayName(IReadOnlyPackage source) { if (source == null) { return("All Packages"); } // Packages that are explicitly mounted in the filesystem use their explicit mount name var fs = (OpenRA.FileSystem.FileSystem)modData.DefaultFileSystem; var name = fs.GetPrefix(source); // Fall back to the path relative to the mod, engine, or support dir if (name == null) { name = source.Name; var compare = Platform.CurrentPlatform == PlatformType.Windows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; if (name.StartsWith(modData.Manifest.Package.Name, compare)) { name = "$" + modData.Manifest.Id + "/" + name.Substring(modData.Manifest.Package.Name.Length + 1); } else if (name.StartsWith(Platform.EngineDir, compare)) { name = "./" + name.Substring(Platform.EngineDir.Length); } else if (name.StartsWith(Platform.SupportDir, compare)) { name = "^" + name.Substring(Platform.SupportDir.Length); } } if (name.Length > 18) { name = "..." + name.Substring(name.Length - 15); } return(name); } }
public ServerListLogic(Widget widget, ModData modData, Action <GameServer> onJoin) { this.modData = modData; this.onJoin = onJoin; services = modData.Manifest.Get <WebServices>(); incompatibleVersionColor = ChromeMetrics.Get <Color>("IncompatibleVersionColor"); incompatibleGameColor = ChromeMetrics.Get <Color>("IncompatibleGameColor"); incompatibleProtectedGameColor = ChromeMetrics.Get <Color>("IncompatibleProtectedGameColor"); protectedGameColor = ChromeMetrics.Get <Color>("ProtectedGameColor"); waitingGameColor = ChromeMetrics.Get <Color>("WaitingGameColor"); incompatibleWaitingGameColor = ChromeMetrics.Get <Color>("IncompatibleWaitingGameColor"); gameStartedColor = ChromeMetrics.Get <Color>("GameStartedColor"); incompatibleGameStartedColor = ChromeMetrics.Get <Color>("IncompatibleGameStartedColor"); serverList = widget.Get <ScrollPanelWidget>("SERVER_LIST"); headerTemplate = serverList.Get <ScrollItemWidget>("HEADER_TEMPLATE"); serverTemplate = serverList.Get <ScrollItemWidget>("SERVER_TEMPLATE"); noticeContainer = widget.GetOrNull("NOTICE_CONTAINER"); if (noticeContainer != null) { noticeContainer.IsVisible = () => showNotices; noticeContainer.Get("OUTDATED_VERSION_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.Outdated; noticeContainer.Get("UNKNOWN_VERSION_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.Unknown; noticeContainer.Get("PLAYTEST_AVAILABLE_LABEL").IsVisible = () => services.ModVersionStatus == ModVersionStatus.PlaytestAvailable; } var noticeWatcher = widget.Get <LogicTickerWidget>("NOTICE_WATCHER"); if (noticeWatcher != null && noticeContainer != null) { var containerHeight = noticeContainer.Bounds.Height; noticeWatcher.OnTick = () => { var show = services.ModVersionStatus != ModVersionStatus.NotChecked && services.ModVersionStatus != ModVersionStatus.Latest; if (show != showNotices) { var dir = show ? 1 : -1; serverList.Bounds.Y += dir * containerHeight; serverList.Bounds.Height -= dir * containerHeight; showNotices = show; } }; } joinButton = widget.GetOrNull <ButtonWidget>("JOIN_BUTTON"); if (joinButton != null) { joinButton.IsVisible = () => currentServer != null; joinButton.IsDisabled = () => !currentServer.IsJoinable; joinButton.OnClick = () => onJoin(currentServer); joinButtonY = joinButton.Bounds.Y; } // Display the progress label over the server list // The text is only visible when the list is empty var progressText = widget.Get <LabelWidget>("PROGRESS_LABEL"); progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; progressText.GetText = ProgressLabelText; var gs = Game.Settings.Game; Action <MPGameFilters> toggleFilterFlag = f => { gs.MPGameFilters ^= f; Game.Settings.Save(); RefreshServerList(); }; var filtersButton = widget.GetOrNull <DropDownButtonWidget>("FILTERS_DROPDOWNBUTTON"); if (filtersButton != null) { // HACK: MULTIPLAYER_FILTER_PANEL doesn't follow our normal procedure for dropdown creation // but we still need to be able to set the dropdown width based on the parent // The yaml should use PARENT_RIGHT instead of DROPDOWN_WIDTH var filtersPanel = Ui.LoadWidget("MULTIPLAYER_FILTER_PANEL", filtersButton, new WidgetArgs()); filtersButton.Children.Remove(filtersPanel); var showWaitingCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("WAITING_FOR_PLAYERS"); if (showWaitingCheckbox != null) { showWaitingCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Waiting); showWaitingCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Waiting); } var showEmptyCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("EMPTY"); if (showEmptyCheckbox != null) { showEmptyCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Empty); showEmptyCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Empty); } var showAlreadyStartedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("ALREADY_STARTED"); if (showAlreadyStartedCheckbox != null) { showAlreadyStartedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Started); showAlreadyStartedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Started); } var showProtectedCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("PASSWORD_PROTECTED"); if (showProtectedCheckbox != null) { showProtectedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Protected); showProtectedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Protected); } var showIncompatibleCheckbox = filtersPanel.GetOrNull <CheckboxWidget>("INCOMPATIBLE_VERSION"); if (showIncompatibleCheckbox != null) { showIncompatibleCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Incompatible); showIncompatibleCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Incompatible); } filtersButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; filtersButton.OnMouseDown = _ => { filtersButton.RemovePanel(); filtersButton.AttachPanel(filtersPanel); }; } var reloadButton = widget.GetOrNull <ButtonWidget>("RELOAD_BUTTON"); if (reloadButton != null) { reloadButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; reloadButton.OnClick = RefreshServerList; var reloadIcon = reloadButton.GetOrNull <ImageWidget>("IMAGE_RELOAD"); if (reloadIcon != null) { var disabledFrame = 0; var disabledImage = "disabled-" + disabledFrame.ToString(); reloadIcon.GetImageName = () => searchStatus == SearchStatus.Fetching ? disabledImage : reloadIcon.ImageName; var reloadTicker = reloadIcon.Get <LogicTickerWidget>("ANIMATION"); if (reloadTicker != null) { reloadTicker.OnTick = () => { disabledFrame = searchStatus == SearchStatus.Fetching ? (disabledFrame + 1) % 12 : 0; disabledImage = "disabled-" + disabledFrame.ToString(); }; } } } var playersLabel = widget.GetOrNull <LabelWidget>("PLAYER_COUNT"); if (playersLabel != null) { var playersText = new CachedTransform <int, string>(c => c == 1 ? "1 Player Online" : c.ToString() + " Players Online"); playersLabel.IsVisible = () => playerCount != 0; playersLabel.GetText = () => playersText.Update(playerCount); } mapPreview = widget.GetOrNull <MapPreviewWidget>("SELECTED_MAP_PREVIEW"); if (mapPreview != null) { mapPreview.Preview = () => currentMap; } var mapTitle = widget.GetOrNull <LabelWidget>("SELECTED_MAP"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => { if (currentMap == null) { return("No Server Selected"); } if (currentMap.Status == MapStatus.Searching) { return("Searching..."); } if (currentMap.Class == MapClassification.Unknown) { return("Unknown Map"); } return(title.Update(currentMap)); }; } var ip = widget.GetOrNull <LabelWidget>("SELECTED_IP"); if (ip != null) { ip.IsVisible = () => currentServer != null; ip.GetText = () => currentServer.Address; } var status = widget.GetOrNull <LabelWidget>("SELECTED_STATUS"); if (status != null) { status.IsVisible = () => currentServer != null; status.GetText = () => GetStateLabel(currentServer); status.GetColor = () => GetStateColor(currentServer, status); } var modVersion = widget.GetOrNull <LabelWidget>("SELECTED_MOD_VERSION"); if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; var font = Game.Renderer.Fonts[modVersion.Font]; var version = new CachedTransform <GameServer, string>(s => WidgetUtils.TruncateText(s.ModLabel, modVersion.Bounds.Width, font)); modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull <LabelWidget>("SELECTED_PLAYERS"); if (players != null) { players.IsVisible = () => currentServer != null && (clientContainer == null || !currentServer.Clients.Any()); players.GetText = () => PlayersLabel(currentServer); } clientContainer = widget.GetOrNull("CLIENT_LIST_CONTAINER"); if (clientContainer != null) { clientList = Ui.LoadWidget("MULTIPLAYER_CLIENT_LIST", clientContainer, new WidgetArgs()) as ScrollPanelWidget; clientList.IsVisible = () => currentServer != null && currentServer.Clients.Any(); clientHeader = clientList.Get <ScrollItemWidget>("HEADER"); clientTemplate = clientList.Get <ScrollItemWidget>("TEMPLATE"); clientList.RemoveChildren(); } lanGameLocations = new List <BeaconLocation>(); try { lanGameProbe = new Probe("OpenRALANGame"); lanGameProbe.BeaconsUpdated += locations => lanGameLocations = locations; lanGameProbe.Start(); } catch (Exception ex) { Log.Write("debug", "BeaconLib.Probe: " + ex.Message); } RefreshServerList(); }
void SelectMap(MapPreview preview) { selectedMap = preview; // Cache the rules on a background thread to avoid jank var difficultyDisabled = true; var difficulties = new Dictionary<string, string>(); var briefingVideo = ""; var briefingVideoVisible = false; var infoVideo = ""; var infoVideoVisible = false; new Thread(() => { var mapDifficulty = preview.Rules.Actors["world"].TraitInfos<ScriptLobbyDropdownInfo>() .FirstOrDefault(sld => sld.ID == "difficulty"); if (mapDifficulty != null) { difficulty = mapDifficulty.Default; difficulties = mapDifficulty.Values; difficultyDisabled = mapDifficulty.Locked; } var missionData = preview.Rules.Actors["world"].TraitInfoOrDefault<MissionDataInfo>(); if (missionData != null) { briefingVideo = missionData.BriefingVideo; briefingVideoVisible = briefingVideo != null; infoVideo = missionData.BackgroundVideo; infoVideoVisible = infoVideo != null; var briefing = WidgetUtils.WrapText(missionData.Briefing.Replace("\\n", "\n"), description.Bounds.Width, descriptionFont); var height = descriptionFont.Measure(briefing).Y; Game.RunAfterTick(() => { if (preview == selectedMap) { description.Text = briefing; description.Bounds.Height = height; descriptionPanel.Layout.AdjustChildren(); } }); } }).Start(); startBriefingVideoButton.IsVisible = () => briefingVideoVisible && playingVideo != PlayingVideo.Briefing; startBriefingVideoButton.OnClick = () => PlayVideo(videoPlayer, briefingVideo, PlayingVideo.Briefing); startInfoVideoButton.IsVisible = () => infoVideoVisible && playingVideo != PlayingVideo.Info; startInfoVideoButton.OnClick = () => PlayVideo(videoPlayer, infoVideo, PlayingVideo.Info); descriptionPanel.ScrollToTop(); if (difficultyButton != null) { var difficultyName = new CachedTransform<string, string>(id => id == null || !difficulties.ContainsKey(id) ? "Normal" : difficulties[id]); difficultyButton.IsDisabled = () => difficultyDisabled; difficultyButton.GetText = () => difficultyName.Update(difficulty); difficultyButton.OnMouseDown = _ => { var options = difficulties.Select(kv => new DropDownOption { Title = kv.Value, IsSelected = () => difficulty == kv.Key, OnClick = () => difficulty = kv.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; }; difficultyButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } if (gameSpeedButton != null) { var speeds = modData.Manifest.Get<GameSpeeds>().Speeds; gameSpeed = "default"; gameSpeedButton.GetText = () => speeds[gameSpeed].Name; gameSpeedButton.OnMouseDown = _ => { var options = speeds.Select(s => new DropDownOption { Title = s.Value.Name, IsSelected = () => gameSpeed == s.Key, OnClick = () => gameSpeed = 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; }; gameSpeedButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer, Action <bool> hideMenu) { var player = world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); var spectatorTemplate = playerPanel.Get("SPECTATOR_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => new Pair <Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); var scoreCache = new CachedTransform <int, string>(s => s.ToString()); var teamMemberScores = t.Select(tt => tt.Second).Where(s => s != null).ToArray().Select(s => s.Experience); teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum()); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.First; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, string>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - suffixLength.Update(c.Second), nameFont) + c.Second); nameLabel.GetText = () => { var suffix = pp.WinState == WinState.Undefined ? "" : " (" + pp.WinState + ")"; if (client != null && client.State == Session.ClientState.Disconnected) { suffix = " (Gone)"; } return(name.Update(Pair.New(pp.PlayerName, suffix))); }; nameLabel.GetColor = () => pp.Color; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.Stances[pp] == Stance.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.Faction.Name; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var scoreCache = new CachedTransform <int, string>(s => s.ToString()); item.Get <LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.Second != null ? p.Second.Experience : 0); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = spectatorTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <Pair <string, string>, string>(c => WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - suffixLength.Update(c.Second), nameFont) + c.Second); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; return(name.Update(Pair.New(client.Name, suffix))); }; var kickButton = item.Get <ButtonWidget>("KICK"); kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index && client.State != Session.ClientState.Disconnected; kickButton.OnClick = () => { hideMenu(true); ConfirmationDialogs.ButtonPrompt( title: "Kick {0}?".F(client.Name), text: "They will not be able to rejoin this game.", onConfirm: () => { orderManager.IssueOrder(Order.Command("kick {0} {1}".F(client.Index, false))); hideMenu(false); }, onCancel: () => hideMenu(false), confirmText: "Kick"); }; playerPanel.AddChild(item); } } }
internal LobbyLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, OrderManager orderManager, Action onExit, Action onStart, bool skirmishMode) { Map = MapCache.UnknownMap; lobby = widget; this.modData = modData; this.orderManager = orderManager; this.onStart = onStart; this.onExit = onExit; this.skirmishMode = skirmishMode; // TODO: This needs to be reworked to support per-map tech levels, bots, etc. this.modRules = modData.DefaultRules; shellmapWorld = worldRenderer.World; 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 || !Map.RulesLoaded || Map.InvalidCustomRules || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; var mapButton = lobby.GetOrNull<ButtonWidget>("CHANGEMAP_BUTTON"); if (mapButton != null) { mapButton.IsDisabled = () => gameStarting || panel == PanelType.Kick || panel == PanelType.ForceStart || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; mapButton.OnClick = () => { var onSelect = new Action<string>(uid => { // Don't select the same map again if (uid == Map.Uid) return; orderManager.IssueOrder(Order.Command("map " + uid)); Game.Settings.Server.Map = uid; Game.Settings.Save(); }); Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", Map.Uid }, { "initialTab", MapClassification.System }, { "onExit", DoNothing }, { "onSelect", Game.IsHost ? onSelect : null }, { "filter", MapVisibility.Lobby }, }); }; } var slotsButton = lobby.GetOrNull<DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON"); if (slotsButton != null) { slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players || (orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) && orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0); slotsButton.OnMouseDown = _ => { var botNames = Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name); 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.RulesLoaded || Map.InvalidCustomRules || panel == PanelType.Kick || panel == PanelType.ForceStart; optionsTab.OnClick = () => panel = PanelType.Options; var playersTab = lobby.Get<ButtonWidget>("PLAYERS_TAB"); playersTab.IsHighlighted = () => panel == PanelType.Players; playersTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; playersTab.OnClick = () => panel = PanelType.Players; var musicTab = lobby.Get<ButtonWidget>("MUSIC_TAB"); musicTab.IsHighlighted = () => panel == PanelType.Music; musicTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; musicTab.OnClick = () => panel = PanelType.Music; // Force start panel Action startGame = () => { gameStarting = true; orderManager.IssueOrder(Order.Command("startgame")); }; var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON"); if (startGameButton != null) { startGameButton.IsDisabled = () => configurationDisabled() || Map.Status != MapStatus.Available || orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) || (orderManager.LobbyInfo.GlobalSettings.DisableSingleplayer && orderManager.LobbyInfo.IsSinglePlayer); 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) { var cheatsLocked = new CachedTransform<MapPreview, bool>( map => map.Rules.Actors["player"].TraitInfo<DeveloperModeInfo>().Locked); allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats; allowCheats.IsDisabled = () => configurationDisabled() || cheatsLocked.Update(Map); allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command( "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats))); } var crates = optionsBin.GetOrNull<CheckboxWidget>("CRATES_CHECKBOX"); if (crates != null) { var cratesLocked = new CachedTransform<MapPreview, bool>(map => { var crateSpawner = map.Rules.Actors["world"].TraitInfoOrDefault<CrateSpawnerInfo>(); return crateSpawner == null || crateSpawner.Locked; }); crates.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Crates; crates.IsDisabled = () => configurationDisabled() || cratesLocked.Update(Map); crates.OnClick = () => orderManager.IssueOrder(Order.Command( "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates))); } var creeps = optionsBin.GetOrNull<CheckboxWidget>("CREEPS_CHECKBOX"); if (creeps != null) { var creepsLocked = new CachedTransform<MapPreview, bool>(map => { var mapCreeps = map.Rules.Actors["world"].TraitInfoOrDefault<MapCreepsInfo>(); return mapCreeps == null || mapCreeps.Locked; }); creeps.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Creeps; creeps.IsDisabled = () => configurationDisabled() || creepsLocked.Update(Map); creeps.OnClick = () => orderManager.IssueOrder(Order.Command( "creeps {0}".F(!orderManager.LobbyInfo.GlobalSettings.Creeps))); } var allybuildradius = optionsBin.GetOrNull<CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX"); if (allybuildradius != null) { var allyBuildRadiusLocked = new CachedTransform<MapPreview, bool>(map => { var mapBuildRadius = map.Rules.Actors["world"].TraitInfoOrDefault<MapBuildRadiusInfo>(); return mapBuildRadius == null || mapBuildRadius.AllyBuildRadiusLocked; }); allybuildradius.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius; allybuildradius.IsDisabled = () => configurationDisabled() || allyBuildRadiusLocked.Update(Map); allybuildradius.OnClick = () => orderManager.IssueOrder(Order.Command( "allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius))); } var shortGame = optionsBin.GetOrNull<CheckboxWidget>("SHORTGAME_CHECKBOX"); if (shortGame != null) { var shortGameLocked = new CachedTransform<MapPreview, bool>( map => map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>().ShortGameLocked); shortGame.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.ShortGame; shortGame.IsDisabled = () => configurationDisabled() || shortGameLocked.Update(Map); shortGame.OnClick = () => orderManager.IssueOrder(Order.Command( "shortgame {0}".F(!orderManager.LobbyInfo.GlobalSettings.ShortGame))); } var difficulty = optionsBin.GetOrNull<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON"); if (difficulty != null) { var mapOptions = new CachedTransform<MapPreview, MapOptionsInfo>( map => map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>()); difficulty.IsVisible = () => Map.RulesLoaded && mapOptions.Update(Map).Difficulties.Any(); difficulty.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).DifficultyLocked; difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty; difficulty.OnMouseDown = _ => { var options = mapOptions.Update(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); }; optionsBin.Get<LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible; } var startingUnits = optionsBin.GetOrNull<DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON"); if (startingUnits != null) { var startUnitsInfos = new CachedTransform<MapPreview, IEnumerable<MPStartUnitsInfo>>( map => map.Rules.Actors["world"].TraitInfos<MPStartUnitsInfo>()); var startUnitsLocked = new CachedTransform<MapPreview, bool>(map => { var spawnUnitsInfo = map.Rules.Actors["world"].TraitInfoOrDefault<SpawnMPUnitsInfo>(); return spawnUnitsInfo == null || spawnUnitsInfo.Locked; }); Func<string, string> className = c => { var selectedClass = startUnitsInfos.Update(Map).Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault(); return selectedClass != null ? selectedClass : c; }; startingUnits.IsDisabled = () => configurationDisabled() || startUnitsLocked.Update(Map); startingUnits.GetText = () => !Map.RulesLoaded || startUnitsLocked.Update(Map) ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); startingUnits.OnMouseDown = _ => { var classes = startUnitsInfos.Update(Map).Select(a => a.Class).Distinct(); 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) { var playerResources = new CachedTransform<MapPreview, PlayerResourcesInfo>( map => map.Rules.Actors["player"].TraitInfo<PlayerResourcesInfo>()); startingCash.IsDisabled = () => configurationDisabled() || playerResources.Update(Map).DefaultCashLocked; startingCash.GetText = () => !Map.RulesLoaded || playerResources.Update(Map).DefaultCashLocked ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash); startingCash.OnMouseDown = _ => { var options = playerResources.Update(Map).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 mapOptions = new CachedTransform<MapPreview, MapOptionsInfo>( map => map.Rules.Actors["world"].TraitInfo<MapOptionsInfo>()); var techLevels = new CachedTransform<MapPreview, List<ProvidesTechPrerequisiteInfo>>( map => map.Rules.Actors["player"].TraitInfos<ProvidesTechPrerequisiteInfo>().ToList()); techLevel.IsVisible = () => Map.RulesLoaded && techLevels.Update(Map).Any(); var techLevelDescription = optionsBin.GetOrNull<LabelWidget>("TECHLEVEL_DESC"); if (techLevelDescription != null) techLevelDescription.IsVisible = techLevel.IsVisible; techLevel.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).TechLevelLocked; techLevel.GetText = () => !Map.RulesLoaded || mapOptions.Update(Map).TechLevelLocked ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); techLevel.OnMouseDown = _ => { var options = techLevels.Update(Map).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 = modData.Manifest.Get<GameSpeeds>().Speeds; gameSpeed.IsDisabled = 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) { var exploredMapLocked = new CachedTransform<MapPreview, bool>( map => map.Rules.Actors["player"].TraitInfo<ShroudInfo>().ExploredMapLocked); exploredMap.IsChecked = () => !orderManager.LobbyInfo.GlobalSettings.Shroud; exploredMap.IsDisabled = () => configurationDisabled() || exploredMapLocked.Update(Map); exploredMap.OnClick = () => orderManager.IssueOrder(Order.Command( "shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud))); } var enableFog = optionsBin.GetOrNull<CheckboxWidget>("FOG_CHECKBOX"); if (enableFog != null) { var fogLocked = new CachedTransform<MapPreview, bool>( map => map.Rules.Actors["player"].TraitInfo<ShroudInfo>().FogLocked); enableFog.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Fog; enableFog.IsDisabled = () => configurationDisabled() || fogLocked.Update(Map); 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(m => m.Type == ChatMessageType.Message); var lobbyChat = lobby.Get("LOBBYCHAT"); lobbyChat.IsVisible = () => chatPanel == ChatPanelType.Lobby; chatLabel = lobby.Get<LabelWidget>("LABEL_CHATTYPE"); var chatTextField = lobby.Get<TextFieldWidget>("CHAT_TEXTFIELD"); chatTextField.TakeKeyboardFocus(); chatTextField.OnEnterKey = () => { if (chatTextField.Text.Length == 0) return true; // Always scroll to bottom when we've typed something lobbyChatPanel.ScrollToBottom(); orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); chatTextField.Text = ""; return true; }; chatTextField.OnTabKey = () => { var previousText = chatTextField.Text; chatTextField.Text = tabCompletion.Complete(chatTextField.Text); chatTextField.CursorPosition = chatTextField.Text.Length; if (chatTextField.Text == previousText) return SwitchTeamChat(); else return true; }; chatTextField.OnEscKey = () => { chatTextField.Text = ""; return true; }; var lobbyChatTab = lobby.Get<ButtonWidget>("LOBBYCHAT_TAB"); lobbyChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Lobby; lobbyChatTab.OnClick = () => { chatPanel = ChatPanelType.Lobby; chatTextField.TakeKeyboardFocus(); }; var lobbyChatLabel = lobbyChatTab.Text; lobbyChatTab.GetText = () => { if (lobbyChatUnreadMessages == 0 || chatPanel == ChatPanelType.Lobby) return lobbyChatLabel; return lobbyChatLabel + " ({0})".F(lobbyChatUnreadMessages); }; lobbyChatPanel = lobby.Get<ScrollPanelWidget>("CHAT_DISPLAY"); chatTemplate = lobbyChatPanel.Get("CHAT_TEMPLATE"); lobbyChatPanel.RemoveChildren(); var settingsButton = lobby.GetOrNull<ButtonWidget>("SETTINGS_BUTTON"); if (settingsButton != null) { settingsButton.OnClick = () => Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs { { "onExit", DoNothing }, { "worldRenderer", worldRenderer } }); } // Add a bot on the first lobbyinfo update if (skirmishMode) addBotOnMapLoad = true; }
public ServerCreationLogic(Widget widget, ModData modData, Action onExit, Action openLobby) { panel = widget; onCreate = openLobby; this.onExit = onExit; var settings = Game.Settings; preview = modData.MapCache[modData.MapCache.ChooseInitialMap(Game.Settings.Server.Map, Game.CosmeticRandom)]; panel.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); }; panel.Get <ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin; var mapButton = panel.GetOrNull <ButtonWidget>("MAP_BUTTON"); if (mapButton != null) { panel.Get <ButtonWidget>("MAP_BUTTON").OnClick = () => { Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", preview.Uid }, { "initialTab", MapClassification.System }, { "onExit", () => { } }, { "onSelect", (Action <string>)(uid => preview = modData.MapCache[uid]) }, { "filter", MapVisibility.Lobby }, { "onStart", () => { } } }); }; panel.Get <MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview; var titleLabel = panel.GetOrNull <LabelWithTooltipWidget>("MAP_TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => { var truncated = WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font); if (m.Title != truncated) { titleLabel.GetTooltipText = () => m.Title; } else { titleLabel.GetTooltipText = null; } return(truncated); }); titleLabel.GetText = () => title.Update(preview); } var typeLabel = panel.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => m.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(preview); } var authorLabel = panel.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform <MapPreview, string>( m => WidgetUtils.TruncateText($"Created by {m.Author}", authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(preview); } } var serverName = panel.Get <TextFieldWidget>("SERVER_NAME"); serverName.Text = Settings.SanitizedServerName(settings.Server.Name); serverName.OnEnterKey = _ => { serverName.YieldKeyboardFocus(); return(true); }; serverName.OnLoseFocus = () => { serverName.Text = Settings.SanitizedServerName(serverName.Text); settings.Server.Name = serverName.Text; }; panel.Get <TextFieldWidget>("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); advertiseOnline = Game.Settings.Server.AdvertiseOnline; var advertiseCheckbox = panel.Get <CheckboxWidget>("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => { advertiseOnline ^= true; BuildNotices(); }; var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); if (passwordField != null) { passwordField.Text = Game.Settings.Server.Password; } noticesLabelA = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_A"); noticesLabelB = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_B"); noticesLabelC = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_C"); var noticesNoUPnP = panel.GetOrNull("NOTICES_NO_UPNP"); if (noticesNoUPnP != null) { noticesNoUPnP.IsVisible = () => advertiseOnline && (Nat.Status == NatStatus.NotSupported || Nat.Status == NatStatus.Disabled); var settingsA = noticesNoUPnP.GetOrNull("SETTINGS_A"); if (settingsA != null) { settingsA.IsVisible = () => Nat.Status == NatStatus.Disabled; } var settingsB = noticesNoUPnP.GetOrNull("SETTINGS_B"); if (settingsB != null) { settingsB.IsVisible = () => Nat.Status == NatStatus.Disabled; } } var noticesUPnP = panel.GetOrNull("NOTICES_UPNP"); if (noticesUPnP != null) { noticesUPnP.IsVisible = () => advertiseOnline && Nat.Status == NatStatus.Enabled; } var noticesLAN = panel.GetOrNull("NOTICES_LAN"); if (noticesLAN != null) { noticesLAN.IsVisible = () => !advertiseOnline; } BuildNotices(); }
internal LobbyLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, OrderManager orderManager, Action onExit, Action onStart, bool skirmishMode) { Map = MapCache.UnknownMap; lobby = widget; this.modData = modData; this.orderManager = orderManager; this.onStart = onStart; this.onExit = onExit; this.skirmishMode = skirmishMode; // TODO: This needs to be reworked to support per-map tech levels, bots, etc. this.modRules = modData.DefaultRules; shellmapWorld = worldRenderer.World; 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 || !Map.RulesLoaded || Map.InvalidCustomRules || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; var mapButton = lobby.GetOrNull<ButtonWidget>("CHANGEMAP_BUTTON"); if (mapButton != null) { mapButton.IsDisabled = () => gameStarting || panel == PanelType.Kick || panel == PanelType.ForceStart || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; mapButton.OnClick = () => { var onSelect = new Action<string>(uid => { // Don't select the same map again if (uid == Map.Uid) return; orderManager.IssueOrder(Order.Command("map " + uid)); Game.Settings.Server.Map = uid; Game.Settings.Save(); }); Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", Map.Uid }, { "initialTab", MapClassification.System }, { "onExit", DoNothing }, { "onSelect", Game.IsHost ? onSelect : null }, { "filter", MapVisibility.Lobby }, }); }; } var slotsButton = lobby.GetOrNull<DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON"); if (slotsButton != null) { slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players || (orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) && orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0); slotsButton.OnMouseDown = _ => { var botNames = Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name); 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.RulesLoaded || Map.InvalidCustomRules || panel == PanelType.Kick || panel == PanelType.ForceStart; optionsTab.OnClick = () => panel = PanelType.Options; var playersTab = lobby.Get<ButtonWidget>("PLAYERS_TAB"); playersTab.IsHighlighted = () => panel == PanelType.Players; playersTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; playersTab.OnClick = () => panel = PanelType.Players; var musicTab = lobby.Get<ButtonWidget>("MUSIC_TAB"); musicTab.IsHighlighted = () => panel == PanelType.Music; musicTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; musicTab.OnClick = () => panel = PanelType.Music; // Force start panel Action startGame = () => { gameStarting = true; orderManager.IssueOrder(Order.Command("startgame")); }; var startGameButton = lobby.GetOrNull<ButtonWidget>("START_GAME_BUTTON"); if (startGameButton != null) { startGameButton.IsDisabled = () => configurationDisabled() || Map.Status != MapStatus.Available || orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) || (!orderManager.LobbyInfo.GlobalSettings.EnableSingleplayer && orderManager.LobbyInfo.IsSinglePlayer); startGameButton.OnClick = () => { // Bots and admins don't count if (orderManager.LobbyInfo.Clients.Any(c => c.Slot != null && !c.IsAdmin && c.Bot == null && !c.IsReady)) panel = PanelType.ForceStart; else startGame(); }; } var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs()); forceStartBin.IsVisible = () => panel == PanelType.ForceStart; forceStartBin.Get("KICK_WARNING").IsVisible = () => orderManager.LobbyInfo.Clients.Any(c => c.IsInvalid); forceStartBin.Get<ButtonWidget>("OK_BUTTON").OnClick = startGame; forceStartBin.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players; // Options panel var optionCheckboxes = new Dictionary<string, string>() { { "EXPLORED_MAP_CHECKBOX", "explored" }, { "CRATES_CHECKBOX", "crates" }, { "SHORTGAME_CHECKBOX", "shortgame" }, { "FOG_CHECKBOX", "fog" }, { "ALLYBUILDRADIUS_CHECKBOX", "allybuild" }, { "ALLOWCHEATS_CHECKBOX", "cheats" }, { "CREEPS_CHECKBOX", "creeps" }, }; foreach (var kv in optionCheckboxes) { var checkbox = optionsBin.GetOrNull<CheckboxWidget>(kv.Key); if (checkbox != null) { var option = new CachedTransform<Session.Global, Session.LobbyOptionState>( gs => gs.LobbyOptions[kv.Value]); var visible = new CachedTransform<Session.Global, bool>( gs => gs.LobbyOptions.ContainsKey(kv.Value)); checkbox.IsVisible = () => visible.Update(orderManager.LobbyInfo.GlobalSettings); checkbox.IsChecked = () => option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled; checkbox.IsDisabled = () => configurationDisabled() || option.Update(orderManager.LobbyInfo.GlobalSettings).Locked; checkbox.OnClick = () => orderManager.IssueOrder(Order.Command( "option {0} {1}".F(kv.Value, !option.Update(orderManager.LobbyInfo.GlobalSettings).Enabled))); } } var optionDropdowns = new Dictionary<string, string>() { { "TECHLEVEL", "techlevel" }, { "STARTINGUNITS", "startingunits" }, { "STARTINGCASH", "startingcash" }, { "DIFFICULTY", "difficulty" }, { "GAMESPEED", "gamespeed" } }; var allOptions = new CachedTransform<MapPreview, LobbyOption[]>( map => map.Rules.Actors["player"].TraitInfos<ILobbyOptions>() .Concat(map.Rules.Actors["world"].TraitInfos<ILobbyOptions>()) .SelectMany(t => t.LobbyOptions(map.Rules)) .ToArray()); foreach (var kv in optionDropdowns) { var dropdown = optionsBin.GetOrNull<DropDownButtonWidget>(kv.Key + "_DROPDOWNBUTTON"); if (dropdown != null) { var optionValue = new CachedTransform<Session.Global, Session.LobbyOptionState>( gs => gs.LobbyOptions[kv.Value]); var option = new CachedTransform<MapPreview, LobbyOption>( map => allOptions.Update(map).FirstOrDefault(o => o.Id == kv.Value)); var getOptionLabel = new CachedTransform<string, string>(id => { string value; if (id == null || !option.Update(Map).Values.TryGetValue(id, out value)) return "Not Available"; return value; }); dropdown.GetText = () => getOptionLabel.Update(optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value); dropdown.IsVisible = () => option.Update(Map) != null; dropdown.IsDisabled = () => configurationDisabled() || optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Locked; dropdown.OnMouseDown = _ => { Func<KeyValuePair<string, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (c, template) => { Func<bool> isSelected = () => optionValue.Update(orderManager.LobbyInfo.GlobalSettings).Value == c.Key; Action onClick = () => orderManager.IssueOrder(Order.Command("option {0} {1}".F(kv.Value, c.Key))); var item = ScrollItemWidget.Setup(template, isSelected, onClick); item.Get<LabelWidget>("LABEL").GetText = () => c.Value; return item; }; var options = option.Update(Map).Values; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; var label = optionsBin.GetOrNull(kv.Key + "_DESC"); if (label != null) label.IsVisible = () => option.Update(Map) != null; } } var disconnectButton = lobby.Get<ButtonWidget>("DISCONNECT_BUTTON"); disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); }; if (skirmishMode) disconnectButton.Text = "Back"; var globalChat = Game.LoadWidget(null, "LOBBY_GLOBALCHAT_PANEL", lobby.Get("GLOBALCHAT_ROOT"), new WidgetArgs()); var globalChatInput = globalChat.Get<TextFieldWidget>("CHAT_TEXTFIELD"); globalChat.IsVisible = () => chatPanel == ChatPanelType.Global; var globalChatTab = lobby.Get<ButtonWidget>("GLOBALCHAT_TAB"); globalChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Global; globalChatTab.OnClick = () => { chatPanel = ChatPanelType.Global; globalChatInput.TakeKeyboardFocus(); }; var globalChatLabel = globalChatTab.Text; globalChatTab.GetText = () => { if (globalChatUnreadMessages == 0 || chatPanel == ChatPanelType.Global) return globalChatLabel; return globalChatLabel + " ({0})".F(globalChatUnreadMessages); }; globalChatLastReadMessages = Game.GlobalChat.History.Count(m => m.Type == ChatMessageType.Message); var lobbyChat = lobby.Get("LOBBYCHAT"); lobbyChat.IsVisible = () => chatPanel == ChatPanelType.Lobby; chatLabel = lobby.Get<LabelWidget>("LABEL_CHATTYPE"); var chatTextField = lobby.Get<TextFieldWidget>("CHAT_TEXTFIELD"); chatTextField.TakeKeyboardFocus(); chatTextField.OnEnterKey = () => { if (chatTextField.Text.Length == 0) return true; // Always scroll to bottom when we've typed something lobbyChatPanel.ScrollToBottom(); orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); chatTextField.Text = ""; return true; }; chatTextField.OnTabKey = () => { var previousText = chatTextField.Text; chatTextField.Text = tabCompletion.Complete(chatTextField.Text); chatTextField.CursorPosition = chatTextField.Text.Length; if (chatTextField.Text == previousText) return SwitchTeamChat(); else return true; }; chatTextField.OnEscKey = () => { chatTextField.Text = ""; return true; }; var lobbyChatTab = lobby.Get<ButtonWidget>("LOBBYCHAT_TAB"); lobbyChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Lobby; lobbyChatTab.OnClick = () => { chatPanel = ChatPanelType.Lobby; chatTextField.TakeKeyboardFocus(); }; var lobbyChatLabel = lobbyChatTab.Text; lobbyChatTab.GetText = () => { if (lobbyChatUnreadMessages == 0 || chatPanel == ChatPanelType.Lobby) return lobbyChatLabel; return lobbyChatLabel + " ({0})".F(lobbyChatUnreadMessages); }; lobbyChatPanel = lobby.Get<ScrollPanelWidget>("CHAT_DISPLAY"); chatTemplate = lobbyChatPanel.Get("CHAT_TEMPLATE"); lobbyChatPanel.RemoveChildren(); var settingsButton = lobby.GetOrNull<ButtonWidget>("SETTINGS_BUTTON"); if (settingsButton != null) { settingsButton.OnClick = () => Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs { { "onExit", DoNothing }, { "worldRenderer", worldRenderer } }); } // Add a bot on the first lobbyinfo update if (skirmishMode) addBotOnMapLoad = true; }
void LoadBrowserPanel(Widget widget) { var browserPanel = Game.LoadWidget(null, "MULTIPLAYER_BROWSER_PANEL", widget.Get("TOP_PANELS_ROOT"), new WidgetArgs()); browserPanel.IsVisible = () => panel == PanelType.Browser; serverList = browserPanel.Get<ScrollPanelWidget>("SERVER_LIST"); headerTemplate = serverList.Get<ScrollItemWidget>("HEADER_TEMPLATE"); serverTemplate = serverList.Get<ScrollItemWidget>("SERVER_TEMPLATE"); var join = widget.Get<ButtonWidget>("JOIN_BUTTON"); join.IsDisabled = () => currentServer == null || !currentServer.IsJoinable; join.OnClick = () => Join(currentServer); // Display the progress label over the server list // The text is only visible when the list is empty var progressText = widget.Get<LabelWidget>("PROGRESS_LABEL"); progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; progressText.GetText = ProgressLabelText; var gs = Game.Settings.Game; Action<MPGameFilters> toggleFilterFlag = f => { gs.MPGameFilters ^= f; Game.Settings.Save(); RefreshServerList(); }; var filtersPanel = Ui.LoadWidget("MULTIPLAYER_FILTER_PANEL", null, new WidgetArgs()); var showWaitingCheckbox = filtersPanel.GetOrNull<CheckboxWidget>("WAITING_FOR_PLAYERS"); if (showWaitingCheckbox != null) { showWaitingCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Waiting); showWaitingCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Waiting); } var showEmptyCheckbox = filtersPanel.GetOrNull<CheckboxWidget>("EMPTY"); if (showEmptyCheckbox != null) { showEmptyCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Empty); showEmptyCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Empty); } var showAlreadyStartedCheckbox = filtersPanel.GetOrNull<CheckboxWidget>("ALREADY_STARTED"); if (showAlreadyStartedCheckbox != null) { showAlreadyStartedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Started); showAlreadyStartedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Started); } var showProtectedCheckbox = filtersPanel.GetOrNull<CheckboxWidget>("PASSWORD_PROTECTED"); if (showProtectedCheckbox != null) { showProtectedCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Protected); showProtectedCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Protected); } var showIncompatibleCheckbox = filtersPanel.GetOrNull<CheckboxWidget>("INCOMPATIBLE_VERSION"); if (showIncompatibleCheckbox != null) { showIncompatibleCheckbox.IsChecked = () => gs.MPGameFilters.HasFlag(MPGameFilters.Incompatible); showIncompatibleCheckbox.OnClick = () => toggleFilterFlag(MPGameFilters.Incompatible); } var filtersButton = widget.GetOrNull<DropDownButtonWidget>("FILTERS_DROPDOWNBUTTON"); if (filtersButton != null) { filtersButton.OnMouseDown = _ => { filtersButton.RemovePanel(); filtersButton.AttachPanel(filtersPanel); }; } var refreshButton = widget.Get<ButtonWidget>("REFRESH_BUTTON"); refreshButton.GetText = () => searchStatus == SearchStatus.Fetching ? "Refreshing..." : "Refresh"; refreshButton.OnClick = RefreshServerList; var mapPreview = widget.GetOrNull<MapPreviewWidget>("SELECTED_MAP_PREVIEW"); if (mapPreview != null) mapPreview.Preview = () => currentMap; var mapTitle = widget.GetOrNull<LabelWidget>("SELECTED_MAP"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform<MapPreview, string>(m => m == null ? "No Server Selected" : WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(currentMap); } var ip = widget.GetOrNull<LabelWidget>("SELECTED_IP"); if (ip != null) { ip.IsVisible = () => currentServer != null; ip.GetText = () => currentServer.Address; } var status = widget.GetOrNull<LabelWidget>("SELECTED_STATUS"); if (status != null) { status.IsVisible = () => currentServer != null; status.GetText = () => GetStateLabel(currentServer); status.GetColor = () => GetStateColor(currentServer, status); } var modVersion = widget.GetOrNull<LabelWidget>("SELECTED_MOD_VERSION"); if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; var font = Game.Renderer.Fonts[modVersion.Font]; var version = new CachedTransform<GameServer, string>(s => WidgetUtils.TruncateText(s.ModLabel, mapTitle.Bounds.Width, font)); modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull<LabelWidget>("SELECTED_PLAYERS"); if (players != null) { players.IsVisible = () => currentServer != null; players.GetText = () => PlayersLabel(currentServer); } }
internal LobbyMapPreviewLogic(Widget widget, OrderManager orderManager, LobbyLogic lobby) { var available = widget.GetOrNull("MAP_AVAILABLE"); if (available != null) { available.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.RuleStatus == MapRuleStatus.Cached; var preview = available.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var titleLabel = available.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(lobby.Map); } var typeLabel = available.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { typeLabel.GetText = () => lobby.Map.Type; } var authorLabel = available.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText("Created by {0}".F(lobby.Map.Author), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(lobby.Map); } } var invalid = widget.GetOrNull("MAP_INVALID"); if (invalid != null) { invalid.IsVisible = () => lobby.Map.Status == MapStatus.Available && lobby.Map.RuleStatus == MapRuleStatus.Invalid; var preview = invalid.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var title = invalid.GetOrNull <LabelWidget>("MAP_TITLE"); if (title != null) { title.GetText = () => lobby.Map.Title; } var type = invalid.GetOrNull <LabelWidget>("MAP_TYPE"); if (type != null) { type.GetText = () => lobby.Map.Type; } } var download = widget.GetOrNull("MAP_DOWNLOADABLE"); if (download != null) { download.IsVisible = () => lobby.Map.Status == MapStatus.DownloadAvailable; var preview = download.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var title = download.GetOrNull <LabelWidget>("MAP_TITLE"); if (title != null) { title.GetText = () => lobby.Map.Title; } var type = download.GetOrNull <LabelWidget>("MAP_TYPE"); if (type != null) { type.GetText = () => lobby.Map.Type; } var author = download.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (author != null) { author.GetText = () => "Created by {0}".F(lobby.Map.Author); } var install = download.GetOrNull <ButtonWidget>("MAP_INSTALL"); if (install != null) { install.OnClick = () => lobby.Map.Install(); } } var progress = widget.GetOrNull("MAP_PROGRESS"); if (progress != null) { progress.IsVisible = () => (lobby.Map.Status != MapStatus.Available || lobby.Map.RuleStatus == MapRuleStatus.Unknown) && lobby.Map.Status != MapStatus.DownloadAvailable; var preview = progress.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.Preview = () => lobby.Map; preview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, preview, lobby.Map, mi); preview.SpawnOccupants = () => LobbyUtils.GetSpawnOccupants(orderManager.LobbyInfo, lobby.Map); var title = progress.GetOrNull <LabelWidget>("MAP_TITLE"); if (title != null) { title.GetText = () => lobby.Map.Title; } var type = progress.GetOrNull <LabelWidget>("MAP_TYPE"); if (type != null) { type.GetText = () => lobby.Map.Type; } var statusSearching = progress.GetOrNull("MAP_STATUS_SEARCHING"); if (statusSearching != null) { statusSearching.IsVisible = () => lobby.Map.Status == MapStatus.Searching; } var statusUnavailable = progress.GetOrNull("MAP_STATUS_UNAVAILABLE"); if (statusUnavailable != null) { statusUnavailable.IsVisible = () => lobby.Map.Status == MapStatus.Unavailable; } var statusError = progress.GetOrNull("MAP_STATUS_ERROR"); if (statusError != null) { statusError.IsVisible = () => lobby.Map.Status == MapStatus.DownloadError; } var statusDownloading = progress.GetOrNull <LabelWidget>("MAP_STATUS_DOWNLOADING"); if (statusDownloading != null) { statusDownloading.IsVisible = () => lobby.Map.Status == MapStatus.Downloading; statusDownloading.GetText = () => { if (lobby.Map.DownloadBytes == 0) { return("Connecting..."); } // Server does not provide the total file length if (lobby.Map.DownloadPercentage == 0) { return("Downloading {0} kB".F(lobby.Map.DownloadBytes / 1024)); } return("Downloading {0} kB ({1}%)".F(lobby.Map.DownloadBytes / 1024, lobby.Map.DownloadPercentage)); }; } var retry = progress.GetOrNull <ButtonWidget>("MAP_RETRY"); if (retry != null) { retry.IsVisible = () => (lobby.Map.Status == MapStatus.DownloadError || lobby.Map.Status == MapStatus.Unavailable) && lobby.Map != MapCache.UnknownMap; retry.OnClick = () => { if (lobby.Map.Status == MapStatus.DownloadError) { lobby.Map.Install(); } else if (lobby.Map.Status == MapStatus.Unavailable) { Game.ModData.MapCache.QueryRemoteMapDetails(new[] { lobby.Map.Uid }); } }; retry.GetText = () => lobby.Map.Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search"; } var progressbar = progress.GetOrNull <ProgressBarWidget>("MAP_PROGRESSBAR"); if (progressbar != null) { progressbar.IsIndeterminate = () => lobby.Map.DownloadPercentage == 0; progressbar.GetPercentage = () => lobby.Map.DownloadPercentage; progressbar.IsVisible = () => !retry.IsVisible(); } } }
public ServerCreationLogic(Widget widget, Action onExit, Action openLobby) { panel = widget; onCreate = openLobby; this.onExit = onExit; var settings = Game.Settings; preview = Game.ModData.MapCache[WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map)]; panel.Get<ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin; var mapButton = panel.GetOrNull<ButtonWidget>("MAP_BUTTON"); if (mapButton != null) { panel.Get<ButtonWidget>("MAP_BUTTON").OnClick = () => { Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", preview.Uid }, { "initialTab", MapClassification.System }, { "onExit", () => { } }, { "onSelect", (Action<string>)(uid => preview = Game.ModData.MapCache[uid]) }, { "filter", MapVisibility.Lobby }, { "onStart", () => { } } }); }; panel.Get<MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview; var mapTitle = panel.Get<LabelWidget>("MAP_NAME"); if (mapTitle != null) { var font = Game.Renderer.Fonts[mapTitle.Font]; var title = new CachedTransform<MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(preview); } } var serverName = panel.Get<TextFieldWidget>("SERVER_NAME"); serverName.Text = Settings.SanitizedServerName(settings.Server.Name); serverName.OnEnterKey = () => { serverName.YieldKeyboardFocus(); return true; }; serverName.OnLoseFocus = () => { serverName.Text = Settings.SanitizedServerName(serverName.Text); settings.Server.Name = serverName.Text; }; panel.Get<TextFieldWidget>("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); advertiseOnline = Game.Settings.Server.AdvertiseOnline; var externalPort = panel.Get<TextFieldWidget>("EXTERNAL_PORT"); externalPort.Text = settings.Server.ExternalPort.ToString(); externalPort.IsDisabled = () => !advertiseOnline; var advertiseCheckbox = panel.Get<CheckboxWidget>("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => advertiseOnline ^= true; allowPortForward = Game.Settings.Server.AllowPortForward; var checkboxUPnP = panel.Get<CheckboxWidget>("UPNP_CHECKBOX"); checkboxUPnP.IsChecked = () => allowPortForward; checkboxUPnP.OnClick = () => allowPortForward ^= true; checkboxUPnP.IsDisabled = () => !Game.Settings.Server.NatDeviceAvailable; var passwordField = panel.GetOrNull<PasswordFieldWidget>("PASSWORD"); if (passwordField != null) passwordField.Text = Game.Settings.Server.Password; }
internal LobbyLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, OrderManager orderManager, Action onExit, Action onStart, bool skirmishMode) { Map = MapCache.UnknownMap; lobby = widget; this.modData = modData; this.orderManager = orderManager; this.onStart = onStart; this.onExit = onExit; this.skirmishMode = skirmishMode; // TODO: This needs to be reworked to support per-map tech levels, bots, etc. this.modRules = modData.DefaultRules; shellmapWorld = worldRenderer.World; 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 || !Map.RulesLoaded || Map.InvalidCustomRules || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; var mapButton = lobby.GetOrNull <ButtonWidget>("CHANGEMAP_BUTTON"); if (mapButton != null) { mapButton.IsDisabled = () => gameStarting || panel == PanelType.Kick || panel == PanelType.ForceStart || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; mapButton.OnClick = () => { var onSelect = new Action <string>(uid => { // Don't select the same map again if (uid == Map.Uid) { return; } orderManager.IssueOrder(Order.Command("map " + uid)); Game.Settings.Server.Map = uid; Game.Settings.Save(); }); Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", Map.Uid }, { "initialTab", MapClassification.System }, { "onExit", DoNothing }, { "onSelect", Game.IsHost ? onSelect : null }, { "filter", MapVisibility.Lobby }, }); }; } var slotsButton = lobby.GetOrNull <DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON"); if (slotsButton != null) { slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players || (orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) && orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0); slotsButton.OnMouseDown = _ => { var botNames = Map.Rules.Actors["player"].TraitInfos <IBotInfo>().Select(t => t.Name); 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.RulesLoaded || Map.InvalidCustomRules || panel == PanelType.Kick || panel == PanelType.ForceStart; optionsTab.OnClick = () => panel = PanelType.Options; var playersTab = lobby.Get <ButtonWidget>("PLAYERS_TAB"); playersTab.IsHighlighted = () => panel == PanelType.Players; playersTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; playersTab.OnClick = () => panel = PanelType.Players; var musicTab = lobby.Get <ButtonWidget>("MUSIC_TAB"); musicTab.IsHighlighted = () => panel == PanelType.Music; musicTab.IsDisabled = () => panel == PanelType.Kick || panel == PanelType.ForceStart; musicTab.OnClick = () => panel = PanelType.Music; // Force start panel Action startGame = () => { gameStarting = true; orderManager.IssueOrder(Order.Command("startgame")); }; var startGameButton = lobby.GetOrNull <ButtonWidget>("START_GAME_BUTTON"); if (startGameButton != null) { startGameButton.IsDisabled = () => configurationDisabled() || Map.Status != MapStatus.Available || orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null) || (orderManager.LobbyInfo.GlobalSettings.DisableSingleplayer && orderManager.LobbyInfo.IsSinglePlayer); 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) { var cheatsLocked = new CachedTransform <MapPreview, bool>( map => map.Rules.Actors["player"].TraitInfo <DeveloperModeInfo>().Locked); allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats; allowCheats.IsDisabled = () => configurationDisabled() || cheatsLocked.Update(Map); allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command( "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats))); } var crates = optionsBin.GetOrNull <CheckboxWidget>("CRATES_CHECKBOX"); if (crates != null) { var cratesLocked = new CachedTransform <MapPreview, bool>(map => { var crateSpawner = map.Rules.Actors["world"].TraitInfoOrDefault <CrateSpawnerInfo>(); return(crateSpawner == null || crateSpawner.Locked); }); crates.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Crates; crates.IsDisabled = () => configurationDisabled() || cratesLocked.Update(Map); crates.OnClick = () => orderManager.IssueOrder(Order.Command( "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates))); } var creeps = optionsBin.GetOrNull <CheckboxWidget>("CREEPS_CHECKBOX"); if (creeps != null) { var creepsLocked = new CachedTransform <MapPreview, bool>(map => { var mapCreeps = map.Rules.Actors["world"].TraitInfoOrDefault <MapCreepsInfo>(); return(mapCreeps == null || mapCreeps.Locked); }); creeps.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Creeps; creeps.IsDisabled = () => configurationDisabled() || creepsLocked.Update(Map); creeps.OnClick = () => orderManager.IssueOrder(Order.Command( "creeps {0}".F(!orderManager.LobbyInfo.GlobalSettings.Creeps))); } var allybuildradius = optionsBin.GetOrNull <CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX"); if (allybuildradius != null) { var allyBuildRadiusLocked = new CachedTransform <MapPreview, bool>(map => { var mapBuildRadius = map.Rules.Actors["world"].TraitInfoOrDefault <MapBuildRadiusInfo>(); return(mapBuildRadius == null || mapBuildRadius.AllyBuildRadiusLocked); }); allybuildradius.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius; allybuildradius.IsDisabled = () => configurationDisabled() || allyBuildRadiusLocked.Update(Map); allybuildradius.OnClick = () => orderManager.IssueOrder(Order.Command( "allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius))); } var shortGame = optionsBin.GetOrNull <CheckboxWidget>("SHORTGAME_CHECKBOX"); if (shortGame != null) { var shortGameLocked = new CachedTransform <MapPreview, bool>( map => map.Rules.Actors["world"].TraitInfo <MapOptionsInfo>().ShortGameLocked); shortGame.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.ShortGame; shortGame.IsDisabled = () => configurationDisabled() || shortGameLocked.Update(Map); shortGame.OnClick = () => orderManager.IssueOrder(Order.Command( "shortgame {0}".F(!orderManager.LobbyInfo.GlobalSettings.ShortGame))); } var difficulty = optionsBin.GetOrNull <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON"); if (difficulty != null) { var mapOptions = new CachedTransform <MapPreview, MapOptionsInfo>( map => map.Rules.Actors["world"].TraitInfo <MapOptionsInfo>()); difficulty.IsVisible = () => Map.RulesLoaded && mapOptions.Update(Map).Difficulties.Any(); difficulty.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).DifficultyLocked; difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty; difficulty.OnMouseDown = _ => { var options = mapOptions.Update(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); }; optionsBin.Get <LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible; } var startingUnits = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON"); if (startingUnits != null) { var startUnitsInfos = new CachedTransform <MapPreview, IEnumerable <MPStartUnitsInfo> >( map => map.Rules.Actors["world"].TraitInfos <MPStartUnitsInfo>()); var startUnitsLocked = new CachedTransform <MapPreview, bool>(map => { var spawnUnitsInfo = map.Rules.Actors["world"].TraitInfoOrDefault <SpawnMPUnitsInfo>(); return(spawnUnitsInfo == null || spawnUnitsInfo.Locked); }); Func <string, string> className = c => { var selectedClass = startUnitsInfos.Update(Map).Where(s => s.Class == c).Select(u => u.ClassName).FirstOrDefault(); return(selectedClass != null ? selectedClass : c); }; startingUnits.IsDisabled = () => configurationDisabled() || startUnitsLocked.Update(Map); startingUnits.GetText = () => !Map.RulesLoaded || startUnitsLocked.Update(Map) ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); startingUnits.OnMouseDown = _ => { var classes = startUnitsInfos.Update(Map).Select(a => a.Class).Distinct(); 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) { var playerResources = new CachedTransform <MapPreview, PlayerResourcesInfo>( map => map.Rules.Actors["player"].TraitInfo <PlayerResourcesInfo>()); startingCash.IsDisabled = () => configurationDisabled() || playerResources.Update(Map).DefaultCashLocked; startingCash.GetText = () => !Map.RulesLoaded || playerResources.Update(Map).DefaultCashLocked ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash); startingCash.OnMouseDown = _ => { var options = playerResources.Update(Map).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 mapOptions = new CachedTransform <MapPreview, MapOptionsInfo>( map => map.Rules.Actors["world"].TraitInfo <MapOptionsInfo>()); var techLevels = new CachedTransform <MapPreview, List <ProvidesTechPrerequisiteInfo> >( map => map.Rules.Actors["player"].TraitInfos <ProvidesTechPrerequisiteInfo>().ToList()); techLevel.IsVisible = () => Map.RulesLoaded && techLevels.Update(Map).Any(); var techLevelDescription = optionsBin.GetOrNull <LabelWidget>("TECHLEVEL_DESC"); if (techLevelDescription != null) { techLevelDescription.IsVisible = techLevel.IsVisible; } techLevel.IsDisabled = () => configurationDisabled() || mapOptions.Update(Map).TechLevelLocked; techLevel.GetText = () => !Map.RulesLoaded || mapOptions.Update(Map).TechLevelLocked ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel); techLevel.OnMouseDown = _ => { var options = techLevels.Update(Map).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 = modData.Manifest.Get <GameSpeeds>().Speeds; gameSpeed.IsDisabled = 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) { var exploredMapLocked = new CachedTransform <MapPreview, bool>( map => map.Rules.Actors["player"].TraitInfo <ShroudInfo>().ExploredMapLocked); exploredMap.IsChecked = () => !orderManager.LobbyInfo.GlobalSettings.Shroud; exploredMap.IsDisabled = () => configurationDisabled() || exploredMapLocked.Update(Map); exploredMap.OnClick = () => orderManager.IssueOrder(Order.Command( "shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud))); } var enableFog = optionsBin.GetOrNull <CheckboxWidget>("FOG_CHECKBOX"); if (enableFog != null) { var fogLocked = new CachedTransform <MapPreview, bool>( map => map.Rules.Actors["player"].TraitInfo <ShroudInfo>().FogLocked); enableFog.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Fog; enableFog.IsDisabled = () => configurationDisabled() || fogLocked.Update(Map); 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(m => m.Type == ChatMessageType.Message); var lobbyChat = lobby.Get("LOBBYCHAT"); lobbyChat.IsVisible = () => chatPanel == ChatPanelType.Lobby; chatLabel = lobby.Get <LabelWidget>("LABEL_CHATTYPE"); var chatTextField = lobby.Get <TextFieldWidget>("CHAT_TEXTFIELD"); chatTextField.TakeKeyboardFocus(); chatTextField.OnEnterKey = () => { if (chatTextField.Text.Length == 0) { return(true); } // Always scroll to bottom when we've typed something lobbyChatPanel.ScrollToBottom(); orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); chatTextField.Text = ""; return(true); }; chatTextField.OnTabKey = () => { var previousText = chatTextField.Text; chatTextField.Text = tabCompletion.Complete(chatTextField.Text); chatTextField.CursorPosition = chatTextField.Text.Length; if (chatTextField.Text == previousText) { return(SwitchTeamChat()); } else { return(true); } }; chatTextField.OnEscKey = () => { chatTextField.Text = ""; return(true); }; var lobbyChatTab = lobby.Get <ButtonWidget>("LOBBYCHAT_TAB"); lobbyChatTab.IsHighlighted = () => chatPanel == ChatPanelType.Lobby; lobbyChatTab.OnClick = () => { chatPanel = ChatPanelType.Lobby; chatTextField.TakeKeyboardFocus(); }; var lobbyChatLabel = lobbyChatTab.Text; lobbyChatTab.GetText = () => { if (lobbyChatUnreadMessages == 0 || chatPanel == ChatPanelType.Lobby) { return(lobbyChatLabel); } return(lobbyChatLabel + " ({0})".F(lobbyChatUnreadMessages)); }; lobbyChatPanel = lobby.Get <ScrollPanelWidget>("CHAT_DISPLAY"); chatTemplate = lobbyChatPanel.Get("CHAT_TEMPLATE"); lobbyChatPanel.RemoveChildren(); var settingsButton = lobby.GetOrNull <ButtonWidget>("SETTINGS_BUTTON"); if (settingsButton != null) { settingsButton.OnClick = () => Ui.OpenWindow("SETTINGS_PANEL", new WidgetArgs { { "onExit", DoNothing }, { "worldRenderer", worldRenderer } }); } // Add a bot on the first lobbyinfo update if (skirmishMode) { addBotOnMapLoad = true; } }
void SelectMap(MapPreview preview) { selectedMap = preview; // Cache the rules on a background thread to avoid jank var difficultyDisabled = true; var difficulties = new Dictionary <string, string>(); var briefingVideo = ""; var briefingVideoVisible = false; var infoVideo = ""; var infoVideoVisible = false; new Thread(() => { var mapDifficulty = preview.Rules.Actors["world"].TraitInfos <ScriptLobbyDropdownInfo>() .FirstOrDefault(sld => sld.ID == "difficulty"); if (mapDifficulty != null) { difficulty = mapDifficulty.Default; difficulties = mapDifficulty.Values; difficultyDisabled = mapDifficulty.Locked; } var missionData = preview.Rules.Actors["world"].TraitInfoOrDefault <MissionDataInfo>(); if (missionData != null) { briefingVideo = missionData.BriefingVideo; briefingVideoVisible = briefingVideo != null; infoVideo = missionData.BackgroundVideo; infoVideoVisible = infoVideo != null; var briefing = WidgetUtils.WrapText(missionData.Briefing.Replace("\\n", "\n"), description.Bounds.Width, descriptionFont); var height = descriptionFont.Measure(briefing).Y; Game.RunAfterTick(() => { if (preview == selectedMap) { description.Text = briefing; description.Bounds.Height = height; descriptionPanel.Layout.AdjustChildren(); } }); } }).Start(); startBriefingVideoButton.IsVisible = () => briefingVideoVisible && playingVideo != PlayingVideo.Briefing; startBriefingVideoButton.OnClick = () => PlayVideo(videoPlayer, briefingVideo, PlayingVideo.Briefing); startInfoVideoButton.IsVisible = () => infoVideoVisible && playingVideo != PlayingVideo.Info; startInfoVideoButton.OnClick = () => PlayVideo(videoPlayer, infoVideo, PlayingVideo.Info); descriptionPanel.ScrollToTop(); if (difficultyButton != null) { var difficultyName = new CachedTransform <string, string>(id => id == null || !difficulties.ContainsKey(id) ? "Normal" : difficulties[id]); difficultyButton.IsDisabled = () => difficultyDisabled; difficultyButton.GetText = () => difficultyName.Update(difficulty); difficultyButton.OnMouseDown = _ => { var options = difficulties.Select(kv => new DropDownOption { Title = kv.Value, IsSelected = () => difficulty == kv.Key, OnClick = () => difficulty = kv.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); }; difficultyButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } if (gameSpeedButton != null) { var speeds = modData.Manifest.Get <GameSpeeds>().Speeds; gameSpeed = "default"; gameSpeedButton.GetText = () => speeds[gameSpeed].Name; gameSpeedButton.OnMouseDown = _ => { var options = speeds.Select(s => new DropDownOption { Title = s.Value.Name, IsSelected = () => gameSpeed == s.Key, OnClick = () => gameSpeed = 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); }; gameSpeedButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } }
public ReplayBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart) { panel = widget; this.modData = modData; this.onStart = onStart; Game.BeforeGameStart += OnGameStart; playerList = panel.Get <ScrollPanelWidget>("PLAYER_LIST"); playerHeader = playerList.Get <ScrollItemWidget>("HEADER"); playerTemplate = playerList.Get <ScrollItemWidget>("TEMPLATE"); playerList.RemoveChildren(); panel.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => { cancelLoadingReplays = true; Ui.CloseWindow(); onExit(); }; replayList = panel.Get <ScrollPanelWidget>("REPLAY_LIST"); var template = panel.Get <ScrollItemWidget>("REPLAY_TEMPLATE"); var mod = modData.Manifest; var dir = Platform.ResolvePath("^", "Replays", mod.Id, mod.Metadata.Version); if (Directory.Exists(dir)) { ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template)); } var watch = panel.Get <ButtonWidget>("WATCH_BUTTON"); watch.IsDisabled = () => selectedReplay == null || selectedReplay.GameInfo.MapPreview.Status != MapStatus.Available; watch.OnClick = () => { WatchReplay(); }; panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null; var preview = panel.Get <MapPreviewWidget>("MAP_PREVIEW"); preview.SpawnOccupants = () => selectedSpawns; preview.Preview = () => selectedReplay != null ? selectedReplay.GameInfo.MapPreview : null; var titleLabel = panel.GetOrNull <LabelWidget>("MAP_TITLE"); if (titleLabel != null) { titleLabel.IsVisible = () => selectedReplay != null; var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(selectedReplay.GameInfo.MapPreview); } var type = panel.GetOrNull <LabelWidget>("MAP_TYPE"); if (type != null) { var mapType = new CachedTransform <MapPreview, string>(m => m.Categories.FirstOrDefault() ?? ""); type.GetText = () => mapType.Update(selectedReplay.GameInfo.MapPreview); } panel.Get <LabelWidget>("DURATION").GetText = () => WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds); SetupFilters(); SetupManagement(); }