#region Copyright & License Information /* * Copyright 2007-2021 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, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using OpenRA.Network; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets.Logic { public class ConnectionLogic : ChromeLogic { Action onConnect, onAbort; Action onRetry; void ConnectionStateChanged(OrderManager om, string password, NetworkConnection connection) { if (om.Connection.ConnectionState == ConnectionState.Connected) { CloseWindow(); onConnect(); } else if (om.Connection.ConnectionState == ConnectionState.NotConnected) { CloseWindow(); var switchPanel = CurrentServerSettings.ServerExternalMod != null ? "CONNECTION_SWITCHMOD_PANEL" : "CONNECTIONFAILED_PANEL"; Ui.OpenWindow(switchPanel, new WidgetArgs() { { "orderManager", om }, { "connection", connection }, { "password", password }, { "onAbort", onAbort }, { "onRetry", onRetry } }); } } void CloseWindow() { Game.ConnectionStateChanged -= ConnectionStateChanged; Ui.CloseWindow(); } [ObjectCreator.UseCtor] public ConnectionLogic(Widget widget, ConnectionTarget endpoint, Action onConnect, Action onAbort, Action onRetry) { this.onConnect = onConnect; this.onAbort = onAbort; this.onRetry = onRetry; Game.ConnectionStateChanged += ConnectionStateChanged; var panel = widget; panel.Get("ABORT_BUTTON").OnClick = () => { CloseWindow(); onAbort(); }; widget.Get("CONNECTING_DESC").GetText = () => $"Connecting to {endpoint}..."; } public static void Connect(ConnectionTarget endpoint, string password, Action onConnect, Action onAbort) { Game.JoinServer(endpoint, password); Action onRetry = newPassword => Connect(endpoint, newPassword, onConnect, onAbort); Ui.OpenWindow("CONNECTING_PANEL", new WidgetArgs() { { "endpoint", endpoint }, { "onConnect", onConnect }, { "onAbort", onAbort }, { "onRetry", onRetry } }); } } public class ConnectionFailedLogic : ChromeLogic { PasswordFieldWidget passwordField; bool passwordOffsetAdjusted; [ObjectCreator.UseCtor] public ConnectionFailedLogic(Widget widget, OrderManager orderManager, NetworkConnection connection, string password, Action onAbort, Action onRetry) { var panel = widget; var abortButton = panel.Get("ABORT_BUTTON"); var retryButton = panel.Get("RETRY_BUTTON"); abortButton.Visible = onAbort != null; abortButton.OnClick = () => { Ui.CloseWindow(); onAbort(); }; retryButton.Visible = onRetry != null; retryButton.OnClick = () => { var pass = passwordField != null && passwordField.IsVisible() ? passwordField.Text : password; Ui.CloseWindow(); onRetry(pass); }; widget.Get("CONNECTING_DESC").GetText = () => $"Could not connect to {connection.Target}"; var connectionError = widget.Get("CONNECTION_ERROR"); connectionError.GetText = () => orderManager.ServerError ?? connection.ErrorMessage ?? "Unknown error"; var panelTitle = widget.Get("TITLE"); panelTitle.GetText = () => orderManager.AuthenticationFailed ? "Password Required" : "Connection Failed"; passwordField = panel.GetOrNull("PASSWORD"); if (passwordField != null) { passwordField.TakeKeyboardFocus(); passwordField.IsVisible = () => orderManager.AuthenticationFailed; var passwordLabel = widget.Get("PASSWORD_LABEL"); passwordLabel.IsVisible = passwordField.IsVisible; passwordField.OnEnterKey = _ => { retryButton.OnClick(); return true; }; passwordField.OnEscKey = _ => { abortButton.OnClick(); return true; }; } passwordOffsetAdjusted = false; var connectionFailedTicker = panel.GetOrNull("CONNECTION_FAILED_TICKER"); if (connectionFailedTicker != null) { connectionFailedTicker.OnTick = () => { // Adjust the dialog once the AuthenticationError is parsed. if (passwordField.IsVisible() && !passwordOffsetAdjusted) { var offset = passwordField.Bounds.Y - connectionError.Bounds.Y; abortButton.Bounds.Y += offset; retryButton.Bounds.Y += offset; panel.Bounds.Height += offset; panel.Bounds.Y -= offset / 2; var background = panel.GetOrNull("CONNECTION_BACKGROUND"); if (background != null) background.Bounds.Height += offset; passwordOffsetAdjusted = true; } }; } } } public class ConnectionSwitchModLogic : ChromeLogic { [ObjectCreator.UseCtor] public ConnectionSwitchModLogic(Widget widget, OrderManager orderManager, string password, NetworkConnection connection, Action onAbort, Action onRetry) { var panel = widget; var abortButton = panel.Get("ABORT_BUTTON"); var switchButton = panel.Get("SWITCH_BUTTON"); var mod = CurrentServerSettings.ServerExternalMod; var modTitle = mod.Title; var modVersion = mod.Version; switchButton.OnClick = () => { var launchCommand = $"Launch.URI={new UriBuilder("tcp", connection.EndPoint.Address.ToString(), connection.EndPoint.Port)}"; Game.SwitchToExternalMod(CurrentServerSettings.ServerExternalMod, new[] { launchCommand }, () => { orderManager.ServerError = "Failed to switch mod."; Ui.CloseWindow(); Ui.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() { { "orderManager", orderManager }, { "onAbort", onAbort }, { "onRetry", onRetry } }); }); }; abortButton.Visible = onAbort != null; abortButton.OnClick = () => { Ui.CloseWindow(); onAbort(); }; var width = 0; var title = panel.GetOrNull("MOD_TITLE"); if (title != null) { var font = Game.Renderer.Fonts[title.Font]; var label = WidgetUtils.TruncateText(modTitle, title.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, title.Bounds.X + labelWidth); title.Bounds.Width = labelWidth; title.GetText = () => label; } var version = panel.GetOrNull("MOD_VERSION"); if (version != null) { var font = Game.Renderer.Fonts[version.Font]; var label = WidgetUtils.TruncateText(modVersion, version.Bounds.Width, font); var labelWidth = font.Measure(label).X; width = Math.Max(width, version.Bounds.X + labelWidth); version.Bounds.Width = labelWidth; version.GetText = () => label; } var logo = panel.GetOrNull("MOD_ICON"); if (logo != null) { logo.GetSprite = () => { var ws = Game.Renderer.WindowScale; if (ws > 2 && mod.Icon3x != null) return mod.Icon3x; if (ws > 1 && mod.Icon2x != null) return mod.Icon2x; return mod.Icon; }; if (mod.Icon == null) { // Hide the logo and center just the text if (title != null) title.Bounds.X = logo.Bounds.X; if (version != null) version.Bounds.X = logo.Bounds.X; width -= logo.Bounds.Width; } else { // Add an equal logo margin on the right of the text width += logo.Bounds.Width; } } var container = panel.GetOrNull("MOD_CONTAINER"); if (container != null) { container.Bounds.X += (container.Bounds.Width - width) / 2; container.Bounds.Width = width; } } } }