22 Nov 2016

This commit is contained in:
g-cont 2016-11-22 00:00:00 +03:00 committed by Alibek Omarov
parent 91b1f6c082
commit 096f37c189
58 changed files with 1109 additions and 1964 deletions

View File

@ -169,7 +169,7 @@ typedef struct mleaf_s
msurface_t **firstmarksurface;
int nummarksurfaces;
byte *compressed_pas;
int cluster; // helper to acess to uncompressed visdata
byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t;

View File

@ -50,6 +50,8 @@
#define FL_ONTRAIN (1<<24) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction.
#define FL_WORLDBRUSH (1<<25) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something)
#define FL_SPECTATOR (1<<26) // This client is a spectator, don't run touch functions, etc.
#define FL_CUSTOMVIEW (1<<27) // Entity has a custom viewing from specified point (trigger_camera, portal, monitor etc)
#define FL_CUSTOMENTITY (1<<29) // This is a custom entity
#define FL_KILLME (1<<30) // This entity is marked for death -- This allows the engine to kill ents at the appropriate time
#define FL_DORMANT (1<<31) // Entity is dormant, no updates to client

View File

@ -176,11 +176,13 @@ typedef struct clientdata_s
#include "weaponinfo.h"
#define MAX_LOCAL_WEAPONS 64 // max weapons that can be predicted on the client
typedef struct local_state_s
{
entity_state_t playerstate;
clientdata_t client;
weapon_data_t weapondata[64];
weapon_data_t weapondata[MAX_LOCAL_WEAPONS];
} local_state_t;
#endif//ENTITY_STATE_H

View File

@ -71,7 +71,7 @@ typedef struct frame_s
clientdata_t client; // local client private data
entity_state_t playerstate[MAX_CLIENTS];
weapon_data_t weapondata[64];
weapon_data_t weapondata[MAX_LOCAL_WEAPONS];
netbandwidthgraph_t graphdata;
int num_entities;

View File

@ -76,7 +76,7 @@ void GL_BackendEndFrame( void )
break;
case 2:
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "visible leafs:\n%3i leafs\ncurrent leaf %3i",
r_stats.c_world_leafs, r_viewleaf - cl.worldmodel->leafs );
r_stats.c_world_leafs, Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes ) - cl.worldmodel->leafs );
break;
case 3:
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i studio models drawn\n%3i sprites drawn",

View File

@ -114,6 +114,8 @@ typedef struct
int viewport[4];
mplane_t frustum[6];
mleaf_t *viewleaf;
mleaf_t *oldviewleaf;
vec3_t pvsorigin;
vec3_t vieworg; // locked vieworigin
vec3_t vforward;
@ -151,6 +153,8 @@ typedef struct
int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536
float lightcache[MAX_LIGHTSTYLES];
byte visbytes[(MAX_MAP_LEAFS+7)/8];// actual PVS for current frame
float viewplanedist;
mplane_t clipPlane;
} ref_instance_t;

View File

@ -290,10 +290,6 @@ void R_DrawMirrors( void )
VectorCopy( origin, RI.pvsorigin );
// combine two leafs from client and mirror views
r_viewleaf = Mod_PointInLeaf( oldRI.pvsorigin, cl.worldmodel->nodes );
r_viewleaf2 = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );
if( GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
{
// allow screen size
@ -340,7 +336,6 @@ void R_DrawMirrors( void )
tr.mirror_entities[i].ent = NULL;
}
r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame
tr.framecount = oldframecount; // restore real framecount
tr.num_mirror_entities = 0;
tr.num_mirrors_used = 0;

View File

@ -30,9 +30,6 @@ float gldepthmin, gldepthmax;
ref_params_t r_lastRefdef;
ref_instance_t RI, prevRI;
mleaf_t *r_viewleaf, *r_oldviewleaf;
mleaf_t *r_viewleaf2, *r_oldviewleaf2;
static int R_RankForRenderMode( cl_entity_t *ent )
{
switch( ent->curstate.rendermode )
@ -745,35 +742,8 @@ R_FindViewLeaf
*/
void R_FindViewLeaf( void )
{
float height;
mleaf_t *leaf;
vec3_t tmp;
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
leaf = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );
r_viewleaf2 = r_viewleaf = leaf;
height = RI.waveHeight ? RI.waveHeight : 16;
// check above and below so crossing solid water doesn't draw wrong
if( leaf->contents == CONTENTS_EMPTY )
{
// look down a bit
VectorCopy( RI.pvsorigin, tmp );
tmp[2] -= height;
leaf = Mod_PointInLeaf( tmp, cl.worldmodel->nodes );
if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 ))
r_viewleaf2 = leaf;
}
else
{
// look up a bit
VectorCopy( RI.pvsorigin, tmp );
tmp[2] += height;
leaf = Mod_PointInLeaf( tmp, cl.worldmodel->nodes );
if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 ))
r_viewleaf2 = leaf;
}
RI.oldviewleaf = RI.viewleaf;
RI.viewleaf = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes );
}
/*
@ -822,9 +792,7 @@ static void R_SetupFrame( void )
{
RI.waveHeight = cl.refdef.movevars->waveHeight * 2.0f; // set global waveheight
RI.isSkyVisible = false; // unknown at this moment
if(!( RI.params & RP_OLDVIEWLEAF ))
R_FindViewLeaf();
R_FindViewLeaf();
}
}
@ -999,13 +967,13 @@ static void R_CheckFog( void )
RI.fogEnabled = false;
if( RI.refdef.waterlevel < 2 || !RI.drawWorld || !r_viewleaf )
if( RI.refdef.waterlevel < 2 || !RI.drawWorld || !RI.viewleaf )
return;
ent = CL_GetWaterEntity( RI.vieworg );
if( ent && ent->model && ent->model->type == mod_brush && ent->curstate.skin < 0 )
cnt = ent->curstate.skin;
else cnt = r_viewleaf->contents;
else cnt = RI.viewleaf->contents;
if( IsLiquidContents( RI.cached_contents ) && !IsLiquidContents( cnt ))
{
@ -1038,8 +1006,8 @@ static void R_CheckFog( void )
}
else
{
tex = R_RecursiveFindWaterTexture( r_viewleaf->parent, NULL, false );
if( tex ) RI.cached_contents = r_viewleaf->contents;
tex = R_RecursiveFindWaterTexture( RI.viewleaf->parent, NULL, false );
if( tex ) RI.cached_contents = RI.viewleaf->contents;
}
if( !tex ) return; // no valid fogs
@ -1390,7 +1358,7 @@ void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size )
R_RenderScene( fd );
r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame
RI.oldviewleaf = RI.viewleaf = NULL; // force markleafs next frame
}
static int GL_RenderGetParm( int parm, int arg )

View File

@ -459,7 +459,6 @@ void R_NewMap( void )
cl.worldmodel->leafs[i+1].efrags = NULL;
tr.skytexturenum = -1;
r_viewleaf = r_oldviewleaf = NULL;
// clearing texture chains
for( i = 0; i < cl.worldmodel->numtextures; i++ )

View File

@ -31,7 +31,6 @@ typedef struct
static int nColinElim; // stats
static vec2_t world_orthocenter;
static vec2_t world_orthohalf;
static byte visbytes[MAX_MAP_LEAFS/8];
static uint r_blocklights[BLOCK_SIZE_MAX*BLOCK_SIZE_MAX*3];
static glpoly_t *fullbright_polys[MAX_TEXTURES];
static qboolean draw_fullbrights = false;
@ -44,7 +43,7 @@ static void LM_UploadBlock( int lightmapnum );
byte *Mod_GetCurrentVis( void )
{
return Mod_LeafPVS( r_viewleaf, cl.worldmodel );
return RI.visbytes;
}
void Mod_SetOrthoBounds( float *mins, float *maxs )
@ -1944,7 +1943,6 @@ Mark the leaves and nodes that are in the PVS for the current leaf
*/
void R_MarkLeaves( void )
{
byte *vis;
mnode_t *node;
int i;
@ -1955,21 +1953,20 @@ void R_MarkLeaves( void )
// force recalc viewleaf
r_novis->modified = false;
tr.fResetVis = false;
r_viewleaf = NULL;
RI.viewleaf = NULL;
}
if( r_viewleaf == r_oldviewleaf && r_viewleaf2 == r_oldviewleaf2 && !r_novis->integer && r_viewleaf != NULL )
if( RI.viewleaf == RI.oldviewleaf && !r_novis->integer && RI.viewleaf != NULL )
return;
// development aid to let you run around
// and see exactly where the pvs ends
if( r_lockpvs->integer ) return;
RI.oldviewleaf = RI.viewleaf;
tr.visframecount++;
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
if( r_novis->integer || RI.drawOrtho || !r_viewleaf || !cl.worldmodel->visdata )
if( r_novis->integer || RI.drawOrtho || !RI.viewleaf || !cl.worldmodel->visdata )
{
// mark everything
for( i = 0; i < cl.worldmodel->numleafs; i++ )
@ -1979,26 +1976,11 @@ void R_MarkLeaves( void )
return;
}
// may have to combine two clusters
// because of solid water boundaries
vis = Mod_LeafPVS( r_viewleaf, cl.worldmodel );
if( r_viewleaf != r_viewleaf2 )
{
int longs = ( cl.worldmodel->numleafs + 31 ) >> 5;
memcpy( visbytes, vis, longs << 2 );
vis = Mod_LeafPVS( r_viewleaf2, cl.worldmodel );
for( i = 0; i < longs; i++ )
((int *)visbytes)[i] |= ((int *)vis)[i];
vis = visbytes;
}
Mod_FatPVS( RI.pvsorigin, REFPVS_RADIUS, RI.visbytes, world.visbytes, FBitSet( RI.params, RP_OLDVIEWLEAF ), r_novis->integer );
for( i = 0; i < cl.worldmodel->numleafs; i++ )
{
if( vis[i>>3] & ( 1<<( i & 7 )))
if( CHECKVISBIT( RI.visbytes, i ))
{
node = (mnode_t *)&cl.worldmodel->leafs[i+1];
do
@ -2134,7 +2116,7 @@ void GL_BuildLightmaps( void )
memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures ));
memset( tr.mirror_entities, 0, sizeof( tr.mirror_entities ));
memset( tr.mirrorTextures, 0, sizeof( tr.mirrorTextures ));
memset( visbytes, 0x00, sizeof( visbytes ));
memset( &RI, 0, sizeof( RI ));
skychain = NULL;

View File

@ -699,25 +699,12 @@ using a 'fat' radius
*/
qboolean SND_CheckPHS( channel_t *ch )
{
mleaf_t *leaf;
int leafnum;
byte *mask = NULL;
mleaf_t *leaf = Mod_PointInLeaf( ch->origin, cl.worldmodel->nodes );
// cull sounds by PHS
if( !s_phs->integer )
if( CHECKVISBIT( s_listener.pasbytes, leaf->cluster ))
return true;
leaf = Mod_PointInLeaf( ch->origin, cl.worldmodel->nodes );
mask = Mod_LeafPHS( leaf, cl.worldmodel );
if( mask )
{
leafnum = Mod_PointLeafnum( s_listener.origin ) - 1;
if( leafnum != -1 && (!(mask[leafnum>>3] & (1<<( leafnum & 7 )))))
return false;
}
return true;
return false;
}
/*
@ -1884,6 +1871,9 @@ void S_RenderFrame( ref_params_t *fd )
VectorCopy( fd->simvel, s_listener.velocity );
AngleVectors( fd->viewangles, s_listener.forward, s_listener.right, s_listener.up );
if( cl.worldmodel != NULL )
Mod_FatPVS( s_listener.origin, FATPHS_RADIUS, s_listener.pasbytes, world.visbytes, false, !s_phs->integer );
// update general area ambient sound sources
S_UpdateAmbientSounds();
@ -1961,9 +1951,9 @@ void S_RenderFrame( ref_params_t *fd )
// to differentiate modes
if( s_cull->integer && s_phs->integer )
VectorSet( info.color, 1.0f, 1.0f, 0.0f );
else if( s_phs->integer )
VectorSet( info.color, 0.0f, 1.0f, 0.0f );
else if( s_phs->integer )
VectorSet( info.color, 1.0f, 1.0f, 0.0f );
else if( s_cull->integer )
VectorSet( info.color, 1.0f, 0.0f, 0.0f );
else VectorSet( info.color, 1.0f, 1.0f, 1.0f );

View File

@ -215,6 +215,8 @@ typedef struct
qboolean paused;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
byte pasbytes[(MAX_MAP_LEAFS+7)/8];// actual PHS for current frame
} listener_t;
typedef struct

View File

@ -19,6 +19,8 @@ GNU General Public License for more details.
#include "utlvector.h"
#include "utlrbtree.h"
//#define NEW_VGUI_DLL
#include<VGUI.h>
#include<VGUI_App.h>
#include<VGUI_Font.h>
@ -127,7 +129,9 @@ public:
virtual void setTitle( const char *title ) { }
virtual void createPopup( Panel* embeddedPanel ) { }
virtual bool isWithin( int x, int y ) { return true; }
#ifdef NEW_VGUI_DLL
virtual void GetMousePos( int &x, int &y );
#endif
virtual bool hasFocus( void );
protected:
virtual int createNewTextureID( void );

View File

@ -56,6 +56,7 @@ void CEngineSurface :: setCursor( Cursor *cursor )
VGUI_CursorSelect( cursor );
}
#ifdef NEW_VGUI_DLL
void CEngineSurface :: GetMousePos( int &x, int &y )
{
POINT curpos;
@ -66,6 +67,7 @@ void CEngineSurface :: GetMousePos( int &x, int &y )
x = curpos.x;
y = curpos.y;
}
#endif
void CEngineSurface :: SetupPaintState( const paintState_t &paintState )
{

View File

@ -102,6 +102,7 @@ typedef enum
// HOST_FIXED_FRAMERATE stuff
#define HOST_MINFPS 20.0
#define HOST_MAXFPS 72.0
#define GAME_FPS 20.0
#define HOST_FPS 60.0 // client and the server clamped at 60.0 fps max. Render clamped at fps_max cvar
#define HOST_FRAMETIME ( 1.0 / HOST_FPS )

View File

@ -1303,7 +1303,6 @@ void Field_Paste( field_t *edit )
pasteLen = Q_strlen( cbd );
for( i = 0; i < pasteLen; i++ )
Field_CharEvent( edit, cbd[i] );
Mem_Free( cbd );
}
/*

View File

@ -14,6 +14,7 @@ GNU General Public License for more details.
*/
#include "imagelib.h"
#include "mathlib.h"
qboolean Image_CheckDXT3Alpha( dds_t *hdr, byte *fin )
{
@ -175,10 +176,10 @@ size_t Image_DXTCalcMipmapSize( dds_t *hdr )
int i, width, height;
// now correct buffer size
for( i = 0; i < max( 1, ( hdr->dwMipMapCount )); i++ )
for( i = 0; i < Q_max( 1, ( hdr->dwMipMapCount )); i++ )
{
width = max( 1, ( hdr->dwWidth >> i ));
height = max( 1, ( hdr->dwHeight >> i ));
width = Q_max( 1, ( hdr->dwWidth >> i ));
height = Q_max( 1, ( hdr->dwHeight >> i ));
buffsize += Image_DXTGetLinearSize( image.type, width, height, image.depth );
}
@ -295,21 +296,22 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, size_t filesize )
switch( image.encode )
{
case DXT_ENCODE_COLOR_YCoCg:
image.flags |= IMAGE_HAS_COLOR;
SetBits( image.flags, IMAGE_HAS_COLOR );
break;
case DXT_ENCODE_NORMAL_AG_ORTHO:
case DXT_ENCODE_NORMAL_AG_STEREO:
case DXT_ENCODE_NORMAL_AG_PARABOLOID:
case DXT_ENCODE_NORMAL_AG_QUARTIC:
case DXT_ENCODE_NORMAL_AG_AZIMUTHAL:
image.flags |= IMAGE_HAS_COLOR;
SetBits( image.flags, IMAGE_HAS_COLOR );
break;
default: // check for real alpha-pixels
if( image.type == PF_DXT3 && Image_CheckDXT3Alpha( &header, fin ))
image.flags |= IMAGE_HAS_ALPHA;
SetBits( image.flags, IMAGE_HAS_ALPHA );
else if( image.type == PF_DXT5 && Image_CheckDXT5Alpha( &header, fin ))
image.flags |= IMAGE_HAS_ALPHA;
image.flags |= IMAGE_HAS_COLOR;
SetBits( image.flags, IMAGE_HAS_ALPHA );
if( !FBitSet( header.dsPixelFormat.dwFlags, DDS_LUMINANCE ))
SetBits( image.flags, IMAGE_HAS_COLOR ); // FIXME: analyze colors
break;
}

View File

@ -102,12 +102,12 @@ void Image_Reset( void )
image.source_width = image.source_height = 0;
image.source_type = image.num_mips = 0;
image.num_sides = image.flags = 0;
image.encode = DXT_ENCODE_DEFAULT;
image.type = PF_UNKNOWN;
image.fogParams[0] = 0;
image.fogParams[1] = 0;
image.fogParams[2] = 0;
image.fogParams[3] = 0;
image.encode = 0;
// pointers will be saved with prevoius picture struct
// don't care about it

View File

@ -375,31 +375,25 @@ void learn( void )
if( rad <= 1 ) rad = 0;
for( i = 0; i < rad; i++ )
{
radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
}
radpower[i] = alpha * ((( rad * rad - i * i ) * radbias ) / ( rad * rad ));
if( delta <= 0 ) return;
if(( lengthcount % prime1 ) != 0 )
{
step = image.bpp * prime1;
step = prime1 * image.bpp;
}
else if(( lengthcount % prime2 ) != 0 )
{
step = prime2 * image.bpp;
}
else if(( lengthcount % prime3 ) != 0 )
{
step = prime3 * image.bpp;
}
else
{
if(( lengthcount % prime2 ) != 0 )
{
step = image.bpp * prime2;
}
else
{
if(( lengthcount % prime3 ) != 0 )
{
step = image.bpp * prime3;
}
else
{
step = image.bpp * prime4;
}
}
step = prime4 * image.bpp;
}
i = 0;
@ -427,7 +421,7 @@ void learn( void )
if( rad <= 1 ) rad = 0;
for( j = 0; j < rad; j++ )
radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
radpower[j] = alpha * ((( rad * rad - j * j ) * radbias ) / ( rad * rad ));
}
}
}

View File

@ -239,7 +239,6 @@ qboolean Image_SaveTGA( const char *name, rgbdata_t *pix )
else outsize = pix->width * pix->height * 3 + 18 + Q_strlen( comment );
buffer = (byte *)Mem_Alloc( host.imagepool, outsize );
memset( buffer, 0, 18 );
// prepare header
buffer[0] = Q_strlen( comment ); // tga comment length

View File

@ -42,6 +42,14 @@ GNU General Public License for more details.
#define SURF_INFO( surf, mod ) ((mextrasurf_t *)mod->cache.data + (surf - mod->surfaces))
#define INFO_SURF( surf, mod ) (mod->surfaces + (surf - (mextrasurf_t *)mod->cache.data))
#define CHECKVISBIT( vis, b ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] & (1 << ((b) & 7))) : (byte)false )
#define SETVISBIT( vis, b )( void ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] |= (1 << ((b) & 7))) : (byte)false )
#define CLEARVISBIT( vis, b )( void ) ((b) >= 0 ? (byte)((vis)[(b) >> 3] &= ~(1 << ((b) & 7))) : (byte)false )
#define REFPVS_RADIUS 2.0f // radius for rendering
#define FATPVS_RADIUS 8.0f // FatPVS use radius smaller than the FatPHS
#define FATPHS_RADIUS 16.0f
// model flags (stored in model_t->flags)
#define MODEL_CONVEYOR BIT( 0 )
#define MODEL_HAS_ORIGIN BIT( 1 )
@ -72,19 +80,29 @@ typedef struct
vec3_t hull_sizes[MAX_MAP_HULLS]; // actual hull sizes
msurface_t **draw_surfaces; // used for sorting translucent surfaces
int max_surfaces; // max surfaces per submodel (for all models)
qboolean loading; // true if worldmodel is loading
qboolean sky_sphere; // true when quake sky-sphere is used
qboolean has_mirrors; // one or more brush models contain reflective textures
qboolean custom_skybox; // if sky_sphere is active and custom skybox set
qboolean water_alpha; // allow translucency water
int lm_sample_size; // defaulting to 16 (BSP31 uses 8)
int block_size; // lightmap blocksize
color24 *deluxedata; // deluxemap data pointer
char message[2048]; // just for debug
// visibility info
byte *visdata; // uncompressed visdata
size_t visbytes; // cluster size
size_t fatbytes; // fatpvs size
int visclusters; // num visclusters
// world stats
size_t visdatasize; // actual size of the visdata
size_t litdatasize; // actual size of the lightdata
size_t vecdatasize; // actual size of the deluxdata
size_t entdatasize; // actual size of the entity string
size_t texdatasize; // actual size of the textures lump
qboolean loading; // true if worldmodel is loading
qboolean sky_sphere; // true when quake sky-sphere is used
qboolean has_mirrors; // one or more brush models contain reflective textures
qboolean custom_skybox; // if sky_sphere is active and custom skybox set
int lm_sample_size; // defaulting to 16 (BSP31 uses 8)
int block_size; // lightmap blocksize
color24 *deluxedata; // deluxemap data pointer
char message[2048]; // just for debug
vec3_t mins; // real accuracy world bounds
vec3_t maxs;
@ -118,20 +136,17 @@ model_t *Mod_FindName( const char *name, qboolean create );
model_t *Mod_LoadModel( model_t *mod, qboolean world );
model_t *Mod_ForName( const char *name, qboolean world );
qboolean Mod_RegisterModel( const char *name, int index );
int Mod_PointLeafnum( const vec3_t p );
byte *Mod_LeafPVS( mleaf_t *leaf, model_t *model );
byte *Mod_LeafPHS( mleaf_t *leaf, model_t *model );
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node );
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, short *lastleaf );
void Mod_TesselatePolygon( msurface_t *surf, model_t *mod, float tessSize );
int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int listsize, int *lastleaf );
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis );
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
void Mod_BuildSurfacePolygons( msurface_t *surf, mextrasurf_t *info );
void Mod_AmbientLevels( const vec3_t p, byte *pvolumes );
byte *Mod_CompressVis( const byte *in, size_t *size );
byte *Mod_DecompressVis( const byte *in );
byte *Mod_GetPVSForPoint( const vec3_t p );
modtype_t Mod_GetType( int handle );
model_t *Mod_Handle( int handle );
struct wadlist_s *Mod_WadList( void );
//
// mod_studio.c

View File

@ -202,96 +202,52 @@ void Mod_SetupHulls( vec3_t mins[MAX_MAP_HULLS], vec3_t maxs[MAX_MAP_HULLS] )
memcpy( maxs, cm_hullmaxs, sizeof( cm_hullmaxs ));
}
/*
===================
Mod_CompressVis
===================
*/
byte *Mod_CompressVis( const byte *in, size_t *size )
{
int j, rep;
int visrow;
byte *dest_p;
if( !worldmodel )
{
Host_Error( "Mod_CompressVis: no worldmodel\n" );
return NULL;
}
dest_p = visdata;
visrow = (worldmodel->numleafs + 7) >> 3;
for( j = 0; j < visrow; j++ )
{
*dest_p++ = in[j];
if( in[j] ) continue;
rep = 1;
for( j++; j < visrow; j++ )
{
if( in[j] || rep == 255 )
break;
else rep++;
}
*dest_p++ = rep;
j--;
}
if( size ) *size = dest_p - visdata;
return visdata;
}
/*
===================
Mod_DecompressVis
===================
*/
byte *Mod_DecompressVis( const byte *in )
static void Mod_DecompressVis( const byte *in, const byte *inend, byte *out, byte *outend )
{
int c, row;
byte *out;
byte *outstart = out;
int c;
if( !worldmodel )
while( out < outend )
{
Host_Error( "Mod_DecompressVis: no worldmodel\n" );
return NULL;
if( in == inend )
{
MsgDev( D_WARN, "Mod_DecompressVis: input underrun (decompressed %i of %i output bytes)\n",
(int)(out - outstart), (int)(outend - outstart));
return;
}
c = *in++;
if( c )
{
*out++ = c;
}
else
{
if( in == inend )
{
MsgDev( D_WARN, "Mod_DecompressVis: input underrun (during zero-run) (decompressed %i of %i output bytes)\n",
(int)(out - outstart), (int)(outend - outstart));
return;
}
for( c = *in++; c > 0; c-- )
{
if( out == outend )
{
MsgDev( D_WARN, "Mod_DecompressVis: output overrun (decompressed %i of %i output bytes)\n",
(int)(out - outstart), (int)(outend - outstart));
return;
}
*out++ = 0;
}
}
}
row = (worldmodel->numleafs + 7) >> 3;
out = visdata;
if( !in )
{
// no vis info, so make all visible
while( row )
{
*out++ = 0xff;
row--;
}
return visdata;
}
do
{
if( *in )
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while( c )
{
*out++ = 0;
c--;
}
} while( out - visdata < row );
return visdata;
}
/*
@ -317,41 +273,99 @@ mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node )
/*
==================
Mod_LeafPVS
Mod_GetPVSForPoint
Returns PVS data for a given point
NOTE: can return NULL
==================
*/
byte *Mod_LeafPVS( mleaf_t *leaf, model_t *model )
byte *Mod_GetPVSForPoint( const vec3_t p )
{
if( !model || !leaf || leaf == model->leafs || !model->visdata )
return Mod_DecompressVis( NULL );
return Mod_DecompressVis( leaf->compressed_vis );
mnode_t *node;
mleaf_t *leaf = NULL;
ASSERT( worldmodel != NULL );
node = worldmodel->nodes;
while( 1 )
{
if( node->contents < 0 )
{
leaf = (mleaf_t *)node;
break; // we found a leaf
}
node = node->children[PlaneDiff( p, node->plane ) < 0];
}
if( leaf && leaf->cluster >= 0 )
return world.visdata + leaf->cluster * world.visbytes;
return NULL;
}
/*
==================
Mod_LeafPHS
Mod_FatPVS_RecursiveBSPNode
==================
*/
byte *Mod_LeafPHS( mleaf_t *leaf, model_t *model )
static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *visbuffer, int visbytes, mnode_t *node )
{
if( !model || !leaf || leaf == model->leafs || !model->visdata )
return Mod_DecompressVis( NULL );
return Mod_DecompressVis( leaf->compressed_pas );
int i;
while( node->contents >= 0 )
{
float d = PlaneDiff( org, node->plane );
if( d > radius )
node = node->children[0];
else if( d < -radius )
node = node->children[1];
else
{
// go down both sides
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0] );
node = node->children[1];
}
}
// if this leaf is in a cluster, accumulate the vis bits
if(((mleaf_t *)node)->cluster >= 0 )
{
byte *vis = world.visdata + ((mleaf_t *)node)->cluster * world.visbytes;
for( i = 0; i < visbytes; i++ )
visbuffer[i] |= vis[i];
}
}
/*
==================
Mod_PointLeafnum
Mod_FatPVS_RecursiveBSPNode
Calculates a PVS that is the inclusive or of all leafs
within radius pixels of the given point.
==================
*/
int Mod_PointLeafnum( const vec3_t p )
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis )
{
// map not loaded
if ( !worldmodel ) return 0;
return Mod_PointInLeaf( p, worldmodel->nodes ) - worldmodel->leafs;
mleaf_t *leaf = Mod_PointInLeaf( org, worldmodel->nodes );
int bytes = world.visbytes;
bytes = Q_min( bytes, visbytes );
// enable full visibility for some reasons
if( fullvis || !world.visclusters || !leaf || leaf->cluster < 0 )
{
memset( visbuffer, 0xFF, bytes );
return bytes;
}
if( !merge ) memset( visbuffer, 0x00, bytes );
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, bytes, worldmodel->nodes );
return bytes;
}
/*
@ -363,8 +377,7 @@ LEAF LISTING
*/
static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
{
mplane_t *plane;
int s;
int sides;
while( 1 )
{
@ -382,18 +395,17 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
return;
}
ll->list[ll->count++] = leaf - worldmodel->leafs - 1;
ll->list[ll->count++] = leaf->cluster;
return;
}
plane = node->plane;
s = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, plane );
sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane );
if( s == 1 )
if( sides == 1 )
{
node = node->children[0];
}
else if( s == 2 )
else if( sides == 2 )
{
node = node->children[1];
}
@ -421,11 +433,12 @@ int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int list
VectorCopy( mins, ll.mins );
VectorCopy( maxs, ll.maxs );
ll.count = 0;
ll.maxcount = listsize;
ll.list = list;
ll.topnode = -1;
ll.overflowed = false;
ll.topnode = -1;
ll.list = list;
ll.count = 0;
Mod_BoxLeafnums_r( &ll, worldmodel->nodes );
@ -453,14 +466,41 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi
for( i = 0; i < count; i++ )
{
int leafnum = leafList[i];
if( leafnum != -1 && visbits[leafnum>>3] & (1<<( leafnum & 7 )))
if( CHECKVISBIT( visbits, leafList[i] ))
return true;
}
return false;
}
/*
=============
Mod_HeadnodeVisible
=============
*/
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, short *lastleaf )
{
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
return false;
if( lastleaf )
*lastleaf = ((mleaf_t *)node)->cluster;
return true;
}
if( Mod_HeadnodeVisible( node->children[0], visbits, lastleaf ))
return true;
if( Mod_HeadnodeVisible( node->children[1], visbits, lastleaf ))
return true;
return false;
}
/*
==================
Mod_AmbientLevels
@ -479,6 +519,41 @@ void Mod_AmbientLevels( const vec3_t p, byte *pvolumes )
*(int *)pvolumes = *(int *)leaf->ambient_sound_level;
}
/*
==================
Mod_CheckWaterAlphaSupport
converted maps potential may don't
support water transparency
==================
*/
static qboolean Mod_CheckWaterAlphaSupport( void )
{
mleaf_t *leaf;
int i, j;
const byte *pvs;
if( world.visdatasize <= 0 ) return true;
// check all liquid leafs to see if they can see into empty leafs, if any
// can we can assume this map supports r_wateralpha
for( i = 0, leaf = loadmodel->leafs; i < loadmodel->numleafs; i++, leaf++ )
{
if(( leaf->contents == CONTENTS_WATER || leaf->contents == CONTENTS_SLIME ) && leaf->cluster >= 0 )
{
pvs = world.visdata + leaf->cluster * world.visbytes;
for( j = 0; j < loadmodel->numleafs; j++ )
{
if( CHECKVISBIT( pvs, loadmodel->leafs[j].cluster ) && loadmodel->leafs[j].contents == CONTENTS_EMPTY )
return true;
}
}
}
return false;
}
/*
================
Mod_FreeUserData
@ -618,7 +693,7 @@ static void Mod_LoadSubmodels( const dlump_t *l )
{
for( j = 0; j < 3; j++ )
{
// spread the mins / maxs by a pixel
// spread the mins / maxs by a unit
out->mins[j] = in->mins[j] - 1.0f;
out->maxs[j] = in->maxs[j] + 1.0f;
out->origin[j] = in->origin[j];
@ -640,7 +715,7 @@ static void Mod_LoadSubmodels( const dlump_t *l )
VectorAverage( out->mins, out->maxs, out->origin );
}
world.max_surfaces = max( world.max_surfaces, out->numfaces );
world.max_surfaces = Q_max( world.max_surfaces, out->numfaces );
}
if( world.loading )
@ -924,11 +999,11 @@ static void Mod_LoadTextures( const dlump_t *l )
{
tx = loadmodel->textures[i];
if( !tx || tx->name[0] != '+' )
if( tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0 )
continue;
if( tx->anim_next )
continue; // allready sequenced
continue; // already sequenced
// find the number of frames in the animation
memset( anims, 0, sizeof( anims ));
@ -951,23 +1026,22 @@ static void Mod_LoadTextures( const dlump_t *l )
altanims[altmax] = tx;
altmax++;
}
else Host_Error( "Mod_LoadTextures: bad animating texture %s\n", tx->name );
else MsgDev( D_ERROR, "Mod_LoadTextures: bad animating texture %s\n", tx->name );
for( j = i + 1; j < loadmodel->numtextures; j++ )
{
tx2 = loadmodel->textures[j];
if( !tx2 || tx2->name[0] != '+' )
continue;
if( Q_strcmp( tx2->name + 2, tx->name + 2 ))
if( tx2->name[0] != '+' || Q_strcmp( tx2->name + 2, tx->name + 2 ))
continue;
num = tx2->name[1];
if( num >= '0' && num <= '9' )
{
num -= '0';
anims[num] = tx2;
if (num+1 > max)
if( num + 1 > max )
max = num + 1;
}
else if( num >= 'a' && num <= 'j' )
@ -977,14 +1051,21 @@ static void Mod_LoadTextures( const dlump_t *l )
if( num + 1 > altmax )
altmax = num + 1;
}
else Host_Error( "Mod_LoadTextures: bad animating texture %s\n", tx->name );
else MsgDev( D_ERROR, "Mod_LoadTextures: bad animating texture %s\n", tx->name );
}
// link them all together
for( j = 0; j < max; j++ )
{
tx2 = anims[j];
if( !tx2 ) Host_Error( "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name );
if( !tx2 )
{
MsgDev( D_ERROR, "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name );
tx->anim_total = 0;
break;
}
tx2->anim_total = max * ANIM_CYCLE;
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j + 1) * ANIM_CYCLE;
@ -995,7 +1076,14 @@ static void Mod_LoadTextures( const dlump_t *l )
for( j = 0; j < altmax; j++ )
{
tx2 = altanims[j];
if( !tx2 ) Host_Error( "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name );
if( !tx2 )
{
MsgDev( D_ERROR, "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name );
tx->anim_total = 0;
break;
}
tx2->anim_total = altmax * ANIM_CYCLE;
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j+1) * ANIM_CYCLE;
@ -1009,11 +1097,11 @@ static void Mod_LoadTextures( const dlump_t *l )
{
tx = loadmodel->textures[i];
if( !tx || tx->name[0] != '-' )
if( tx->name[0] != '-' || tx->name[1] == 0 || tx->name[2] == 0 )
continue;
if( tx->anim_next )
continue; // allready sequenced
continue; // already sequenced
// find the number of frames in the sequence
memset( anims, 0, sizeof( anims ));
@ -1026,33 +1114,39 @@ static void Mod_LoadTextures( const dlump_t *l )
anims[max] = tx;
max++;
}
else Host_Error( "Mod_LoadTextures: bad detail texture %s\n", tx->name );
else MsgDev( D_ERROR, "Mod_LoadTextures: bad detail texture %s\n", tx->name );
for( j = i + 1; j < loadmodel->numtextures; j++ )
{
tx2 = loadmodel->textures[j];
if( !tx2 || tx2->name[0] != '-' )
continue;
if( Q_strcmp( tx2->name + 2, tx->name + 2 ))
if( tx2->name[0] != '-' || Q_strcmp( tx2->name + 2, tx->name + 2 ))
continue;
num = tx2->name[1];
if( num >= '0' && num <= '9' )
{
num -= '0';
anims[num] = tx2;
if( num+1 > max )
if( num + 1 > max )
max = num + 1;
}
else Host_Error( "Mod_LoadTextures: bad detail texture %s\n", tx->name );
else MsgDev( D_ERROR, "Mod_LoadTextures: bad detail texture %s\n", tx->name );
}
// link them all together
for( j = 0; j < max; j++ )
{
tx2 = anims[j];
if( !tx2 ) Host_Error( "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name );
if( !tx2 )
{
MsgDev( D_ERROR, "Mod_LoadTextures: missing frame %i of %s\n", j, tx->name );
tx->anim_total = 0;
break;
}
tx2->anim_total = -( max * ANIM_CYCLE ); // to differentiate from animations
tx2->anim_min = j * ANIM_CYCLE;
tx2->anim_max = (j + 1) * ANIM_CYCLE;
@ -1272,7 +1366,7 @@ static void Mod_CalcSurfaceExtents( msurface_t *surf )
surf->texturemins[i] = bmins[i] * LM_SAMPLE_SIZE;
surf->extents[i] = (bmaxs[i] - bmins[i]) * LM_SAMPLE_SIZE;
if(!( tex->flags & TEX_SPECIAL ) && surf->extents[i] > 4096 )
if( !FBitSet( tex->flags, TEX_SPECIAL ) && surf->extents[i] > 4096 )
MsgDev( D_ERROR, "Bad surface extents %i\n", surf->extents[i] );
}
}
@ -2095,6 +2189,17 @@ static void Mod_LoadLeafs( const dlump_t *l )
loadmodel->leafs = out;
loadmodel->numleafs = count;
if( world.loading )
{
// get visleafs from the submodel data
world.visclusters = loadmodel->submodels[0].visleafs;
world.visbytes = (world.visclusters + 7) >> 3;
world.visdata = (byte *)Mem_Alloc( loadmodel->mempool, world.visclusters * world.visbytes );
// enable full visibility as default
memset( world.visdata, 0xFF, world.visclusters * world.visbytes );
}
for( i = 0; i < count; i++, in++, out++ )
{
for( j = 0; j < 3; j++ )
@ -2107,6 +2212,29 @@ static void Mod_LoadLeafs( const dlump_t *l )
p = in->visofs;
if( world.loading )
{
out->cluster = ( i - 1 ); // solid leaf 0 has no visdata
if( out->cluster >= world.visclusters )
out->cluster = -1;
// ignore visofs errors on leaf 0 (solid)
if( p >= 0 && out->cluster >= 0 && loadmodel->visdata )
{
if( p < world.visdatasize )
{
byte *inrow = loadmodel->visdata + p;
byte *inrowend = loadmodel->visdata + world.visdatasize;
byte *outrow = world.visdata + out->cluster * world.visbytes;
byte *outrowend = world.visdata + (out->cluster + 1) * world.visbytes;
Mod_DecompressVis( inrow, inrowend, outrow, outrowend );
}
else MsgDev( D_WARN, "Mod_LoadLeafs: invalid visofs for leaf #%i\n", i );
}
}
else out->cluster = -1; // no visclusters on bmodels
if( p == -1 ) out->compressed_vis = NULL;
else out->compressed_vis = loadmodel->visdata + p;
@ -2130,6 +2258,14 @@ static void Mod_LoadLeafs( const dlump_t *l )
if( loadmodel->leafs[0].contents != CONTENTS_SOLID )
Host_Error( "Mod_LoadLeafs: Map %s has leaf 0 is not CONTENTS_SOLID\n", loadmodel->name );
// do some final things for world
if( world.loading )
{
// store size of fat pvs
world.fatbytes = (world.visclusters + 31) >> 3;
world.water_alpha = Mod_CheckWaterAlphaSupport();
}
}
/*
@ -2162,6 +2298,9 @@ static void Mod_LoadPlanes( const dlump_t *l )
out->signbits |= 1<<j;
}
if( VectorIsNull( out->normal ))
Host_Error( "Mod_LoadPlanes: bad normal for plane #%i\n", i );
out->dist = in->dist;
out->type = in->type;
}
@ -2495,135 +2634,6 @@ static void Mod_MakeHull0( void )
}
}
/*
=================
Mod_CalcPHS
=================
*/
void Mod_CalcPHS( void )
{
int hcount, vcount;
int i, j, k, l, index, num;
int rowbytes, rowwords;
int bitbyte, rowsize;
int *visofs, total_size = 0;
byte *vismap, *vismap_p;
byte *uncompressed_vis;
byte *uncompressed_pas;
byte *compressed_pas;
byte *scan, *comp;
uint *dest, *src;
double timestart;
size_t phsdatasize;
// no worldmodel or no visdata
if( !world.loading || !worldmodel || !worldmodel->visdata )
return;
MsgDev( D_NOTE, "Building PAS...\n" );
timestart = Sys_DoubleTime();
// NOTE: first leaf is skipped becuase is a outside leaf. Now all leafs have shift up by 1.
// and last leaf (which equal worldmodel->numleafs) has no visdata! Add one extra leaf
// to avoid this situation.
num = worldmodel->numleafs;
rowwords = (num + 31) >> 5;
rowbytes = rowwords * 4;
// typically PHS reqiured more room because RLE fails on multiple 1 not 0
phsdatasize = world.visdatasize * 32; // empirically determined
// allocate pvs and phs data single array
visofs = Mem_Alloc( worldmodel->mempool, num * sizeof( int ));
uncompressed_vis = Mem_Alloc( worldmodel->mempool, rowbytes * num * 2 );
uncompressed_pas = uncompressed_vis + rowbytes * num;
compressed_pas = Mem_Alloc( worldmodel->mempool, phsdatasize );
vismap = vismap_p = compressed_pas; // compressed PHS buffer
scan = uncompressed_vis;
vcount = 0;
// uncompress pvs first
for( i = 0; i < num; i++, scan += rowbytes )
{
memcpy( scan, Mod_LeafPVS( worldmodel->leafs + i, worldmodel ), rowbytes );
if( i == 0 ) continue;
for( j = 0; j < num; j++ )
{
if( scan[j>>3] & (1<<( j & 7 )))
vcount++;
}
}
scan = uncompressed_vis;
hcount = 0;
dest = (uint *)uncompressed_pas;
for( i = 0; i < num; i++, dest += rowwords, scan += rowbytes )
{
memcpy( dest, scan, rowbytes );
for( j = 0; j < rowbytes; j++ )
{
bitbyte = scan[j];
if( !bitbyte ) continue;
for( k = 0; k < 8; k++ )
{
if(!( bitbyte & ( 1<<k )))
continue;
// or this pvs row into the phs
// +1 because pvs is 1 based
index = ((j<<3) + k + 1);
if( index >= num ) continue;
src = (uint *)uncompressed_vis + index * rowwords;
for( l = 0; l < rowwords; l++ )
dest[l] |= src[l];
}
}
// compress PHS data back
comp = Mod_CompressVis( (byte *)dest, &rowsize );
visofs[i] = vismap_p - vismap; // leaf 0 is a common solid
total_size += rowsize;
if( total_size > phsdatasize )
{
Host_Error( "CalcPHS: vismap expansion overflow %s > %s\n", Q_memprint( total_size ), Q_memprint( phsdatasize ));
}
memcpy( vismap_p, comp, rowsize );
vismap_p += rowsize; // move pointer
if( i == 0 ) continue;
for( j = 0; j < num; j++ )
{
if(((byte *)dest)[j>>3] & (1<<( j & 7 )))
hcount++;
}
}
// adjust compressed pas data to fit the size
compressed_pas = Mem_Realloc( worldmodel->mempool, compressed_pas, total_size );
// apply leaf pointers
for( i = 0; i < worldmodel->numleafs; i++ )
worldmodel->leafs[i].compressed_pas = compressed_pas + visofs[i];
// release uncompressed data
Mem_Free( uncompressed_vis );
Mem_Free( visofs ); // release vis offsets
// NOTE: we don't need to store off pointer to compressed pas-data
// because this is will be automatiaclly frees by mempool internal pointer
// and we never use this pointer after this point
MsgDev( D_NOTE, "Average leaves visible / audible / total: %i / %i / %i\n", vcount / num, hcount / num, num );
MsgDev( D_NOTE, "PAS building time: %g secs\n", Sys_DoubleTime() - timestart );
}
/*
=================
Mod_UnloadBrushModel
@ -2739,6 +2749,7 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
if( world.version <= 29 && world.mapversion == 220 && (header->lumps[LUMP_LIGHTING].filelen % 3) == 0 )
world.version = bmodel_version = HLBSP_VERSION;
Mod_LoadSubmodels( &header->lumps[LUMP_MODELS] );
Mod_LoadVertexes( &header->lumps[LUMP_VERTEXES] );
Mod_LoadEdges( &header->lumps[LUMP_EDGES] );
Mod_LoadSurfEdges( &header->lumps[LUMP_SURFEDGES] );
@ -2754,7 +2765,6 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
if( bmodel_version == XTBSP_VERSION )
Mod_LoadClipnodes31( &header->lumps[LUMP_CLIPNODES], &header->lumps[LUMP_CLIPNODES2], &header->lumps[LUMP_CLIPNODES3] );
else Mod_LoadClipnodes( &header->lumps[LUMP_CLIPNODES] );
Mod_LoadSubmodels( &header->lumps[LUMP_MODELS] );
Mod_MakeHull0 ();
@ -2786,12 +2796,14 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
if( i != 0 )
{
// HACKHACK: c2a1 issues
if( !bm->origin[0] && !bm->origin[1] ) mod->flags |= MODEL_HAS_ORIGIN;
if( !bm->origin[0] && !bm->origin[1] )
SetBits( mod->flags, MODEL_HAS_ORIGIN );
Mod_FindModelOrigin( ents, va( "*%i", i ), bm->origin );
// flag 2 is indicated model with origin brush!
if( !VectorIsNull( bm->origin )) mod->flags |= MODEL_HAS_ORIGIN;
if( !VectorIsNull( bm->origin ))
SetBits( mod->flags, MODEL_HAS_ORIGIN );
}
for( j = 0; i != 0 && j < mod->nummodelsurfaces; j++ )
@ -2810,7 +2822,7 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
if( surf->plane->type == PLANE_Z )
{
// kill bottom plane too
if( info->mins[2] == bm->mins[2] + 1 )
if( info->mins[2] == bm->mins[2] + 1.0f )
surf->flags |= SURF_WATERCSG;
}
else
@ -3005,7 +3017,6 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean multiplayer )
// now replacement table is invalidate
memset( com_models, 0, sizeof( com_models ));
com_models[1] = cm_models; // make link to world
// update the lightmap blocksize
@ -3026,7 +3037,6 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean multiplayer )
}
// clear all studio submodels on restart
// HACKHACK: throw all external BSP-models to refresh their lightmaps properly
for( i = 1; i < cm_nummodels; i++ )
{
if( cm_models[i].type == mod_studio )
@ -3047,9 +3057,6 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean multiplayer )
world.loading = false;
if( checksum ) *checksum = world.checksum;
// calc Potentially Hearable Set and compress it
Mod_CalcPHS();
}
/*
@ -3239,9 +3246,4 @@ model_t *Mod_Handle( int handle )
return NULL;
}
return com_models[handle];
}
wadlist_t *Mod_WadList( void )
{
return &wadlist;
}

View File

@ -50,75 +50,76 @@ typedef struct sizebuf_s
#define MSG_GetRealBytesRead MSG_GetRealBytesWritten
#define MSG_GetNumBitsRead MSG_GetNumBitsWritten
#define MSG_ReadBitAngles MSG_ReadBitVec3Coord
#define MSG_ReadString( bf ) MSG_ReadStringExt( bf, false )
#define MSG_ReadStringLine( bf ) MSG_ReadStringExt( bf, true )
#define MSG_ReadAngle( bf ) (float)(MSG_ReadChar( bf ) * ( 360.0f / 256.0f ))
#define MSG_Init( bf, name, data, bytes ) MSG_InitExt( bf, name, data, bytes, -1 )
#define MSG_ReadString( sb ) MSG_ReadStringExt( sb, false )
#define MSG_ReadStringLine( sb ) MSG_ReadStringExt( sb, true )
#define MSG_ReadAngle( sb ) (float)(MSG_ReadChar( sb ) * ( 360.0f / 256.0f ))
#define MSG_Init( sb, name, data, bytes ) MSG_InitExt( sb, name, data, bytes, -1 )
// common functions
void MSG_InitExt( sizebuf_t *bf, const char *pDebugName, void *pData, int nBytes, int nMaxBits );
void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits );
void MSG_InitMasks( void ); // called once at startup engine
void MSG_SeekToBit( sizebuf_t *bf, int bitPos );
void MSG_SeekToByte( sizebuf_t *bf, int bytePos );
void MSG_ExciseBits( sizebuf_t *bf, int startbit, int bitstoremove );
qboolean MSG_CheckOverflow( sizebuf_t *bf );
void MSG_SeekToBit( sizebuf_t *sb, int bitPos );
void MSG_SeekToByte( sizebuf_t *sb, int bytePos );
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
qboolean MSG_CheckOverflow( sizebuf_t *sb );
short MSG_BigShort( short swap );
// init writing
void MSG_StartWriting( sizebuf_t *bf, void *pData, int nBytes, int iStartBit, int nBits );
void MSG_Clear( sizebuf_t *bf );
void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits );
void MSG_Clear( sizebuf_t *sb );
// Bit-write functions
void MSG_WriteOneBit( sizebuf_t *bf, int nValue );
void MSG_WriteUBitLong( sizebuf_t *bf, uint curData, int numbits );
void MSG_WriteSBitLong( sizebuf_t *bf, int data, int numbits );
void MSG_WriteBitLong( sizebuf_t *bf, uint data, int numbits, qboolean bSigned );
qboolean MSG_WriteBits( sizebuf_t *bf, const void *pData, int nBits );
void MSG_WriteBitAngle( sizebuf_t *bf, float fAngle, int numbits );
void MSG_WriteBitFloat( sizebuf_t *bf, float val );
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits );
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits );
void MSG_WriteBitFloat( sizebuf_t *sb, float val );
// Byte-write functions
void MSG_WriteChar( sizebuf_t *bf, int val );
void MSG_WriteByte( sizebuf_t *bf, int val );
void MSG_WriteShort( sizebuf_t *bf, int val );
void MSG_WriteWord( sizebuf_t *bf, int val );
void MSG_WriteLong( sizebuf_t *bf, long val );
void MSG_WriteChar( sizebuf_t *sb, int val );
void MSG_WriteByte( sizebuf_t *sb, int val );
void MSG_WriteShort( sizebuf_t *sb, int val );
void MSG_WriteWord( sizebuf_t *sb, int val );
void MSG_WriteLong( sizebuf_t *sb, long val );
void MSG_WriteDword( sizebuf_t *sb, dword val );
void MSG_WriteCoord( sizebuf_t *bf, float val );
void MSG_WriteFloat( sizebuf_t *bf, float val );
void MSG_WriteVec3Coord( sizebuf_t *bf, const float *fa );
qboolean MSG_WriteBytes( sizebuf_t *bf, const void *pBuf, int nBytes ); // same as MSG_WriteData
qboolean MSG_WriteString( sizebuf_t *bf, const char *pStr ); // returns false if it overflows the buffer.
void MSG_WriteCoord( sizebuf_t *sb, float val );
void MSG_WriteFloat( sizebuf_t *sb, float val );
void MSG_WriteVec3Coord( sizebuf_t *sb, const float *fa );
qboolean MSG_WriteBytes( sizebuf_t *sb, const void *pBuf, int nBytes ); // same as MSG_WriteData
qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr ); // returns false if it overflows the buffer.
// helper functions
_inline int MSG_GetNumBytesWritten( sizebuf_t *bf ) { return BitByte( bf->iCurBit ); }
_inline int MSG_GetRealBytesWritten( sizebuf_t *bf ) { return bf->iCurBit >> 3; } // unpadded
_inline int MSG_GetNumBitsWritten( sizebuf_t *bf ) { return bf->iCurBit; }
_inline int MSG_GetMaxBits( sizebuf_t *bf ) { return bf->nDataBits; }
_inline int MSG_GetMaxBytes( sizebuf_t *bf ) { return bf->nDataBits >> 3; }
_inline int MSG_GetNumBitsLeft( sizebuf_t *bf ) { return bf->nDataBits - bf->iCurBit; }
_inline int MSG_GetNumBytesLeft( sizebuf_t *bf ) { return MSG_GetNumBitsLeft( bf ) >> 3; }
_inline byte *MSG_GetData( sizebuf_t *bf ) { return bf->pData; }
_inline int MSG_GetNumBytesWritten( sizebuf_t *sb ) { return BitByte( sb->iCurBit ); }
_inline int MSG_GetRealBytesWritten( sizebuf_t *sb ) { return sb->iCurBit >> 3; } // unpadded
_inline int MSG_GetNumBitsWritten( sizebuf_t *sb ) { return sb->iCurBit; }
_inline int MSG_GetMaxBits( sizebuf_t *sb ) { return sb->nDataBits; }
_inline int MSG_GetMaxBytes( sizebuf_t *sb ) { return sb->nDataBits >> 3; }
_inline int MSG_GetNumBitsLeft( sizebuf_t *sb ) { return sb->nDataBits - sb->iCurBit; }
_inline int MSG_GetNumBytesLeft( sizebuf_t *sb ) { return MSG_GetNumBitsLeft( sb ) >> 3; }
_inline byte *MSG_GetData( sizebuf_t *sb ) { return sb->pData; }
// Bit-read functions
int MSG_ReadOneBit( sizebuf_t *bf );
float MSG_ReadBitFloat( sizebuf_t *bf );
qboolean MSG_ReadBits( sizebuf_t *bf, void *pOutData, int nBits );
float MSG_ReadBitAngle( sizebuf_t *bf, int numbits );
int MSG_ReadSBitLong( sizebuf_t *bf, int numbits );
uint MSG_ReadUBitLong( sizebuf_t *bf, int numbits );
uint MSG_ReadBitLong( sizebuf_t *bf, int numbits, qboolean bSigned );
int MSG_ReadOneBit( sizebuf_t *sb );
float MSG_ReadBitFloat( sizebuf_t *sb );
qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits );
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits );
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits );
uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits );
uint MSG_ReadBitLong( sizebuf_t *sb, int numbits, qboolean bSigned );
// Byte-read functions
int MSG_ReadChar( sizebuf_t *bf );
int MSG_ReadByte( sizebuf_t *bf );
int MSG_ReadShort( sizebuf_t *bf );
int MSG_ReadWord( sizebuf_t *bf );
long MSG_ReadLong( sizebuf_t *bf );
float MSG_ReadCoord( sizebuf_t *bf );
float MSG_ReadFloat( sizebuf_t *bf );
void MSG_ReadVec3Coord( sizebuf_t *bf, vec3_t fa );
qboolean MSG_ReadBytes( sizebuf_t *bf, void *pOut, int nBytes );
char *MSG_ReadStringExt( sizebuf_t *bf, qboolean bLine );
int MSG_ReadChar( sizebuf_t *sb );
int MSG_ReadByte( sizebuf_t *sb );
int MSG_ReadShort( sizebuf_t *sb );
int MSG_ReadWord( sizebuf_t *sb );
long MSG_ReadLong( sizebuf_t *sb );
dword MSG_ReadDword( sizebuf_t *sb );
float MSG_ReadCoord( sizebuf_t *sb );
float MSG_ReadFloat( sizebuf_t *sb );
void MSG_ReadVec3Coord( sizebuf_t *sb, vec3_t fa );
qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes );
char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine );
#endif//NET_BUFFER_H

View File

@ -17,6 +17,7 @@ GNU General Public License for more details.
#include "netchan.h"
#include "mathlib.h"
#include "net_encode.h"
#include "protocol.h"
#define MAKE_FRAGID( id, count ) ((( id & 0xffff ) << 16 ) | ( count & 0xffff ))
#define FRAG_GETID( fragid ) (( fragid >> 16 ) & 0xffff )
@ -121,7 +122,6 @@ void Netchan_Init( void )
net_mempool = Mem_AllocPool( "Network Pool" );
Huff_Init (); // initialize huffman compression
MSG_InitMasks (); // initialize bit-masks
}
@ -163,7 +163,6 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport )
chan->incoming_sequence = 0;
chan->outgoing_sequence = 1;
chan->rate = DEFAULT_RATE;
chan->compress = false; // work but low efficiency
chan->qport = qport;
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
@ -1166,8 +1165,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
qboolean send_reliable_fragment;
qboolean send_resending = false;
qboolean send_reliable;
size_t size1, size2;
uint w1, w2, hdr_size;
uint w1, w2;
int i, j;
float fRate;
@ -1351,9 +1349,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
}
if( send_reliable && send_reliable_fragment )
{
w1 |= ( 1 << 30 );
}
SetBits( w1, BIT( 30 ));
chan->outgoing_sequence++;
chan->last_sent = host.realtime;
@ -1385,8 +1381,6 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
}
}
hdr_size = MSG_GetNumBytesWritten( &send );
// copy the reliable message to the packet first
if( send_reliable )
{
@ -1396,16 +1390,11 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// is there room for the unreliable payload?
if( MSG_GetNumBitsLeft( &send ) >= length )
{
MSG_WriteBits( &send, data, length );
}
else
{
MsgDev( D_WARN, "Netchan_Transmit: unreliable message overflow\n" );
}
else MsgDev( D_WARN, "Netchan_Transmit: unreliable message overflow\n" );
// deal with packets that are too small for some networks
if( MSG_GetNumBytesWritten( &send ) < 16 ) // packet too small for some networks
if( MSG_GetNumBytesWritten( &send ) < 16 && !NET_IsLocalAddress( chan->remote_address )) // packet too small for some networks
{
int i;
@ -1413,7 +1402,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
for( i = MSG_GetNumBytesWritten( &send ); i < 16; i++ )
{
// NOTE: that the server can parse svc_nop, too.
MSG_WriteByte( &send, 1 );
MSG_WriteByte( &send, svc_nop );
}
}
@ -1424,12 +1413,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
Netchan_UpdateFlow( chan );
size1 = MSG_GetNumBytesWritten( &send );
if( chan->compress ) Huff_CompressPacket( &send, hdr_size );
size2 = MSG_GetNumBytesWritten( &send );
chan->total_sended += size2;
chan->total_sended_uncompressed += size1;
chan->total_sended += MSG_GetNumBytesWritten( &send );
// send the datagram
if( !CL_IsPlaybackDemo( ))
@ -1488,21 +1472,18 @@ modifies net_message so that it points to the packet payload
*/
qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
{
uint sequence, sequence_ack, hdr_size;
uint sequence, sequence_ack;
uint reliable_ack, reliable_message;
uint fragid[MAX_STREAMS] = { 0, 0 };
qboolean frag_message[MAX_STREAMS] = { false, false };
int frag_offset[MAX_STREAMS] = { 0, 0 };
int frag_length[MAX_STREAMS] = { 0, 0 };
qboolean message_contains_fragments;
size_t size1, size2;
int i, qport;
if( !CL_IsPlaybackDemo() && !NET_CompareAdr( net_from, chan->remote_address ))
{
return false;
}
// get sequence numbers
MSG_Clear( msg );
sequence = MSG_ReadLong( msg );
@ -1517,7 +1498,7 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
reliable_message = sequence >> 31;
reliable_ack = sequence_ack >> 31;
message_contains_fragments = sequence & ( 1 << 30 ) ? true : false;
message_contains_fragments = FBitSet( sequence, BIT( 30 )) ? true : false;
if( message_contains_fragments )
{
@ -1533,9 +1514,9 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
}
}
sequence &= ~(1<<31);
sequence &= ~(1<<30);
sequence_ack &= ~(1<<31);
sequence &= ~BIT( 31 );
sequence &= ~BIT( 30 );
sequence_ack &= ~BIT( 31 );
if( net_showpackets->integer == 2 )
{
@ -1619,14 +1600,8 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
chan->flow[FLOW_INCOMING].current++;
Netchan_UpdateFlow( chan );
hdr_size = MSG_GetNumBytesRead( msg );
size1 = MSG_GetMaxBytes( msg );
if( chan->compress ) Huff_DecompressPacket( msg, hdr_size );
size2 = MSG_GetMaxBytes( msg );
chan->total_received += size1;
chan->total_received_uncompressed += size2;
chan->total_received += MSG_GetMaxBytes( msg );
chan->good_count += 1;
if( message_contains_fragments )

View File

@ -747,7 +747,11 @@ void Delta_InitFields( void )
while(( pfile = COM_ParseFile( pfile, token )) != NULL )
{
dt = Delta_FindStruct( token );
if( dt == NULL ) Sys_Error( "delta.lst: unknown struct %s\n", token );
if( dt == NULL )
{
Sys_Error( "%s: unknown struct %s\n", DELTA_PATH, token );
}
pfile = COM_ParseFile( pfile, encodeDll );
@ -757,7 +761,11 @@ void Delta_InitFields( void )
// jump to '{'
pfile = COM_ParseFile( pfile, token );
if( token[0] != '{' ) Sys_Error( "delta.lst: missing '{' in section %s\n", dt->pName );
if( token[0] != '{' )
{
Sys_Error( "%s: missing '{' in section %s\n", DELTA_PATH, dt->pName );
}
Delta_ParseTable( &pfile, dt, encodeDll, encodeFunc );
}
@ -1026,7 +1034,7 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
else if( pField->flags & ( DT_FLOAT|DT_ANGLE ))
else if( pField->flags & ( DT_ANGLE|DT_FLOAT ))
{
// don't convert floats to integers
fromF = *((int *)((byte *)from + pField->offset ));
@ -1144,7 +1152,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
else if( pField->flags & DT_TIMEWINDOW_BIG )
{
flValue = *(float *)((byte *)to + pField->offset );
flTime = (timebase * pField->multiplier) - (flValue * pField->multiplier);
flTime = Q_rint( timebase * pField->multiplier ) - Q_rint( flValue * pField->multiplier );
iValue = (uint)abs( flTime );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
@ -1665,10 +1673,11 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
MSG_WriteWord( msg, to->number );
MSG_WriteUBitLong( msg, 0, 2 ); // alive
if( to->entityType != from->entityType )
if( force || ( to->entityType != from->entityType ))
{
MSG_WriteOneBit( msg, 1 );
MSG_WriteUBitLong( msg, to->entityType, 2 );
numChanges++;
}
else MSG_WriteOneBit( msg, 0 );

View File

@ -1,613 +0,0 @@
/*
net_huff.c - Huffman compression routines for network bitstream
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "netchan.h"
#define VALUE(a) ((int )(a))
#define NODE(a) ((void *)(a))
#define NODE_START NODE( 1)
#define NODE_NONE NODE(256)
#define NODE_NEXT NODE(257)
#define NOT_REFERENCED 256
#define HUFF_TREE_SIZE 7175
typedef void *tree_t[HUFF_TREE_SIZE];
//
// pre-defined frequency counts for all bytes [0..255]
//
static const int huff_tree[256] =
{
0x3D1CB, 0x0A0E9, 0x01894, 0x01BC2, 0x00E92, 0x00EA6, 0x017DE, 0x05AF3,
0x08225, 0x01B26, 0x01E9E, 0x025F2, 0x02429, 0x0436B, 0x00F6D, 0x006F2,
0x02060, 0x00644, 0x00636, 0x0067F, 0x0044C, 0x004BD, 0x004D6, 0x0046E,
0x006D5, 0x00423, 0x004DE, 0x0047D, 0x004F9, 0x01186, 0x00AF5, 0x00D90,
0x0553B, 0x00487, 0x00686, 0x0042A, 0x00413, 0x003F4, 0x0041D, 0x0042E,
0x006BE, 0x00378, 0x0049C, 0x00352, 0x003C0, 0x0030C, 0x006D8, 0x00CE0,
0x02986, 0x011A2, 0x016F9, 0x00A7D, 0x0122A, 0x00EFD, 0x0082D, 0x0074B,
0x00A18, 0x0079D, 0x007B4, 0x003AC, 0x0046E, 0x006FC, 0x00686, 0x004B6,
0x01657, 0x017F0, 0x01C36, 0x019FE, 0x00E7E, 0x00ED3, 0x005D4, 0x005F4,
0x008A7, 0x00474, 0x0054B, 0x003CB, 0x00884, 0x004E0, 0x00530, 0x004AB,
0x006EA, 0x00436, 0x004F0, 0x004F2, 0x00490, 0x003C5, 0x00483, 0x004A2,
0x00543, 0x004CC, 0x005F9, 0x00640, 0x00A39, 0x00800, 0x009F2, 0x00CCB,
0x0096A, 0x00E01, 0x009C8, 0x00AF0, 0x00A73, 0x01802, 0x00E4F, 0x00B18,
0x037AD, 0x00C5C, 0x008AD, 0x00697, 0x00C88, 0x00AB3, 0x00DB8, 0x012BC,
0x00FFB, 0x00DBB, 0x014A8, 0x00FB0, 0x01F01, 0x0178F, 0x014F0, 0x00F54,
0x0131C, 0x00E9F, 0x011D6, 0x012C7, 0x016DC, 0x01900, 0x01851, 0x02063,
0x05ACB, 0x01E9E, 0x01BA1, 0x022E7, 0x0153D, 0x01183, 0x00E39, 0x01488,
0x014C0, 0x014D0, 0x014FA, 0x00DA4, 0x0099A, 0x0069E, 0x0071D, 0x00849,
0x0077C, 0x0047D, 0x005EC, 0x00557, 0x004D4, 0x00405, 0x004EA, 0x00450,
0x004DD, 0x003EE, 0x0047D, 0x00401, 0x004D9, 0x003B8, 0x00507, 0x003E5,
0x006B1, 0x003F1, 0x004A3, 0x0036F, 0x0044B, 0x003A1, 0x00436, 0x003B7,
0x00678, 0x003A2, 0x00481, 0x00406, 0x004EE, 0x00426, 0x004BE, 0x00424,
0x00655, 0x003A2, 0x00452, 0x00390, 0x0040A, 0x0037C, 0x00486, 0x003DE,
0x00497, 0x00352, 0x00461, 0x00387, 0x0043F, 0x00398, 0x00478, 0x00420,
0x00D86, 0x008C0, 0x0112D, 0x02F68, 0x01E4E, 0x00541, 0x0051B, 0x00CCE,
0x0079E, 0x00376, 0x003FF, 0x00458, 0x00435, 0x00412, 0x00425, 0x0042F,
0x005CC, 0x003E9, 0x00448, 0x00393, 0x0041C, 0x003E3, 0x0042E, 0x0036C,
0x00457, 0x00353, 0x00423, 0x00325, 0x00458, 0x0039B, 0x0044F, 0x00331,
0x0076B, 0x00750, 0x003D0, 0x00349, 0x00467, 0x003BC, 0x00487, 0x003B6,
0x01E6F, 0x003BA, 0x00509, 0x003A5, 0x00467, 0x00C87, 0x003FC, 0x0039F,
0x0054B, 0x00300, 0x00410, 0x002E9, 0x003B8, 0x00325, 0x00431, 0x002E4,
0x003F5, 0x00325, 0x003F0, 0x0031C, 0x003E4, 0x00421, 0x02CC1, 0x034C0
};
// static Huffman tree
static tree_t huffTree;
// received from MSG_* code
static int huffBitPos;
static qboolean huffInit = false;
/*
=======================================================================================
HUFFMAN TREE CONSTRUCTION
=======================================================================================
*/
/*
============
Huff_PrepareTree
============
*/
static _inline void Huff_PrepareTree( tree_t tree )
{
void **node;
memset( tree, 0, sizeof( tree_t ));
// create first node
node = &tree[263];
VALUE( tree[0] )++;
node[7] = NODE_NONE;
tree[2] = node;
tree[3] = node;
tree[4] = node;
tree[261] = node;
}
/*
============
Huff_GetNode
============
*/
static _inline void **Huff_GetNode( void **tree )
{
void **node;
int value;
node = tree[262];
if( !node )
{
value = VALUE( tree[1] )++;
node = &tree[value + 6407];
return node;
}
tree[262] = node[0];
return node;
}
/*
============
Huff_Swap
============
*/
static _inline void Huff_Swap( void **tree1, void **tree2, void **tree3 )
{
void **a, **b;
a = tree2[2];
if( a )
{
if( a[0] == tree2 )
a[0] = tree3;
else a[1] = tree3;
}
else tree1[2] = tree3;
b = tree3[2];
if( b )
{
if( b[0] == tree3 )
{
b[0] = tree2;
tree2[2] = b;
tree3[2] = a;
return;
}
b[1] = tree2;
tree2[2] = b;
tree3[2] = a;
return;
}
tree1[2] = tree2;
tree2[2] = NULL;
tree3[2] = a;
}
/*
============
Huff_SwapTrees
============
*/
static _inline void Huff_SwapTrees( void **tree1, void **tree2 )
{
void **temp;
temp = tree1[3];
tree1[3] = tree2[3];
tree2[3] = temp;
temp = tree1[4];
tree1[4] = tree2[4];
tree2[4] = temp;
if( tree1[3] == tree1 )
tree1[3] = tree2;
if( tree2[3] == tree2 )
tree2[3] = tree1;
temp = tree1[3];
if( temp ) temp[4] = tree1;
temp = tree2[3];
if( temp ) temp[4] = tree2;
temp = tree1[4];
if( temp ) temp[3] = tree1;
temp = tree2[4];
if( temp ) temp[3] = tree2;
}
/*
============
Huff_DeleteNode
============
*/
static _inline void Huff_DeleteNode( void **tree1, void **tree2 )
{
tree2[0] = tree1[262];
tree1[262] = tree2;
}
/*
============
Huff_IncrementFreq_r
============
*/
static void Huff_IncrementFreq_r( void **tree1, void **tree2 )
{
void **a, **b;
if( !tree2 ) return;
a = tree2[3];
if( a )
{
a = a[6];
if( a == tree2[6] )
{
b = tree2[5];
if( b[0] != tree2[2] )
Huff_Swap( tree1, b[0], tree2 );
Huff_SwapTrees( b[0], tree2 );
}
}
a = tree2[4];
if( a && a[6] == tree2[6] )
{
b = tree2[5];
b[0] = a;
}
else
{
a = tree2[5];
a[0] = 0;
Huff_DeleteNode( tree1, tree2[5] );
}
VALUE( tree2[6] )++;
a = tree2[3];
if( a && a[6] == tree2[6] )
{
tree2[5] = a[5];
}
else
{
a = Huff_GetNode( tree1 );
tree2[5] = a;
a[0] = tree2;
}
if( tree2[2] )
{
Huff_IncrementFreq_r( tree1, tree2[2] );
if( tree2[4] == tree2[2] )
{
Huff_SwapTrees( tree2, tree2[2] );
a = tree2[5];
if( a[0] == tree2 ) a[0] = tree2[2];
}
}
}
/*
============
Huff_AddReference
Insert 'ch' into the tree or increment it's frequency
============
*/
static void Huff_AddReference( void **tree, int ch )
{
void **a, **b, **c, **d;
int value;
ch &= 255;
if( tree[ch + 5] )
{
Huff_IncrementFreq_r( tree, tree[ch + 5] );
return; // already added
}
value = VALUE( tree[0] )++;
b = &tree[value * 8 + 263];
value = VALUE( tree[0] )++;
a = &tree[value * 8 + 263];
a[7] = NODE_NEXT;
a[6] = NODE_START;
d = tree[3];
a[3] = d[3];
if( a[3] )
{
d = a[3];
d[4] = a;
d = a[3];
if( d[6] == NODE_START )
{
a[5] = d[5];
}
else
{
d = Huff_GetNode( tree );
a[5] = d;
d[0] = a;
}
}
else
{
d = Huff_GetNode( tree );
a[5] = d;
d[0] = a;
}
d = tree[3];
d[3] = a;
a[4] = tree[3];
b[7] = NODE( ch );
b[6] = NODE_START;
d = tree[3];
b[3] = d[3];
if( b[3] )
{
d = b[3];
d[4] = b;
if( d[6] == NODE_START )
{
b[5] = d[5];
}
else
{
d = Huff_GetNode( tree );
b[5] = d;
d[0] = a;
}
}
else
{
d = Huff_GetNode( tree );
b[5] = d;
d[0] = b;
}
d = tree[3];
d[3] = b;
b[4] = tree[3];
b[1] = NULL;
b[0] = NULL;
d = tree[3];
c = d[2];
if( c )
{
if( c[0] == tree[3] )
c[0] = a;
else c[1] = a;
}
else tree[2] = a;
a[1] = b;
d = tree[3];
a[0] = d;
a[2] = d[2];
b[2] = a;
d = tree[3];
d[2] = a;
tree[ch + 5] = b;
Huff_IncrementFreq_r( tree, a[2] );
}
/*
=======================================================================================
BITSTREAM I/O
=======================================================================================
*/
/*
============
Huff_EmitBit
Put one bit into buffer
============
*/
static _inline void Huff_EmitBit( int bit, byte *buffer )
{
if(!(huffBitPos & 7)) buffer[huffBitPos >> 3] = 0;
buffer[huffBitPos >> 3] |= bit << (huffBitPos & 7);
huffBitPos++;
}
/*
============
Huff_GetBit
Read one bit from buffer
============
*/
static _inline int Huff_GetBit( byte *buffer )
{
int bit = buffer[huffBitPos >> 3] >> (huffBitPos & 7);
huffBitPos++;
return (bit & 1);
}
/*
============
Huff_EmitPathToByte
============
*/
static _inline void Huff_EmitPathToByte( void **tree, void **subtree, byte *buffer )
{
if( tree[2] ) Huff_EmitPathToByte( tree[2], tree, buffer );
if( !subtree ) return;
// emit tree walking control bits
if( tree[1] == subtree )
Huff_EmitBit( 1, buffer );
else Huff_EmitBit( 0, buffer );
}
/*
============
Huff_GetByteFromTree
Get one byte using dynamic or static tree
============
*/
static _inline int Huff_GetByteFromTree( void **tree, byte *buffer )
{
if( !tree ) return 0;
// walk through the tree until we get a value
while( tree[7] == NODE_NEXT )
{
if( !Huff_GetBit( buffer ))
tree = tree[0];
else tree = tree[1];
if( !tree ) return 0;
}
return VALUE( tree[7] );
}
/*
============
Huff_EmitByteDynamic
Emit one byte using dynamic tree
============
*/
static void Huff_EmitByteDynamic( void **tree, int value, byte *buffer )
{
void **subtree;
int i;
// if byte was already referenced, emit path to it
subtree = tree[value + 5];
if( subtree )
{
if( subtree[2] )
Huff_EmitPathToByte( subtree[2], subtree, buffer );
return;
}
// byte was not referenced, just emit 8 bits
Huff_EmitByteDynamic( tree, NOT_REFERENCED, buffer );
for( i = 7; i >= 0; i-- )
{
Huff_EmitBit( (value >> i) & 1, buffer );
}
}
/*
=======================================================================================
PUBLIC INTERFACE
=======================================================================================
*/
/*
============
Huff_CompressPacket
Compress message using dynamic Huffman tree,
beginning from specified offset
============
*/
void Huff_CompressPacket( sizebuf_t *msg, int offset )
{
tree_t tree;
byte buffer[NET_MAX_PAYLOAD];
byte *data;
int outLen;
int i, inLen;
data = MSG_GetData( msg ) + offset;
inLen = MSG_GetNumBytesWritten( msg ) - offset;
if( inLen <= 0 || inLen >= NET_MAX_PAYLOAD )
return;
Huff_PrepareTree( tree );
buffer[0] = inLen >> 8;
buffer[1] = inLen & 0xFF;
huffBitPos = 16;
for( i = 0; i < inLen; i++ )
{
Huff_EmitByteDynamic( tree, data[i], buffer );
Huff_AddReference( tree, data[i] );
}
outLen = (huffBitPos >> 3) + 1;
msg->iCurBit = (offset + outLen) << 3;
memcpy( data, buffer, outLen );
}
/*
============
Huff_DecompressPacket
Decompress message using dynamic Huffman tree,
beginning from specified offset
============
*/
void Huff_DecompressPacket( sizebuf_t *msg, int offset )
{
tree_t tree;
byte buffer[NET_MAX_PAYLOAD];
byte *data;
int outLen;
int inLen;
int ch, i, j;
data = MSG_GetData( msg ) + offset;
inLen = MSG_GetMaxBytes( msg ) - offset;
if( inLen <= 0 ) return;
Huff_PrepareTree( tree );
outLen = ( data[0] << 8 ) + data[1];
huffBitPos = 16;
if( outLen > NET_MAX_PAYLOAD - offset )
outLen = NET_MAX_PAYLOAD - offset;
for( i = 0; i < outLen; i++ )
{
if(( huffBitPos >> 3 ) > inLen )
{
buffer[i] = 0;
break;
}
ch = Huff_GetByteFromTree( tree[2], data );
if( ch == NOT_REFERENCED )
{
ch = 0; // just read 8 bits
for( j = 0; j < 8; j++ )
{
ch <<= 1;
ch |= Huff_GetBit( data );
}
}
buffer[i] = ch;
Huff_AddReference( tree, ch );
}
msg->nDataBits = ( offset + outLen ) << 3;
memcpy( data, buffer, outLen );
}
/*
============
Huff_Init
============
*/
void Huff_Init( void )
{
int i, j;
if( huffInit ) return;
// build empty tree
Huff_PrepareTree( huffTree );
// add all pre-defined byte references
for( i = 0; i < 256; i++ )
for( j = 0; j < huff_tree[i]; j++ )
Huff_AddReference( huffTree, i );
huffInit = true;
}

View File

@ -38,7 +38,7 @@ GNU General Public License for more details.
// NETWORKING INFO
// This is the packet payload without any header bytes (which are attached for actual sending)
#define NET_MAX_PAYLOAD 80000
#define NET_MAX_PAYLOAD 96000
// This is the payload plus any header info (excluding UDP header)
@ -130,9 +130,7 @@ typedef struct netchan_s
netsrc_t sock; // NS_SERVER or NS_CLIENT, depending on channel.
netadr_t remote_address; // address this channel is talking to.
int qport; // qport value to write when transmitting
qboolean compress; // enable huffman compression
double last_received; // for timeouts
double last_sent; // for retransmits
@ -185,10 +183,7 @@ typedef struct netchan_s
// added for net_speeds
size_t total_sended;
size_t total_sended_uncompressed;
size_t total_received;
size_t total_received_uncompressed;
} netchan_t;
extern netadr_t net_from;
@ -216,9 +211,4 @@ qboolean Netchan_CanPacket( netchan_t *chan );
void Netchan_FragSend( netchan_t *chan );
void Netchan_Clear( netchan_t *chan );
// huffman compression
void Huff_Init( void );
void Huff_CompressPacket( sizebuf_t *msg, int offset );
void Huff_DecompressPacket( sizebuf_t *msg, int offset );
#endif//NET_MSG_H

View File

@ -65,6 +65,7 @@ GNU General Public License for more details.
#define svc_resourcelist 43 // [short][...]
#define svc_deltamovevars 44 // [movevars_t]
#define svc_customization 45 // <see code>
#define svc_crosshairangle 47 // [byte][byte]
#define svc_soundfade 48 // [float*4] sound fade parms

View File

@ -23,9 +23,9 @@ static long idum = 0;
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define AM (1.0/IM)
#define EPS 1.2e-7
#define NDIV (1 + (IM - 1) / NTAB)
#define AM (1.0 / IM)
#define RNMX (1.0 - EPS)
void COM_SetRandomSeed( long lSeed )
@ -41,15 +41,14 @@ void COM_SetRandomSeed( long lSeed )
long lran1( void )
{
int j;
long k;
static long iy = 0;
static long iv[NTAB];
int j;
long k;
static long iy = 0;
static long iv[NTAB];
if( idum <= 0 || !iy )
{
if(-(idum) < 1) idum=1;
if( -(idum) < 1 ) idum = 1;
else idum = -(idum);
for( j = NTAB + 7; j >= 0; j-- )
@ -59,10 +58,11 @@ long lran1( void )
if( idum < 0 ) idum += IM;
if( j < NTAB ) iv[j] = idum;
}
iy = iv[0];
}
k = (idum)/IQ;
k = (idum) / IQ;
idum = IA * (idum - k * IQ) - IR * k;
if( idum < 0 ) idum += IM;
j = iy / NDIV;
@ -72,7 +72,7 @@ long lran1( void )
return iy;
}
// fran1 -- return a random floating-point number on the interval [0,1)
// fran1 -- return a random floating-point number on the interval [0,1]
float fran1( void )
{
float temp = (float)AM * lran1();
@ -85,20 +85,20 @@ float Com_RandomFloat( float flLow, float flHigh )
{
float fl;
if( idum == 0 ) COM_SetRandomSeed(0);
if( idum == 0 ) COM_SetRandomSeed( 0 );
fl = fran1(); // float in [0, 1)
fl = fran1(); // float in [0,1]
return (fl * (flHigh - flLow)) + flLow; // float in [low, high)
}
long Com_RandomLong( long lLow, long lHigh )
{
dword maxAcceptable;
dword n, x = lHigh-lLow + 1;
dword n, x = lHigh - lLow + 1;
if( idum == 0 ) COM_SetRandomSeed(0);
if( idum == 0 ) COM_SetRandomSeed( 0 );
if( x <= 0 || MAX_RANDOM_RANGE < x-1 )
if( x <= 0 || MAX_RANDOM_RANGE < x - 1 )
return lLow;
// The following maps a uniform distribution on the interval [0, MAX_RANDOM_RANGE]
@ -108,7 +108,7 @@ long Com_RandomLong( long lLow, long lHigh )
// the average number of times through the loop is 2. For cases where x is
// much smaller than MAX_RANDOM_RANGE, the average number of times through the
// loop is very close to 1.
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x );
maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE + 1) % x );
do
{
n = lran1();

View File

@ -48,8 +48,15 @@ create buffer, that contain clipboard
*/
char *Sys_GetClipboardData( void )
{
char *data = NULL;
char *cliptext;
static char *data = NULL;
char *cliptext;
if( data )
{
// release previous cbd
Z_Free( data );
data = NULL;
}
if( OpenClipboard( NULL ) != 0 )
{
@ -66,6 +73,7 @@ char *Sys_GetClipboardData( void )
}
CloseClipboard();
}
return data;
}
@ -259,9 +267,9 @@ qboolean _Sys_GetParmFromCmdLine( char *parm, char *out, size_t size )
{
int argc = Sys_CheckParm( parm );
if( !argc ) return false;
if( !out ) return false;
if( !host.argv[argc + 1] ) return false;
if( !argc || !out || !host.argv[argc + 1] )
return false;
Q_strncpy( out, host.argv[argc+1], size );
return true;
@ -554,22 +562,20 @@ void Sys_Print( const char *pMsg )
if( msg[i] == '\n' && msg[i+1] == '\r' )
{
b[0] = '\r';
b[1] = '\n';
c[0] = '\n';
b[1] = c[0] = '\n';
b += 2, c++;
i++;
}
else if( msg[i] == '\r' )
{
b[0] = '\r';
b[0] = c[0] = '\r';
b[1] = '\n';
b += 2;
b += 2, c++;
}
else if( msg[i] == '\n' )
{
b[0] = '\r';
b[1] = '\n';
c[0] = '\n';
b[1] = c[0] = '\n';
b += 2, c++;
}
else if( msg[i] == '\35' || msg[i] == '\36' || msg[i] == '\37' )
@ -588,7 +594,7 @@ void Sys_Print( const char *pMsg )
i++;
}
*b = *c = 0; // cutoff garbage
*b = *c = 0; // terminator
Sys_PrintLog( logbuf );
Con_WinPrint( buffer );

View File

@ -86,8 +86,6 @@ void Sys_SetClipboardData( const byte *buffer, size_t size );
qboolean _Sys_GetParmFromCmdLine( char *parm, char *out, size_t size );
void Sys_ShellExecute( const char *path, const char *parms, qboolean exit );
void Sys_SendKeyEvents( void );
qboolean Sys_CheckMMX( void );
qboolean Sys_CheckSSE( void );
void Sys_Print( const char *pMsg );
void Sys_PrintLog( const char *pMsg );
void Sys_InitLog( void );

View File

@ -15,8 +15,8 @@ GNU General Public License for more details.
#include "common.h"
#define MEMCLUMPSIZE (65536 - 1536) // give malloc padding so we can't waste most of a page at the end
#define MEMUNIT 8 // smallest unit we care about is this many bytes
#define MEMCLUMPSIZE (65536 - 1536) // give malloc padding so we can't waste most of a page at the end
#define MEMBITS (MEMCLUMPSIZE / MEMUNIT)
#define MEMBITINTS (MEMBITS / 32)
@ -71,7 +71,7 @@ void *_Mem_Alloc( byte *poolptr, size_t size, const char *filename, int fileline
int i, j, k, needed, endbit, largest;
memclump_t *clump, **clumpchainpointer;
memheader_t *mem;
mempool_t *pool = (mempool_t *)((byte *)poolptr);
mempool_t *pool = (mempool_t *)poolptr;
if( size <= 0 ) return NULL;
if( poolptr == NULL ) Sys_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)\n", filename, fileline );
@ -165,16 +165,9 @@ static const char *Mem_CheckFilename( const char *filename )
int i;
if( !out ) return dummy;
for( i = 0; i < 128; i++, out++ )
{
if( *out == '\0' )
break; // valid name
}
if( i == 128 )
return dummy;
if( out == '\0' ) break; // valid name
if( i == 128 ) return dummy;
return filename;
}
@ -264,8 +257,8 @@ void _Mem_Free( void *data, const char *filename, int fileline )
void *_Mem_Realloc( byte *poolptr, void *memptr, size_t size, const char *filename, int fileline )
{
char *nb;
memheader_t *memhdr = NULL;
char *nb;
if( size <= 0 ) return memptr; // no need to reallocate
@ -307,12 +300,12 @@ byte *_Mem_AllocPool( const char *name, const char *filename, int fileline )
pool->next = poolchain;
poolchain = pool;
return (byte *)((mempool_t *)pool);
return (byte *)pool;
}
void _Mem_FreePool( byte **poolptr, const char *filename, int fileline )
{
mempool_t *pool = (mempool_t *)((byte *)*poolptr );
mempool_t *pool = (mempool_t *)*poolptr;
mempool_t **chainaddress;
if( pool )
@ -335,7 +328,7 @@ void _Mem_FreePool( byte **poolptr, const char *filename, int fileline )
void _Mem_EmptyPool( byte *poolptr, const char *filename, int fileline )
{
mempool_t *pool = (mempool_t *)((byte *)poolptr);
mempool_t *pool = (mempool_t *)poolptr;
if( poolptr == NULL ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
@ -374,7 +367,7 @@ Check pointer for memory
qboolean Mem_IsAllocatedExt( byte *poolptr, void *data )
{
mempool_t *pool = NULL;
if( poolptr ) pool = (mempool_t *)((byte *)poolptr);
if( poolptr ) pool = (mempool_t *)poolptr;
return Mem_CheckAlloc( pool, data );
}
@ -383,7 +376,9 @@ void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline )
{
memheader_t *mem;
if( data == NULL ) Sys_Error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)\n", filename, fileline );
if( data == NULL )
Sys_Error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)\n", filename, fileline );
mem = (memheader_t *)((byte *) data - sizeof(memheader_t));
if( mem->sentinel1 != MEMHEADER_SENTINEL1 )

View File

@ -384,10 +384,6 @@ SOURCE=.\common\net_encode.c
# End Source File
# Begin Source File
SOURCE=.\common\net_huff.c
# End Source File
# Begin Source File
SOURCE=.\common\network.c
# End Source File
# Begin Source File

View File

@ -37,7 +37,7 @@ extern int SV_UPDATE_BACKUP;
// hostflags
#define SVF_SKIPLOCALHOST BIT( 0 )
#define SVF_PLAYERSONLY BIT( 1 )
#define SVF_PORTALPASS BIT( 2 ) // we are do portal pass
#define SVF_MERGE_VISIBILITY BIT( 2 ) // we are do portal pass
// mapvalid flags
#define MAP_IS_EXIST BIT( 0 )
@ -53,10 +53,18 @@ extern int SV_UPDATE_BACKUP;
#define MAKE_STRING(str) SV_MakeString( str )
#define MAX_PUSHED_ENTS 256
#define MAX_CAMERAS 32
#define MAX_VIEWENTS 128
#define FCL_RESEND_USERINFO BIT( 0 )
#define FCL_RESEND_MOVEVARS BIT( 1 )
#define FCL_SKIP_NET_MESSAGE BIT( 2 )
#define FCL_SEND_NET_MESSAGE BIT( 3 )
#define FCL_PREDICT_MOVEMENT BIT( 4 ) // movement prediction is enabled
#define FCL_LOCAL_WEAPONS BIT( 5 ) // weapon prediction is enabled
#define FCL_LAG_COMPENSATION BIT( 6 ) // lag compensation is enabled
#define FCL_FAKECLIENT BIT( 7 ) // this client is a fake player controlled by the game DLL
#define FCL_HLTV_PROXY BIT( 8 ) // this is a proxy for a HLTV client (spectator)
#define DVIS_PVS 0
#define DVIS_PHS 1
typedef enum
{
@ -114,7 +122,9 @@ typedef struct server_s
int viewentity; // applied on client restore. this is temporare place
// until client connected
double time; // sv.time += host.frametime
double time; // sv.time += sv.frametime
double time_residual; // unclamped
float frametime; // 1.0 / sv_fps->value
int net_framenum; // to avoid send edicts twice through portals
int hostflags; // misc server flags: predicting etc
@ -143,10 +153,6 @@ typedef struct server_s
sv_baselines_t instanced; // instanced baselines
// unreliable data to send to clients.
sizebuf_t datagram;
byte datagram_buf[NET_MAX_PAYLOAD];
// reliable data to send to clients.
sizebuf_t reliable_datagram; // copied to all clients at end of frame
byte reliable_datagram_buf[NET_MAX_PAYLOAD];
@ -165,6 +171,7 @@ typedef struct server_s
uint checksum; // for catching cheater maps
qboolean write_bad_message; // just for debug
qboolean simulating; // physics is running
qboolean paused;
} server_t;
@ -175,7 +182,7 @@ typedef struct
float latency;
clientdata_t clientdata;
weapon_data_t weapondata[64];
weapon_data_t weapondata[MAX_LOCAL_WEAPONS];
int num_entities;
int first_entity; // into the circular sv_packet_entities[]
@ -185,35 +192,24 @@ typedef struct sv_client_s
{
cl_state_t state;
char name[32]; // extracted from userinfo, color string allowed
int flags; // client flags, some info
char userinfo[MAX_INFO_STRING]; // name, etc (received from client)
char physinfo[MAX_INFO_STRING]; // set on server (transmit to client)
qboolean send_message;
qboolean skip_message;
qboolean local_weapons; // enable weapon predicting
qboolean lag_compensation; // enable lag compensation
qboolean hltv_proxy; // this is spectator proxy (hltv)
netchan_t netchan;
int chokecount; // number of messages rate supressed
int delta_sequence; // -1 = no compression.
double next_messagetime; // time when we should send next world state update
double cl_updaterate; // default time to wait for next message
double next_checkpingtime; // time to send all players pings to client
double cl_updaterate; // client requested updaterate
double timebase; // client timebase
customization_t customization; // player customization linked list
resource_t resource1;
resource_t resource2; // <mapname.res> from client (server downloading)
qboolean sendmovevars;
qboolean sendinfo;
qboolean fakeclient; // This client is a fake player controlled by the game DLL
usercmd_t lastcmd; // for filling in big drops
double last_cmdtime;
@ -231,8 +227,8 @@ typedef struct sv_client_s
edict_t *pViewEntity; // svc_setview member
int messagelevel; // for filtering printed messages
edict_t *cameras[MAX_CAMERAS]; // list of portal cameras in player PVS
int num_cameras; // num of portal cameras that can merge PVS
edict_t *viewentity[MAX_VIEWENTS]; // list of portal cameras in player PVS
int num_viewents; // num of portal cameras that can merge PVS
// the datagram is written to by sound calls, prints, temp ents, etc.
// it can be harmlessly overflowed.
@ -269,8 +265,8 @@ typedef struct sv_client_s
typedef struct
{
netadr_t adr;
int challenge;
double time;
int challenge;
qboolean connected;
} challenge_t;
@ -448,6 +444,7 @@ void SV_PrepWorldFrame( void );
void SV_ProcessFile( sv_client_t *cl, char *filename );
void SV_SendResourceList( sv_client_t *cl );
void SV_AddToMaster( netadr_t from, sizebuf_t *msg );
qboolean SV_IsSimulating( void );
void Master_Add( void );
void Master_Heartbeat( void );
void Master_Packet( void );
@ -491,7 +488,7 @@ void SV_WaterMove( edict_t *ent );
//
void SV_SendClientMessages( void );
void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... );
void SV_BroadcastPrintf( int level, char *fmt, ... );
void SV_BroadcastPrintf( sv_client_t *ignore, int level, char *fmt, ... );
void SV_BroadcastCommand( char *fmt, ... );
//
@ -502,7 +499,6 @@ void SV_RefreshUserinfo( void );
void SV_GetChallenge( netadr_t from );
void SV_DirectConnect( netadr_t from );
void SV_TogglePause( const char *msg );
void SV_PutClientInServer( edict_t *ent );
qboolean SV_ShouldUpdatePing( sv_client_t *cl );
const char *SV_GetClientIDString( sv_client_t *cl );
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg );
@ -552,6 +548,7 @@ void SV_FreeEdict( edict_t *pEdict );
void SV_InitEdict( edict_t *pEdict );
const char *SV_ClassName( const edict_t *e );
void SV_SetModel( edict_t *ent, const char *name );
void SV_FreePrivateData( edict_t *pEdict );
void SV_CopyTraceToGlobal( trace_t *trace );
void SV_SetMinMaxSize( edict_t *e, const float *min, const float *max );
edict_t* SV_FindEntityByString( edict_t *pStartEdict, const char *pszField, const char *pszValue );
@ -612,7 +609,6 @@ void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs )
//
void SV_ClearWorld( void );
void SV_UnlinkEdict( edict_t *ent );
qboolean SV_HeadnodeVisible( mnode_t *node, byte *visbits, int *lastleaf );
void SV_ClipMoveToEntity( 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 );
trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end );

View File

@ -97,10 +97,10 @@ A connection request that did not come from the master
void SV_DirectConnect( netadr_t from )
{
char userinfo[MAX_INFO_STRING];
char physinfo[MAX_PHYSINFO_STRING];
sv_client_t temp, *cl, *newcl;
char physinfo[512];
int i, edictnum;
int qport, version;
int i, edictnum;
int count = 0;
int challenge;
edict_t *ent;
@ -245,9 +245,9 @@ gotnewcl:
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect" );
newcl->state = cs_connected;
newcl->cl_updaterate = 0.05; // 20 fps as default
newcl->lastmessage = host.realtime;
newcl->lastconnect = host.realtime;
newcl->cl_updaterate = 0.05; // 20 fps as default
newcl->delta_sequence = -1;
// parse some info from the info strings (this can override cl_updaterate)
@ -280,16 +280,7 @@ void SV_DisconnectClient( edict_t *pClient )
// don't send to other clients
pClient->v.modelindex = 0;
if( pClient->pvPrivateData != NULL )
{
// NOTE: new interface can be missing
if( svgame.dllFuncs2.pfnOnFreeEntPrivateData != NULL )
svgame.dllFuncs2.pfnOnFreeEntPrivateData( pClient );
// clear any dlls data but keep engine data
Mem_Free( pClient->pvPrivateData );
pClient->pvPrivateData = NULL;
}
SV_FreePrivateData( pClient );
// invalidate serial number
pClient->serialnumber++;
@ -355,9 +346,9 @@ edict_t *SV_FakeConnect( const char *netname )
ent = EDICT_NUM( edictnum );
newcl->edict = ent;
newcl->challenge = -1; // fake challenge
newcl->fakeclient = true;
newcl->delta_sequence = -1;
newcl->userid = g_userid++; // create unique userid
SetBits( newcl->flags, FCL_FAKECLIENT );
// get the game a chance to reject this connection or modify the userinfo
if( !SV_ClientConnect( ent, userinfo ))
@ -371,11 +362,11 @@ edict_t *SV_FakeConnect( const char *netname )
MsgDev( D_NOTE, "Bot %i connecting with challenge %p\n", i, -1 );
ent->v.flags |= FL_FAKECLIENT; // mark it as fakeclient
SetBits( ent->v.flags, FL_FAKECLIENT ); // mark it as fakeclient
newcl->state = cs_spawned;
newcl->lastmessage = host.realtime; // don't timeout
newcl->lastconnect = host.realtime;
newcl->sendinfo = true;
SetBits( newcl->flags, FCL_RESEND_USERINFO );
return ent;
}
@ -425,21 +416,19 @@ void SV_DropClient( sv_client_t *drop )
return; // already dropped
// add the disconnect
if( !drop->fakeclient )
{
if( !FBitSet( drop->flags, FCL_FAKECLIENT ))
MSG_WriteByte( &drop->netchan.message, svc_disconnect );
}
// let the game known about client state
SV_DisconnectClient( drop->edict );
drop->fakeclient = false;
drop->hltv_proxy = false;
ClearBits( drop->flags, FCL_FAKECLIENT );
ClearBits( drop->flags, FCL_HLTV_PROXY );
drop->state = cs_zombie; // become free in a few seconds
drop->name[0] = 0;
if( drop->frames )
Mem_Free( drop->frames ); // fakeclients doesn't have frames
Mem_Free( drop->frames ); // release delta
drop->frames = NULL;
if( NET_CompareBaseAdr( drop->netchan.remote_address, host.rd.address ) )
@ -492,7 +481,7 @@ void SV_BeginRedirect( netadr_t adr, int target, char *buffer, int buffersize, v
void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
{
if( svs.currentPlayer && svs.currentPlayer->fakeclient )
if( svs.currentPlayer && FBitSet( svs.currentPlayer->flags, FCL_FAKECLIENT ))
return;
switch( dest )
@ -703,6 +692,7 @@ void SV_BuildNetAnswer( netadr_t from )
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
return;
}
if( type == NETAPI_REQUEST_PING )
{
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, "" );
@ -798,8 +788,8 @@ Redirect all printfs
*/
void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
{
char remaining[1024];
static char outputbuf[2048];
char remaining[1024];
int i;
MsgDev( D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString( from ), MSG_GetData( msg ) + 4 );
@ -834,7 +824,7 @@ int SV_CalcPing( sv_client_t *cl )
client_frame_t *frame;
// bots don't have a real ping
if( cl->fakeclient || !cl->frames )
if( FBitSet( cl->flags, FCL_FAKECLIENT ) || !cl->frames )
return 5;
count = 0;
@ -988,11 +978,14 @@ SV_RefreshUserinfo
*/
void SV_RefreshUserinfo( void )
{
int i;
sv_client_t *cl;
int i;
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
if( cl->state >= cs_connected ) cl->sendinfo = true;
{
if( cl->state >= cs_connected )
SetBits( cl->flags, FCL_RESEND_USERINFO );
}
}
/*
@ -1021,10 +1014,10 @@ if this person needs ping data.
*/
qboolean SV_ShouldUpdatePing( sv_client_t *cl )
{
if( !cl->hltv_proxy )
if( !FBitSet( cl->flags, FCL_HLTV_PROXY ))
{
SV_CalcPing( cl );
return cl->lastcmd.buttons & IN_SCORE; // they are viewing the scoreboard. Send them pings.
return FBitSet( cl->lastcmd.buttons, IN_SCORE ); // they are viewing the scoreboard. Send them pings.
}
if( host.realtime > cl->next_checkpingtime )
@ -1085,85 +1078,85 @@ Called when a player connects to a server or respawns in
a deathmatch.
============
*/
void SV_PutClientInServer( edict_t *ent )
void SV_PutClientInServer( sv_client_t *cl )
{
sv_client_t *client;
edict_t *ent = cl->edict;
client = SV_ClientFromEdict( ent, true );
ASSERT( client != NULL );
// now client is spawned
cl->state = cs_spawned;
if( !sv.loadgame )
{
client->hltv_proxy = Q_atoi( Info_ValueForKey( client->userinfo, "hltv" )) ? true : false;
if( Q_atoi( Info_ValueForKey( cl->userinfo, "hltv" )))
SetBits( cl->flags, FCL_HLTV_PROXY );
if( client->hltv_proxy )
ent->v.flags |= FL_PROXY;
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
SetBits( ent->v.flags, FL_PROXY );
else ent->v.flags = 0;
ent->v.netname = MAKE_STRING( client->name );
ent->v.netname = MAKE_STRING( cl->name );
// fisrt entering
svgame.globals->time = sv.time;
svgame.dllFuncs.pfnClientPutInServer( ent );
if( sv.background ) // don't attack player in background mode
ent->v.flags |= (FL_GODMODE|FL_NOTARGET);
SetBits( ent->v.flags, FL_GODMODE|FL_NOTARGET );
client->pViewEntity = NULL; // reset pViewEntity
cl->pViewEntity = NULL; // reset pViewEntity
if( svgame.globals->cdAudioTrack )
{
MSG_WriteByte( &client->netchan.message, svc_stufftext );
MSG_WriteString( &client->netchan.message, va( "cd loop %3d\n", svgame.globals->cdAudioTrack ));
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, va( "cd loop %3d\n", svgame.globals->cdAudioTrack ));
svgame.globals->cdAudioTrack = 0;
}
}
else
{
// enable dev-mode to prevent crash cheat-protecting from Invasion mod
if( ent->v.flags & (FL_GODMODE|FL_NOTARGET) && !Q_stricmp( GI->gamefolder, "invasion" ))
SV_ExecuteClientCommand( client, "test\n" );
if( FBitSet( ent->v.flags, FL_GODMODE|FL_NOTARGET ) && !Q_stricmp( GI->gamefolder, "invasion" ))
SV_ExecuteClientCommand( cl, "test\n" );
// NOTE: we needs to setup angles on restore here
if( ent->v.fixangle == 1 )
{
MSG_WriteByte( &client->netchan.message, svc_setangle );
MSG_WriteBitAngle( &client->netchan.message, ent->v.angles[0], 16 );
MSG_WriteBitAngle( &client->netchan.message, ent->v.angles[1], 16 );
MSG_WriteBitAngle( &client->netchan.message, ent->v.angles[2], 16 );
MSG_WriteByte( &cl->netchan.message, svc_setangle );
MSG_WriteBitAngle( &cl->netchan.message, ent->v.angles[0], 16 );
MSG_WriteBitAngle( &cl->netchan.message, ent->v.angles[1], 16 );
MSG_WriteBitAngle( &cl->netchan.message, ent->v.angles[2], 16 );
ent->v.fixangle = 0;
}
ent->v.effects |= EF_NOINTERP;
SetBits( ent->v.effects, EF_NOINTERP );
// reset weaponanim
MSG_WriteByte( &client->netchan.message, svc_weaponanim );
MSG_WriteByte( &client->netchan.message, 0 );
MSG_WriteByte( &client->netchan.message, 0 );
MSG_WriteByte( &cl->netchan.message, svc_weaponanim );
MSG_WriteByte( &cl->netchan.message, 0 );
MSG_WriteByte( &cl->netchan.message, 0 );
// trigger_camera restored here
if( sv.viewentity > 0 && sv.viewentity < GI->max_edicts )
client->pViewEntity = EDICT_NUM( sv.viewentity );
else client->pViewEntity = NULL;
cl->pViewEntity = EDICT_NUM( sv.viewentity );
else cl->pViewEntity = NULL;
}
// reset client times
client->last_cmdtime = 0.0;
client->last_movetime = 0.0;
client->next_movetime = 0.0;
cl->last_cmdtime = 0.0;
cl->last_movetime = 0.0;
cl->next_movetime = 0.0;
if( !client->fakeclient )
if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
{
int viewEnt;
// resend the signon
MSG_WriteBits( &client->netchan.message, MSG_GetData( &sv.signon ), MSG_GetNumBitsWritten( &sv.signon ));
MSG_WriteBits( &cl->netchan.message, MSG_GetData( &sv.signon ), MSG_GetNumBitsWritten( &sv.signon ));
if( client->pViewEntity )
viewEnt = NUM_FOR_EDICT( client->pViewEntity );
else viewEnt = NUM_FOR_EDICT( client->edict );
if( cl->pViewEntity )
viewEnt = NUM_FOR_EDICT( cl->pViewEntity );
else viewEnt = NUM_FOR_EDICT( cl->edict );
MSG_WriteByte( &client->netchan.message, svc_setview );
MSG_WriteWord( &client->netchan.message, viewEnt );
MSG_WriteByte( &cl->netchan.message, svc_setview );
MSG_WriteWord( &cl->netchan.message, viewEnt );
}
// clear any temp states
@ -1186,7 +1179,7 @@ void SV_TogglePause( const char *msg )
sv.paused ^= 1;
if( msg ) SV_BroadcastPrintf( PRINT_HIGH, "%s", msg );
if( msg ) SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s", msg );
// send notification to all clients
MSG_WriteByte( &sv.reliable_datagram, svc_setpause );
@ -1211,11 +1204,10 @@ This will be sent on the initial connection and upon each server load.
void SV_New_f( sv_client_t *cl )
{
int playernum;
edict_t *ent;
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "new is not valid from the console\n" );
MsgDev( D_INFO, "'new' is not valid from the console\n" );
return;
}
@ -1242,8 +1234,7 @@ void SV_New_f( sv_client_t *cl )
if( sv.state == ss_active )
{
// set up the entity for the client
ent = EDICT_NUM( playernum + 1 );
cl->edict = ent;
cl->edict = EDICT_NUM( playernum + 1 );
// NOTE: custom resources download is disabled until is done
if( /*sv_maxclients->integer ==*/ 1 )
@ -1272,7 +1263,7 @@ void SV_ContinueLoading_f( sv_client_t *cl )
{
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "continueloading is not valid from the console\n" );
MsgDev( D_INFO, "'continueloading' is not valid from the console\n" );
return;
}
@ -1362,14 +1353,14 @@ void SV_WriteModels_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "modellist is not valid from the console\n" );
MsgDev( D_INFO, "'modellist' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "modellist from different level\n" );
MsgDev( D_INFO, "'modellist' from different level\n" );
SV_New_f( cl );
return;
}
@ -1408,14 +1399,14 @@ void SV_WriteSounds_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "soundlist is not valid from the console\n" );
MsgDev( D_INFO, "'soundlist' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "soundlist from different level\n" );
MsgDev( D_INFO, "'soundlist' from different level\n" );
SV_New_f( cl );
return;
}
@ -1454,14 +1445,14 @@ void SV_WriteEvents_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "eventlist is not valid from the console\n" );
MsgDev( D_INFO, "'eventlist' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "eventlist from different level\n" );
MsgDev( D_INFO, "'eventlist' from different level\n" );
SV_New_f( cl );
return;
}
@ -1500,14 +1491,14 @@ void SV_WriteLightstyles_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "lightstyles is not valid from the console\n" );
MsgDev( D_INFO, "'lightstyles' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "lightstyles from different level\n" );
MsgDev( D_INFO, "'lightstyles' from different level\n" );
SV_New_f( cl );
return;
}
@ -1548,14 +1539,14 @@ void SV_UserMessages_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "usermessages is not valid from the console\n" );
MsgDev( D_INFO, "'usermsgs' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "usermessages from different level\n" );
MsgDev( D_INFO, "'usermsgs' from different level\n" );
SV_New_f( cl );
return;
}
@ -1598,14 +1589,14 @@ void SV_DeltaInfo_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "deltainfo is not valid from the console\n" );
MsgDev( D_INFO, "'deltainfo' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "deltainfo from different level\n" );
MsgDev( D_INFO, "'deltainfo' from different level\n" );
SV_New_f( cl );
return;
}
@ -1661,14 +1652,14 @@ void SV_Baselines_f( sv_client_t *cl )
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "baselines is not valid from the console\n" );
MsgDev( D_INFO, "'baselines' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
MsgDev( D_INFO, "baselines from different level\n" );
MsgDev( D_INFO, "'baselines' from different level\n" );
SV_New_f( cl );
return;
}
@ -1706,20 +1697,19 @@ void SV_Begin_f( sv_client_t *cl )
{
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "begin is not valid from the console\n" );
MsgDev( D_INFO, "'begin' is not valid from the console\n" );
return;
}
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
Msg( "begin from different level\n" );
Msg( "'begin' from different level\n" );
SV_New_f( cl );
return;
}
cl->state = cs_spawned;
SV_PutClientInServer( cl->edict );
SV_PutClientInServer( cl );
// if we are paused, tell the client
if( sv.paused )
@ -1771,7 +1761,7 @@ void SV_Pause_f( sv_client_t *cl )
return;
}
if( cl->hltv_proxy )
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
{
SV_ClientPrintf( cl, PRINT_HIGH, "Spectators can not pause.\n" );
return;
@ -1796,7 +1786,7 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
{
int i, dupc = 1;
edict_t *ent = cl->edict;
string temp1, temp2;
string name1, name2;
sv_client_t *current;
char *val;
@ -1805,26 +1795,26 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
Q_strncpy( cl->userinfo, userinfo, sizeof( cl->userinfo ));
val = Info_ValueForKey( cl->userinfo, "name" );
Q_strncpy( temp2, val, sizeof( temp2 ));
COM_TrimSpace( temp2, temp1 );
Q_strncpy( name2, val, sizeof( name2 ));
COM_TrimSpace( name2, name1 );
if( !Q_stricmp( temp1, "console" )) // keyword came from OSHLDS
if( !Q_stricmp( name1, "console" ))
{
Info_SetValueForKey( cl->userinfo, "name", "unnamed" );
val = Info_ValueForKey( cl->userinfo, "name" );
}
else if( Q_strcmp( temp1, val ))
else if( Q_strcmp( name1, val ))
{
Info_SetValueForKey( cl->userinfo, "name", temp1 );
Info_SetValueForKey( cl->userinfo, "name", name1 );
val = Info_ValueForKey( cl->userinfo, "name" );
}
if( !Q_strlen( temp1 ) )
if( !Q_strlen( name1 ))
{
Info_SetValueForKey( cl->userinfo, "name", "unnamed" );
val = Info_ValueForKey( cl->userinfo, "name" );
Q_strncpy( temp2, "unnamed", sizeof( temp2 ));
Q_strncpy( temp1, "unnamed", sizeof( temp1 ));
Q_strncpy( name2, "unnamed", sizeof( name2 ));
Q_strncpy( name1, "unnamed", sizeof( name1 ));
}
// check to see if another user by the same name exists
@ -1842,15 +1832,15 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
if( i != sv_maxclients->integer )
{
// dup name
Q_snprintf( temp2, sizeof( temp2 ), "%s (%u)", temp1, dupc++ );
Info_SetValueForKey( cl->userinfo, "name", temp2 );
Q_snprintf( name2, sizeof( name2 ), "%s (%u)", name1, dupc++ );
Info_SetValueForKey( cl->userinfo, "name", name2 );
val = Info_ValueForKey( cl->userinfo, "name" );
Q_strncpy( cl->name, temp2, sizeof( cl->name ));
Q_strncpy( cl->name, name2, sizeof( cl->name ));
}
else
{
if( dupc == 1 ) // unchanged
Q_strncpy( cl->name, temp1, sizeof( cl->name ));
Q_strncpy( cl->name, name1, sizeof( cl->name ));
break;
}
}
@ -1865,15 +1855,28 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
val = Info_ValueForKey( cl->userinfo, "cl_msglevel" );
if( Q_strlen( val )) cl->messagelevel = Q_atoi( val );
cl->local_weapons = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )) ? true : false;
cl->lag_compensation = Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lc" )) ? true : false;
if( Q_atoi( Info_ValueForKey( cl->userinfo, "cl_predict" )))
SetBits( cl->flags, FCL_PREDICT_MOVEMENT );
else ClearBits( cl->flags, FCL_PREDICT_MOVEMENT );
if( Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lc" )))
SetBits( cl->flags, FCL_LAG_COMPENSATION );
else ClearBits( cl->flags, FCL_LAG_COMPENSATION );
if( Q_atoi( Info_ValueForKey( cl->userinfo, "cl_lw" )))
SetBits( cl->flags, FCL_LOCAL_WEAPONS );
else ClearBits( cl->flags, FCL_LOCAL_WEAPONS );
val = Info_ValueForKey( cl->userinfo, "cl_updaterate" );
if( Q_strlen( val ))
{
int i = bound( 10, Q_atoi( val ), 300 );
cl->cl_updaterate = 1.0f / i;
if( Q_atoi( val ) != 0 )
{
int i = bound( 10, Q_atoi( val ), 300 );
cl->cl_updaterate = 1.0 / i;
}
else cl->cl_updaterate = 0.0;
}
if( sv_maxclients->integer > 1 )
@ -1900,7 +1903,7 @@ void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo )
svgame.dllFuncs.pfnClientUserInfoChanged( cl->edict, cl->userinfo );
ent->v.netname = MAKE_STRING( cl->name );
if( cl->state >= cs_connected ) cl->sendinfo = true; // needs for update client info
if( cl->state >= cs_connected ) SetBits( cl->flags, FCL_RESEND_USERINFO ); // needs for update client info
}
/*
@ -1951,7 +1954,7 @@ static void SV_Godmode_f( sv_client_t *cl )
pEntity->v.flags = pEntity->v.flags ^ FL_GODMODE;
if ( !( pEntity->v.flags & FL_GODMODE ))
if( !FBitSet( pEntity->v.flags, FL_GODMODE ))
SV_ClientPrintf( cl, PRINT_HIGH, "godmode OFF\n" );
else SV_ClientPrintf( cl, PRINT_HIGH, "godmode ON\n" );
}
@ -1970,7 +1973,7 @@ static void SV_Notarget_f( sv_client_t *cl )
pEntity->v.flags = pEntity->v.flags ^ FL_NOTARGET;
if ( !( pEntity->v.flags & FL_NOTARGET ))
if( !FBitSet( pEntity->v.flags, FL_NOTARGET ))
SV_ClientPrintf( cl, PRINT_HIGH, "notarget OFF\n" );
else SV_ClientPrintf( cl, PRINT_HIGH, "notarget ON\n" );
}
@ -1982,12 +1985,12 @@ SV_SendRes_f
*/
void SV_SendRes_f( sv_client_t *cl )
{
sizebuf_t msg;
static byte buffer[65535];
sizebuf_t msg;
if( cl->state != cs_connected )
{
MsgDev( D_INFO, "sendres is not valid from the console\n" );
MsgDev( D_INFO, "'sendres' is not valid from the console\n" );
return;
}
@ -2072,7 +2075,8 @@ void SV_TSourceEngineQuery( netadr_t from )
{
// A2S_INFO
char answer[1024] = "";
int count = 0, bots = 0, index;
int count = 0, bots = 0;
int index;
sizebuf_t buf;
if( svs.clients )
@ -2081,7 +2085,7 @@ void SV_TSourceEngineQuery( netadr_t from )
{
if( svs.clients[index].state >= cs_connected )
{
if( svs.clients[index].fakeclient )
if( FBitSet( svs.clients[index].flags, FCL_FAKECLIENT ))
bots++;
else count++;
}
@ -2188,8 +2192,8 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
client_frame_t *frame;
int key, size, checksum1, checksum2;
int i, numbackup, newcmds, numcmds;
usercmd_t nullcmd, *from;
usercmd_t cmds[32], *to;
usercmd_t nullcmd, *to, *from;
usercmd_t cmds[32];
edict_t *player;
player = cl->edict;
@ -2215,7 +2219,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
return;
}
from = &nullcmd; // first cmd are starting from null-comressed usercmd_t
from = &nullcmd; // first cmd are starting from null-compressed usercmd_t
for( i = numcmds - 1; i >= 0; i-- )
{
@ -2296,7 +2300,7 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
// adjust latency time by 1/2 last client frame since
// the message probably arrived 1/2 through client's frame loop
frame->latency -= cl->lastcmd.msec * 0.5f / 1000.0f;
frame->latency = max( 0.0f, frame->latency );
frame->latency = Q_max( 0.0f, frame->latency );
if( player->v.animtime > svgame.globals->time + host.frametime )
player->v.animtime = svgame.globals->time + host.frametime;
@ -2367,7 +2371,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
// calc ping time
frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK];
// raw ping doesn't factor in message interval, either
// ping time doesn't factor in message interval, either
frame->ping_time = host.realtime - frame->senttime - cl->cl_updaterate;
// on first frame ( no senttime ) don't skew ping

View File

@ -25,10 +25,10 @@ Sends text across to be displayed if the level passes
*/
void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... )
{
va_list argptr;
char string[MAX_SYSPATH];
va_list argptr;
if( level < cl->messagelevel || cl->fakeclient )
if( level < cl->messagelevel || FBitSet( cl->flags, FCL_FAKECLIENT ))
return;
va_start( argptr, fmt );
@ -47,14 +47,15 @@ SV_BroadcastPrintf
Sends text to all active clients
=================
*/
void SV_BroadcastPrintf( int level, char *fmt, ... )
void SV_BroadcastPrintf( sv_client_t *ignore, int level, char *fmt, ... )
{
char string[MAX_SYSPATH];
va_list argptr;
sv_client_t *cl;
int i;
if( !sv.state ) return;
if( sv.state == ss_dead )
return;
va_start( argptr, fmt );
Q_vsprintf( string, fmt, argptr );
@ -65,9 +66,11 @@ void SV_BroadcastPrintf( int level, char *fmt, ... )
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( level < cl->messagelevel ) continue;
if( cl->state != cs_spawned ) continue;
if( cl->fakeclient ) continue;
if( level < cl->messagelevel || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
if( cl == ignore || cl->state != cs_spawned )
continue;
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, level );
@ -84,10 +87,12 @@ Sends text to all active clients
*/
void SV_BroadcastCommand( char *fmt, ... )
{
va_list argptr;
char string[MAX_SYSPATH];
if( !sv.state ) return;
va_list argptr;
if( sv.state == ss_dead )
return;
va_start( argptr, fmt );
Q_vsprintf( string, fmt, argptr );
va_end( argptr );
@ -187,6 +192,7 @@ void SV_Map_f( void )
// hold mapname to other place
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
FS_StripExtension( mapname );
// determine spawn entity classname
if( sv_maxclients->integer == 1 )
@ -195,19 +201,19 @@ void SV_Map_f( void )
flags = SV_MapIsValid( mapname, spawn_entity, NULL );
if( flags & MAP_INVALID_VERSION )
if( FBitSet( flags, MAP_INVALID_VERSION ))
{
Msg( "SV_NewMap: map %s is invalid or not supported\n", mapname );
return;
}
if(!( flags & MAP_IS_EXIST ))
if( !FBitSet( flags, MAP_IS_EXIST ))
{
Msg( "SV_NewMap: map %s doesn't exist\n", mapname );
return;
}
if(!( flags & MAP_HAS_SPAWNPOINT ))
if( !FBitSet( flags, MAP_HAS_SPAWNPOINT ))
{
Msg( "SV_NewMap: map %s doesn't have a valid spawnpoint\n", mapname );
return;
@ -259,16 +265,24 @@ void SV_MapBackground_f( void )
// hold mapname to other place
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
FS_StripExtension( mapname );
flags = SV_MapIsValid( mapname, GI->sp_entity, NULL );
if(!( flags & MAP_IS_EXIST ))
if( FBitSet( flags, MAP_INVALID_VERSION ))
{
Msg( "SV_NewMap: map %s is invalid or not supported\n", mapname );
return;
}
if( !FBitSet( flags, MAP_IS_EXIST ))
{
Msg( "SV_NewMap: map %s doesn't exist\n", mapname );
return;
}
// background maps allow without spawnpoints (just throw warning)
if(!( flags & MAP_HAS_SPAWNPOINT ))
if( !FBitSet( flags, MAP_HAS_SPAWNPOINT ))
MsgDev( D_WARN, "SV_NewMap: map %s doesn't have a valid spawnpoint\n", mapname );
Q_strncpy( host.finalmsg, "", MAX_STRING );
@ -453,7 +467,8 @@ Saves the state of the map just being exited and goes to a new map.
*/
void SV_ChangeLevel_f( void )
{
char *spawn_entity, *mapname;
string mapname;
char *spawn_entity;
int flags, c = Cmd_Argc();
if( c < 2 )
@ -462,7 +477,9 @@ void SV_ChangeLevel_f( void )
return;
}
mapname = Cmd_Argv( 1 );
// hold mapname to other place
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
FS_StripExtension( mapname );
// determine spawn entity classname
if( sv_maxclients->integer == 1 )
@ -471,19 +488,19 @@ void SV_ChangeLevel_f( void )
flags = SV_MapIsValid( mapname, spawn_entity, Cmd_Argv( 2 ));
if( flags & MAP_INVALID_VERSION )
if( FBitSet( flags, MAP_INVALID_VERSION ))
{
Msg( "SV_ChangeLevel: map %s is invalid or not supported\n", mapname );
return;
}
if(!( flags & MAP_IS_EXIST ))
if( !FBitSet( flags, MAP_IS_EXIST ))
{
Msg( "SV_ChangeLevel: map %s doesn't exist\n", mapname );
return;
}
if( c >= 3 && !( flags & MAP_HAS_LANDMARK ))
if( c >= 3 && !FBitSet( flags, MAP_HAS_LANDMARK ))
{
if( sv_validate_changelevel->integer )
{
@ -501,7 +518,7 @@ void SV_ChangeLevel_f( void )
return;
}
if( c == 2 && !( flags & MAP_HAS_SPAWNPOINT ))
if( c == 2 && !FBitSet( flags, MAP_HAS_SPAWNPOINT ))
{
if( sv_validate_changelevel->integer )
{
@ -510,7 +527,7 @@ void SV_ChangeLevel_f( void )
}
}
// bad changelevel position invoke enables in one-way transtion
// bad changelevel position invoke enables in one-way transition
if( sv.net_framenum < 15 )
{
if( sv_validate_changelevel->integer )
@ -611,7 +628,7 @@ void SV_Kick_f( void )
return;
}
SV_BroadcastPrintf( PRINT_HIGH, "%s was kicked\n", svs.currentPlayer->name );
SV_BroadcastPrintf( svs.currentPlayer, PRINT_HIGH, "%s was kicked\n", svs.currentPlayer->name );
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "You were kicked from the game\n" );
SV_DropClient( svs.currentPlayer );
@ -633,7 +650,7 @@ void SV_Kill_f( void )
if( svs.currentPlayer->edict->v.health <= 0.0f )
{
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "Can't suicide -- allready dead!\n");
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "Can't suicide - already dead!\n");
return;
}
@ -673,8 +690,8 @@ SV_Status_f
*/
void SV_Status_f( void )
{
int i;
sv_client_t *cl;
int i;
if( !svs.clients || sv.background )
{
@ -698,7 +715,7 @@ void SV_Status_f( void )
if( cl->state == cs_connected ) Msg( "Connect" );
else if( cl->state == cs_zombie ) Msg( "Zombie " );
else if( cl->fakeclient ) Msg( "Bot " );
else if( FBitSet( cl->flags, FCL_FAKECLIENT )) Msg( "Bot " );
else
{
ping = cl->ping < 9999 ? cl->ping : 9999;
@ -812,7 +829,9 @@ Kick everyone off, possibly in preparation for a new game
*/
void SV_KillServer_f( void )
{
if( !svs.initialized ) return;
if( !svs.initialized )
return;
Q_strncpy( host.finalmsg, "Server was killed", MAX_STRING );
SV_Shutdown( false );
NET_Config ( false ); // close network sockets
@ -830,18 +849,18 @@ void SV_PlayersOnly_f( void )
if( !Cvar_VariableInteger( "sv_cheats" )) return;
sv.hostflags = sv.hostflags ^ SVF_PLAYERSONLY;
if(!( sv.hostflags & SVF_PLAYERSONLY ))
SV_BroadcastPrintf( D_INFO, "Resume server physic\n" );
else SV_BroadcastPrintf( D_INFO, "Freeze server physic\n" );
if( !FBitSet( sv.hostflags, SVF_PLAYERSONLY ))
SV_BroadcastPrintf( NULL, PRINT_HIGH, "Resume server physic\n" );
else SV_BroadcastPrintf( NULL, PRINT_HIGH, "Freeze server physic\n" );
}
/*
===============
SV_EdictsInfo_f
SV_EdictUsage_f
===============
*/
void SV_EdictsInfo_f( void )
void SV_EdictUsage_f( void )
{
int active;
@ -924,7 +943,7 @@ void SV_InitOperatorCommands( void )
Cmd_AddCommand( "restart", SV_Restart_f, "restarting current level" );
Cmd_AddCommand( "reload", SV_Reload_f, "continue from latest save or restart level" );
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
Cmd_AddCommand( "edicts_info", SV_EdictsInfo_f, "show info about edicts" );
Cmd_AddCommand( "edict_usage", SV_EdictUsage_f, "show info about edicts usage" );
Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" );
if( host.type == HOST_DEDICATED )
@ -968,7 +987,7 @@ void SV_KillOperatorCommands( void )
Cmd_RemoveCommand( "restart" );
Cmd_RemoveCommand( "reload" );
Cmd_RemoveCommand( "entpatch" );
Cmd_RemoveCommand( "edicts_info" );
Cmd_RemoveCommand( "edict_usage" );
Cmd_RemoveCommand( "entity_info" );
if( host.type == HOST_DEDICATED )

View File

@ -302,7 +302,7 @@ void SV_SendConsistencyList( sizebuf_t *msg )
int lastIndex;
int i;
if( mp_consistency->integer && ( sv.num_consistency_resources > 0 ) && !svs.currentPlayer->hltv_proxy )
if( mp_consistency->integer && ( sv.num_consistency_resources > 0 ) && !FBitSet( svs.currentPlayer->flags, FCL_HLTV_PROXY ))
{
lastIndex = 0;
MSG_WriteOneBit( msg, 1 );

View File

@ -24,9 +24,6 @@ typedef struct
entity_state_t entities[MAX_VISIBLE_PACKET];
} sv_ents_t;
static byte *clientpvs; // FatPVS
static byte *clientphs; // FatPHS
int c_fullsend; // just a debug counter
/*
@ -55,77 +52,84 @@ SV_AddEntitiesToPacket
=============
*/
static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_frame_t *frame, sv_ents_t *ents )
static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_frame_t *frame, sv_ents_t *ents, qboolean from_client )
{
edict_t *ent;
byte *pset;
byte *clientpvs;
byte *clientphs;
qboolean fullvis = false;
sv_client_t *netclient;
sv_client_t *cl = NULL;
entity_state_t *state;
int e, player;
int e;
// during an error shutdown message we may need to transmit
// the shutdown message after the server has shutdown, so
// specifically check for it
if( !sv.state ) return;
if( sv.state == ss_dead )
return;
cl = SV_ClientFromEdict( pClient, true );
ASSERT( cl != NULL );
if( pClient && !( sv.hostflags & SVF_PORTALPASS ))
// portals can't change hostflags
if( pClient && from_client )
{
// portals can't change hostflags
sv.hostflags &= ~SVF_SKIPLOCALHOST;
// setup hostflags
if( cl->local_weapons )
{
sv.hostflags |= SVF_SKIPLOCALHOST;
}
if( FBitSet( cl->flags, FCL_LOCAL_WEAPONS ))
SetBits( sv.hostflags, SVF_SKIPLOCALHOST );
else ClearBits( sv.hostflags, SVF_SKIPLOCALHOST );
// reset cameras each frame
cl->num_cameras = 0;
// reset viewents each frame
cl->num_viewents = 0;
}
svgame.dllFuncs.pfnSetupVisibility( pViewEnt, pClient, &clientpvs, &clientphs );
if( !clientpvs ) fullvis = true;
// don't send the world
for( e = 1; e < svgame.numEntities; e++ )
{
byte *pset;
ent = EDICT_NUM( e );
if( ent->free ) continue;
if( !SV_IsValidEdict( ent ))
continue;
// don't double add an entity through portals (already added)
// HACHACK: use pushmsec to keep net_framenum
if( ent->v.pushmsec == sv.net_framenum )
continue;
if( ent->v.effects & EF_REQUEST_PHS )
if( FBitSet( ent->v.effects, EF_REQUEST_PHS ))
pset = clientphs;
else pset = clientpvs;
state = &ents->entities[ents->num_entities];
netclient = SV_ClientFromEdict( ent, true );
player = ( netclient != NULL );
// add entity to the net packet
if( svgame.dllFuncs.pfnAddToFullPack( state, e, ent, pClient, sv.hostflags, player, pset ))
if( svgame.dllFuncs.pfnAddToFullPack( state, e, ent, pClient, sv.hostflags, ( netclient != NULL ), pset ))
{
// to prevent adds it twice through portals
ent->v.pushmsec = sv.net_framenum;
if( netclient && netclient->modelindex ) // apply custom model if present
state->modelindex = netclient->modelindex;
if( SV_IsValidEdict( ent->v.aiment ) && ( ent->v.aiment->v.effects & EF_MERGE_VISIBILITY ))
if( netclient && netclient->modelindex )
{
if( cl != NULL && cl->num_cameras < MAX_CAMERAS )
// update playermodel if this was changed
state->modelindex = netclient->modelindex;
}
if( SV_IsValidEdict( ent->v.aiment ) && FBitSet( ent->v.aiment->v.effects, EF_MERGE_VISIBILITY ))
{
if( cl != NULL && cl->num_viewents < MAX_VIEWENTS )
{
cl->cameras[cl->num_cameras] = ent->v.aiment;
cl->num_cameras++;
cl->viewentity[cl->num_viewents] = ent->v.aiment;
cl->num_viewents++;
}
else MsgDev( D_ERROR, "SV_AddEntitiesToPacket: too many viewentities!\n" );
}
// if we are full, silently discard entities
@ -146,11 +150,11 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
if( fullvis ) continue; // portal ents will be added anyway, ignore recursion
// if its a portal entity, add everything visible from its camera position
if( !( sv.hostflags & SVF_PORTALPASS ) && ent->v.effects & EF_MERGE_VISIBILITY )
if( from_client && FBitSet( ent->v.effects, EF_MERGE_VISIBILITY ))
{
sv.hostflags |= SVF_PORTALPASS;
SV_AddEntitiesToPacket( ent, pClient, frame, ents );
sv.hostflags &= ~SVF_PORTALPASS;
SetBits( sv.hostflags, SVF_MERGE_VISIBILITY );
SV_AddEntitiesToPacket( ent, pClient, frame, ents, false );
ClearBits( sv.hostflags, SVF_MERGE_VISIBILITY );
}
}
}
@ -173,8 +177,8 @@ void SV_EmitPacketEntities( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg
{
entity_state_t *oldent, *newent;
int oldindex, newindex;
int oldnum, newnum;
int from_num_entities;
int oldnum, newnum;
client_frame_t *from;
// this is the frame that we are going to delta update from
@ -184,7 +188,7 @@ void SV_EmitPacketEntities( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg
from_num_entities = from->num_entities;
// the snapshot's entities may still have rolled off the buffer, though
if( from->first_entity <= svs.next_client_entities - svs.num_client_entities )
if( from->first_entity <= ( svs.next_client_entities - svs.num_client_entities ))
{
MsgDev( D_WARN, "%s: delta request from out of date entities.\n", cl->name );
@ -223,7 +227,7 @@ void SV_EmitPacketEntities( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg
}
else
{
newent = &svs.packet_entities[(to->first_entity+newindex)%svs.num_client_entities];
newent = &svs.packet_entities[(to->first_entity+newindex) % svs.num_client_entities];
newnum = newent->number;
}
@ -233,7 +237,7 @@ void SV_EmitPacketEntities( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg
}
else
{
oldent = &svs.packet_entities[(from->first_entity+oldindex)%svs.num_client_entities];
oldent = &svs.packet_entities[(from->first_entity+oldindex) % svs.num_client_entities];
oldnum = oldent->number;
}
@ -315,7 +319,7 @@ static void SV_EmitEvents( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg )
for( j = 0; j < to->num_entities; j++ )
{
state = &svs.packet_entities[(to->first_entity+j)%svs.num_client_entities];
state = &svs.packet_entities[(to->first_entity+j) % svs.num_client_entities];
if( state->number == ent_index )
break;
}
@ -331,10 +335,10 @@ static void SV_EmitEvents( sv_client_t *cl, client_frame_t *to, sizebuf_t *msg )
info->packet_index = j;
info->args.ducking = 0;
if(!( info->args.flags & FEVENT_ORIGIN ))
if( !FBitSet( info->args.flags, FEVENT_ORIGIN ))
VectorClear( info->args.origin );
if(!( info->args.flags & FEVENT_ANGLES ))
if( !FBitSet( info->args.flags, FEVENT_ANGLES ))
VectorClear( info->args.angles );
VectorClear( info->args.velocity );
@ -477,14 +481,15 @@ void SV_WriteClientdataToMessage( sv_client_t *cl, sizebuf_t *msg )
}
clent->v.fixangle = 0; // reset fixangle
clent->v.pushmsec = 0; // reset net framenum
memset( &frame->clientdata, 0, sizeof( frame->clientdata ));
clent->v.pushmsec = 0; // reset net framenum
// update clientdata_t
svgame.dllFuncs.pfnUpdateClientData( clent, cl->local_weapons, &frame->clientdata );
svgame.dllFuncs.pfnUpdateClientData( clent, FBitSet( cl->flags, FCL_LOCAL_WEAPONS ), &frame->clientdata );
MSG_WriteByte( msg, svc_clientdata );
if( cl->hltv_proxy ) return; // don't send more nothing
if( FBitSet( cl->flags, FCL_HLTV_PROXY )) return; // don't send more nothing
if( cl->delta_sequence == -1 ) from_cd = &nullcd;
else from_cd = &cl->frames[cl->delta_sequence & SV_UPDATE_MASK].clientdata;
@ -503,11 +508,11 @@ void SV_WriteClientdataToMessage( sv_client_t *cl, sizebuf_t *msg )
// write clientdata_t
MSG_WriteClientData( msg, from_cd, to_cd, sv.time );
if( cl->local_weapons && svgame.dllFuncs.pfnGetWeaponData( clent, frame->weapondata ))
if( FBitSet( cl->flags, FCL_LOCAL_WEAPONS ) && svgame.dllFuncs.pfnGetWeaponData( clent, frame->weapondata ))
{
memset( &nullwd, 0, sizeof( nullwd ));
for( i = 0; i < 64; i++ )
for( i = 0; i < MAX_LOCAL_WEAPONS; i++ )
{
if( cl->delta_sequence == -1 ) from_wd = &nullwd;
else from_wd = &cl->frames[cl->delta_sequence & SV_UPDATE_MASK].weapondata[i];
@ -536,22 +541,22 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg )
static sv_ents_t frame_ents;
int i, send_pings;
clent = cl->edict;
viewent = cl->pViewEntity; // himself or trigger_camera
frame = &cl->frames[cl->netchan.outgoing_sequence & SV_UPDATE_MASK];
clent = cl->edict;
viewent = cl->pViewEntity; // himself or trigger_camera
send_pings = SV_ShouldUpdatePing( cl );
ClearBits( sv.hostflags, SVF_MERGE_VISIBILITY );
sv.net_framenum++; // now all portal-through entities are invalidate
sv.hostflags &= ~SVF_PORTALPASS;
// clear everything in this snapshot
frame_ents.num_entities = c_fullsend = 0;
// add all the entities directly visible to the eye, which
// may include portal entities that merge other viewpoints
SV_AddEntitiesToPacket( viewent, clent, frame, &frame_ents );
SV_AddEntitiesToPacket( viewent, clent, frame, &frame_ents, true );
// if there were portals visible, there may be out of order entities
// in the list which will need to be resorted for the delta compression
@ -559,10 +564,7 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg )
// of an entity being included twice.
qsort( frame_ents.entities, frame_ents.num_entities, sizeof( frame_ents.entities[0] ), SV_EntityNumbers );
// copy the entity states out
frame->num_entities = 0;
// It will break all connected clients, but it takes more than one week to overflow it
// it will break all connected clients, but it takes more than one week to overflow it
if(( (uint)svs.next_client_entities ) + frame_ents.num_entities >= 0x7FFFFFFE )
{
// just reset counter
@ -571,6 +573,8 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg )
SV_FinalMessage( "Server is running to long, reconnecting!", true );
}
// copy the entity states out
frame->num_entities = 0;
frame->first_entity = svs.next_client_entities;
for( i = 0; i < frame_ents.num_entities; i++ )
@ -601,13 +605,12 @@ SV_SendClientDatagram
*/
void SV_SendClientDatagram( sv_client_t *cl )
{
byte msg_buf[NET_MAX_PAYLOAD];
sizebuf_t msg;
static byte msg_buf[NET_MAX_PAYLOAD];
sizebuf_t msg;
svs.currentPlayer = cl;
svs.currentPlayerNum = (cl - svs.clients);
svs.currentPlayer = cl;
memset( msg_buf, 0, NET_MAX_PAYLOAD );
MSG_Init( &msg, "Datagram", msg_buf, sizeof( msg_buf ));
// always send servertime at new frame
@ -641,8 +644,8 @@ SV_UpdateToReliableMessages
*/
void SV_UpdateToReliableMessages( void )
{
int i;
sv_client_t *cl;
int i;
// check for changes to be sent over the reliable streams to all clients
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
@ -652,36 +655,29 @@ void SV_UpdateToReliableMessages( void )
if( cl->state != cs_spawned )
continue;
if( cl->sendinfo )
if( FBitSet( cl->flags, FCL_RESEND_USERINFO ))
{
cl->sendinfo = false;
SV_FullClientUpdate( cl, &sv.reliable_datagram );
ClearBits( cl->flags, FCL_RESEND_USERINFO );
}
if( cl->sendmovevars )
if( FBitSet( cl->flags, FCL_RESEND_MOVEVARS ))
{
cl->sendmovevars = false;
SV_FullUpdateMovevars( cl, &cl->netchan.message );
}
ClearBits( cl->flags, FCL_RESEND_MOVEVARS );
}
}
// 1% chanse for simulate random network bugs
if( sv.write_bad_message && Com_RandomLong( 0, 512 ) == 404 )
{
// just for network debugging (send only for local client)
MSG_WriteByte( &sv.datagram, svc_bad );
MSG_WriteLong( &sv.datagram, rand( )); // send some random data
MSG_WriteString( &sv.datagram, host.finalmsg ); // send final message
MSG_WriteByte( &sv.reliable_datagram, svc_bad );
MSG_WriteLong( &sv.reliable_datagram, rand( )); // send some random data
MSG_WriteString( &sv.reliable_datagram, host.finalmsg ); // send final message
sv.write_bad_message = false;
}
// clear the server datagram if it overflowed.
if( MSG_CheckOverflow( &sv.datagram ))
{
MsgDev( D_ERROR, "sv.datagram overflowed!\n" );
MSG_Clear( &sv.datagram );
}
// clear the server datagram if it overflowed.
if( MSG_CheckOverflow( &sv.spectator_datagram ))
{
@ -692,22 +688,18 @@ void SV_UpdateToReliableMessages( void )
// now send the reliable and server datagrams to all clients.
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state < cs_connected || cl->fakeclient )
if( cl->state < cs_connected || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue; // reliables go to all connected or spawned
MSG_WriteBits( &cl->netchan.message, MSG_GetData( &sv.reliable_datagram ), MSG_GetNumBitsWritten( &sv.reliable_datagram ));
MSG_WriteBits( &cl->datagram, MSG_GetData( &sv.datagram ), MSG_GetNumBitsWritten( &sv.datagram ));
if( cl->hltv_proxy )
{
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
MSG_WriteBits( &cl->datagram, MSG_GetData( &sv.spectator_datagram ), MSG_GetNumBitsWritten( &sv.spectator_datagram ));
}
}
// now clear the reliable and datagram buffers.
MSG_Clear( &sv.spectator_datagram );
MSG_Clear( &sv.reliable_datagram );
MSG_Clear( &sv.datagram );
}
/*
@ -731,32 +723,22 @@ void SV_SendClientMessages( void )
// send a message to each connected client
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( !cl->state || cl->fakeclient )
if( !cl->state || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
if( cl->skip_message )
if( FBitSet( cl->flags, FCL_SKIP_NET_MESSAGE ))
{
cl->skip_message = false;
ClearBits( cl->flags, FCL_SKIP_NET_MESSAGE );
continue;
}
if( !host_limitlocal->integer && NET_IsLocalAddress( cl->netchan.remote_address ))
cl->send_message = true;
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
if( cl->state == cs_spawned )
{
// Try to send a message as soon as we can.
// If the target time for sending is within the next frame interval ( based on last frame ),
// trigger the send now. Note that in single player,
// send_message is also set to true any time a packet arrives from the client.
float time_unti_next_message = cl->next_messagetime - (host.realtime + host.frametime);
if( time_unti_next_message <= 0.0f )
cl->send_message = true;
// something got hosed
if( time_unti_next_message > 2.0f )
cl->send_message = true;
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ) || ( host.realtime + host.frametime ) >= cl->next_messagetime )
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
}
// if the reliable message overflowed, drop the client
@ -764,45 +746,42 @@ void SV_SendClientMessages( void )
{
MSG_Clear( &cl->netchan.message );
MSG_Clear( &cl->datagram );
SV_BroadcastPrintf( PRINT_HIGH, "%s overflowed\n", cl->name );
SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s overflowed\n", cl->name );
MsgDev( D_WARN, "reliable overflow for %s\n", cl->name );
SV_DropClient( cl );
cl->send_message = true;
cl->netchan.cleartime = 0; // don't choke this message
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
cl->netchan.cleartime = 0.0; // don't choke this message
}
else if( cl->send_message )
else if( FBitSet( cl->flags, FCL_SEND_NET_MESSAGE ))
{
// If we haven't gotten a message in sv_failuretime seconds, then stop sending messages to this client
// until we get another packet in from the client. This prevents crash/drop and reconnect where they are
// being hosed with "sequenced packet without connection" packets.
if(( host.realtime - cl->netchan.last_received ) > sv_failuretime->value )
cl->send_message = false;
ClearBits( cl->flags, FCL_SEND_NET_MESSAGE );
}
// only send messages if the client has sent one
// and the bandwidth is not choked
if( !cl->send_message ) continue;
// Bandwidth choke active?
if( !Netchan_CanPacket( &cl->netchan ))
if( FBitSet( cl->flags, FCL_SEND_NET_MESSAGE ))
{
cl->chokecount++;
continue;
}
// bandwidth choke active?
if( !Netchan_CanPacket( &cl->netchan ))
{
cl->chokecount++;
continue;
}
cl->send_message = false;
// now that we were able to send, reset timer to point to next possible send time.
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
cl->next_messagetime = host.realtime + cl->cl_updaterate;
else cl->next_messagetime = host.realtime + host.frametime + cl->cl_updaterate;
ClearBits( cl->flags, FCL_SEND_NET_MESSAGE );
// Now that we were able to send, reset timer to point to next possible send time.
cl->next_messagetime = host.realtime + host.frametime + cl->cl_updaterate;
if( cl->state == cs_spawned )
{
SV_SendClientDatagram( cl );
}
else
{
// just update reliable
Netchan_Transmit( &cl->netchan, 0, NULL );
// NOTE: we should send frame even if server is not simulated to prevent overflow
if( cl->state == cs_spawned )
SV_SendClientDatagram( cl );
else Netchan_Transmit( &cl->netchan, 0, NULL ); // just update reliable
}
}
@ -820,8 +799,8 @@ e.g. before changing level
*/
void SV_SendMessagesToAll( void )
{
int i;
sv_client_t *cl;
int i;
if( sv.state == ss_dead )
return;
@ -829,8 +808,9 @@ void SV_SendMessagesToAll( void )
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state >= cs_connected )
cl->send_message = true;
SetBits( cl->flags, FCL_SEND_NET_MESSAGE );
}
SV_SendClientMessages();
}
@ -843,17 +823,18 @@ used before changing level
*/
void SV_SkipUpdates( void )
{
int i;
sv_client_t *cl;
int i;
if( sv.state == ss_dead )
return;
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state != cs_spawned || cl->fakeclient )
if( cl->state != cs_spawned || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
cl->skip_message = true;
SetBits( cl->flags, FCL_SKIP_NET_MESSAGE );
}
}
@ -878,7 +859,7 @@ void SV_InactivateClients( void )
if( !cl->state || !cl->edict )
continue;
if( !cl->edict || (cl->edict->v.flags & FL_FAKECLIENT))
if( !cl->edict || FBitSet( cl->edict->v.flags, FL_FAKECLIENT ))
continue;
if( svs.clients[i].state > cs_connected )

View File

@ -28,8 +28,6 @@ static byte fatpvs[MAX_MAP_LEAFS/8];
static byte fatphs[MAX_MAP_LEAFS/8];
static byte clientpvs[MAX_MAP_LEAFS/8]; // for find client in PVS
static vec3_t viewPoint[MAX_CLIENTS];
static byte *bitvector;
static int fatbytes;
// exports
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
@ -218,35 +216,37 @@ Check visibility through client camera, portal camera, etc
*/
qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask )
{
int i, leafnum, clientnum;
float *viewOrg = NULL;
int i, clientnum;
vec3_t vieworg;
mleaf_t *leaf;
if( !mask ) return true; // full visibility
clientnum = cl - svs.clients;
viewOrg = viewPoint[clientnum];
VectorCopy( viewPoint[clientnum], vieworg );
// Invasion issues: wrong camera position received in ENGINE_SET_PVS
if( cl->pViewEntity && !VectorCompare( viewOrg, cl->pViewEntity->v.origin ))
viewOrg = cl->pViewEntity->v.origin;
if( cl->pViewEntity && !VectorCompare( vieworg, cl->pViewEntity->v.origin ))
VectorCopy( cl->pViewEntity->v.origin, vieworg );
// -1 is because pvs rows are 1 based, not 0 based like leafs
leafnum = Mod_PointLeafnum( viewOrg ) - 1;
if( leafnum == -1 || (mask[leafnum>>3] & (1<<( leafnum & 7 ))))
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes );
if( CHECKVISBIT( mask, leaf->cluster ))
return true; // visible from player view or camera view
// now check all the portal cameras
for( i = 0; i < cl->num_cameras; i++ )
for( i = 0; i < cl->num_viewents; i++ )
{
edict_t *cam = cl->cameras[i];
edict_t *view = cl->viewentity[i];
if( !SV_IsValidEdict( cam ))
if( !SV_IsValidEdict( view ))
continue;
leafnum = Mod_PointLeafnum( cam->v.origin ) - 1;
// g-cont. probably camera in bad leaf... allow to send message here?
if( leafnum == -1 || (mask[leafnum>>3] & (1<<( leafnum & 7 ))))
return true;
VectorAdd( view->v.origin, view->v.view_ofs, vieworg );
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes );
if( CHECKVISBIT( mask, leaf->cluster ))
return true; // visible from portal camera view
}
// not visible from any viewpoint
@ -263,7 +263,7 @@ then clears sv.multicast.
MSG_ONE send to one client (ent can't be NULL)
MSG_ALL same as broadcast (origin can be NULL)
MSG_PVS send to clients potentially visible from org
MSG_PHS send to clients potentially hearable from org
MSG_PHS send to clients potentially audible from org
=================
*/
qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent, qboolean usermessage )
@ -274,7 +274,6 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent, qboolean us
qboolean reliable = false;
qboolean specproxy = false;
int numsends = 0;
mleaf_t *leaf;
switch( dest )
{
@ -298,16 +297,15 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent, qboolean us
// intentional fallthrough
case MSG_PAS:
if( origin == NULL ) return false;
leaf = Mod_PointInLeaf( origin, sv.worldmodel->nodes );
mask = Mod_LeafPHS( leaf, sv.worldmodel );
Mod_FatPVS( origin, FATPHS_RADIUS, fatphs, world.fatbytes, false, false );
mask = fatphs; // using the FatPVS like a PHS
break;
case MSG_PVS_R:
reliable = true;
// intentional fallthrough
case MSG_PVS:
if( origin == NULL ) return false;
leaf = Mod_PointInLeaf( origin, sv.worldmodel->nodes );
mask = Mod_LeafPVS( leaf, sv.worldmodel );
mask = Mod_GetPVSForPoint( origin );
break;
case MSG_ONE:
reliable = true;
@ -336,10 +334,10 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent, qboolean us
if( cl->state != cs_spawned && ( !reliable || usermessage ))
continue;
if( specproxy && !cl->hltv_proxy )
if( specproxy && !FBitSet( cl->flags, FCL_HLTV_PROXY ))
continue;
if( !cl->edict || cl->fakeclient )
if( !cl->edict || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
if( ent != NULL && ent->v.groupinfo && cl->edict->v.groupinfo )
@ -359,7 +357,7 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent, qboolean us
MSG_Clear( &sv.multicast );
return numsends; // debug
return numsends; // just for debug
}
/*
@ -524,57 +522,6 @@ void SV_RestartStaticEnts( void )
}
}
/*
=============================================================================
The PVS must include a small area around the client to allow head bobbing
or other small motion on the client side. Otherwise, a bob might cause an
entity that should be visible to not show up, especially when the bob
crosses a waterline.
=============================================================================
*/
static void SV_AddToFatPVS( const vec3_t org, int type, mnode_t *node )
{
byte *vis;
float d;
while( 1 )
{
// if this is a leaf, accumulate the pvs bits
if( node->contents < 0 )
{
if( node->contents != CONTENTS_SOLID )
{
mleaf_t *leaf;
int i;
leaf = (mleaf_t *)node;
if( type == DVIS_PVS )
vis = Mod_LeafPVS( leaf, sv.worldmodel );
else if( type == DVIS_PHS )
vis = Mod_LeafPHS( leaf, sv.worldmodel );
else vis = Mod_DecompressVis( NULL ); // get full visibility
for( i = 0; i < fatbytes; i++ )
bitvector[i] |= vis[i];
}
return;
}
d = PlaneDiff( org, node->plane );
if( d > 8.0f ) node = node->children[0];
else if( d < -8.0f ) node = node->children[1];
else
{
// go down both
SV_AddToFatPVS( org, type, node->children[0] );
node = node->children[1];
}
}
}
/*
==============
SV_BoxInPVS
@ -584,8 +531,7 @@ check brush boxes in fat pvs
*/
static qboolean SV_BoxInPVS( const vec3_t org, const vec3_t absmin, const vec3_t absmax )
{
mleaf_t *leaf = Mod_PointInLeaf( org, sv.worldmodel->nodes );
byte *vis = Mod_LeafPVS( leaf, sv.worldmodel );
byte *vis = Mod_GetPVSForPoint( org );
if( !Mod_BoxVisible( absmin, absmax, vis ))
return false;
@ -834,7 +780,7 @@ void SV_InitEdict( edict_t *pEdict )
void SV_FreeEdict( edict_t *pEdict )
{
ASSERT( pEdict );
ASSERT( pEdict != NULL );
ASSERT( pEdict->free == false );
// unlink from world
@ -1033,7 +979,10 @@ void SV_BaselineForEntity( edict_t *pEdict )
float *mins, *maxs;
sv_client_t *cl;
if( pEdict->v.flags & FL_CLIENT && ( cl = SV_ClientFromEdict( pEdict, false )))
if( !SV_IsValidEdict( pEdict ))
return;
if( FBitSet( pEdict->v.flags, FL_CLIENT ) && ( cl = SV_ClientFromEdict( pEdict, false )))
{
usehull = ( pEdict->v.flags & FL_DUCKING ) ? true : false;
modelindex = cl->modelindex ? cl->modelindex : pEdict->v.modelindex;
@ -1435,31 +1384,27 @@ build the new client PVS
int SV_CheckClientPVS( int check, qboolean bMergePVS )
{
byte *pvs;
edict_t *ent;
mleaf_t *leaf;
vec3_t view;
vec3_t vieworg;
sv_client_t *cl;
int i, j, k;
int pvsbytes;
edict_t *ent = NULL;
// cycle to the next one
check = bound( 1, check, svgame.globals->maxClients );
if( check == svgame.globals->maxClients )
i = 1;
i = 1; // reset cycle
else i = check + 1;
for( ;; i++ )
{
if( i == svgame.globals->maxClients + 1 )
if( i == ( svgame.globals->maxClients + 1 ))
i = 1;
ent = EDICT_NUM( i );
if( i == check ) break; // didn't find anything else
if( i == check )
break; // didn't find anything else
if( ent->free || !ent->pvPrivateData || ( ent->v.flags & FL_NOTARGET ))
if( ent->free || !ent->pvPrivateData || FBitSet( ent->v.flags, FL_NOTARGET ))
continue;
// anything that is a client, or has a client as an enemy
@ -1467,31 +1412,28 @@ int SV_CheckClientPVS( int check, qboolean bMergePVS )
}
cl = SV_ClientFromEdict( ent, true );
pvsbytes = (sv.worldmodel->numleafs + 7) >> 3;
memset( clientpvs, 0xFF, world.visbytes );
// get the PVS for the entity
VectorAdd( ent->v.origin, ent->v.view_ofs, view );
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes );
pvs = Mod_LeafPVS( leaf, sv.worldmodel );
memcpy( clientpvs, pvs, pvsbytes );
VectorAdd( ent->v.origin, ent->v.view_ofs, vieworg );
pvs = Mod_GetPVSForPoint( vieworg );
if( pvs ) memcpy( clientpvs, pvs, world.visbytes );
// transition in progress
if( !cl ) return i;
// now merge PVS with all portal cameras
for( k = 0; k < cl->num_cameras && bMergePVS; k++ )
// now merge PVS with all the portal cameras
for( k = 0; k < cl->num_viewents && bMergePVS; k++ )
{
edict_t *cam = cl->cameras[k];
edict_t *view = cl->viewentity[k];
if( !SV_IsValidEdict( cam ))
if( !SV_IsValidEdict( view ))
continue;
VectorAdd( cam->v.origin, cam->v.view_ofs, view );
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes );
if( leaf == NULL ) continue; // skip outside cameras
pvs = Mod_LeafPVS( leaf, sv.worldmodel );
VectorAdd( view->v.origin, view->v.view_ofs, vieworg );
pvs = Mod_GetPVSForPoint( vieworg );
for( j = 0; j < pvsbytes; j++ )
for( j = 0; j < world.visbytes && pvs; j++ )
clientpvs[j] |= pvs[j];
}
@ -1511,7 +1453,7 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
float delta;
model_t *mod;
qboolean bMergePVS;
int i;
mleaf_t *leaf;
if( !SV_IsValidEdict( pEdict ))
return svgame.edicts;
@ -1519,7 +1461,7 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
delta = ( sv.time - sv.lastchecktime );
// don't merge visibility for portal entity, only for monsters
bMergePVS = (pEdict->v.flags & FL_MONSTER) ? true : false;
bMergePVS = FBitSet( pEdict->v.flags, FL_MONSTER ) ? true : false;
// find a new check if on a new frame
if( delta < 0.0f || delta >= 0.1f )
@ -1530,6 +1472,7 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
// return check if it might be visible
pClient = EDICT_NUM( sv.lastcheck );
if( !SV_ClientFromEdict( pClient, true ))
return svgame.edicts;
@ -1537,7 +1480,7 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
// portals & monitors
// NOTE: this specific break "radiaton tick" in normal half-life. use only as feature
if(( host.features & ENGINE_TRANSFORM_TRACE_AABB ) && mod && mod->type == mod_brush && !( mod->flags & MODEL_HAS_ORIGIN ))
if( FBitSet( host.features, ENGINE_TRANSFORM_TRACE_AABB ) && mod && mod->type == mod_brush && !FBitSet( mod->flags, MODEL_HAS_ORIGIN ))
{
// handle PVS origin for bmodels
VectorAverage( pEdict->v.mins, pEdict->v.maxs, view );
@ -1551,13 +1494,12 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
if( pEdict->v.effects & EF_INVLIGHT )
view[2] -= 1.0f; // HACKHACK for barnacle
i = Mod_PointLeafnum( view ) - 1;
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes );
if( i < 0 || !((clientpvs[i>>3]) & (1 << (i & 7))))
return svgame.edicts;
if( CHECKVISBIT( clientpvs, leaf->cluster ))
return pClient; // client which currently in PVS
// client which currently in PVS
return pClient;
return svgame.edicts;
}
/*
@ -2341,7 +2283,7 @@ pfnClientCommand
*/
void pfnClientCommand( edict_t* pEdict, char* szFmt, ... )
{
sv_client_t *client;
sv_client_t *cl;
string buffer;
va_list args;
@ -2351,13 +2293,13 @@ void pfnClientCommand( edict_t* pEdict, char* szFmt, ... )
return;
}
if(( client = SV_ClientFromEdict( pEdict, true )) == NULL )
if(( cl = SV_ClientFromEdict( pEdict, true )) == NULL )
{
MsgDev( D_ERROR, "SV_ClientCommand: client is not spawned!\n" );
return;
}
if( client->fakeclient )
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
return;
va_start( args, szFmt );
@ -2366,8 +2308,8 @@ void pfnClientCommand( edict_t* pEdict, char* szFmt, ... )
if( SV_IsValidCmd( buffer ))
{
MSG_WriteByte( &client->netchan.message, svc_stufftext );
MSG_WriteString( &client->netchan.message, buffer );
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, buffer );
}
else MsgDev( D_ERROR, "Tried to stuff bad command %s\n", buffer );
}
@ -2390,18 +2332,20 @@ void pfnParticleEffect( const float *org, const float *dir, float color, float c
return;
}
MSG_WriteByte( &sv.datagram, svc_particle );
MSG_WriteVec3Coord( &sv.datagram, org );
MSG_WriteByte( &sv.multicast, svc_particle );
MSG_WriteVec3Coord( &sv.multicast, org );
for( i = 0; i < 3; i++ )
{
v = bound( -128, dir[i] * 16.0f, 127 );
MSG_WriteChar( &sv.datagram, v );
MSG_WriteChar( &sv.multicast, v );
}
MSG_WriteByte( &sv.datagram, count );
MSG_WriteByte( &sv.datagram, color );
MSG_WriteByte( &sv.datagram, 0 );
MSG_WriteByte( &sv.multicast, count );
MSG_WriteByte( &sv.multicast, color );
MSG_WriteByte( &sv.multicast, 0 );
SV_Send( MSG_PVS, org, NULL, false );
}
/*
@ -2821,7 +2765,7 @@ static void pfnAlertMessage( ALERT_TYPE level, char *szFmt, ... )
=============
pfnEngineFprintf
legacy. probably was a part of early save\restore system
legacy. probably was a part of early version of save\restore system
=============
*/
static void pfnEngineFprintf( FILE *pfile, char *szFmt, ... )
@ -3198,15 +3142,18 @@ void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
switch( ptype )
{
case print_console:
if( client->fakeclient ) MsgDev( D_INFO, "%s", szMsg );
if( FBitSet( client->flags, FCL_FAKECLIENT ))
MsgDev( D_INFO, "%s", szMsg );
else SV_ClientPrintf( client, PRINT_HIGH, "%s", szMsg );
break;
case print_chat:
if( client->fakeclient ) return;
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
SV_ClientPrintf( client, PRINT_CHAT, "%s", szMsg );
break;
case print_center:
if( client->fakeclient ) return;
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
MSG_WriteByte( &client->netchan.message, svc_centerprint );
MSG_WriteString( &client->netchan.message, szMsg );
break;
@ -3223,7 +3170,7 @@ void pfnServerPrint( const char *szMsg )
{
// while loading in-progress we can sending message only for local client
if( sv.state != ss_active ) MsgDev( D_INFO, "%s", szMsg );
else SV_BroadcastPrintf( PRINT_HIGH, "%s", szMsg );
else SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s", szMsg );
}
/*
@ -3273,7 +3220,8 @@ void pfnCrosshairAngle( const edict_t *pClient, float pitch, float yaw )
}
// fakeclients ignores it silently
if( client->fakeclient ) return;
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
if( pitch > 180.0f ) pitch -= 360;
if( pitch < -180.0f ) pitch += 360;
@ -3317,7 +3265,8 @@ void pfnSetView( const edict_t *pClient, const edict_t *pViewent )
else client->pViewEntity = (edict_t *)pViewent;
// fakeclients ignore to send client message (but can see into the trigger_camera through the PVS)
if( client->fakeclient ) return;
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
MSG_WriteByte( &client->netchan.message, svc_setview );
MSG_WriteWord( &client->netchan.message, NUM_FOR_EDICT( pViewent ));
@ -3370,22 +3319,7 @@ pfnGetPlayerWONId
*/
uint pfnGetPlayerWONId( edict_t *e )
{
sv_client_t *cl;
int i;
if( sv.state != ss_active )
return -1;
if( !SV_ClientFromEdict( e, false ))
return -1;
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->edict == e && cl->authentication_method == 0 )
return cl->WonID;
}
return -1;
return 0xFFFFFFFF;
}
/*
@ -3428,7 +3362,8 @@ void pfnFadeClientVolume( const edict_t *pEdict, int fadePercent, int fadeOutSec
return;
}
if( cl->fakeclient ) return;
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
return;
MSG_WriteByte( &cl->netchan.message, svc_soundfade );
MSG_WriteByte( &cl->netchan.message, fadePercent );
@ -3478,14 +3413,14 @@ void pfnRunPlayerMove( edict_t *pClient, const float *v_angle, float fmove, floa
return;
}
if( !cl->fakeclient )
return; // only fakeclients allows
if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
return; // only fakeclients allows
oldcl = svs.currentPlayer;
svs.currentPlayer = SV_ClientFromEdict( pClient, true );
svs.currentPlayerNum = (svs.currentPlayer - svs.clients);
svs.currentPlayer->timebase = (sv.time + host.frametime) - (msec / 1000.0f);
svs.currentPlayer->timebase = (sv.time + sv.frametime) - (msec / 1000.0f);
memset( &cmd, 0, sizeof( cmd ));
if( v_angle ) VectorCopy( v_angle, cmd.viewangles );
@ -3559,16 +3494,20 @@ pfnSetClientKeyValue
*/
void pfnSetClientKeyValue( int clientIndex, char *infobuffer, char *key, char *value )
{
sv_client_t *cl;
clientIndex -= 1;
if( clientIndex < 0 || clientIndex >= sv_maxclients->integer )
if( !svs.clients || clientIndex < 0 || clientIndex >= sv_maxclients->integer )
return;
if( svs.clients[clientIndex].state < cs_spawned || infobuffer == NULL )
cl = &svs.clients[clientIndex];
if( cl->state < cs_spawned || infobuffer == NULL )
return;
Info_SetValueForKey( infobuffer, key, value );
svs.clients[clientIndex].sendinfo = true;
SetBits( cl->flags, FCL_RESEND_USERINFO );
}
/*
@ -3662,7 +3601,7 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
byte *mask = NULL;
vec3_t pvspoint;
if( flags & FEV_CLIENT )
if( FBitSet( flags, FEV_CLIENT ))
return; // someone stupid joke
// first check event for out of bounds
@ -3710,14 +3649,14 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
args.entindex = invokerIndex = NUM_FOR_EDICT( pInvoker );
// g-cont. allow 'ducking' param for all entities
args.ducking = (pInvoker->v.flags & FL_DUCKING) ? true : false;
args.ducking = FBitSet( pInvoker->v.flags, FL_DUCKING ) ? true : false;
// this will be send only for reliable event
if(!( args.flags & FEVENT_ORIGIN ))
if( !FBitSet( args.flags, FEVENT_ORIGIN ))
VectorCopy( pInvoker->v.origin, args.origin );
// this will be send only for reliable event
if(!( args.flags & FEVENT_ANGLES ))
if( !FBitSet( args.flags, FEVENT_ANGLES ))
VectorCopy( pInvoker->v.angles, args.angles );
if( sv_sendvelocity->integer )
@ -3730,54 +3669,50 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
invokerIndex = -1;
}
if(!( flags & FEV_GLOBAL ) && VectorIsNull( pvspoint ))
if( !FBitSet( flags, FEV_GLOBAL ) && VectorIsNull( pvspoint ))
{
MsgDev( D_ERROR, "%s: not a FEV_GLOBAL event missing origin. Ignored.\n", sv.event_precache[eventindex] );
return;
}
// check event for some user errors
if( flags & (FEV_NOTHOST|FEV_HOSTONLY))
if( FBitSet( flags, FEV_NOTHOST|FEV_HOSTONLY ))
{
if( !SV_ClientFromEdict( pInvoker, true ))
{
const char *ev_name = sv.event_precache[eventindex];
if( flags & FEV_NOTHOST )
if( FBitSet( flags, FEV_NOTHOST ))
{
MsgDev( D_WARN, "%s: specified FEV_NOTHOST when invoker not a client\n", ev_name );
flags &= ~FEV_NOTHOST;
ClearBits( flags, FEV_NOTHOST );
}
if( flags & FEV_HOSTONLY )
if( FBitSet( flags, FEV_HOSTONLY ))
{
MsgDev( D_WARN, "%s: specified FEV_HOSTONLY when invoker not a client\n", ev_name );
flags &= ~FEV_HOSTONLY;
ClearBits( flags, FEV_HOSTONLY );
}
}
}
flags |= FEV_SERVER; // it's a server event!
SetBits( flags, FEV_SERVER ); // it's a server event!
if( delay < 0.0f ) delay = 0.0f; // fixup negative delays
if(!( flags & FEV_GLOBAL ))
{
mleaf_t *leaf;
// setup pvs cluster for invoker
leaf = Mod_PointInLeaf( pvspoint, sv.worldmodel->nodes );
mask = Mod_LeafPVS( leaf, sv.worldmodel );
}
// setup pvs cluster for invoker
if( !FBitSet( flags, FEV_GLOBAL ))
mask = Mod_GetPVSForPoint( pvspoint );
// process all the clients
for( slot = 0, cl = svs.clients; slot < sv_maxclients->integer; slot++, cl++ )
{
if( cl->state != cs_spawned || !cl->edict || cl->fakeclient )
if( cl->state != cs_spawned || !cl->edict || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
if( SV_IsValidEdict( pInvoker ) && pInvoker->v.groupinfo && cl->edict->v.groupinfo )
{
if(( svs.groupop == 0 && (cl->edict->v.groupinfo & pInvoker->v.groupinfo) == 0 )
|| ( svs.groupop == 1 && (cl->edict->v.groupinfo & pInvoker->v.groupinfo) == 1 ))
if(( svs.groupop == 0 && FBitSet( cl->edict->v.groupinfo, pInvoker->v.groupinfo ) == 0 )
|| ( svs.groupop == 1 && FBitSet( cl->edict->v.groupinfo, pInvoker->v.groupinfo ) == 1 ))
continue;
}
@ -3787,16 +3722,16 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
continue;
}
if( flags & FEV_NOTHOST && cl == svs.currentPlayer && cl->local_weapons )
if( FBitSet( flags, FEV_NOTHOST ) && cl == svs.currentPlayer && FBitSet( cl->flags, FCL_LOCAL_WEAPONS ))
continue; // will be played on client side
if( flags & FEV_HOSTONLY && cl->edict != pInvoker )
if( FBitSet( flags, FEV_HOSTONLY ) && cl->edict != pInvoker )
continue; // sending only to invoker
// all checks passed, send the event
// reliable event
if( flags & FEV_RELIABLE )
if( FBitSet( flags, FEV_RELIABLE ))
{
// skipping queue, write direct into reliable datagram
SV_PlaybackReliableEvent( &cl->netchan.message, eventindex, delay, &args );
@ -3807,11 +3742,12 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
es = &cl->events;
bestslot = -1;
if( flags & FEV_UPDATE )
if( FBitSet( flags, FEV_UPDATE ))
{
for( j = 0; j < MAX_EVENT_QUEUE; j++ )
{
ei = &es->ei[j];
if( ei->index == eventindex && invokerIndex != -1 && invokerIndex == ei->entity_index )
{
bestslot = j;
@ -3864,16 +3800,15 @@ so we can't use a single PVS point
*/
byte *pfnSetFatPVS( const float *org )
{
qboolean fullvis = false;
if( !sv.worldmodel->visdata || sv_novis->integer || !org || CL_DisableVisibility( ))
return Mod_DecompressVis( NULL );
fullvis = true;
ASSERT( svs.currentPlayerNum >= 0 && svs.currentPlayerNum < MAX_CLIENTS );
fatbytes = (sv.worldmodel->numleafs+31)>>3;
bitvector = fatpvs;
// portals can't change viewpoint!
if(!( sv.hostflags & SVF_PORTALPASS ))
if( !FBitSet( sv.hostflags, SVF_MERGE_VISIBILITY ))
{
vec3_t viewPos, offset;
@ -3885,7 +3820,7 @@ byte *pfnSetFatPVS( const float *org )
// }
// so we have unneeded duck calculations who have affect when player
// is ducked into water. Remove offset to restore right PVS position
if( svs.currentPlayer->edict->v.flags & FL_DUCKING )
if( FBitSet( svs.currentPlayer->edict->v.flags, FL_DUCKING ))
{
VectorSubtract( svgame.pmove->player_mins[0], svgame.pmove->player_mins[1], offset );
VectorSubtract( org, offset, viewPos );
@ -3893,17 +3828,16 @@ byte *pfnSetFatPVS( const float *org )
else VectorCopy( org, viewPos );
// build a new PVS frame
memset( bitvector, 0, fatbytes );
SV_AddToFatPVS( viewPos, DVIS_PVS, sv.worldmodel->nodes );
Mod_FatPVS( viewPos, FATPVS_RADIUS, fatpvs, world.fatbytes, false, fullvis );
VectorCopy( viewPos, viewPoint[svs.currentPlayerNum] );
}
else
{
SV_AddToFatPVS( org, DVIS_PVS, sv.worldmodel->nodes );
// merge PVS
Mod_FatPVS( org, FATPVS_RADIUS, fatpvs, world.fatbytes, true, fullvis );
}
return bitvector;
return fatpvs;
}
/*
@ -3916,16 +3850,15 @@ so we can't use a single PHS point
*/
byte *pfnSetFatPAS( const float *org )
{
qboolean fullvis = false;
if( !sv.worldmodel->visdata || sv_novis->integer || !org || CL_DisableVisibility( ))
return Mod_DecompressVis( NULL );
fullvis = true;
ASSERT( svs.currentPlayerNum >= 0 && svs.currentPlayerNum < MAX_CLIENTS );
fatbytes = (sv.worldmodel->numleafs+31)>>3;
bitvector = fatphs;
// portals can't change viewpoint!
if(!( sv.hostflags & SVF_PORTALPASS ))
if( !FBitSet( sv.hostflags, SVF_MERGE_VISIBILITY ))
{
vec3_t viewPos, offset;
@ -3937,7 +3870,7 @@ byte *pfnSetFatPAS( const float *org )
// }
// so we have unneeded duck calculations who have affect when player
// is ducked into water. Remove offset to restore right PVS position
if( svs.currentPlayer->edict->v.flags & FL_DUCKING )
if( FBitSet( svs.currentPlayer->edict->v.flags, FL_DUCKING ))
{
VectorSubtract( svgame.pmove->player_mins[0], svgame.pmove->player_mins[1], offset );
VectorSubtract( org, offset, viewPos );
@ -3945,17 +3878,15 @@ byte *pfnSetFatPAS( const float *org )
else VectorCopy( org, viewPos );
// build a new PHS frame
memset( bitvector, 0, fatbytes );
SV_AddToFatPVS( viewPos, DVIS_PHS, sv.worldmodel->nodes );
Mod_FatPVS( viewPos, FATPHS_RADIUS, fatphs, world.fatbytes, false, fullvis );
}
else
{
// merge PVS
SV_AddToFatPVS( org, DVIS_PHS, sv.worldmodel->nodes );
// merge PHS
Mod_FatPVS( org, FATPHS_RADIUS, fatphs, world.fatbytes, true, fullvis );
}
return bitvector;
return fatphs;
}
/*
@ -3977,7 +3908,7 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
// vis not set - fullvis enabled
if( !pset ) return 1;
if( ent->v.flags & FL_CUSTOMENTITY && ent->v.owner && ent->v.owner->v.flags & FL_CLIENT )
if( FBitSet( ent->v.flags, FL_CUSTOMENTITY ) && ent->v.owner && FBitSet( ent->v.owner->v.flags, FL_CLIENT ))
ent = ent->v.owner; // upcast beams to my owner
if( ent->headnode < 0 )
@ -3985,7 +3916,7 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
// check individual leafs
for( i = 0; i < ent->num_leafs; i++ )
{
if( pset[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7 )))
if( CHECKVISBIT( pset, ent->leafnums[i] ))
return 1; // visible passed by leaf
}
@ -3993,18 +3924,19 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
}
else
{
int leafnum;
short leafnum;
for( i = 0; i < MAX_ENT_LEAFS; i++ )
{
leafnum = ent->leafnums[i];
if( leafnum == -1 ) break;
if( pset[leafnum >> 3] & (1 << ( leafnum & 7 )))
if( CHECKVISBIT( pset, leafnum ))
return 1; // visible passed by leaf
}
// too many leafs for individual check, go by headnode
if( !SV_HeadnodeVisible( &sv.worldmodel->nodes[ent->headnode], pset, &leafnum ))
if( !Mod_HeadnodeVisible( &sv.worldmodel->nodes[ent->headnode], pset, &leafnum ))
return 0;
((edict_t *)ent)->leafnums[ent->num_leafs] = leafnum;
@ -4027,7 +3959,7 @@ int pfnCanSkipPlayer( const edict_t *player )
if(( cl = SV_ClientFromEdict( player, false )) == NULL )
return false;
return cl->local_weapons;
return FBitSet( cl->flags, FCL_LOCAL_WEAPONS );
}
/*
@ -4038,9 +3970,7 @@ pfnGetCurrentPlayer
*/
int pfnGetCurrentPlayer( void )
{
if( svs.currentPlayer )
return (svs.currentPlayer - svs.clients);
return -1;
return svs.currentPlayerNum;
}
/*
@ -4256,7 +4186,7 @@ const char *pfnGetPlayerAuthId( edict_t *e )
{
if( cl->edict == e )
{
if( cl->fakeclient )
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
Q_strncat( result, "BOT", sizeof( result ));
else if( cl->authentication_method == 0 )
Q_snprintf( result, sizeof( result ), "%u", (uint)cl->WonID );

View File

@ -18,10 +18,17 @@ GNU General Public License for more details.
int SV_UPDATE_BACKUP = SINGLEPLAYER_BACKUP;
server_t sv; // local server
server_static_t svs; // persistant server info
svgame_static_t svgame; // persistant game info
server_t sv; // local server
/*
================
SV_ModelIndex
register unique model for a server and client
================
*/
int SV_ModelIndex( const char *filename )
{
char name[64];
@ -60,6 +67,13 @@ int SV_ModelIndex( const char *filename )
return i;
}
/*
================
SV_SoundIndex
register unique sound for client
================
*/
int SV_SoundIndex( const char *filename )
{
char name[64];
@ -98,6 +112,13 @@ int SV_SoundIndex( const char *filename )
return i;
}
/*
================
SV_EventIndex
register network event for a server and client
================
*/
int SV_EventIndex( const char *filename )
{
char name[64];
@ -135,6 +156,13 @@ int SV_EventIndex( const char *filename )
return i;
}
/*
================
SV_GenericIndex
register generic resourse for a server and client
================
*/
int SV_GenericIndex( const char *filename )
{
char name[64];
@ -181,8 +209,8 @@ get entity script for current map
char *SV_EntityScript( void )
{
string entfilename;
char *ents;
size_t ft1, ft2;
char *ents;
if( !sv.worldmodel )
return NULL;
@ -224,14 +252,11 @@ baseline will be transmitted
*/
void SV_CreateBaseline( void )
{
edict_t *pEdict;
int e;
for( e = 0; e < svgame.numEntities; e++ )
{
pEdict = EDICT_NUM( e );
if( !SV_IsValidEdict( pEdict )) continue;
SV_BaselineForEntity( pEdict );
SV_BaselineForEntity( EDICT_NUM( e ));
}
// create the instanced baselines
@ -311,7 +336,7 @@ void SV_ActivateServer( void )
numFrames = (sv.loadgame) ? 1 : 2;
if( !sv.loadgame || svgame.globals->changelevel )
host.frametime = 0.1f;
sv.frametime = 0.1f;
// GoldSrc rules
// NOTE: this stuff is breaking sound from func_rotating in multiplayer
@ -344,10 +369,9 @@ void SV_ActivateServer( void )
MsgDev( D_INFO, "Game started\n" );
}
// dedicated server purge unused resources here
if( host.type == HOST_DEDICATED )
{
Mod_FreeUnused ();
}
sv.state = ss_active;
physinfo->modified = true;
@ -529,8 +553,7 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot )
svgame.globals->time = sv.time;
// initialize buffers
MSG_Init( &sv.datagram, "Datagram", sv.datagram_buf, sizeof( sv.datagram_buf ));
MSG_Init( &sv.reliable_datagram, "Datagram R", sv.reliable_datagram_buf, sizeof( sv.reliable_datagram_buf ));
MSG_Init( &sv.reliable_datagram, "Reliable Datagram", sv.reliable_datagram_buf, sizeof( sv.reliable_datagram_buf ));
MSG_Init( &sv.multicast, "Multicast", sv.multicast_buf, sizeof( sv.multicast_buf ));
MSG_Init( &sv.signon, "Signon", sv.signon_buf, sizeof( sv.signon_buf ));
MSG_Init( &sv.spectator_datagram, "Spectator Datagram", sv.spectator_buf, sizeof( sv.spectator_buf ));
@ -587,12 +610,6 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot )
// clear physics interaction links
SV_ClearWorld();
// disabled because invoke crash in battlegrounds mod
#if 0
// tell dlls about new level started
svgame.dllFuncs.pfnParmsNewLevel();
#endif
return true;
}
@ -674,6 +691,7 @@ void SV_InitGame( void )
svs.num_client_entities = sv_maxclients->integer * SV_UPDATE_BACKUP * 64;
svs.packet_entities = Z_Malloc( sizeof( entity_state_t ) * svs.num_client_entities );
svs.baselines = Z_Malloc( sizeof( entity_state_t ) * GI->max_edicts );
MsgDev( D_INFO, "%s alloced by server packet entities\n", Q_memprint( sizeof( entity_state_t ) * svs.num_client_entities ));
// client frames will be allocated in SV_DirectConnect
@ -693,8 +711,8 @@ void SV_InitGame( void )
{
// setup all the clients
ent = EDICT_NUM( i + 1 );
SV_InitEdict( ent );
svs.clients[i].edict = ent;
SV_InitEdict( ent );
}
// get actual movevars

View File

@ -113,7 +113,7 @@ void SV_CalcPings( void )
{
cl = &svs.clients[i];
if( cl->state != cs_spawned || cl->fakeclient )
if( cl->state != cs_spawned || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
total = count = 0;
@ -152,7 +152,7 @@ int SV_CalcPacketLoss( sv_client_t *cl )
lost = 0;
count = 0;
if( cl->fakeclient )
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
return 0;
numsamples = SV_UPDATE_BACKUP / 2;
@ -160,9 +160,9 @@ int SV_CalcPacketLoss( sv_client_t *cl )
for( i = 0; i < numsamples; i++ )
{
frame = &cl->frames[(cl->netchan.incoming_acknowledged - 1 - i) & SV_UPDATE_MASK];
count++;
if( frame->latency == -1 )
lost++;
count++;
}
if( !count ) return 100;
@ -370,7 +370,7 @@ void SV_ReadPackets( void )
// check for packets from connected clients
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->state == cs_free || cl->fakeclient )
if( cl->state == cs_free || FBitSet( cl->flags, FCL_FAKECLIENT ))
continue;
if( !NET_CompareBaseAdr( net_from, cl->netchan.remote_address ))
@ -381,21 +381,21 @@ void SV_ReadPackets( void )
if( cl->netchan.remote_address.port != net_from.port )
{
MsgDev( D_INFO, "SV_ReadPackets: fixing up a translated port\n");
MsgDev( D_NOTE, "SV_ReadPackets: fixing up a translated port\n");
cl->netchan.remote_address.port = net_from.port;
}
if( Netchan_Process( &cl->netchan, &net_message ))
{
if( sv_maxclients->integer == 1 || cl->state != cs_spawned )
cl->send_message = true; // reply at end of frame
if(( sv_maxclients->integer == 1 && !FBitSet( host.features, ENGINE_FIXED_FRAMERATE )) || cl->state != cs_spawned )
SetBits( cl->flags, FCL_SEND_NET_MESSAGE ); // reply at end of frame
// this is a valid, sequenced packet, so process it
if( cl->state != cs_zombie )
{
cl->lastmessage = host.realtime; // don't timeout
SV_ExecuteClientMessage( cl, &net_message );
svgame.globals->frametime = host.frametime;
svgame.globals->frametime = sv.frametime;
svgame.globals->time = sv.time;
}
}
@ -449,12 +449,13 @@ void SV_CheckTimeouts( void )
{
if( cl->state >= cs_connected )
{
if( cl->edict && !( cl->edict->v.flags & (FL_SPECTATOR|FL_FAKECLIENT)))
if( cl->edict && !FBitSet( cl->edict->v.flags, FL_SPECTATOR|FL_FAKECLIENT ))
numclients++;
}
// fake clients do not timeout
if( cl->fakeclient ) cl->lastmessage = host.realtime;
if( FBitSet( cl->flags, FCL_FAKECLIENT ))
cl->lastmessage = host.realtime;
// message times may be wrong across a changelevel
if( cl->lastmessage > host.realtime )
@ -466,11 +467,14 @@ void SV_CheckTimeouts( void )
continue;
}
if(( cl->state == cs_connected || cl->state == cs_spawned ) && cl->lastmessage < droppoint && !NET_IsLocalAddress( cl->netchan.remote_address ))
if(( cl->state == cs_connected || cl->state == cs_spawned ) && cl->lastmessage < droppoint )
{
SV_BroadcastPrintf( PRINT_HIGH, "%s timed out\n", cl->name );
SV_DropClient( cl );
cl->state = cs_free; // don't bother with zombie state
if( !NET_IsLocalAddress( cl->netchan.remote_address ))
{
SV_BroadcastPrintf( NULL, PRINT_HIGH, "%s timed out\n", cl->name );
SV_DropClient( cl );
cl->state = cs_free; // don't bother with zombie state
}
}
}
@ -499,7 +503,7 @@ void SV_PrepWorldFrame( void )
ent = EDICT_NUM( i );
if( ent->free ) continue;
ent->v.effects &= ~(EF_MUZZLEFLASH|EF_NOINTERP);
ClearBits( ent->v.effects, EF_MUZZLEFLASH|EF_NOINTERP );
}
}
@ -528,12 +532,15 @@ qboolean SV_IsSimulating( void )
return true; // force simulating for background map
}
if( sv.hostflags & SVF_PLAYERSONLY )
if( FBitSet( sv.hostflags, SVF_PLAYERSONLY ))
return false;
if( !SV_HasActivePlayers())
return false;
if( !sv.paused && CL_IsInGame( ))
return true;
return false;
}
@ -542,13 +549,38 @@ qboolean SV_IsSimulating( void )
SV_RunGameFrame
=================
*/
void SV_RunGameFrame( void )
/*
=================
SV_RunGameFrame
=================
*/
qboolean SV_RunGameFrame( void )
{
if( !SV_IsSimulating( )) return;
int numFrames = 0;
SV_Physics();
if( !( sv.simulating = SV_IsSimulating( )))
return true;
sv.time += host.frametime;
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
{
while( sv.time_residual >= sv.frametime )
{
SV_Physics();
sv.time_residual -= sv.frametime;
sv.time += sv.frametime;
numFrames++;
}
return (numFrames != 0);
}
else
{
SV_Physics();
sv.time += sv.frametime;
return true;
}
}
/*
@ -562,7 +594,14 @@ void Host_ServerFrame( void )
// if server is not active, do nothing
if( !svs.initialized ) return;
svgame.globals->frametime = host.frametime;
if( FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
sv.frametime = ( 1.0 / (double)( GAME_FPS - 0.01 )); // FP issues
else sv.frametime = host.frametime;
if( sv.simulating || sv.state != ss_active )
sv.time_residual += host.frametime;
svgame.globals->frametime = sv.frametime;
// check timeouts
SV_CheckTimeouts ();
@ -583,7 +622,7 @@ void Host_ServerFrame( void )
SV_UpdateMovevars ( false );
// let everything in the world think and move
SV_RunGameFrame ();
if( !SV_RunGameFrame ()) return;
// send messages back to the clients that had packets read this frame
SV_SendClientMessages ();
@ -678,7 +717,7 @@ void SV_AddToMaster( netadr_t from, sizebuf_t *msg )
{
if( svs.clients[index].state >= cs_connected )
{
if( svs.clients[index].fakeclient )
if( FBitSet( svs.clients[index].flags, FCL_FAKECLIENT ))
bots++;
else clients++;
}
@ -848,11 +887,11 @@ void SV_FinalMessage( char *message, qboolean reconnect )
// send it twice
// stagger the packets to crutch operating system limited buffers
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
if( cl->state >= cs_connected && !cl->fakeclient )
if( cl->state >= cs_connected && !FBitSet( cl->flags, FCL_FAKECLIENT ))
Netchan_Transmit( &cl->netchan, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg ));
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
if( cl->state >= cs_connected && !cl->fakeclient )
if( cl->state >= cs_connected && !FBitSet( cl->flags, FCL_FAKECLIENT ))
Netchan_Transmit( &cl->netchan, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg ));
}

View File

@ -200,7 +200,7 @@ qboolean SV_RunThink( edict_t *ent )
if(!( ent->v.flags & FL_KILLME ))
{
thinktime = ent->v.nextthink;
if( thinktime <= 0.0f || thinktime > sv.time + host.frametime )
if( thinktime <= 0.0f || thinktime > sv.time + sv.frametime )
return true;
if( thinktime < sv.time )
@ -703,8 +703,8 @@ void SV_AddGravity( edict_t *ent )
else ent_gravity = 1.0f;
// add gravity incorrectly
ent->v.velocity[2] -= ( ent_gravity * sv_gravity->value * host.frametime );
ent->v.velocity[2] += ( ent->v.basevelocity[2] * host.frametime );
ent->v.velocity[2] -= ( ent_gravity * sv_gravity->value * sv.frametime );
ent->v.velocity[2] += ( ent->v.basevelocity[2] * sv.frametime );
ent->v.basevelocity[2] = 0.0f;
// bound velocity
@ -727,7 +727,7 @@ void SV_AddHalfGravity( edict_t *ent, float timestep )
// Add 1/2 of the total gravitational effects over this timestep
ent->v.velocity[2] -= ( 0.5f * ent_gravity * sv_gravity->value * timestep );
ent->v.velocity[2] += ( ent->v.basevelocity[2] * host.frametime );
ent->v.velocity[2] += ( ent->v.basevelocity[2] * sv.frametime );
ent->v.basevelocity[2] = 0.0f;
// bound velocity
@ -1128,12 +1128,12 @@ void SV_Physics_Pusher( edict_t *ent )
oldtime = ent->v.ltime;
thinktime = ent->v.nextthink;
if( thinktime < oldtime + host.frametime )
if( thinktime < oldtime + sv.frametime )
{
movetime = thinktime - oldtime;
if( movetime < 0.0f ) movetime = 0.0f;
}
else movetime = host.frametime;
else movetime = sv.frametime;
if( movetime )
{
@ -1247,7 +1247,7 @@ void SV_Physics_Compound( edict_t *ent )
{
VectorCopy( parent->v.origin, ent->v.oldorigin );
VectorCopy( parent->v.angles, ent->v.avelocity );
ent->v.ltime = host.frametime;
ent->v.ltime = sv.frametime;
return;
}
@ -1303,8 +1303,8 @@ void SV_Physics_Noclip( edict_t *ent )
SV_CheckWater( ent );
VectorMA( ent->v.origin, host.frametime, ent->v.velocity, ent->v.origin );
VectorMA( ent->v.angles, host.frametime, ent->v.avelocity, ent->v.angles );
VectorMA( ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin );
VectorMA( ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles );
// noclip ents never touch triggers
SV_LinkEdict( ent, false );
@ -1444,10 +1444,10 @@ void SV_Physics_Toss( edict_t *ent )
{
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
SV_AngularMove( ent, host.frametime, ent->v.friction );
SV_AngularMove( ent, sv.frametime, ent->v.friction );
break;
default:
SV_AngularMove( ent, host.frametime, 0.0f );
SV_AngularMove( ent, sv.frametime, 0.0f );
break;
}
@ -1457,7 +1457,7 @@ void SV_Physics_Toss( edict_t *ent )
VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
SV_CheckVelocity( ent );
VectorScale( ent->v.velocity, host.frametime, move );
VectorScale( ent->v.velocity, sv.frametime, move );
VectorSubtract( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
@ -1496,7 +1496,7 @@ void SV_Physics_Toss( edict_t *ent )
VectorAdd( ent->v.velocity, ent->v.basevelocity, move );
vel = DotProduct( move, move );
if( ent->v.velocity[2] < sv_gravity->value * host.frametime )
if( ent->v.velocity[2] < sv_gravity->value * sv.frametime )
{
// we're rolling on the ground, add static friction.
ent->v.groundentity = trace.ent;
@ -1513,8 +1513,8 @@ void SV_Physics_Toss( edict_t *ent )
}
else
{
VectorScale( ent->v.velocity, (1.0f - trace.fraction) * host.frametime * 0.9f, move );
VectorMA( move, (1.0f - trace.fraction) * host.frametime * 0.9f, ent->v.basevelocity, move );
VectorScale( ent->v.velocity, (1.0f - trace.fraction) * sv.frametime * 0.9f, move );
VectorMA( move, (1.0f - trace.fraction) * sv.frametime * 0.9f, ent->v.basevelocity, move );
trace = SV_PushEntity( ent, move, vec3_origin, NULL );
if( ent->free ) return;
}
@ -1561,7 +1561,7 @@ void SV_Physics_Step( edict_t *ent )
if( ent->v.flags & FL_FLOAT && ent->v.waterlevel > 0 )
{
float buoyancy = SV_Submerged( ent ) * ent->v.skin * host.frametime;
float buoyancy = SV_Submerged( ent ) * ent->v.skin * sv.frametime;
SV_AddGravity( ent );
ent->v.velocity[2] += buoyancy;
@ -1592,7 +1592,7 @@ void SV_Physics_Step( edict_t *ent )
if( wasonmover ) friction *= 0.5f; // add a little friction
control = (speed < sv_stopspeed->value) ? sv_stopspeed->value : speed;
newspeed = speed - (host.frametime * control * friction);
newspeed = speed - (sv.frametime * control * friction);
if( newspeed < 0 ) newspeed = 0;
newspeed /= speed;
@ -1604,7 +1604,7 @@ void SV_Physics_Step( edict_t *ent )
VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
SV_CheckVelocity( ent );
SV_FlyMove( ent, host.frametime, NULL );
SV_FlyMove( ent, sv.frametime, NULL );
if( ent->free ) return;
SV_CheckVelocity( ent );
@ -1685,7 +1685,7 @@ static void SV_Physics_Entity( edict_t *ent )
if(!( ent->v.flags & FL_BASEVELOCITY ) && !VectorIsNull( ent->v.basevelocity ))
{
// Apply momentum (add in half of the previous frame of velocity first)
VectorMA( ent->v.velocity, 1.0f + (host.frametime * 0.5f), ent->v.basevelocity, ent->v.velocity );
VectorMA( ent->v.velocity, 1.0f + (sv.frametime * 0.5f), ent->v.basevelocity, ent->v.velocity );
VectorClear( ent->v.basevelocity );
}
@ -1777,7 +1777,7 @@ void SV_Physics( void )
if( sv_skyspeed->value )
{
// evaluate sky rotation.
float skyAngle = sv_skyangle->value + sv_skyspeed->value * host.frametime;
float skyAngle = sv_skyangle->value + sv_skyspeed->value * sv.frametime;
Cvar_SetFloat( "sv_skyangle", anglemod( skyAngle ));
}
@ -1809,7 +1809,7 @@ Inplementation for new physics interface
*/
double SV_GetFrameTime( void )
{
return host.frametime;
return sv.frametime;
}
/*

View File

@ -148,7 +148,7 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin )
{
if( !cl->lag_compensation || !sv_unlag->integer )
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ) || !sv_unlag->integer )
return;
// don't allow unlag in singleplayer
@ -165,7 +165,7 @@ void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin )
void SV_GetTrueMinMax( sv_client_t *cl, int edictnum, vec3_t mins, vec3_t maxs )
{
if( !cl->lag_compensation || !sv_unlag->integer )
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ) || !sv_unlag->integer )
return;
// don't allow unlag in singleplayer
@ -225,12 +225,12 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
continue;
// ignore monsterclip brushes
if(( check->v.flags & FL_MONSTERCLIP ) && check->v.solid == SOLID_BSP )
if( FBitSet( check->v.flags, FL_MONSTERCLIP ) && check->v.solid == SOLID_BSP )
continue;
if( check == pl ) continue; // himself
if((( check->v.flags & FL_CLIENT ) && check->v.health <= 0 ) || check->v.deadflag == DEAD_DEAD )
if(( FBitSet( check->v.flags, FL_CLIENT|FL_FAKECLIENT ) && check->v.health <= 0.0f ) || check->v.deadflag == DEAD_DEAD )
continue; // dead body
if( VectorIsNull( check->v.size ))
@ -239,7 +239,7 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
VectorCopy( check->v.absmin, mins );
VectorCopy( check->v.absmax, maxs );
if( check->v.flags & FL_CLIENT )
if( FBitSet( check->v.flags, FL_CLIENT ))
{
// trying to get interpolated values
if( svs.currentPlayer )
@ -620,14 +620,14 @@ static void PM_CheckMovingGround( edict_t *ent, float frametime )
SV_UpdateBaseVelocity( ent );
}
if( !( ent->v.flags & FL_BASEVELOCITY ))
if( !FBitSet( ent->v.flags, FL_BASEVELOCITY ))
{
// apply momentum (add in half of the previous frame of velocity first)
VectorMA( ent->v.velocity, 1.0f + (frametime * 0.5f), ent->v.basevelocity, ent->v.velocity );
VectorClear( ent->v.basevelocity );
}
ent->v.flags &= ~FL_BASEVELOCITY;
ClearBits( ent->v.flags, FL_BASEVELOCITY );
}
static void SV_SetupPMove( playermove_t *pmove, sv_client_t *cl, usercmd_t *ucmd, const char *physinfo )
@ -827,7 +827,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
return;
// unlag disabled for current client
if( !cl->lag_compensation )
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ))
return;
has_update = true;
@ -986,7 +986,7 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
return;
// unlag disabled for current client
if( !cl->lag_compensation )
if( !FBitSet( cl->flags, FCL_LAG_COMPENSATION ))
return;
for( i = 0, check = svs.clients; i < sv_maxclients->integer; i++, check++ )
@ -1050,7 +1050,7 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
return;
}
if( !cl->fakeclient )
if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
{
SV_SetupMoveInterpolant( cl );
}
@ -1127,7 +1127,7 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
svgame.dllFuncs.pfnPlayerPostThink( clent );
svgame.dllFuncs.pfnCmdEnd( clent );
if( !cl->fakeclient )
if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
{
SV_RestoreMoveInterpolant( cl );
}

View File

@ -32,7 +32,7 @@ half-life implementation of saverestore system
#define SAVEGAME_VERSION 0x0065 // Version 0.65
#define CLIENT_SAVEGAME_VERSION 0x0068 // Version 0.68
#define SAVE_AGED_COUNT 1
#define SAVE_AGED_COUNT 2
#define SAVENAME_LENGTH 128 // matches with MAX_OSPATH
#define LUMP_DECALS_OFFSET 0
@ -723,7 +723,8 @@ void SV_DirectoryCopy( const char *pPath, file_t *pFile )
void SV_DirectoryExtract( file_t *pFile, int fileCount )
{
char szName[SAVENAME_LENGTH], fileName[SAVENAME_LENGTH];
char szName[SAVENAME_LENGTH];
char fileName[SAVENAME_LENGTH];
int i, fileSize;
file_t *pCopy;

View File

@ -536,15 +536,14 @@ SV_FindTouchedLeafs
*/
void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
{
mplane_t *splitplane;
int sides, leafnum;
int sides;
mleaf_t *leaf;
if( !node || node->contents == CONTENTS_SOLID )
if( node->contents == CONTENTS_SOLID )
return;
// add an efrag if the node is a leaf
if( node->contents < 0 )
if( node->contents < 0 )
{
if( ent->num_leafs > ( MAX_ENT_LEAFS - 1 ))
{
@ -555,18 +554,16 @@ void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
else
{
leaf = (mleaf_t *)node;
leafnum = leaf - sv.worldmodel->leafs - 1;
ent->leafnums[ent->num_leafs] = leafnum;
ent->leafnums[ent->num_leafs] = leaf->cluster;
ent->num_leafs++;
}
return;
}
// NODE_MIXED
splitplane = node->plane;
sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, splitplane );
sides = BOX_ON_PLANE_SIDE( ent->v.absmin, ent->v.absmax, node->plane );
if( sides == 3 && *headnode == -1 )
if(( sides == 3 ) && ( *headnode == -1 ))
*headnode = node - sv.worldmodel->nodes;
// recurse down the contacted sides
@ -574,36 +571,6 @@ void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node, int *headnode )
if( sides & 2 ) SV_FindTouchedLeafs( ent, node->children[1], headnode );
}
/*
=============
SV_HeadnodeVisible
=============
*/
qboolean SV_HeadnodeVisible( mnode_t *node, byte *visbits, int *lastleaf )
{
int leafnum;
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
leafnum = ((mleaf_t *)node - sv.worldmodel->leafs) - 1;
if(!( visbits[leafnum >> 3] & (1<<( leafnum & 7 ))))
return false;
if( lastleaf )
*lastleaf = leafnum;
return true;
}
if( SV_HeadnodeVisible( node->children[0], visbits, lastleaf ))
return true;
return SV_HeadnodeVisible( node->children[1], visbits, lastleaf );
}
/*
===============
SV_LinkEdict
@ -623,9 +590,9 @@ void SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
if( ent->v.movetype == MOVETYPE_FOLLOW && SV_IsValidEdict( ent->v.aiment ))
{
ent->headnode = ent->v.aiment->headnode;
ent->num_leafs = ent->v.aiment->num_leafs;
memcpy( ent->leafnums, ent->v.aiment->leafnums, sizeof( ent->leafnums ));
ent->num_leafs = ent->v.aiment->num_leafs;
ent->headnode = ent->v.aiment->headnode;
}
else
{
@ -1560,7 +1527,7 @@ void SV_RunLightStyles( void )
// run lightstyles animation
for( i = 0, ls = sv.lightstyles; i < MAX_LIGHTSTYLES; i++, ls++ )
{
ls->time += host.frametime;
ls->time += sv.frametime;
ofs = (ls->time * 10);
if( ls->length == 0 ) ls->value = scale; // disable this light

View File

@ -80,8 +80,7 @@
#ifdef _WIN32
# define VGUIAPI __declspec( dllexport )
#else
# define VGUIAPI __attribute__ ((visibility("default")))
#include <sys/types.h> // size_t define
# define VGUIAPI
#endif
#define null 0L
@ -94,7 +93,7 @@ typedef unsigned long ulong;
namespace vgui
{
VGUIAPI void vgui_setMalloc(void *(*malloc)(size_t size) );
VGUIAPI void vgui_setMalloc(void* (*malloc)(size_t size));
VGUIAPI void vgui_setFree(void (*free)(void* memblock));
VGUIAPI void vgui_strcpy(char* dst,int dstLen,const char* src);
VGUIAPI char* vgui_strdup(const char* src);

View File

@ -17,6 +17,8 @@
namespace vgui
{
enum MouseCode;
enum KeyCode;
class Panel;
class TickSignal;
class Scheme;
@ -115,7 +117,7 @@ protected:
bool _buildMode;
bool _wantedBuildMode;
Panel* _mouseArenaPanel;
Cursor* _cursor[Cursor::dc_last];
Cursor* _cursor[Cursor::DefaultCursor::dc_last];
Cursor* _cursorOveride;
private:
long _nextTickMillis;

View File

@ -10,8 +10,7 @@
#include<VGUI.h>
#include<VGUI_Dar.h>
#include <VGUI_MouseCode.h>
#include <VGUI_KeyCode.h>
namespace vgui
{

View File

@ -166,7 +166,6 @@ protected:
ELEMTYPE* _data;
};
#ifdef _WIN32
//forward referencing all the template types used so they get exported
template class VGUIAPI Dar<char>;
template class VGUIAPI Dar<char*>;
@ -186,7 +185,7 @@ template class VGUIAPI Dar<class ChangeSignal*>;
template class VGUIAPI Dar<class Panel*>;
template class VGUIAPI Dar<class Label*>;
template class VGUIAPI Dar<class RepaintSignal*>;
#endif
}

View File

@ -32,9 +32,6 @@ class VGUIAPI Font
virtual void getCharABCwide(int ch,int& a,int& b,int& c);
virtual void getTextSize(const char* text,int& wide,int& tall);
virtual int getTall();
#ifndef _WIN32
virtual int getWide();
#endif
virtual int getId();
protected:
char* _name;

View File

@ -11,7 +11,6 @@
#include<VGUI.h>
#include<VGUI_Panel.h>
#include<VGUI_Scheme.h>
#include<VGUI_Image.h>
//TODO: this should use a TextImage for the text

View File

@ -28,10 +28,6 @@ TODO:
#include<VGUI_Dar.h>
#include<VGUI_Scheme.h>
#include<VGUI_Color.h>
#include<VGUI_Cursor.h>
#include <VGUI_MouseCode.h>
#include <VGUI_KeyCode.h>
#include <VGUI_RepaintSignal.h>
namespace vgui
{

View File

@ -1,117 +0,0 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_Point_H
#define VGUI_Point_H
#ifdef _WIN32
#pragma once
#endif
#include <VGUI.h>
namespace vgui
{
//-----------------------------------------------------------------------------
// Purpose: Basic handler for a Points in 2 dimensions
// This class is fully inline
//-----------------------------------------------------------------------------
class Point
{
public:
// constructors
Point()
{
SetPoint(0, 0);
}
Point(int x,int y)
{
SetPoint(x,y);
}
void SetPoint(int x1, int y1)
{
x=x1;
y=y1;
}
void GetPoint(int& x1,int& y1) const
{
x1 = x;
y1 = y;
}
bool operator == (Point &rhs) const
{
return ( x == rhs.x && y==rhs.y);
}
private:
int x,y;
};
}
#endif // VGUI_Point_H
//## <b>class Point</b>
//## Point is a class to handle Points in VGUI.
//## // The default Point is (0,0,0,0)
//## Point()
//##
//## // A Point may be created with x,yvalues.
//## Point(int x,int y)
//##
//## // Set the x,y components of the Point.
//## void SetPoint(int x1, int y1)
//##
//## // Get the position of the Point
//## void GetPoint(int& x1,int& y1) const
//##
//## // Point classes can be set equal to each other.
//## bool operator == (Point &rhs) const
//##
//##
//## <hr>
//##
//##
//## <method>Point()
//## Description: Default constructor. The default Point is (0,0,0,0)
//##
//##
//## <method>Point(int x,int y)
//## Description:
//## A Point may be created with a x,y position.
//## Arguments:
//## x - x position (horizontal axis) (0-65535)
//## y - y position (vertical axis) (0-65535)
//##
//##
//## <method>void SetPoint(int x1, int x1)
//## Description:
//## Set the position of the Point.
//## Arguments:
//## x - x position (horizontal axis) (0-65535)
//## y - y position (vertical axis) (0-65535)
//##
//##
//## <method>void GetPoint(int& x1,int& y1) const
//## Description:
//## Get the x,y components of a Point
//## Arguments:
//## x - x position (horizontal axis) (0-65535)
//## y - y position (vertical axis) (0-65535)
//##
//## <method>bool operator == (Point &rhs) const
//## Description:
//## Point classes can be set equal to each other.
//##
//##

View File

@ -12,8 +12,7 @@
namespace vgui
{
class Panel;
class RepaintSignal
{
public:

View File

@ -31,7 +31,6 @@ public:
virtual void createPopup(Panel* embeddedPanel);
virtual bool hasFocus();
virtual bool isWithin(int x,int y);
virtual void GetMousePos( int &x, int &y );
protected:
virtual int createNewTextureID(void);
virtual void drawSetColor(int r,int g,int b,int a);

View File

@ -44,7 +44,6 @@ public:
virtual bool hasFocus()=0;
virtual bool isWithin(int x,int y)=0;
virtual int createNewTextureID(void)=0;
virtual void GetMousePos( int &x, int &y ) = 0;
protected:
virtual void addModeInfo(int wide,int tall,int bpp);
protected:

View File

@ -10,7 +10,6 @@
#include<VGUI_Panel.h>
#include<VGUI_Dar.h>
#include<VGUI_Button.h>
namespace vgui
{

Binary file not shown.