diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 7f2560bcc4adc2f398d87aa8066119ee9ec3b455..3adfe4656f8516b1ee973e9b2eca43dafa0a9b0c 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -110,6 +110,8 @@ static patch_t *nopingicon;
 // crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see m_menu.c
 static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics
 
+static consvar_t cv_showprivatemessages = CVAR_INIT ("hu_showprivatemessages", "Off", CV_SAVE, CV_OnOff, NULL);
+
 // -------
 // protos.
 // -------
@@ -296,6 +298,7 @@ void HU_Init(void)
 	COM_AddCommand("sayto", Command_Sayto_f, COM_LUA);
 	COM_AddCommand("sayteam", Command_Sayteam_f, COM_LUA);
 	COM_AddCommand("csay", Command_CSay_f, COM_LUA);
+	CV_RegisterVar(&cv_showprivatemessages);
 	RegisterNetXCmd(XD_SAY, Got_Saycmd);
 
 	// set shift translation table
@@ -734,9 +737,10 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 	if (playernum == consoleplayer // By you
 	|| (target == -1 && ST_SameTeam(&players[consoleplayer], &players[playernum])) // To your team
 	|| target == 0 // To everyone
-	|| consoleplayer == target-1) // To you
+	|| consoleplayer == target-1 // To you
+	|| (cv_showprivatemessages.value && server)) // Via the server (if enabled)
 	{
-		const char *prefix = "", *cstart = "", *cend = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80";
+		const char *prefix = "", *cstart = "", *adminchar = "\x82~\x83", *remotechar = "\x82@\x83", *fmt2, *textcolor = "\x80";
 		char *tempchar = NULL;
 
 		// player is a spectator?
@@ -793,25 +797,35 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 		// name, color end, and the message itself.
 		// '\4' makes the message yellow and beeps; '\3' just beeps.
 		if (action)
-			fmt2 = "* %s%s%s%s \x82%s%s";
+			fmt2 = "* %s%s%s %s%s";
 		else if (target-1 == consoleplayer) // To you
 		{
 			prefix = "\x82[PM]";
 			cstart = "\x82";
 			textcolor = "\x82";
-			fmt2 = "%s<%s%s>%s\x80 %s%s";
+			fmt2 = "%s<%s%s> %s%s";
 		}
 		else if (target > 0) // By you, to another player
 		{
-			// Use target's name.
-			dispname = player_names[target-1];
-			prefix = "\x82[TO]";
-			cstart = "\x82";
-			fmt2 = "%s<%s%s>%s\x80 %s%s";
-
+			if (cv_showprivatemessages.value && server)
+			{
+				// we have to do our own formatting here since this one uses different parameters.
+				HU_AddChatText(va("\x82[TO %s]<%s> %s", player_names[target-1], player_names[playernum], msg), cv_chatnotifications.value); // add to chat
+				if (tempchar)
+					Z_Free(tempchar);
+				return;
+			}
+			else
+			{
+				// Use target's name.
+				dispname = player_names[target-1];
+				prefix = "\x82[TO]";
+				cstart = "\x82";
+				fmt2 = "%s<%s%s> %s%s";
+			}
 		}
 		else if (target == 0) // To everyone
-			fmt2 = "%s<%s%s%s>\x80 %s%s";
+			fmt2 = "%s<%s%s> %s%s";
 		else // To your team
 		{
 			if (players[playernum].ctfteam == 1) // red
@@ -821,10 +835,10 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 			else
 				prefix = "\x83"; // makes sure this doesn't implode if you sayteam on non-team gamemodes
 
-			fmt2 = "%s<%s%s>\x80%s %s%s";
+			fmt2 = "%s<%s%s> %s%s";
 		}
 
-		HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), cv_chatnotifications.value); // add to chat
+		HU_AddChatText(va(fmt2, prefix, cstart, dispname, textcolor, msg), cv_chatnotifications.value); // add to chat
 
 		if (tempchar)
 			Z_Free(tempchar);