public override void Display() { if (r == null) { return; } // Update text at most every 0.5 seconds if (lastUpdate.Elapsed.TotalSeconds < 0.5) { return; } if (r.Fonts == null) { return; } lastUpdate.Restart(); var text = messages.Random(Game.CosmeticRandom); var textSize = r.Fonts["Bold"].Measure(text); r.BeginFrame(int2.Zero, 1f); if (stripe != null) { WidgetUtils.FillRectWithSprite(stripeRect, stripe); } if (logo != null) { r.RgbaSpriteRenderer.DrawSprite(logo, logoPos); } r.Fonts["Bold"].DrawText(text, new float2(r.Resolution.Width - textSize.X - 20, r.Resolution.Height - textSize.Y - 20), Color.White); r.EndFrame(new NullInputHandler()); }
public AnonymousProfileTooltipLogic(Widget widget, OrderManager orderManager, Session.Client client) { var nameLabel = widget.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; widget.Bounds.Width = nameFont.Measure(nameLabel.Text).X + 2 * nameLabel.Bounds.Left; var locationLabel = widget.Get <LabelWidget>("LOCATION"); var ipLabel = widget.Get <LabelWidget>("IP"); var adminLabel = widget.Get("GAME_ADMIN"); if (client.Location != null) { var locationFont = Game.Renderer.Fonts[locationLabel.Font]; var locationWidth = widget.Bounds.Width - 2 * locationLabel.Bounds.X; var location = WidgetUtils.TruncateText(client.Location, locationWidth, locationFont); locationLabel.IsVisible = () => true; locationLabel.GetText = () => location; widget.Bounds.Height += locationLabel.Bounds.Height; ipLabel.Bounds.Y += locationLabel.Bounds.Height; adminLabel.Bounds.Y += locationLabel.Bounds.Height; } if (client.AnonymizedIPAddress != null) { ipLabel.IsVisible = () => true; ipLabel.GetText = () => client.AnonymizedIPAddress; widget.Bounds.Height += ipLabel.Bounds.Height; adminLabel.Bounds.Y += locationLabel.Bounds.Height; } if (client.IsAdmin) { adminLabel.IsVisible = () => true; widget.Bounds.Height += adminLabel.Bounds.Height; } }
public ProductionPaletteWidget(World world, WorldRenderer worldRenderer) { this.world = world; this.worldRenderer = worldRenderer; tooltipContainer = Lazy.New(() => Widget.RootWidget.GetWidget <TooltipContainerWidget>(TooltipContainer)); cantBuild = new Animation("clock"); cantBuild.PlayFetchIndex("idle", () => 0); clock = new Animation("clock"); iconSprites = Rules.Info.Values .Where(u => u.Traits.Contains <BuildableInfo>() && u.Name[0] != '^') .ToDictionary( u => u.Name, u => Game.modData.SpriteLoader.LoadAllSprites( u.Traits.Get <TooltipInfo>().Icon ?? (u.Name + "icon"))[0]); overlayFont = Game.Renderer.Fonts["TinyBold"]; holdOffset = new float2(32, 24) - overlayFont.Measure("On Hold") / 2; readyOffset = new float2(32, 24) - overlayFont.Measure("Ready") / 2; timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; queuedOffset = new float2(4, 2); }
public override void Draw() { // TODO this whole block can be removed when arrows are widgets! if (visibleIcons < buildableItems.Length) { var position = new int2(RenderBounds.X + ButtonWidget.Size / 4, RenderBounds.Y + ButtonWidget.Size / 4 + visibleIcons * ButtonWidget.Size); sidebar.Buttons.PlayFetchIndex("button-small", () => 0); WidgetUtils.DrawSHPCentered(sidebar.Buttons.Image, position, sidebar.IngameUi.Palette); sidebar.Buttons.PlayFetchIndex("button-small-down", () => 0); WidgetUtils.DrawSHPCentered(sidebar.Buttons.Image, position, sidebar.IngameUi.Palette); if (scrollOffset + visibleIcons == buildableItems.Length) { WidgetUtils.FillRectWithColor(new Rectangle( RenderBounds.X, RenderBounds.Y + visibleIcons * ButtonWidget.Size, ButtonWidget.Size / 2, ButtonWidget.Size / 2), Color.FromArgb(128, 0, 0, 0)); } sidebar.Buttons.PlayFetchIndex("button-small", () => 0); WidgetUtils.DrawSHPCentered(sidebar.Buttons.Image, position + new int2(ButtonWidget.Size / 2, 0), sidebar.IngameUi.Palette); sidebar.Buttons.PlayFetchIndex("button-small-up", () => 0); WidgetUtils.DrawSHPCentered(sidebar.Buttons.Image, position + new int2(ButtonWidget.Size / 2, 0), sidebar.IngameUi.Palette); if (scrollOffset == 0) { WidgetUtils.FillRectWithColor(new Rectangle( RenderBounds.X + ButtonWidget.Size / 2, RenderBounds.Y + visibleIcons * ButtonWidget.Size, ButtonWidget.Size / 2, ButtonWidget.Size / 2), Color.FromArgb(128, 0, 0, 0)); } } }
void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices, ScrollPanelWidget scrollPanel) { var i = 0; var options = devices.ToDictionary(d => (i++).ToString(), d => d); Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (o, itemTemplate) => { var item = ScrollItemWidget.Setup(itemTemplate, () => soundDevice == options[o], () => { soundDevice = options[o]; SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel); }); var deviceLabel = item.Get <LabelWidget>("LABEL"); var font = Game.Renderer.Fonts[deviceLabel.Font]; var label = WidgetUtils.TruncateText(options[o].Label, deviceLabel.Bounds.Width, font); deviceLabel.GetText = () => label; return(item); }; dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); }
void AddChatLine(Color c, string from, string text) { var template = chatTemplate.Clone(); var nameLabel = template.Get <LabelWidget>("NAME"); var timeLabel = template.Get <LabelWidget>("TIME"); var textLabel = template.Get <LabelWidget>("TEXT"); var name = from + ":"; var font = Game.Renderer.Fonts[nameLabel.Font]; var nameSize = font.Measure(from); var time = DateTime.Now; timeLabel.GetText = () => "{0:D2}:{1:D2}".F(time.Hour, time.Minute); nameLabel.GetColor = () => c; nameLabel.GetText = () => name; nameLabel.Bounds.Width = nameSize.X; textLabel.Bounds.X += nameSize.X; textLabel.Bounds.Width -= nameSize.X; // Hack around our hacky wordwrap behavior: need to resize the widget to fit the text text = WidgetUtils.WrapText(text, textLabel.Bounds.Width, font); textLabel.GetText = () => text; var dh = font.Measure(text).Y - textLabel.Bounds.Height; if (dh > 0) { textLabel.Bounds.Height += dh; template.Bounds.Height += dh; } chatPanel.AddChild(template); chatPanel.ScrollToBottom(); Sound.PlayNotification(null, "Sounds", "ChatLine", null); }
public override void Draw() { // Background foreach (var rect in Icons.Keys) WidgetUtils.DrawPanel("panel-black", rect.InflateBy(1,1,1,1)); // Icons foreach (var p in Icons.Values) { WidgetUtils.DrawSHP(p.Sprite, p.Pos, worldRenderer); // Charge progress clock.PlayFetchIndex("idle", () => (p.Power.TotalTime - p.Power.RemainingTime) * (clock.CurrentSequence.Length - 1) / p.Power.TotalTime); clock.Tick(); WidgetUtils.DrawSHP(clock.Image, p.Pos, worldRenderer); } // Overlay foreach (var p in Icons.Values) { if (p.Power.Ready) overlayFont.DrawTextWithContrast("Ready", p.Pos + readyOffset, Color.White, Color.Black, 1); else if (!p.Power.Active) overlayFont.DrawTextWithContrast("On Hold", p.Pos + holdOffset, Color.White, Color.Black, 1); else overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime), p.Pos + timeOffset, Color.White, Color.Black, 1); } }
void DrawBuildTabs(World world) { const int tabWidth = 24; const int tabHeight = 40; var x = paletteOrigin.X - tabWidth; var y = paletteOrigin.Y + 9; tabs.Clear(); foreach (var queue in VisibleQueues) { string[] tabKeys = { "normal", "ready", "selected" }; var producing = queue.CurrentItem(); var index = queue == CurrentQueue ? 2 : (producing != null && producing.Done) ? 1 : 0; var race = world.LocalPlayer.Country.Race; WidgetUtils.DrawRGBA(ChromeProvider.GetImage("tabs-" + tabKeys[index], race + "-" + queue.Info.Type), new float2(x, y)); var rect = new Rectangle((int)x, (int)y, tabWidth, tabHeight); tabs.Add(Pair.New(rect, HandleTabClick(queue, world))); if (rect.Contains(Viewport.LastMousePos)) { var text = queue.Info.Type; var font = Game.Renderer.Fonts["Bold"]; var sz = font.Measure(text); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(rect.Left - sz.X - 30, rect.Top, rect.Left - 5, rect.Bottom), PanelSides.All); font.DrawText(text, new float2(rect.Left - sz.X - 20, rect.Top + 12), Color.White); } y += tabHeight; } }
public override void Draw() { buttons.Clear(); if (world.LocalPlayer == null) { return; } var manager = world.LocalPlayer.PlayerActor.Trait <SupportPowerManager>(); var powers = manager.Powers.Where(p => !p.Value.Disabled); var numPowers = powers.Count(); if (numPowers == 0) { return; } var rectBounds = RenderBounds; WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-top"), new float2(rectBounds.X, rectBounds.Y)); for (var i = 1; i < numPowers; i++) { WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-middle"), new float2(rectBounds.X, rectBounds.Y + i * 51)); } WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-bottom"), new float2(rectBounds.X, rectBounds.Y + numPowers * 51)); // Hack Hack Hack rectBounds.Width = 69; rectBounds.Height = 10 + numPowers * 51 + 21; var y = rectBounds.Y + 10; foreach (var kv in powers) { var sp = kv.Value; var image = spsprites[sp.Info.Image]; var drawPos = new float2(rectBounds.X + 5, y); var rect = new Rectangle(rectBounds.X + 5, y, 64, 48); if (rect.Contains(Viewport.LastMousePos)) { var pos = drawPos.ToInt2(); var tl = new int2(pos.X - 3, pos.Y - 3); var m = new int2(pos.X + 64 + 3, pos.Y + 48 + 3); var br = tl + new int2(64 + 3 + 20, 40); if (sp.TotalTime > 0) { br += new int2(0, 20); } if (sp.Info.LongDesc != null) { br += Game.Renderer.Fonts["Regular"].Measure(sp.Info.LongDesc.Replace("\\n", "\n")); } else { br += new int2(300, 0); } var border = WidgetUtils.GetBorderSizes("dialog4"); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(tl.X, tl.Y, m.X + border[3], m.Y), PanelSides.Left | PanelSides.Top | PanelSides.Bottom | PanelSides.Center); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X - border[2], tl.Y, br.X, m.Y + border[1]), PanelSides.Top | PanelSides.Right | PanelSides.Center); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X, m.Y - border[1], br.X, br.Y), PanelSides.Left | PanelSides.Right | PanelSides.Bottom | PanelSides.Center); pos += new int2(77, 5); Game.Renderer.Fonts["Bold"].DrawText(sp.Info.Description, pos, Color.White); if (sp.TotalTime > 0) { pos += new int2(0, 20); Game.Renderer.Fonts["Bold"].DrawText(WidgetUtils.FormatTime(sp.RemainingTime).ToString(), pos, Color.White); Game.Renderer.Fonts["Bold"].DrawText("/ {0}".F(WidgetUtils.FormatTime(sp.TotalTime)), pos + new int2(45, 0), Color.White); } if (sp.Info.LongDesc != null) { pos += new int2(0, 20); Game.Renderer.Fonts["Regular"].DrawText(sp.Info.LongDesc.Replace("\\n", "\n"), pos, Color.White); } } WidgetUtils.DrawSHP(image, drawPos, worldRenderer); clock.PlayFetchIndex("idle", () => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime) * (clock.CurrentSequence.Length - 1) / sp.TotalTime); clock.Tick(); WidgetUtils.DrawSHP(clock.Image, drawPos, worldRenderer); var overlay = sp.Ready ? ReadyText : sp.Active ? null : HoldText; var font = Game.Renderer.Fonts["TinyBold"]; if (overlay != null) { var size = font.Measure(overlay); var overlayPos = drawPos + new float2(32, 16); font.DrawTextWithContrast(overlay, overlayPos - new float2(size.X / 2, 0), Color.White, Color.Black, 1); } buttons.Add(Pair.New(rect, HandleSupportPower(kv.Key, manager))); y += 51; } }
void DrawProductionTooltip(World world, string unit, Hotkey hotkey, int2 pos) { pos.Y += 15; var pl = world.LocalPlayer; var p = pos.ToFloat2() - new float2(297, -3); var info = world.Map.Rules.Actors[unit]; var tooltip = info.Traits.Get <TooltipInfo>(); var buildable = info.Traits.Get <BuildableInfo>(); var cost = info.Traits.Get <ValuedInfo>().Cost; var canBuildThis = CurrentQueue.CanBuild(info); var longDescSize = Game.Renderer.Fonts["Regular"].Measure(tooltip.Description.Replace("\\n", "\n")).Y; if (!canBuildThis) { longDescSize += 8; } WidgetUtils.DrawPanel("dialog4", new Rectangle(Game.Renderer.Resolution.Width - 300, pos.Y, 300, longDescSize + 65)); Game.Renderer.Fonts["Bold"].DrawText( tooltip.Name + (hotkey.IsValid() ? " ({0})".F(hotkey.DisplayString()) : ""), p.ToInt2() + new int2(5, 5), Color.White); var resources = pl.PlayerActor.Trait <PlayerResources>(); var power = pl.PlayerActor.Trait <PowerManager>(); DrawRightAligned("${0}".F(cost), pos + new int2(-5, 5), (resources.DisplayCash + resources.DisplayResources >= cost ? Color.White : Color.Red)); var lowpower = power.PowerState != PowerState.Normal; var time = CurrentQueue.GetBuildTime(info.Name) * ((lowpower) ? CurrentQueue.Info.LowPowerSlowdown : 1); DrawRightAligned(WidgetUtils.FormatTime(time), pos + new int2(-5, 35), lowpower ? Color.Red : Color.White); var pi = info.Traits.GetOrDefault <PowerInfo>(); if (pi != null) { DrawRightAligned("{1}{0}".F(pi.Amount, pi.Amount > 0 ? "+" : ""), pos + new int2(-5, 20), ((power.PowerProvided - power.PowerDrained) >= -pi.Amount || pi.Amount > 0) ? Color.White : Color.Red); } p += new int2(5, 35); if (!canBuildThis) { var prereqs = buildable.Prerequisites.Select(s => Description(world.Map.Rules, s)).Where(s => !s.StartsWith("~")); if (prereqs.Any()) { Game.Renderer.Fonts["Regular"].DrawText(RequiresText.F(prereqs.JoinWith(", ")), p.ToInt2(), Color.White); p += new int2(0, 8); } } p += new int2(0, 15); Game.Renderer.Fonts["Regular"].DrawText(tooltip.Description.Replace("\\n", "\n"), p.ToInt2(), Color.White); }
int DrawPalette(ProductionQueue queue) { buttons.Clear(); var paletteCollection = "palette-" + world.LocalPlayer.Country.Race; var origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9); var iconOffset = 0.5f * new float2(IconWidth, IconHeight); var x = 0; var y = 0; if (queue != null) { var buildableItems = queue.BuildableItems().ToArray(); var allBuildables = queue.AllItems().OrderBy(a => a.Traits.Get <BuildableInfo>().BuildPaletteOrder).ToArray(); var overlayBits = new List <Pair <Sprite, float2> >(); var textBits = new List <Pair <float2, string> >(); numActualRows = Math.Max((allBuildables.Count() + Columns - 1) / Columns, Rows); // Palette Background WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9)); for (var w = 0; w < numActualRows; w++) { WidgetUtils.DrawRGBA( ChromeProvider.GetImage(paletteCollection, "bg-" + (w % 4)), new float2(origin.X - 9, origin.Y + IconHeight * w)); } WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "bottom"), new float2(origin.X - 9, origin.Y - 1 + IconHeight * numActualRows)); // Icons string tooltipItem = null; var tooltipHotkey = Hotkey.Invalid; var i = 0; foreach (var item in allBuildables) { var rect = new RectangleF(origin.X + x * IconWidth, origin.Y + IconHeight * y, IconWidth, IconHeight); var drawPos = new float2(rect.Location); var icon = new Animation(world, RenderSimple.GetImage(item)); icon.Play(item.Traits.Get <TooltipInfo>().Icon); WidgetUtils.DrawSHPCentered(icon.Image, drawPos + iconOffset, worldRenderer); var firstOfThis = queue.AllQueued().FirstOrDefault(a => a.Item == item.Name); if (rect.Contains(Viewport.LastMousePos)) { tooltipItem = item.Name; tooltipHotkey = Game.Settings.Keys.GetProductionHotkey(i); } var overlayPos = drawPos + new float2(32, 16); if (firstOfThis != null) { clock.PlayFetchIndex("idle", () => (firstOfThis.TotalTime - firstOfThis.RemainingTime) * (clock.CurrentSequence.Length - 1) / firstOfThis.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, drawPos + iconOffset, worldRenderer); if (queue.CurrentItem() == firstOfThis) { textBits.Add(Pair.New(overlayPos, GetOverlayForItem(firstOfThis))); } var repeats = queue.AllQueued().Count(a => a.Item == item.Name); if (repeats > 1 || queue.CurrentItem() != firstOfThis) { textBits.Add(Pair.New(overlayPos + new float2(-24, -14), repeats.ToString())); } } else if (buildableItems.All(a => a.Name != item.Name)) { overlayBits.Add(Pair.New(cantBuild.Image, drawPos)); } var closureName = buildableItems.Any(a => a.Name == item.Name) ? item.Name : null; buttons.Add(Pair.New(new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), HandleClick(closureName, world))); if (++x == Columns) { x = 0; y++; } i++; } if (x != 0) { y++; } foreach (var ob in overlayBits) { WidgetUtils.DrawSHPCentered(ob.First, ob.Second + iconOffset, worldRenderer); } var font = Game.Renderer.Fonts["TinyBold"]; foreach (var tb in textBits) { var size = font.Measure(tb.Second); if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber / 9 % 2 == 0 || tb.Second != ReadyText) { font.DrawTextWithContrast(tb.Second, tb.First - new float2(size.X / 2, 0), Color.White, Color.Black, 1); } else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) { font.DrawTextWithContrast(tb.Second, tb.First - new float2(size.X / 2, 0), ReadyTextAltColor, Color.Black, 1); } } // Tooltip if (tooltipItem != null && !paletteAnimating && paletteOpen) { DrawProductionTooltip(world, tooltipItem, tooltipHotkey, new float2(Game.Renderer.Resolution.Width, origin.Y + numActualRows * IconHeight + 9).ToInt2()); } } // Palette Dock WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "dock-top"), new float2(Game.Renderer.Resolution.Width - 14, origin.Y - 23)); for (var i = 0; i < numActualRows; i++) { WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "dock-" + (i % 4)), new float2(Game.Renderer.Resolution.Width - 14, origin.Y + IconHeight * i)); } WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "dock-bottom"), new float2(Game.Renderer.Resolution.Width - 14, origin.Y - 1 + IconHeight * numActualRows)); return(IconHeight * y + 9); }
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette, World world) { var mapRules = palette.World.Map.Rules; var pm = palette.World.LocalPlayer.PlayerActor.Trait <PowerManager>(); var pr = palette.World.LocalPlayer.PlayerActor.Trait <PlayerResources>(); widget.IsVisible = () => palette.TooltipIcon != 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]; ActorInfo lastActor = null; tooltipContainer.BeforeRender = () => { if (palette.TooltipIcon == null) { return; } var actor = palette.TooltipIcon.Actor; if (actor == null || actor == lastActor) { return; } var tooltip = actor.TraitInfo <TooltipInfo>(); var buildable = actor.TraitInfo <BuildableInfo>(); var cost = actor.TraitInfo <ValuedInfo>().Cost; nameLabel.GetText = () => tooltip.Name; var hotkey = palette.TooltipIcon.Hotkey; var nameWidth = font.Measure(tooltip.Name).X; var hotkeyText = "({0})".F(hotkey.DisplayString()); var hotkeyWidth = hotkey.IsValid() ? font.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X : 0; hotkeyLabel.GetText = () => hotkeyText; hotkeyLabel.Bounds.X = nameWidth + 2 * nameLabel.Bounds.X; hotkeyLabel.Visible = hotkey.IsValid(); var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a)).Where(s => !s.StartsWith("~")); var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : ""; requiresLabel.GetText = () => requiresString; var power = actor.TraitInfos <PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(i => i.Amount); var powerString = power.ToString(); powerLabel.GetText = () => powerString; powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0) ? Color.White : Color.Red; powerLabel.IsVisible = () => power != 0; powerIcon.IsVisible = () => power != 0; var lowpower = pm.PowerState != PowerState.Normal; var time = palette.CurrentQueue == null ? 0 : palette.CurrentQueue.GetBuildTime(actor.Name) * (lowpower ? palette.CurrentQueue.Info.LowPowerSlowdown : 1); var timeString = WidgetUtils.FormatTime(time, world.Timestep); timeLabel.GetText = () => timeString; timeLabel.GetColor = () => lowpower ? Color.Red : Color.White; var costString = cost.ToString(); costLabel.GetText = () => costString; costLabel.GetColor = () => pr.DisplayCash + pr.DisplayResources >= cost ? Color.White : Color.Red; var descString = tooltip.Description.Replace("\\n", "\n"); descLabel.GetText = () => descString; var leftWidth = new[] { nameWidth + hotkeyWidth, requiresFont.Measure(requiresString).X, descFont.Measure(descString).X }.Aggregate(Math.Max); var rightWidth = new[] { font.Measure(powerString).X, font.Measure(timeString).X, font.Measure(costString).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 = font.Measure(tooltip.Name).Y + requiresFont.Measure(requiresString).Y + descFont.Measure(descString).Y; var rightHeight = font.Measure(powerString).Y + font.Measure(timeString).Y + font.Measure(costString).Y; widget.Bounds.Height = Math.Max(leftHeight, rightHeight) * 3 / 2 + 3 * nameLabel.Bounds.Y; lastActor = actor; }; }
void EnumerateMaps(MapClassification tab, ScrollItemWidget template) { int playerCountFilter; if (!int.TryParse(mapFilter, out playerCountFilter)) { playerCountFilter = -1; } var maps = tabMaps[tab] .Where(m => category == null || m.Categories.Contains(category)) .Where(m => mapFilter == null || (m.Title != null && m.Title.IndexOf(mapFilter, StringComparison.OrdinalIgnoreCase) >= 0) || (m.Author != null && m.Author.IndexOf(mapFilter, StringComparison.OrdinalIgnoreCase) >= 0) || m.PlayerCount == playerCountFilter) .OrderBy(m => m.PlayerCount) .ThenBy(m => m.Title); scrollpanels[tab].RemoveChildren(); foreach (var loop in maps) { var preview = loop; // Access the minimap to trigger async generation of the minimap. preview.GetMinimap(); Action dblClick = () => { if (onSelect != null) { Ui.CloseWindow(); onSelect(preview.Uid); } }; var item = ScrollItemWidget.Setup(preview.Uid, template, () => selectedUid == preview.Uid, () => selectedUid = preview.Uid, dblClick); item.IsVisible = () => item.RenderBounds.IntersectsWith(scrollpanels[tab].RenderBounds); var titleLabel = item.Get <LabelWidget>("TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = WidgetUtils.TruncateText(preview.Title, titleLabel.Bounds.Width, font); titleLabel.GetText = () => title; } var previewWidget = item.Get <MapPreviewWidget>("PREVIEW"); previewWidget.Preview = () => preview; var detailsWidget = item.GetOrNull <LabelWidget>("DETAILS"); if (detailsWidget != null) { var type = preview.Categories.FirstOrDefault(); var details = ""; if (type != null) { details = type + " "; } details += "({0} players)".F(preview.PlayerCount); detailsWidget.GetText = () => details; } var authorWidget = item.GetOrNull <LabelWidget>("AUTHOR"); if (authorWidget != null) { var font = Game.Renderer.Fonts[authorWidget.Font]; var author = WidgetUtils.TruncateText("Created by {0}".F(preview.Author), authorWidget.Bounds.Width, font); authorWidget.GetText = () => author; } var sizeWidget = item.GetOrNull <LabelWidget>("SIZE"); if (sizeWidget != null) { var size = preview.Bounds.Width + "x" + preview.Bounds.Height; var numberPlayableCells = preview.Bounds.Width * preview.Bounds.Height; if (numberPlayableCells >= 120 * 120) { size += " (Huge)"; } else if (numberPlayableCells >= 90 * 90) { size += " (Large)"; } else if (numberPlayableCells >= 60 * 60) { size += " (Medium)"; } else { size += " (Small)"; } sizeWidget.GetText = () => size; } scrollpanels[tab].AddChild(item); } if (tab == currentTab) { visibleMaps = maps.Select(m => m.Uid).ToArray(); SetupGameModeDropdown(currentTab, gameModeDropdown, template); } if (visibleMaps.Contains(selectedUid)) { scrollpanels[tab].ScrollToItem(selectedUid); } }
internal LobbyLogic(Widget widget, World world, OrderManager orderManager, Action onExit, Action onStart, bool addBots) { lobby = widget; this.orderManager = orderManager; this.OnGameStart = () => { CloseWindow(); onStart(); }; this.onExit = onExit; Game.LobbyInfoChanged += UpdateCurrentMap; Game.LobbyInfoChanged += UpdatePlayerList; Game.BeforeGameStart += OnGameStart; Game.AddChatLine += AddChatLine; Game.ConnectionStateChanged += ConnectionStateChanged; var name = lobby.GetOrNull <LabelWidget>("SERVER_NAME"); if (name != null) { name.GetText = () => orderManager.LobbyInfo.GlobalSettings.ServerName; } UpdateCurrentMap(); Players = Ui.LoadWidget <ScrollPanelWidget>("LOBBY_PLAYER_BIN", lobby.Get("PLAYER_BIN_ROOT"), new WidgetArgs()); Players.IsVisible = () => panel == PanelType.Players; EditablePlayerTemplate = Players.Get("TEMPLATE_EDITABLE_PLAYER"); NonEditablePlayerTemplate = Players.Get("TEMPLATE_NONEDITABLE_PLAYER"); EmptySlotTemplate = Players.Get("TEMPLATE_EMPTY"); EditableSpectatorTemplate = Players.Get("TEMPLATE_EDITABLE_SPECTATOR"); NonEditableSpectatorTemplate = Players.Get("TEMPLATE_NONEDITABLE_SPECTATOR"); NewSpectatorTemplate = Players.Get("TEMPLATE_NEW_SPECTATOR"); colorPreview = lobby.Get <ColorPreviewManagerWidget>("COLOR_MANAGER"); colorPreview.Color = Game.Settings.Player.Color; var mapPreview = lobby.Get <MapPreviewWidget>("MAP_PREVIEW"); mapPreview.IsVisible = () => Map != null; mapPreview.Map = () => Map; mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, Map, mi); mapPreview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, Map); var mapTitle = lobby.GetOrNull <LabelWidget>("MAP_TITLE"); if (mapTitle != null) { mapTitle.IsVisible = () => Map != null; mapTitle.GetText = () => Map.Title; } var mapType = lobby.GetOrNull <LabelWidget>("MAP_TYPE"); if (mapType != null) { mapType.IsVisible = () => Map != null; mapType.GetText = () => Map.Type; } var mapAuthor = lobby.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (mapAuthor != null) { mapAuthor.IsVisible = () => Map != null; mapAuthor.GetText = () => "Created by {0}".F(Map.Author); } CountryNames = Rules.Info["world"].Traits.WithInterface <CountryInfo>() .Where(c => c.Selectable) .ToDictionary(a => a.Race, a => a.Name); CountryNames.Add("random", "Any"); var gameStarting = false; Func <bool> configurationDisabled = () => !Game.IsHost || gameStarting || panel == PanelType.Kick || orderManager.LocalClient == null || orderManager.LocalClient.IsReady; var mapButton = lobby.GetOrNull <ButtonWidget>("CHANGEMAP_BUTTON"); if (mapButton != null) { mapButton.IsDisabled = configurationDisabled; mapButton.OnClick = () => { var onSelect = new Action <Map>(m => { orderManager.IssueOrder(Order.Command("map " + m.Uid)); Game.Settings.Server.Map = m.Uid; Game.Settings.Save(); }); Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", Map.Uid }, { "onExit", () => {} }, { "onSelect", onSelect } }); }; } var slotsButton = lobby.GetOrNull <DropDownButtonWidget>("SLOTS_DROPDOWNBUTTON"); if (slotsButton != null) { slotsButton.IsDisabled = () => configurationDisabled() || panel != PanelType.Players || !orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots || !s.LockTeam); var aiModes = Rules.Info["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name); slotsButton.OnMouseDown = _ => { var options = new Dictionary <string, IEnumerable <DropDownOption> >(); var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin); if (orderManager.LobbyInfo.Slots.Values.Any(s => s.AllowBots)) { var botOptions = new List <DropDownOption>() { new DropDownOption() { Title = "Add", IsSelected = () => false, OnClick = () => { foreach (var slot in orderManager.LobbyInfo.Slots) { var bot = aiModes.Random(Game.CosmeticRandom); var c = orderManager.LobbyInfo.ClientInSlot(slot.Key); if (slot.Value.AllowBots == true && (c == null || c.Bot != null)) { orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot.Key, botController.Index, bot))); } } } } }; if (orderManager.LobbyInfo.Clients.Any(c => c.Bot != null)) { botOptions.Add(new DropDownOption() { Title = "Remove", IsSelected = () => false, OnClick = () => { foreach (var slot in orderManager.LobbyInfo.Slots) { var c = orderManager.LobbyInfo.ClientInSlot(slot.Key); if (c != null && c.Bot != null) { orderManager.IssueOrder(Order.Command("slot_open " + slot.Value.PlayerReference)); } } } }); } options.Add("Configure Bots", botOptions); } var teamCount = (orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) + 1) / 2; if (teamCount >= 1) { var teamOptions = Enumerable.Range(2, teamCount - 1).Reverse().Select(d => new DropDownOption { Title = "{0} Teams".F(d), IsSelected = () => false, OnClick = () => orderManager.IssueOrder(Order.Command("assignteams {0}".F(d.ToString()))) }).ToList(); if (orderManager.LobbyInfo.Slots.Any(s => s.Value.AllowBots)) { teamOptions.Add(new DropDownOption { Title = "Humans vs Bots", IsSelected = () => false, OnClick = () => orderManager.IssueOrder(Order.Command("assignteams 1")) }); } teamOptions.Add(new DropDownOption { Title = "Free for all", IsSelected = () => false, OnClick = () => orderManager.IssueOrder(Order.Command("assignteams 0")) }); options.Add("Configure Teams", teamOptions); } Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get <LabelWidget>("LABEL").GetText = () => option.Title; return(item); }; slotsButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 175, options, setupItem); }; } var optionsBin = Ui.LoadWidget("LOBBY_OPTIONS_BIN", lobby, new WidgetArgs()); optionsBin.IsVisible = () => panel == PanelType.Options; var optionsButton = lobby.Get <ButtonWidget>("OPTIONS_BUTTON"); optionsButton.IsDisabled = () => panel == PanelType.Kick; optionsButton.GetText = () => panel == PanelType.Options ? "Players" : "Options"; optionsButton.OnClick = () => panel = (panel == PanelType.Options) ? PanelType.Players : PanelType.Options; var startGameButton = lobby.GetOrNull <ButtonWidget>("START_GAME_BUTTON"); if (startGameButton != null) { startGameButton.IsDisabled = () => configurationDisabled() || orderManager.LobbyInfo.Slots.Any(sl => sl.Value.Required && orderManager.LobbyInfo.ClientInSlot(sl.Key) == null); startGameButton.OnClick = () => { gameStarting = true; orderManager.IssueOrder(Order.Command("startgame")); }; } // Options panel var allowCheats = optionsBin.GetOrNull <CheckboxWidget>("ALLOWCHEATS_CHECKBOX"); if (allowCheats != null) { allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats; allowCheats.IsDisabled = () => Map.Options.Cheats.HasValue || configurationDisabled(); allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command( "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats))); } var crates = optionsBin.GetOrNull <CheckboxWidget>("CRATES_CHECKBOX"); if (crates != null) { crates.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Crates; crates.IsDisabled = () => Map.Options.Crates.HasValue || configurationDisabled(); crates.OnClick = () => orderManager.IssueOrder(Order.Command( "crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates))); } var allybuildradius = optionsBin.GetOrNull <CheckboxWidget>("ALLYBUILDRADIUS_CHECKBOX"); if (allybuildradius != null) { allybuildradius.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius; allybuildradius.IsDisabled = () => Map.Options.AllyBuildRadius.HasValue || configurationDisabled(); allybuildradius.OnClick = () => orderManager.IssueOrder(Order.Command( "allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius))); } var fragileAlliance = optionsBin.GetOrNull <CheckboxWidget>("FRAGILEALLIANCES_CHECKBOX"); if (fragileAlliance != null) { fragileAlliance.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances; fragileAlliance.IsDisabled = () => Map.Options.FragileAlliances.HasValue || configurationDisabled(); fragileAlliance.OnClick = () => orderManager.IssueOrder(Order.Command( "fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances))); } var difficulty = optionsBin.GetOrNull <DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON"); if (difficulty != null) { difficulty.IsVisible = () => Map.Options.Difficulties.Any(); difficulty.IsDisabled = configurationDisabled; difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty; difficulty.OnMouseDown = _ => { var options = Map.Options.Difficulties.Select(d => new DropDownOption { Title = d, IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d, OnClick = () => orderManager.IssueOrder(Order.Command("difficulty {0}".F(d))) }); Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get <LabelWidget>("LABEL").GetText = () => option.Title; return(item); }; difficulty.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; optionsBin.Get <LabelWidget>("DIFFICULTY_DESC").IsVisible = difficulty.IsVisible; } var startingUnits = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGUNITS_DROPDOWNBUTTON"); if (startingUnits != null) { var classNames = new Dictionary <string, string>() { { "none", "MCV Only" }, { "light", "Light Support" }, { "heavy", "Heavy Support" }, }; Func <string, string> className = c => classNames.ContainsKey(c) ? classNames[c] : c; var classes = Rules.Info["world"].Traits.WithInterface <MPStartUnitsInfo>() .Select(a => a.Class).Distinct(); startingUnits.IsDisabled = () => !Map.Options.ConfigurableStartingUnits || configurationDisabled(); startingUnits.GetText = () => !Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass); startingUnits.OnMouseDown = _ => { var options = classes.Select(c => new DropDownOption { Title = className(c), IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass == c, OnClick = () => orderManager.IssueOrder(Order.Command("startingunits {0}".F(c))) }); Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get <LabelWidget>("LABEL").GetText = () => option.Title; return(item); }; startingUnits.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; optionsBin.Get <LabelWidget>("STARTINGUNITS_DESC").IsVisible = startingUnits.IsVisible; } var startingCash = optionsBin.GetOrNull <DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON"); if (startingCash != null) { startingCash.IsDisabled = () => Map.Options.StartingCash.HasValue || configurationDisabled(); startingCash.GetText = () => Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash); startingCash.OnMouseDown = _ => { var options = Rules.Info["player"].Traits.Get <PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption { Title = "${0}".F(c), IsSelected = () => orderManager.LobbyInfo.GlobalSettings.StartingCash == c, OnClick = () => orderManager.IssueOrder(Order.Command("startingcash {0}".F(c))) }); Func <DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get <LabelWidget>("LABEL").GetText = () => option.Title; return(item); }; startingCash.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem); }; } var enableShroud = optionsBin.GetOrNull <CheckboxWidget>("SHROUD_CHECKBOX"); if (enableShroud != null) { enableShroud.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Shroud; enableShroud.IsDisabled = () => Map.Options.Shroud.HasValue || configurationDisabled(); enableShroud.OnClick = () => orderManager.IssueOrder(Order.Command( "shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud))); } var enableFog = optionsBin.GetOrNull <CheckboxWidget>("FOG_CHECKBOX"); if (enableFog != null) { enableFog.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Fog; enableFog.IsDisabled = () => Map.Options.Fog.HasValue || configurationDisabled(); enableFog.OnClick = () => orderManager.IssueOrder(Order.Command( "fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog))); } var disconnectButton = lobby.Get <ButtonWidget>("DISCONNECT_BUTTON"); disconnectButton.OnClick = () => { CloseWindow(); onExit(); }; bool teamChat = false; var chatLabel = lobby.Get <LabelWidget>("LABEL_CHATTYPE"); var chatTextField = lobby.Get <TextFieldWidget>("CHAT_TEXTFIELD"); chatTextField.OnEnterKey = () => { if (chatTextField.Text.Length == 0) { return(true); } orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); chatTextField.Text = ""; return(true); }; chatTextField.OnTabKey = () => { teamChat ^= true; chatLabel.Text = (teamChat) ? "Team:" : "Chat:"; return(true); }; chatPanel = lobby.Get <ScrollPanelWidget>("CHAT_DISPLAY"); chatTemplate = chatPanel.Get("CHAT_TEMPLATE"); chatPanel.RemoveChildren(); var musicButton = lobby.GetOrNull <ButtonWidget>("MUSIC_BUTTON"); if (musicButton != null) { musicButton.OnClick = () => Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs { { "onExit", () => {} } }); } // Add a bot on the first lobbyinfo update if (addBots) { Game.LobbyInfoChanged += WidgetUtils.Once(() => { var slot = orderManager.LobbyInfo.FirstEmptySlot(); var bot = Rules.Info["player"].Traits.WithInterface <IBotInfo>().Select(t => t.Name).FirstOrDefault(); var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin); if (slot != null && bot != null) { orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot))); } }); } }
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 <VqaPlayerWidget>("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 ? "{0} / {1}".F(player.Video.CurrentFrame + 1, player.Video.Frames) : "{0} / {1}".F(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 = ""; var fs = modData.DefaultFileSystem as OpenRA.FileSystem.FileSystem; if (fs != null) { prefix = fs.GetPrefix(package); if (prefix != null) { prefix += "|"; } } if (Path.GetExtension(filename.ToLowerInvariant()) == ".vqa") { player = panel.Get <VqaPlayerWidget>("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 => m == null ? "No Server Selected" : WidgetUtils.TruncateText(m.Title, mapTitle.Bounds.Width, font)); mapTitle.GetText = () => title.Update(currentMap); } var ip = widget.GetOrNull <LabelWidget>("SELECTED_IP"); if (ip != null) { ip.IsVisible = () => currentServer != null; ip.GetText = () => currentServer.Address; } var status = widget.GetOrNull <LabelWidget>("SELECTED_STATUS"); if (status != null) { status.IsVisible = () => currentServer != null; status.GetText = () => GetStateLabel(currentServer); status.GetColor = () => GetStateColor(currentServer, status); } var modVersion = widget.GetOrNull <LabelWidget>("SELECTED_MOD_VERSION"); if (modVersion != null) { modVersion.IsVisible = () => currentServer != null; modVersion.GetColor = () => currentServer.IsCompatible ? modVersion.TextColor : incompatibleVersionColor; var font = Game.Renderer.Fonts[modVersion.Font]; var version = new CachedTransform <GameServer, string>(s => WidgetUtils.TruncateText(s.ModLabel, modVersion.Bounds.Width, font)); modVersion.GetText = () => version.Update(currentServer); } var players = widget.GetOrNull <LabelWidget>("SELECTED_PLAYERS"); if (players != null) { players.IsVisible = () => currentServer != null && (clientContainer == null || !currentServer.Clients.Any()); players.GetText = () => PlayersLabel(currentServer); } clientContainer = widget.GetOrNull("CLIENT_LIST_CONTAINER"); if (clientContainer != null) { clientList = Ui.LoadWidget("MULTIPLAYER_CLIENT_LIST", clientContainer, new WidgetArgs()) as ScrollPanelWidget; clientList.IsVisible = () => currentServer != null && currentServer.Clients.Any(); clientHeader = clientList.Get <ScrollItemWidget>("HEADER"); clientTemplate = clientList.Get <ScrollItemWidget>("TEMPLATE"); clientList.RemoveChildren(); } lanGameLocations = new List <BeaconLocation>(); try { lanGameProbe = new Probe("OpenRALANGame"); lanGameProbe.BeaconsUpdated += locations => lanGameLocations = locations; lanGameProbe.Start(); } catch (Exception ex) { Log.Write("debug", "BeaconLib.Probe: " + ex.Message); } RefreshServerList(); }
protected override void DrawContents() { this.Sidebar.Buttons.PlayFetchIndex("sell", () => 0); WidgetUtils.DrawSpriteCentered(this.Sidebar.Buttons.Image, this.Sidebar.IngameUi.Palette, this.Center + new int2(0, this.Active ? 1 : 0)); }
List <Widget> LoadGameRows(List <GameServer> games, out ScrollItemWidget nextServerRow) { nextServerRow = null; var rows = new List <Widget>(); var mods = games.GroupBy(g => g.ModLabel) .OrderByDescending(g => GroupSortOrder(g.First())) .ThenByDescending(g => g.Count()); foreach (var modGames in mods) { if (modGames.All(Filtered)) { continue; } var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); var headerTitle = modGames.First().ModLabel; header.Get <LabelWidget>("LABEL").GetText = () => headerTitle; rows.Add(header); Func <GameServer, int> listOrder = g => { // Servers waiting for players are always first if (g.State == (int)ServerState.WaitingPlayers && g.Players > 0) { return(0); } // Then servers with spectators if (g.State == (int)ServerState.WaitingPlayers && g.Spectators > 0) { return(1); } // Then active games if (g.State >= (int)ServerState.GameStarted) { return(2); } // Empty servers are shown at the end because a flood of empty servers // at the top of the game list make the community look dead return(3); }; foreach (var modGamesByState in modGames.GroupBy(listOrder).OrderBy(g => g.Key)) { // Sort 'Playing' games by Started, others by number of players foreach (var game in modGamesByState.Key == 2 ? modGamesByState.OrderByDescending(g => g.Started) : modGamesByState.OrderByDescending(g => g.Players)) { if (Filtered(game)) { continue; } var canJoin = game.IsJoinable; var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => SelectServer(game), () => onJoin(game)); var title = item.GetOrNull <LabelWidget>("TITLE"); if (title != null) { var font = Game.Renderer.Fonts[title.Font]; var label = WidgetUtils.TruncateText(game.Name, title.Bounds.Width, font); title.GetText = () => label; title.GetColor = () => canJoin ? title.TextColor : incompatibleGameColor; } var password = item.GetOrNull <ImageWidget>("PASSWORD_PROTECTED"); if (password != null) { password.IsVisible = () => game.Protected; password.GetImageName = () => canJoin ? "protected" : "protected-disabled"; } var players = item.GetOrNull <LabelWithTooltipWidget>("PLAYERS"); if (players != null) { var label = "{0} / {1}".F(game.Players + game.Bots, game.MaxPlayers + game.Bots) + (game.Spectators > 0 ? " + {0}".F(game.Spectators) : ""); var color = canJoin ? players.TextColor : incompatibleGameColor; players.GetText = () => label; players.GetColor = () => color; if (game.Clients.Any()) { var displayClients = game.Clients.Select(c => c.Name); if (game.Clients.Length > 10) { displayClients = displayClients .Take(9) .Append("+ {0} other players".F(game.Clients.Length - 9)); } var tooltip = displayClients.JoinWith("\n"); players.GetTooltipText = () => tooltip; } else { players.GetTooltipText = null; } } var state = item.GetOrNull <LabelWidget>("STATUS"); if (state != null) { var label = game.State >= (int)ServerState.GameStarted ? "Playing" : "Waiting"; state.GetText = () => label; var color = GetStateColor(game, state, !canJoin); state.GetColor = () => color; } var location = item.GetOrNull <LabelWidget>("LOCATION"); if (location != null) { var font = Game.Renderer.Fonts[location.Font]; var cachedServerLocation = game.Id != -1 ? GeoIP.LookupCountry(game.Address.Split(':')[0]) : "Local Network"; var label = WidgetUtils.TruncateText(cachedServerLocation, location.Bounds.Width, font); location.GetText = () => label; location.GetColor = () => canJoin ? location.TextColor : incompatibleGameColor; } if (currentServer != null && game.Address == currentServer.Address) { nextServerRow = item; } rows.Add(item); } } } return(rows); }
void SelectServer(GameServer server) { currentServer = server; currentMap = server != null ? modData.MapCache[server.Map] : null; if (server == null || !server.Clients.Any()) { if (joinButton != null) { joinButton.Bounds.Y = joinButtonY; } return; } if (joinButton != null) { joinButton.Bounds.Y = clientContainer.Bounds.Bottom; } // Can only show factions if the server is running the same mod var disableFactionDisplay = server.Mod != modData.Manifest.Id; if (server != null && mapPreview != null) { var spawns = currentMap.SpawnPoints; var occupants = server.Clients .Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Length)) .ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c, disableFactionDisplay)); mapPreview.SpawnOccupants = () => occupants; } if (clientList == null) { return; } clientList.RemoveChildren(); var players = server.Clients .Where(c => !c.IsSpectator) .GroupBy(p => p.Team) .OrderBy(g => g.Key); var teams = new Dictionary <string, IEnumerable <GameClient> >(); var noTeams = players.Count() == 1; foreach (var p in players) { var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : "Team {0}".F(p.Key); teams.Add(label, p); } if (server.Clients.Any(c => c.IsSpectator)) { teams.Add("Spectators", server.Clients.Where(c => c.IsSpectator)); } var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos <FactionInfo>(); foreach (var kv in teams) { var group = kv.Key; if (group.Length > 0) { var header = ScrollItemWidget.Setup(clientHeader, () => true, () => { }); header.Get <LabelWidget>("LABEL").GetText = () => group; clientList.AddChild(header); } foreach (var option in kv.Value) { var o = option; var item = ScrollItemWidget.Setup(clientTemplate, () => false, () => { }); if (!o.IsSpectator && !disableFactionDisplay) { var label = item.Get <LabelWidget>("LABEL"); var font = Game.Renderer.Fonts[label.Font]; var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font); label.GetText = () => name; label.GetColor = () => o.Color.RGB; var flag = item.Get <ImageWidget>("FLAG"); flag.IsVisible = () => true; flag.GetImageCollection = () => "flags"; flag.GetImageName = () => (factionInfo != null && factionInfo.Any(f => f.InternalName == o.Faction)) ? o.Faction : "Random"; } else { var label = item.Get <LabelWidget>("NOFLAG_LABEL"); var font = Game.Renderer.Fonts[label.Font]; var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font); // Force spectator color to prevent spoofing by the server var color = o.IsSpectator ? Color.White : o.Color.RGB; label.GetText = () => name; label.GetColor = () => color; } clientList.AddChild(item); } } }
public string FormatTime(int ticks, bool leadingMinuteZero = true) { return(WidgetUtils.FormatTime(ticks, leadingMinuteZero, 40)); }
public GameInfoStatsLogic(Widget widget, World world, OrderManager orderManager, WorldRenderer worldRenderer, Action <bool> hideMenu) { var player = world.LocalPlayer; var playerPanel = widget.Get <ScrollPanelWidget>("PLAYER_LIST"); if (player != null && !player.NonCombatant) { var checkbox = widget.Get <CheckboxWidget>("STATS_CHECKBOX"); var statusLabel = widget.Get <LabelWidget>("STATS_STATUS"); checkbox.IsChecked = () => player.WinState != WinState.Undefined; checkbox.GetCheckType = () => player.WinState == WinState.Won ? "checked" : "crossed"; if (player.HasObjectives) { var mo = player.PlayerActor.Trait <MissionObjectives>(); checkbox.GetText = () => mo.Objectives.First().Description; } statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : player.WinState == WinState.Lost ? "Failed" : "In progress"; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } else { // Expand the stats window to cover the hidden objectives var objectiveGroup = widget.Get("OBJECTIVE"); var statsHeader = widget.Get("STATS_HEADERS"); objectiveGroup.Visible = false; statsHeader.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Y -= objectiveGroup.Bounds.Height; playerPanel.Bounds.Height += objectiveGroup.Bounds.Height; } var teamTemplate = playerPanel.Get <ScrollItemWidget>("TEAM_TEMPLATE"); var playerTemplate = playerPanel.Get("PLAYER_TEMPLATE"); var spectatorTemplate = playerPanel.Get("SPECTATOR_TEMPLATE"); playerPanel.RemoveChildren(); var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault <PlayerStatistics>())) .OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team) .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0)); foreach (var t in teams) { if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); teamHeader.Get <LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); var teamRating = teamHeader.Get <LabelWidget>("TEAM_SCORE"); var scoreCache = new CachedTransform <int, string>(s => s.ToString()); var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience); teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum()); playerPanel.AddChild(teamHeader); } foreach (var p in t.ToList()) { var pp = p.Player; var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var item = playerTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); WidgetUtils.BindPlayerNameAndStatus(nameLabel, pp); nameLabel.GetColor = () => pp.Color; var flag = item.Get <ImageWidget>("FACTIONFLAG"); flag.GetImageCollection = () => "flags"; if (player == null || player.RelationshipWith(pp) == PlayerRelationship.Ally || player.WinState != WinState.Undefined) { flag.GetImageName = () => pp.Faction.InternalName; var factionName = pp.Faction.Name != pp.DisplayFaction.Name ? "{0} ({1})".F(pp.DisplayFaction.Name, pp.Faction.Name) : pp.Faction.Name; item.Get <LabelWidget>("FACTION").GetText = () => factionName; } else { flag.GetImageName = () => pp.DisplayFaction.InternalName; item.Get <LabelWidget>("FACTION").GetText = () => pp.DisplayFaction.Name; } var scoreCache = new CachedTransform <int, string>(s => s.ToString()); item.Get <LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.PlayerStatistics?.Experience ?? 0); playerPanel.AddChild(item); } } var spectators = orderManager.LobbyInfo.Clients.Where(c => c.IsObserver).ToList(); if (spectators.Any()) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); spectatorHeader.Get <LabelWidget>("TEAM").GetText = () => "Spectators"; playerPanel.AddChild(spectatorHeader); foreach (var client in spectators) { var item = spectatorTemplate.Clone(); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); var nameLabel = item.Get <LabelWidget>("NAME"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var suffixLength = new CachedTransform <string, int>(s => nameFont.Measure(s).X); var name = new CachedTransform <(string Name, string Suffix), string>(c => WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - suffixLength.Update(c.Suffix), nameFont) + c.Suffix); nameLabel.GetText = () => { var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; return(name.Update((client.Name, suffix))); }; var kickButton = item.Get <ButtonWidget>("KICK"); kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index && client.State != Session.ClientState.Disconnected; kickButton.OnClick = () => { hideMenu(true); ConfirmationDialogs.ButtonPrompt( title: "Kick {0}?".F(client.Name), text: "They will not be able to rejoin this game.", onConfirm: () => { orderManager.IssueOrder(Order.Command("kick {0} {1}".F(client.Index, false))); hideMenu(false); }, onCancel: () => hideMenu(false), confirmText: "Kick"); }; playerPanel.AddChild(item); } } }
public ServerCreationLogic(Widget widget, ModData modData, Action onExit, Action openLobby) { panel = widget; onCreate = openLobby; this.onExit = onExit; var settings = Game.Settings; preview = modData.MapCache[modData.MapCache.ChooseInitialMap(Game.Settings.Server.Map, Game.CosmeticRandom)]; panel.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); }; panel.Get <ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin; var mapButton = panel.GetOrNull <ButtonWidget>("MAP_BUTTON"); if (mapButton != null) { panel.Get <ButtonWidget>("MAP_BUTTON").OnClick = () => { Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", preview.Uid }, { "initialTab", MapClassification.System }, { "onExit", () => { } }, { "onSelect", (Action <string>)(uid => preview = modData.MapCache[uid]) }, { "filter", MapVisibility.Lobby }, { "onStart", () => { } } }); }; panel.Get <MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview; var titleLabel = panel.GetOrNull <LabelWithTooltipWidget>("MAP_TITLE"); if (titleLabel != null) { var font = Game.Renderer.Fonts[titleLabel.Font]; var title = new CachedTransform <MapPreview, string>(m => WidgetUtils.TruncateText(m.Title, titleLabel.Bounds.Width, font)); titleLabel.GetText = () => title.Update(preview); titleLabel.GetTooltipText = () => preview.Title; } var typeLabel = panel.GetOrNull <LabelWidget>("MAP_TYPE"); if (typeLabel != null) { var type = new CachedTransform <MapPreview, string>(m => m.Categories.FirstOrDefault() ?? ""); typeLabel.GetText = () => type.Update(preview); } var authorLabel = panel.GetOrNull <LabelWidget>("MAP_AUTHOR"); if (authorLabel != null) { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform <MapPreview, string>( m => WidgetUtils.TruncateText("Created by {0}".F(m.Author), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(preview); } } var serverName = panel.Get <TextFieldWidget>("SERVER_NAME"); serverName.Text = Settings.SanitizedServerName(settings.Server.Name); serverName.OnEnterKey = () => { serverName.YieldKeyboardFocus(); return(true); }; serverName.OnLoseFocus = () => { serverName.Text = Settings.SanitizedServerName(serverName.Text); settings.Server.Name = serverName.Text; }; panel.Get <TextFieldWidget>("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); advertiseOnline = Game.Settings.Server.AdvertiseOnline; var advertiseCheckbox = panel.Get <CheckboxWidget>("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => { advertiseOnline ^= true; BuildNotices(); }; var passwordField = panel.GetOrNull <PasswordFieldWidget>("PASSWORD"); if (passwordField != null) { passwordField.Text = Game.Settings.Server.Password; } noticesLabelA = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_A"); noticesLabelB = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_B"); noticesLabelC = panel.GetOrNull <LabelWidget>("NOTICES_HEADER_C"); var noticesNoUPnP = panel.GetOrNull("NOTICES_NO_UPNP"); if (noticesNoUPnP != null) { noticesNoUPnP.IsVisible = () => advertiseOnline && (Nat.Status == NatStatus.NotSupported || Nat.Status == NatStatus.Disabled); var settingsA = noticesNoUPnP.GetOrNull("SETTINGS_A"); if (settingsA != null) { settingsA.IsVisible = () => Nat.Status == NatStatus.Disabled; } var settingsB = noticesNoUPnP.GetOrNull("SETTINGS_B"); if (settingsB != null) { settingsB.IsVisible = () => Nat.Status == NatStatus.Disabled; } } var noticesUPnP = panel.GetOrNull("NOTICES_UPNP"); if (noticesUPnP != null) { noticesUPnP.IsVisible = () => advertiseOnline && Nat.Status == NatStatus.Enabled; } var noticesLAN = panel.GetOrNull("NOTICES_LAN"); if (noticesLAN != null) { noticesLAN.IsVisible = () => !advertiseOnline; } BuildNotices(); }
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.WorldActorInfo.TraitInfos <ScriptLobbyDropdownInfo>() .FirstOrDefault(sld => sld.ID == "difficulty"); if (mapDifficulty != null) { difficulty = mapDifficulty.Default; difficulties = mapDifficulty.Values; difficultyDisabled = mapDifficulty.Locked; } var missionData = preview.WorldActorInfo.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 ConnectionSwitchModLogic(Widget widget, OrderManager orderManager, NetworkConnection connection, Action onAbort, Action <string> onRetry) { var panel = widget; var abortButton = panel.Get <ButtonWidget>("ABORT_BUTTON"); var switchButton = panel.Get <ButtonWidget>("SWITCH_BUTTON"); var mod = CurrentServerSettings.ServerExternalMod; var modTitle = mod.Title; var modVersion = mod.Version; switchButton.OnClick = () => { var launchCommand = $"Launch.URI={new UriBuilder("tcp", connection.EndPoint.Address.ToString(), connection.EndPoint.Port)}"; Game.SwitchToExternalMod(CurrentServerSettings.ServerExternalMod, new[] { launchCommand }, () => { orderManager.ServerError = "Failed to switch mod."; Ui.CloseWindow(); Ui.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() { { "orderManager", orderManager }, { "onAbort", onAbort }, { "onRetry", onRetry } }); }); }; abortButton.Visible = onAbort != null; abortButton.OnClick = () => { Ui.CloseWindow(); onAbort(); }; var width = 0; var title = panel.GetOrNull <LabelWidget>("MOD_TITLE"); if (title != null) { var font = Game.Renderer.Fonts[title.Font]; var label = WidgetUtils.TruncateText(modTitle, title.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, title.Bounds.X + labelWidth); title.Bounds.Width = labelWidth; title.GetText = () => label; } var version = panel.GetOrNull <LabelWidget>("MOD_VERSION"); if (version != null) { var font = Game.Renderer.Fonts[version.Font]; var label = WidgetUtils.TruncateText(modVersion, version.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, version.Bounds.X + labelWidth); version.Bounds.Width = labelWidth; version.GetText = () => label; } var logo = panel.GetOrNull <RGBASpriteWidget>("MOD_ICON"); if (logo != null) { logo.GetSprite = () => { var ws = Game.Renderer.WindowScale; if (ws > 2 && mod.Icon3x != null) { return(mod.Icon3x); } if (ws > 1 && mod.Icon2x != null) { return(mod.Icon2x); } return(mod.Icon); }; if (mod.Icon == null) { // Hide the logo and center just the text if (title != null) { title.Bounds.X = logo.Bounds.X; } if (version != null) { version.Bounds.X = logo.Bounds.X; } width -= logo.Bounds.Width; } else { // Add an equal logo margin on the right of the text width += logo.Bounds.Width; } } var container = panel.GetOrNull("MOD_CONTAINER"); if (container != null) { container.Bounds.X += (container.Bounds.Width - width) / 2; container.Bounds.Width = width; } }
public MainMenuLogic(Widget widget, World world, ModData modData) { rootMenu = widget; rootMenu.Get <LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version; // Menu buttons var mainMenu = widget.Get("MAIN_MENU"); mainMenu.IsVisible = () => menuType == MenuType.Main; mainMenu.Get <ButtonWidget>("SINGLEPLAYER_BUTTON").OnClick = () => SwitchMenu(MenuType.Singleplayer); mainMenu.Get <ButtonWidget>("MULTIPLAYER_BUTTON").OnClick = () => { SwitchMenu(MenuType.None); Ui.OpenWindow("MULTIPLAYER_PANEL", new WidgetArgs { { "onStart", RemoveShellmapUI }, { "onExit", () => SwitchMenu(MenuType.Main) }, { "directConnectHost", null }, { "directConnectPort", 0 }, }); }; mainMenu.Get <ButtonWidget>("CONTENT_BUTTON").OnClick = () => { // Switching mods changes the world state (by disposing it), // so we can't do this inside the input handler. Game.RunAfterTick(() => { Game.InitializeMod("modcontent", new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id })); }); }; mainMenu.Get <ButtonWidget>("SETTINGS_BUTTON").OnClick = () => { SwitchMenu(MenuType.None); Game.OpenWindow("SETTINGS_PANEL", new WidgetArgs { { "onExit", () => SwitchMenu(MenuType.Main) } }); }; mainMenu.Get <ButtonWidget>("EXTRAS_BUTTON").OnClick = () => SwitchMenu(MenuType.Extras); mainMenu.Get <ButtonWidget>("QUIT_BUTTON").OnClick = Game.Exit; // Singleplayer menu var singleplayerMenu = widget.Get("SINGLEPLAYER_MENU"); singleplayerMenu.IsVisible = () => menuType == MenuType.Singleplayer; var missionsButton = singleplayerMenu.Get <ButtonWidget>("MISSIONS_BUTTON"); missionsButton.OnClick = () => { SwitchMenu(MenuType.None); Game.OpenWindow("MISSIONBROWSER_PANEL", new WidgetArgs { { "onExit", () => SwitchMenu(MenuType.Singleplayer) }, { "onStart", RemoveShellmapUI } }); }; var hasCampaign = modData.Manifest.Missions.Any(); var hasMissions = modData.MapCache .Any(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector)); missionsButton.Disabled = !hasCampaign && !hasMissions; singleplayerMenu.Get <ButtonWidget>("SKIRMISH_BUTTON").OnClick = StartSkirmishGame; singleplayerMenu.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Main); // Extras menu var extrasMenu = widget.Get("EXTRAS_MENU"); extrasMenu.IsVisible = () => menuType == MenuType.Extras; extrasMenu.Get <ButtonWidget>("REPLAYS_BUTTON").OnClick = () => { SwitchMenu(MenuType.None); Ui.OpenWindow("REPLAYBROWSER_PANEL", new WidgetArgs { { "onExit", () => SwitchMenu(MenuType.Extras) }, { "onStart", RemoveShellmapUI } }); }; extrasMenu.Get <ButtonWidget>("MUSIC_BUTTON").OnClick = () => { SwitchMenu(MenuType.None); Ui.OpenWindow("MUSIC_PANEL", new WidgetArgs { { "onExit", () => SwitchMenu(MenuType.Extras) }, { "world", world } }); }; extrasMenu.Get <ButtonWidget>("MAP_EDITOR_BUTTON").OnClick = () => SwitchMenu(MenuType.MapEditor); var assetBrowserButton = extrasMenu.GetOrNull <ButtonWidget>("ASSETBROWSER_BUTTON"); if (assetBrowserButton != null) { assetBrowserButton.OnClick = () => { SwitchMenu(MenuType.None); Game.OpenWindow("ASSETBROWSER_PANEL", new WidgetArgs { { "onExit", () => SwitchMenu(MenuType.Extras) }, }); } } ; extrasMenu.Get <ButtonWidget>("CREDITS_BUTTON").OnClick = () => { SwitchMenu(MenuType.None); Ui.OpenWindow("CREDITS_PANEL", new WidgetArgs { { "onExit", () => SwitchMenu(MenuType.Extras) }, }); }; extrasMenu.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Main); // Map editor menu var mapEditorMenu = widget.Get("MAP_EDITOR_MENU"); mapEditorMenu.IsVisible = () => menuType == MenuType.MapEditor; // Loading into the map editor Game.BeforeGameStart += RemoveShellmapUI; var onSelect = new Action <string>(uid => LoadMapIntoEditor(modData.MapCache[uid].Uid)); var newMapButton = widget.Get <ButtonWidget>("NEW_MAP_BUTTON"); newMapButton.OnClick = () => { SwitchMenu(MenuType.None); Game.OpenWindow("NEW_MAP_BG", new WidgetArgs() { { "onSelect", onSelect }, { "onExit", () => SwitchMenu(MenuType.MapEditor) } }); }; var loadMapButton = widget.Get <ButtonWidget>("LOAD_MAP_BUTTON"); loadMapButton.OnClick = () => { SwitchMenu(MenuType.None); Game.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { { "initialMap", null }, { "initialTab", MapClassification.User }, { "onExit", () => SwitchMenu(MenuType.MapEditor) }, { "onSelect", onSelect }, { "filter", MapVisibility.Lobby | MapVisibility.Shellmap | MapVisibility.MissionSelector }, }); }; mapEditorMenu.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Extras); var newsBG = widget.GetOrNull("NEWS_BG"); if (newsBG != null) { newsBG.IsVisible = () => Game.Settings.Game.FetchNews && menuType != MenuType.None && menuType != MenuType.SystemInfoPrompt; newsPanel = Ui.LoadWidget <ScrollPanelWidget>("NEWS_PANEL", null, new WidgetArgs()); newsTemplate = newsPanel.Get("NEWS_ITEM_TEMPLATE"); newsPanel.RemoveChild(newsTemplate); newsStatus = newsPanel.Get <LabelWidget>("NEWS_STATUS"); SetNewsStatus("Loading news"); } Game.OnRemoteDirectConnect += OnRemoteDirectConnect; var newsURL = modData.Manifest.Get <WebServices>().GameNews; // System information opt-out prompt var sysInfoPrompt = widget.Get("SYSTEM_INFO_PROMPT"); sysInfoPrompt.IsVisible = () => menuType == MenuType.SystemInfoPrompt; if (Game.Settings.Debug.SystemInformationVersionPrompt < SystemInformationVersion) { menuType = MenuType.SystemInfoPrompt; var sysInfoCheckbox = sysInfoPrompt.Get <CheckboxWidget>("SYSINFO_CHECKBOX"); sysInfoCheckbox.IsChecked = () => Game.Settings.Debug.SendSystemInformation; sysInfoCheckbox.OnClick = () => Game.Settings.Debug.SendSystemInformation ^= true; var sysInfoData = sysInfoPrompt.Get <ScrollPanelWidget>("SYSINFO_DATA"); var template = sysInfoData.Get <LabelWidget>("DATA_TEMPLATE"); sysInfoData.RemoveChildren(); foreach (var info in GetSystemInformation().Values) { var label = template.Clone() as LabelWidget; var text = info.First + ": " + info.Second; label.GetText = () => text; sysInfoData.AddChild(label); } sysInfoPrompt.Get <ButtonWidget>("BACK_BUTTON").OnClick = () => { Game.Settings.Debug.SystemInformationVersionPrompt = SystemInformationVersion; Game.Settings.Save(); SwitchMenu(MenuType.Main); LoadAndDisplayNews(newsURL, newsBG); }; } else { LoadAndDisplayNews(newsURL, newsBG); } } void LoadAndDisplayNews(string newsURL, Widget newsBG) { if (newsBG != null) { var cacheFile = Platform.ResolvePath("^", "news.yaml"); var currentNews = ParseNews(cacheFile); if (currentNews != null) { DisplayNews(currentNews); } var newsButton = newsBG.GetOrNull <DropDownButtonWidget>("NEWS_BUTTON"); if (newsButton != null) { if (!fetchedNews) { // Send the mod and engine version to support version-filtered news (update prompts) newsURL += "?version={0}&mod={1}&modversion={2}".F( Uri.EscapeUriString(Game.Mods["modcontent"].Metadata.Version), Uri.EscapeUriString(Game.ModData.Manifest.Id), Uri.EscapeUriString(Game.ModData.Manifest.Metadata.Version)); // Append system profile data if the player has opted in if (Game.Settings.Debug.SendSystemInformation) { newsURL += "&sysinfoversion={0}&".F(SystemInformationVersion) + GetSystemInformation() .Select(kv => kv.Key + "=" + Uri.EscapeUriString(kv.Value.Second)) .JoinWith("&"); } new Download(newsURL, cacheFile, e => { }, e => NewsDownloadComplete(e, cacheFile, currentNews, () => newsButton.AttachPanel(newsPanel))); } newsButton.OnClick = () => newsButton.AttachPanel(newsPanel); } } } void OnRemoteDirectConnect(string host, int port) { SwitchMenu(MenuType.None); Ui.OpenWindow("MULTIPLAYER_PANEL", new WidgetArgs { { "onStart", RemoveShellmapUI }, { "onExit", () => SwitchMenu(MenuType.Main) }, { "directConnectHost", host }, { "directConnectPort", port }, }); } void LoadMapIntoEditor(string uid) { ConnectionLogic.Connect(IPAddress.Loopback.ToString(), Game.CreateLocalServer(uid), "", () => { Game.LoadEditor(uid); }, () => { Game.CloseServer(); SwitchMenu(MenuType.MapEditor); }); } void SetNewsStatus(string message) { message = WidgetUtils.WrapText(message, newsStatus.Bounds.Width, Game.Renderer.Fonts[newsStatus.Font]); newsStatus.GetText = () => message; }
public static void InitializeMod(string mod, Arguments args) { // Clear static state if we have switched mods LobbyInfoChanged = () => { }; ConnectionStateChanged = om => { }; BeforeGameStart = () => { }; OnRemoteDirectConnect = (a, b) => { }; delayedActions = new ActionQueue(); Ui.ResetAll(); if (worldRenderer != null) { worldRenderer.Dispose(); } worldRenderer = null; if (server != null) { server.Shutdown(); } if (OrderManager != null) { OrderManager.Dispose(); } if (ModData != null) { ModData.Dispose(); } ModData = null; // Fall back to default if the mod doesn't exist if (!ModMetadata.AllMods.ContainsKey(mod)) { mod = new GameSettings().Mod; } Console.WriteLine("Loading mod: {0}", mod); Settings.Game.Mod = mod; Sound.StopMusic(); Sound.StopVideo(); Sound.Initialize(); ModData = new ModData(mod, !Settings.Server.Dedicated); ModData.InitializeLoaders(); if (!Settings.Server.Dedicated) { Renderer.InitializeFonts(ModData.Manifest); } using (new PerfTimer("LoadMaps")) ModData.MapCache.LoadMaps(); if (Settings.Graphics.HardwareCursors) { try { Cursor = new HardwareCursor(ModData.CursorProvider); } catch (Exception e) { Log.Write("debug", "Failed to initialize hardware cursors. Falling back to software cursors."); Log.Write("debug", "Error was: " + e.Message); Console.WriteLine("Failed to initialize hardware cursors. Falling back to software cursors."); Console.WriteLine("Error was: " + e.Message); Cursor = new SoftwareCursor(ModData.CursorProvider); Settings.Graphics.HardwareCursors = false; } } else { Cursor = new SoftwareCursor(ModData.CursorProvider); } PerfHistory.Items["render"].HasNormalTick = false; PerfHistory.Items["batches"].HasNormalTick = false; PerfHistory.Items["render_widgets"].HasNormalTick = false; PerfHistory.Items["render_flip"].HasNormalTick = false; JoinLocal(); if (Settings.Server.Dedicated) { while (true) { Settings.Server.Map = WidgetUtils.ChooseInitialMap(Settings.Server.Map); Settings.Save(); CreateServer(new ServerSettings(Settings.Server)); while (true) { Thread.Sleep(100); if (server.State == Server.ServerState.GameStarted && server.Conns.Count < 1) { Console.WriteLine("No one is playing, shutting down..."); server.Shutdown(); break; } } if (Settings.Server.DedicatedLoop) { Console.WriteLine("Starting a new server instance..."); ModData.MapCache.LoadMaps(); continue; } break; } Environment.Exit(0); } else { ModData.LoadScreen.StartGame(args); } }
public ReplayBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart) { map = MapCache.UnknownMap; panel = widget; services = modData.Manifest.Get <WebServices>(); this.modData = modData; this.onStart = onStart; Game.BeforeGameStart += OnGameStart; playerList = panel.Get <ScrollPanelWidget>("PLAYER_LIST"); playerHeader = playerList.Get <ScrollItemWidget>("HEADER"); playerTemplate = playerList.Get <ScrollItemWidget>("TEMPLATE"); playerList.RemoveChildren(); panel.Get <ButtonWidget>("CANCEL_BUTTON").OnClick = () => { cancelLoadingReplays = true; Ui.CloseWindow(); onExit(); }; replayList = panel.Get <ScrollPanelWidget>("REPLAY_LIST"); var template = panel.Get <ScrollItemWidget>("REPLAY_TEMPLATE"); var mod = modData.Manifest; var dir = Platform.ResolvePath(Platform.SupportDirPrefix, "Replays", mod.Id, mod.Metadata.Version); if (Directory.Exists(dir)) { ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template)); } var watch = panel.Get <ButtonWidget>("WATCH_BUTTON"); watch.IsDisabled = () => selectedReplay == null || map.Status != MapStatus.Available; watch.OnClick = () => { WatchReplay(); }; var mapPreviewRoot = panel.Get("MAP_PREVIEW_ROOT"); mapPreviewRoot.IsVisible = () => selectedReplay != null; panel.Get("REPLAY_INFO").IsVisible = () => selectedReplay != null; Ui.LoadWidget("MAP_PREVIEW", mapPreviewRoot, new WidgetArgs { { "orderManager", null }, { "getMap", (Func <MapPreview>)(() => map) }, { "onMouseDown", (Action <MapPreviewWidget, MapPreview, MouseInput>)((preview, mapPreview, mi) => { }) }, { "getSpawnOccupants", (Func <MapPreview, Dictionary <CPos, SpawnOccupant> >)(mapPreview => LobbyUtils.GetSpawnOccupants(selectedReplay.GameInfo.Players, mapPreview)) }, { "showUnoccupiedSpawnpoints", false }, }); var replayDuration = new CachedTransform <ReplayMetadata, string>(r => "Duration: {0}".F(WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds))); panel.Get <LabelWidget>("DURATION").GetText = () => replayDuration.Update(selectedReplay); SetupFilters(); SetupManagement(); }
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 SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Func <SupportPowersWidget.SupportPowerIcon> getTooltipIcon, World world) { widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Power.Info != null; var nameLabel = widget.Get <LabelWidget>("NAME"); var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY"); var timeLabel = widget.Get <LabelWidget>("TIME"); var descLabel = widget.Get <LabelWidget>("DESC"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var hotkeyFont = Game.Renderer.Fonts[hotkeyLabel.Font]; var timeFont = Game.Renderer.Fonts[timeLabel.Font]; var descFont = Game.Renderer.Fonts[descLabel.Font]; var baseHeight = widget.Bounds.Height; var timeOffset = timeLabel.Bounds.X; SupportPowerInstance lastPower = null; Hotkey lastHotkey = Hotkey.Invalid; var lastRemainingSeconds = 0; tooltipContainer.BeforeRender = () => { var icon = getTooltipIcon(); if (icon == null || icon.Power == null || icon.Power.Instances.Count == 0) { return; } var sp = icon.Power; // HACK: This abuses knowledge of the internals of WidgetUtils.FormatTime // to efficiently work when the label is going to change, requiring a panel relayout var remainingSeconds = (int)Math.Ceiling(sp.RemainingTicks * world.Timestep / 1000f); var hotkey = icon.Hotkey?.GetValue() ?? Hotkey.Invalid; if (sp == lastPower && hotkey == lastHotkey && lastRemainingSeconds == remainingSeconds) { return; } nameLabel.Text = sp.Info.Description; var nameSize = nameFont.Measure(nameLabel.Text); descLabel.Text = sp.Info.LongDesc.Replace("\\n", "\n"); var descSize = descFont.Measure(descLabel.Text); var customLabel = sp.TooltipTimeTextOverride(); if (customLabel == null) { var remaining = WidgetUtils.FormatTime(sp.RemainingTicks, world.Timestep); var total = WidgetUtils.FormatTime(sp.Info.ChargeInterval, world.Timestep); timeLabel.Text = $"{remaining} / {total}"; } else { timeLabel.Text = customLabel; } var timeSize = timeFont.Measure(timeLabel.Text); var hotkeyWidth = 0; hotkeyLabel.Visible = hotkey.IsValid(); if (hotkeyLabel.Visible) { var hotkeyText = $"({hotkey.DisplayString()})"; hotkeyWidth = hotkeyFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; hotkeyLabel.Text = hotkeyText; hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X; } var timeWidth = timeSize.X; var topWidth = nameSize.X + hotkeyWidth + timeWidth + timeOffset; widget.Bounds.Width = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X); widget.Bounds.Height = baseHeight + descSize.Y; timeLabel.Bounds.X = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth; lastPower = sp; lastHotkey = hotkey; lastRemainingSeconds = remainingSeconds; }; timeLabel.GetColor = () => getTooltipIcon() != null && !getTooltipIcon().Power.Active ? Color.Red : Color.White; }
void SelectReplay(ReplayMetadata replay) { selectedReplay = replay; map = selectedReplay != null ? selectedReplay.GameInfo.MapPreview : MapCache.UnknownMap; if (replay == null) { return; } try { if (map.Status != MapStatus.Available) { if (map.Status == MapStatus.DownloadAvailable) { LoadMapPreviewRules(map); } else if (Game.Settings.Game.AllowDownloading) { modData.MapCache.QueryRemoteMapDetails(services.MapRepository, new[] { map.Uid }, LoadMapPreviewRules); } } var players = replay.GameInfo.Players .GroupBy(p => p.Team) .OrderBy(g => g.Key); var teams = new Dictionary <string, IEnumerable <GameInformation.Player> >(); var noTeams = players.Count() == 1; foreach (var p in players) { var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : "Team {0}".F(p.Key); teams.Add(label, p); } playerList.RemoveChildren(); foreach (var kv in teams) { var group = kv.Key; if (group.Length > 0) { var header = ScrollItemWidget.Setup(playerHeader, () => true, () => { }); header.Get <LabelWidget>("LABEL").GetText = () => group; playerList.AddChild(header); } foreach (var option in kv.Value) { var o = option; var color = o.Color; var item = ScrollItemWidget.Setup(playerTemplate, () => false, () => { }); var label = item.Get <LabelWidget>("LABEL"); var font = Game.Renderer.Fonts[label.Font]; var name = WidgetUtils.TruncateText(o.Name, label.Bounds.Width, font); label.GetText = () => name; label.GetColor = () => color; var flag = item.Get <ImageWidget>("FLAG"); flag.GetImageCollection = () => "flags"; var factionInfo = modData.DefaultRules.Actors["world"].TraitInfos <FactionInfo>(); flag.GetImageName = () => (factionInfo != null && factionInfo.Any(f => f.InternalName == o.FactionId)) ? o.FactionId : "Random"; playerList.AddChild(item); } } } catch (Exception e) { Log.Write("debug", "Exception while parsing replay: {0}", e); SelectReplay(null); } }