diff --git a/ClientCore/CnCNet5/NameValidator.cs b/ClientCore/CnCNet5/NameValidator.cs index c0dfa731f..9ac7a6177 100644 --- a/ClientCore/CnCNet5/NameValidator.cs +++ b/ClientCore/CnCNet5/NameValidator.cs @@ -60,8 +60,41 @@ public static string GetValidOfflineName(string name) if (validName.Length > ClientConfiguration.Instance.MaxNameLength) return validName.Substring(0, ClientConfiguration.Instance.MaxNameLength); - + return validName; } + + /// + /// Checks if a game name is valid for CnCNet. + /// + /// Game name. + /// Null if the game name is valid, otherwise a string that tells + /// what is wrong with the name. + public static string IsGameNameValid(string gameName) + { + + if (string.IsNullOrEmpty(gameName)) + { + return "Please enter a game name.".L10N("Client:ClientCore:GameNameMissing"); + } + + char[] disallowedCharacters = { ',', ';' }; + if (gameName.IndexOfAny(disallowedCharacters) != -1) + { + return "Game name contains disallowed characters.".L10N("Client:ClientCore:GameNameDisallowedChars"); + } + + if (gameName.Length > 23) + { + return "Game name is too long.".L10N("Client:ClientCore:GameNameTooLong"); + } + + if (new ProfanityFilter().IsOffensive(gameName)) + { + return "Please enter a less offensive game name.".L10N("Client:ClientCore:GameNameOffensiveText"); + } + + return null; + } } } diff --git a/DXMainClient/DXGUI/Multiplayer/CnCNet/GameCreationWindow.cs b/DXMainClient/DXGUI/Multiplayer/CnCNet/GameCreationWindow.cs index 1bcc189d3..154287337 100644 --- a/DXMainClient/DXGUI/Multiplayer/CnCNet/GameCreationWindow.cs +++ b/DXMainClient/DXGUI/Multiplayer/CnCNet/GameCreationWindow.cs @@ -8,6 +8,7 @@ using Rampastring.XNAUI.XNAControls; using System; using System.IO; +using ClientCore.CnCNet5; namespace DTAClient.DXGUI.Multiplayer.CnCNet { @@ -239,17 +240,14 @@ private void BtnLoadMPGame_LeftClick(object sender, EventArgs e) private void BtnCreateGame_LeftClick(object sender, EventArgs e) { - string gameName = tbGameName.Text.Replace(";", string.Empty); - if (string.IsNullOrEmpty(gameName)) - { - return; - } + var gameName = tbGameName.Text; + var gameNameValid = NameValidator.IsGameNameValid(gameName); - if (new ProfanityFilter().IsOffensive(gameName)) + if (!string.IsNullOrEmpty(gameNameValid)) { - XNAMessageBox.Show(WindowManager, "Offensive game name".L10N("Client:Main:GameNameOffensiveTitle"), - "Please enter a less offensive game name.".L10N("Client:Main:GameNameOffensiveText")); + XNAMessageBox.Show(WindowManager, "Invalid game name".L10N("Client:Main:GameNameInvalid"), + gameNameValid); return; } @@ -259,7 +257,7 @@ private void BtnCreateGame_LeftClick(object sender, EventArgs e) } GameCreated?.Invoke(this, - new GameCreationEventArgs(gameName,int.Parse(ddMaxPlayers.SelectedItem.Text), + new GameCreationEventArgs(gameName, int.Parse(ddMaxPlayers.SelectedItem.Text), tbPassword.Text,tunnelHandler.Tunnels[lbTunnelList.SelectedIndex], ddSkillLevel.SelectedIndex) ); diff --git a/DXMainClient/DXGUI/Multiplayer/GameLobby/CnCNetGameLobby.cs b/DXMainClient/DXGUI/Multiplayer/GameLobby/CnCNetGameLobby.cs index 892fde5b1..78810a3c2 100644 --- a/DXMainClient/DXGUI/Multiplayer/GameLobby/CnCNetGameLobby.cs +++ b/DXMainClient/DXGUI/Multiplayer/GameLobby/CnCNetGameLobby.cs @@ -37,6 +37,7 @@ public class CnCNetGameLobby : MultiplayerGameLobby private const string MAP_SHARING_DOWNLOAD_REQUEST = "MAPOK"; private const string MAP_SHARING_UPLOAD_REQUEST = "MAPREQ"; private const string MAP_SHARING_DISABLED_MESSAGE = "MAPSDISABLED"; + private const string GAME_NAME_CHANGED = "GNC"; private const string CHEAT_DETECTED_MESSAGE = "CD"; private const string DICE_ROLL_MESSAGE = "DR"; private const string CHANGE_TUNNEL_SERVER_MESSAGE = "CHTNL"; @@ -87,6 +88,7 @@ PrivateMessagingWindow pmWindow new StringCommandHandler("MM", CheaterNotification), new StringCommandHandler(DICE_ROLL_MESSAGE, HandleDiceRollResult), new NoParamCommandHandler(CHEAT_DETECTED_MESSAGE, HandleCheatDetectedMessage), + new StringCommandHandler(GAME_NAME_CHANGED, HandleGameNameChangeMessage), new StringCommandHandler(CHANGE_TUNNEL_SERVER_MESSAGE, HandleTunnelServerChangeMessage) }; @@ -97,6 +99,8 @@ PrivateMessagingWindow pmWindow AddChatBoxCommand(new ChatBoxCommand("TUNNELINFO", "View tunnel server information".L10N("Client:Main:TunnelInfoCommand"), false, PrintTunnelServerInformation)); + AddChatBoxCommand(new ChatBoxCommand("GAMENAME", + "Change a game's name (game host only).\nExample: \"/gamename 2v2 3v3\"".L10N("Client:Main:ChangeGameNameCommand"), true, s => ChangeGameName(s))); AddChatBoxCommand(new ChatBoxCommand("CHANGETUNNEL", "Change the used CnCNet tunnel server (game host only)".L10N("Client:Main:ChangeTunnelCommand"), true, (s) => ShowTunnelSelectionWindow("Select tunnel server:".L10N("Client:Main:SelectTunnelServerCommand")))); @@ -1561,6 +1565,12 @@ protected override void BanPlayer(int playerIndex) private void HandleCheatDetectedMessage(string sender) => AddNotice(string.Format("{0} has modified game files during the client session. They are likely attempting to cheat!".L10N("Client:Main:PlayerModifyFileCheat"), sender), Color.Red); + private void HandleGameNameChangeMessage(string sender, string newGameName) + { + AddNotice(String.Format("The game host has changed the game name to {0}".L10N("Client:Main:HostGameNameChanged"), newGameName)); + channel.UIName = newGameName; + } + private void HandleTunnelServerChangeMessage(string sender, string tunnelAddressAndPort) { if (sender != hostName) @@ -1882,6 +1892,30 @@ private void DownloadMapByIdCommand(string parameters) #region Game broadcasting logic + /// + /// Handles changing the UIName + /// + /// The new name for the hosted game. + private void ChangeGameName(string gameName) + { + var gameNameValid = NameValidator.IsGameNameValid(gameName); + + if (!string.IsNullOrEmpty(gameNameValid)) + { + XNAMessageBox.Show(WindowManager, "Invalid game name".L10N("Client:Main:GameNameInvalid"), + gameNameValid); + return; + } + + //update the name and broadcast to everyone + channel.UIName = gameName; + AccelerateGameBroadcasting(); + + //inform the players in the room + channel.SendCTCPMessage(GAME_NAME_CHANGED + " " + gameName, QueuedMessageType.SYSTEM_MESSAGE, priority: 9); + AddNotice(String.Format("Game name changed to {0}.".L10N("Client:Main:GameNameChanged"), gameName)); + } + /// /// Lowers the time until the next game broadcasting message. /// diff --git a/DXMainClient/Online/Channel.cs b/DXMainClient/Online/Channel.cs index 88b304f4f..1c08c02ab 100644 --- a/DXMainClient/Online/Channel.cs +++ b/DXMainClient/Online/Channel.cs @@ -63,7 +63,7 @@ public Channel(string uiName, string channelName, bool persistent, bool isChatCh #region Public members - public string UIName { get; } + public string UIName { get; set; } public string ChannelName { get; }