engine: server: finally, make a union for large leaf indices in edict_t so we can run bsp2 maps without recompiling

This commit is contained in:
Alibek Omarov 2025-01-08 07:55:50 +03:00
parent 47aff9e30b
commit 8a41be9d47
4 changed files with 46 additions and 27 deletions

View file

@ -16,11 +16,8 @@
#ifndef EDICT_H #ifndef EDICT_H
#define EDICT_H #define EDICT_H
#ifdef SUPPORT_BSP2_FORMAT #define MAX_ENT_LEAFS_32 24 // Orignally was 16
#define MAX_ENT_LEAFS 24 // Orignally was 16 #define MAX_ENT_LEAFS_16 48
#else
#define MAX_ENT_LEAFS 48
#endif
#include "progdefs.h" #include "progdefs.h"
@ -33,11 +30,12 @@ struct edict_s
int headnode; // -1 to use normal leaf check int headnode; // -1 to use normal leaf check
int num_leafs; int num_leafs;
#ifdef SUPPORT_BSP2_FORMAT union
int leafnums[MAX_ENT_LEAFS]; {
#else int leafnums32[MAX_ENT_LEAFS_32];
short leafnums[MAX_ENT_LEAFS]; short leafnums16[MAX_ENT_LEAFS_16];
#endif };
float freetime; // sv.time when the object was freed float freetime; // sv.time when the object was freed
void* pvPrivateData; // Alloced and freed by engine, used by DLLs void* pvPrivateData; // Alloced and freed by engine, used by DLLs

View file

@ -67,6 +67,8 @@ extern int SV_UPDATE_BACKUP;
#define MAX_PUSHED_ENTS 256 #define MAX_PUSHED_ENTS 256
#define MAX_VIEWENTS 128 #define MAX_VIEWENTS 128
#define MAX_ENT_LEAFS( ext ) (( ext ) ? MAX_ENT_LEAFS_32 : MAX_ENT_LEAFS_16 )
#define FCL_RESEND_USERINFO BIT( 0 ) #define FCL_RESEND_USERINFO BIT( 0 )
#define FCL_RESEND_MOVEVARS BIT( 1 ) #define FCL_RESEND_MOVEVARS BIT( 1 )
#define FCL_SKIP_NET_MESSAGE BIT( 2 ) #define FCL_SKIP_NET_MESSAGE BIT( 2 )

View file

@ -4329,6 +4329,7 @@ pfnCheckVisibility
static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset ) static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
{ {
int i, leafnum; int i, leafnum;
qboolean large_leafs = FBitSet( sv.worldmodel->flags, MODEL_QBSP2 );
if( !SV_IsValidEdict( ent )) if( !SV_IsValidEdict( ent ))
return 0; return 0;
@ -4344,17 +4345,28 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
// check individual leafs // check individual leafs
for( i = 0; i < ent->num_leafs; i++ ) for( i = 0; i < ent->num_leafs; i++ )
{ {
if( CHECKVISBIT( pset, ent->leafnums[i] )) if( large_leafs )
{
if( CHECKVISBIT( pset, ent->leafnums32[i] ))
return 1; // visible passed by leaf return 1; // visible passed by leaf
} }
else
{
if( CHECKVISBIT( pset, ent->leafnums16[i] ))
return 1; // visible passed by leaf
}
}
return 0; return 0;
} }
else else
{ {
for( i = 0; i < MAX_ENT_LEAFS; i++ ) for( i = 0; i < MAX_ENT_LEAFS( large_leafs ); i++ )
{ {
leafnum = ent->leafnums[i]; if( large_leafs )
leafnum = ent->leafnums32[i];
else
leafnum = ent->leafnums16[i];
if( leafnum == -1 ) break; if( leafnum == -1 ) break;
if( CHECKVISBIT( pset, leafnum )) if( CHECKVISBIT( pset, leafnum ))
@ -4365,8 +4377,12 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
if( !Mod_HeadnodeVisible( sv.worldmodel, &sv.worldmodel->nodes[ent->headnode], pset, &leafnum )) if( !Mod_HeadnodeVisible( sv.worldmodel, &sv.worldmodel->nodes[ent->headnode], pset, &leafnum ))
return 0; return 0;
((edict_t *)ent)->leafnums[ent->num_leafs] = leafnum; if( large_leafs )
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS; ((edict_t *)ent)->leafnums32[ent->num_leafs] = leafnum;
else
((edict_t *)ent)->leafnums16[ent->num_leafs] = leafnum;
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS( large_leafs );
return 2; // visible passed by headnode return 2; // visible passed by headnode
} }

View file

@ -611,7 +611,7 @@ SV_FindTouchedLeafs
=============== ===============
*/ */
static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode ) static void SV_FindTouchedLeafs( edict_t *ent, model_t *mod, mnode_t *node, int *headnode )
{ {
int sides; int sides;
mleaf_t *leaf; mleaf_t *leaf;
@ -622,16 +622,19 @@ static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
// add an efrag if the node is a leaf // add an efrag if the node is a leaf
if( node->contents < 0 ) if( node->contents < 0 )
{ {
if( ent->num_leafs > ( MAX_ENT_LEAFS - 1 )) if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )))
{ {
// continue counting leafs, // continue counting leafs,
// so we know how many it's overrun // so we know how many it's overrun
ent->num_leafs = (MAX_ENT_LEAFS + 1); ent->num_leafs = (MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )) + 1);
} }
else else
{ {
leaf = (mleaf_t *)node; leaf = (mleaf_t *)node;
ent->leafnums[ent->num_leafs] = leaf->cluster; if( FBitSet( mod->flags, MODEL_QBSP2 ))
ent->leafnums32[ent->num_leafs] = leaf->cluster;
else
ent->leafnums16[ent->num_leafs] = leaf->cluster;
ent->num_leafs++; ent->num_leafs++;
} }
return; return;
@ -641,13 +644,13 @@ static void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, node->plane ); sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, node->plane );
if(( sides == 3 ) && ( *headnode == -1 )) if(( sides == 3 ) && ( *headnode == -1 ))
*headnode = node - sv.worldmodel->nodes; *headnode = node - mod->nodes;
// recurse down the contacted sides // recurse down the contacted sides
if( sides & 1 ) if( sides & 1 )
SV_FindTouchedLeafs( ent, node_child( node, 0, sv.worldmodel ), headnode ); SV_FindTouchedLeafs( ent, mod, node_child( node, 0, mod ), headnode );
if( sides & 2 ) if( sides & 2 )
SV_FindTouchedLeafs( ent, node_child( node, 1, sv.worldmodel ), headnode ); SV_FindTouchedLeafs( ent, mod, node_child( node, 1, mod ), headnode );
} }
/* /*
@ -669,7 +672,7 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
if( ent->v.movetype == MOVETYPE_FOLLOW && SV_IsValidEdict( ent->v.aiment )) if( ent->v.movetype == MOVETYPE_FOLLOW && SV_IsValidEdict( ent->v.aiment ))
{ {
memcpy( ent->leafnums, ent->v.aiment->leafnums, sizeof( ent->leafnums )); memcpy( ent->leafnums32, ent->v.aiment->leafnums32, sizeof( ent->leafnums32 ));
ent->num_leafs = ent->v.aiment->num_leafs; ent->num_leafs = ent->v.aiment->num_leafs;
ent->headnode = ent->v.aiment->headnode; ent->headnode = ent->v.aiment->headnode;
} }
@ -681,11 +684,11 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
headnode = -1; headnode = -1;
if( ent->v.modelindex ) if( ent->v.modelindex )
SV_FindTouchedLeafs( ent, sv.worldmodel->nodes, &headnode ); SV_FindTouchedLeafs( ent, sv.worldmodel, sv.worldmodel->nodes, &headnode );
if( ent->num_leafs > MAX_ENT_LEAFS ) if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( sv.worldmodel->flags, MODEL_QBSP2 )))
{ {
memset( ent->leafnums, -1, sizeof( ent->leafnums )); memset( ent->leafnums32, -1, sizeof( ent->leafnums32 ));
ent->num_leafs = 0; // so we use headnode instead ent->num_leafs = 0; // so we use headnode instead
ent->headnode = headnode; ent->headnode = headnode;
} }