From 48d4e97515ed16866661fe1e65efe4be3a13ee58 Mon Sep 17 00:00:00 2001
From: Spoike <acceptthis@users.sourceforge.net>
Date: Sat, 1 Aug 2020 06:33:05 +0000
Subject: [PATCH] Try to make the readcmd builtin more robust (by erroring out
 if some command destroyed the qcvm during execution). Stop forceinfokey from
 spamming when the new value is unchanged.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5739 fc73d0e0-1445-4013-8a0c-d673dee63da5
---
 engine/server/pr_cmds.c  | 13 +++++++++++++
 engine/server/sv_ccmds.c |  3 +--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c
index 325717c45..10634bf50 100644
--- a/engine/server/pr_cmds.c
+++ b/engine/server/pr_cmds.c
@@ -7202,6 +7202,7 @@ static void QCBUILTIN PF_readcmd (pubprogfuncs_t *prinst, struct globalvars_s *p
 	extern int sv_redirectedlang;
 	redirect_t old;
 	int oldl;
+	int spawncount = svs.spawncount;
 
 	s = PR_GetStringOfs(prinst, OFS_PARM0);
 
@@ -7219,6 +7220,9 @@ static void QCBUILTIN PF_readcmd (pubprogfuncs_t *prinst, struct globalvars_s *p
 	G_INT(OFS_RETURN) = (int)PR_TempString(prinst, sv_redirected_buf);
 	SV_EndRedirect();
 
+	if (svs.spawncount != spawncount || sv.state < ss_loading || prinst != sv.world.progs)
+		Host_EndGame("PF_readcmd: map changed during reading\n");
+
 	if (old != RD_NONE)
 		SV_BeginRedirect(old, oldl);
 }
@@ -9564,8 +9568,13 @@ static void QCBUILTIN PF_te_plasmaburn(pubprogfuncs_t *prinst, struct globalvars
 
 int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *value, size_t valsize)
 {
+	const char *oldval;
+	size_t oldsize;
 	if (entnum == 0)
 	{	//serverinfo
+		oldval = InfoBuf_BlobForKey(&svs.info, key, &oldsize, NULL);
+		if (oldsize == valsize && !memcmp(oldval, value, valsize))
+			return 2;	//unchanged
 		InfoBuf_SetStarBlobKey(&svs.info, key, value, valsize);
 		return 2;
 	}
@@ -9576,6 +9585,10 @@ int PF_ForceInfoKey_Internal(unsigned int entnum, const char *key, const char *v
 			Con_DPrintf("PF_ForceInfoKey: inactive client\n");
 			return 0;
 		}
+		oldval = InfoBuf_BlobForKey(&svs.clients[entnum-1].userinfo, key, &oldsize, NULL);
+		if (oldsize == valsize && !memcmp(oldval, value, valsize))
+			return 1;	//unchanged
+
 		if (InfoBuf_SetStarBlobKey(&svs.clients[entnum-1].userinfo, key, value, valsize))
 		{
 			SV_ExtractFromUserinfo (&svs.clients[entnum-1], false);
diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c
index db86e9000..c98461c49 100644
--- a/engine/server/sv_ccmds.c
+++ b/engine/server/sv_ccmds.c
@@ -2544,11 +2544,10 @@ void SV_User_f (void)
 											"OLD vweap",	"q2bsp",	"q3bsp",			"colormod",		"splitscreen",	"hexen2",		"spawnstatic2",		"customtempeffects",
 											"packents",		"UNKNOWN",	"showpic",			"setattachment","UNKNOWN",		"chunkeddls",	"csqc",				"dpflags"};
 	static const char *pext2names[32] = {	"prydoncursor",	"voip",		"setangledelta",	"rplcdeltas",	"maxplayers",	"predinfo",		"sizeenc",			"infoblobs",
-											"UNKNOWN",		"UNKNOWN",	"UNKNOWN",			"UNKNOWN",		"UNKNOWN",		"UNKNOWN",		"UNKNOWN",			"UNKNOWN", 
+											"stunaware",	"UNKNOWN",	"UNKNOWN",			"UNKNOWN",		"UNKNOWN",		"UNKNOWN",		"UNKNOWN",			"UNKNOWN",
 											"UNKNOWN",		"UNKNOWN",	"UNKNOWN",			"UNKNOWN",		"UNKNOWN",		"UNKNOWN",		"UNKNOWN",			"UNKNOWN",
 											"UNKNOWN",		"UNKNOWN",	"UNKNOWN",			"UNKNOWN",		"UNKNOWN",		"UNKNOWN",		"UNKNOWN",			"UNKNOWN"};
 
-
 	if (Cmd_Argc() != 2)
 	{
 		Con_TPrintf ("Usage: info <userid>\n");