From 727b8d40dbb8e577b451344a45523234ab75a57c Mon Sep 17 00:00:00 2001
From: Spoike <acceptthis@users.sourceforge.net>
Date: Sat, 16 Aug 2014 19:03:04 +0000
Subject: [PATCH] fix 3 issues that appear to happen with hipnotic.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4721 fc73d0e0-1445-4013-8a0c-d673dee63da5
---
 engine/client/cl_demo.c      |  4 ++-
 engine/client/cl_parse.c     |  2 +-
 engine/server/net_preparse.c | 67 ++++++++++++++++++++++++++++++++++--
 3 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c
index 7f59f8415..f382f7a0c 100644
--- a/engine/client/cl_demo.c
+++ b/engine/client/cl_demo.c
@@ -1730,7 +1730,9 @@ void CL_PlayDemo(char *demoname)
 		//work out if the first line is a int for the track number.
 		while ((VFS_READ(f, &chr, 1)==1) && (chr != '\n'))
 		{
-			if (chr == '-')
+			if (chr == ' ')
+				;
+			else if (chr == '-')
 				neg = true;
 			else if (chr < '0' || chr > '9')
 				break;
diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c
index 6e1b78052..5a6a932ea 100644
--- a/engine/client/cl_parse.c
+++ b/engine/client/cl_parse.c
@@ -3419,7 +3419,7 @@ void CLNQ_ParseClientdata (void)
 //			cl.mvelocity[0][i] = 0;
 	}
 
-	if (bits & SU_ITEMS)
+	if ((bits & SU_ITEMS) || cls.protocol_nq == CPNQ_ID)	//hipnotic bug - hipnotic demos don't always have SU_ITEMS set, yet they update STAT_ITEMS anyway.
 		CL_SetStatInt(0, STAT_ITEMS, MSG_ReadLong());
 
 //	cl.onground = (bits & SU_ONGROUND) != 0;
diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c
index 2ced448fe..2010014a3 100644
--- a/engine/server/net_preparse.c
+++ b/engine/server/net_preparse.c
@@ -922,6 +922,7 @@ void NPP_NQWriteByte(int dest, qbyte data)	//replacement write func (nq to qw)
 
 	if (!bufferlen)	//new message section
 	{
+		majortype = data;
 		switch(data)
 		{
 		case svcdp_showlmp:
@@ -997,16 +998,74 @@ void NPP_NQWriteByte(int dest, qbyte data)	//replacement write func (nq to qw)
 			protocollen = sizeof(buffer);
 			break;
 		default:
-			Con_DPrintf("NQWriteByte: bad protocol %i\n", (int)data);
-			protocollen = sizeof(buffer);
+			if (data & 128)
+			{
+				majortype = 128;	//nq 'fast update'
+				ignoreprotocol = true;
+				//this handling is explicitly for hipnotic.
+				//hipnotic sends a camera entity this way so that svc_setview knows where to position itself.
+				//we emulate this with quakeworld protocols, so we don't necessarily need to support it other than to strip it.
+				//we're probably screwed if we're acting as an nq server, but few people will use that.
+			}
+			else
+			{
+				Con_DPrintf("NQWriteByte: bad protocol %i\n", (int)data);
+				protocollen = sizeof(buffer);
+			}
 			break;
 		}
-		majortype = data;
 	}
 	if (bufferlen == 1 && !protocollen)	//some of them depend on the following bytes for size.
 	{
 		switch(majortype)
 		{
+		case 128:
+			{
+				unsigned int bits = buffer[0];
+				protocollen = 1;
+				if (bits & NQU_MOREBITS)
+				{
+					bits |= data<<8;
+					protocollen+=1;
+				}
+
+				if (bits != (NQU_SIGNAL|NQU_MOREBITS|NQU_ORIGIN1|NQU_ORIGIN2|NQU_ORIGIN3|NQU_LONGENTITY))
+				{	//this mask is what hipnotic uses. warn if anyone else tries it.
+					Con_Printf("fast update will be stripped\n");
+					PR_StackTrace(svprogfuncs, false);
+				}
+				if (bits & NQU_ORIGIN1)
+					protocollen+=2;
+				if (bits & NQU_ORIGIN2)
+					protocollen+=2;
+				if (bits & NQU_ORIGIN3)
+					protocollen+=2;
+				if (bits & NQU_ANGLE2)
+					protocollen+=1;
+				//nolerp no data
+				if (bits & NQU_FRAME)
+					protocollen+=1;
+
+				if (bits & NQU_ANGLE1)
+					protocollen+=1;
+				if (bits & NQU_ANGLE3)
+					protocollen+=1;
+				if (bits & NQU_MODEL)
+					protocollen+=1;
+				if (bits & NQU_COLORMAP)
+					protocollen+=1;
+				if (bits & NQU_SKIN)
+					protocollen+=1;
+				if (bits & NQU_EFFECTS)
+					protocollen+=1;
+				if (bits & NQU_LONGENTITY)
+					protocollen+=2;
+				else
+					protocollen+=1;
+				if (bits & DPU_EXTEND1)
+					Con_DPrintf("NQWriteByte: fast update with extension bits is not supported\n");
+			}
+			break;
 		case svc_sound:
 			protocollen = 5+destprim->coordsize*3;
 			if (data & NQSND_VOLUME)
@@ -1174,6 +1233,7 @@ void NPP_NQWriteByte(int dest, qbyte data)	//replacement write func (nq to qw)
 		case svcdp_hidelmp:
 		case svc_stufftext:
 		case svc_centerprint:
+		case svc_cutscene:
 			if (!data)
 				protocollen = bufferlen;
 			break;
@@ -1383,6 +1443,7 @@ void NPP_NQWriteString(int dest, const char *data)	//replacement write func (nq
 		case svc_updatename:
 		case svc_stufftext:
 		case svc_centerprint:
+		case svc_cutscene:
 			protocollen = bufferlen;
 			break;
 		}