From f7cdca7ad2c9b39b772728a5253352e68ed51b3e Mon Sep 17 00:00:00 2001
From: nillerusr <nillerusr@users.noreply.github.com>
Date: Sun, 14 Nov 2021 00:07:58 +0300
Subject: [PATCH] saverestore fixes

---
 engine/cmodel.cpp      | 152 +++++++++++++++++++----------------------
 game/server/player.cpp |   2 +
 public/datamap.h       |  28 ++++----
 3 files changed, 87 insertions(+), 95 deletions(-)

diff --git a/engine/cmodel.cpp b/engine/cmodel.cpp
index 466d4451d3..e9af063de0 100644
--- a/engine/cmodel.cpp
+++ b/engine/cmodel.cpp
@@ -539,64 +539,62 @@ struct leafnums_t
 	CCollisionBSPData *pBSPData;
 };
 
-
-
 int CM_BoxLeafnums( leafnums_t &context, const Vector &center, const Vector &extents, int nodenum )
 {
-	int leafCount = 0;
-	const int NODELIST_MAX = 1024;
-	int nodeList[NODELIST_MAX];
-	int nodeReadIndex = 0;
-	int nodeWriteIndex = 0;
-	cplane_t	*plane;
-	cnode_t		*node;
-	int prev_topnode = -1;
+        int leafCount = 0;
+        const int NODELIST_MAX = 1024;
+        int nodeList[NODELIST_MAX];
+        int nodeReadIndex = 0;
+        int nodeWriteIndex = 0;
+        cplane_t        *plane;
+        cnode_t         *node;
+        int prev_topnode = -1;
 
-	while (1)
-	{
-		if (nodenum < 0)
-		{
-			// This handles the case when the box lies completely
-			// within a single node. In that case, the top node should be
-			// the parent of the leaf
-			if (context.leafTopNode == -1)
-				context.leafTopNode = prev_topnode;
+        while (1)
+        {
+                if (nodenum < 0)
+                {
+                        // This handles the case when the box lies completely
+                        // within a single node. In that case, the top node should be
+                        // the parent of the leaf
+                        if (context.leafTopNode == -1)
+                                context.leafTopNode = prev_topnode;
 
-			if (leafCount < context.leafMaxCount)
-			{
-				context.pLeafList[leafCount] = -1 - nodenum;
-				leafCount++;
-			}
-			if ( nodeReadIndex == nodeWriteIndex )
-				return leafCount;
-			nodenum = nodeList[nodeReadIndex];
-			nodeReadIndex = (nodeReadIndex+1) & (NODELIST_MAX-1);
-		}
-		else
-		{
-			node = &context.pBSPData->map_rootnode[nodenum];
-			plane = node->plane;
-			//		s = BoxOnPlaneSide (leaf_mins, leaf_maxs, plane);
-			//		s = BOX_ON_PLANE_SIDE(*leaf_mins, *leaf_maxs, plane);
-			float d0 = DotProduct( plane->normal, center ) - plane->dist;
-			float d1 = DotProductAbs( plane->normal, extents );
-			prev_topnode = nodenum;
-			if (d0 >= d1)
-				nodenum = node->children[0];
-			else if (d0 < -d1)
-				nodenum = node->children[1];
-			else
-			{	// go down both
-				if (context.leafTopNode == -1)
-					context.leafTopNode = nodenum;
-				nodeList[nodeWriteIndex] = node->children[0];
-				nodeWriteIndex = (nodeWriteIndex+1) & (NODELIST_MAX-1);
-				// check for overflow of the ring buffer
-				Assert(nodeWriteIndex != nodeReadIndex);
-				nodenum = node->children[1];
-			}
-		}
-	}
+                        if (leafCount < context.leafMaxCount)
+                        {
+                                context.pLeafList[leafCount] = -1 - nodenum;
+                                leafCount++;
+                        }
+                        if ( nodeReadIndex == nodeWriteIndex )
+                                return leafCount;
+                        nodenum = nodeList[nodeReadIndex];
+                        nodeReadIndex = (nodeReadIndex+1) & (NODELIST_MAX-1);
+                }
+                else
+                {
+                        node = &context.pBSPData->map_rootnode[nodenum];
+                        plane = node->plane;
+                        //              s = BoxOnPlaneSide (leaf_mins, leaf_maxs, plane);
+                        //              s = BOX_ON_PLANE_SIDE(*leaf_mins, *leaf_maxs, plane);
+                        float d0 = DotProduct( plane->normal, center ) - plane->dist;
+                        float d1 = DotProductAbs( plane->normal, extents );
+                        prev_topnode = nodenum;
+                        if (d0 >= d1)
+                                nodenum = node->children[0];
+                        else if (d0 < -d1)
+                                nodenum = node->children[1];
+                        else
+                        {       // go down both
+                                if (context.leafTopNode == -1)
+                                        context.leafTopNode = nodenum;
+                                nodeList[nodeWriteIndex] = node->children[0];
+                                nodeWriteIndex = (nodeWriteIndex+1) & (NODELIST_MAX-1);
+                                // check for overflow of the ring buffer
+                                Assert(nodeWriteIndex != nodeReadIndex);
+                                nodenum = node->children[1];
+                        }
+                }
+        }
 }
 
 int	CM_BoxLeafnums ( const Vector& mins, const Vector& maxs, int *list, int listsize, int *topnode)
@@ -2666,38 +2664,32 @@ bool CM_HeadnodeVisible (int nodenum, const byte *visbits, int vissize )
 //			*visbits - pvs or pas of some cluster
 // Output : true if visible, false if not
 //-----------------------------------------------------------------------------
-#define MAX_BOX_LEAVES	256
-int	CM_BoxVisible( const Vector& mins, const Vector& maxs, const byte *visbits, int vissize )
+#define MAX_BOX_LEAVES  256
+int     CM_BoxVisible( const Vector& mins, const Vector& maxs, const byte *visbits, int vissize )
 {
-	int leafList[MAX_BOX_LEAVES];
-	int topnode;
+        int leafList[MAX_BOX_LEAVES];
+        int topnode;
 
-	// FIXME: Could save a loop here by traversing the tree in this routine like the code above
-	int count = CM_BoxLeafnums( mins, maxs, leafList, MAX_BOX_LEAVES, &topnode );
-	for ( int i = 0; i < count; i++ )
-	{
-		int cluster = CM_LeafCluster( leafList[i] );
-		int offset = cluster>>3;
+        // FIXME: Could save a loop here by traversing the tree in this routine like the code above
+        int count = CM_BoxLeafnums( mins, maxs, leafList, MAX_BOX_LEAVES, &topnode );
+        for ( int i = 0; i < count; i++ )
+        {
+                int cluster = CM_LeafCluster( leafList[i] );
+                int offset = cluster>>3;
 
-		if ( offset == -1 )
-		{
-			return false;
-		}
+                if ( offset > vissize )
+                {
+                        Sys_Error( "CM_BoxVisible:  cluster %i, offset %i out of bounds %i\n", cluster, offset, vissize );
+                }
 
-		if ( offset > vissize || offset < 0 )
-		{
-			Sys_Error( "CM_BoxVisible:  cluster %i, offset %i out of bounds %i\n", cluster, offset, vissize );
-		}
-
-		if (visbits[cluster>>3] & (1<<(cluster&7)))
-		{
-			return true;
-		}
-	}
-	return false;
+                if (visbits[cluster>>3] & (1<<(cluster&7)))
+                {
+                        return true;
+                }
+        }
+        return false;
 }
 
-
 //-----------------------------------------------------------------------------
 // Returns the world-space center of an entity
 //-----------------------------------------------------------------------------
diff --git a/game/server/player.cpp b/game/server/player.cpp
index 7dea1f5075..b5d4debc20 100644
--- a/game/server/player.cpp
+++ b/game/server/player.cpp
@@ -3380,12 +3380,14 @@ void CBasePlayer::PhysicsSimulate( void )
 			pi->m_nNumCmds = commandsToRun;
 		}
 	}
+#if 0
 	else if ( GetTimeSinceLastUserCommand() > sv_player_usercommand_timeout.GetFloat() )
 	{
 		// no usercommand from player after some threshold
 		// server should start RunNullCommand as if client sends an empty command so that Think and gamestate related things run properly
 		RunNullCommand();
 	}
+#endif
 
 	// Restore the true server clock
 	// FIXME:  Should this occur after simulation of children so
diff --git a/public/datamap.h b/public/datamap.h
index 909d67f54c..936f44368f 100644
--- a/public/datamap.h
+++ b/public/datamap.h
@@ -128,11 +128,9 @@ DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX,	sizeof(int) )
 #define ARRAYSIZE2D(p)		(sizeof(p)/sizeof(p[0][0]))
 #define SIZE_OF_ARRAY(p)	_ARRAYSIZE(p)
 
-// Normal offset of is invalid on non-array-types, this is dubious as hell. The rest of the codebase converted to the
-// legit offsetof from the C headers, so we'll use the old impl here to avoid exposing temptation to others
-#define _hacky_datamap_offsetof(s,m)	((size_t)&(((s *)0)->m))
+#define _offsetof(s,m)	((size_t)&(((s *)0)->m))
 
-#define _FIELD(name,fieldtype,count,flags,mapname,tolerance)		{ fieldtype, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance }
+#define _FIELD(name,fieldtype,count,flags,mapname,tolerance)		{ fieldtype, #name, { _offsetof(classNameTypedef, name), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance }
 #define DEFINE_FIELD_NULL	{ FIELD_VOID,0, {0,0},0,0,0,0,0,0}
 #define DEFINE_FIELD(name,fieldtype)			_FIELD(name, fieldtype, 1,  FTYPEDESC_SAVE, NULL, 0 )
 #define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1,  FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
@@ -144,35 +142,35 @@ DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX,	sizeof(int) )
 #define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype)	_FIELD(edict_t, name, fieldtype, 1,  FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 )
 #define DEFINE_GLOBAL_FIELD(name,fieldtype)	_FIELD(name, fieldtype, 1,  FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 )
 #define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname)	_FIELD(name, fieldtype, 1,  FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
-#define DEFINE_CUSTOM_FIELD(name,datafuncs)	{ FIELD_CUSTOM, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL }
-#define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname)	{ FIELD_CUSTOM, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL }
+#define DEFINE_CUSTOM_FIELD(name,datafuncs)	{ FIELD_CUSTOM, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL }
+#define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname)	{ FIELD_CUSTOM, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL }
 #define DEFINE_AUTO_ARRAY2D(name,fieldtype)		_FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
 // Used by byteswap datadescs
 #define DEFINE_BITFIELD(name,fieldtype,bitcount)	DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) )
 #define DEFINE_INDEX(name,fieldtype)			_FIELD(name, fieldtype, 1,  FTYPEDESC_INDEX, NULL, 0 )
 
 #define DEFINE_EMBEDDED( name )						\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
 
 #define DEFINE_EMBEDDED_OVERRIDE( name, overridetype )	\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
 
 #define DEFINE_EMBEDDEDBYREF( name )					\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f }
 
 #define DEFINE_EMBEDDED_ARRAY( name, count )			\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f  }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f  }
 
 #define DEFINE_EMBEDDED_AUTO_ARRAY( name )			\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f  }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f  }
 
 #ifndef NO_ENTITY_PREDICTION
 
 #define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype )						\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &fieldtype::m_PredMap }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &fieldtype::m_PredMap }
 
 #define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype )						\
-	{ FIELD_EMBEDDED, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &fieldtype::m_PredMap }
+	{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &fieldtype::m_PredMap }
 
 #else
 
@@ -193,7 +191,7 @@ DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX,	sizeof(int) )
 //#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1,  flags, extname )
 
 // INPUTS
-#define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY,	inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) }
+#define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY,	inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) }
 #define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, { NULL, NULL }, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast <inputfunc_t> (&classNameTypedef::inputfunc) }
 
 // OUTPUTS
@@ -201,7 +199,7 @@ DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX,	sizeof(int) )
 // we know the output type from the variable itself, so it doesn't need to be specified here
 class ISaveRestoreOps;
 extern ISaveRestoreOps *eventFuncs;
-#define DEFINE_OUTPUT( name, outputname )	{ FIELD_CUSTOM, #name, { (int)_hacky_datamap_offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs }
+#define DEFINE_OUTPUT( name, outputname )	{ FIELD_CUSTOM, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs }
 
 // replaces EXPORT table for portability and non-DLL based systems (xbox)
 #define DEFINE_FUNCTION_RAW( function, func_type )			{ FIELD_VOID, nameHolder.GenerateName(#function), { NULL, NULL }, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) }