From 2e9336eb91bff075266ff5639c95e47bcc6da245 Mon Sep 17 00:00:00 2001
From: Spoike <acceptthis@users.sourceforge.net>
Date: Sat, 21 Aug 2010 22:12:43 +0000
Subject: [PATCH] Don't let spammed centerprints/h2plaques result in
 disconnections.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3598 fc73d0e0-1445-4013-8a0c-d673dee63da5
---
 engine/server/pr_cmds.c | 49 ++++++++++++-----------------------------
 engine/server/server.h  |  1 +
 engine/server/sv_main.c |  8 +++++--
 engine/server/sv_send.c | 41 +++++++++++++++++++++++++++++++++-
 4 files changed, 61 insertions(+), 38 deletions(-)

diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c
index d5a7b9ffc..6155c144a 100644
--- a/engine/server/pr_cmds.c
+++ b/engine/server/pr_cmds.c
@@ -2272,46 +2272,23 @@ void PF_centerprint_Internal (int entnum, qboolean plaque, char *s)
 		return;
 	}
 
-	if (!*s)
-		plaque = false;
-
 	cl = &svs.clients[entnum-1];
+	if (cl->centerprintstring)
+		Z_Free(cl->centerprintstring);
+	cl->centerprintstring = NULL;
+
 	slen = strlen(s);
-	if (plaque)
-		slen += 2;
-
-	if (cl->controller)
-	{	//this is a slave client.
-		//find the right number and send.
-		int pnum = 0;
-		for (sp = cl->controller; sp; sp = sp->controlled)
-		{
-			if (sp == cl)
-				break;
-			pnum++;
-		}
-		cl = cl->controller;
-
-		ClientReliableWrite_Begin (cl, svcfte_choosesplitclient, 4 + slen);
-		ClientReliableWrite_Byte (cl, pnum);
-		ClientReliableWrite_Byte (cl, svc_centerprint);
+	if (plaque && *s)
+	{
+		cl->centerprintstring = Z_Malloc(slen+3);
+		cl->centerprintstring[0] = '/';
+		cl->centerprintstring[1] = 'P';
+		strcpy(cl->centerprintstring+2, s);
 	}
 	else
 	{
-		ClientReliableWrite_Begin (cl, svc_centerprint, 2 + slen);
-	}
-	if (plaque)
-	{
-		ClientReliableWrite_Char (cl, '/');
-		ClientReliableWrite_Char (cl, 'P');
-	}
-	ClientReliableWrite_String (cl, s);
-
-	if (sv.mvdrecording)
-	{
-		MVDWrite_Begin (dem_single, entnum - 1, 2 + slen);
-		MSG_WriteByte ((sizebuf_t*)demo.dbuf, svc_centerprint);
-		MSG_WriteString ((sizebuf_t*)demo.dbuf, s);
+		cl->centerprintstring = Z_Malloc(slen+1);
+		strcpy(cl->centerprintstring, s);
 	}
 }
 
@@ -7043,7 +7020,9 @@ void PF_h2plaque_draw(progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	if (G_FLOAT(OFS_PARM1) == 0)
 		s = "";
 	else
+	{
 		s = T_GetString(G_FLOAT(OFS_PARM1)-1);
+	}
 
 	if (G_FLOAT(OFS_PARM0) == MSG_ONE)
 	{
diff --git a/engine/server/server.h b/engine/server/server.h
index d45fe001e..cbc67d1a5 100644
--- a/engine/server/server.h
+++ b/engine/server/server.h
@@ -417,6 +417,7 @@ typedef struct client_s
 	int				statsi[MAX_CL_STATS];
 	float			statsf[MAX_CL_STATS];
 	char			*statss[MAX_CL_STATS];
+	char			*centerprintstring;
 
 	union{	//save space
 		client_frame_t	*frames;	// updates can be deltad from here
diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c
index 4749c8a6d..ab1351033 100644
--- a/engine/server/sv_main.c
+++ b/engine/server/sv_main.c
@@ -521,6 +521,10 @@ void SV_DropClient (client_t *drop)
 		break;
 	}
 
+	if (drop->centerprintstring)
+		Z_Free(drop->centerprintstring);
+	drop->centerprintstring = NULL;
+
 	if (drop->spectator)
 		Con_Printf ("Spectator %s removed\n",drop->name);
 	else
@@ -3382,7 +3386,7 @@ void SV_Frame (void)
 		if (sv.time < oldtime)
 			sv.time = oldtime;	//urm
 
-		if (sv.paused)
+		if (sv.paused && sv.time > 1.5)
 		{
 			sv.starttime += sv.time - oldtime;	//move the offset
 			sv.time = oldtime;	//and keep time as it was.
@@ -3453,7 +3457,7 @@ void SV_MVDStream_Poll(void);
 	}
 
 	// move autonomous things around if enough time has passed
-	if (!sv.paused)
+	if (!sv.paused || sv.time < 1.5)
 	{
 #ifdef Q2SERVER
 		//q2 is idle even if clients sent packets.
diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c
index 8666e613b..c14400522 100644
--- a/engine/server/sv_send.c
+++ b/engine/server/sv_send.c
@@ -1034,6 +1034,40 @@ void SV_WriteEntityDataToMessage (client_t *client, sizebuf_t *msg, int pnum)
 	}
 }
 
+/*sends the a centerprint string directly to the client*/
+void SV_WriteCenterPrint(client_t *cl, char *s)
+{
+	if (cl->controller)
+	{	//this is a slave client.
+		//find the right number and send.
+		int pnum = 0;
+		client_t *sp;
+		for (sp = cl->controller; sp; sp = sp->controlled)
+		{
+			if (sp == cl)
+				break;
+			pnum++;
+		}
+		cl = cl->controller;
+
+		ClientReliableWrite_Begin (cl, svcfte_choosesplitclient, 4 + strlen(s));
+		ClientReliableWrite_Byte (cl, pnum);
+		ClientReliableWrite_Byte (cl, svc_centerprint);
+	}
+	else
+	{
+		ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen(s));
+	}
+	ClientReliableWrite_String (cl, s);
+
+	if (sv.mvdrecording)
+	{
+		MVDWrite_Begin (dem_single, cl - svs.clients, 2 + strlen(s));
+		MSG_WriteByte ((sizebuf_t*)demo.dbuf, svc_centerprint);
+		MSG_WriteString ((sizebuf_t*)demo.dbuf, s);
+	}
+}
+
 /*
 ==================
 SV_WriteClientdataToMessage
@@ -1050,7 +1084,12 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
 	client_t *split;
 	int pnum=0;
 
-
+	if (client->centerprintstring && ! client->num_backbuf)
+	{
+		SV_WriteCenterPrint(client, client->centerprintstring);
+		Z_Free(client->centerprintstring);
+		client->centerprintstring = NULL;
+	}
 
 	// send the chokecount for r_netgraph
 	if (ISQWCLIENT(client))