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
#define EDICT_H
#ifdef SUPPORT_BSP2_FORMAT
#define MAX_ENT_LEAFS 24 // Orignally was 16
#else
#define MAX_ENT_LEAFS 48
#endif
#define MAX_ENT_LEAFS_32 24 // Orignally was 16
#define MAX_ENT_LEAFS_16 48
#include "progdefs.h"
@ -33,11 +30,12 @@ struct edict_s
int headnode; // -1 to use normal leaf check
int num_leafs;
#ifdef SUPPORT_BSP2_FORMAT
int leafnums[MAX_ENT_LEAFS];
#else
short leafnums[MAX_ENT_LEAFS];
#endif
union
{
int leafnums32[MAX_ENT_LEAFS_32];
short leafnums16[MAX_ENT_LEAFS_16];
};
float freetime; // sv.time when the object was freed
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_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_MOVEVARS BIT( 1 )
#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 )
{
int i, leafnum;
qboolean large_leafs = FBitSet( sv.worldmodel->flags, MODEL_QBSP2 );
if( !SV_IsValidEdict( ent ))
return 0;
@ -4344,17 +4345,28 @@ static int GAME_EXPORT pfnCheckVisibility( const edict_t *ent, byte *pset )
// check individual leafs
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
}
else
{
if( CHECKVISBIT( pset, ent->leafnums16[i] ))
return 1; // visible passed by leaf
}
}
return 0;
}
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( 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 ))
return 0;
((edict_t *)ent)->leafnums[ent->num_leafs] = leafnum;
((edict_t *)ent)->num_leafs = (ent->num_leafs + 1) % MAX_ENT_LEAFS;
if( large_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
}

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;
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
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,
// 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
{
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++;
}
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 );
if(( sides == 3 ) && ( *headnode == -1 ))
*headnode = node - sv.worldmodel->nodes;
*headnode = node - mod->nodes;
// recurse down the contacted sides
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 )
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 ))
{
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->headnode = ent->v.aiment->headnode;
}
@ -681,11 +684,11 @@ void GAME_EXPORT SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
headnode = -1;
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->headnode = headnode;
}