diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index a536661221..e96b7ed0f2 100755 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -344,9 +344,10 @@ namespace OpenRA { if (orderManager.world != null) orderManager.world.traitDict.PrintReport(); + + orderManager.Dispose(); CloseServer(); JoinLocal(); - orderManager.Dispose(); } public static void CloseServer() diff --git a/OpenRA.Game/Network/Connection.cs b/OpenRA.Game/Network/Connection.cs index 19718c9e3c..79037791e6 100755 --- a/OpenRA.Game/Network/Connection.cs +++ b/OpenRA.Game/Network/Connection.cs @@ -202,7 +202,10 @@ namespace OpenRA.Network if (socket != null) socket.Client.Close(); using( new PerfSample( "Thread.Join" )) - t.Join(); + { + if (!t.Join(1000)) + return; + } } ~NetworkConnection() { Dispose(); } diff --git a/OpenRA.Game/Network/ReplayConnection.cs b/OpenRA.Game/Network/ReplayConnection.cs index efae2bf61b..0942165219 100755 --- a/OpenRA.Game/Network/ReplayConnection.cs +++ b/OpenRA.Game/Network/ReplayConnection.cs @@ -109,6 +109,7 @@ namespace OpenRA.Network return; writer.Close(); + inner.Dispose(); disposed = true; } diff --git a/OpenRA.Game/Widgets/ScrollItemWidget.cs b/OpenRA.Game/Widgets/ScrollItemWidget.cs index 6860bc770e..51a4d3dacf 100644 --- a/OpenRA.Game/Widgets/ScrollItemWidget.cs +++ b/OpenRA.Game/Widgets/ScrollItemWidget.cs @@ -9,8 +9,6 @@ #endregion using System; -using System.Drawing; -using OpenRA.Graphics; namespace OpenRA.Widgets { diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index 2bdb93e10a..4425d1d80e 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -1,4 +1,4 @@ - + Debug @@ -75,20 +75,14 @@ - - - - - - @@ -103,7 +97,6 @@ - diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncCheatsLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncCheatsLogic.cs index 456acc4f7a..1ace3f9c35 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncCheatsLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncCheatsLogic.cs @@ -1,20 +1,10 @@ #region Copyright & License Information /* - * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. - * This file is part of OpenRA. - * - * OpenRA is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * OpenRA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with OpenRA. If not, see . + * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. */ #endregion diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncDirectConnectLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncDirectConnectLogic.cs deleted file mode 100644 index 99f6e09099..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncDirectConnectLogic.cs +++ /dev/null @@ -1,43 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets.Logic -{ - public class CncDirectConnectLogic - { - [ObjectCreator.UseCtor] - public CncDirectConnectLogic(Widget widget, Action onExit, Action openLobby) - { - var panel = widget.GetWidget("DIRECTCONNECT_PANEL"); - var ipField = panel.GetWidget("IP"); - var portField = panel.GetWidget("PORT"); - - var last = Game.Settings.Player.LastServer.Split(':'); - ipField.Text = last.Length > 1 ? last[0] : "localhost"; - portField.Text = last.Length > 2 ? last[1] : "1234"; - - panel.GetWidget("JOIN_BUTTON").OnClick = () => - { - var port = Exts.WithDefault(1234, () => int.Parse(portField.Text)); - - Game.Settings.Player.LastServer = "{0}:{1}".F(ipField.Text, port); - Game.Settings.Save(); - - Widget.CloseWindow(); - CncConnectionLogic.Connect(ipField.Text, port, openLobby, onExit); - }; - - panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; - } - } -} diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs index ca65ee42d2..dfe8533ac9 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncInstallFromCDLogic.cs @@ -102,7 +102,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic retryButton.IsDisabled = () => false; })); - var t = new Thread( _ => + new Thread( _ => { try { @@ -122,8 +122,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic { onError("Installation failed"); } - }) { IsBackground = true }; - t.Start(); + }) { IsBackground = true }.Start(); } } } diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs deleted file mode 100644 index 3928706cf5..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncLobbyLogic.cs +++ /dev/null @@ -1,446 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using OpenRA.Mods.RA; -using OpenRA.Mods.RA.Widgets.Logic; -using OpenRA.Network; -using OpenRA.Traits; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets.Logic -{ - public class CncLobbyLogic - { - Widget EditablePlayerTemplate, NonEditablePlayerTemplate, EmptySlotTemplate, - EditableSpectatorTemplate, NonEditableSpectatorTemplate, NewSpectatorTemplate; - ScrollPanelWidget chatPanel; - Widget chatTemplate; - - ScrollPanelWidget Players; - Dictionary CountryNames; - string MapUid; - Map Map; - - ColorPickerPaletteModifier PlayerPalettePreview; - - readonly Action OnGameStart; - readonly Action onExit; - readonly OrderManager orderManager; - - // Listen for connection failures - void ConnectionStateChanged(OrderManager om) - { - if (om.Connection.ConnectionState == ConnectionState.NotConnected) - { - // Show connection failed dialog - CloseWindow(); - - Action onConnect = () => - { - Game.OpenWindow("SERVER_LOBBY", new WidgetArgs() - { - { "onExit", onExit }, - { "onStart", OnGameStart }, - { "addBots", false } - }); - }; - - Action onRetry = () => - { - CloseWindow(); - CncConnectionLogic.Connect(om.Host, om.Port, onConnect, onExit); - }; - - Widget.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() - { - { "onAbort", onExit }, - { "onRetry", onRetry }, - { "host", om.Host }, - { "port", om.Port } - }); - } - } - - void CloseWindow() - { - Game.LobbyInfoChanged -= UpdateCurrentMap; - Game.LobbyInfoChanged -= UpdatePlayerList; - Game.BeforeGameStart -= OnGameStart; - Game.AddChatLine -= AddChatLine; - Game.ConnectionStateChanged -= ConnectionStateChanged; - - Widget.CloseWindow(); - } - - [ObjectCreator.UseCtor] - internal CncLobbyLogic(Widget widget, World world, OrderManager orderManager, - Action onExit, Action onStart, bool addBots) - { - var lobby = widget; - this.orderManager = orderManager; - this.OnGameStart = () => { CloseWindow(); onStart(); }; - this.onExit = onExit; - - Game.LobbyInfoChanged += UpdateCurrentMap; - Game.LobbyInfoChanged += UpdatePlayerList; - Game.BeforeGameStart += OnGameStart; - Game.AddChatLine += AddChatLine; - Game.ConnectionStateChanged += ConnectionStateChanged; - - UpdateCurrentMap(); - PlayerPalettePreview = world.WorldActor.Trait(); - PlayerPalettePreview.Ramp = Game.Settings.Player.ColorRamp; - Players = lobby.GetWidget("PLAYERS"); - EditablePlayerTemplate = Players.GetWidget("TEMPLATE_EDITABLE_PLAYER"); - NonEditablePlayerTemplate = Players.GetWidget("TEMPLATE_NONEDITABLE_PLAYER"); - EmptySlotTemplate = Players.GetWidget("TEMPLATE_EMPTY"); - EditableSpectatorTemplate = Players.GetWidget("TEMPLATE_EDITABLE_SPECTATOR"); - NonEditableSpectatorTemplate = Players.GetWidget("TEMPLATE_NONEDITABLE_SPECTATOR"); - NewSpectatorTemplate = Players.GetWidget("TEMPLATE_NEW_SPECTATOR"); - - var mapPreview = lobby.GetWidget("MAP_PREVIEW"); - mapPreview.IsVisible = () => Map != null; - mapPreview.Map = () => Map; - mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint( orderManager, mapPreview, Map, mi ); - - var mapTitle = lobby.GetWidget("MAP_TITLE"); - mapTitle.IsVisible = () => Map != null; - mapTitle.GetText = () => Map.Title; - - mapPreview.SpawnColors = () => LobbyUtils.GetSpawnColors( orderManager, Map ); - - CountryNames = Rules.Info["world"].Traits.WithInterface() - .Where(c => c.Selectable) - .ToDictionary(a => a.Race, a => a.Name); - CountryNames.Add("random", "Any"); - - var mapButton = lobby.GetWidget("CHANGEMAP_BUTTON"); - mapButton.OnClick = () => - { - var onSelect = new Action(m => - { - orderManager.IssueOrder(Order.Command("map " + m.Uid)); - Game.Settings.Server.Map = m.Uid; - Game.Settings.Save(); - }); - - Widget.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() - { - { "initialMap", Map.Uid }, - { "onExit", () => {} }, - { "onSelect", onSelect } - }); - }; - mapButton.IsVisible = () => mapButton.Visible && Game.IsHost; - - var disconnectButton = lobby.GetWidget("DISCONNECT_BUTTON"); - disconnectButton.OnClick = () => { CloseWindow(); onExit(); }; - - var gameStarting = false; - - var allowCheats = lobby.GetWidget("ALLOWCHEATS_CHECKBOX"); - allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats; - allowCheats.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null - || orderManager.LocalClient.IsReady; - allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command( - "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats))); - - var startGameButton = lobby.GetWidget("START_GAME_BUTTON"); - startGameButton.IsVisible = () => Game.IsHost; - startGameButton.IsDisabled = () => gameStarting; - startGameButton.OnClick = () => - { - gameStarting = true; - orderManager.IssueOrder(Order.Command("startgame")); - }; - - bool teamChat = false; - var chatLabel = lobby.GetWidget("LABEL_CHATTYPE"); - var chatTextField = lobby.GetWidget("CHAT_TEXTFIELD"); - - chatTextField.OnEnterKey = () => - { - if (chatTextField.Text.Length == 0) - return true; - - orderManager.IssueOrder(Order.Chat(teamChat, chatTextField.Text)); - chatTextField.Text = ""; - return true; - }; - - chatTextField.OnTabKey = () => - { - teamChat ^= true; - chatLabel.Text = (teamChat) ? "Team:" : "Chat:"; - return true; - }; - - chatPanel = lobby.GetWidget("CHAT_DISPLAY"); - chatTemplate = chatPanel.GetWidget("CHAT_TEMPLATE"); - chatPanel.RemoveChildren(); - - var musicButton = lobby.GetWidget("MUSIC_BUTTON"); - if (musicButton != null) - musicButton.OnClick = () => Widget.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().Select(t => t.Name).FirstOrDefault(); - if (slot != null && bot != null) - orderManager.IssueOrder(Order.Command("slot_bot {0} {1}".F(slot, bot))); - }); - } - - void AddChatLine(Color c, string from, string text) - { - var template = chatTemplate.Clone(); - var nameLabel = template.GetWidget("NAME"); - var timeLabel = template.GetWidget("TIME"); - var textLabel = template.GetWidget("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.Play("scold1.aud"); - } - - void UpdateCurrentMap() - { - if (MapUid == orderManager.LobbyInfo.GlobalSettings.Map) return; - MapUid = orderManager.LobbyInfo.GlobalSettings.Map; - Map = new Map(Game.modData.AvailableMaps[MapUid].Path); - - var title = Widget.RootWidget.GetWidget("TITLE"); - title.Text = orderManager.LobbyInfo.GlobalSettings.ServerName; - } - - void UpdatePlayerList() - { - // This causes problems for people who are in the process of editing their names (the widgets vanish from beneath them) - // Todo: handle this nicer - Players.RemoveChildren(); - - foreach (var kv in orderManager.LobbyInfo.Slots) - { - var key = kv.Key; - var slot = kv.Value; - var client = orderManager.LobbyInfo.ClientInSlot(key); - Widget template; - - // Empty slot - if (client == null) - { - template = EmptySlotTemplate.Clone(); - Func getText = () => slot.Closed ? "Closed" : "Open"; - var ready = orderManager.LocalClient.IsReady; - - if (Game.IsHost) - { - var name = template.GetWidget("NAME_HOST"); - name.IsVisible = () => true; - name.IsDisabled = () => ready; - name.GetText = getText; - name.OnMouseDown = _ => LobbyUtils.ShowSlotDropDown(name, slot, client, orderManager); - } - else - { - var name = template.GetWidget("NAME"); - name.IsVisible = () => true; - name.GetText = getText; - } - - var join = template.GetWidget("JOIN"); - join.IsVisible = () => !slot.Closed; - join.IsDisabled = () => ready; - join.OnClick = () => orderManager.IssueOrder(Order.Command("slot " + key)); - } - // Editable player in slot - else if ((client.Index == orderManager.LocalClient.Index) || - (client.Bot != null && Game.IsHost)) - { - template = EditablePlayerTemplate.Clone(); - var botReady = client.Bot != null && Game.IsHost && orderManager.LocalClient.IsReady; - var ready = botReady || client.IsReady; - - if (client.Bot != null) - { - var name = template.GetWidget("BOT_DROPDOWN"); - name.IsVisible = () => true; - name.IsDisabled = () => ready; - name.GetText = () => client.Name; - name.OnMouseDown = _ => LobbyUtils.ShowSlotDropDown(name, slot, client, orderManager); - } - else - { - var name = template.GetWidget("NAME"); - name.IsVisible = () => true; - name.IsDisabled = () => ready; - LobbyUtils.SetupNameWidget(orderManager, client, name); - } - - var color = template.GetWidget("COLOR"); - color.IsDisabled = () => slot.LockColor || ready; - color.OnMouseDown = _ => LobbyUtils.ShowColorDropDown(color, client, orderManager, PlayerPalettePreview); - - var colorBlock = color.GetWidget("COLORBLOCK"); - colorBlock.GetColor = () => client.ColorRamp.GetColor(0); - - var faction = template.GetWidget("FACTION"); - faction.IsDisabled = () => slot.LockRace || ready; - faction.OnMouseDown = _ => LobbyUtils.ShowRaceDropDown(faction, client, orderManager, CountryNames); - - var factionname = faction.GetWidget("FACTIONNAME"); - factionname.GetText = () => CountryNames[client.Country]; - var factionflag = faction.GetWidget("FACTIONFLAG"); - factionflag.GetImageName = () => client.Country; - factionflag.GetImageCollection = () => "flags"; - - var team = template.GetWidget("TEAM"); - team.IsDisabled = () => slot.LockTeam || ready; - team.OnMouseDown = _ => LobbyUtils.ShowTeamDropDown(team, client, orderManager, Map); - team.GetText = () => (client.Team == 0) ? "-" : client.Team.ToString(); - - if (client.Bot == null) - { - // local player - var status = template.GetWidget("STATUS_CHECKBOX"); - status.IsChecked = () => ready; - status.IsVisible = () => true; - status.OnClick += CycleReady; - } - else // Bot - template.GetWidget("STATUS_IMAGE").IsVisible = () => true; - } - else - { // Non-editable player in slot - template = NonEditablePlayerTemplate.Clone(); - template.GetWidget("NAME").GetText = () => client.Name; - var color = template.GetWidget("COLOR"); - color.GetColor = () => client.ColorRamp.GetColor(0); - - var faction = template.GetWidget("FACTION"); - var factionname = faction.GetWidget("FACTIONNAME"); - factionname.GetText = () => CountryNames[client.Country]; - var factionflag = faction.GetWidget("FACTIONFLAG"); - factionflag.GetImageName = () => client.Country; - factionflag.GetImageCollection = () => "flags"; - - var team = template.GetWidget("TEAM"); - team.GetText = () => (client.Team == 0) ? "-" : client.Team.ToString(); - - template.GetWidget("STATUS_IMAGE").IsVisible = () => - client.Bot != null || client.IsReady; - - var kickButton = template.GetWidget("KICK"); - kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index; - kickButton.IsDisabled = () => orderManager.LocalClient.IsReady; - kickButton.OnClick = () => orderManager.IssueOrder(Order.Command("kick " + client.Index)); - } - - template.IsVisible = () => true; - Players.AddChild(template); - } - - // Add spectators - foreach (var client in orderManager.LobbyInfo.Clients.Where(client => client.Slot == null)) - { - Widget template; - var c = client; - var ready = c.IsReady; - - // Editable spectator - if (c.Index == orderManager.LocalClient.Index) - { - template = EditableSpectatorTemplate.Clone(); - var name = template.GetWidget("NAME"); - name.IsDisabled = () => ready; - LobbyUtils.SetupNameWidget(orderManager, c, name); - - var color = template.GetWidget("COLOR"); - color.IsDisabled = () => ready; - color.OnMouseDown = _ => LobbyUtils.ShowColorDropDown(color, c, orderManager, PlayerPalettePreview); - - var colorBlock = color.GetWidget("COLORBLOCK"); - colorBlock.GetColor = () => c.ColorRamp.GetColor(0); - - var status = template.GetWidget("STATUS_CHECKBOX"); - status.IsChecked = () => ready; - status.OnClick += CycleReady; - } - // Non-editable spectator - else - { - template = NonEditableSpectatorTemplate.Clone(); - template.GetWidget("NAME").GetText = () => c.Name; - var color = template.GetWidget("COLOR"); - color.GetColor = () => c.ColorRamp.GetColor(0); - - template.GetWidget("STATUS_IMAGE").IsVisible = () => c.Bot != null || c.IsReady; - - var kickButton = template.GetWidget("KICK"); - kickButton.IsVisible = () => Game.IsHost && c.Index != orderManager.LocalClient.Index; - kickButton.IsDisabled = () => orderManager.LocalClient.IsReady; - kickButton.OnClick = () => orderManager.IssueOrder(Order.Command("kick " + c.Index)); - } - - template.IsVisible = () => true; - Players.AddChild(template); - } - - // Spectate button - if (orderManager.LocalClient.Slot != null) - { - var spec = NewSpectatorTemplate.Clone(); - var btn = spec.GetWidget("SPECTATE"); - btn.OnClick = () => orderManager.IssueOrder(Order.Command("spectate")); - btn.IsDisabled = () => orderManager.LocalClient.IsReady; - spec.IsVisible = () => true; - Players.AddChild(spec); - } - } - - bool SpawnPointAvailable(int index) { return (index == 0) || orderManager.LobbyInfo.Clients.All(c => c.SpawnPoint != index); } - - void CycleReady() - { - orderManager.IssueOrder(Order.Command("ready")); - } - } -} diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncMenuLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncMenuLogic.cs index 09af6597ca..52ee13bf32 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncMenuLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncMenuLogic.cs @@ -9,6 +9,7 @@ #endregion using System.Net; +using OpenRA.Mods.RA.Widgets.Logic; using OpenRA.Widgets; namespace OpenRA.Mods.Cnc.Widgets.Logic @@ -54,35 +55,9 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic multiplayerMenu.IsVisible = () => Menu == MenuType.Multiplayer; multiplayerMenu.GetWidget("BACK_BUTTON").OnClick = () => Menu = MenuType.Main; - multiplayerMenu.GetWidget("JOIN_BUTTON").OnClick = () => - { - Menu = MenuType.None; - Widget.OpenWindow("SERVERBROWSER_PANEL", new WidgetArgs() - { - { "onExit", () => Menu = MenuType.Multiplayer }, - { "openLobby", () => OpenLobbyPanel(MenuType.Multiplayer, false) } - }); - }; - - multiplayerMenu.GetWidget("CREATE_BUTTON").OnClick = () => - { - Menu = MenuType.None; - Widget.OpenWindow("CREATESERVER_PANEL", new WidgetArgs() - { - { "onExit", () => Menu = MenuType.Multiplayer }, - { "openLobby", () => OpenLobbyPanel(MenuType.Multiplayer, false) } - }); - }; - - multiplayerMenu.GetWidget("DIRECTCONNECT_BUTTON").OnClick = () => - { - Menu = MenuType.None; - Widget.OpenWindow("DIRECTCONNECT_PANEL", new WidgetArgs() - { - { "onExit", () => Menu = MenuType.Multiplayer }, - { "openLobby", () => OpenLobbyPanel(MenuType.Multiplayer, false) } - }); - }; + multiplayerMenu.GetWidget("JOIN_BUTTON").OnClick = () => OpenGamePanel("SERVERBROWSER_PANEL"); + multiplayerMenu.GetWidget("CREATE_BUTTON").OnClick = () => OpenGamePanel("CREATESERVER_PANEL"); + multiplayerMenu.GetWidget("DIRECTCONNECT_BUTTON").OnClick = () => OpenGamePanel("DIRECTCONNECT_PANEL"); // Settings menu var settingsMenu = widget.GetWidget("SETTINGS_MENU"); @@ -121,6 +96,16 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic rootMenu.GetWidget("RECBLOCK").IsVisible = () => world.FrameNumber / 25 % 2 == 0; } + + void OpenGamePanel(string id) + { + Menu = MenuType.None; + Widget.OpenWindow(id, new WidgetArgs() + { + { "onExit", () => Menu = MenuType.Multiplayer }, + { "openLobby", () => OpenLobbyPanel(MenuType.Multiplayer, false) } + }); + } void RemoveShellmapUI() { @@ -142,10 +127,10 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic { var map = WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map); - CncConnectionLogic.Connect(IPAddress.Loopback.ToString(), - Game.CreateLocalServer(map), - () => OpenLobbyPanel(MenuType.Main, true), - () => { Game.CloseServer(); Menu = MenuType.Main; }); + ConnectionLogic.Connect(IPAddress.Loopback.ToString(), + Game.CreateLocalServer(map), + () => OpenLobbyPanel(MenuType.Main, true), + () => { Game.CloseServer(); Menu = MenuType.Main; }); } } } diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs index 0c8f555355..5c2ded3398 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncMusicPlayerLogic.cs @@ -11,7 +11,6 @@ using System; using System.IO; using System.Linq; -using System.Threading; using OpenRA.FileFormats; using OpenRA.GameRules; using OpenRA.Traits; @@ -129,7 +128,6 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic } } - void Play() { if (currentSong == null) diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncReplayBrowserLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncReplayBrowserLogic.cs deleted file mode 100644 index ef00f05bd0..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncReplayBrowserLogic.cs +++ /dev/null @@ -1,101 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.IO; -using System.Linq; -using OpenRA.Network; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets.Logic -{ - public class CncReplayBrowserLogic - { - Widget panel; - - [ObjectCreator.UseCtor] - public CncReplayBrowserLogic(Widget widget, Action onExit, Action onStart) - { - panel = widget.GetWidget("REPLAYBROWSER_PANEL"); - - panel.GetWidget("CANCEL_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; - - var rl = panel.GetWidget("REPLAY_LIST"); - var replayDir = Path.Combine(Platform.SupportDir, "Replays"); - - var template = panel.GetWidget("REPLAY_TEMPLATE"); - - rl.RemoveChildren(); - if (Directory.Exists(replayDir)) - { - var files = Directory.GetFiles(replayDir, "*.rep").Reverse(); - foreach (var replayFile in files) - AddReplay(rl, replayFile, template); - - SelectReplay(files.FirstOrDefault()); - } - - var watch = panel.GetWidget("WATCH_BUTTON"); - watch.IsDisabled = () => currentReplay == null || currentMap == null || currentReplay.Duration == 0; - watch.OnClick = () => - { - if (currentReplay != null) - { - Game.JoinReplay(currentReplay.Filename); - Widget.CloseWindow(); - onStart(); - } - }; - - panel.GetWidget("REPLAY_INFO").IsVisible = () => currentReplay != null; - } - - Replay currentReplay; - Map currentMap; - - void SelectReplay(string filename) - { - if (filename == null) - return; - - try - { - currentReplay = new Replay(filename); - currentMap = currentReplay.Map(); - - panel.GetWidget("DURATION").GetText = - () => WidgetUtils.FormatTime(currentReplay.Duration * 3 /* todo: 3:1 ratio isnt always true. */); - panel.GetWidget("MAP_PREVIEW").Map = () => currentMap; - panel.GetWidget("MAP_TITLE").GetText = - () => currentMap != null ? currentMap.Title : "(Unknown Map)"; - - var players = currentReplay.LobbyInfo.Slots - .Count(s => currentReplay.LobbyInfo.ClientInSlot(s.Key) != null); - panel.GetWidget("PLAYERS").GetText = () => players.ToString(); - } - catch (Exception e) - { - Log.Write("debug", "Exception while parsing replay: {0}", e); - currentReplay = null; - currentMap = null; - } - } - - void AddReplay(ScrollPanelWidget list, string filename, ScrollItemWidget template) - { - var item = ScrollItemWidget.Setup(template, - () => currentReplay != null && currentReplay.Filename == filename, - () => SelectReplay(filename)); - var f = Path.GetFileName(filename); - item.GetWidget("TITLE").GetText = () => f; - list.AddChild(item); - } - } -} diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncServerBrowserLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncServerBrowserLogic.cs deleted file mode 100644 index ddbaf23b71..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncServerBrowserLogic.cs +++ /dev/null @@ -1,158 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using OpenRA.Mods.RA.Widgets.Logic; -using OpenRA.Network; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets.Logic -{ - public class CncServerBrowserLogic - { - GameServer currentServer; - ScrollItemWidget serverTemplate; - - enum SearchStatus { Fetching, Failed, NoGames, Hidden } - SearchStatus searchStatus = SearchStatus.Fetching; - - public string ProgressLabelText() - { - switch (searchStatus) - { - case SearchStatus.Fetching: - return "Fetching game list..."; - case SearchStatus.Failed: - return "Failed to contact master server."; - case SearchStatus.NoGames: - return "No games found."; - default: - return ""; - } - } - - [ObjectCreator.UseCtor] - public CncServerBrowserLogic(Widget widget, Action openLobby, Action onExit) - { - var panel = widget.GetWidget("SERVERBROWSER_PANEL"); - var sl = panel.GetWidget("SERVER_LIST"); - - // Menu buttons - var refreshButton = panel.GetWidget("REFRESH_BUTTON"); - refreshButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; - refreshButton.OnClick = () => - { - searchStatus = SearchStatus.Fetching; - sl.RemoveChildren(); - currentServer = null; - ServerList.Query(games => RefreshServerList(panel, games)); - }; - - var join = panel.GetWidget("JOIN_BUTTON"); - join.IsDisabled = () => currentServer == null || !currentServer.CanJoin(); - join.OnClick = () => - { - if (currentServer == null) - return; - - var host = currentServer.Address.Split(':')[0]; - var port = int.Parse(currentServer.Address.Split(':')[1]); - - Widget.CloseWindow(); - CncConnectionLogic.Connect(host, port, openLobby, onExit); - }; - - panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; - - // Server list - serverTemplate = sl.GetWidget("SERVER_TEMPLATE"); - - // Display the progress label over the server list - // The text is only visible when the list is empty - var progressText = panel.GetWidget("PROGRESS_LABEL"); - progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; - progressText.GetText = ProgressLabelText; - - // Map preview - var preview = panel.GetWidget("MAP_PREVIEW"); - preview.Map = () => CurrentMap(); - preview.IsVisible = () => CurrentMap() != null; - - // Server info - var infoPanel = panel.GetWidget("SERVER_INFO"); - infoPanel.IsVisible = () => currentServer != null; - infoPanel.GetWidget("SERVER_IP").GetText = () => currentServer.Address; - infoPanel.GetWidget("SERVER_MODS").GetText = () => ServerBrowserLogic.GenerateModsLabel(currentServer); - infoPanel.GetWidget("MAP_TITLE").GetText = () => (CurrentMap() != null) ? CurrentMap().Title : "Unknown"; - infoPanel.GetWidget("MAP_PLAYERS").GetText = () => GetPlayersLabel(currentServer); - - ServerList.Query(games => RefreshServerList(panel, games)); - } - - string GetPlayersLabel(GameServer game) - { - if (game == null) - return ""; - - var map = Game.modData.FindMapByUid(game.Map); - return map == null ? "{0}".F(currentServer.Players) : "{0} / {1}".F(currentServer.Players, map.PlayerCount); - } - - Map CurrentMap() - { - return (currentServer == null) ? null : Game.modData.FindMapByUid(currentServer.Map); - } - - public void RefreshServerList(Widget panel, IEnumerable games) - { - var sl = panel.GetWidget("SERVER_LIST"); - - sl.RemoveChildren(); - currentServer = null; - - if (games == null) - { - searchStatus = SearchStatus.Failed; - return; - } - - var gamesWaiting = games.Where(g => g.CanJoin()); - - if (gamesWaiting.Count() == 0) - { - searchStatus = SearchStatus.NoGames; - return; - } - - searchStatus = SearchStatus.Hidden; - currentServer = gamesWaiting.FirstOrDefault(); - - foreach (var loop in gamesWaiting) - { - var game = loop; - - var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => currentServer = game); - item.GetWidget("TITLE").GetText = () => game.Name; - // TODO: Use game.MapTitle once the server supports it - item.GetWidget("MAP").GetText = () => - { - var map = Game.modData.FindMapByUid(game.Map); - return map == null ? "Unknown" : map.Title; - }; - // TODO: Use game.MaxPlayers once the server supports it - item.GetWidget("PLAYERS").GetText = () => GetPlayersLabel(game); - item.GetWidget("IP").GetText = () => game.Address; - sl.AddChild(item); - } - } - } -} diff --git a/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs b/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs index 0ea52edba7..e6391e9ae6 100755 --- a/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs +++ b/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.Cnc.Widgets { public List Tabs = new List(); public string Group; - public int CumulativeCount; + public int NextQueueName = 1; public bool Alert { get { return Tabs.Any(t => t.Queue.CurrentDone); } } public void Update(IEnumerable allQueues) @@ -51,7 +51,7 @@ namespace OpenRA.Mods.Cnc.Widgets foreach (var queue in queues) tabs.Add(new ProductionTab() { - Name = (++CumulativeCount).ToString(), + Name = (NextQueueName++).ToString(), Queue = queue }); Tabs = tabs; diff --git a/OpenRA.Mods.RA/AttackMove.cs b/OpenRA.Mods.RA/AttackMove.cs index 40ae1043c7..cd6cf7e754 100644 --- a/OpenRA.Mods.RA/AttackMove.cs +++ b/OpenRA.Mods.RA/AttackMove.cs @@ -9,7 +9,6 @@ #endregion using System.Drawing; -using OpenRA.Effects; using OpenRA.Mods.RA.Move; using OpenRA.Traits; diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index e673e94365..914ef046b6 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -1,4 +1,4 @@ - + Debug @@ -250,8 +250,8 @@ - + @@ -332,9 +332,9 @@ + - - + @@ -352,6 +352,7 @@ + @@ -391,4 +392,4 @@ copy "$(TargetPath)" "$(SolutionDir)mods/ra/" cd "$(SolutionDir)" - + \ No newline at end of file diff --git a/OpenRA.Mods.RA/RALoadScreen.cs b/OpenRA.Mods.RA/RALoadScreen.cs index 55dc98b3f1..ce47436c98 100644 --- a/OpenRA.Mods.RA/RALoadScreen.cs +++ b/OpenRA.Mods.RA/RALoadScreen.cs @@ -70,32 +70,6 @@ namespace OpenRA.Mods.RA public void StartGame() { - Game.ConnectionStateChanged += orderManager => - { - Widget.CloseWindow(); - switch (orderManager.Connection.ConnectionState) - { - case ConnectionState.PreConnecting: - Widget.LoadWidget("MAINMENU_BG", Widget.RootWidget, new WidgetArgs()); - break; - case ConnectionState.Connecting: - Widget.OpenWindow("CONNECTING_BG", - new WidgetArgs() { { "host", orderManager.Host }, { "port", orderManager.Port } }); - break; - case ConnectionState.NotConnected: - Widget.OpenWindow("CONNECTION_FAILED_BG", - new WidgetArgs() { { "orderManager", orderManager } }); - break; - case ConnectionState.Connected: - var lobby = Game.OpenWindow("SERVER_LOBBY", new WidgetArgs {}); - lobby.GetWidget("CHAT_DISPLAY").ClearChat(); - lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true; - lobby.GetWidget("ALLOWCHEATS_CHECKBOX").Visible = true; - lobby.GetWidget("DISCONNECT_BUTTON").Visible = true; - break; - } - }; - TestAndContinue(); Game.JoinExternalGame(); } diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs index 41db5c0e1e..9cff445cf8 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs @@ -10,9 +10,8 @@ using System.Collections.Generic; using System.Linq; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Traits; using OpenRA.Graphics; +using OpenRA.Traits; namespace OpenRA.Mods.RA { diff --git a/OpenRA.Mods.RA/Widgets/Logic/ConnectionDialogsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ConnectionDialogsLogic.cs deleted file mode 100644 index c27afca6c2..0000000000 --- a/OpenRA.Mods.RA/Widgets/Logic/ConnectionDialogsLogic.cs +++ /dev/null @@ -1,53 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using OpenRA.Network; -using OpenRA.Widgets; - -namespace OpenRA.Mods.RA.Widgets.Logic -{ - public class ConnectionDialogsLogic - { - [ObjectCreator.UseCtor] - public ConnectionDialogsLogic(Widget widget, string host, int port) - { - widget.GetWidget("CONNECTION_BUTTON_ABORT").OnClick = () => { - widget.GetWidget("CONNECTION_BUTTON_ABORT").Parent.Visible = false; - Game.Disconnect(); - Game.LoadShellMap(); - Widget.CloseWindow(); - Widget.OpenWindow("MAINMENU_BG"); - }; - - widget.GetWidget("CONNECTING_DESC").GetText = () => - "Connecting to {0}:{1}...".F(host, port); - } - } - - public class ConnectionFailedLogic - { - [ObjectCreator.UseCtor] - public ConnectionFailedLogic(Widget widget, OrderManager orderManager) - { - widget.GetWidget("CONNECTION_BUTTON_CANCEL").OnClick = () => { - widget.GetWidget("CONNECTION_BUTTON_CANCEL").Parent.Visible = false; - Game.Disconnect(); - Game.LoadShellMap(); - Widget.CloseWindow(); - Widget.OpenWindow("MAINMENU_BG"); - }; - widget.GetWidget("CONNECTION_BUTTON_RETRY").OnClick = () => - Game.JoinServer(orderManager.Host, orderManager.Port); - - widget.GetWidget("CONNECTION_FAILED_DESC").GetText = () => string.IsNullOrEmpty(orderManager.ServerError) ? - "Could not connect to {0}:{1}".F(orderManager.Host, orderManager.Port) : orderManager.ServerError; - } - } -} diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncConnectionLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ConnectionLogic.cs similarity index 83% rename from OpenRA.Mods.Cnc/Widgets/Logic/CncConnectionLogic.cs rename to OpenRA.Mods.RA/Widgets/Logic/ConnectionLogic.cs index b3d550c5d8..a8fd3c786f 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncConnectionLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ConnectionLogic.cs @@ -12,9 +12,9 @@ using System; using OpenRA.Network; using OpenRA.Widgets; -namespace OpenRA.Mods.Cnc.Widgets.Logic +namespace OpenRA.Mods.RA.Widgets.Logic { - public class CncConnectionLogic + public class ConnectionLogic { Action onConnect, onRetry, onAbort; string host; @@ -48,7 +48,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic } [ObjectCreator.UseCtor] - public CncConnectionLogic(Widget widget, string host, int port, Action onConnect, Action onRetry, Action onAbort) + public ConnectionLogic(Widget widget, string host, int port, Action onConnect, Action onRetry, Action onAbort) { this.host = host; this.port = port; @@ -58,7 +58,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic Game.ConnectionStateChanged += ConnectionStateChanged; - var panel = widget.GetWidget("CONNECTING_PANEL"); + var panel = widget; panel.GetWidget("ABORT_BUTTON").OnClick = () => { CloseWindow(); onAbort(); }; widget.GetWidget("CONNECTING_DESC").GetText = () => @@ -79,16 +79,17 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic } } - public class CncConnectionFailedLogic + public class ConnectionFailedLogic { [ObjectCreator.UseCtor] - public CncConnectionFailedLogic(Widget widget, string host, int port, Action onRetry, Action onAbort) + public ConnectionFailedLogic(Widget widget, string host, int port, Action onRetry, Action onAbort) { - var panel = widget.GetWidget("CONNECTIONFAILED_PANEL"); + var panel = widget; panel.GetWidget("ABORT_BUTTON").OnClick = () => { Widget.CloseWindow(); onAbort(); }; panel.GetWidget("RETRY_BUTTON").OnClick = () => { Widget.CloseWindow(); onRetry(); }; widget.GetWidget("CONNECTING_DESC").GetText = () => "Could not connect to {0}:{1}".F(host, port); } - }} + } +} \ No newline at end of file diff --git a/OpenRA.Mods.RA/Widgets/Logic/CreateServerMenuLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/CreateServerMenuLogic.cs deleted file mode 100644 index fb7c29a8b7..0000000000 --- a/OpenRA.Mods.RA/Widgets/Logic/CreateServerMenuLogic.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Net; -using OpenRA.GameRules; -using OpenRA.Widgets; - -namespace OpenRA.Mods.RA.Widgets.Logic -{ - public class CreateServerMenuLogic - { - [ObjectCreator.UseCtor] - public CreateServerMenuLogic(Widget widget) - { - var settings = Game.Settings; - var cs = widget; - - cs.GetWidget("BUTTON_CANCEL").OnClick = () => Widget.CloseWindow(); - cs.GetWidget("BUTTON_START").OnClick = () => - { - settings.Server.Name = cs.GetWidget("GAME_TITLE").Text; - settings.Server.ListenPort = int.Parse(cs.GetWidget("LISTEN_PORT").Text); - settings.Server.ExternalPort = int.Parse(cs.GetWidget("EXTERNAL_PORT").Text); - settings.Server.Map = WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map); - settings.Save(); - - // Take a copy so that subsequent settings changes don't affect the server - Game.CreateServer(new ServerSettings(Game.Settings.Server)); - Game.JoinServer(IPAddress.Loopback.ToString(), settings.Server.ListenPort); - }; - - cs.GetWidget("GAME_TITLE").Text = settings.Server.Name ?? ""; - cs.GetWidget("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); - cs.GetWidget("EXTERNAL_PORT").Text = settings.Server.ExternalPort.ToString(); - - var onlineCheckbox = cs.GetWidget("CHECKBOX_ONLINE"); - onlineCheckbox.IsChecked = () => settings.Server.AdvertiseOnline; - onlineCheckbox.OnClick = () => { settings.Server.AdvertiseOnline ^= true; settings.Save(); }; - } - } -} diff --git a/OpenRA.Mods.RA/Widgets/Logic/DeveloperModeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/DeveloperModeLogic.cs index 2e40e26e06..4411f345c1 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/DeveloperModeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/DeveloperModeLogic.cs @@ -1,20 +1,10 @@ #region Copyright & License Information /* - * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. - * This file is part of OpenRA. - * - * OpenRA is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * OpenRA is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with OpenRA. If not, see . + * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. */ #endregion diff --git a/OpenRA.Mods.RA/Widgets/Logic/DirectConnectLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/DirectConnectLogic.cs index 83fa978d1b..06a7ee3694 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/DirectConnectLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/DirectConnectLogic.cs @@ -8,7 +8,7 @@ */ #endregion -using System.Linq; +using System; using OpenRA.Widgets; namespace OpenRA.Mods.RA.Widgets.Logic @@ -16,34 +16,28 @@ namespace OpenRA.Mods.RA.Widgets.Logic public class DirectConnectLogic { [ObjectCreator.UseCtor] - public DirectConnectLogic(Widget widget) + public DirectConnectLogic(Widget widget, Action onExit, Action openLobby) { - var dc = widget.GetWidget("DIRECTCONNECT_BG"); + var panel = widget; + var ipField = panel.GetWidget("IP"); + var portField = panel.GetWidget("PORT"); - dc.GetWidget("SERVER_ADDRESS").Text = Game.Settings.Player.LastServer; + var last = Game.Settings.Player.LastServer.Split(':'); + ipField.Text = last.Length > 1 ? last[0] : "localhost"; + portField.Text = last.Length > 2 ? last[1] : "1234"; - dc.GetWidget("JOIN_BUTTON").OnClick = () => + panel.GetWidget("JOIN_BUTTON").OnClick = () => { - var address = dc.GetWidget("SERVER_ADDRESS").Text; - var addressParts = address.Split(':'); - if (addressParts.Length < 1 || addressParts.Length > 2) - return; + var port = Exts.WithDefault(1234, () => int.Parse(portField.Text)); - var port = Exts.WithDefault(1234, () => int.Parse(addressParts[1])); - - Game.Settings.Player.LastServer = address; + Game.Settings.Player.LastServer = "{0}:{1}".F(ipField.Text, port); Game.Settings.Save(); Widget.CloseWindow(); - Game.JoinServer(addressParts[0], port); + ConnectionLogic.Connect(ipField.Text, port, openLobby, onExit); }; - dc.GetWidget("CANCEL_BUTTON").OnClick = () => - { - Widget.CloseWindow(); - Widget.OpenWindow("MAINMENU_BG"); - }; + panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; } } } - diff --git a/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs index f0208f930a..56727332df 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/LobbyLogic.cs @@ -20,8 +20,10 @@ namespace OpenRA.Mods.RA.Widgets.Logic { public class LobbyLogic { - Widget lobby, LocalPlayerTemplate, RemotePlayerTemplate, EmptySlotTemplate, EmptySlotTemplateHost, - LocalSpectatorTemplate, RemoteSpectatorTemplate, NewSpectatorTemplate; + Widget EditablePlayerTemplate, NonEditablePlayerTemplate, EmptySlotTemplate, + EditableSpectatorTemplate, NonEditableSpectatorTemplate, NewSpectatorTemplate; + ScrollPanelWidget chatPanel; + Widget chatTemplate; ScrollPanelWidget Players; Dictionary CountryNames; @@ -30,39 +32,98 @@ namespace OpenRA.Mods.RA.Widgets.Logic ColorPickerPaletteModifier PlayerPalettePreview; + readonly Action OnGameStart; + readonly Action onExit; readonly OrderManager orderManager; - [ObjectCreator.UseCtor] - internal LobbyLogic(Widget widget, World world, OrderManager orderManager) + // Listen for connection failures + void ConnectionStateChanged(OrderManager om) { + if (om.Connection.ConnectionState == ConnectionState.NotConnected) + { + // Show connection failed dialog + CloseWindow(); + + Action onConnect = () => + { + Game.OpenWindow("SERVER_LOBBY", new WidgetArgs() + { + { "onExit", onExit }, + { "onStart", OnGameStart }, + { "addBots", false } + }); + }; + + Action onRetry = () => + { + CloseWindow(); + ConnectionLogic.Connect(om.Host, om.Port, onConnect, onExit); + }; + + Widget.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() + { + { "onAbort", onExit }, + { "onRetry", onRetry }, + { "host", om.Host }, + { "port", om.Port } + }); + } + } + + void CloseWindow() + { + Game.LobbyInfoChanged -= UpdateCurrentMap; + Game.LobbyInfoChanged -= UpdatePlayerList; + Game.BeforeGameStart -= OnGameStart; + Game.AddChatLine -= AddChatLine; + Game.ConnectionStateChanged -= ConnectionStateChanged; + + Widget.CloseWindow(); + } + + [ObjectCreator.UseCtor] + internal LobbyLogic(Widget widget, World world, OrderManager orderManager, + Action onExit, Action onStart, bool addBots) + { + var lobby = widget; this.orderManager = orderManager; - this.lobby = widget; - Game.BeforeGameStart += CloseWindow; + this.OnGameStart = () => { CloseWindow(); onStart(); }; + this.onExit = onExit; + Game.LobbyInfoChanged += UpdateCurrentMap; Game.LobbyInfoChanged += UpdatePlayerList; - UpdateCurrentMap(); + Game.BeforeGameStart += OnGameStart; + Game.AddChatLine += AddChatLine; + Game.ConnectionStateChanged += ConnectionStateChanged; + UpdateCurrentMap(); PlayerPalettePreview = world.WorldActor.Trait(); PlayerPalettePreview.Ramp = Game.Settings.Player.ColorRamp; - Players = lobby.GetWidget("PLAYERS"); - LocalPlayerTemplate = Players.GetWidget("TEMPLATE_LOCAL"); - RemotePlayerTemplate = Players.GetWidget("TEMPLATE_REMOTE"); + EditablePlayerTemplate = Players.GetWidget("TEMPLATE_EDITABLE_PLAYER"); + NonEditablePlayerTemplate = Players.GetWidget("TEMPLATE_NONEDITABLE_PLAYER"); EmptySlotTemplate = Players.GetWidget("TEMPLATE_EMPTY"); - EmptySlotTemplateHost = Players.GetWidget("TEMPLATE_EMPTY_HOST"); - LocalSpectatorTemplate = Players.GetWidget("TEMPLATE_LOCAL_SPECTATOR"); - RemoteSpectatorTemplate = Players.GetWidget("TEMPLATE_REMOTE_SPECTATOR"); + EditableSpectatorTemplate = Players.GetWidget("TEMPLATE_EDITABLE_SPECTATOR"); + NonEditableSpectatorTemplate = Players.GetWidget("TEMPLATE_NONEDITABLE_SPECTATOR"); NewSpectatorTemplate = Players.GetWidget("TEMPLATE_NEW_SPECTATOR"); - var mapPreview = lobby.GetWidget("LOBBY_MAP_PREVIEW"); + var mapPreview = lobby.GetWidget("MAP_PREVIEW"); + mapPreview.IsVisible = () => Map != null; mapPreview.Map = () => Map; mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint( orderManager, mapPreview, Map, mi ); mapPreview.SpawnColors = () => LobbyUtils.GetSpawnColors( orderManager, Map ); + var mapTitle = lobby.GetWidget("MAP_TITLE"); + if (mapTitle != null) + { + mapTitle.IsVisible = () => Map != null; + mapTitle.GetText = () => Map.Title; + } + CountryNames = Rules.Info["world"].Traits.WithInterface() .Where(c => c.Selectable) .ToDictionary(a => a.Race, a => a.Name); - CountryNames.Add("random", "Random"); + CountryNames.Add("random", "Any"); var mapButton = lobby.GetWidget("CHANGEMAP_BUTTON"); mapButton.OnClick = () => @@ -74,48 +135,40 @@ namespace OpenRA.Mods.RA.Widgets.Logic Game.Settings.Save(); }); - Widget.OpenWindow("MAP_CHOOSER", new WidgetArgs() + Widget.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { - { "initialMap", MapUid }, + { "initialMap", Map.Uid }, { "onExit", () => {} }, { "onSelect", onSelect } }); }; - mapButton.IsVisible = () => mapButton.Visible && Game.IsHost; var disconnectButton = lobby.GetWidget("DISCONNECT_BUTTON"); - disconnectButton.OnClick = () => - { - CloseWindow(); - Game.Disconnect(); - Game.LoadShellMap(); - Widget.OpenWindow("MAINMENU_BG"); - }; + disconnectButton.OnClick = () => { CloseWindow(); onExit(); }; + + var gameStarting = false; var allowCheats = lobby.GetWidget("ALLOWCHEATS_CHECKBOX"); allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats; - allowCheats.OnClick = () => - { - if (Game.IsHost) - orderManager.IssueOrder(Order.Command( + allowCheats.IsDisabled = () => !Game.IsHost || gameStarting || orderManager.LocalClient == null + || orderManager.LocalClient.IsReady; + allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command( "allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats))); - }; var startGameButton = lobby.GetWidget("START_GAME_BUTTON"); + startGameButton.IsVisible = () => Game.IsHost; + startGameButton.IsDisabled = () => gameStarting; startGameButton.OnClick = () => { - mapButton.Visible = false; - disconnectButton.Visible = false; + gameStarting = true; orderManager.IssueOrder(Order.Command("startgame")); }; - // Todo: Only show if the map requirements are met for player slots - startGameButton.IsVisible = () => Game.IsHost; - bool teamChat = false; var chatLabel = lobby.GetWidget("LABEL_CHATTYPE"); var chatTextField = lobby.GetWidget("CHAT_TEXTFIELD"); + chatTextField.OnEnterKey = () => { if (chatTextField.Text.Length == 0) @@ -133,36 +186,69 @@ namespace OpenRA.Mods.RA.Widgets.Logic return true; }; - Game.AddChatLine += AddChatLine; - } + chatPanel = lobby.GetWidget("CHAT_DISPLAY"); + chatTemplate = chatPanel.GetWidget("CHAT_TEMPLATE"); + chatPanel.RemoveChildren(); - public void CloseWindow() - { - Game.LobbyInfoChanged -= UpdateCurrentMap; - Game.LobbyInfoChanged -= UpdatePlayerList; - Game.AddChatLine -= AddChatLine; - Game.BeforeGameStart -= CloseWindow; + var musicButton = lobby.GetWidget("MUSIC_BUTTON"); + if (musicButton != null) + musicButton.OnClick = () => Widget.OpenWindow("MUSIC_PANEL", new WidgetArgs + { { "onExit", () => {} } }); - Widget.CloseWindow(); + // 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().Select(t => t.Name).FirstOrDefault(); + if (slot != null && bot != null) + orderManager.IssueOrder(Order.Command("slot_bot {0} {1}".F(slot, bot))); + }); } void AddChatLine(Color c, string from, string text) { - lobby.GetWidget("CHAT_DISPLAY").AddLine(c, from, text); + var template = chatTemplate.Clone(); + var nameLabel = template.GetWidget("NAME"); + var timeLabel = template.GetWidget("TIME"); + var textLabel = template.GetWidget("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.Play("scold1.aud"); } void UpdateCurrentMap() { - var newMap = orderManager.LobbyInfo.GlobalSettings.Map; - if (MapUid == newMap) return; - - MapUid = newMap; + if (MapUid == orderManager.LobbyInfo.GlobalSettings.Map) return; + MapUid = orderManager.LobbyInfo.GlobalSettings.Map; Map = new Map(Game.modData.AvailableMaps[MapUid].Path); - var title = Widget.RootWidget.GetWidget("LOBBY_TITLE"); - if (title != null) - title.Text = "OpenRA Multiplayer Lobby - {0} - {1}".F( - orderManager.LobbyInfo.GlobalSettings.ServerName, Map.Title); + var title = Widget.RootWidget.GetWidget("TITLE"); + title.Text = orderManager.LobbyInfo.GlobalSettings.ServerName; } void UpdatePlayerList() @@ -173,108 +259,119 @@ namespace OpenRA.Mods.RA.Widgets.Logic foreach (var kv in orderManager.LobbyInfo.Slots) { - var s = kv.Value; - var c = orderManager.LobbyInfo.ClientInSlot(kv.Key); + var key = kv.Key; + var slot = kv.Value; + var client = orderManager.LobbyInfo.ClientInSlot(key); Widget template; - if (c == null) + // Empty slot + if (client == null) { + template = EmptySlotTemplate.Clone(); + Func getText = () => slot.Closed ? "Closed" : "Open"; + var ready = orderManager.LocalClient.IsReady; + if (Game.IsHost) { - template = EmptySlotTemplateHost.Clone(); - var name = template.GetWidget("NAME"); - name.GetText = () => s.Closed ? "Closed" : "Open"; - name.OnMouseDown = _ => LobbyUtils.ShowSlotDropDown(name, s, c, orderManager); + var name = template.GetWidget("NAME_HOST"); + name.IsVisible = () => true; + name.IsDisabled = () => ready; + name.GetText = getText; + name.OnMouseDown = _ => LobbyUtils.ShowSlotDropDown(name, slot, client, orderManager); } else { - template = EmptySlotTemplate.Clone(); var name = template.GetWidget("NAME"); - name.GetText = () => s.Closed ? "Closed" : "Open"; + name.IsVisible = () => true; + name.GetText = getText; } var join = template.GetWidget("JOIN"); - if (join != null) - { - join.OnClick = () => orderManager.IssueOrder(Order.Command("slot " + s.PlayerReference)); - join.IsVisible = () => !s.Closed && c == null && !orderManager.LocalClient.IsReady; - } + join.IsVisible = () => !slot.Closed; + join.IsDisabled = () => ready; + join.OnClick = () => orderManager.IssueOrder(Order.Command("slot " + key)); } - - else if ((c.Index == orderManager.LocalClient.Index && !c.IsReady) || (c.Bot != null && Game.IsHost)) + // Editable player in slot + else if ((client.Index == orderManager.LocalClient.Index) || + (client.Bot != null && Game.IsHost)) { - template = LocalPlayerTemplate.Clone(); + template = EditablePlayerTemplate.Clone(); + var botReady = client.Bot != null && Game.IsHost && orderManager.LocalClient.IsReady; + var ready = botReady || client.IsReady; - var botReady = (c.Bot != null && Game.IsHost - && orderManager.LocalClient.IsReady); - var ready = botReady || c.IsReady; - - if (c.Bot == null) - { - LobbyUtils.SetupNameWidget(orderManager, c, template.GetWidget("NAME")); - } - else + if (client.Bot != null) { var name = template.GetWidget("BOT_DROPDOWN"); name.IsVisible = () => true; name.IsDisabled = () => ready; - name.GetText = () => c.Name; - name.OnMouseDown = _ => LobbyUtils.ShowSlotDropDown(name, s, c, orderManager); - } + name.GetText = () => client.Name; + name.OnMouseDown = _ => LobbyUtils.ShowSlotDropDown(name, slot, client, orderManager); + } + else + { + var name = template.GetWidget("NAME"); + name.IsVisible = () => true; + name.IsDisabled = () => ready; + LobbyUtils.SetupNameWidget(orderManager, client, name); + } var color = template.GetWidget("COLOR"); - color.IsDisabled = () => s.LockColor; - color.OnMouseDown = _ => LobbyUtils.ShowColorDropDown(color, c, orderManager, PlayerPalettePreview); + color.IsDisabled = () => slot.LockColor || ready; + color.OnMouseDown = _ => LobbyUtils.ShowColorDropDown(color, client, orderManager, PlayerPalettePreview); var colorBlock = color.GetWidget("COLORBLOCK"); - colorBlock.GetColor = () => c.ColorRamp.GetColor(0); + colorBlock.GetColor = () => client.ColorRamp.GetColor(0); var faction = template.GetWidget("FACTION"); - faction.IsDisabled = () => s.LockRace; - faction.OnMouseDown = _ => LobbyUtils.ShowRaceDropDown(faction, c, orderManager, CountryNames); + faction.IsDisabled = () => slot.LockRace || ready; + faction.OnMouseDown = _ => LobbyUtils.ShowRaceDropDown(faction, client, orderManager, CountryNames); var factionname = faction.GetWidget("FACTIONNAME"); - factionname.GetText = () => CountryNames[c.Country]; + factionname.GetText = () => CountryNames[client.Country]; var factionflag = faction.GetWidget("FACTIONFLAG"); - factionflag.GetImageName = () => c.Country; + factionflag.GetImageName = () => client.Country; factionflag.GetImageCollection = () => "flags"; var team = template.GetWidget("TEAM"); - team.IsDisabled = () => s.LockTeam; - team.OnMouseDown = _ => LobbyUtils.ShowTeamDropDown(team, c, orderManager, Map); - team.GetText = () => (c.Team == 0) ? "-" : c.Team.ToString(); + team.IsDisabled = () => slot.LockTeam || ready; + team.OnMouseDown = _ => LobbyUtils.ShowTeamDropDown(team, client, orderManager, Map); + team.GetText = () => (client.Team == 0) ? "-" : client.Team.ToString(); - var status = template.GetWidget("STATUS"); - status.IsChecked = () => c.IsReady; - status.OnClick = CycleReady; - status.IsVisible = () => c.Bot == null; + if (client.Bot == null) + { + // local player + var status = template.GetWidget("STATUS_CHECKBOX"); + status.IsChecked = () => ready; + status.IsVisible = () => true; + status.OnClick += CycleReady; + } + else // Bot + template.GetWidget("STATUS_IMAGE").IsVisible = () => true; } else - { - template = RemotePlayerTemplate.Clone(); - template.GetWidget("NAME").GetText = () => c.Name; + { // Non-editable player in slot + template = NonEditablePlayerTemplate.Clone(); + template.GetWidget("NAME").GetText = () => client.Name; var color = template.GetWidget("COLOR"); - color.GetColor = () => c.ColorRamp.GetColor(0); + color.GetColor = () => client.ColorRamp.GetColor(0); var faction = template.GetWidget("FACTION"); var factionname = faction.GetWidget("FACTIONNAME"); - factionname.GetText = () => CountryNames[c.Country]; + factionname.GetText = () => CountryNames[client.Country]; var factionflag = faction.GetWidget("FACTIONFLAG"); - factionflag.GetImageName = () => c.Country; + factionflag.GetImageName = () => client.Country; factionflag.GetImageCollection = () => "flags"; var team = template.GetWidget("TEAM"); - team.GetText = () => (c.Team == 0) ? "-" : c.Team.ToString(); + team.GetText = () => (client.Team == 0) ? "-" : client.Team.ToString(); - var status = template.GetWidget("STATUS"); - status.IsChecked = () => c.IsReady; - if (c.Index == orderManager.LocalClient.Index) - status.OnClick = CycleReady; - status.IsVisible = () => c.Bot == null; + template.GetWidget("STATUS_IMAGE").IsVisible = () => + client.Bot != null || client.IsReady; var kickButton = template.GetWidget("KICK"); - kickButton.IsVisible = () => Game.IsHost && c.Index != orderManager.LocalClient.Index; - kickButton.OnClick = () => orderManager.IssueOrder(Order.Command("kick " + c.Index)); + kickButton.IsVisible = () => Game.IsHost && client.Index != orderManager.LocalClient.Index; + kickButton.IsDisabled = () => orderManager.LocalClient.IsReady; + kickButton.OnClick = () => orderManager.IssueOrder(Order.Command("kick " + client.Index)); } template.IsVisible = () => true; @@ -284,39 +381,42 @@ namespace OpenRA.Mods.RA.Widgets.Logic // Add spectators foreach (var client in orderManager.LobbyInfo.Clients.Where(client => client.Slot == null)) { - var c = client; Widget template; + var c = client; + var ready = c.IsReady; + // Editable spectator - if (c.Index == orderManager.LocalClient.Index && !c.IsReady) + if (c.Index == orderManager.LocalClient.Index) { - template = LocalSpectatorTemplate.Clone(); - LobbyUtils.SetupNameWidget(orderManager, c, template.GetWidget("NAME")); + template = EditableSpectatorTemplate.Clone(); + var name = template.GetWidget("NAME"); + name.IsDisabled = () => ready; + LobbyUtils.SetupNameWidget(orderManager, c, name); var color = template.GetWidget("COLOR"); + color.IsDisabled = () => ready; color.OnMouseDown = _ => LobbyUtils.ShowColorDropDown(color, c, orderManager, PlayerPalettePreview); var colorBlock = color.GetWidget("COLORBLOCK"); colorBlock.GetColor = () => c.ColorRamp.GetColor(0); - var status = template.GetWidget("STATUS"); - status.IsChecked = () => c.IsReady; + var status = template.GetWidget("STATUS_CHECKBOX"); + status.IsChecked = () => ready; status.OnClick += CycleReady; } // Non-editable spectator else { - template = RemoteSpectatorTemplate.Clone(); + template = NonEditableSpectatorTemplate.Clone(); template.GetWidget("NAME").GetText = () => c.Name; var color = template.GetWidget("COLOR"); color.GetColor = () => c.ColorRamp.GetColor(0); - var status = template.GetWidget("STATUS"); - status.IsChecked = () => c.IsReady; - if (c.Index == orderManager.LocalClient.Index) - status.OnClick += CycleReady; + template.GetWidget("STATUS_IMAGE").IsVisible = () => c.Bot != null || c.IsReady; var kickButton = template.GetWidget("KICK"); kickButton.IsVisible = () => Game.IsHost && c.Index != orderManager.LocalClient.Index; + kickButton.IsDisabled = () => orderManager.LocalClient.IsReady; kickButton.OnClick = () => orderManager.IssueOrder(Order.Command("kick " + c.Index)); } @@ -325,11 +425,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic } // Spectate button - if (orderManager.LocalClient.Slot != null && !orderManager.LocalClient.IsReady) + if (orderManager.LocalClient.Slot != null) { var spec = NewSpectatorTemplate.Clone(); var btn = spec.GetWidget("SPECTATE"); btn.OnClick = () => orderManager.IssueOrder(Order.Command("spectate")); + btn.IsDisabled = () => orderManager.LocalClient.IsReady; spec.IsVisible = () => true; Players.AddChild(spec); } diff --git a/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs index 8421648a87..772ca6790e 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MainMenuButtonsLogic.cs @@ -8,58 +8,62 @@ */ #endregion -using System; -using System.Linq; -using OpenRA.FileFormats; using OpenRA.Widgets; namespace OpenRA.Mods.RA.Widgets.Logic { public class MainMenuButtonsLogic { + Widget rootMenu; + [ObjectCreator.UseCtor] public MainMenuButtonsLogic(Widget widget) { + rootMenu = widget; + Game.modData.WidgetLoader.LoadWidget( new WidgetArgs(), Widget.RootWidget, "PERF_BG" ); - widget.GetWidget("MAINMENU_BUTTON_JOIN").OnClick = () => Widget.OpenWindow("JOINSERVER_BG"); - widget.GetWidget("MAINMENU_BUTTON_CREATE").OnClick = () => Widget.OpenWindow("CREATESERVER_BG"); + widget.GetWidget("MAINMENU_BUTTON_JOIN").OnClick = () => OpenGamePanel("JOINSERVER_BG"); + widget.GetWidget("MAINMENU_BUTTON_CREATE").OnClick = () => OpenGamePanel("CREATESERVER_BG"); + widget.GetWidget("MAINMENU_BUTTON_DIRECTCONNECT").OnClick = () => OpenGamePanel("DIRECTCONNECT_BG"); widget.GetWidget("MAINMENU_BUTTON_SETTINGS").OnClick = () => Widget.OpenWindow("SETTINGS_MENU"); widget.GetWidget("MAINMENU_BUTTON_MUSIC").OnClick = () => Widget.OpenWindow("MUSIC_MENU"); - widget.GetWidget("MAINMENU_BUTTON_REPLAY_VIEWER").OnClick = () => Widget.OpenWindow("REPLAYBROWSER_BG"); + widget.GetWidget("MAINMENU_BUTTON_MODS").OnClick = () => + Widget.OpenWindow("MODS_PANEL", new WidgetArgs() + { + { "onExit", () => {} }, + { "onSwitch", RemoveShellmapUI } + }); + widget.GetWidget("MAINMENU_BUTTON_REPLAY_VIEWER").OnClick = () => + Widget.OpenWindow("REPLAYBROWSER_BG", new WidgetArgs() + { + { "onExit", () => {} }, + { "onStart", RemoveShellmapUI } + }); widget.GetWidget("MAINMENU_BUTTON_QUIT").OnClick = () => Game.Exit(); - - DisplayModSelector(); } - public static void DisplayModSelector() + void RemoveShellmapUI() { - var selector = Game.modData.WidgetLoader.LoadWidget( new WidgetArgs(), Widget.RootWidget, "QUICKMODSWITCHER" ); - var switcher = selector.GetWidget("SWITCHER"); - switcher.OnMouseDown = _ => ShowModsDropDown(switcher); - switcher.GetText = WidgetUtils.ActiveModTitle; - selector.GetWidget("VERSION").GetText = WidgetUtils.ActiveModVersion; + rootMenu.Parent.RemoveChild(rootMenu); } - static void LoadMod(string mod) + void OpenGamePanel(string id) { - var mods = Mod.AllMods[mod].WithPrerequisites(); - - if (Game.CurrentMods.Keys.SymmetricDifference(mods).Any()) - Game.RunAfterTick(() => Game.InitializeWithMods(mods)); - } - - static void ShowModsDropDown(DropDownButtonWidget dropdown) - { - Func setupItem = (m, itemTemplate) => + Widget.OpenWindow(id, new WidgetArgs() { - var item = ScrollItemWidget.Setup(itemTemplate, - () => m == Game.CurrentMods.Keys.First(), - () => LoadMod(m)); - item.GetWidget("LABEL").GetText = () => Mod.AllMods[m].Title; - return item; - }; + { "onExit", () => {} }, + { "openLobby", () => OpenLobbyPanel() } + }); + } - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 150, Mod.AllMods.Keys, setupItem); + void OpenLobbyPanel() + { + Game.OpenWindow("SERVER_LOBBY", new WidgetArgs() + { + { "onExit", () => { Game.Disconnect(); } }, + { "onStart", RemoveShellmapUI }, + { "addBots", false } + }); } } } diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncModBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs similarity index 87% rename from OpenRA.Mods.Cnc/Widgets/Logic/CncModBrowserLogic.cs rename to OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs index 5e3273ca2d..f6327f3048 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncModBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ModBrowserLogic.cs @@ -13,16 +13,16 @@ using System.Linq; using OpenRA.FileFormats; using OpenRA.Widgets; -namespace OpenRA.Mods.Cnc.Widgets.Logic +namespace OpenRA.Mods.RA.Widgets.Logic { - public class CncModBrowserLogic + public class ModBrowserLogic { Mod currentMod; [ObjectCreator.UseCtor] - public CncModBrowserLogic(Widget widget, Action onSwitch, Action onExit) + public ModBrowserLogic(Widget widget, Action onSwitch, Action onExit) { - var panel = widget.GetWidget("MODS_PANEL"); + var panel = widget; var modList = panel.GetWidget("MOD_LIST"); var loadButton = panel.GetWidget("LOAD_BUTTON"); loadButton.OnClick = () => LoadMod(currentMod.Id, onSwitch); @@ -53,7 +53,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic { Widget.CloseWindow(); onSwitch(); - Game.InitializeWithMods(mods.ToArray()); + Game.InitializeWithMods(mods); }); } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/RAInstallLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/RAInstallLogic.cs index cb2080fb1c..733c2ced3c 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/RAInstallLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/RAInstallLogic.cs @@ -33,8 +33,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic Widget.OpenWindow("INSTALL_FROMCD_PANEL", args); panel.GetWidget("QUIT_BUTTON").OnClick = Game.Exit; - - MainMenuButtonsLogic.DisplayModSelector(); } } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/ReplayBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ReplayBrowserLogic.cs index f279760699..f56d248c6e 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ReplayBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ReplayBrowserLogic.cs @@ -18,70 +18,80 @@ namespace OpenRA.Mods.RA.Widgets.Logic { public class ReplayBrowserLogic { - Widget widget; + Widget panel; [ObjectCreator.UseCtor] - public ReplayBrowserLogic(Widget widget) + public ReplayBrowserLogic(Widget widget, Action onExit, Action onStart) { - this.widget = widget; + panel = widget; - widget.GetWidget("CANCEL_BUTTON").OnClick = () => Widget.CloseWindow(); + panel.GetWidget("CANCEL_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; - /* find some replays? */ - var rl = widget.GetWidget("REPLAY_LIST"); + var rl = panel.GetWidget("REPLAY_LIST"); var replayDir = Path.Combine(Platform.SupportDir, "Replays"); - var template = widget.GetWidget("REPLAY_TEMPLATE"); - SelectReplay(null); + var template = panel.GetWidget("REPLAY_TEMPLATE"); rl.RemoveChildren(); if (Directory.Exists(replayDir)) - foreach (var replayFile in Directory.GetFiles(replayDir, "*.rep").Reverse()) + { + var files = Directory.GetFiles(replayDir, "*.rep").Reverse(); + foreach (var replayFile in files) AddReplay(rl, replayFile, template); - widget.GetWidget("WATCH_BUTTON").OnClick = () => + SelectReplay(files.FirstOrDefault()); + } + + var watch = panel.GetWidget("WATCH_BUTTON"); + watch.IsDisabled = () => currentReplay == null || currentMap == null || currentReplay.Duration == 0; + watch.OnClick = () => { if (currentReplay != null) { + Game.JoinReplay(currentReplay.Filename); Widget.CloseWindow(); - Game.JoinReplay(currentReplay); + onStart(); } }; - widget.GetWidget("REPLAY_INFO").IsVisible = () => currentReplay != null; + panel.GetWidget("REPLAY_INFO").IsVisible = () => currentReplay != null; } - string currentReplay; + Replay currentReplay; + Map currentMap; void SelectReplay(string filename) { - currentReplay = filename; + if (filename == null) + return; - if (currentReplay != null) + try { - try - { - var summary = new Replay(currentReplay); - var mapStub = summary.Map(); + currentReplay = new Replay(filename); + currentMap = currentReplay.Map(); - widget.GetWidget("DURATION").GetText = - () => WidgetUtils.FormatTime(summary.Duration * 3 /* todo: 3:1 ratio isnt always true. */); - widget.GetWidget("MAP_PREVIEW").Map = () => mapStub; - widget.GetWidget("MAP_TITLE").GetText = - () => mapStub != null ? mapStub.Title : "(Unknown Map)"; - } - catch(Exception e) - { - Log.Write("debug", "Exception while parsing replay: {0}", e); - currentReplay = null; - } + panel.GetWidget("DURATION").GetText = + () => WidgetUtils.FormatTime(currentReplay.Duration * 3 /* todo: 3:1 ratio isnt always true. */); + panel.GetWidget("MAP_PREVIEW").Map = () => currentMap; + panel.GetWidget("MAP_TITLE").GetText = + () => currentMap != null ? currentMap.Title : "(Unknown Map)"; + + var players = currentReplay.LobbyInfo.Slots + .Count(s => currentReplay.LobbyInfo.ClientInSlot(s.Key) != null); + panel.GetWidget("PLAYERS").GetText = () => players.ToString(); + } + catch (Exception e) + { + Log.Write("debug", "Exception while parsing replay: {0}", e); + currentReplay = null; + currentMap = null; } } void AddReplay(ScrollPanelWidget list, string filename, ScrollItemWidget template) { var item = ScrollItemWidget.Setup(template, - () => currentReplay == filename, + () => currentReplay != null && currentReplay.Filename == filename, () => SelectReplay(filename)); var f = Path.GetFileName(filename); item.GetWidget("TITLE").GetText = () => f; diff --git a/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs index 2bba35259b..a62bfbce1c 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ServerBrowserLogic.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; @@ -18,65 +19,88 @@ namespace OpenRA.Mods.RA.Widgets.Logic { public class ServerBrowserLogic { - GameServer currentServer = null; - ScrollItemWidget ServerTemplate; + GameServer currentServer; + ScrollItemWidget serverTemplate; + + enum SearchStatus { Fetching, Failed, NoGames, Hidden } + SearchStatus searchStatus = SearchStatus.Fetching; + + public string ProgressLabelText() + { + switch (searchStatus) + { + case SearchStatus.Fetching: return "Fetching game list..."; + case SearchStatus.Failed: return "Failed to contact master server."; + case SearchStatus.NoGames: return "No games found."; + default: return ""; + } + } [ObjectCreator.UseCtor] - public ServerBrowserLogic(Widget widget) + public ServerBrowserLogic(Widget widget, Action openLobby, Action onExit) { - var bg = widget.GetWidget("JOINSERVER_BG"); + var panel = widget; + var sl = panel.GetWidget("SERVER_LIST"); - bg.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true; - bg.GetWidget("JOINSERVER_PROGRESS_TITLE").Text = "Fetching game list..."; - - ServerList.Query(RefreshServerList); - - bg.GetWidget("SERVER_INFO").IsVisible = () => currentServer != null; - var preview = bg.GetWidget("MAP_PREVIEW"); - preview.Map = () => CurrentMap(); - preview.IsVisible = () => CurrentMap() != null; - - bg.GetWidget("SERVER_IP").GetText = () => currentServer.Address; - bg.GetWidget("SERVER_MODS").GetText = () => GenerateModsLabel(currentServer); - bg.GetWidget("MAP_TITLE").GetText = () => (CurrentMap() != null) ? CurrentMap().Title : "Unknown"; - bg.GetWidget("MAP_PLAYERS").GetText = () => + // Menu buttons + var refreshButton = panel.GetWidget("REFRESH_BUTTON"); + refreshButton.IsDisabled = () => searchStatus == SearchStatus.Fetching; + refreshButton.OnClick = () => { - if (currentServer == null) - return ""; - string ret = currentServer.Players.ToString(); - if (CurrentMap() != null) - ret += "/" + CurrentMap().PlayerCount.ToString(); - return ret; - }; - - var sl = bg.GetWidget("SERVER_LIST"); - ServerTemplate = sl.GetWidget("SERVER_TEMPLATE"); - - bg.GetWidget("REFRESH_BUTTON").OnClick = () => - { - bg.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true; - bg.GetWidget("JOINSERVER_PROGRESS_TITLE").Text = "Fetching game list..."; + searchStatus = SearchStatus.Fetching; sl.RemoveChildren(); currentServer = null; - - ServerList.Query(RefreshServerList); + ServerList.Query(games => RefreshServerList(panel, games)); }; - bg.GetWidget("CANCEL_BUTTON").OnClick = () => Widget.CloseWindow(); - bg.GetWidget("DIRECTCONNECT_BUTTON").OnClick = () => - { - Widget.CloseWindow(); - Widget.OpenWindow("DIRECTCONNECT_BG"); - }; - - bg.GetWidget("JOIN_BUTTON").OnClick = () => + var join = panel.GetWidget("JOIN_BUTTON"); + join.IsDisabled = () => currentServer == null || !currentServer.CanJoin(); + join.OnClick = () => { if (currentServer == null) return; + var host = currentServer.Address.Split(':')[0]; + var port = int.Parse(currentServer.Address.Split(':')[1]); + Widget.CloseWindow(); - Game.JoinServer(currentServer.Address.Split(':')[0], int.Parse(currentServer.Address.Split(':')[1])); + ConnectionLogic.Connect(host, port, openLobby, onExit); }; + + panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; + + // Server list + serverTemplate = sl.GetWidget("SERVER_TEMPLATE"); + + // Display the progress label over the server list + // The text is only visible when the list is empty + var progressText = panel.GetWidget("PROGRESS_LABEL"); + progressText.IsVisible = () => searchStatus != SearchStatus.Hidden; + progressText.GetText = ProgressLabelText; + + // Map preview + var preview = panel.GetWidget("MAP_PREVIEW"); + preview.Map = () => CurrentMap(); + preview.IsVisible = () => CurrentMap() != null; + + // Server info + var infoPanel = panel.GetWidget("SERVER_INFO"); + infoPanel.IsVisible = () => currentServer != null; + infoPanel.GetWidget("SERVER_IP").GetText = () => currentServer.Address; + infoPanel.GetWidget("SERVER_MODS").GetText = () => ServerBrowserLogic.GenerateModsLabel(currentServer); + infoPanel.GetWidget("MAP_TITLE").GetText = () => (CurrentMap() != null) ? CurrentMap().Title : "Unknown"; + infoPanel.GetWidget("MAP_PLAYERS").GetText = () => GetPlayersLabel(currentServer); + + ServerList.Query(games => RefreshServerList(panel, games)); + } + + string GetPlayersLabel(GameServer game) + { + if (game == null) + return ""; + + var map = Game.modData.FindMapByUid(game.Map); + return map == null ? "{0}".F(currentServer.Players) : "{0} / {1}".F(currentServer.Players, map.PlayerCount); } Map CurrentMap() @@ -97,23 +121,16 @@ namespace OpenRA.Mods.RA.Widgets.Logic return s.UsefulMods.Select(m => GenerateModLabel(m)).JoinWith("\n"); } - void RefreshServerList(IEnumerable games) + public void RefreshServerList(Widget panel, IEnumerable games) { - var r = Widget.RootWidget; - var bg = r.GetWidget("JOINSERVER_BG"); - - if (bg == null) // We got a MasterServer reply AFTER the browser is gone, just return to prevent crash - Gecko - return; - - var sl = bg.GetWidget("SERVER_LIST"); + var sl = panel.GetWidget("SERVER_LIST"); sl.RemoveChildren(); currentServer = null; if (games == null) { - r.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true; - r.GetWidget("JOINSERVER_PROGRESS_TITLE").Text = "Failed to contact master server."; + searchStatus = SearchStatus.Failed; return; } @@ -121,22 +138,28 @@ namespace OpenRA.Mods.RA.Widgets.Logic if (gamesWaiting.Count() == 0) { - r.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = true; - r.GetWidget("JOINSERVER_PROGRESS_TITLE").Text = "No games found."; + searchStatus = SearchStatus.NoGames; return; } - r.GetWidget("JOINSERVER_PROGRESS_TITLE").Visible = false; - + searchStatus = SearchStatus.Hidden; currentServer = gamesWaiting.FirstOrDefault(); foreach (var loop in gamesWaiting) { var game = loop; - var item = ScrollItemWidget.Setup(ServerTemplate, - () => currentServer == game, - () => currentServer = game); - item.GetWidget("TITLE").GetText = () => "{0} ({1})".F(game.Name, game.Address); + + var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => currentServer = game); + item.GetWidget("TITLE").GetText = () => game.Name; + // TODO: Use game.MapTitle once the server supports it + item.GetWidget("MAP").GetText = () => + { + var map = Game.modData.FindMapByUid(game.Map); + return map == null ? "Unknown" : map.Title; + }; + // TODO: Use game.MaxPlayers once the server supports it + item.GetWidget("PLAYERS").GetText = () => GetPlayersLabel(game); + item.GetWidget("IP").GetText = () => game.Address; sl.AddChild(item); } } diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncServerCreationLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs similarity index 72% rename from OpenRA.Mods.Cnc/Widgets/Logic/CncServerCreationLogic.cs rename to OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs index 7b913392c1..aaa8da3bd3 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncServerCreationLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/ServerCreationLogic.cs @@ -13,9 +13,9 @@ using System.Net; using OpenRA.GameRules; using OpenRA.Widgets; -namespace OpenRA.Mods.Cnc.Widgets.Logic +namespace OpenRA.Mods.RA.Widgets.Logic { - public class CncServerCreationLogic + public class ServerCreationLogic { Widget panel; Action onCreate; @@ -24,9 +24,9 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic bool advertiseOnline; [ObjectCreator.UseCtor] - public CncServerCreationLogic(Widget widget, Action onExit, Action openLobby) + public ServerCreationLogic(Widget widget, Action onExit, Action openLobby) { - panel = widget.GetWidget("CREATESERVER_PANEL"); + panel = widget; onCreate = openLobby; this.onExit = onExit; @@ -34,20 +34,24 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; panel.GetWidget("CREATE_BUTTON").OnClick = CreateAndJoin; - panel.GetWidget("MAP_BUTTON").OnClick = () => - { - Widget.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() - { - { "initialMap", map.Uid }, - { "onExit", () => {} }, - { "onSelect", (Action)(m => map = m) } - }); - }; - map = Game.modData.AvailableMaps[ WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map) ]; - panel.GetWidget("MAP_PREVIEW").Map = () => map; - panel.GetWidget("MAP_NAME").GetText = () => map.Title; + var mapButton = panel.GetWidget("MAP_BUTTON"); + if (mapButton != null) + { + panel.GetWidget("MAP_BUTTON").OnClick = () => + { + Widget.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() + { + { "initialMap", map.Uid }, + { "onExit", () => {} }, + { "onSelect", (Action)(m => map = m) } + }); + }; + + panel.GetWidget("MAP_PREVIEW").Map = () => map; + panel.GetWidget("MAP_NAME").GetText = () => map.Title; + } panel.GetWidget("SERVER_NAME").Text = settings.Server.Name ?? ""; panel.GetWidget("LISTEN_PORT").Text = settings.Server.ListenPort.ToString(); @@ -60,10 +64,6 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic var advertiseCheckbox = panel.GetWidget("ADVERTISE_CHECKBOX"); advertiseCheckbox.IsChecked = () => advertiseOnline; advertiseCheckbox.OnClick = () => advertiseOnline ^= true; - - // Disable these until we have some logic behind them - panel.GetWidget("SERVER_DESC").IsDisabled = () => true; - panel.GetWidget("SERVER_PASSWORD").IsDisabled = () => true; } void CreateAndJoin() @@ -90,7 +90,7 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic // Create and join the server Game.CreateServer(settings); Widget.CloseWindow(); - CncConnectionLogic.Connect(IPAddress.Loopback.ToString(), Game.Settings.Server.ListenPort, onCreate, onExit); + ConnectionLogic.Connect(IPAddress.Loopback.ToString(), Game.Settings.Server.ListenPort, onCreate, onExit); } } } diff --git a/mods/cnc/chrome/connection.yaml b/mods/cnc/chrome/connection.yaml index d88bd15f02..9b3eefb319 100644 --- a/mods/cnc/chrome/connection.yaml +++ b/mods/cnc/chrome/connection.yaml @@ -1,6 +1,6 @@ Container@CONNECTING_PANEL: Id:CONNECTING_PANEL - Logic:CncConnectionLogic + Logic:ConnectionLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 90)/2 Width:370 @@ -37,7 +37,7 @@ Container@CONNECTING_PANEL: Container@CONNECTIONFAILED_PANEL: Id:CONNECTIONFAILED_PANEL - Logic:CncConnectionFailedLogic + Logic:ConnectionFailedLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 90)/2 Width:370 @@ -77,4 +77,4 @@ Container@CONNECTIONFAILED_PANEL: Y:89 Width:140 Height:35 - Text:Abort \ No newline at end of file + Text:Abort diff --git a/mods/cnc/chrome/createserver.yaml b/mods/cnc/chrome/createserver.yaml index 50e1511b24..c1423669d0 100644 --- a/mods/cnc/chrome/createserver.yaml +++ b/mods/cnc/chrome/createserver.yaml @@ -1,9 +1,6 @@ -# TODO: Hook up the description field -# TODO: Hook up the password field -# TODO: Have the advertise checkbox en/disable the external port textfield Container@CREATESERVER_PANEL: Id:CREATESERVER_PANEL - Logic:CncServerCreationLogic + Logic:ServerCreationLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 260)/2 Width:604 @@ -57,34 +54,6 @@ Container@CREATESERVER_PANEL: MaxLength:50 Height:25 Text:My OpenRA Server - Label@SERVER_DESC_LABEL: - X:15 - Y:49 - Width:90 - Height:25 - Align:Right - Text:Description: - TextField@SERVER_DESC: - Id:SERVER_DESC - X:110 - Y:50 - Width:275 - MaxLength:50 - Height:25 - Label@SERVER_PASSWORD_LABEL: - X:15 - Y:84 - Width:90 - Height:25 - Align:Right - Text:Password: - TextField@SERVER_PASSWORD: - Id:SERVER_PASSWORD - X:110 - Y:85 - Width:275 - MaxLength:50 - Height:25 Label@LISTEN_PORT_LABEL: X:15 Y:119 @@ -151,4 +120,4 @@ Container@CREATESERVER_PANEL: Y:259 Width:140 Height:35 - Text:Create \ No newline at end of file + Text:Create diff --git a/mods/cnc/chrome/directconnect.yaml b/mods/cnc/chrome/directconnect.yaml index f0341023dd..26708e091d 100644 --- a/mods/cnc/chrome/directconnect.yaml +++ b/mods/cnc/chrome/directconnect.yaml @@ -1,6 +1,6 @@ Container@DIRECTCONNECT_PANEL: Id:DIRECTCONNECT_PANEL - Logic:CncDirectConnectLogic + Logic:DirectConnectLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 90)/2 Width:370 diff --git a/mods/cnc/chrome/lobby.yaml b/mods/cnc/chrome/lobby.yaml index cfbbac5dca..8322bd370c 100644 --- a/mods/cnc/chrome/lobby.yaml +++ b/mods/cnc/chrome/lobby.yaml @@ -1,6 +1,6 @@ Container@SERVER_LOBBY: Id:SERVER_LOBBY - Logic:CncLobbyLogic + Logic:LobbyLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 500)/2 Width:740 diff --git a/mods/cnc/chrome/modchooser.yaml b/mods/cnc/chrome/modchooser.yaml index cd8077b043..6e9e169479 100644 --- a/mods/cnc/chrome/modchooser.yaml +++ b/mods/cnc/chrome/modchooser.yaml @@ -1,6 +1,6 @@ Container@MODS_PANEL: Id:MODS_PANEL - Logic:CncModBrowserLogic + Logic:ModBrowserLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 500)/2 Width:740 @@ -93,4 +93,4 @@ Container@MODS_PANEL: Y:499 Width:140 Height:35 - Text:Load Mod \ No newline at end of file + Text:Load Mod diff --git a/mods/cnc/chrome/replaybrowser.yaml b/mods/cnc/chrome/replaybrowser.yaml index dc680d60d2..0c5e160da0 100644 --- a/mods/cnc/chrome/replaybrowser.yaml +++ b/mods/cnc/chrome/replaybrowser.yaml @@ -1,6 +1,6 @@ Container@REPLAYBROWSER_PANEL: Id:REPLAYBROWSER_PANEL - Logic:CncReplayBrowserLogic + Logic:ReplayBrowserLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 300)/2 Width:520 @@ -111,4 +111,4 @@ Container@REPLAYBROWSER_PANEL: Y:299 Width:140 Height:35 - Text:Watch \ No newline at end of file + Text:Watch diff --git a/mods/cnc/chrome/serverbrowser.yaml b/mods/cnc/chrome/serverbrowser.yaml index 556eefe053..0e5749ac10 100644 --- a/mods/cnc/chrome/serverbrowser.yaml +++ b/mods/cnc/chrome/serverbrowser.yaml @@ -1,6 +1,6 @@ Container@SERVERBROWSER_PANEL: Id:SERVERBROWSER_PANEL - Logic:CncServerBrowserLogic + Logic:ServerBrowserLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - 500)/2 Width:740 diff --git a/mods/ra/chrome/create-server.yaml b/mods/ra/chrome/create-server.yaml index a9d84722fe..8e21d9deff 100644 --- a/mods/ra/chrome/create-server.yaml +++ b/mods/ra/chrome/create-server.yaml @@ -1,6 +1,6 @@ Background@CREATESERVER_BG: Id:CREATESERVER_BG - Logic:CreateServerMenuLogic + Logic:ServerCreationLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - HEIGHT)/2 Width:400 @@ -15,16 +15,16 @@ Background@CREATESERVER_BG: Text:Create Server Align:Center Font:Bold - Label@GAME_TITLE_LABEL: - Id:GAME_TITLE_LABEL + Label@SERVER_NAME_LABEL: + Id:SERVER_NAME_LABEL X:50 Y:59 Width:95 Height:25 Align: Right Text:Game Title: - TextField@GAME_TITLE: - Id:GAME_TITLE + TextField@SERVER_NAME: + Id:SERVER_NAME X:150 Y:60 Width:210 @@ -62,15 +62,15 @@ Background@CREATESERVER_BG: Width:50 MaxLength:5 Height:25 - Checkbox@CHECKBOX_ONLINE: - Id:CHECKBOX_ONLINE + Checkbox@ADVERTISE_CHECKBOX: + Id:ADVERTISE_CHECKBOX X:165 Y:130 Width:300 Height:20 Text:Advertise game Online - Button@BUTTON_START: - Id:BUTTON_START + Button@CREATE_BUTTON: + Id:CREATE_BUTTON X:130 Y:PARENT_BOTTOM - 45 Width:120 @@ -78,8 +78,8 @@ Background@CREATESERVER_BG: Text:Create Font:Bold Key:return - Button@BUTTON_CANCEL: - Id:BUTTON_CANCEL + Button@BACK_BUTTON: + Id:BACK_BUTTON X:260 Y:PARENT_BOTTOM - 45 Width:120 diff --git a/mods/ra/chrome/lobby.yaml b/mods/ra/chrome/lobby.yaml index 6c0567ad02..2f2dccff37 100644 --- a/mods/ra/chrome/lobby.yaml +++ b/mods/ra/chrome/lobby.yaml @@ -6,8 +6,8 @@ Background@SERVER_LOBBY: Width:800 Height:600 Children: - Label@LOBBY_TITLE: - Id:LOBBY_TITLE + Label@TITLE: + Id:TITLE X:0 Y:17 Align:Center @@ -22,8 +22,8 @@ Background@SERVER_LOBBY: Height:252 Background:dialog3 Children: - MapPreview@LOBBY_MAP_PREVIEW: - Id:LOBBY_MAP_PREVIEW + MapPreview@MAP_PREVIEW: + Id:MAP_PREVIEW X:4 Y:4 Width:244 @@ -36,8 +36,8 @@ Background@SERVER_LOBBY: Width:504 Height:235 Children: - Container@TEMPLATE_LOCAL: - Id:TEMPLATE_LOCAL + Container@TEMPLATE_EDITABLE_PLAYER: + Id:TEMPLATE_EDITABLE_PLAYER X:5 Y:0 Width:475 @@ -99,14 +99,25 @@ Background@SERVER_LOBBY: Height:25 X:390 Y:0 - Checkbox@STATUS: - Id:STATUS + Checkbox@STATUS_CHECKBOX: + Id:STATUS_CHECKBOX X:448 Y:2 Width:20 Height:20 - Container@TEMPLATE_REMOTE: - Id:TEMPLATE_REMOTE + Visible:false + Image@STATUS_IMAGE: + Id:STATUS_IMAGE + Visible:false + X:450 + Y:4 + Width:20 + Height:20 + ImageCollection:checkbox-bits + ImageName:checked + Visible:false + Container@TEMPLATE_NONEDITABLE_PLAYER: + Id:TEMPLATE_NONEDITABLE_PLAYER X:5 Y:0 Width:475 @@ -162,12 +173,16 @@ Background@SERVER_LOBBY: Align:Center X:390 Y:0 - Checkbox@STATUS: - Id:STATUS - X:448 - Y:2 + Image@STATUS_IMAGE: + Id:STATUS_IMAGE + Visible:false + X:450 + Y:4 Width:20 Height:20 + ImageCollection:checkbox-bits + ImageName:checked + Container@TEMPLATE_EMPTY: Id:TEMPLATE_EMPTY X:5 @@ -183,28 +198,14 @@ Background@SERVER_LOBBY: Height:25 X:5 Y:0-1 - Button@JOIN: - Id:JOIN - Text:Play in this slot - Width:278 - Height:25 - X:160 - Y:0 - Container@TEMPLATE_EMPTY_HOST: - Id:TEMPLATE_EMPTY_HOST - X:5 - Y:0 - Width:400 - Height:25 - Visible:false - Children: - DropDownButton@NAME: - Id:NAME + DropDownButton@NAME_HOST: + Id:NAME_HOST Text:Name Width:150 Height:25 X:0 Y:0 + Visible:false Button@JOIN: Id:JOIN Text:Play in this slot @@ -212,8 +213,8 @@ Background@SERVER_LOBBY: Height:25 X:160 Y:0 - Container@TEMPLATE_LOCAL_SPECTATOR: - Id:TEMPLATE_LOCAL_SPECTATOR + Container@TEMPLATE_EDITABLE_SPECTATOR: + Id:TEMPLATE_EDITABLE_SPECTATOR X:5 Y:0 Width:475 @@ -247,14 +248,24 @@ Background@SERVER_LOBBY: Y:0 Align:Center Font:Bold - Checkbox@STATUS: - Id:STATUS + Checkbox@STATUS_CHECKBOX: + Id:STATUS_CHECKBOX X:448 Y:2 Width:20 Height:20 - Container@TEMPLATE_REMOTE_SPECTATOR: - Id:TEMPLATE_REMOTE_SPECTATOR + Image@STATUS_IMAGE: + Id:STATUS_IMAGE + Visible:false + X:450 + Y:4 + Width:20 + Height:20 + ImageCollection:checkbox-bits + ImageName:checked + + Container@TEMPLATE_NONEDITABLE_SPECTATOR: + Id:TEMPLATE_NONEDITABLE_SPECTATOR X:5 Y:0 Width:475 @@ -290,12 +301,15 @@ Background@SERVER_LOBBY: Y:0 Align:Center Font:Bold - Checkbox@STATUS: - Id:STATUS - X:448 - Y:2 + Image@STATUS_IMAGE: + Id:STATUS_IMAGE + Visible:false + X:450 + Y:4 Width:20 Height:20 + ImageCollection:checkbox-bits + ImageName:checked Container@TEMPLATE_NEW_SPECTATOR: Id:TEMPLATE_NEW_SPECTATOR X:5 @@ -369,13 +383,40 @@ Background@SERVER_LOBBY: Height:25 Text:Change Map Font:Bold - ChatDisplay@CHAT_DISPLAY: + ScrollPanel@CHAT_DISPLAY: Id:CHAT_DISPLAY X:20 - Notification: rabeep1.aud - Height:230 Y:PARENT_BOTTOM - 289 Width:PARENT_RIGHT - 200 + Height:230 + ItemSpacing:1 + Children: + Container@CHAT_TEMPLATE: + Id:CHAT_TEMPLATE + Width:PARENT_RIGHT-27 + Height:16 + X:2 + Y:0 + Children: + Label@TIME: + Id:TIME + X:3 + Width:50 + Height:15 + VAlign:Top + Label@NAME: + Id:NAME + X:45 + Width:50 + Height:15 + VAlign:Top + Label@TEXT: + Id:TEXT + X:55 + Width:PARENT_RIGHT - 60 + Height:15 + WordWrap:true + VAlign:Top Label@LABEL_CHATTYPE: Id:LABEL_CHATTYPE Width:65 diff --git a/mods/ra/chrome/mainmenu.yaml b/mods/ra/chrome/mainmenu.yaml index 6880a379cb..ce92afadc8 100644 --- a/mods/ra/chrome/mainmenu.yaml +++ b/mods/ra/chrome/mainmenu.yaml @@ -3,7 +3,7 @@ Background@MAINMENU_BG: X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - HEIGHT)/2 Width:250 - Height:330 + Height:420 Visible:true Logic:MainMenuButtonsLogic Children: @@ -32,18 +32,34 @@ Background@MAINMENU_BG: Height:25 Text:Create Game Font:Bold - Button@MAINMENU_BUTTON_SETTINGS: - Id:MAINMENU_BUTTON_SETTINGS + Button@MAINMENU_BUTTON_DIRECTCONNECT: + Id:MAINMENU_BUTTON_DIRECTCONNECT X:45 Y:150 Width:160 Height:25 + Text:Direct Connect + Font:Bold + Button@MAINMENU_BUTTON_SETTINGS: + Id:MAINMENU_BUTTON_SETTINGS + X:45 + Y:190 + Width:160 + Height:25 Text:Settings Font:Bold + Button@MAINMENU_BUTTON_MODS: + Id:MAINMENU_BUTTON_MODS + X:45 + Y:230 + Width:160 + Height:25 + Text:Mods + Font:Bold Button@MAINMENU_BUTTON_MUSIC: Id:MAINMENU_BUTTON_MUSIC X:45 - Y:190 + Y:270 Width:160 Height:25 Text:Music @@ -51,7 +67,7 @@ Background@MAINMENU_BG: Button@MAINMENU_BUTTON_REPLAY_VIEWER: Id:MAINMENU_BUTTON_REPLAY_VIEWER X:45 - Y:230 + Y:310 Width:160 Height:25 Text:Replay Viewer @@ -59,42 +75,11 @@ Background@MAINMENU_BG: Button@MAINMENU_BUTTON_QUIT: Id:MAINMENU_BUTTON_QUIT X:45 - Y:270 + Y:350 Width:160 Height:25 Text:Quit Font:Bold -Background@QUICKMODSWITCHER: - Id:QUICKMODSWITCHER - Background: dialog4 - X:(WINDOW_RIGHT - PARENT_LEFT - WIDTH - 10) - Y:10 - PARENT_TOP - Width:205 - Height:65 - Children: - Label@TITLE: - X:8 - Y:3 - Width:PARENT_RIGHT - Height:25 - Text:Mod: - Align:Left - Font:Bold - DropDownButton@SWITCHER: - Id:SWITCHER - Text:Team - Width:150 - Height:25 - X:50 - Y:5 - Label@VERSION: - Id:VERSION - X:50 - Y:30 - Width:150 - Height:25 - Align:Center - Font:Bold Background@PERF_BG: ClickThrough:true Id:PERF_BG diff --git a/mods/ra/chrome/modchooser.yaml b/mods/ra/chrome/modchooser.yaml new file mode 100644 index 0000000000..fbf43a168c --- /dev/null +++ b/mods/ra/chrome/modchooser.yaml @@ -0,0 +1,92 @@ +Background@MODS_PANEL: + Logic:ModBrowserLogic + Id:MODS_PANEL + Width:740 + Height:500 + X:(WINDOW_RIGHT - WIDTH)/2 + Y:(WINDOW_BOTTOM - HEIGHT)/2 + Children: + Label@TITLE: + Text:Select Mod + Width:PARENT_RIGHT + Y:20 + Font:Bold + Align:Center + ScrollPanel@MOD_LIST: + Id:MOD_LIST + X:15 + Y:70 + Width:710 + Height:PARENT_BOTTOM - 125 + Children: + ScrollItem@MOD_TEMPLATE: + Id:MOD_TEMPLATE + Width:PARENT_RIGHT-27 + Height:25 + X:2 + Y:0 + Visible:false + Children: + Label@TITLE: + X:10 + Id:TITLE + Width:200 + Height:25 + Label@AUTHOR: + Id:AUTHOR + X:PARENT_RIGHT-300 + Align:Center + Width:50 + Height:25 + Label@VERSION: + Id:VERSION + Width:140 + X:PARENT_RIGHT-150 + Align:Center + Height:25 + Container@MOD_LABELS: + Width:710-25 + Height:25 + X:15 + Y:45 + Children: + Label@TITLE: + Width:125 + Height:25 + X:0 + Y:0 + Text:Title + Align:Center + Font:Bold + Label@AUTHOR: + X:PARENT_RIGHT-300 + Align:Center + Width:50 + Height:25 + Text:Author + Font:Bold + Label@VERSION: + Width:140 + X:PARENT_RIGHT-150 + Align:Center + Height:25 + Text:Version + Font:Bold + Button@BACK_BUTTON: + Id:BACK_BUTTON + Key:escape + X:PARENT_RIGHT-180 + Y:PARENT_BOTTOM-45 + Width:160 + Height:25 + Font:Bold + Text:Cancel + Button@LOAD_BUTTON: + Id:LOAD_BUTTON + Key:return + X:PARENT_RIGHT-360 + Y:PARENT_BOTTOM-45 + Width:160 + Height:25 + Font:Bold + Text:Load Mod diff --git a/mods/ra/chrome/replaybrowser.yaml b/mods/ra/chrome/replaybrowser.yaml index 30bb6463a7..7565e76780 100644 --- a/mods/ra/chrome/replaybrowser.yaml +++ b/mods/ra/chrome/replaybrowser.yaml @@ -81,6 +81,22 @@ Background@REPLAYBROWSER_BG: Align:Left Width:70 Height:20 + Label@PLAYERS_LABEL: + Id:PLAYERS_LABEL + X:PARENT_RIGHT - 200 - WIDTH + Y:290 + Align:Right + Width:70 + Height:20 + Text:Players: + Font:Bold + Label@PLAYERS: + Id:PLAYERS + X:PARENT_RIGHT - 195 + Y:290 + Align:Left + Width:70 + Height:20 Button@WATCH_BUTTON: Id:WATCH_BUTTON X:PARENT_RIGHT - 140 - 130 diff --git a/mods/ra/chrome/serverbrowser.yaml b/mods/ra/chrome/serverbrowser.yaml index a4a73e7acd..956272473f 100644 --- a/mods/ra/chrome/serverbrowser.yaml +++ b/mods/ra/chrome/serverbrowser.yaml @@ -34,8 +34,19 @@ Background@JOINSERVER_BG: Id:TITLE Width:200 Height:25 - Label@JOINSERVER_PROGRESS_TITLE: - Id:JOINSERVER_PROGRESS_TITLE + Label@MAP: + Id:MAP + X:210 + Width:100 + Height:25 + Label@PLAYERS: + Id:PLAYERS + Visible:False + Label@IP: + Id:IP + Visible:False + Label@PROGRESS_LABEL: + Id:PROGRESS_LABEL X:150 Y:PARENT_BOTTOM / 2 - HEIGHT Width:150 @@ -121,17 +132,9 @@ Background@JOINSERVER_BG: VAlign:Top Width:70 Height:20 - Button@DIRECTCONNECT_BUTTON: - Id:DIRECTCONNECT_BUTTON - X:20 - Y:PARENT_BOTTOM - 45 - Width:120 - Height:25 - Text:Direct Connect - Font:Bold Button@REFRESH_BUTTON: Id:REFRESH_BUTTON - X:160 + X:20 Y:PARENT_BOTTOM - 45 Width:120 Height:25 @@ -146,8 +149,8 @@ Background@JOINSERVER_BG: Text:Join Font:Bold Key:return - Button@CANCEL_BUTTON: - Id:CANCEL_BUTTON + Button@BACK_BUTTON: + Id:BACK_BUTTON X:PARENT_RIGHT - 140 Y:PARENT_BOTTOM - 45 Width:120 @@ -180,13 +183,20 @@ Background@DIRECTCONNECT_BG: Height:25 Align:Right Text:Server Address: - TextField@SERVER_ADDRESS: - Id:SERVER_ADDRESS + TextField@IP: + Id:IP X:150 Y:60 - Width:200 + Width:160 MaxLength:50 Height:25 + TextField@PORT: + Id:PORT + X:315 + Y:60 + Width:55 + MaxLength:5 + Height:25 Button@JOIN_BUTTON: Id:JOIN_BUTTON X:130 @@ -196,8 +206,8 @@ Background@DIRECTCONNECT_BG: Text:Join Font:Bold Key:return - Button@CANCEL_BUTTON: - Id:CANCEL_BUTTON + Button@BACK_BUTTON: + Id:BACK_BUTTON X:260 Y:PARENT_BOTTOM - 45 Width:120 @@ -205,8 +215,8 @@ Background@DIRECTCONNECT_BG: Text:Cancel Font:Bold Key:escape -Background@CONNECTION_FAILED_BG: - Id:CONNECTION_FAILED_BG +Background@CONNECTIONFAILED_PANEL: + Id:CONNECTIONFAILED_PANEL Logic:ConnectionFailedLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - HEIGHT)/2 @@ -222,16 +232,16 @@ Background@CONNECTION_FAILED_BG: Text:Connection Failed Align:Center Font:Bold - Label@CONNECTION_FAILED_DESC: - Id:CONNECTION_FAILED_DESC + Label@CONNECTING_DESC: + Id:CONNECTING_DESC X:0 Y:60 Width:PARENT_RIGHT Height:25 Text:Could not connect to AAA.BBB.CCC.DDD:EEEE Align:Center - Button@CONNECTION_BUTTON_RETRY: - Id:CONNECTION_BUTTON_RETRY + Button@RETRY_BUTTON: + Id:RETRY_BUTTON X:PARENT_RIGHT - 360 Y:PARENT_BOTTOM - 45 Width:160 @@ -239,8 +249,8 @@ Background@CONNECTION_FAILED_BG: Text:Retry Font:Bold Key:return - Button@CONNECTION_BUTTON_CANCEL: - Id:CONNECTION_BUTTON_CANCEL + Button@ABORT_BUTTON: + Id:ABORT_BUTTON X:PARENT_RIGHT - 180 Y:PARENT_BOTTOM - 45 Width:160 @@ -248,9 +258,9 @@ Background@CONNECTION_FAILED_BG: Text:Cancel Font:Bold Key:escape -Background@CONNECTING_BG: - Id:CONNECTING_BG - Logic:ConnectionDialogsLogic +Background@CONNECTING_PANEL: + Id:CONNECTING_PANEL + Logic:ConnectionLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM - HEIGHT)/2 Width:450 @@ -273,8 +283,8 @@ Background@CONNECTING_BG: Height:25 Text:Connecting to AAA.BBB.CCC.DDD:EEEE... Align:Center - Button@CONNECTION_BUTTON_ABORT: - Id:CONNECTION_BUTTON_ABORT + Button@ABORT_BUTTON: + Id:ABORT_BUTTON X:PARENT_RIGHT - 180 Y:PARENT_BOTTOM - 45 Width:160 diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 3e7725ea7b..cb6e3e4de5 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -62,6 +62,7 @@ ChromeLayout: mods/ra/chrome/serverbrowser.yaml mods/ra/chrome/replaybrowser.yaml mods/ra/chrome/dropdowns.yaml + mods/ra/chrome/modchooser.yaml Weapons: mods/ra/weapons.yaml