diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c
index 4860d8688b4a8b998b59523c6cf52502c69d10ca..8cfee4b8113790d70588dd05a1de556f20d23d9f 100644
--- a/src/netcode/d_net.c
+++ b/src/netcode/d_net.c
@@ -515,43 +515,6 @@ void Net_AckTicker(void)
 	}
 }
 
-// Remove last packet received ack before resending the ackreturn
-// (the higher layer doesn't have room, or something else ....)
-void Net_UnAcknowledgePacket(INT32 node)
-{
-	INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND;
-	DEBFILE(va("UnAcknowledge node %d\n", node));
-	if (!node)
-		return;
-	if (nodes[node].acktosend[hm1] == netbuffer->ack)
-	{
-		nodes[node].acktosend[hm1] = 0;
-		nodes[node].acktosend_head = (UINT8)hm1;
-	}
-	else if (nodes[node].firstacktosend == netbuffer->ack)
-	{
-		nodes[node].firstacktosend--;
-		if (!nodes[node].firstacktosend)
-			nodes[node].firstacktosend = UINT8_MAX;
-	}
-	else
-	{
-		while (nodes[node].firstacktosend != netbuffer->ack)
-		{
-			nodes[node].acktosend_tail = (UINT8)
-				((nodes[node].acktosend_tail-1+MAXACKTOSEND) % MAXACKTOSEND);
-			nodes[node].acktosend[nodes[node].acktosend_tail] = nodes[node].firstacktosend;
-
-			nodes[node].firstacktosend--;
-			if (!nodes[node].firstacktosend)
-				nodes[node].firstacktosend = UINT8_MAX;
-		}
-		nodes[node].firstacktosend++;
-		if (!nodes[node].firstacktosend)
-			nodes[node].firstacktosend = 1;
-	}
-}
-
 /** Checks if all acks have been received
   *
   * \return True if all acks have been received
diff --git a/src/netcode/d_net.h b/src/netcode/d_net.h
index 2f83939f8c5324883eb11e90dbb4e2897a54254c..ccaede648189db26ed7e9ce9738ec436ac6dda2e 100644
--- a/src/netcode/d_net.h
+++ b/src/netcode/d_net.h
@@ -71,7 +71,6 @@ void D_SetDoomcom(void);
 boolean D_CheckNetGame(void);
 void D_CloseConnection(void);
 boolean Net_IsNodeIPv6(INT32 node);
-void Net_UnAcknowledgePacket(INT32 node);
 void Net_CloseConnection(INT32 node);
 void Net_ConnectionTimeout(INT32 node);
 void Net_AbortPacketType(UINT8 packettype);
diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c
index 8376f26b9b4e853197f7d4fe393e7fb52cf322fd..b6f11693acd03b2137887086ec99d2538997d420 100644
--- a/src/netcode/d_netcmd.c
+++ b/src/netcode/d_netcmd.c
@@ -130,6 +130,7 @@ static void Command_ListWADS_f(void);
 static void Command_RunSOC(void);
 static void Command_Pause(void);
 static void Command_Suicide(void);
+static void Command_Chatbug(void);
 
 static void Command_Version_f(void);
 #ifdef UPDATE_ALERT
@@ -513,6 +514,7 @@ void D_RegisterServerCommands(void)
 	COM_AddCommand("runsoc", Command_RunSOC, COM_LUA);
 	COM_AddCommand("pause", Command_Pause, COM_LUA);
 	COM_AddCommand("suicide", Command_Suicide, COM_LUA);
+	COM_AddCommand("chatbug", Command_Chatbug, 0);
 
 	COM_AddCommand("gametype", Command_ShowGametype_f, COM_LUA);
 	COM_AddCommand("version", Command_Version_f, COM_LUA);
@@ -2224,6 +2226,20 @@ static void Command_Suicide(void)
 	SendNetXCmd(XD_SUICIDE, &buf, 4);
 }
 
+// TODO: remove after enough testing is done
+static void Command_Chatbug(void)
+{
+	// Hammer 2 TEXTCMD packets at the same time
+	// Shouldn't normally be possible but can happen if clock rate between server and client differs
+	netbuffer->packettype = PT_TEXTCMD;
+	netbuffer->u.textcmd[0] = 0;
+	HSendPacket(servernode, true, 0, 1);
+
+	netbuffer->packettype = PT_TEXTCMD;
+	netbuffer->u.textcmd[0] = 0;
+	HSendPacket(servernode, true, 0, 1);
+}
+
 static void Got_Suicide(UINT8 **cp, INT32 playernum)
 {
 	INT32 suicideplayer = READINT32(*cp);
diff --git a/src/netcode/net_command.c b/src/netcode/net_command.c
index 2b3abfd0238a3246fedc086afc007a85c993b425..48beef156a8f3556ae05de3b75d1629e4a194f47 100644
--- a/src/netcode/net_command.c
+++ b/src/netcode/net_command.c
@@ -239,9 +239,7 @@ void PT_TextCmd(SINT8 node, INT32 netconsole)
 	if (netbuffer->packettype == PT_TEXTCMD2)
 		netconsole = netnodes[node].player2;
 
-	if (netconsole < 0 || netconsole >= MAXPLAYERS)
-		Net_UnAcknowledgePacket(node);
-	else
+	if (netconsole >= 0 && netconsole < MAXPLAYERS)
 	{
 		size_t j;
 		tic_t tic = maketic;
@@ -253,7 +251,6 @@ void PT_TextCmd(SINT8 node, INT32 netconsole)
 		{
 			DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n",
 				node, netconsole));
-			Net_UnAcknowledgePacket(node);
 			return;
 		}
 
@@ -264,7 +261,6 @@ void PT_TextCmd(SINT8 node, INT32 netconsole)
 			DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n",
 			netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1),
 				node, netconsole));
-			Net_UnAcknowledgePacket(node);
 			return;
 		}
 
@@ -285,7 +281,6 @@ void PT_TextCmd(SINT8 node, INT32 netconsole)
 			DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, "
 				"tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)),
 				maketic, firstticstosend, node, netconsole));
-			Net_UnAcknowledgePacket(node);
 			return;
 		}