22 Nov 2016
This commit is contained in:
parent
91b1f6c082
commit
096f37c189
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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++ )
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
|
||||
#include<VGUI.h>
|
||||
#include<VGUI_Dar.h>
|
||||
#include <VGUI_MouseCode.h>
|
||||
#include <VGUI_KeyCode.h>
|
||||
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
//##
|
||||
//##
|
|
@ -12,8 +12,7 @@
|
|||
|
||||
namespace vgui
|
||||
{
|
||||
class Panel;
|
||||
|
||||
|
||||
class RepaintSignal
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include<VGUI_Panel.h>
|
||||
#include<VGUI_Dar.h>
|
||||
#include<VGUI_Button.h>
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
|
Binary file not shown.
Reference in New Issue