From 8a41be9d4733ab75e29dae6af61d73d35813a5ad Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 8 Jan 2025 07:55:50 +0300 Subject: [PATCH] engine: server: finally, make a union for large leaf indices in edict_t so we can run bsp2 maps without recompiling --- engine/edict.h | 18 ++++++++---------- engine/server/server.h | 2 ++ engine/server/sv_game.c | 28 ++++++++++++++++++++++------ engine/server/sv_world.c | 25 ++++++++++++++----------- 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/engine/edict.h b/engine/edict.h index d74d08b1..d0e76715 100644 --- a/engine/edict.h +++ b/engine/edict.h @@ -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 diff --git a/engine/server/server.h b/engine/server/server.h index 2f145fc6..f1e6fad0 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -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 ) diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 06e0431a..99a903b2 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -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] )) - return 1; // visible passed by leaf + 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 } diff --git a/engine/server/sv_world.c b/engine/server/sv_world.c index 1690997e..0c52fd3f 100644 --- a/engine/server/sv_world.c +++ b/engine/server/sv_world.c @@ -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; }