Browse Source

Apply 4483 update

pull/2/head
Alibek Omarov 6 years ago
parent
commit
c215b89923
  1. 2
      common/bspfile.h
  2. 11
      common/com_model.h
  3. 2
      common/features.h
  4. 1
      common/render_api.h
  5. 5
      engine/client/cl_game.c
  6. 4
      engine/client/cl_gameui.c
  7. 1
      engine/client/cl_main.c
  8. 2
      engine/client/cl_parse.c
  9. 71
      engine/client/cl_pmove.c
  10. 2
      engine/client/gl_beams.c
  11. 2
      engine/client/gl_decals.c
  12. 41
      engine/client/gl_image.c
  13. 3
      engine/client/gl_local.h
  14. 19
      engine/client/gl_rmain.c
  15. 1
      engine/client/gl_rmisc.c
  16. 3
      engine/client/gl_rpart.c
  17. 6
      engine/client/gl_rsurf.c
  18. 9
      engine/client/gl_studio.c
  19. 2
      engine/client/gl_vidnt.c
  20. 2
      engine/common/avikit.c
  21. 3
      engine/common/cmd.c
  22. 20
      engine/common/common.c
  23. 4
      engine/common/common.h
  24. 2
      engine/common/console.c
  25. 2
      engine/common/crclib.c
  26. 4
      engine/common/host.c
  27. 27
      engine/common/imagelib/img_dds.c
  28. 23
      engine/common/imagelib/img_main.c
  29. 7
      engine/common/imagelib/img_utils.c
  30. 3
      engine/common/keys.c
  31. 138
      engine/common/mod_bmodel.c
  32. 22
      engine/common/mod_studio.c
  33. 5
      engine/common/model.c
  34. 7
      engine/common/net_buffer.c
  35. 2
      engine/common/net_buffer.h
  36. 124
      engine/common/net_encode.c
  37. 6
      engine/common/netchan.h
  38. 2
      engine/common/pm_local.h
  39. 210
      engine/common/pm_surface.c
  40. 78
      engine/common/pm_trace.c
  41. 2
      engine/common/zone.c
  42. 2
      engine/server/server.h
  43. 5
      engine/server/sv_cmds.c
  44. 23
      engine/server/sv_frame.c
  45. 32
      engine/server/sv_game.c
  46. 23
      engine/server/sv_init.c
  47. 31
      engine/server/sv_main.c
  48. 28
      engine/server/sv_pmove.c
  49. 1
      engine/server/sv_world.c

2
common/bspfile.h

@ -134,6 +134,8 @@ BRUSH MODELS
#define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel #define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel
#define TEX_SCROLL BIT( 6 ) // Doom special FX #define TEX_SCROLL BIT( 6 ) // Doom special FX
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
// ambient sound types // ambient sound types
enum enum
{ {

11
common/com_model.h

@ -109,6 +109,15 @@ typedef struct
int reserved[32]; // just for future expansions or mod-makers int reserved[32]; // just for future expansions or mod-makers
} mfaceinfo_t; } mfaceinfo_t;
typedef struct
{
mplane_t *edges;
int numedges;
vec3_t origin;
vec_t radius; // for culling tests
int contents; // sky or solid
} mfacebevel_t;
typedef struct typedef struct
{ {
float vecs[2][4]; // [s/t] unit vectors in world space. float vecs[2][4]; // [s/t] unit vectors in world space.
@ -208,7 +217,7 @@ typedef struct mextrasurf_s
// begin userdata // begin userdata
struct msurface_s *lightmapchain; // lightmapped polys struct msurface_s *lightmapchain; // lightmapped polys
struct mextrasurf_s *detailchain; // for detail textures drawing struct mextrasurf_s *detailchain; // for detail textures drawing
struct mextrasurf_s *mirrorchain; // for gl_texsort drawing mfacebevel_t *bevel; // for exact face traceline
struct mextrasurf_s *lumachain; // draw fullbrights struct mextrasurf_s *lumachain; // draw fullbrights
struct cl_entity_s *parent; // upcast to owner entity struct cl_entity_s *parent; // upcast to owner entity

2
common/features.h

@ -23,7 +23,7 @@ GNU General Public License for more details.
#define ENGINE_PHYSICS_PUSHER_EXT (1<<3) // enable sets of improvements for MOVETYPE_PUSH physics #define ENGINE_PHYSICS_PUSHER_EXT (1<<3) // enable sets of improvements for MOVETYPE_PUSH physics
#define ENGINE_LARGE_LIGHTMAPS (1<<4) // change lightmap sizes from 128x128 to 1024x1024 #define ENGINE_LARGE_LIGHTMAPS (1<<4) // change lightmap sizes from 128x128 to 1024x1024
#define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed #define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed
// reserved #define ENGINE_IMPROVED_LINETRACE (1<<6) // new traceline that tracing through alphatextures
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine #define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#endif//FEATURES_H #endif//FEATURES_H

1
common/render_api.h

@ -60,6 +60,7 @@ GNU General Public License for more details.
#define PARM_GLES_WRAPPER 35 // #define PARM_GLES_WRAPPER 35 //
#define PARM_STENCIL_ACTIVE 36 #define PARM_STENCIL_ACTIVE 36
#define PARM_WATER_ALPHA 37 #define PARM_WATER_ALPHA 37
#define PARM_TEX_MEMORY 38 // returns total memory of uploaded texture in bytes
// skybox ordering // skybox ordering
enum enum

5
engine/client/cl_game.c

@ -254,7 +254,7 @@ Return contents for point
*/ */
int CL_PointContents( const vec3_t p ) int CL_PointContents( const vec3_t p )
{ {
int cont = CL_TruePointContents( p ); int cont = PM_PointContents( clgame.pmove, p );
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN ) if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
cont = CONTENTS_WATER; cont = CONTENTS_WATER;
@ -2165,7 +2165,7 @@ static int pfnPointContents( const float *p, int *truecontents )
{ {
int cont, truecont; int cont, truecont;
truecont = cont = CL_TruePointContents( p ); truecont = cont = PM_PointContents( clgame.pmove, p );
if( truecontents ) *truecontents = truecont; if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN ) if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
@ -3124,6 +3124,7 @@ void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn )
// check for invalid parms // check for invalid parms
if( flEnd <= flStart ) if( flEnd <= flStart )
{ {
glState.isFogEnabled = false;
RI.fogCustom = false; RI.fogCustom = false;
pglDisable( GL_FOG ); pglDisable( GL_FOG );
return; return;

4
engine/client/cl_gameui.c

@ -378,7 +378,7 @@ static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long im
{ {
HIMAGE tx; HIMAGE tx;
if( !szPicName || !*szPicName ) if( !COM_CheckString( szPicName ))
{ {
Con_Reportf( S_ERROR "CL_LoadImage: bad name!\n" ); Con_Reportf( S_ERROR "CL_LoadImage: bad name!\n" );
return 0; return 0;
@ -902,7 +902,7 @@ pfnHostEndGame
static void pfnHostEndGame( const char *szFinalMessage ) static void pfnHostEndGame( const char *szFinalMessage )
{ {
if( !szFinalMessage ) szFinalMessage = ""; if( !szFinalMessage ) szFinalMessage = "";
Host_EndGame( true, szFinalMessage ); Host_EndGame( false, szFinalMessage );
} }
/* /*

1
engine/client/cl_main.c

@ -2099,6 +2099,7 @@ void CL_ReadPackets( void )
// check resource for downloading and precache // check resource for downloading and precache
CL_EstimateNeededResources(); CL_EstimateNeededResources();
CL_BatchResourceRequest( false ); CL_BatchResourceRequest( false );
cls.dl.doneregistering = false;
cls.dl.custom = true; cls.dl.custom = true;
} }

2
engine/client/cl_parse.c

@ -1492,7 +1492,7 @@ void CL_RegisterResources( sizebuf_t *msg )
ASSERT( clgame.entities != NULL ); ASSERT( clgame.entities != NULL );
clgame.entities->model = cl.worldmodel; clgame.entities->model = cl.worldmodel;
if( cls.state != ca_disconnected ) if( !cl.video_prepped && !cl.audio_prepped )
{ {
Con_Printf( "Setting up renderer...\n" ); Con_Printf( "Setting up renderer...\n" );

71
engine/client/cl_pmove.c

@ -472,7 +472,7 @@ void CL_AddLinksToPmove( frame_t *frame )
if( VectorIsNull( state->mins ) && VectorIsNull( state->maxs )) if( VectorIsNull( state->mins ) && VectorIsNull( state->maxs ))
continue; continue;
if( state->solid == SOLID_NOT && state->skin < CONTENTS_EMPTY ) if( state->solid == SOLID_NOT && state->skin == CONTENTS_LADDER )
{ {
if( clgame.pmove->nummoveent >= MAX_MOVEENTS ) if( clgame.pmove->nummoveent >= MAX_MOVEENTS )
continue; continue;
@ -588,67 +588,6 @@ void CL_SetSolidPlayers( int playernum )
} }
} }
/*
=============
CL_TruePointContents
=============
*/
int CL_TruePointContents( const vec3_t p )
{
int i, contents;
int oldhull;
hull_t *hull;
vec3_t test, offset;
physent_t *pe;
// sanity check
if( !p ) return CONTENTS_NONE;
oldhull = clgame.pmove->usehull;
// get base contents from world
contents = PM_HullPointContents( &cl.worldmodel->hulls[0], 0, p );
for( i = 0; i < clgame.pmove->nummoveent; i++ )
{
pe = &clgame.pmove->moveents[i];
if( pe->solid != SOLID_NOT ) // disabled ?
continue;
// only brushes can have special contents
if( !pe->model || pe->model->type != mod_brush )
continue;
// check water brushes accuracy
clgame.pmove->usehull = 2;
hull = PM_HullForBsp( pe, clgame.pmove, offset );
clgame.pmove->usehull = oldhull;
// offset the test point appropriately for this hull.
VectorSubtract( p, offset, test );
if( FBitSet( pe->model->flags, MODEL_HAS_ORIGIN ) && !VectorIsNull( pe->angles ))
{
matrix4x4 matrix;
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
Matrix4x4_VectorITransform( matrix, p, test );
}
// test hull for intersection with this model
if( PM_HullPointContents( hull, hull->firstclipnode, test ) == CONTENTS_EMPTY )
continue;
// compare contents ranking
if( RankForContents( pe->skin ) > RankForContents( contents ))
contents = pe->skin; // new content has more priority
}
return contents;
}
/* /*
============= =============
CL_WaterEntity CL_WaterEntity
@ -666,9 +605,9 @@ int CL_WaterEntity( const float *rgflPos )
oldhull = clgame.pmove->usehull; oldhull = clgame.pmove->usehull;
for( i = 0; i < clgame.pmove->nummoveent; i++ ) for( i = 0; i < clgame.pmove->numphysent; i++ )
{ {
pe = &clgame.pmove->moveents[i]; pe = &clgame.pmove->physents[i];
if( pe->solid != SOLID_NOT ) // disabled ? if( pe->solid != SOLID_NOT ) // disabled ?
continue; continue;
@ -793,7 +732,7 @@ static int pfnPointContents( float *p, int *truecontents )
{ {
int cont, truecont; int cont, truecont;
truecont = cont = CL_TruePointContents( p ); truecont = cont = PM_PointContents( clgame.pmove, p );
if( truecontents ) *truecontents = truecont; if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN ) if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
@ -803,7 +742,7 @@ static int pfnPointContents( float *p, int *truecontents )
static int pfnTruePointContents( float *p ) static int pfnTruePointContents( float *p )
{ {
return CL_TruePointContents( p ); return PM_TruePointContents( clgame.pmove, p );
} }
static int pfnHullPointContents( struct hull_s *hull, int num, float *p ) static int pfnHullPointContents( struct hull_s *hull, int num, float *p )

2
engine/client/gl_beams.c

@ -686,7 +686,7 @@ void R_DrawDisk( vec3_t source, vec3_t delta, float width, float scale, float fr
scale = scale * length; scale = scale * length;
// clamp the beam width // clamp the beam width
w = fmod( freq, width ) * delta[2]; w = fmod( freq, width * 0.1f ) * delta[2];
// NOTE: we must force the degenerate triangles to be on the edge // NOTE: we must force the degenerate triangles to be on the edge
for( i = 0; i < segments; i++ ) for( i = 0; i < segments; i++ )

2
engine/client/gl_decals.c

@ -77,7 +77,7 @@ static void R_DecalUnlink( decal_t *pdecal )
else else
{ {
tmp = pdecal->psurface->pdecals; tmp = pdecal->psurface->pdecals;
if( !tmp ) Host_Error( "D_DecalUnlink: bad decal list\n" ); if( !tmp ) Host_Error( "R_DecalUnlink: bad decal list\n" );
while( tmp->pnext ) while( tmp->pnext )
{ {

41
engine/client/gl_image.c

@ -112,6 +112,9 @@ void GL_ApplyTextureParams( gl_texture_t *tex )
{ {
vec4_t border = { 0.0f, 0.0f, 0.0f, 1.0f }; vec4_t border = { 0.0f, 0.0f, 0.0f, 1.0f };
if( !glw_state.initialized )
return;
Assert( tex != NULL ); Assert( tex != NULL );
// set texture filter // set texture filter
@ -348,6 +351,9 @@ static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int d
switch( format ) switch( format )
{ {
case PF_LUMINANCE:
size = width * height * depth;
break;
case PF_RGB_24: case PF_RGB_24:
case PF_BGR_24: case PF_BGR_24:
size = width * height * depth * 3; size = width * height * depth * 3;
@ -1085,6 +1091,10 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
qboolean normalMap; qboolean normalMap;
const byte *bufend; const byte *bufend;
// dedicated server
if( !glw_state.initialized )
return true;
Assert( pic != NULL ); Assert( pic != NULL );
Assert( tex != NULL ); Assert( tex != NULL );
@ -1210,6 +1220,7 @@ do specified actions on pixels
*/ */
static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic ) static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
{ {
float emboss_scale = 0.0f;
uint img_flags = 0; uint img_flags = 0;
// force upload texture as RGB or RGBA (detail textures requires this) // force upload texture as RGB or RGBA (detail textures requires this)
@ -1255,8 +1266,12 @@ static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
if( pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32 ) if( pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32 )
img_flags |= IMAGE_FORCE_RGBA; img_flags |= IMAGE_FORCE_RGBA;
// dedicated server doesn't register this variable
if( gl_emboss_scale != NULL )
emboss_scale = gl_emboss_scale->value;
// processing image before uploading (force to rgba, make luma etc) // processing image before uploading (force to rgba, make luma etc)
if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags, gl_emboss_scale->value ); if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags, emboss_scale );
if( FBitSet( tex->flags, TF_LUMINANCE )) if( FBitSet( tex->flags, TF_LUMINANCE ))
ClearBits( pic->flags, IMAGE_HAS_COLOR ); ClearBits( pic->flags, IMAGE_HAS_COLOR );
@ -1270,7 +1285,7 @@ GL_CheckTexName
*/ */
qboolean GL_CheckTexName( const char *name ) qboolean GL_CheckTexName( const char *name )
{ {
if( !COM_CheckString( name ) || !glw_state.initialized ) if( !COM_CheckString( name ))
return false; return false;
// because multi-layered textures can exceed name string // because multi-layered textures can exceed name string
@ -1385,6 +1400,7 @@ static void GL_DeleteTexture( gl_texture_t *tex )
if( tex->original ) if( tex->original )
FS_FreeImage( tex->original ); FS_FreeImage( tex->original );
if( glw_state.initialized )
pglDeleteTextures( 1, &tex->texnum ); pglDeleteTextures( 1, &tex->texnum );
memset( tex, 0, sizeof( *tex )); memset( tex, 0, sizeof( *tex ));
} }
@ -1643,6 +1659,7 @@ int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags
} }
GL_ProcessImage( tex, pic ); GL_ProcessImage( tex, pic );
if( !GL_UploadTexture( tex, pic )) if( !GL_UploadTexture( tex, pic ))
{ {
memset( tex, 0, sizeof( gl_texture_t )); memset( tex, 0, sizeof( gl_texture_t ));
@ -1784,8 +1801,7 @@ GL_FreeTexture
void GL_FreeTexture( GLenum texnum ) void GL_FreeTexture( GLenum texnum )
{ {
// number 0 it's already freed // number 0 it's already freed
if( texnum <= 0 || !glw_state.initialized ) if( texnum <= 0 ) return;
return;
GL_DeleteTexture( &gl_textures[texnum] ); GL_DeleteTexture( &gl_textures[texnum] );
} }
@ -1842,6 +1858,23 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
FS_FreeImage( pic ); FS_FreeImage( pic );
} }
/*
================
GL_TexMemory
return size of all uploaded textures
================
*/
int GL_TexMemory( void )
{
int i, total = 0;
for( i = 0; i < gl_numTextures; i++ )
total += gl_textures[i].size;
return total;
}
/* /*
============================================================================== ==============================================================================

3
engine/client/gl_local.h

@ -206,7 +206,6 @@ typedef struct
int recursion_level; int recursion_level;
int max_recursion; int max_recursion;
byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS
int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536 int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536
int block_size; // lightmap blocksize int block_size; // lightmap blocksize
@ -331,6 +330,7 @@ void R_InitDlightTexture( void );
void R_TextureList_f( void ); void R_TextureList_f( void );
void R_InitImages( void ); void R_InitImages( void );
void R_ShutdownImages( void ); void R_ShutdownImages( void );
int GL_TexMemory( void );
// //
// gl_refrag.c // gl_refrag.c
@ -612,6 +612,7 @@ typedef struct
GLboolean texIdentityMatrix[MAX_TEXTURE_UNITS]; GLboolean texIdentityMatrix[MAX_TEXTURE_UNITS];
GLint genSTEnabled[MAX_TEXTURE_UNITS]; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R GLint genSTEnabled[MAX_TEXTURE_UNITS]; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R
GLint texCoordArrayMode[MAX_TEXTURE_UNITS]; // 0 - disabled, 1 - enabled, 2 - cubemap GLint texCoordArrayMode[MAX_TEXTURE_UNITS]; // 0 - disabled, 1 - enabled, 2 - cubemap
GLint isFogEnabled;
int faceCull; int faceCull;

19
engine/client/gl_rmain.c

@ -43,18 +43,14 @@ static int R_RankForRenderMode( int rendermode )
void R_AllowFog( int allowed ) void R_AllowFog( int allowed )
{ {
static int isFogEnabled;
if( allowed ) if( allowed )
{ {
if( isFogEnabled ) if( glState.isFogEnabled )
pglEnable( GL_FOG ); pglEnable( GL_FOG );
} }
else else
{ {
isFogEnabled = pglIsEnabled( GL_FOG ); if( glState.isFogEnabled )
if( isFogEnabled )
pglDisable( GL_FOG ); pglDisable( GL_FOG );
} }
} }
@ -487,6 +483,9 @@ static void R_SetupFrame( void )
// setup viewplane dist // setup viewplane dist
RI.viewplanedist = DotProduct( RI.vieworg, RI.vforward ); RI.viewplanedist = DotProduct( RI.vieworg, RI.vforward );
// NOTE: this request is the fps-killer on some NVidia drivers
glState.isFogEnabled = pglIsEnabled( GL_FOG );
if( !gl_nosort->value ) if( !gl_nosort->value )
{ {
// sort translucents entities by rendermode and distance // sort translucents entities by rendermode and distance
@ -690,7 +689,11 @@ static void R_CheckFog( void )
// in some cases waterlevel jumps from 3 to 1. Catch it // in some cases waterlevel jumps from 3 to 1. Catch it
RI.cached_waterlevel = cl.local.waterlevel; RI.cached_waterlevel = cl.local.waterlevel;
RI.cached_contents = CONTENTS_EMPTY; RI.cached_contents = CONTENTS_EMPTY;
if( !RI.fogCustom ) pglDisable( GL_FOG ); if( !RI.fogCustom )
{
glState.isFogEnabled = false;
pglDisable( GL_FOG );
}
} }
return; return;
} }
@ -1271,6 +1274,8 @@ static int GL_RenderGetParm( int parm, int arg )
return glState.stencilEnabled; return glState.stencilEnabled;
case PARM_WATER_ALPHA: case PARM_WATER_ALPHA:
return FBitSet( world.flags, FWORLD_WATERALPHA ); return FBitSet( world.flags, FWORLD_WATERALPHA );
case PARM_TEX_MEMORY:
return GL_TexMemory();
} }
return 0; return 0;
} }

1
engine/client/gl_rmisc.c

@ -178,6 +178,7 @@ void R_NewMap( void )
for( i = 0; i < cl.worldmodel->numleafs; i++ ) for( i = 0; i < cl.worldmodel->numleafs; i++ )
cl.worldmodel->leafs[i+1].efrags = NULL; cl.worldmodel->leafs[i+1].efrags = NULL;
glState.isFogEnabled = false;
tr.skytexturenum = -1; tr.skytexturenum = -1;
tr.max_recursion = 0; tr.max_recursion = 0;
pglDisable( GL_FOG ); pglDisable( GL_FOG );

3
engine/client/gl_rpart.c

@ -674,9 +674,6 @@ void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, f
R_SetupRefParams( rvp ); R_SetupRefParams( rvp );
R_SetupFrustum(); R_SetupFrustum();
R_SetupGL( false ); // don't touch GL-states R_SetupGL( false ); // don't touch GL-states
// setup PVS for frame
memcpy( RI.visbytes, tr.visbytes, world.visbytes );
tr.frametime = frametime; tr.frametime = frametime;
if( trans_pass == false ) if( trans_pass == false )

6
engine/client/gl_rsurf.c

@ -204,7 +204,7 @@ void GL_SetupFogColorForSurfaces( void )
vec3_t fogColor; vec3_t fogColor;
float factor, div; float factor, div;
if( !pglIsEnabled( GL_FOG )) if( !glState.isFogEnabled )
return; return;
if( RI.currententity && RI.currententity->curstate.rendermode == kRenderTransTexture ) if( RI.currententity && RI.currententity->curstate.rendermode == kRenderTransTexture )
@ -224,7 +224,7 @@ void GL_SetupFogColorForSurfaces( void )
void GL_ResetFogColor( void ) void GL_ResetFogColor( void )
{ {
// restore fog here // restore fog here
if( pglIsEnabled( GL_FOG )) if( glState.isFogEnabled )
pglFogfv( GL_FOG_COLOR, RI.fogColor ); pglFogfv( GL_FOG_COLOR, RI.fogColor );
} }
@ -1081,7 +1081,7 @@ void R_RenderBrushPoly( msurface_t *fa, int cull_type )
if( CVAR_TO_BOOL( r_detailtextures )) if( CVAR_TO_BOOL( r_detailtextures ))
{ {
if( pglIsEnabled( GL_FOG )) if( glState.isFogEnabled )
{ {
// don't apply detail textures for windows in the fog // don't apply detail textures for windows in the fog
if( RI.currententity->curstate.rendermode != kRenderTransTexture ) if( RI.currententity->curstate.rendermode != kRenderTransTexture )

9
engine/client/gl_studio.c

@ -1553,8 +1553,6 @@ StudioCalcAttachments
static void R_StudioCalcAttachments( void ) static void R_StudioCalcAttachments( void )
{ {
mstudioattachment_t *pAtt; mstudioattachment_t *pAtt;
vec3_t forward, bonepos;
vec3_t localOrg, localAng;
int i; int i;
// calculate attachment points // calculate attachment points
@ -1563,11 +1561,6 @@ static void R_StudioCalcAttachments( void )
for( i = 0; i < Q_min( MAXSTUDIOATTACHMENTS, m_pStudioHeader->numattachments ); i++ ) for( i = 0; i < Q_min( MAXSTUDIOATTACHMENTS, m_pStudioHeader->numattachments ); i++ )
{ {
Matrix3x4_VectorTransform( g_studio.lighttransform[pAtt[i].bone], pAtt[i].org, RI.currententity->attachment[i] ); Matrix3x4_VectorTransform( g_studio.lighttransform[pAtt[i].bone], pAtt[i].org, RI.currententity->attachment[i] );
VectorSubtract( RI.currententity->attachment[i], RI.currententity->origin, localOrg );
Matrix3x4_OriginFromMatrix( g_studio.lighttransform[pAtt[i].bone], bonepos );
VectorSubtract( localOrg, bonepos, forward ); // make forward
VectorNormalizeFast( forward );
VectorAngles( forward, localAng );
} }
} }
@ -3803,7 +3796,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
ptexture->index = (int)((byte *)phdr) + ptexture->index; ptexture->index = (int)((byte *)phdr) + ptexture->index;
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768; size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768;
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ) && FBitSet( ptexture->flags, STUDIO_NF_MASKED )) if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && FBitSet( ptexture->flags, STUDIO_NF_MASKED ))
flags |= TF_KEEP_SOURCE; // Paranoia2 texture alpha-tracing flags |= TF_KEEP_SOURCE; // Paranoia2 texture alpha-tracing
// build the texname // build the texname

2
engine/client/gl_vidnt.c

@ -1772,7 +1772,7 @@ void GL_InitExtensions( void )
GL_CheckExtension( "GL_ARB_depth_texture", NULL, NULL, GL_DEPTH_TEXTURE ); GL_CheckExtension( "GL_ARB_depth_texture", NULL, NULL, GL_DEPTH_TEXTURE );
GL_CheckExtension( "GL_ARB_texture_float", NULL, "gl_texture_float", GL_ARB_TEXTURE_FLOAT_EXT ); GL_CheckExtension( "GL_ARB_texture_float", NULL, "gl_texture_float", GL_ARB_TEXTURE_FLOAT_EXT );
GL_CheckExtension( "GL_ARB_depth_buffer_float", NULL, "gl_texture_float", GL_ARB_DEPTH_FLOAT_EXT ); GL_CheckExtension( "GL_ARB_depth_buffer_float", NULL, "gl_texture_depth_float", GL_ARB_DEPTH_FLOAT_EXT );
GL_CheckExtension( "GL_EXT_gpu_shader4", NULL, NULL, GL_EXT_GPU_SHADER4 ); // don't confuse users GL_CheckExtension( "GL_EXT_gpu_shader4", NULL, NULL, GL_EXT_GPU_SHADER4 ); // don't confuse users
GL_CheckExtension( "GL_ARB_shading_language_100", NULL, NULL, GL_SHADER_GLSL100_EXT ); GL_CheckExtension( "GL_ARB_shading_language_100", NULL, NULL, GL_SHADER_GLSL100_EXT );

2
engine/common/avikit.c

@ -405,7 +405,7 @@ long AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, long offset, long l
for( i = 0; i < length; i++ ) for( i = 0; i < length; i++ )
audiodata[i] = 0; audiodata[i] = 0;
return length; // return length;
} }
} }

3
engine/common/cmd.c

@ -976,9 +976,8 @@ void Cmd_ExecuteString( char *text )
{ {
Cmd_ForwardToServer(); Cmd_ForwardToServer();
} }
else if( text[0] != '@' && Cvar_VariableInteger( "host_gameloaded" )) else if( Cvar_VariableInteger( "host_gameloaded" ))
{ {
// commands with leading '@' are hidden system commands
Con_Printf( S_WARN "Unknown command \"%s\"\n", text ); Con_Printf( S_WARN "Unknown command \"%s\"\n", text );
} }
} }

20
engine/common/common.c

@ -22,16 +22,16 @@ GNU General Public License for more details.
const char *file_exts[10] = const char *file_exts[10] =
{ {
".cfg", "cfg",
".lst", "lst",
".exe", "exe",
".vbs", "vbs",
".com", "com",
".bat", "bat",
".dll", "dll",
".ini", "ini",
".log", "log",
".sys", "sys",
}; };
#ifdef _DEBUG #ifdef _DEBUG

4
engine/common/common.h

@ -505,7 +505,7 @@ typically expanded to rgba buffer
NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 == PF_RGB_888 NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 == PF_RGB_888
======================================================================== ========================================================================
*/ */
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24) #define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2) #define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2)
typedef enum typedef enum
@ -517,6 +517,7 @@ typedef enum
PF_BGRA_32, // big endian RGBA (MacOS) PF_BGRA_32, // big endian RGBA (MacOS)
PF_RGB_24, // uncompressed dds or another 24-bit image PF_RGB_24, // uncompressed dds or another 24-bit image
PF_BGR_24, // big-endian RGB (MacOS) PF_BGR_24, // big-endian RGB (MacOS)
PF_LUMINANCE, // 8-bit single channel
PF_DXT1, // s3tc DXT1 format PF_DXT1, // s3tc DXT1 format
PF_DXT3, // s3tc DXT3 format PF_DXT3, // s3tc DXT3 format
PF_DXT5, // s3tc DXT5 format PF_DXT5, // s3tc DXT5 format
@ -891,7 +892,6 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
void SV_StartMusic( const char *curtrack, const char *looptrack, long position ); void SV_StartMusic( const char *curtrack, const char *looptrack, long position );
void SV_CreateDecal( struct sizebuf_s *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale ); void SV_CreateDecal( struct sizebuf_s *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
void Log_Printf( const char *fmt, ... ); void Log_Printf( const char *fmt, ... );
struct sizebuf_s *SV_GetReliableDatagram( void );
void SV_BroadcastCommand( const char *fmt, ... ); void SV_BroadcastCommand( const char *fmt, ... );
qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent ); qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
void SV_BroadcastPrintf( struct sv_client_s *ignore, char *fmt, ... ); void SV_BroadcastPrintf( struct sv_client_s *ignore, char *fmt, ... );

2
engine/common/console.c

@ -154,7 +154,7 @@ void Con_SetColor_f( void )
{ {
vec3_t color; vec3_t color;
switch( Cmd_Argc() ) switch( Cmd_Argc( ))
{ {
case 1: case 1:
Con_Printf( "\"con_color\" is %i %i %i\n", g_color_table[7][0], g_color_table[7][1], g_color_table[7][2] ); Con_Printf( "\"con_color\" is %i %i %i\n", g_color_table[7][0], g_color_table[7][1], g_color_table[7][2] );

2
engine/common/crclib.c

@ -229,7 +229,7 @@ qboolean CRC32_File( dword *crcvalue, const char *filename )
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer ) qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer )
{ {
char headbuf[256], buffer[1024]; char headbuf[1024], buffer[1024];
int i, num_bytes, lumplen; int i, num_bytes, lumplen;
int version, hdr_size; int version, hdr_size;
dheader_t *header; dheader_t *header;

4
engine/common/host.c

@ -31,6 +31,8 @@ sysinfo_t SI;
CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" ); CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" ); CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" );
convar_t *host_serverstate;
convar_t *host_gameloaded; convar_t *host_gameloaded;
convar_t *host_clientloaded; convar_t *host_clientloaded;
convar_t *host_limitlocal; convar_t *host_limitlocal;
@ -411,6 +413,7 @@ double Host_CalcFPS( void )
else else
{ {
fps = host_maxfps->value; fps = host_maxfps->value;
if( fps == 0.0 ) fps = MAX_FPS;
fps = bound( MIN_FPS, fps, MAX_FPS ); fps = bound( MIN_FPS, fps, MAX_FPS );
} }
@ -818,6 +821,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons"); Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
} }
host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" );
host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" ); host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" );
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" ); host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
host_gameloaded = Cvar_Get( "host_gameloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" ); host_gameloaded = Cvar_Get( "host_gameloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );

27
engine/common/imagelib/img_dds.c

@ -18,7 +18,6 @@ GNU General Public License for more details.
qboolean Image_CheckDXT3Alpha( dds_t *hdr, byte *fin ) qboolean Image_CheckDXT3Alpha( dds_t *hdr, byte *fin )
{ {
uint bitmask;
word sAlpha; word sAlpha;
byte *alpha; byte *alpha;
int x, y, i, j; int x, y, i, j;
@ -27,10 +26,8 @@ qboolean Image_CheckDXT3Alpha( dds_t *hdr, byte *fin )
{ {
for( x = 0; x < hdr->dwWidth; x += 4 ) for( x = 0; x < hdr->dwWidth; x += 4 )
{ {
alpha = fin; alpha = fin + 8;
fin += 8; fin += 16;
bitmask = ((uint *)fin)[1];
fin += 8;
for( j = 0; j < 4; j++ ) for( j = 0; j < 4; j++ )
{ {
@ -138,11 +135,21 @@ void Image_DXTGetPixelFormat( dds_t *hdr )
} }
else else
{ {
if( bits == 32 ) switch( bits )
{
case 32:
image.type = PF_BGRA_32; image.type = PF_BGRA_32;
else if( bits == 24 ) break;
case 24:
image.type = PF_BGR_24; image.type = PF_BGR_24;
else image.type = PF_UNKNOWN; // assume error; break;
case 8:
image.type = PF_LUMINANCE;
break;
default:
image.type = PF_UNKNOWN;
break;
}
} }
} }
@ -162,6 +169,7 @@ size_t Image_DXTGetLinearSize( int type, int width, int height, int depth )
case PF_DXT3: case PF_DXT3:
case PF_DXT5: case PF_DXT5:
case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 ); case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 );
case PF_LUMINANCE: return (width * height * depth);
case PF_BGR_24: case PF_BGR_24:
case PF_RGB_24: return (width * height * depth * 3); case PF_RGB_24: return (width * height * depth * 3);
case PF_BGRA_32: case PF_BGRA_32:
@ -314,6 +322,9 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, size_t filesize )
break; break;
} }
if( image.type == PF_LUMINANCE )
ClearBits( image.flags, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA );
if( header.dwReserved1[1] != 0 ) if( header.dwReserved1[1] != 0 )
{ {
// store texture reflectivity // store texture reflectivity

23
engine/common/imagelib/img_main.c

@ -72,17 +72,18 @@ static const cubepack_t load_cubemap[] =
// soul of ImageLib - table of image format constants // soul of ImageLib - table of image format constants
const bpc_desc_t PFDesc[] = const bpc_desc_t PFDesc[] =
{ {
{PF_UNKNOWN, "raw", 0x1908, 0 }, { PF_UNKNOWN, "raw", 0x1908, 0 },
{PF_INDEXED_24, "pal 24", 0x1908, 1 }, { PF_INDEXED_24, "pal 24", 0x1908, 1 },
{PF_INDEXED_32, "pal 32", 0x1908, 1 }, { PF_INDEXED_32, "pal 32", 0x1908, 1 },
{PF_RGBA_32, "RGBA 32",0x1908, 4 }, { PF_RGBA_32, "RGBA 32",0x1908, 4 },
{PF_BGRA_32, "BGRA 32",0x80E1, 4 }, { PF_BGRA_32, "BGRA 32",0x80E1, 4 },
{PF_RGB_24, "RGB 24", 0x1908, 3 }, { PF_RGB_24, "RGB 24", 0x1908, 3 },
{PF_BGR_24, "BGR 24", 0x80E0, 3 }, { PF_BGR_24, "BGR 24", 0x80E0, 3 },
{PF_DXT1, "DXT 1", 0x83F1, 4 }, { PF_LUMINANCE, "LUM 8", 0x1909, 1 },
{PF_DXT3, "DXT 3", 0x83F2, 4 }, { PF_DXT1, "DXT 1", 0x83F1, 4 },
{PF_DXT5, "DXT 5", 0x83F3, 4 }, { PF_DXT3, "DXT 3", 0x83F2, 4 },
{PF_ATI2, "ATI 2", 0x8837, 4 }, { PF_DXT5, "DXT 5", 0x83F3, 4 },
{ PF_ATI2, "ATI 2", 0x8837, 4 },
}; };
void Image_Reset( void ) void Image_Reset( void )

7
engine/common/imagelib/img_utils.c

@ -151,11 +151,16 @@ void Image_Init( void )
image.loadformats = load_game; image.loadformats = load_game;
image.saveformats = save_game; image.saveformats = save_game;
break; break;
default: // all other instances not using imagelib case HOST_DEDICATED:
image.cmd_flags = 0; image.cmd_flags = 0;
image.loadformats = load_game; image.loadformats = load_game;
image.saveformats = save_null; image.saveformats = save_null;
break; break;
default: // all other instances not using imagelib
image.cmd_flags = 0;
image.loadformats = load_null;
image.saveformats = save_null;
break;
} }
image.tempbuffer = NULL; image.tempbuffer = NULL;

3
engine/common/keys.c

@ -333,6 +333,9 @@ void Key_Unbindall_f( void )
if( keys[i].binding ) if( keys[i].binding )
Key_SetBinding( i, "" ); Key_SetBinding( i, "" );
} }
// set some defaults
Key_SetBinding( K_ESCAPE, "cancelselect" );
} }
/* /*

138
engine/common/mod_bmodel.c

@ -37,7 +37,7 @@ typedef struct leaflist_s
int count; int count;
int maxcount; int maxcount;
qboolean overflowed; qboolean overflowed;
short *list; int *list;
vec3_t mins, maxs; vec3_t mins, maxs;
int topnode; // for overflows where each leaf can't be stored individually int topnode; // for overflows where each leaf can't be stored individually
} leaflist_t; } leaflist_t;
@ -669,7 +669,7 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
Mod_BoxLeafnums Mod_BoxLeafnums
================== ==================
*/ */
static int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int listsize, int *topnode ) static int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *topnode )
{ {
leaflist_t ll; leaflist_t ll;
@ -700,7 +700,7 @@ is potentially visible
*/ */
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits ) qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits )
{ {
short leafList[MAX_BOX_LEAFS]; int leafList[MAX_BOX_LEAFS];
int i, count; int i, count;
if( !visbits || !mins || !maxs ) if( !visbits || !mins || !maxs )
@ -885,6 +885,59 @@ int Mod_SampleSizeForFace( msurface_t *surf )
return LM_SAMPLE_SIZE; return LM_SAMPLE_SIZE;
} }
/*
==================
Mod_GetFaceContents
determine face contents by name
==================
*/
static int Mod_GetFaceContents( const char *name )
{
if( !Q_strnicmp( name, "SKY", 3 ))
return CONTENTS_SKY;
if( name[0] == '!' || name[0] == '*' )
{
if( !Q_strnicmp( name + 1, "lava", 4 ))
return CONTENTS_LAVA;
else if( !Q_strnicmp( name + 1, "slime", 5 ))
return CONTENTS_SLIME;
return CONTENTS_WATER; // otherwise it's water
}
if( !Q_strnicmp( name, "water", 5 ))
return CONTENTS_WATER;
return CONTENTS_SOLID;
}
/*
==================
Mod_GetFaceContents
determine face contents by name
==================
*/
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge )
{
int lindex;
medge_t *edge;
lindex = mod->surfedges[surfedge];
if( lindex > 0 )
{
edge = &mod->edges[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
edge = &mod->edges[-lindex];
return &mod->vertexes[edge->v[1]];
}
}
/* /*
================== ==================
Mod_MakeNormalAxial Mod_MakeNormalAxial
@ -1067,6 +1120,66 @@ static void Mod_CalcSurfaceBounds( msurface_t *surf )
VectorAverage( surf->info->mins, surf->info->maxs, surf->info->origin ); VectorAverage( surf->info->mins, surf->info->maxs, surf->info->origin );
} }
/*
=================
Mod_CreateFaceBevels
=================
*/
static void Mod_CreateFaceBevels( msurface_t *surf )
{
vec3_t delta, edgevec;
byte *facebevel;
vec3_t faceNormal;
mvertex_t *v0, *v1;
int contents;
int i, size;
vec_t radius;
mfacebevel_t *fb;
if( surf->texinfo && surf->texinfo->texture )
contents = Mod_GetFaceContents( surf->texinfo->texture->name );
else contents = CONTENTS_SOLID;
size = sizeof( mfacebevel_t ) + surf->numedges * sizeof( mplane_t );
facebevel = (byte *)Mem_Calloc( loadmodel->mempool, size );
fb = (mfacebevel_t *)facebevel;
facebevel += sizeof( mfacebevel_t );
fb->edges = (mplane_t *)facebevel;
fb->numedges = surf->numedges;
fb->contents = contents;
surf->info->bevel = fb;
if( FBitSet( surf->flags, SURF_PLANEBACK ))
VectorNegate( surf->plane->normal, faceNormal );
else VectorCopy( surf->plane->normal, faceNormal );
// compute face origin and plane edges
for( i = 0; i < surf->numedges; i++ )
{
mplane_t *dest = &fb->edges[i];
v0 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + i );
v1 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + (i + 1) % surf->numedges );
VectorSubtract( v1->position, v0->position, edgevec );
CrossProduct( faceNormal, edgevec, dest->normal );
VectorNormalize( dest->normal );
dest->dist = DotProduct( dest->normal, v0->position );
dest->type = PlaneTypeForNormal( dest->normal );
VectorAdd( fb->origin, v0->position, fb->origin );
}
VectorScale( fb->origin, 1.0f / surf->numedges, fb->origin );
// compute face radius
for( i = 0; i < surf->numedges; i++ )
{
v0 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + i );
VectorSubtract( v0->position, fb->origin, delta );
radius = DotProduct( delta, delta );
fb->radius = Q_max( radius, fb->radius );
}
}
/* /*
================= =================
Mod_SetParent Mod_SetParent
@ -1519,7 +1632,7 @@ static void Mod_LoadEntities( dbspmodel_t *bmod )
{ {
byte *entpatch = NULL; byte *entpatch = NULL;
char token[MAX_TOKEN]; char token[MAX_TOKEN];
char wadstring[2048]; char wadstring[MAX_TOKEN];
string keyname; string keyname;
char *pfile; char *pfile;
@ -1527,7 +1640,7 @@ static void Mod_LoadEntities( dbspmodel_t *bmod )
{ {
char entfilename[MAX_QPATH]; char entfilename[MAX_QPATH];
long entpatchsize; long entpatchsize;
size_t ft1, ft2; long ft1, ft2;
// world is check for entfile too // world is check for entfile too
Q_strncpy( entfilename, loadmodel->name, sizeof( entfilename )); Q_strncpy( entfilename, loadmodel->name, sizeof( entfilename ));
@ -1818,6 +1931,8 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
for( i = 0; i < loadmodel->numtextures; i++ ) for( i = 0; i < loadmodel->numtextures; i++ )
{ {
int txFlags = 0;
if( in->dataofs[i] == -1 ) if( in->dataofs[i] == -1 )
{ {
// create default texture (some mods requires this) // create default texture (some mods requires this)
@ -1845,6 +1960,9 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
tx->width = mt->width; tx->width = mt->width;
tx->height = mt->height; tx->height = mt->height;
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mt->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
if( mt->offsets[0] > 0 ) if( mt->offsets[0] > 0 )
{ {
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
@ -1892,7 +2010,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( FS_FileExists( texpath, false )) if( FS_FileExists( texpath, false ))
{ {
tx->gl_texturenum = GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS ); tx->gl_texturenum = GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS|txFlags );
bmod->wadlist.wadusage[j]++; // this wad are really used bmod->wadlist.wadusage[j]++; // this wad are really used
break; break;
} }
@ -1908,13 +2026,12 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( custom_palette ) size += sizeof( short ) + 768; if( custom_palette ) size += sizeof( short ) + 768;
Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name ); Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name );
tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS ); tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS|txFlags );
} }
// if texture is completely missed // if texture is completely missed
if( !tx->gl_texturenum ) if( !tx->gl_texturenum )
{ {
if( host.type != HOST_DEDICATED )
Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name ); Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name );
tx->gl_texturenum = tr.defaultTexture; tx->gl_texturenum = tr.defaultTexture;
} }
@ -2210,6 +2327,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod )
Mod_CalcSurfaceBounds( out ); Mod_CalcSurfaceBounds( out );
Mod_CalcSurfaceExtents( out ); Mod_CalcSurfaceExtents( out );
Mod_CreateFaceBevels( out );
// grab the second sample to detect colored lighting // grab the second sample to detect colored lighting
if( test_lightsize > 0 && lightofs != -1 ) if( test_lightsize > 0 && lightofs != -1 )
@ -2830,7 +2948,7 @@ check lump for existing
*/ */
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize ) int Mod_CheckLump( const char *filename, const int lump, int *lumpsize )
{ {
file_t *f = FS_Open( filename, "rb", true ); file_t *f = FS_Open( filename, "rb", false );
byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )]; byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )];
size_t prefetch_size = sizeof( buffer ); size_t prefetch_size = sizeof( buffer );
dextrahdr_t *extrahdr; dextrahdr_t *extrahdr;
@ -2889,7 +3007,7 @@ reading random lump by user request
*/ */
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ) int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize )
{ {
file_t *f = FS_Open( filename, "rb", true ); file_t *f = FS_Open( filename, "rb", false );
byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )]; byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )];
size_t prefetch_size = sizeof( buffer ); size_t prefetch_size = sizeof( buffer );
dextrahdr_t *extrahdr; dextrahdr_t *extrahdr;

22
engine/common/mod_studio.c

@ -507,6 +507,8 @@ void Mod_StudioGetAttachment( const edict_t *e, int iAtt, float *origin, float *
{ {
mstudioattachment_t *pAtt; mstudioattachment_t *pAtt;
vec3_t angles2; vec3_t angles2;
matrix3x4 localPose;
matrix3x4 worldPose;
model_t *mod; model_t *mod;
mod = SV_ModelHandle( e->v.modelindex ); mod = SV_ModelHandle( e->v.modelindex );
@ -534,19 +536,15 @@ void Mod_StudioGetAttachment( const edict_t *e, int iAtt, float *origin, float *
pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, angles2, e->v.origin, e->v.controller, e->v.blending, pAtt->bone, e ); pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, angles2, e->v.origin, e->v.controller, e->v.blending, pAtt->bone, e );
// compute pos and angles Matrix3x4_LoadIdentity( localPose );
if( origin != NULL ) Matrix3x4_SetOrigin( localPose, pAtt->org[0], pAtt->org[1], pAtt->org[2] );
Matrix3x4_VectorTransform( studio_bones[pAtt->bone], pAtt->org, origin ); Matrix3x4_ConcatTransforms( worldPose, studio_bones[pAtt->bone], localPose );
if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ) && origin != NULL && angles != NULL ) if( origin != NULL ) // origin is used always
{ Matrix3x4_OriginFromMatrix( worldPose, origin );
vec3_t forward, bonepos;
Matrix3x4_OriginFromMatrix( studio_bones[pAtt->bone], bonepos ); if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ) && angles != NULL )
VectorSubtract( origin, bonepos, forward ); // make forward Matrix3x4_AnglesFromMatrix( worldPose, angles );
VectorNormalizeFast( forward );
VectorAngles( forward, angles );
}
} }
/* /*
@ -565,7 +563,7 @@ void Mod_GetBonePosition( const edict_t *e, int iBone, float *origin, float *ang
pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, e->v.angles, e->v.origin, e->v.controller, e->v.blending, iBone, e ); pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, e->v.angles, e->v.origin, e->v.controller, e->v.blending, iBone, e );
if( origin ) Matrix3x4_OriginFromMatrix( studio_bones[iBone], origin ); if( origin ) Matrix3x4_OriginFromMatrix( studio_bones[iBone], origin );
if( angles ) VectorAngles( studio_bones[iBone][0], angles ); // bone forward to angles if( angles ) Matrix3x4_AnglesFromMatrix( studio_bones[iBone], angles );
} }
/* /*

5
engine/common/model.c

@ -137,6 +137,11 @@ static void Mod_FreeModel( model_t *mod )
=============================================================================== ===============================================================================
*/ */
/*
================
Mod_Init
================
*/
void Mod_Init( void ) void Mod_Init( void )
{ {
com_studiocache = Mem_AllocPool( "Studio Cache" ); com_studiocache = Mem_AllocPool( "Studio Cache" );

7
engine/common/net_buffer.c

@ -214,11 +214,11 @@ void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits )
} }
} }
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned ) void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned )
{ {
if( bSigned ) if( bSigned )
MSG_WriteSBitLong( sb, (int)data, numbits ); MSG_WriteSBitLong( sb, data, numbits );
else MSG_WriteUBitLong( sb, data, numbits ); else MSG_WriteUBitLong( sb, (uint)data, numbits );
} }
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits ) qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
@ -616,7 +616,6 @@ void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa )
fa[2] = MSG_ReadBitAngle( sb, 16 ); fa[2] = MSG_ReadBitAngle( sb, 16 );
} }
long MSG_ReadLong( sizebuf_t *sb ) long MSG_ReadLong( sizebuf_t *sb )
{ {
return MSG_ReadSBitLong( sb, sizeof( long ) << 3 ); return MSG_ReadSBitLong( sb, sizeof( long ) << 3 );

2
engine/common/net_buffer.h

@ -73,7 +73,7 @@ void MSG_Clear( sizebuf_t *sb );
void MSG_WriteOneBit( sizebuf_t *sb, int nValue ); void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits ); void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits ); void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned ); void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned );
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits ); qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits );
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits ); void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits );
void MSG_WriteBitFloat( sizebuf_t *sb, float val ); void MSG_WriteBitFloat( sizebuf_t *sb, float val );

124
engine/common/net_encode.c

@ -308,7 +308,7 @@ delta_info_t *Delta_FindStruct( const char *name )
{ {
int i; int i;
if( !name || !name[0] ) if( !COM_CheckString( name ))
return NULL; return NULL;
for( i = 0; i < NUM_FIELDS( dt_info ); i++ ) for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
@ -427,8 +427,12 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags,
{ {
if( !Q_strcmp( pField->name, pName )) if( !Q_strcmp( pField->name, pName ))
{ {
Con_Reportf( "Delta_Add: %s->%s already existing\n", pStructName, pName ); // update existed field
return false; // field already exist pField->flags = flags;
pField->bits = bits;
pField->multiplier = mul;
pField->post_multiplier = post_mul;
return true;
} }
} }
@ -470,7 +474,7 @@ void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t *pFiel
Assert( pField != NULL ); Assert( pField != NULL );
if( !pField->name || !*pField->name ) if( !COM_CheckString( pField->name ))
return; // not initialized ? return; // not initialized ?
dt = Delta_FindStructByIndex( tableIndex ); dt = Delta_FindStructByIndex( tableIndex );
@ -526,10 +530,10 @@ void Delta_ParseTableField( sizebuf_t *msg )
if( MSG_ReadOneBit( msg )) if( MSG_ReadOneBit( msg ))
post_mul = MSG_ReadFloat( msg ); post_mul = MSG_ReadFloat( msg );
#if 0
// delta encoders it's already initialized on this machine (local game) // delta encoders it's already initialized on this machine (local game)
if( delta_init ) return; if( delta_init ) return;
#endif
// add field to table // add field to table
Delta_AddField( dt->pName, pName, flags, bits, mul, post_mul ); Delta_AddField( dt->pName, pName, flags, bits, mul, post_mul );
} }
@ -610,7 +614,6 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt
} }
// read delta-bits // read delta-bits
if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL )
{ {
Con_DPrintf( S_ERROR "Delta_ReadField: %s field bits argument is missing\n", pField->name ); Con_DPrintf( S_ERROR "Delta_ReadField: %s field bits argument is missing\n", pField->name );
@ -765,13 +768,8 @@ void Delta_InitFields( void )
Delta_ParseTable( &pfile, dt, encodeDll, encodeFunc ); Delta_ParseTable( &pfile, dt, encodeDll, encodeFunc );
} }
Mem_Free( afile ); Mem_Free( afile );
#if 0
// adding some required fields that user may forget or don't know how to specified
Delta_AddField( "event_t", "velocity[0]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
Delta_AddField( "event_t", "velocity[1]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
Delta_AddField( "event_t", "velocity[2]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
#endif
} }
void Delta_Init( void ) void Delta_Init( void )
@ -877,73 +875,18 @@ Delta_ClampIntegerField
prevent data to out of range prevent data to out of range
===================== =====================
*/ */
int Delta_ClampIntegerField( int iValue, qboolean bSigned, int bits ) int Delta_ClampIntegerField( delta_t *pField, int iValue, qboolean bSigned, int numbits )
{ {
switch( bits ) #ifdef _DEBUG
if( numbits < 32 && abs( iValue ) >= (uint)BIT( numbits ))
Msg( "%s %d overflow %d\n", pField->name, abs( iValue ), (uint)BIT( numbits ));
#endif
if( numbits < 32 )
{ {
case 1: int signbits = bSigned ? (numbits - 1) : numbits;
iValue = bound( 0, (byte)iValue, 1 ); int maxnum = BIT( signbits ) - 1;
break; int minnum = bSigned ? -maxnum : 0;
case 2: iValue = bound( minnum, iValue, maxnum );
if( bSigned ) iValue = bound( -2, (short)iValue, 1 );
else iValue = bound( 0, (word)iValue, 3 );
break;
case 3:
if( bSigned ) iValue = bound( -4, (short)iValue, 3 );
else iValue = bound( 0, (word)iValue, 7 );
break;
case 4:
if( bSigned ) iValue = bound( -8, (short)iValue, 7 );
else iValue = bound( 0, (word)iValue, 15 );
break;
case 5:
if( bSigned ) iValue = bound( -16, (short)iValue, 15 );
else iValue = bound( 0, (word)iValue, 31 );
break;
case 6:
if( bSigned ) iValue = bound( -32, (short)iValue, 31 );
else iValue = bound( 0, (word)iValue, 63 );
break;
case 7:
if( bSigned ) iValue = bound( -64, (short)iValue, 63 );
else iValue = bound( 0, (word)iValue, 127 );
break;
case 8:
if( bSigned ) iValue = bound( -128, (short)iValue, 127 );
else iValue = bound( 0, (word)iValue, 255 );
break;
case 9:
if( bSigned ) iValue = bound( -256, (short)iValue, 255 );
else iValue = bound( 0, (word)iValue, 511 );
break;
case 10:
if( bSigned ) iValue = bound( -512, (short)iValue, 511 );
else iValue = bound( 0, (word)iValue, 1023 );
break;
case 11:
if( bSigned ) iValue = bound( -1024, (short)iValue, 1023 );
else iValue = bound( 0, (word)iValue, 2047 );
break;
case 12:
if( bSigned ) iValue = bound( -2048, (short)iValue, 2047 );
else iValue = bound( 0, (word)iValue, 4095 );
break;
case 13:
if( bSigned ) iValue = bound( -4096, (short)iValue, 4095 );
else iValue = bound( 0, (word)iValue, 8191 );
break;
case 14:
if( bSigned ) iValue = bound( -8192, (short)iValue, 8191 );
else iValue = bound( 0, (word)iValue, 16383 );
break;
case 15:
if( bSigned ) iValue = bound( -16384, (short)iValue, 16383 );
else iValue = bound( 0, (word)iValue, 32767 );
break;
case 16:
if( bSigned ) iValue = bound( -32768, (short)iValue, 32767 );
else iValue = bound( 0, (word)iValue, 65535 );
break;
} }
return iValue; // clamped; return iValue; // clamped;
@ -985,8 +928,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
toF = *(byte *)((byte *)to + pField->offset ); toF = *(byte *)((byte *)to + pField->offset );
} }
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits ); fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier; if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
} }
@ -1003,8 +946,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
toF = *(word *)((byte *)to + pField->offset ); toF = *(word *)((byte *)to + pField->offset );
} }
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits ); fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier; if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
} }
@ -1021,8 +964,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
toF = *(uint *)((byte *)to + pField->offset ); toF = *(uint *)((byte *)to + pField->offset );
} }
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits ); fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier; if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
} }
@ -1158,21 +1101,21 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
if( pField->flags & DT_BYTE ) if( pField->flags & DT_BYTE )
{ {
iValue = *(byte *)((byte *)to + pField->offset ); iValue = *(byte *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_SHORT ) else if( pField->flags & DT_SHORT )
{ {
iValue = *(word *)((byte *)to + pField->offset ); iValue = *(word *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_INTEGER ) else if( pField->flags & DT_INTEGER )
{ {
iValue = *(uint *)((byte *)to + pField->offset ); iValue = *(uint *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits ); iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier; if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
@ -1180,6 +1123,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
{ {
flValue = *(float *)((byte *)to + pField->offset ); flValue = *(float *)((byte *)to + pField->offset );
iValue = (int)(flValue * pField->multiplier); iValue = (int)(flValue * pField->multiplier);
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_ANGLE ) else if( pField->flags & DT_ANGLE )
@ -1193,9 +1137,9 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
else if( pField->flags & DT_TIMEWINDOW_8 ) else if( pField->flags & DT_TIMEWINDOW_8 )
{ {
flValue = *(float *)((byte *)to + pField->offset ); flValue = *(float *)((byte *)to + pField->offset );
flTime = Q_rint( timebase * 100.0f ) - Q_rint(flValue * 100.0f); flTime = Q_rint( timebase * 100.0f ) - Q_rint( flValue * 100.0f );
iValue = (uint)abs( flTime ); iValue = (uint)abs( flTime );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_TIMEWINDOW_BIG ) else if( pField->flags & DT_TIMEWINDOW_BIG )
@ -1203,7 +1147,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
flValue = *(float *)((byte *)to + pField->offset ); flValue = *(float *)((byte *)to + pField->offset );
flTime = Q_rint( timebase * pField->multiplier ) - Q_rint( flValue * pField->multiplier ); flTime = Q_rint( timebase * pField->multiplier ) - Q_rint( flValue * pField->multiplier );
iValue = (uint)abs( flTime ); iValue = (uint)abs( flTime );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_STRING ) else if( pField->flags & DT_STRING )

6
engine/common/netchan.h

@ -58,10 +58,10 @@ GNU General Public License for more details.
// { // {
// byte (on/off) // byte (on/off)
// int (fragment id) // int (fragment id)
// short (startpos) // int (startpos)
// short (length) // int (length)
// } // }
#define HEADER_BYTES ( 8 + MAX_STREAMS * 9 ) #define HEADER_BYTES ( 8 + MAX_STREAMS * 13 )
// Pad this to next higher 16 byte boundary // Pad this to next higher 16 byte boundary
// This is the largest packet that can come in/out over the wire, before processing the header // This is the largest packet that can come in/out over the wire, before processing the header

2
engine/common/pm_local.h

@ -36,6 +36,8 @@ qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec
pmtrace_t PM_PlayerTraceExt( playermove_t *pm, vec3_t p1, vec3_t p2, int flags, int numents, physent_t *ents, int ignore_pe, pfnIgnore pmFilter ); pmtrace_t PM_PlayerTraceExt( playermove_t *pm, vec3_t p1, vec3_t p2, int flags, int numents, physent_t *ents, int ignore_pe, pfnIgnore pmFilter );
int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, pfnIgnore pmFilter ); int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, pfnIgnore pmFilter );
int PM_HullPointContents( hull_t *hull, int num, const vec3_t p ); int PM_HullPointContents( hull_t *hull, int num, const vec3_t p );
int PM_TruePointContents( playermove_t *pmove, const vec3_t p );
int PM_PointContents( playermove_t *pmove, const vec3_t p );
void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent ); void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent );
// //

210
engine/common/pm_surface.c

@ -16,84 +16,153 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "mathlib.h" #include "mathlib.h"
#include "pm_local.h" #include "pm_local.h"
#include "gl_local.h"
#define FRAC_EPSILON (1.0f / 32.0f)
typedef struct typedef struct
{ {
float fraction; float fraction;
int contents; int contents;
msurface_t *surface;
} linetrace_t; } linetrace_t;
/*
==============
fix_coord
converts the reletive tex coords to absolute
==============
*/
static uint fix_coord( vec_t in, uint width )
{
if( in > 0 ) return (uint)in % width;
return width - ((uint)fabs( in ) % width);
}
/*
=============
SampleMiptex
fence texture testing
=============
*/
int PM_SampleMiptex( const msurface_t *surf, const vec3_t point )
{
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int contents;
vec_t ds, dt;
byte *data;
int x, y;
mtexinfo_t *tx;
texture_t *mt;
rgbdata_t *src;
// fill the default contents
if( fb ) contents = fb->contents;
else contents = CONTENTS_SOLID;
if( !surf->texinfo || !surf->texinfo->texture )
return contents;
tx = surf->texinfo;
mt = tx->texture;
if( mt->name[0] != '{' )
return contents;
src = R_GetTexture( mt->gl_texturenum )->original;
if( !src ) return contents; // original doesn't kept
ds = DotProduct( point, tx->vecs[0] ) + tx->vecs[0][3];
dt = DotProduct( point, tx->vecs[1] ) + tx->vecs[1][3];
// convert ST to real pixels position
x = fix_coord( ds, mt->width - 1 );
y = fix_coord( dt, mt->height - 1 );
ASSERT( x >= 0 && y >= 0 );
data = src->buffer;
if( data[(mt->width * y) + x] == 255 )
return CONTENTS_EMPTY;
return CONTENTS_SOLID;
}
/* /*
================== ==================
PM_RecursiveSurfCheck PM_RecursiveSurfCheck
================== ==================
*/ */
msurface_t *PM_RecursiveSurfCheck( model_t *model, mnode_t *node, vec3_t p1, vec3_t p2 ) msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_t p2 )
{ {
float t1, t2, frac; float t1, t2, frac;
int side, ds, dt; int i, side;
mplane_t *plane;
msurface_t *surf; msurface_t *surf;
vec3_t mid; vec3_t mid;
int i; loc0:
if( node->contents < 0 ) if( node->contents < 0 )
return NULL; return NULL;
plane = node->plane; t1 = PlaneDiff( p1, node->plane );
t2 = PlaneDiff( p2, node->plane );
if( plane->type < 3 ) if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
{ {
t1 = p1[plane->type] - plane->dist; node = node->children[0];
t2 = p2[plane->type] - plane->dist; goto loc0;
} }
else
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{ {
t1 = DotProduct( plane->normal, p1 ) - plane->dist; node = node->children[1];
t2 = DotProduct( plane->normal, p2 ) - plane->dist; goto loc0;
} }
if( t1 >= 0.0f && t2 >= 0.0f ) side = (t1 < 0.0f);
return PM_RecursiveSurfCheck( model, node->children[0], p1, p2 );
if( t1 < 0.0f && t2 < 0.0f )
return PM_RecursiveSurfCheck( model, node->children[1], p1, p2 );
frac = t1 / ( t1 - t2 ); frac = t1 / ( t1 - t2 );
frac = bound( 0.0f, frac, 1.0f );
if( frac < 0.0f ) frac = 0.0f;
if( frac > 1.0f ) frac = 1.0f;
VectorLerp( p1, frac, p2, mid ); VectorLerp( p1, frac, p2, mid );
side = (t1 < 0.0f); if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
return surf;
// now this is weird.
surf = PM_RecursiveSurfCheck( model, node->children[side], p1, mid );
if( surf != NULL || ( t1 >= 0.0f && t2 >= 0.0f ) || ( t1 < 0.0f && t2 < 0.0f )) // walk through real faces
for( i = 0; i < node->numsurfaces; i++ )
{ {
return surf; msurface_t *surf = &mod->surfaces[node->firstsurface + i];
} mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
vec3_t delta;
surf = model->surfaces + node->firstsurface; if( !fb ) continue; // ???
for( i = 0; i < node->numsurfaces; i++, surf++ ) VectorSubtract( mid, fb->origin, delta );
{ if( DotProduct( delta, delta ) >= fb->radius )
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] ); continue; // no intersection
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] ) for( j = 0; j < fb->numedges; j++ )
{ {
int s = ds - surf->texturemins[0]; if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
int t = dt - surf->texturemins[1]; break; // outside the bounds
}
if( s <= surf->extents[0] && t <= surf->extents[1] ) if( j != fb->numedges )
continue; // we are outside the bounds of the facet
// hit the surface
contents = PM_SampleMiptex( surf, mid );
if( contents != CONTENTS_EMPTY )
return surf; return surf;
} return NULL; // through the fence
} }
return PM_RecursiveSurfCheck( model, node->children[side^1], mid, p2 ); return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 );
} }
/* /*
@ -160,32 +229,34 @@ PM_TestLine_r
optimized trace for light gathering optimized trace for light gathering
================== ==================
*/ */
int PM_TestLine_r( mnode_t *node, vec_t p1f, vec_t p2f, const vec3_t start, const vec3_t stop, linetrace_t *trace ) int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, const vec3_t start, const vec3_t stop, linetrace_t *trace )
{ {
float front, back; float front, back;
float frac, midf; float frac, midf;
int r, side; int i, r, side;
vec3_t mid; vec3_t mid;
loc0: loc0:
if( node->contents < 0 ) if( node->contents < 0 )
trace->contents = node->contents; {
// water, slime or lava interpret as empty
if( node->contents == CONTENTS_SOLID ) if( node->contents == CONTENTS_SOLID )
return CONTENTS_SOLID; return CONTENTS_SOLID;
if( node->contents == CONTENTS_SKY ) if( node->contents == CONTENTS_SKY )
return CONTENTS_SKY; return CONTENTS_SKY;
if( node->contents < 0 ) trace->fraction = 1.0f;
return CONTENTS_EMPTY; return CONTENTS_EMPTY;
}
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, node->plane ); back = PlaneDiff( stop, node->plane );
if( front >= -ON_EPSILON && back >= -ON_EPSILON ) if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
{ {
node = node->children[0]; node = node->children[0];
goto loc0; goto loc0;
} }
if( front < ON_EPSILON && back < ON_EPSILON ) if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{ {
node = node->children[1]; node = node->children[1];
goto loc0; goto loc0;
@ -198,15 +269,54 @@ loc0:
VectorLerp( start, frac, stop, mid ); VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac; midf = p1f + ( p2f - p1f ) * frac;
r = PM_TestLine_r( node->children[side], p1f, midf, start, mid, trace ); r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace );
if( r != CONTENTS_EMPTY ) if( r != CONTENTS_EMPTY )
{ {
if( trace->surface == NULL )
trace->fraction = midf; trace->fraction = midf;
trace->contents = r;
return r; return r;
} }
return PM_TestLine_r( node->children[!side], midf, p2f, mid, stop, trace ); // walk through real faces
for( i = 0; i < node->numsurfaces; i++ )
{
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
vec3_t delta;
if( !fb ) continue;
VectorSubtract( mid, fb->origin, delta );
if( DotProduct( delta, delta ) >= fb->radius )
continue; // no intersection
for( j = 0; j < fb->numedges; j++ )
{
if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
break; // outside the bounds
}
if( j != fb->numedges )
continue; // we are outside the bounds of the facet
// hit the surface
contents = PM_SampleMiptex( surf, mid );
// fill the trace and out
trace->contents = contents;
trace->fraction = midf;
if( contents != CONTENTS_EMPTY )
trace->surface = surf;
return contents;
}
return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace );
} }
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags ) int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )
@ -221,18 +331,19 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
trace.contents = CONTENTS_EMPTY; trace.contents = CONTENTS_EMPTY;
trace.fraction = 1.0f; trace.fraction = 1.0f;
trace.surface = NULL;
for( i = 0; i < numents; i++ ) for( i = 0; i < numents; i++ )
{ {
pe = &ents[i]; pe = &ents[i];
if( i != 0 && ( flags & PM_WORLD_ONLY )) if( i != 0 && FBitSet( flags, PM_WORLD_ONLY ))
break; break;
if( !pe->model || pe->model->type != mod_brush || pe->solid != SOLID_BSP ) if( !pe->model || pe->model->type != mod_brush || pe->solid != SOLID_BSP )
continue; continue;
if( pe->rendermode != kRenderNormal ) if( FBitSet( flags, PM_GLASS_IGNORE ) && pe->rendermode != kRenderNormal )
continue; continue;
hull = &pe->model->hulls[0]; hull = &pe->model->hulls[0];
@ -257,8 +368,9 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
trace_bbox.contents = CONTENTS_EMPTY; trace_bbox.contents = CONTENTS_EMPTY;
trace_bbox.fraction = 1.0f; trace_bbox.fraction = 1.0f;
trace_bbox.surface = NULL;
PM_TestLine_r( &pe->model->nodes[hull->firstclipnode], 0.0f, 1.0f, start_l, end_l, &trace_bbox ); PM_TestLine_r( pe->model, &pe->model->nodes[hull->firstclipnode], 0.0f, 1.0f, start_l, end_l, &trace_bbox );
if( trace_bbox.contents != CONTENTS_EMPTY || trace_bbox.fraction < trace.fraction ) if( trace_bbox.contents != CONTENTS_EMPTY || trace_bbox.fraction < trace.fraction )
{ {

78
engine/common/pm_trace.c

@ -651,3 +651,81 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
return -1; // didn't hit anything return -1; // didn't hit anything
} }
/*
=============
PM_TruePointContents
=============
*/
int PM_TruePointContents( playermove_t *pmove, const vec3_t p )
{
hull_t *hull = &pmove->physents[0].model->hulls[0];
if( hull )
{
return PM_HullPointContents( hull, hull->firstclipnode, p );
}
else
{
return CONTENTS_EMPTY;
}
}
/*
=============
PM_PointContents
=============
*/
int PM_PointContents( playermove_t *pmove, const vec3_t p )
{
int i, contents;
hull_t *hull;
vec3_t test;
physent_t *pe;
// sanity check
if( !p || !pmove->physents[0].model )
return CONTENTS_NONE;
// get base contents from world
contents = PM_HullPointContents( &pmove->physents[0].model->hulls[0], 0, p );
for( i = 1; i < pmove->numphysent; i++ )
{
pe = &pmove->physents[i];
if( pe->solid != SOLID_NOT ) // disabled ?
continue;
// only brushes can have special contents
if( !pe->model ) continue;
// check water brushes accuracy
hull = &pe->model->hulls[0];
if( FBitSet( pe->model->flags, MODEL_HAS_ORIGIN ) && !VectorIsNull( pe->angles ))
{
matrix4x4 matrix;
Matrix4x4_CreateFromEntity( matrix, pe->angles, pe->origin, 1.0f );
Matrix4x4_VectorITransform( matrix, p, test );
}
else
{
// offset the test point appropriately for this hull.
VectorSubtract( p, pe->origin, test );
}
// test hull for intersection with this model
if( PM_HullPointContents( hull, hull->firstclipnode, test ) == CONTENTS_EMPTY )
continue;
// compare contents ranking
if( RankForContents( pe->skin ) > RankForContents( contents ))
contents = pe->skin; // new content has more priority
}
return contents;
}

2
engine/common/zone.c

@ -269,7 +269,7 @@ void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline )
Sys_Error( "Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline ); Sys_Error( "Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );
} }
if( *((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 ) if( *((byte *)mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 )
{ {
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
Sys_Error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline ); Sys_Error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );

2
engine/server/server.h

@ -263,7 +263,6 @@ typedef struct sv_client_s
a program error, like an overflowed reliable buffer a program error, like an overflowed reliable buffer
============================================================================= =============================================================================
*/ */
// MAX_CHALLENGES is made large to prevent a denial // MAX_CHALLENGES is made large to prevent a denial
// of service attack that could cycle all of them // of service attack that could cycle all of them
// out before legitimate users connected // out before legitimate users connected
@ -457,6 +456,7 @@ void SV_ProcessFile( sv_client_t *cl, const char *filename );
void SV_SendResource( resource_t *pResource, sizebuf_t *msg ); void SV_SendResource( resource_t *pResource, sizebuf_t *msg );
void SV_SendResourceList( sv_client_t *cl ); void SV_SendResourceList( sv_client_t *cl );
void SV_AddToMaster( netadr_t from, sizebuf_t *msg ); void SV_AddToMaster( netadr_t from, sizebuf_t *msg );
void Host_SetServerState( int state );
qboolean SV_IsSimulating( void ); qboolean SV_IsSimulating( void );
qboolean SV_InitGame( void ); qboolean SV_InitGame( void );
void SV_FreeClients( void ); void SV_FreeClients( void );

5
engine/server/sv_cmds.c

@ -16,6 +16,8 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "server.h" #include "server.h"
extern convar_t *con_gamemaps;
/* /*
================= =================
SV_ClientPrintf SV_ClientPrintf
@ -282,7 +284,7 @@ void SV_NextMap_f( void )
int i, next; int i, next;
search_t *t; search_t *t;
t = FS_Search( "maps/*.bsp", true, true ); // only in gamedir t = FS_Search( "maps\\*.bsp", true, CVAR_TO_BOOL( con_gamemaps )); // only in gamedir
if( !t ) if( !t )
{ {
Con_Printf( "next map can't be found\n" ); Con_Printf( "next map can't be found\n" );
@ -869,6 +871,7 @@ void SV_EntityInfo_f( void )
Con_Printf( "\n" ); Con_Printf( "\n" );
} }
} }
/* /*
================== ==================
SV_InitHostCommands SV_InitHostCommands

23
engine/server/sv_frame.c

@ -155,7 +155,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
if( fullvis ) continue; // portal ents will be added anyway, ignore recursion if( fullvis ) continue; // portal ents will be added anyway, ignore recursion
// if its a portal entity, add everything visible from its camera position // if it's a portal entity, add everything visible from its camera position
if( from_client && FBitSet( ent->v.effects, EF_MERGE_VISIBILITY )) if( from_client && FBitSet( ent->v.effects, EF_MERGE_VISIBILITY ))
{ {
SetBits( sv.hostflags, SVF_MERGE_VISIBILITY ); SetBits( sv.hostflags, SVF_MERGE_VISIBILITY );
@ -809,33 +809,18 @@ void SV_UpdateToReliableMessages( void )
continue; // reliables go to all connected or spawned continue; // reliables go to all connected or spawned
if( MSG_GetNumBytesWritten( &sv.reliable_datagram ) < MSG_GetNumBytesLeft( &cl->netchan.message )) if( MSG_GetNumBytesWritten( &sv.reliable_datagram ) < MSG_GetNumBytesLeft( &cl->netchan.message ))
{
MSG_WriteBits( &cl->netchan.message, MSG_GetBuf( &sv.reliable_datagram ), MSG_GetNumBitsWritten( &sv.reliable_datagram )); MSG_WriteBits( &cl->netchan.message, MSG_GetBuf( &sv.reliable_datagram ), MSG_GetNumBitsWritten( &sv.reliable_datagram ));
} else Netchan_CreateFragments( &cl->netchan, &sv.reliable_datagram );
else
{
Netchan_CreateFragments( &cl->netchan, &sv.reliable_datagram );
}
if( MSG_GetNumBytesWritten( &sv.datagram ) < MSG_GetNumBytesLeft( &cl->datagram )) if( MSG_GetNumBytesWritten( &sv.datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
{
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.datagram ), MSG_GetNumBitsWritten( &sv.datagram )); MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.datagram ), MSG_GetNumBitsWritten( &sv.datagram ));
} else Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name );
else
{
Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name );
}
if( FBitSet( cl->flags, FCL_HLTV_PROXY )) if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
{ {
if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram )) if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
{
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.spec_datagram ), MSG_GetNumBitsWritten( &sv.spec_datagram )); MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.spec_datagram ), MSG_GetNumBitsWritten( &sv.spec_datagram ));
} else Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name );
else
{
Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name );
}
} }
} }

32
engine/server/sv_game.c

@ -752,8 +752,8 @@ Create entity patch for selected map
*/ */
void SV_WriteEntityPatch( const char *filename ) void SV_WriteEntityPatch( const char *filename )
{ {
int ver = -1, lumpofs = 0, lumplen = 0; int lumpofs = 0, lumplen = 0;
byte buf[MAX_SYSPATH]; // 1 kb byte buf[MAX_TOKEN]; // 1 kb
string bspfilename; string bspfilename;
dheader_t *header; dheader_t *header;
file_t *f; file_t *f;
@ -762,8 +762,8 @@ void SV_WriteEntityPatch( const char *filename )
f = FS_Open( bspfilename, "rb", false ); f = FS_Open( bspfilename, "rb", false );
if( !f ) return; if( !f ) return;
memset( buf, 0, MAX_SYSPATH ); memset( buf, 0, MAX_TOKEN );
FS_Read( f, buf, MAX_SYSPATH ); FS_Read( f, buf, MAX_TOKEN );
header = (dheader_t *)buf; header = (dheader_t *)buf;
// check all the lumps and some other errors // check all the lumps and some other errors
@ -801,9 +801,9 @@ pfnMapIsValid use this
static char *SV_ReadEntityScript( const char *filename, int *flags ) static char *SV_ReadEntityScript( const char *filename, int *flags )
{ {
string bspfilename, entfilename; string bspfilename, entfilename;
int ver = -1, lumpofs = 0, lumplen = 0; int lumpofs = 0, lumplen = 0;
byte buf[MAX_TOKEN];
char *ents = NULL; char *ents = NULL;
byte buf[1024];
dheader_t *header; dheader_t *header;
size_t ft1, ft2; size_t ft1, ft2;
file_t *f; file_t *f;
@ -815,8 +815,8 @@ static char *SV_ReadEntityScript( const char *filename, int *flags )
if( !f ) return NULL; if( !f ) return NULL;
SetBits( *flags, MAP_IS_EXIST ); SetBits( *flags, MAP_IS_EXIST );
memset( buf, 0, MAX_SYSPATH ); memset( buf, 0, MAX_TOKEN );
FS_Read( f, buf, MAX_SYSPATH ); FS_Read( f, buf, MAX_TOKEN );
header = (dheader_t *)buf; header = (dheader_t *)buf;
// check all the lumps and some other errors // check all the lumps and some other errors
@ -834,7 +834,7 @@ static char *SV_ReadEntityScript( const char *filename, int *flags )
// check for entfile too // check for entfile too
Q_strncpy( entfilename, va( "maps/%s.ent", filename ), sizeof( entfilename )); Q_strncpy( entfilename, va( "maps/%s.ent", filename ), sizeof( entfilename ));
// make sure what entity patch is never than bsp // make sure what entity patch is newer than bsp
ft1 = FS_FileTime( bspfilename, false ); ft1 = FS_FileTime( bspfilename, false );
ft2 = FS_FileTime( entfilename, true ); ft2 = FS_FileTime( entfilename, true );
@ -875,7 +875,7 @@ int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *l
if( ents ) if( ents )
{ {
qboolean need_landmark = Q_strlen( landmark_name ) > 0 ? true : false; qboolean need_landmark = Q_strlen( landmark_name ) > 0 ? true : false;
char token[2048]; char token[MAX_TOKEN];
string check_name; string check_name;
// g-cont. in-dev mode we can entering on map even without "info_player_start" // g-cont. in-dev mode we can entering on map even without "info_player_start"
@ -1280,6 +1280,7 @@ pfnSetModel
void pfnSetModel( edict_t *e, const char *m ) void pfnSetModel( edict_t *e, const char *m )
{ {
char name[MAX_QPATH]; char name[MAX_QPATH];
qboolean found = false;
model_t *mod; model_t *mod;
int i; int i;
@ -1296,10 +1297,13 @@ void pfnSetModel( edict_t *e, const char *m )
for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ ) for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ )
{ {
if( !Q_stricmp( sv.model_precache[i], name )) if( !Q_stricmp( sv.model_precache[i], name ))
{
found = true;
break; break;
} }
}
if( i == MAX_MODELS ) if( !found )
{ {
Con_Printf( S_ERROR "no precache: %s\n", name ); Con_Printf( S_ERROR "no precache: %s\n", name );
return; return;
@ -2780,7 +2784,7 @@ void pfnWriteString( const char *src )
{ {
static char string[MAX_USERMSG_LENGTH]; static char string[MAX_USERMSG_LENGTH];
int len = Q_strlen( src ) + 1; int len = Q_strlen( src ) + 1;
int rem = rem = sizeof( string ) - 1; int rem = sizeof( string ) - 1;
char *dst; char *dst;
if( len == 1 ) if( len == 1 )
@ -4518,7 +4522,7 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent )
// keynames with a leading underscore are used for // keynames with a leading underscore are used for
// utility comments and are immediately discarded by engine // utility comments and are immediately discarded by engine
if( keyname[0] == '_' && Q_strcmp( keyname, "_light" )) if( FBitSet( world.flags, FWORLD_SKYSPHERE ) && keyname[0] == '_' )
continue; continue;
// ignore attempts to set value "" // ignore attempts to set value ""
@ -4621,7 +4625,7 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent )
Mem_Free( pkvd[i].szValue ); Mem_Free( pkvd[i].szValue );
} }
if( classname ) if( classname && Mem_IsAllocatedExt( host.mempool, classname ))
Mem_Free( classname ); Mem_Free( classname );
return true; return true;

23
engine/server/sv_init.c

@ -135,7 +135,6 @@ int SV_SoundIndex( const char *filename )
char name[MAX_QPATH]; char name[MAX_QPATH];
int i; int i;
// don't precache sentence names!
if( !COM_CheckString( filename )) if( !COM_CheckString( filename ))
return 0; return 0;
@ -263,7 +262,7 @@ int SV_GenericIndex( const char *filename )
================ ================
SV_ModelHandle SV_ModelHandle
register unique model for a server and client get model by handle
================ ================
*/ */
model_t *SV_ModelHandle( int modelindex ) model_t *SV_ModelHandle( int modelindex )
@ -273,6 +272,13 @@ model_t *SV_ModelHandle( int modelindex )
return sv.models[modelindex]; return sv.models[modelindex];
} }
/*
================
SV_CreateGenericResources
loads external resource list
================
*/
void SV_CreateGenericResources( void ) void SV_CreateGenericResources( void )
{ {
string filename, token; string filename, token;
@ -303,6 +309,13 @@ void SV_CreateGenericResources( void )
Mem_Free( afile ); Mem_Free( afile );
} }
/*
================
SV_CreateResourceList
add resources to common list
================
*/
void SV_CreateResourceList( void ) void SV_CreateResourceList( void )
{ {
qboolean ffirstsent = false; qboolean ffirstsent = false;
@ -571,7 +584,7 @@ void SV_ActivateServer( int runPhysics )
Mod_FreeUnused (); Mod_FreeUnused ();
host.movevars_changed = true; host.movevars_changed = true;
sv.state = ss_active; Host_SetServerState( ss_active );
Con_DPrintf( "level loaded at %.2f sec\n", Sys_DoubleTime() - svs.timestart ); Con_DPrintf( "level loaded at %.2f sec\n", Sys_DoubleTime() - svs.timestart );
@ -609,7 +622,7 @@ void SV_DeactivateServer( void )
svgame.globals->time = sv.time; svgame.globals->time = sv.time;
svgame.dllFuncs.pfnServerDeactivate(); svgame.dllFuncs.pfnServerDeactivate();
sv.state = ss_dead; Host_SetServerState( ss_dead );
SV_FreeEdicts (); SV_FreeEdicts ();
@ -821,7 +834,7 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
COM_FileBase( mapname, sv.name ); COM_FileBase( mapname, sv.name );
// precache and static commands can be issued during map initialization // precache and static commands can be issued during map initialization
sv.state = ss_loading; Host_SetServerState( ss_loading );
if( startspot ) if( startspot )
Q_strncpy( sv.startspot, startspot, sizeof( sv.startspot )); Q_strncpy( sv.startspot, startspot, sizeof( sv.startspot ));

31
engine/server/sv_main.c

@ -152,6 +152,9 @@ send updates to client if changed
*/ */
void SV_UpdateMovevars( qboolean initialize ) void SV_UpdateMovevars( qboolean initialize )
{ {
if( sv.state == ss_dead )
return;
if( !initialize && !host.movevars_changed ) if( !initialize && !host.movevars_changed )
return; return;
@ -260,6 +263,13 @@ void SV_CheckCmdTimes( void )
} }
} }
/*
=================
SV_ProcessFile
process incoming file (customization)
=================
*/
void SV_ProcessFile( sv_client_t *cl, const char *filename ) void SV_ProcessFile( sv_client_t *cl, const char *filename )
{ {
customization_t *pList; customization_t *pList;
@ -548,11 +558,6 @@ qboolean SV_IsSimulating( void )
return false; return false;
} }
/*
=================
SV_RunGameFrame
=================
*/
/* /*
================= =================
SV_RunGameFrame SV_RunGameFrame
@ -638,6 +643,17 @@ void Host_ServerFrame( void )
Master_Heartbeat (); Master_Heartbeat ();
} }
/*
==================
Host_SetServerState
==================
*/
void Host_SetServerState( int state )
{
Cvar_FullSet( "host_serverstate", va( "%i", state ), FCVAR_READ_ONLY );
sv.state = state;
}
//============================================================================ //============================================================================
/* /*
@ -874,7 +890,7 @@ to totally exit after returning from this function.
*/ */
void SV_FinalMessage( const char *message, qboolean reconnect ) void SV_FinalMessage( const char *message, qboolean reconnect )
{ {
byte msg_buf[64]; byte msg_buf[1024];
sv_client_t *cl; sv_client_t *cl;
sizebuf_t msg; sizebuf_t msg;
int i; int i;
@ -981,6 +997,9 @@ void SV_Shutdown( const char *finalmsg )
SV_FreeClients(); SV_FreeClients();
svs.maxclients = 0; svs.maxclients = 0;
// release all models
Mod_FreeAll();
HPAK_FlushHostQueue(); HPAK_FlushHostQueue();
Log_Printf( "Server shutdown\n" ); Log_Printf( "Server shutdown\n" );
Log_Close(); Log_Close();

28
engine/server/sv_pmove.c

@ -79,7 +79,7 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
else if( FBitSet( ed->v.flags, FL_CLIENT )) else if( FBitSet( ed->v.flags, FL_CLIENT ))
{ {
// client // client
SV_GetTrueOrigin( &svs.clients[pe->info - 1], pe->info, pe->origin ); SV_GetTrueOrigin( sv.current_client, pe->info, pe->origin );
Q_strncpy( pe->name, "player", sizeof( pe->name )); Q_strncpy( pe->name, "player", sizeof( pe->name ));
pe->player = pe->info; pe->player = pe->info;
} }
@ -304,7 +304,7 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3
model_t *mod; model_t *mod;
physent_t *pe; physent_t *pe;
// get water edicts // get ladder edicts
for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next ) for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next )
{ {
next = l->next; next = l->next;
@ -339,6 +339,11 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3
SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs ); SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs );
} }
int SV_TestLine( const vec3_t start, const vec3_t end, int flags )
{
return PM_TestLineExt( svgame.pmove, svgame.pmove->physents, svgame.pmove->numphysent, start, end, flags );
}
static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace ) static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
{ {
return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL ); return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL );
@ -367,7 +372,7 @@ static int pfnPointContents( float *p, int *truecontents )
{ {
int cont, truecont; int cont, truecont;
truecont = cont = SV_TruePointContents( p ); truecont = cont = PM_PointContents( svgame.pmove, p );
if( truecontents ) *truecontents = truecont; if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN ) if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
@ -377,7 +382,7 @@ static int pfnPointContents( float *p, int *truecontents )
static int pfnTruePointContents( float *p ) static int pfnTruePointContents( float *p )
{ {
return SV_TruePointContents( p ); return PM_TruePointContents( svgame.pmove, p );
} }
static int pfnHullPointContents( struct hull_s *hull, int num, float *p ) static int pfnHullPointContents( struct hull_s *hull, int num, float *p )
@ -755,11 +760,11 @@ static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl )
if( pmove->onground == -1 ) if( pmove->onground == -1 )
{ {
clent->v.flags &= ~FL_ONGROUND; ClearBits( clent->v.flags, FL_ONGROUND );
} }
else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent ) else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent )
{ {
clent->v.flags |= FL_ONGROUND; SetBits( clent->v.flags, FL_ONGROUND );
clent->v.groundentity = EDICT_NUM( pmove->physents[pmove->onground].info ); clent->v.groundentity = EDICT_NUM( pmove->physents[pmove->onground].info );
} }
@ -880,10 +885,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
if( SV_UnlagCheckTeleport( state->origin, lerp->finalpos )) if( SV_UnlagCheckTeleport( state->origin, lerp->finalpos ))
lerp->nointerp = true; lerp->nointerp = true;
} }
else else lerp->firstframe = true;
{
lerp->firstframe = true;
}
VectorCopy( state->origin, lerp->finalpos ); VectorCopy( state->origin, lerp->finalpos );
} }
@ -981,10 +983,10 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
oldlerp = &svgame.interp[i]; oldlerp = &svgame.interp[i];
if( VectorCompare( oldlerp->oldpos, oldlerp->newpos ) || !oldlerp->moving ) if( VectorCompareEpsilon( oldlerp->oldpos, oldlerp->newpos, ON_EPSILON ))
continue; // they didn't actually move. continue; // they didn't actually move.
if( !oldlerp->active ) if( !oldlerp->moving || !oldlerp->active )
continue; continue;
if( VectorCompare( oldlerp->curpos, check->edict->v.origin )) if( VectorCompare( oldlerp->curpos, check->edict->v.origin ))
@ -1034,9 +1036,7 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
} }
if( !FBitSet( cl->flags, FCL_FAKECLIENT )) if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
{
SV_SetupMoveInterpolant( cl ); SV_SetupMoveInterpolant( cl );
}
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed ); svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed );

1
engine/server/sv_world.c

@ -1113,6 +1113,7 @@ or custom physics implementation
*/ */
void SV_CustomClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace ) void SV_CustomClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace )
{ {
// initialize custom trace
memset( trace, 0, sizeof( trace_t )); memset( trace, 0, sizeof( trace_t ));
VectorCopy( end, trace->endpos ); VectorCopy( end, trace->endpos );
trace->allsolid = true; trace->allsolid = true;

Loading…
Cancel
Save