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; }