05 Aug 2010

This commit is contained in:
g-cont 2010-08-05 00:00:00 +04:00 committed by Alibek Omarov
parent edcae071bd
commit 621d270b4b
43 changed files with 2377 additions and 1474 deletions

View File

@ -1215,7 +1215,6 @@ addEntity:
state->rendermode = pEntity->pev->rendermode; // rendering mode
state->renderamt = pEntity->pev->renderamt; // alpha value
state->animtime = (int)(1000.0 * pEntity->pev->animtime) * 0.001; // sequence time
state->localtime = (int)(1000.0 * pEntity->pev->ltime) * 0.001; // movement time
state->scale = pEntity->pev->scale; // shared client and render flags
state->movetype = (movetype_t)pEntity->pev->movetype;
state->frame = pEntity->pev->frame; // any model current frame
@ -1223,24 +1222,27 @@ addEntity:
state->mins = pEntity->pev->mins;
state->maxs = pEntity->pev->maxs;
state->flags = pEntity->pev->flags;
state->rendercolor = pEntity->pev->rendercolor;
state->oldorigin = pEntity->pev->oldorigin;
state->colormap = pEntity->pev->colormap; // attachments
state->rendercolor.r = (byte)pEntity->pev->rendercolor.x;
state->rendercolor.g = (byte)pEntity->pev->rendercolor.y;
state->rendercolor.b = (byte)pEntity->pev->rendercolor.z;
if( pEntity->pev->groundentity )
state->groundent = ENTINDEX( pEntity->pev->groundentity );
else state->groundent = -1;
state->onground = ENTINDEX( pEntity->pev->groundentity );
else state->onground = 0;
// translate attached entity
if( pEntity->pev->aiment )
state->aiment = ENTINDEX( pEntity->pev->aiment );
else state->aiment = -1;
else state->aiment = 0;
// studio model sequence
if( pEntity->pev->sequence != -1 )
state->sequence = pEntity->pev->sequence;
for( int i = 0; i < 16; i++ )
for( int i = 0; i < 4; i++ )
{
// copy blendings and bone ctrlrs
state->blending[i] = pEntity->pev->blending[i];
@ -1256,18 +1258,12 @@ addEntity:
pEntity->pev->teleport_time = 0.0f;
}
if( pEntity->pev->viewmodel )
state->viewmodel = MODEL_INDEX( STRING( pEntity->pev->viewmodel ));
else state->viewmodel = 0;
if( pEntity->pev->aiment )
state->aiment = ENTINDEX( pEntity->pev->aiment );
else state->aiment = -1;
else state->aiment = 0;
state->viewoffset = pEntity->pev->view_ofs;
state->viewangles = pEntity->pev->v_angle;
state->idealpitch = pEntity->pev->idealpitch;
state->punch_angles = pEntity->pev->punchangle;
state->velocity = pEntity->pev->velocity;
state->basevelocity = pEntity->pev->clbasevelocity;
state->iStepLeft = pEntity->pev->iStepLeft;
@ -1279,13 +1275,7 @@ addEntity:
if( pEntity->pev->weaponmodel != iStringNull )
state->weaponmodel = MODEL_INDEX( STRING( pEntity->pev->weaponmodel ));
else state->weaponmodel = 0;
state->weapons = pEntity->pev->weapons;
state->maxspeed = pEntity->pev->maxspeed;
// clamp fov
if( pEntity->pev->fov < 0.0 ) pEntity->pev->fov = 0.0;
if( pEntity->pev->fov > 160 ) pEntity->pev->fov = 160;
state->fov = pEntity->pev->fov;
}
else if( state->ed_type == ED_AMBIENT )
{
@ -1306,7 +1296,7 @@ addEntity:
// translate StartBeamEntity
if( pEntity->pev->owner )
state->owner = ENTINDEX( pEntity->pev->owner );
else state->owner = -1;
else state->owner = 0;
}
return 1;
@ -1332,9 +1322,9 @@ void CreateBaseline( entity_state_t *baseline, edict_t *entity, int playermodeli
// render information
baseline->rendermode = (byte)entity->v.rendermode;
baseline->renderamt = (byte)entity->v.renderamt;
baseline->rendercolor.x = (byte)entity->v.rendercolor.x;
baseline->rendercolor.y = (byte)entity->v.rendercolor.y;
baseline->rendercolor.z = (byte)entity->v.rendercolor.z;
baseline->rendercolor.r = (byte)entity->v.rendercolor.x;
baseline->rendercolor.g = (byte)entity->v.rendercolor.y;
baseline->rendercolor.b = (byte)entity->v.rendercolor.z;
baseline->renderfx = (byte)entity->v.renderfx;
baseline->mins = entity->v.mins;

View File

@ -188,13 +188,6 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
m_fLerp = 1.0f;
else m_fLerp = GetLerpFrac();
if( state->flags & FL_PROJECTILE && state->ed_flags & ( ESF_NO_PREDICTION|ESF_NODELTA ))
{
// cut rocket trail, dont pass it from teleport
// FIXME: don't work
g_pViewRenderBeams->KillDeadBeams( ent );
}
// copy state to progs
ent->v.modelindex = state->modelindex;
ent->v.weaponmodel = state->weaponmodel;
@ -212,23 +205,25 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
ent->v.colormap = state->colormap;
ent->v.rendermode = state->rendermode;
ent->v.renderfx = state->renderfx;
ent->v.fov = state->fov;
// ent->v.fov = state->fov;
ent->v.scale = state->scale;
ent->v.weapons = state->weapons;
ent->v.gravity = state->gravity;
ent->v.health = state->health;
ent->v.solid = state->solid;
ent->v.movetype = state->movetype;
ent->v.flags = state->flags;
ent->v.idealpitch = state->idealpitch;
ent->v.animtime = state->animtime;
ent->v.ltime = state->localtime;
if( state->groundent != -1 )
ent->v.groundentity = GetEntityByIndex( state->groundent );
if( ent != GetLocalPlayer())
{
ent->v.health = state->health;
}
if( state->onground )
ent->v.groundentity = GetEntityByIndex( state->onground );
else ent->v.groundentity = NULL;
if( state->aiment != -1 )
if( state->aiment )
ent->v.aiment = GetEntityByIndex( state->aiment );
else ent->v.aiment = NULL;
@ -255,15 +250,17 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
else
{
ent->v.angles = LerpAngle( prev->angles, state->angles, m_fLerp );
ent->v.origin = LerpPoint( prev->origin, state->origin, m_fLerp );
ent->v.basevelocity = LerpPoint( prev->basevelocity, state->basevelocity, m_fLerp );
}
// interpolate scale, renderamount etc
ent->v.scale = LerpPoint( prev->scale, state->scale, m_fLerp );
ent->v.rendercolor = LerpPoint( prev->rendercolor, state->rendercolor, m_fLerp );
ent->v.renderamt = LerpPoint( prev->renderamt, state->renderamt, m_fLerp );
ent->v.rendercolor.x = state->rendercolor.r;
ent->v.rendercolor.y = state->rendercolor.g;
ent->v.rendercolor.z = state->rendercolor.b;
if( ent->v.animtime )
{
// use normal studio lerping
@ -278,32 +275,21 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
switch( state->ed_type )
{
case ED_CLIENT:
ent->v.punchangle = LerpAngle( prev->punch_angles, state->punch_angles, m_fLerp );
ent->v.v_angle = LerpAngle( prev->viewangles, state->viewangles, m_fLerp );
ent->v.view_ofs = LerpPoint( prev->viewoffset, state->viewoffset, m_fLerp );
if( prev->fov != 90.0f && state->fov == 90.0f )
ent->v.fov = state->fov; // fov is reset, so don't lerping
else ent->v.fov = LerpPoint( prev->fov, state->fov, m_fLerp );
if( ent != GetLocalPlayer( ))
{
ent->v.origin = LerpPoint( prev->origin, state->origin, m_fLerp );
if( prev->fov != 90.0f && state->fov == 90.0f )
ent->v.fov = state->fov; // fov is reset, so don't lerping
else ent->v.fov = LerpPoint( prev->fov, state->fov, m_fLerp );
}
ent->v.maxspeed = state->maxspeed;
ent->v.iStepLeft = state->iStepLeft;
ent->v.flFallVelocity = state->flFallVelocity;
if( ent == GetLocalPlayer())
{
edict_t *viewent = GetViewModel();
// if viewmodel has changed update sequence here
if( viewent->v.modelindex != state->viewmodel )
{
// ALERT( at_console, "Viewmodel changed\n" );
SendWeaponAnim( viewent->v.sequence, viewent->v.body, viewent->v.framerate );
}
// setup player viewmodel (only for local player!)
viewent->v.modelindex = state->viewmodel;
gHUD.m_flFOV = ent->v.fov; // keep client fov an actual
}
break;
case ED_PORTAL:
case ED_MOVER:
@ -326,7 +312,7 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
case ED_BEAM:
ent->v.oldorigin = state->oldorigin; // beam endpoint
ent->v.frags = state->gaitsequence;
if( state->owner != -1 )
if( state->owner )
ent->v.owner = GetEntityByIndex( state->owner );
else ent->v.owner = NULL;
@ -341,11 +327,11 @@ void HUD_UpdateEntityVars( edict_t *ent, const entity_state_t *state, const enti
int i;
// copy blendings
for( i = 0; i < MAXSTUDIOBLENDS; i++ )
for( i = 0; i < 4; i++ )
ent->v.blending[i] = state->blending[i];
// copy controllers
for( i = 0; i < MAXSTUDIOCONTROLLERS; i++ )
for( i = 0; i < 4; i++ )
ent->v.controller[i] = state->controller[i];
// g-cont. moved here because we may needs apply null scale to skyportal
@ -372,20 +358,66 @@ playerstate update in entity_state_t. In order for these overrides to eventuall
structure, we need to copy them into the state structure at this point.
=========================
*/
void HUD_UpdateClientVars( entity_state_t *state, const clientdata_t *client )
void HUD_UpdateClientVars( edict_t *ent, const clientdata_t *state, const clientdata_t *prev )
{
// Copy origin
state->origin = client->origin;
float m_fLerp;
m_fLerp = GetLerpFrac();
// copy origin
ent->v.origin = LerpPoint( prev->origin, state->origin, m_fLerp );
ent->v.velocity = state->velocity;
ent->v.flags = state->flags;
ent->v.health = state->health;
ent->v.flags = state->flags;
ent->v.punchangle = LerpAngle( prev->punchangle, state->punchangle, m_fLerp );
ent->v.view_ofs = LerpPoint( prev->view_ofs, state->view_ofs, m_fLerp );
if( prev->fov != 90.0f && state->fov == 90.0f )
ent->v.fov = state->fov; // fov is reset, so don't lerping
else ent->v.fov = LerpPoint( prev->fov, state->fov, m_fLerp );
// Water state
ent->v.watertype = state->watertype;
ent->v.waterlevel = state->waterlevel;
// suit and weapon bits
ent->v.weapons = state->weapons;
ent->v.bInDuck = state->bInDuck;
ent->v.flTimeStepSound = state->flTimeStepSound;
ent->v.flDuckTime = state->flDuckTime;
ent->v.flSwimTime = state->flSwimTime;
ent->v.teleport_time = state->waterjumptime;
// Viewmodel code
edict_t *viewent = GetViewModel();
// if viewmodel has changed update sequence here
if( viewent->v.modelindex != state->viewmodel )
{
// ALERT( at_console, "Viewmodel changed\n" );
SendWeaponAnim( viewent->v.sequence, viewent->v.body, viewent->v.framerate );
}
// setup player viewmodel (only for local player!)
viewent->v.modelindex = state->viewmodel;
gHUD.m_flFOV = ent->v.fov; // keep client fov an actual
ent->v.maxspeed = state->maxspeed;
ent->v.weaponanim = state->weaponanim; // g-cont. hmm. we can grab weaponanim from here ?
ent->v.pushmsec = state->pushmsec;
// Spectator
state->iuser1 = client->iuser1;
state->iuser2 = client->iuser2;
ent->v.iuser1 = state->iuser1;
ent->v.iuser2 = state->iuser2;
// Duck prevention
state->iuser3 = client->iuser3;
ent->v.iuser3 = state->iuser3;
// Fire prevention
state->iuser4 = client->iuser4;
ent->v.iuser4 = state->iuser4;
}
int HUD_AddVisibleEntity( edict_t *pEnt, int ed_type )

View File

@ -124,7 +124,6 @@ inline void CL_PlaySound( int iSound, float flVolume, Vector &pos, float pitch =
#define ConsolePrint (*g_engfuncs.pfnConsolePrint)
#define GetViewAngles (*g_engfuncs.pfnGetViewAngles)
#define SetViewAngles (*g_engfuncs.pfnSetViewAngles)
#define GetEntityByIndex (*g_engfuncs.pfnGetEntityByIndex)
#define GetLocalPlayer (*g_engfuncs.pfnGetLocalPlayer)
#define GetClientMaxspeed (*g_engfuncs.pfnGetClientMaxspeed)
#define IsSpectateOnly (*g_engfuncs.pfnIsSpectateOnly)

View File

@ -518,9 +518,6 @@ void IN_CreateMove( usercmd_t *cmd, int msec, int active )
// set button and flag bits
cmd->buttons = CL_ButtonBits( 1 );
// random seed for predictable random values
cmd->random_seed = RANDOM_LONG( 0, 0x7fffffff ); // full range
last_msec = msec;
GetViewAngles( cl_viewangles );

View File

@ -23,7 +23,7 @@ void DBG_AssertFunction( BOOL fExpr, const char* szExpr, const char* szFile, int
if( szMessage != NULL )
sprintf( szOut, "ASSERT FAILED:\n %s \n(%s@%d)\n%s", szExpr, szFile, szLine, szMessage );
else sprintf( szOut, "ASSERT FAILED:\n %s \n(%s@%d)", szExpr, szFile, szLine );
HOST_ERROR( szOut );
ALERT( at_error, szOut );
}
#endif // DEBUG

View File

@ -27,6 +27,12 @@ void DBG_AssertFunction( BOOL fExpr, const char* szExpr, const char* szFile, int
#define ASSERTSZ( f, sz )
#endif
#ifdef _DEBUG
#define GetEntityByIndex(e) DBG_GetEntityByIndex( e, __FILE__, __LINE__ )
#else
#define GetEntityByIndex (*g_engfuncs.pfnGetEntityByIndex)
#endif
extern DLL_GLOBAL const Vector g_vecZero;
extern cl_globalvars_t *gpGlobals;
extern movevars_t *gpMovevars;
@ -35,7 +41,7 @@ extern int HUD_VidInit( void );
extern void HUD_Init( void );
extern int HUD_Redraw( float flTime, int state );
extern void HUD_UpdateEntityVars( edict_t *out, const entity_state_t *s, const entity_state_t *p );
extern void HUD_UpdateClientVars( entity_state_t *state, const clientdata_t *client );
extern void HUD_UpdateClientVars( edict_t *out, const clientdata_t *s, const clientdata_t *p );
extern void HUD_UpdateOnRemove( edict_t *pEdict );
extern void HUD_Reset( void );
extern void HUD_StartFrame( void );
@ -173,6 +179,14 @@ inline int ConsoleStringLen( const char *string )
return _width;
}
#ifdef _DEBUG
inline edict_t *DBG_GetEntityByIndex( int entnum, const char *file, const int line )
{
DBG_AssertFunction(( entnum >= 0 && entnum < gpGlobals->numEntities ), "Invalid entnum", file, line, NULL );
return (*g_engfuncs.pfnGetEntityByIndex)( entnum );
}
#endif
extern Vector BitsToDir( int bits );
// message reading

View File

@ -139,7 +139,7 @@ void V_Init( void )
//==========================
void V_StartPitchDrift( void )
{
if( pd.laststop == GetClientTime())
if( pd.laststop == GetClientTime( ))
return;
if( pd.nodrift || !pd.pitchvel )

View File

@ -46,4 +46,6 @@ typedef float vec_t;
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
typedef struct { byte r; byte g; byte b; } color24;
#endif//BASETYPES_H

View File

@ -228,7 +228,7 @@ typedef struct
void (*pfnInit)( void );
int (*pfnRedraw)( float flTime, int state );
void (*pfnUpdateEntityVars)( edict_t *out, const struct entity_state_s *in1, const struct entity_state_s *in2 );
void (*pfnUpdateClientVars)( struct entity_state_s *state, const struct clientdata_s *client );
void (*pfnUpdateClientVars)( edict_t *ent, const struct clientdata_s *in1, const struct clientdata_s *in2 );
void (*pfnOnFreeEntPrivateData)( edict_t *pEnt ); // this is called on entity removed
void (*pfnReset)( void );
void (*pfnStartFrame)( void );

View File

@ -41,58 +41,63 @@ typedef struct entity_state_s
string_t classname; // edict classname
int ed_flags; // engine clearing this at end of server frame
// physics information
// Fields which can be transitted and reconstructed over the network stream
vec3_t origin;
vec3_t angles; // entity angles, not viewangles
solid_t solid; // entity solid
movetype_t movetype; // entity movetype
float friction; // friction, for prediction.
int gravity; // gravity multiplier
int aiment; // attached entity
int owner; // projectiles owner
int groundent; // onground edict num, valid only if FL_ONGROUND is set, else -1
vec3_t mins; // entity bbox mins
vec3_t maxs; // entity bbox maxs
vec3_t velocity; // for predicting & tracing
vec3_t basevelocity; // for predicting & tracing
vec3_t oldorigin; // portal pvs, lerping state, etc
int contents; // for predicting & tracing on client
int modelindex;
int sequence;
float frame;
int colormap;
short skin;
short solid;
int effects;
float scale;
byte eflags;
// model state
int modelindex; // general modelindex
int colormap; // change base color for some textures or sprite frames
float scale; // model or sprite scale, affects to physics too
float frame; // % playback position in animation sequences (0..255)
int skin; // skin for studiomodels
int body; // sub-model selection for studiomodels
float localtime; // pev->ltime for monsters for right lerping on platforms, trains etc
float animtime; // auto-animating time
float framerate; // custom framerate, specified by QC
int sequence; // animation sequence (0 - 255)
int blending[16]; // studio animation blending
int controller[16]; // studio bone controllers
int flags; // v.flags
int effects; // effect flags like q1 and hl1
int renderfx; // render effects same as hl1
float renderamt; // alpha value or like somewhat
vec3_t rendercolor; // hl1 legacy stuff, working, but not needed
int rendermode; // hl1 legacy stuff, working, but not needed
// Render information
int rendermode;
int renderamt;
color24 rendercolor;
int renderfx;
int movetype;
float animtime;
float framerate;
int body;
byte controller[4];
byte blending[4];
vec3_t velocity;
// Send bbox down to client for use during prediction.
vec3_t mins;
vec3_t maxs;
int aiment;
int owner; // If owned by a player, the index of that player ( for projectiles )
float friction; // Friction, for prediction.
float gravity; // Gravity multiplier
// client specific
vec3_t punch_angles; // add to view direction to get render angles
vec3_t viewangles; // already calculated view angles on server-side
vec3_t viewoffset; // viewoffset over ground
int gaitsequence; // client\nps\bot gaitsequence
int viewmodel; // contains viewmodel index
int weaponmodel; // contains weaponmodel index
float idealpitch; // client idealpitch
float maxspeed; // min( pev->maxspeed, sv_maxspeed->value )
float health; // client health (other parms can be send by custom messages)
int weapons; // weapon flags
float fov; // horizontal field of view
int iStepLeft; // synched footsteps
float flFallVelocity; // how fast we are falling
int weaponanim; // to see weapon animation of other players
int team;
int playerclass;
int health;
int spectator;
int weaponmodel;
int gaitsequence;
vec3_t basevelocity; // If standing on conveyor, e.g.
int usehull; // Use the crouched hull, or the regular player hull.
int oldbuttons; // Latched buttons last time state updated.
int onground; // -1 = in air, else pmove entity number
int iStepLeft;
float flFallVelocity; // How fast we are falling
float fov;
int weaponanim;
// parametric movement overrides
vec3_t startpos;
vec3_t endpos;
float impacttime;
float starttime;
// for mods
int iuser1;
@ -108,6 +113,12 @@ typedef struct entity_state_s
vec3_t vuser3;
vec3_t vuser4;
// FIXME: old xash variables needs to be removed
int flags;
float maxspeed;
float idealpitch;
vec3_t oldorigin; // FIXME: needs to be removed
vec3_t viewangles; // already calculated view angles on server-side
} entity_state_t;
typedef struct clientdata_s

View File

@ -8,17 +8,22 @@
// usercmd_t communication (a part of network protocol)
typedef struct usercmd_s
{
short lerp_msec; // interpolation time on client
int msec; // duration in ms of command
vec3_t viewangles; // command view angles
// intended velocities
float forwardmove; // forward velocity
float sidemove; // sideways velocity
float upmove; // upward velocity
int lightlevel; // light level at spot where we are standing.
int buttons; // attack and move buttons
int impulse; // impulse command issued
int weaponselect; // current weapon id
int random_seed; // shared random seed
int target_edict; // mouse captured edict
byte lightlevel; // light level at spot where we are standing.
word buttons; // attack and move buttons
byte impulse; // impulse command issued
byte weaponselect; // current weapon id
// experimental player impact stuff.
int impact_index;
vec3_t impact_position;
} usercmd_t;
#endif//USERCMD_H

View File

@ -6,6 +6,8 @@
#include "common.h"
#include "client.h"
#include "byteorder.h"
#include "protocol.h"
#include "net_encode.h"
/*
====================
@ -14,7 +16,7 @@ CL_WriteDemoMessage
Dumps the current net message, prefixed by the length
====================
*/
void CL_WriteDemoMessage( sizebuf_t *msg, int head_size )
void CL_WriteDemoMessage( bitbuf_t *msg, int head_size )
{
int len, swlen;
@ -23,12 +25,12 @@ void CL_WriteDemoMessage( sizebuf_t *msg, int head_size )
return;
// the first eight bytes are just packet sequencing stuff
len = msg->cursize - head_size;
len = BF_GetNumBytesWritten( msg ) - head_size;
swlen = LittleLong( len );
if( !swlen ) return; // ignore null messages
FS_Write( cls.demofile, &swlen, 4 );
FS_Write( cls.demofile, msg->data + head_size, len );
FS_Write( cls.demofile, BF_GetData( msg ) + head_size, len );
}
void CL_WriteDemoHeader( const char *name )
@ -36,7 +38,7 @@ void CL_WriteDemoHeader( const char *name )
char buf_data[MAX_MSGLEN];
entity_state_t *state, nullstate;
movevars_t nullmovevars;
sizebuf_t buf;
bitbuf_t buf;
int i, len;
MsgDev( D_INFO, "recording to %s.\n", name );
@ -53,34 +55,34 @@ void CL_WriteDemoHeader( const char *name )
cls.demowaiting = true;
// write out messages to hold the startup information
MSG_Init( &buf, buf_data, sizeof( buf_data ));
BF_Init( &buf, "DemoWrite", buf_data, sizeof( buf_data ));
// send the serverdata
MSG_WriteByte( &buf, svc_serverdata );
MSG_WriteLong( &buf, PROTOCOL_VERSION );
MSG_WriteLong( &buf, cl.servercount );
MSG_WriteByte( &buf, cl.playernum );
MSG_WriteByte( &buf, clgame.globals->maxClients );
MSG_WriteWord( &buf, clgame.globals->maxEntities );
MSG_WriteString( &buf, cl.configstrings[CS_NAME] );
MSG_WriteString( &buf, clgame.maptitle );
BF_WriteByte( &buf, svc_serverdata );
BF_WriteLong( &buf, PROTOCOL_VERSION );
BF_WriteLong( &buf, cl.servercount );
BF_WriteByte( &buf, cl.playernum );
BF_WriteByte( &buf, clgame.globals->maxClients );
BF_WriteWord( &buf, clgame.globals->maxEntities );
BF_WriteString( &buf, cl.configstrings[CS_NAME] );
BF_WriteString( &buf, clgame.maptitle );
// configstrings
for( i = 0; i < MAX_CONFIGSTRINGS; i++ )
{
if( cl.configstrings[i][0] )
{
MSG_WriteByte( &buf, svc_configstring );
MSG_WriteShort( &buf, i );
MSG_WriteString( &buf, cl.configstrings[i] );
BF_WriteByte( &buf, svc_configstring );
BF_WriteShort( &buf, i );
BF_WriteString( &buf, cl.configstrings[i] );
if( buf.cursize > ( buf.maxsize / 2 ))
if( BF_GetNumBytesWritten( &buf ) > ( BF_GetMaxBytes( &buf ) / 2 ))
{
// write it out
len = LittleLong( buf.cursize );
len = LittleLong( BF_GetNumBytesWritten( &buf ));
FS_Write( cls.demofile, &len, 4 );
FS_Write( cls.demofile, buf.data, buf.cursize );
buf.cursize = 0;
FS_Write( cls.demofile, BF_GetData( &buf ), len );
BF_Clear( &buf );
}
}
@ -91,18 +93,18 @@ void CL_WriteDemoHeader( const char *name )
{
if( clgame.msg[i].name[0] )
{
MSG_WriteByte( &buf, svc_usermessage );
MSG_WriteString( &buf, clgame.msg[i].name );
MSG_WriteByte( &buf, clgame.msg[i].number );
MSG_WriteByte( &buf, (byte)clgame.msg[i].size );
BF_WriteByte( &buf, svc_usermessage );
BF_WriteString( &buf, clgame.msg[i].name );
BF_WriteByte( &buf, clgame.msg[i].number );
BF_WriteByte( &buf, (byte)clgame.msg[i].size );
if( buf.cursize > ( buf.maxsize / 2 ))
if( BF_GetNumBytesWritten( &buf ) > ( BF_GetMaxBytes( &buf ) / 2 ))
{
// write it out
len = LittleLong( buf.cursize );
len = LittleLong( BF_GetNumBytesWritten( &buf ));
FS_Write( cls.demofile, &len, 4 );
FS_Write( cls.demofile, buf.data, buf.cursize );
buf.cursize = 0;
FS_Write( cls.demofile, BF_GetData( &buf ), len );
BF_Clear( &buf );
}
}
@ -118,48 +120,48 @@ void CL_WriteDemoHeader( const char *name )
if( !state->modelindex && !state->effects )
continue;
MSG_WriteByte( &buf, svc_spawnbaseline );
BF_WriteByte( &buf, svc_spawnbaseline );
MSG_WriteDeltaEntity( &nullstate, state, &buf, true, true );
if( buf.cursize > ( buf.maxsize / 2 ))
if( BF_GetNumBytesWritten( &buf ) > ( BF_GetMaxBytes( &buf ) / 2 ))
{
// write it out
len = LittleLong( buf.cursize );
len = LittleLong( BF_GetNumBytesWritten( &buf ));
FS_Write( cls.demofile, &len, 4 );
FS_Write( cls.demofile, buf.data, buf.cursize );
buf.cursize = 0;
FS_Write( cls.demofile, BF_GetData( &buf ), len );
BF_Clear( &buf );
}
}
MSG_WriteByte( &buf, svc_stufftext );
MSG_WriteString( &buf, "precache\n" );
BF_WriteByte( &buf, svc_stufftext );
BF_WriteString( &buf, "precache\n" );
MSG_WriteByte( &buf, svc_setview );
MSG_WriteWord( &buf, cl.refdef.viewentity );
BF_WriteByte( &buf, svc_setview );
BF_WriteWord( &buf, cl.refdef.viewentity );
// write all clients userinfo
for( i = 0; i < clgame.globals->maxClients; i++ )
{
player_info_t *pi;
MSG_WriteByte( &buf, svc_updateuserinfo );
MSG_WriteByte( &buf, i );
BF_WriteByte( &buf, svc_updateuserinfo );
BF_WriteByte( &buf, i );
pi = &cl.players[i];
if( pi->name[0] )
{
MSG_WriteByte( &buf, true );
MSG_WriteString( &buf, pi->userinfo );
BF_WriteByte( &buf, true );
BF_WriteString( &buf, pi->userinfo );
}
else MSG_WriteByte( &buf, false );
else BF_WriteByte( &buf, false );
}
MSG_WriteDeltaMovevars( &buf, &nullmovevars, &clgame.movevars );
BF_WriteDeltaMovevars( &buf, &nullmovevars, &clgame.movevars );
// write it to the demo file
len = LittleLong( buf.cursize );
len = LittleLong( BF_GetNumBytesWritten( &buf ));
FS_Write( cls.demofile, &len, 4 );
FS_Write( cls.demofile, buf.data, buf.cursize );
FS_Write( cls.demofile, BF_GetData( &buf ), len );
// force client.dll update
Cmd_ExecuteString( "cmd fullupdate\n" );
@ -194,7 +196,6 @@ CLIENT SIDE DEMO PLAYBACK
=======================================================================
*/
/*
==================
CL_NextDemo
@ -253,9 +254,9 @@ reads demo data and write it to client
*/
void CL_ReadDemoMessage( void )
{
sizebuf_t buf;
char bufData[MAX_MSGLEN];
int r;
bitbuf_t buf;
char buf_data[MAX_MSGLEN];
int r, curSize;
if( !cls.demofile )
{
@ -270,32 +271,32 @@ void CL_ReadDemoMessage( void )
if( cl.time <= cl.frame.servertime )
return;
// init the message
MSG_Init( &buf, bufData, sizeof( bufData ));
// get the length
r = FS_Read( cls.demofile, &buf.cursize, 4 );
r = FS_Read( cls.demofile, &curSize, 4 );
if( r != 4 )
{
CL_DemoCompleted();
return;
}
buf.cursize = LittleLong( buf.cursize );
if( buf.cursize == -1 )
curSize = LittleLong( curSize );
if( curSize == -1 )
{
CL_DemoCompleted();
return;
}
if( buf.cursize > buf.maxsize )
if( curSize > sizeof( buf_data ))
{
Host_Error( "CL_ReadDemoMessage: demoMsglen > MAX_MSGLEN\n" );
return;
}
r = FS_Read( cls.demofile, buf.data, buf.cursize );
if( r != buf.cursize )
// init the message (set maxsize to cursize so overflow check will be working properly)
BF_Init( &buf, "DemoRead", buf_data, curSize );
r = FS_Read( cls.demofile, buf.pData, curSize );
if( r != curSize )
{
MsgDev( D_ERROR, "CL_ReadDemoMessage: demo file was truncated( %d )\n", cls.state );
CL_DemoCompleted();
@ -303,7 +304,8 @@ void CL_ReadDemoMessage( void )
}
cls.connect_time = cls.realtime;
buf.readcount = 0;
BF_Clear( &buf ); // reset curpos
CL_ParseServerMessage( &buf );
}
@ -355,9 +357,9 @@ bool CL_GetComment( const char *demoname, char *comment )
{
file_t *demfile;
char buf_data[MAX_MSGLEN];
int r, maxClients, curSize;
string maptitle;
int r, maxClients;
sizebuf_t buf;
bitbuf_t buf;
if( !comment ) return false;
@ -368,12 +370,9 @@ bool CL_GetComment( const char *demoname, char *comment )
return false;
}
// write out messages to hold the startup information
MSG_Init( &buf, buf_data, sizeof( buf_data ));
// read the first demo packet. extract info from it
// get the length
r = FS_Read( demfile, &buf.cursize, 4 );
r = FS_Read( demfile, &curSize, 4 );
if( r != 4 )
{
FS_Close( demfile );
@ -381,45 +380,47 @@ bool CL_GetComment( const char *demoname, char *comment )
return false;
}
buf.cursize = LittleLong( buf.cursize );
if( buf.cursize == -1 )
curSize = LittleLong( curSize );
if( curSize == -1 )
{
FS_Close( demfile );
com.strncpy( comment, "<corrupted>", MAX_STRING );
return false;
}
if( buf.cursize > buf.maxsize )
if( curSize > sizeof( buf_data ))
{
FS_Close( demfile );
com.strncpy( comment, "<not compatible>", MAX_STRING );
return false;
}
r = FS_Read( demfile, buf.data, buf.cursize );
// init the message (set maxsize to cursize so overflow check will be working properly)
BF_Init( &buf, "DemoRead", buf_data, curSize );
r = FS_Read( demfile, buf.pData, curSize );
if( r != buf.cursize )
if( r != curSize )
{
FS_Close( demfile );
com.strncpy( comment, "<truncated file>", MAX_STRING );
return false;
}
MSG_BeginReading( &buf );
// skip server data ident
BF_ReadByte( &buf );
// send the serverdata
MSG_ReadByte( &buf ); // skip server data
if( PROTOCOL_VERSION != MSG_ReadLong( &buf ))
if( PROTOCOL_VERSION != BF_ReadLong( &buf ))
{
FS_Close( demfile );
com.strncpy( comment, "<invalid protocol>", MAX_STRING );
return false;
}
MSG_ReadLong( &buf ); // server count
MSG_ReadByte( &buf );// playernum
maxClients = MSG_ReadByte( &buf );
if( MSG_ReadWord( &buf ) > GI->max_edicts )
BF_ReadLong( &buf ); // server count
BF_ReadByte( &buf );// playernum
maxClients = BF_ReadByte( &buf );
if( BF_ReadWord( &buf ) > GI->max_edicts )
{
FS_Close( demfile );
com.strncpy( comment, "<too many edicts>", MAX_STRING );
@ -427,8 +428,8 @@ bool CL_GetComment( const char *demoname, char *comment )
}
// split comment to sections
com.strncpy( comment, MSG_ReadString( &buf ), CS_SIZE ); // mapname
com.strncpy( maptitle, MSG_ReadString( &buf ), MAX_STRING ); // maptitle
com.strncpy( comment, BF_ReadString( &buf ), CS_SIZE ); // mapname
com.strncpy( maptitle, BF_ReadString( &buf ), MAX_STRING ); // maptitle
if( !com.strlen( maptitle )) com.strncpy( maptitle, "<no title>", MAX_STRING );
com.strncpy( comment + CS_SIZE, maptitle, CS_SIZE );
com.strncpy( comment + CS_SIZE * 2, va( "%i", maxClients ), CS_TIME );

View File

@ -5,6 +5,8 @@
#include "common.h"
#include "client.h"
#include "protocol.h"
#include "net_encode.h"
/*
=========================================================================
@ -40,7 +42,7 @@ Parses deltas from the given base and adds the resulting entity
to the current frame
==================
*/
void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t *old, bool unchanged )
void CL_DeltaEntity( bitbuf_t *msg, frame_t *frame, int newnum, entity_state_t *old, bool unchanged )
{
edict_t *ent;
entity_state_t *state;
@ -52,7 +54,7 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
if( newent ) old = &clgame.baselines[newnum];
if( unchanged ) *state = *old;
else MSG_ReadDeltaEntity( msg, old, state, newnum );
else MSG_ReadDeltaEntity( msg, old, state, newnum, cl.frame.servertime );
if( state->number == MAX_EDICTS )
{
@ -92,7 +94,7 @@ An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newframe )
void CL_ParsePacketEntities( bitbuf_t *msg, frame_t *oldframe, frame_t *newframe )
{
int newnum;
entity_state_t *oldstate;
@ -121,11 +123,11 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
while( 1 )
{
// read the entity index number
newnum = MSG_ReadShort( msg );
newnum = BF_ReadShort( msg );
if( !newnum ) break; // end of packet entities
if( msg->error )
Host_Error("CL_ParsePacketEntities: end of message[%d > %d]\n", msg->readcount, msg->cursize );
if( BF_CheckOverflow( msg ))
Host_Error( "CL_ParsePacketEntities: read overflow\n" );
while( newnum >= clgame.globals->numEntities )
clgame.globals->numEntities++;
@ -193,30 +195,47 @@ void CL_ParsePacketEntities( sizebuf_t *msg, frame_t *oldframe, frame_t *newfram
}
}
/*
===================
CL_ParseClientData
===================
*/
void CL_ParseClientData( frame_t *from, frame_t *to, bitbuf_t *msg )
{
clientdata_t *cd, *ocd;
clientdata_t dummy;
cd = &to->cd;
// clear to old value before delta parsing
if( !from )
{
ocd = &dummy;
Mem_Set( &dummy, 0, sizeof( dummy ));
}
else ocd = &from->cd;
MSG_ReadClientData( msg, ocd, cd, to->servertime );
}
/*
================
CL_ParseFrame
================
*/
void CL_ParseFrame( sizebuf_t *msg )
void CL_ParseFrame( bitbuf_t *msg )
{
int cmd, client_idx;
int cmd;
edict_t *clent;
Mem_Set( &cl.frame, 0, sizeof( cl.frame ));
cl.frame.serverframe = MSG_ReadLong( msg );
cl.frame.servertime = MSG_ReadLong( msg );
cl.frame.deltaframe = MSG_ReadLong( msg );
cl.serverframetime = MSG_ReadByte( msg );
cl.surpressCount = MSG_ReadByte( msg );
client_idx = MSG_ReadByte( msg );
cl.frame.serverframe = BF_ReadLong( msg );
cl.frame.servertime = BF_ReadLong( msg );
cl.frame.deltaframe = BF_ReadLong( msg );
cl.serverframetime = BF_ReadByte( msg );
cl.surpressCount = BF_ReadByte( msg );
// read clientindex
clent = EDICT_NUM( client_idx ); // get client
if(( client_idx - 1 ) != cl.playernum )
Host_Error( "CL_ParseFrame: invalid playernum (%d should be %d)\n", client_idx - 1, cl.playernum );
// If the frame is delta compressed from data that we
// no longer have available, we must suck up the rest of
// the frame, but not use it, then ask for a non-compressed
@ -254,9 +273,16 @@ void CL_ParseFrame( sizebuf_t *msg )
else if( cl.time < cl.frame.servertime - cl.serverframetime )
cl.time = cl.frame.servertime - cl.serverframetime;
// read clientdata
cmd = BF_ReadByte( msg );
if( cmd != svc_clientdata ) Host_Error( "CL_ParseFrame: not cliendata[%d]\n", cmd );
CL_ParseClientData( cl.oldframe, &cl.frame, msg );
clent = CL_GetLocalPlayer(); // get client
// read packet entities
cmd = MSG_ReadByte( msg );
if( cmd != svc_packetentities ) Host_Error("CL_ParseFrame: not packetentities[%d]\n", cmd );
cmd = BF_ReadByte( msg );
if( cmd != svc_packetentities ) Host_Error( "CL_ParseFrame: not packetentities[%d]\n", cmd );
CL_ParsePacketEntities( msg, cl.oldframe, &cl.frame );
// save the frame off in the backup array for later delta comparisons
@ -300,12 +326,31 @@ CL_AddPacketEntities
*/
void CL_AddPacketEntities( frame_t *frame )
{
edict_t *ent;
int e, ed_type;
edict_t *ent, *clent;
clientdata_t *cd, *ocd, dummy;
int e, ed_type;
// now recalc actual entcount
for( ; EDICT_NUM( clgame.globals->numEntities - 1 )->free; clgame.globals->numEntities-- );
clent = CL_GetLocalPlayer();
if( !clent ) return;
cd = &cl.frame.cd;
if( cl.oldframe )
{
ocd = &cl.oldframe->cd;
}
else
{
Mem_Set( &dummy, 0, sizeof( dummy ));
ocd = &dummy;
}
// update client vars
clgame.dllFuncs.pfnUpdateClientVars( clent, cd, ocd );
for( e = 1; e < clgame.globals->numEntities; e++ )
{
ent = CL_GetEdictByIndex( e );

View File

@ -8,6 +8,7 @@
#include "byteorder.h"
#include "matrix_lib.h"
#include "const.h"
#include "protocol.h"
#include "triangle_api.h"
#include "effects_api.h"
#include "pm_defs.h"

View File

@ -6,6 +6,7 @@
#include "common.h"
#include "client.h"
#include "byteorder.h"
#include "protocol.h"
cvar_t *rcon_client_password;
cvar_t *rcon_address;
@ -116,10 +117,11 @@ void CL_ForwardToServer_f( void )
// don't forward the first argument
if( Cmd_Argc() > 1 )
{
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, Cmd_Args());
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, Cmd_Args( ));
}
}
/*
===================
Cmd_ForwardToServer
@ -147,13 +149,13 @@ void Cmd_ForwardToServer( void )
return;
}
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, cmd );
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, cmd );
if( Cmd_Argc() > 1 )
{
MSG_Print( &cls.netchan.message, " " );
MSG_Print( &cls.netchan.message, Cmd_Args( ));
BF_WriteString( &cls.netchan.message, " " );
BF_WriteString( &cls.netchan.message, Cmd_Args( ));
}
}
@ -361,12 +363,34 @@ void CL_ClearState( void )
// wipe the entire cl structure
Mem_Set( &cl, 0, sizeof( cl ));
MSG_Clear( &cls.netchan.message );
BF_Clear( &cls.netchan.message );
Cvar_SetValue( "scr_download", 0.0f );
Cvar_SetValue( "scr_loading", 0.0f );
}
/*
=====================
CL_SendDisconnectMessage
Sends a disconnect message to the server
=====================
*/
void CL_SendDisconnectMessage( void )
{
bitbuf_t buf;
byte data[32];
BF_Init( &buf, "LastMessage", data, sizeof( data ));
BF_WriteByte( &buf, clc_stringcmd );
BF_WriteString( &buf, "disconnect" );
// make sure message will be delivered
Netchan_Transmit( &cls.netchan, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf ));
Netchan_Transmit( &cls.netchan, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf ));
Netchan_Transmit( &cls.netchan, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf ));
}
/*
=====================
CL_Disconnect
@ -378,8 +402,6 @@ This is also called on Host_Error, so it shouldn't cause any errors
*/
void CL_Disconnect( void )
{
byte final[32];
if( cls.state == ca_disconnected )
return;
@ -387,11 +409,7 @@ void CL_Disconnect( void )
CL_Stop_f();
// send a disconnect message to the server
final[0] = clc_stringcmd;
com.strcpy((char *)final+1, "disconnect" );
Netchan_Transmit( &cls.netchan, com.strlen( final ), final );
Netchan_Transmit( &cls.netchan, com.strlen( final ), final );
Netchan_Transmit( &cls.netchan, com.strlen( final ), final );
CL_SendDisconnectMessage();
CL_ClearState ();
@ -416,8 +434,6 @@ void CL_Disconnect_f( void )
void CL_Crashed_f( void )
{
byte final[32];
// already freed
if( host.state == HOST_CRASHED ) return;
if( host.type != HOST_NORMAL ) return;
@ -428,11 +444,7 @@ void CL_Crashed_f( void )
CL_Stop_f(); // stop any demos
// send a disconnect message to the server
final[0] = clc_stringcmd;
com.strcpy((char *)final+1, "disconnect" );
Netchan_Transmit( &cls.netchan, com.strlen( final ), final );
Netchan_Transmit( &cls.netchan, com.strlen( final ), final );
Netchan_Transmit( &cls.netchan, com.strlen( final ), final );
CL_SendDisconnectMessage();
// stop any downloads
if( cls.download ) FS_Close( cls.download );
@ -537,8 +549,8 @@ void CL_Reconnect_f( void )
{
cls.demonum = -1; // not in the demo loop now
cls.state = ca_connected;
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, "new" );
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, "new" );
return;
}
@ -564,11 +576,11 @@ CL_ParseStatusMessage
Handle a reply from a info
=================
*/
void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
void CL_ParseStatusMessage( netadr_t from, bitbuf_t *msg )
{
char *s;
s = MSG_ReadString( msg );
s = BF_ReadString( msg );
UI_AddServerToList( from, s );
}
@ -692,14 +704,14 @@ CL_ConnectionlessPacket
Responses to broadcasts, etc
=================
*/
void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
void CL_ConnectionlessPacket( netadr_t from, bitbuf_t *msg )
{
char *s, *c;
MSG_BeginReading( msg );
MSG_ReadLong( msg ); // skip the -1
BF_Clear( msg );
BF_ReadLong( msg ); // skip the -1
s = MSG_ReadStringLine( msg );
s = BF_ReadStringLine( msg );
Cmd_TokenizeString( s );
c = Cmd_Argv( 0 );
@ -714,11 +726,15 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
MsgDev( D_INFO, "dup connect received. ignored\n");
return;
}
Netchan_Setup( NS_CLIENT, &cls.netchan, from, Cvar_VariableValue( "net_qport" ));
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, "new" );
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, "new" );
cls.state = ca_connected;
UI_SetActiveMenu( false );
// FIXME!!! properly send tables to client
Delta_Init ();
}
else if( !com.strcmp( c, "info" ))
{
@ -728,7 +744,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !com.strcmp( c, "cmd" ))
{
// remote command from gui front end
if(!NET_IsLocalAddress( from ))
if( !NET_IsLocalAddress( from ))
{
Msg( "Command packet from remote host. Ignored.\n" );
return;
@ -736,14 +752,14 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
ShowWindow( host.hWnd, SW_RESTORE );
SetForegroundWindow ( host.hWnd );
s = MSG_ReadString( msg );
s = BF_ReadString( msg );
Cbuf_AddText( s );
Cbuf_AddText( "\n" );
}
else if( !com.strcmp( c, "print" ))
{
// print command from somewhere
s = MSG_ReadString( msg );
s = BF_ReadString( msg );
Msg( s );
}
else if( !com.strcmp( c, "ping" ))
@ -779,12 +795,17 @@ CL_ReadNetMessage
*/
void CL_ReadNetMessage( void )
{
while( NET_GetPacket( NS_CLIENT, &net_from, net_message.data, &net_message.cursize ))
int curSize;
while( NET_GetPacket( NS_CLIENT, &net_from, net_message_buffer, &curSize ))
{
if( host.type == HOST_DEDICATED || cls.demoplayback )
return;
if( net_message.cursize >= 4 && *(int *)net_message.data == -1 )
BF_Init( &net_message, "ServerData", net_message_buffer, curSize );
// check for connectionless packet (0xffffffff) first
if( BF_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 )
{
CL_ConnectionlessPacket( net_from, &net_message );
return;
@ -793,7 +814,7 @@ void CL_ReadNetMessage( void )
// can't be a valid sequenced packet
if( cls.state < ca_connected ) return;
if( net_message.cursize < 8 )
if( BF_GetMaxBytes( &net_message ) < 8 )
{
MsgDev( D_WARN, "%s: runt packet\n", NET_AdrToString( net_from ));
return;
@ -809,7 +830,7 @@ void CL_ReadNetMessage( void )
if( Netchan_Process( &cls.netchan, &net_message ))
{
// the header is different lengths for reliable and unreliable messages
int headerBytes = net_message.readcount;
int headerBytes = BF_GetNumBytesRead( &net_message );
CL_ParseServerMessage( &net_message );
@ -881,8 +902,8 @@ int precache_spawncount;
void CL_RequestNextDownload( void )
{
string fn;
uint map_checksum; // for detecting cheater maps
string fn;
uint map_checksum; // for detecting cheater maps
if( cls.state != ca_connected )
return;
@ -989,8 +1010,8 @@ void CL_RequestNextDownload( void )
CL_PrepVideo();
if( cls.demoplayback ) return; // not really connected
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, va( "begin %i\n", precache_spawncount ));
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, va( "begin %i\n", precache_spawncount ));
}
/*
@ -1031,6 +1052,7 @@ void CL_DumpCfgStrings_f( void )
Msg( "%s [%i]\n", cl.configstrings[i], i );
numStrings++;
}
Msg( "%i total strings used\n", numStrings );
}
@ -1060,8 +1082,6 @@ void CL_InitLocal( void )
{
cls.state = ca_disconnected;
MSG_Init( &net_message, net_message_buffer, sizeof( net_message_buffer ));
// register our variables
cl_predict = Cvar_Get( "cl_predict", "1", CVAR_ARCHIVE, "disables client movement prediction" );
cl_crosshair = Cvar_Get( "crosshair", "1", CVAR_ARCHIVE|CVAR_USERINFO, "show weapon chrosshair" );

View File

@ -8,6 +8,8 @@
#include "matrix_lib.h"
#include "const.h"
#include "pm_defs.h"
#include "protocol.h"
#include "net_encode.h"
#define CONNECTION_PROBLEM_TIME 15.0 * 1000 // 15 seconds
@ -74,6 +76,9 @@ usercmd_t CL_CreateCmd( void )
clgame.dllFuncs.pfnCreateMove( &cmd, host.inputmsec, ( cls.state == ca_active && !cl.refdef.paused ));
// random seed for predictable random values
cl.random_seed = Com_RandomLong( 0, 0x7fffffff ); // full range
// never let client.dll calc frametime for player
// because is potential backdoor for cheating
cmd.msec = ms;
@ -98,12 +103,12 @@ During normal gameplay, a client packet will contain something like:
*/
void CL_WritePacket( void )
{
sizebuf_t buf;
bool noDelta = false;
byte data[MAX_MSGLEN];
usercmd_t *cmd, *oldcmd;
usercmd_t nullcmd;
int key;
bitbuf_t buf;
bool noDelta = false;
byte data[MAX_MSGLEN];
usercmd_t *cmd, *oldcmd;
usercmd_t nullcmd;
int key, size;
// don't send anything if playing back a demo
if( cls.demoplayback || cls.state == ca_cinematic )
@ -115,7 +120,7 @@ void CL_WritePacket( void )
if( cls.state == ca_connected )
{
// just update reliable
if( cls.netchan.message.cursize || cls.realtime - cls.netchan.last_sent > 1000 )
if( BF_GetNumBytesWritten( &cls.netchan.message ) || cls.realtime - cls.netchan.last_sent > 1000 )
Netchan_Transmit( &cls.netchan, 0, NULL );
return;
}
@ -136,23 +141,27 @@ void CL_WritePacket( void )
if( userinfo->modified )
{
userinfo->modified = false;
MSG_WriteByte( &cls.netchan.message, clc_userinfo );
MSG_WriteString( &cls.netchan.message, Cvar_Userinfo( ));
BF_WriteByte( &cls.netchan.message, clc_userinfo );
BF_WriteString( &cls.netchan.message, Cvar_Userinfo( ));
}
MSG_Init( &buf, data, sizeof( data ));
BF_Init( &buf, "ClientData", data, sizeof( data ));
// write new random_seed
BF_WriteByte( &buf, clc_random_seed );
BF_WriteUBitLong( &buf, cl.random_seed, 32 ); // full range
// begin a client move command
MSG_WriteByte( &buf, clc_move );
BF_WriteByte( &buf, clc_move );
// save the position for a checksum byte
key = buf.cursize;
MSG_WriteByte( &buf, 0 );
key = BF_GetNumBytesWritten( &buf );
BF_WriteByte( &buf, 0 );
// let the server know what the last frame we
// got was, so the next message can be delta compressed
if( noDelta ) MSG_WriteLong( &buf, -1 ); // no compression
else MSG_WriteLong( &buf, cl.frame.serverframe );
if( noDelta ) BF_WriteLong( &buf, -1 ); // no compression
else BF_WriteLong( &buf, cl.frame.serverframe );
// send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered
@ -169,10 +178,11 @@ void CL_WritePacket( void )
MSG_WriteDeltaUsercmd( &buf, oldcmd, cmd );
// calculate a checksum over the move commands
buf.data[key] = CRC_Sequence( buf.data + key + 1, buf.cursize - key - 1, cls.netchan.outgoing_sequence );
size = BF_GetNumBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC_Sequence( buf.pData + key + 1, size, cls.netchan.outgoing_sequence );
// deliver the message
Netchan_Transmit( &cls.netchan, buf.cursize, buf.data );
Netchan_Transmit( &cls.netchan, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf ));
}
/*
@ -503,7 +513,7 @@ void CL_PostRunCmd( edict_t *clent, usercmd_t *ucmd )
{
if( !clent ) return;
clgame.pmove->runfuncs = false; // all next calls ignore footstep sounds
clgame.dllFuncs.pfnCmdEnd( clent, ucmd, ucmd->random_seed );
clgame.dllFuncs.pfnCmdEnd( clent, ucmd, cl.random_seed );
}
/*
@ -560,6 +570,7 @@ void CL_PredictMovement( void )
int frame;
int ack, current;
edict_t *player, *viewent;
clientdata_t *cd;
usercmd_t *cmd;
if( cls.state != ca_active ) return;
@ -567,6 +578,7 @@ void CL_PredictMovement( void )
player = CL_GetLocalPlayer ();
viewent = CL_GetEdictByIndex( cl.refdef.viewentity );
cd = &cl.frame.cd;
if( cls.demoplayback && CL_IsValidEdict( viewent ))
{
@ -604,10 +616,10 @@ void CL_PredictMovement( void )
// setup initial pmove state
VectorCopy( player->v.movedir, clgame.pmove->movedir );
VectorCopy( player->pvClientData->current.origin, clgame.pmove->origin );
VectorCopy( player->pvClientData->current.velocity, clgame.pmove->velocity );
VectorCopy( cd->origin, clgame.pmove->origin );
VectorCopy( cd->velocity, clgame.pmove->velocity );
VectorCopy( player->pvClientData->current.basevelocity, clgame.pmove->basevelocity );
VectorCopy( player->pvClientData->current.viewoffset, player->v.view_ofs );
VectorCopy( cd->view_ofs, player->v.view_ofs );
clgame.pmove->flWaterJumpTime = player->v.teleport_time;
clgame.pmove->onground = player->v.groundentity;
clgame.pmove->usehull = (player->pvClientData->current.flags & FL_DUCKING) ? 1 : 0; // reset hull

View File

@ -5,7 +5,9 @@
#include "common.h"
#include "client.h"
#include "protocol.h"
#include "net_sound.h"
#include "net_encode.h"
#define MSG_COUNT 32 // last 32 messages parsed
#define MSG_MASK (MSG_COUNT - 1)
@ -111,7 +113,7 @@ CL_WriteErrorMessage
write net_message into buffer.dat for debugging
=====================
*/
void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
void CL_WriteErrorMessage( int current_count, bitbuf_t *msg )
{
file_t *fp;
const char *buffer_file = "buffer.dat";
@ -121,7 +123,7 @@ void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
FS_Write( fp, &starting_count, sizeof( int ));
FS_Write( fp, &current_count, sizeof( int ));
FS_Write( fp, msg->data, msg->cursize );
FS_Write( fp, BF_GetData( msg ), BF_GetMaxBytes( msg ));
FS_Close( fp );
MsgDev( D_INFO, "Wrote erroneous message to %s\n", buffer_file );
@ -138,7 +140,7 @@ void CL_WriteMessageHistory( void )
{
int i, thecmd;
oldcmd_t *old, *failcommand;
sizebuf_t *msg = &net_message;
bitbuf_t *msg = &net_message;
if( !cls.initialized || cls.state == ca_disconnected )
return;
@ -164,11 +166,11 @@ void CL_WriteMessageHistory( void )
failcommand = &cls_message_debug.oldcmd[thecmd];
MsgDev( D_INFO, "BAD: %3i:%s\n", msg->readcount - 1, CL_MsgInfo( failcommand->command ));
MsgDev( D_INFO, "BAD: %3i:%s\n", BF_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
if( host.developer >= 3 )
{
CL_WriteErrorMessage( msg->readcount - 1, msg );
CL_WriteErrorMessage( BF_GetNumBytesRead( msg ) - 1, msg );
}
cls_message_debug.parsing = false;
}
@ -210,14 +212,14 @@ bool CL_CheckOrDownloadFile( const char *filename )
cls.download = f;
// give the server an offset to start the download
MsgDev( D_INFO, "Resume download %s at %i\n", cls.downloadname, len );
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, va("download %s %i", cls.downloadname, len ));
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, va("download %s %i", cls.downloadname, len ));
}
else
{
MsgDev( D_INFO, "Start download %s\n", cls.downloadname );
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, va("download %s", cls.downloadname ));
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, va("download %s", cls.downloadname ));
}
cls.downloadnumber++;
@ -231,15 +233,16 @@ CL_ParseDownload
A download message has been received from the server
=====================
*/
void CL_ParseDownload( sizebuf_t *msg )
void CL_ParseDownload( bitbuf_t *msg )
{
int size, percent;
string name;
int r;
int size, percent;
char buffer[MAX_MSGLEN];
string name;
int r;
// read the data
size = MSG_ReadShort( msg );
percent = MSG_ReadByte( msg );
size = BF_ReadShort( msg );
percent = BF_ReadByte( msg );
if( size == -1 )
{
@ -262,22 +265,24 @@ void CL_ParseDownload( sizebuf_t *msg )
if( !cls.download )
{
msg->readcount += size;
Msg( "Failed to open %s\n", cls.downloadtempname );
msg->iCurBit += size << 3; // FIXME!!!
MsgDev( D_ERROR, "failed to open %s\n", cls.downloadtempname );
CL_RequestNextDownload();
return;
}
}
FS_Write( cls.download, msg->data + msg->readcount, size );
msg->readcount += size;
ASSERT( size <= sizeof( buffer ));
BF_ReadBytes( msg, buffer, size );
FS_Write( cls.download, buffer, size );
if( percent != 100 )
{
// request next block
Cvar_SetValue("scr_download", percent );
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, "nextdl" );
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, "nextdl" );
}
else
{
@ -327,7 +332,7 @@ CL_ParseSoundPacket
==================
*/
void CL_ParseSoundPacket( sizebuf_t *msg, bool is_ambient )
void CL_ParseSoundPacket( bitbuf_t *msg, bool is_ambient )
{
vec3_t pos_;
float *pos = NULL;
@ -336,30 +341,30 @@ void CL_ParseSoundPacket( sizebuf_t *msg, bool is_ambient )
int flags, pitch, entnum;
sound_t handle;
flags = MSG_ReadWord( msg );
sound = MSG_ReadWord( msg );
chan = MSG_ReadByte( msg );
flags = BF_ReadWord( msg );
sound = BF_ReadWord( msg );
chan = BF_ReadByte( msg );
if( flags & SND_VOLUME )
volume = MSG_ReadByte( msg ) / 255.0f;
volume = BF_ReadByte( msg ) / 255.0f;
else volume = VOL_NORM;
if( flags & SND_ATTENUATION )
attn = MSG_ReadByte( msg ) / 64.0f;
attn = BF_ReadByte( msg ) / 64.0f;
else attn = ATTN_NONE;
if( flags & SND_PITCH )
pitch = MSG_ReadByte( msg );
pitch = BF_ReadByte( msg );
else pitch = PITCH_NORM;
// entity reletive
entnum = MSG_ReadWord( msg );
entnum = BF_ReadWord( msg );
// positioned in space
if( flags & SND_FIXED_ORIGIN )
{
pos = pos_;
MSG_ReadPos( msg, pos );
BF_ReadBitVec3Coord( msg, pos );
}
if( flags & SND_SENTENCE )
@ -387,9 +392,9 @@ CL_ParseMovevars
==================
*/
void CL_ParseMovevars( sizebuf_t *msg )
void CL_ParseMovevars( bitbuf_t *msg )
{
MSG_ReadDeltaMovevars( msg, &clgame.oldmovevars, &clgame.movevars );
BF_ReadDeltaMovevars( msg, &clgame.oldmovevars, &clgame.movevars );
Mem_Copy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
}
@ -399,18 +404,18 @@ CL_ParseParticles
==================
*/
void CL_ParseParticles( sizebuf_t *msg )
void CL_ParseParticles( bitbuf_t *msg )
{
vec3_t org, dir;
int i, count, color;
MSG_ReadPos( msg, org );
BF_ReadBitVec3Coord( msg, org );
for( i = 0; i < 3; i++ )
dir[i] = MSG_ReadChar( msg ) * (1.0f / 16);
dir[i] = BF_ReadChar( msg ) * (1.0f / 16);
count = MSG_ReadByte( msg );
color = MSG_ReadByte( msg );
count = BF_ReadByte( msg );
color = BF_ReadByte( msg );
if( count == 255 ) count = 1024;
clgame.dllFuncs.pfnParticleEffect( org, dir, color, count );
@ -422,56 +427,56 @@ CL_ParseStaticDecal
==================
*/
void CL_ParseStaticDecal( sizebuf_t *msg )
void CL_ParseStaticDecal( bitbuf_t *msg )
{
vec3_t origin;
int decalIndex, entityIndex, modelIndex;
int flags;
MSG_ReadPos( msg, origin );
decalIndex = MSG_ReadWord( msg );
entityIndex = MSG_ReadShort( msg );
BF_ReadBitVec3Coord( msg, origin );
decalIndex = BF_ReadWord( msg );
entityIndex = BF_ReadShort( msg );
if( entityIndex > 0 )
modelIndex = MSG_ReadWord( msg );
modelIndex = BF_ReadWord( msg );
else modelIndex = 0;
flags = MSG_ReadByte( msg );
flags = BF_ReadByte( msg );
CL_DecalShoot( cl.decal_shaders[decalIndex], entityIndex, modelIndex, origin, flags );
}
void CL_ParseSoundFade( sizebuf_t *msg )
void CL_ParseSoundFade( bitbuf_t *msg )
{
float fadePercent, fadeOutSeconds;
float holdTime, fadeInSeconds;
fadePercent = MSG_ReadFloat( msg );
fadeOutSeconds = MSG_ReadFloat( msg );
holdTime = MSG_ReadFloat( msg );
fadeInSeconds = MSG_ReadFloat( msg );
fadePercent = BF_ReadFloat( msg );
fadeOutSeconds = BF_ReadFloat( msg );
holdTime = BF_ReadFloat( msg );
fadeInSeconds = BF_ReadFloat( msg );
S_FadeClientVolume( fadePercent, fadeOutSeconds, holdTime, fadeInSeconds );
}
void CL_ParseReliableEvent( sizebuf_t *msg, int flags )
void CL_ParseReliableEvent( bitbuf_t *msg, int flags )
{
int event_index;
event_args_t nullargs, args;
float delay;
Mem_Set( &nullargs, 0, sizeof( nullargs ));
event_index = MSG_ReadWord( msg ); // read event index
delay = MSG_ReadWord( msg ) / 100.0f; // read event delay
event_index = BF_ReadWord( msg ); // read event index
delay = BF_ReadWord( msg ) / 100.0f; // read event delay
MSG_ReadDeltaEvent( msg, &nullargs, &args ); // FIXME: zero-compressing
CL_QueueEvent( flags, event_index, delay, &args );
}
void CL_ParseEvent( sizebuf_t *msg )
void CL_ParseEvent( bitbuf_t *msg )
{
int i, num_events;
num_events = MSG_ReadByte( msg );
num_events = BF_ReadByte( msg );
// parse events queue
for( i = 0 ; i < num_events; i++ )
@ -490,7 +495,7 @@ void CL_ParseEvent( sizebuf_t *msg )
CL_ParseServerData
==================
*/
void CL_ParseServerData( sizebuf_t *msg )
void CL_ParseServerData( bitbuf_t *msg )
{
string str;
int i;
@ -503,18 +508,18 @@ void CL_ParseServerData( sizebuf_t *msg )
cls.state = ca_connected;
// parse protocol version number
i = MSG_ReadLong( msg );
i = BF_ReadLong( msg );
cls.serverProtocol = i;
if( i != PROTOCOL_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
cl.servercount = MSG_ReadLong( msg );
cl.playernum = MSG_ReadByte( msg );
clgame.globals->maxClients = MSG_ReadByte( msg );
clgame.globals->maxEntities = MSG_ReadWord( msg );
com.strncpy( str, MSG_ReadString( msg ), MAX_STRING );
com.strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING );
cl.servercount = BF_ReadLong( msg );
cl.playernum = BF_ReadByte( msg );
clgame.globals->maxClients = BF_ReadByte( msg );
clgame.globals->maxEntities = BF_ReadWord( msg );
com.strncpy( str, BF_ReadString( msg ), MAX_STRING );
com.strncpy( clgame.maptitle, BF_ReadString( msg ), MAX_STRING );
gameui.globals->maxClients = clgame.globals->maxClients;
com.strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle ));
@ -552,15 +557,15 @@ void CL_ParseServerData( sizebuf_t *msg )
CL_ParseBaseline
==================
*/
void CL_ParseBaseline( sizebuf_t *msg )
void CL_ParseBaseline( bitbuf_t *msg )
{
int newnum;
int newnum, timebase;
entity_state_t nullstate;
entity_state_t *baseline;
edict_t *ent;
Mem_Set( &nullstate, 0, sizeof( nullstate ));
newnum = MSG_ReadWord( msg );
newnum = BF_ReadWord( msg );
if( newnum < 0 ) Host_Error( "CL_SpawnEdict: invalid number %i\n", newnum );
if( newnum > clgame.globals->maxEntities ) Host_Error( "CL_AllocEdict: no free edicts\n" );
@ -572,8 +577,12 @@ void CL_ParseBaseline( sizebuf_t *msg )
ent = EDICT_NUM( newnum );
if( ent->free ) CL_InitEdict( ent ); // initialize edict
if( cls.state == ca_active )
timebase = cl.frame.servertime;
else timebase = 1000; // sv.state == ss_loading
baseline = &clgame.baselines[newnum];
MSG_ReadDeltaEntity( msg, &nullstate, baseline, newnum );
MSG_ReadDeltaEntity( msg, &nullstate, baseline, newnum, cl.time );
CL_LinkEdict( ent, false ); // first entering, link always
}
@ -582,14 +591,14 @@ void CL_ParseBaseline( sizebuf_t *msg )
CL_ParseConfigString
================
*/
void CL_ParseConfigString( sizebuf_t *msg )
void CL_ParseConfigString( bitbuf_t *msg )
{
int i;
i = MSG_ReadShort( msg );
i = BF_ReadShort( msg );
if( i < 0 || i >= MAX_CONFIGSTRINGS )
Host_Error( "configstring > MAX_CONFIGSTRINGS\n" );
com.strcpy( cl.configstrings[i], MSG_ReadString( msg ));
com.strcpy( cl.configstrings[i], BF_ReadString( msg ));
// do something apropriate
if( i == CS_SKYNAME && cl.video_prepped )
@ -660,13 +669,10 @@ CL_ParseSetAngle
set the view angle to this absolute value
================
*/
void CL_ParseSetAngle( sizebuf_t *msg )
void CL_ParseSetAngle( bitbuf_t *msg )
{
cl.refdef.cl_viewangles[0] = MSG_ReadAngle32( msg );
cl.refdef.cl_viewangles[1] = MSG_ReadAngle32( msg );
if( cl.refdef.cl_viewangles[0] > 180 ) cl.refdef.cl_viewangles[0] -= 360;
if( cl.refdef.cl_viewangles[1] > 180 ) cl.refdef.cl_viewangles[1] -= 360;
cl.refdef.cl_viewangles[0] = BF_ReadBitAngle( msg, 16 );
cl.refdef.cl_viewangles[1] = BF_ReadBitAngle( msg, 16 );
}
/*
@ -676,15 +682,11 @@ CL_ParseAddAngle
add the view angle yaw
================
*/
void CL_ParseAddAngle( sizebuf_t *msg )
void CL_ParseAddAngle( bitbuf_t *msg )
{
float add_angle;
add_angle = MSG_ReadAngle32( msg );
if( add_angle > 180.0f )
add_angle -= 360.0f;
add_angle = BF_ReadBitAngle( msg, 16 );
cl.refdef.cl_viewangles[1] += add_angle;
}
/*
@ -694,10 +696,10 @@ CL_ParseCrosshairAngle
offset crosshair angles
================
*/
void CL_ParseCrosshairAngle( sizebuf_t *msg )
void CL_ParseCrosshairAngle( bitbuf_t *msg )
{
cl.refdef.crosshairangle[0] = MSG_ReadAngle8( msg );
cl.refdef.crosshairangle[1] = MSG_ReadAngle8( msg );
cl.refdef.crosshairangle[0] = BF_ReadBitAngle( msg, 8 );
cl.refdef.crosshairangle[1] = BF_ReadBitAngle( msg, 8 );
cl.refdef.crosshairangle[2] = 0.0f; // not used for screen space
}
@ -708,14 +710,14 @@ CL_RegisterUserMessage
register new user message or update existing
================
*/
void CL_RegisterUserMessage( sizebuf_t *msg )
void CL_RegisterUserMessage( bitbuf_t *msg )
{
char *pszName;
int svc_num, size;
pszName = MSG_ReadString( msg );
svc_num = MSG_ReadByte( msg );
size = MSG_ReadByte( msg );
pszName = BF_ReadString( msg );
svc_num = BF_ReadByte( msg );
size = BF_ReadByte( msg );
// important stuff
if( size == 0xFF ) size = -1;
@ -730,23 +732,23 @@ CL_UpdateUserinfo
collect userinfo from all players
================
*/
void CL_UpdateUserinfo( sizebuf_t *msg )
void CL_UpdateUserinfo( bitbuf_t *msg )
{
int slot;
bool active;
player_info_t *player;
slot = MSG_ReadByte( msg );
slot = BF_ReadByte( msg );
if( slot >= MAX_CLIENTS )
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo > MAX_CLIENTS\n" );
player = &cl.players[slot];
active = MSG_ReadByte( msg ) ? true : false;
active = BF_ReadByte( msg ) ? true : false;
if( active )
{
com.strncpy( player->userinfo, MSG_ReadString( msg ), sizeof( player->userinfo ));
com.strncpy( player->userinfo, BF_ReadString( msg ), sizeof( player->userinfo ));
com.strncpy( player->name, Info_ValueForKey( player->userinfo, "name" ), sizeof( player->name ));
com.strncpy( player->model, Info_ValueForKey( player->userinfo, "model" ), sizeof( player->model ));
}
@ -760,13 +762,13 @@ CL_ServerInfo
change serverinfo
==============
*/
void CL_ServerInfo( sizebuf_t *msg )
void CL_ServerInfo( bitbuf_t *msg )
{
char key[MAX_MSGLEN];
char value[MAX_MSGLEN];
com.strncpy( key, MSG_ReadString( msg ), sizeof( key ));
com.strncpy( value, MSG_ReadString( msg ), sizeof( value ));
com.strncpy( key, BF_ReadString( msg ), sizeof( key ));
com.strncpy( value, BF_ReadString( msg ), sizeof( value ));
Info_SetValueForKey( cl.serverinfo, key, value );
}
@ -777,9 +779,9 @@ CL_ParseUserMessage
handles all user messages
==============
*/
void CL_ParseUserMessage( sizebuf_t *net_buffer, int svc_num )
void CL_ParseUserMessage( bitbuf_t *msg, int svc_num )
{
int iSize;
int i, iSize;
byte *pbuf;
// NOTE: any user message parse on engine, not in client.dll
@ -792,17 +794,31 @@ void CL_ParseUserMessage( sizebuf_t *net_buffer, int svc_num )
// unregister message can't be parsed
if( clgame.msg[svc_num].number != svc_num )
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num );
{
for( i = 0; i < MAX_USER_MESSAGES; i++ )
{
// across-transition problems... this is temporary solution
if( clgame.msg[i].number == svc_num )
{
MsgDev( D_WARN, "CL_RemapUserMsg: from %i to %i\n", svc_num, i );
svc_num = i;
break;
}
}
if( i == MAX_USER_MESSAGES )
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num );
}
iSize = clgame.msg[svc_num].size;
pbuf = NULL;
// message with variable sizes receive an actual size as first byte
if( iSize == -1 ) iSize = MSG_ReadByte( net_buffer );
if( iSize == -1 ) iSize = BF_ReadByte( msg );
if( iSize > 0 ) pbuf = Mem_Alloc( clgame.private, iSize );
// parse user message into buffer
MSG_ReadData( net_buffer, pbuf, iSize );
BF_ReadBytes( msg, pbuf, iSize );
if( clgame.msg[svc_num].func ) clgame.msg[svc_num].func( clgame.msg[svc_num].name, iSize, pbuf );
else MsgDev( D_WARN, "CL_ParseUserMessage: %s not hooked\n", clgame.msg[svc_num].name );
@ -821,29 +837,32 @@ ACTION MESSAGES
CL_ParseServerMessage
=====================
*/
void CL_ParseServerMessage( sizebuf_t *msg )
void CL_ParseServerMessage( bitbuf_t *msg )
{
char *s;
int i, cmd;
int bufStart;
cls_message_debug.parsing = true; // begin parsing
starting_count = msg->readcount; // updates each frame
cls_message_debug.parsing = true; // begin parsing
starting_count = BF_GetNumBytesRead( msg ); // updates each frame
// parse the message
while( 1 )
{
if( msg->error )
if( BF_CheckOverflow( msg ))
{
Host_Error( "CL_ParseServerMessage: bad server message\n" );
return;
}
// mark start position
bufStart = msg->readcount;
bufStart = BF_GetNumBytesRead( msg );
cmd = MSG_ReadByte( msg );
if( cmd == -1 ) break;
// end of message
if( BF_GetNumBitsLeft( msg ) < 8 )
break;
cmd = BF_ReadByte( msg );
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
@ -875,7 +894,7 @@ void CL_ParseServerMessage( sizebuf_t *msg )
cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately
break;
case svc_stufftext:
s = MSG_ReadString( msg );
s = BF_ReadString( msg );
Cbuf_AddText( s );
break;
case svc_serverdata:
@ -904,25 +923,25 @@ void CL_ParseServerMessage( sizebuf_t *msg )
CL_ParseAddAngle( msg );
break;
case svc_setview:
cl.refdef.viewentity = MSG_ReadWord( msg );
cl.refdef.viewentity = BF_ReadWord( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_physinfo:
com.strncpy( cl.physinfo, MSG_ReadString( msg ), sizeof( cl.physinfo ));
com.strncpy( cl.physinfo, BF_ReadString( msg ), sizeof( cl.physinfo ));
break;
case svc_print:
i = MSG_ReadByte( msg );
i = BF_ReadByte( msg );
if( i == PRINT_CHAT ) // chat
S_StartLocalSound( "misc/talk.wav" ); // FIXME: INTRESOURCE
MsgDev( D_INFO, "^6%s\n", MSG_ReadString( msg ));
MsgDev( D_INFO, "^6%s\n", BF_ReadString( msg ));
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.35f );
CL_CenterPrint( BF_ReadString( msg ), 0.35f );
break;
case svc_setpause:
cl.refdef.paused = (MSG_ReadByte( msg ) != 0 );
cl.refdef.paused = (BF_ReadByte( msg ) != 0 );
break;
case svc_movevars:
CL_ParseMovevars( msg );

View File

@ -31,12 +31,13 @@ typedef struct player_info_s
//=============================================================================
typedef struct frame_s
{
bool valid; // cleared if delta parsing was invalid
int servertime;
int serverframe;
int deltaframe;
int num_entities;
int parse_entities; // non-masked index into cl_parse_entities array
bool valid; // cleared if delta parsing was invalid
int servertime;
int serverframe;
int deltaframe;
int num_entities;
int parse_entities; // non-masked index into cl_parse_entities array
clientdata_t cd; // current client data
} frame_t;
#define CMD_BACKUP 64 // allow a lot of command backups for very fast systems
@ -82,6 +83,7 @@ typedef struct
event_state_t events;
// predicting stuff
uint random_seed; // for predictable random values
vec3_t predicted_origins[CMD_BACKUP]; // for debug comparing against server
vec3_t predicted_origin; // generated by CL_PredictMovement
vec3_t predicted_viewofs;
@ -363,7 +365,7 @@ extern cvar_t *userinfo;
//=============================================================================
bool CL_CheckOrDownloadFile( const char *filename );
void CL_ParseConfigString( sizebuf_t *msg );
void CL_ParseConfigString( bitbuf_t *msg );
void CL_SetLightstyle( int i );
void CL_RunLightStyles( void );
@ -411,7 +413,7 @@ void CL_SendCmd( void );
// cl_demo.c
//
void CL_DrawDemoRecording( void );
void CL_WriteDemoMessage( sizebuf_t *msg, int head_size );
void CL_WriteDemoMessage( bitbuf_t *msg, int head_size );
void CL_ReadDemoMessage( void );
void CL_StopPlayback( void );
void CL_StopRecord( void );
@ -427,7 +429,7 @@ void CL_Stop_f( void );
//
void CL_UnloadProgs( void );
bool CL_LoadProgs( const char *name );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
void CL_ParseUserMessage( bitbuf_t *msg, int svc_num );
void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize );
void CL_DrawHUD( int state );
void CL_InitEdicts( void );
@ -459,7 +461,7 @@ _inline edict_t *CL_EDICT_NUM( int n, const char *file, const int line )
//
// cl_parse.c
//
void CL_ParseServerMessage( sizebuf_t *msg );
void CL_ParseServerMessage( bitbuf_t *msg );
void CL_RunBackgroundTrack( void );
void CL_Download_f( void );
@ -502,7 +504,7 @@ void CL_UpdateBaseVelocity( edict_t *ent );
//
// cl_frame.c
//
void CL_ParseFrame( sizebuf_t *msg );
void CL_ParseFrame( bitbuf_t *msg );
void CL_GetEntitySpatialization( int ent, vec3_t origin, vec3_t velocity );
//

View File

@ -6,13 +6,14 @@
#include "common.h"
#include "client.h"
#include "keydefs.h"
#include "protocol.h" // get the protocol version
#include "byteorder.h"
cvar_t *con_notifytime;
cvar_t *scr_conspeed;
cvar_t *con_fontsize;
#define CON_TIMES 5 // need for 4 lines
#define CON_TIMES 5 // need for 4 lines
#define COLOR_DEFAULT '7'
#define CON_HISTORY 32
@ -379,15 +380,23 @@ static int Con_DrawCharacter( int x, int y, int number, rgba_t color )
void Con_DrawStringLen( const char *pText, int *length, int *height )
{
int curLength = 0;
if( height ) *height = con.charHeight;
if( !length ) return;
*length = 0;
while( *pText && *pText != '\n' )
while( *pText )
{
byte c = *pText;
if( *pText == '\n' )
{
pText++;
curLength = 0;
}
// skip color strings they are not drawing
if( IsColorString( pText ))
{
@ -395,8 +404,11 @@ void Con_DrawStringLen( const char *pText, int *length, int *height )
continue;
}
*length += con.charWidths[c];
curLength += con.charWidths[c];
pText++;
if( curLength > *length )
*length = curLength;
}
}
@ -421,6 +433,13 @@ int Con_DrawGenericString( int x, int y, const char *string, rgba_t setColor, bo
while ( *s )
{
if( *s == '\n' )
{
s++;
drawLen = 0; // begin new row
y += con.charHeight;
}
if( IsColorString( s ))
{
if( !forceColor )

View File

@ -33,7 +33,7 @@ void BF_InitMasks( void )
ExtraMasks[maskBit] = BIT( maskBit ) - 1;
}
void BF_Init( bitbuf_t *bf, const char *pDebugName, void *pData, int nBytes, int nMaxBits )
void BF_InitExt( bitbuf_t *bf, const char *pDebugName, void *pData, int nBytes, int nMaxBits )
{
bf->pDebugName = pDebugName;
@ -42,8 +42,8 @@ void BF_Init( bitbuf_t *bf, const char *pDebugName, void *pData, int nBytes, int
void BF_StartWriting( bitbuf_t *bf, void *pData, int nBytes, int iStartBit, int nBits )
{
// Make sure it's dword aligned and padded.
ASSERT(( nBytes % 4 ) == 0 );
// make sure it's dword aligned and padded.
// ASSERT(( nBytes % 4 ) == 0 );
ASSERT(((dword)pData & 3 ) == 0 );
bf->pData = (byte *)pData;
@ -63,6 +63,13 @@ void BF_StartWriting( bitbuf_t *bf, void *pData, int nBytes, int iStartBit, int
bf->bOverflow = false;
}
/*
=======================
MSG_Clear
for clearing overflowed buffer
=======================
*/
void BF_Clear( bitbuf_t *bf )
{
bf->iCurBit = 0;
@ -74,16 +81,28 @@ static bool BF_Overflow( bitbuf_t *bf, int nBits )
if( bf->iCurBit + nBits > bf->nDataBits )
{
bf->bOverflow = true;
MsgDev( D_ERROR, "Msg %s: overflow!\n", bf->pDebugName );
Host_Error( "Msg %s: overflow! %i + %i > %i\n", bf->pDebugName, bf->iCurBit, nBits, bf->nDataBits );
}
return bf->bOverflow;
}
bool BF_CheckOverflow( bitbuf_t *bf )
{
ASSERT( bf );
return BF_Overflow( bf, 0 );
}
void BF_SeekToBit( bitbuf_t *bf, int bitPos )
{
bf->iCurBit = bitPos;
}
void BF_SeekToByte( bitbuf_t *bf, int bytePos )
{
bf->iCurBit = bytePos << 3;
}
void BF_WriteOneBit( bitbuf_t *bf, int nValue )
{
if( !BF_Overflow( bf, 1 ))
@ -112,7 +131,7 @@ void BF_WriteUBitLongExt( bitbuf_t *bf, uint curData, int numbits, bool bCheckRa
{
bf->bOverflow = true;
bf->iCurBit = bf->nDataBits;
MsgDev( D_ERROR, "Msg %s: overflow!\n", bf->pDebugName );
MsgDev( D_ERROR, "WriteError: %s: overflow!\n", bf->pDebugName );
}
else
{
@ -240,6 +259,10 @@ void BF_WriteBitAngle( bitbuf_t *bf, float fAngle, int numbits )
uint mask, shift;
int d;
// clamp the angle before receiving
if( fAngle > 360 ) fAngle -= 360;
else if( fAngle < 0 ) fAngle += 360;
shift = ( 1 << numbits );
mask = shift - 1;
@ -390,11 +413,11 @@ bool BF_WriteString( bitbuf_t *bf, const char *pStr )
do
{
BF_WriteChar( bf, *pStr );
++pStr;
} while(*( pStr - 1 ) != 0 );
pStr++;
} while( *( pStr - 1 ));
}
else BF_WriteChar( bf, 0 );
return !bf->bOverflow;
}
@ -414,11 +437,19 @@ uint BF_ReadUBitLong( bitbuf_t *bf, int numbits )
int idword1;
uint dword1, ret;
if( numbits == 8 )
{
int leftBits = BF_GetNumBitsLeft( bf );
if( leftBits >= 0 && leftBits < 8 )
return 0; // end of message
}
if(( bf->iCurBit + numbits ) > bf->nDataBits )
{
bf->bOverflow = true;
MsgDev( D_ERROR, "ReadError: %s: overflow! cur %i num %i, total %i\n", bf->pDebugName, bf->iCurBit, numbits, bf->nDataBits );
bf->iCurBit = bf->nDataBits;
MsgDev( D_ERROR, "Msg %s: overflow!\n", bf->pDebugName );
return 0;
}
@ -447,7 +478,6 @@ uint BF_ReadUBitLong( bitbuf_t *bf, int numbits )
// shift the second dword's part into the high bits.
ret |= (dword2 << ( numbits - nExtraBits ));
}
return ret;
}
@ -526,6 +556,10 @@ float BF_ReadBitAngle( bitbuf_t *bf, int numbits )
i = BF_ReadUBitLong( bf, numbits );
fReturn = (float)i * ( 360.0 / shift );
// clamp the finale angle
if( fReturn < -180 ) fReturn += 360;
else if( fReturn > 180 ) fReturn -= 360;
return fReturn;
}
@ -688,36 +722,27 @@ bool BF_ReadBytes( bitbuf_t *bf, void *pOut, int nBytes )
return BF_ReadBits( bf, pOut, nBytes << 3 );
}
const char *BF_ReadString( bitbuf_t *bf, bool bLine )
char *BF_ReadStringExt( bitbuf_t *bf, bool bLine )
{
static char string[2048];
int maxLen = sizeof( string ) - 1;
char *pStr = string;
bool bTooSmall = false;
int iChar = 0;
while( 1 )
static char string[MAX_SYSPATH];
int l = 0, c;
do
{
char val = BF_ReadChar( bf );
// use BF_ReadByte so -1 is out of bounds
c = BF_ReadByte( bf );
if( val == 0 ) break;
else if( bLine && val == '\n' )
if( c == 0 ) break;
else if( bLine && c == '\n' )
break;
// translate all fmt spec to avoid crash bugs
if( val == '%' ) val = '.';
if( c == '%' ) c = '.';
if( iChar < ( maxLen - 1 ))
{
pStr[iChar] = val;
iChar++;
}
else bTooSmall = true;
}
// make sure it's null-terminated.
ASSERT( iChar < maxLen );
pStr[iChar] = 0;
string[l] = c;
l++;
} while( l < sizeof( string ) - 1 );
string[l] = 0; // terminator
return string;
}

View File

@ -14,7 +14,7 @@ _inline int BitByte( int bits )
return PAD_NUMBER( bits, 8 ) >> 3;
}
typedef struct
typedef struct bitbuf_s
{
bool bOverflow; // overflow reading or writing
const char *pDebugName; // buffer name (pointer to const name)
@ -30,18 +30,22 @@ typedef struct
#define BF_StartReading BF_StartWriting
#define BF_GetNumBytesRead BF_GetNumBytesWritten
#define BF_ReadBitAngles BF_ReadBitVec3Coord
#define BF_ReadStringLine( bf ) BF_ReadString( bf, true );
#define BF_ReadString( bf ) BF_ReadStringExt( bf, false )
#define BF_ReadStringLine( bf ) BF_ReadStringExt( bf, true )
#define BF_Init( bf, name, data, bytes ) BF_InitExt( bf, name, data, bytes, -1 )
// common functions
void BF_Init( bitbuf_t *bf, const char *pDebugName, void *pData, int nBytes, int nMaxBits );
void BF_InitExt( bitbuf_t *bf, const char *pDebugName, void *pData, int nBytes, int nMaxBits );
void BF_InitMasks( void ); // called once at startup engine
void BF_SeekToBit( bitbuf_t *bf, int bitPos );
void BF_SeekToByte( bitbuf_t *bf, int bytePos );
bool BF_CheckOverflow( bitbuf_t *bf );
// init writing
void BF_StartWriting( bitbuf_t *bf, void *pData, int nBytes, int iStartBit, int nBits );
void BF_Clear( bitbuf_t *bf );
// Bit-write functions
void BF_SeekToBit( bitbuf_t *bf, int bitPos );
void BF_WriteOneBit( bitbuf_t *bf, int nValue );
void BF_WriteUBitLongExt( bitbuf_t *bf, uint curData, int numbits, bool bCheckRange );
void BF_WriteSBitLong( bitbuf_t *bf, int data, int numbits );
@ -65,10 +69,14 @@ void BF_WriteFloat( bitbuf_t *bf, float val );
bool BF_WriteBytes( bitbuf_t *bf, const void *pBuf, int nBytes ); // same as MSG_WriteData
bool BF_WriteString( bitbuf_t *bf, const char *pStr ); // returns false if it overflows the buffer.
// delta-write functions
bool BF_WriteDeltaMovevars( bitbuf_t *sb, movevars_t *from, movevars_t *cmd );
// helper functions
_inline int BF_GetNumBytesWritten( bitbuf_t *bf ) { return BitByte( bf->iCurBit ); }
_inline int BF_GetNumBitsWritten( bitbuf_t *bf ) { return bf->iCurBit; }
_inline int BF_GetMaxNumBits( bitbuf_t *bf ) { return bf->nDataBits; }
_inline int BF_GetMaxBits( bitbuf_t *bf ) { return bf->nDataBits; }
_inline int BF_GetMaxBytes( bitbuf_t *bf ) { return bf->nDataBytes; }
_inline int BF_GetNumBitsLeft( bitbuf_t *bf ) { return bf->nDataBits - bf->iCurBit; }
_inline int BF_GetNumBytesLeft( bitbuf_t *bf ) { return BF_GetNumBitsLeft( bf ) >> 3; }
_inline byte *BF_GetData( bitbuf_t *bf ) { return bf->pData; }
@ -79,6 +87,7 @@ float BF_ReadBitFloat( bitbuf_t *bf );
bool BF_ReadBits( bitbuf_t *bf, void *pOutData, int nBits );
float BF_ReadBitAngle( bitbuf_t *bf, int numbits );
int BF_ReadSBitLong( bitbuf_t *bf, int numbits );
uint BF_ReadUBitLong( bitbuf_t *bf, int numbits );
uint BF_ReadBitLong( bitbuf_t *bf, int numbits, bool bSigned );
float BF_ReadBitCoord( bitbuf_t *bf );
void BF_ReadBitVec3Coord( bitbuf_t *bf, vec3_t fa );
@ -93,7 +102,9 @@ int BF_ReadWord( bitbuf_t *bf );
long BF_ReadLong( bitbuf_t *bf );
float BF_ReadFloat( bitbuf_t *bf );
bool BF_ReadBytes( bitbuf_t *bf, void *pOut, int nBytes );
const char *BF_ReadString( bitbuf_t *bf, bool bLine );
char *BF_ReadStringExt( bitbuf_t *bf, bool bLine );
// delta-read functions
void BF_ReadDeltaMovevars( bitbuf_t *sb, movevars_t *from, movevars_t *cmd );
#endif//NET_BUFFER_H

View File

@ -6,6 +6,8 @@
#include "common.h"
#include "mathlib.h"
#include "byteorder.h"
#include "protocol.h"
#include "net_encode.h"
/*
packet header ( size in bits )
@ -28,7 +30,7 @@ the retransmit has been acknowledged and the reliable still failed to get there.
if the sequence number is -1, the packet should be handled without a netcon
The reliable message can be added to at any time by doing
MSG_Write* (&netchan->message, <data>).
BF_Write* (&netchan->message, <data>).
If the message buffer is overflowed, either by a single message, or by
multiple frames worth piling up while the last reliable transmit goes
@ -64,7 +66,7 @@ cvar_t *net_speeds;
cvar_t *net_qport;
netadr_t net_from;
sizebuf_t net_message;
bitbuf_t net_message;
byte net_message_buffer[MAX_MSGLEN];
/*
@ -83,6 +85,9 @@ void Netchan_Init( void )
net_showdrop = Cvar_Get ("net_showdrop", "0", 0, "show packets that are dropped" );
net_speeds = Cvar_Get ("net_speeds", "0", CVAR_ARCHIVE, "show network packets" );
net_qport = Cvar_Get ("net_qport", va( "%i", port ), CVAR_INIT, "current quake netport" );
Huff_Init (); // initialize huffman compression
BF_InitMasks (); // initialize bit-masks
}
/*
@ -102,9 +107,9 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport )
chan->last_received = Sys_Milliseconds ();
chan->incoming_sequence = 0;
chan->outgoing_sequence = 1;
chan->compress = true;
chan->compress = false;
MSG_Init( &chan->message, chan->message_buf, sizeof( chan->message_buf ));
BF_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
}
/*
@ -116,17 +121,17 @@ Sends an out-of-band datagram
*/
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data )
{
sizebuf_t send;
bitbuf_t send;
byte send_buf[MAX_MSGLEN];
// write the packet header
MSG_Init( &send, send_buf, sizeof( send_buf ));
BF_Init( &send, "SequencePacket", send_buf, sizeof( send_buf ));
MSG_WriteLong( &send, -1 ); // -1 sequence means out of band
MSG_WriteData( &send, data, length );
BF_WriteLong( &send, -1 ); // -1 sequence means out of band
BF_WriteBytes( &send, data, length );
// send the datagram
NET_SendPacket( net_socket, send.cursize, send.data, adr );
NET_SendPacket( net_socket, BF_GetNumBytesWritten( &send ), BF_GetData( &send ), adr );
}
/*
@ -139,7 +144,7 @@ Sends a text message in an out-of-band datagram
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, char *format, ... )
{
va_list argptr;
char string[MAX_MSGLEN];
char string[MAX_SYSPATH];
va_start( argptr, format );
com.vsprintf( string, format, argptr );
@ -159,14 +164,14 @@ bool Netchan_NeedReliable( netchan_t *chan )
send_reliable = true;
// if the reliable transmit buffer is empty, copy the current message out
if( !chan->reliable_length && chan->message.cursize )
if( !chan->reliable_length && BF_GetNumBitsWritten( &chan->message ))
send_reliable = true;
if( !chan->reliable_length && chan->message.cursize )
if( !chan->reliable_length && BF_GetNumBitsWritten( &chan->message ))
{
Mem_Copy( chan->reliable_buf, chan->message_buf, chan->message.cursize );
chan->reliable_length = chan->message.cursize;
chan->message.cursize = 0;
Mem_Copy( chan->reliable_buf, chan->message_buf, BF_GetNumBytesWritten( &chan->message ));
chan->reliable_length = BF_GetNumBitsWritten( &chan->message );
BF_Clear( &chan->message );
chan->reliable_sequence ^= 1;
}
@ -183,9 +188,14 @@ transmition / retransmition of the reliable messages.
A 0 length will still generate a packet and deal with the reliable messages.
================
*/
void Netchan_Transmit( netchan_t *chan, int length, byte *data )
void Netchan_Transmit( netchan_t *chan, int lengthInBytes, byte *data )
{
sizebuf_t send;
Netchan_TransmitBits( chan, lengthInBytes << 3, data );
}
void Netchan_TransmitBits( netchan_t *chan, int lengthInBits, byte *data )
{
bitbuf_t send;
static bool overflow = false;
byte send_buf[MAX_MSGLEN];
bool send_reliable;
@ -193,7 +203,7 @@ void Netchan_Transmit( netchan_t *chan, int length, byte *data )
uint w1, w2;
// check for message overflow
if( chan->message.overflowed )
if( BF_CheckOverflow( &chan->message ))
{
chan->fatal_error = true;
MsgDev( D_ERROR, "%s:outgoing message overflow\n", NET_AdrToString( chan->remote_address ));
@ -203,7 +213,7 @@ void Netchan_Transmit( netchan_t *chan, int length, byte *data )
send_reliable = Netchan_NeedReliable( chan );
// write the packet header
MSG_Init( &send, send_buf, sizeof(send_buf));
BF_Init( &send, "NetSend", send_buf, sizeof( send_buf ));
w1 = (chan->outgoing_sequence & ~(1<<31)) | (send_reliable<<31);
w2 = (chan->incoming_sequence & ~(1<<31)) | (chan->incoming_reliable_sequence<<31);
@ -211,23 +221,23 @@ void Netchan_Transmit( netchan_t *chan, int length, byte *data )
chan->outgoing_sequence++;
chan->last_sent = Sys_Milliseconds ();
MSG_WriteLong( &send, w1 );
MSG_WriteLong( &send, w2 );
BF_WriteLong( &send, w1 );
BF_WriteLong( &send, w2 );
// send the qport if we are a client
if( chan->sock == NS_CLIENT ) MSG_WriteWord( &send, Cvar_VariableValue( "net_qport" ));
if( chan->sock == NS_CLIENT ) BF_WriteWord( &send, Cvar_VariableValue( "net_qport" ));
// copy the reliable message to the packet first
if( send_reliable )
{
MSG_WriteData( &send, chan->reliable_buf, chan->reliable_length );
BF_WriteBits( &send, chan->reliable_buf, chan->reliable_length );
chan->last_reliable_sequence = chan->outgoing_sequence;
}
// add the unreliable part if space is available
if( send.maxsize - send.cursize >= length )
if( BF_GetNumBitsLeft( &send ) >= lengthInBits )
{
MSG_WriteData( &send, data, length );
BF_WriteBits( &send, data, lengthInBits );
overflow = false;
}
else
@ -237,15 +247,15 @@ void Netchan_Transmit( netchan_t *chan, int length, byte *data )
overflow = true;
}
size1 = send.cursize;
size1 = BF_GetNumBytesWritten( &send );
if( chan->compress ) Huff_CompressPacket( &send, (chan->sock == NS_CLIENT) ? 10 : 8 );
size2 = send.cursize;
size2 = BF_GetNumBytesWritten( &send );
chan->total_sended += size2;
chan->total_sended_uncompressed += size1;
// send the datagram
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address );
NET_SendPacket( chan->sock, BF_GetNumBytesWritten( &send ), BF_GetData( &send ), chan->remote_address );
if( net_showpackets->integer == 1 )
{
@ -269,7 +279,7 @@ called when the current net message is from remote_address
modifies net message so that it points to the packet payload
=================
*/
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg )
bool Netchan_Process( netchan_t *chan, bitbuf_t *msg )
{
uint sequence, sequence_ack;
uint reliable_ack, recv_reliable;
@ -277,13 +287,13 @@ bool Netchan_Process( netchan_t *chan, sizebuf_t *msg )
int qport;
// get sequence numbers
MSG_BeginReading( msg );
sequence = MSG_ReadLong( msg );
sequence_ack = MSG_ReadLong( msg );
BF_Clear( msg );
sequence = BF_ReadLong( msg );
sequence_ack = BF_ReadLong( msg );
// read the qport if we are a server
if( chan->sock == NS_SERVER )
qport = MSG_ReadShort( msg );
qport = BF_ReadShort( msg );
recv_reliable = sequence>>31;
reliable_ack = sequence_ack>>31;
@ -318,9 +328,10 @@ bool Netchan_Process( netchan_t *chan, sizebuf_t *msg )
chan->incoming_acknowledged = sequence_ack;
chan->incoming_reliable_acknowledged = reliable_ack;
if( recv_reliable ) chan->incoming_reliable_sequence ^= 1;
size1 = msg->cursize;
size1 = BF_GetMaxBytes( msg );
if( chan->compress ) Huff_DecompressPacket( msg, ( chan->sock == NS_SERVER) ? 10 : 8 );
size2 = msg->cursize;
size2 = BF_GetMaxBytes( msg );
chan->total_received += size1;
chan->total_received_uncompressed += size2;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
//=======================================================================
// Copyright XashXT Group 2010 ©
// net_encode.h - delta encode routines
//=======================================================================
#ifndef NET_ENCODE_H
#define NET_ENCODE_H
#define DT_BYTE BIT( 0 ) // A byte
#define DT_SHORT BIT( 1 ) // 2 byte field
#define DT_FLOAT BIT( 2 ) // A floating point field
#define DT_INTEGER BIT( 3 ) // 4 byte integer
#define DT_ANGLE BIT( 4 ) // A floating point angle ( will get masked correctly )
#define DT_TIMEWINDOW BIT( 5 ) // A floating point timestamp, relative to sv.time
// and re-encoded on the client relative to the client's clock
#define DT_STRING BIT( 6 ) // A null terminated string, sent as 8 byte chars
#define DT_SIGNED BIT( 7 ) // sign modificator
#define offsetof( s, m ) (size_t)&(((s *)0)->m)
#define NUM_FIELDS( x ) ((sizeof( x ) / sizeof( x[0] )) - 1)
// helper macroses
#define ENTS_DEF( x ) #x, offsetof( entity_state_t, x ), sizeof( ((entity_state_t *)0)->x )
#define UCMD_DEF( x ) #x, offsetof( usercmd_t, x ), sizeof( ((usercmd_t *)0)->x )
#define EVNT_DEF( x ) #x, offsetof( event_args_t, x ), sizeof( ((event_args_t *)0)->x )
#define PHYS_DEF( x ) #x, offsetof( movevars_t, x ), sizeof( ((movevars_t *)0)->x )
#define CLDT_DEF( x ) #x, offsetof( clientdata_t, x ), sizeof( ((clientdata_t *)0)->x )
#define WPDT_DEF( x ) #x, offsetof( weapon_data_t, x ), sizeof( ((weapon_data_t *)0)->x )
enum
{
CUSTOM_NONE = 0,
CUSTOM_SEREVR_ENCODE, // keyword "gamedll"
CUSTOM_CLIENT_ENCODE, // keyword "client"
};
// struct info (filled by engine)
typedef struct
{
const char *name;
const int offset;
const int size;
} delta_field_t;
typedef struct delta_s
{
const char *name;
int offset; // in bytes
int flags; // DT_INTEGER, DT_FLOAT etc
float multiplier;
float post_multiplier; // for DEFINE_DELTA_POST
int bits; // how many bits we send\receive
} delta_t;
typedef void (*pfnDeltaEncode)( delta_t *pFields, const byte *from, const byte *to );
typedef struct
{
const char *pName;
const delta_field_t *pInfo;
const int maxFields; // maximum number of fields in struct
int numFields; // may be merged during initialization
delta_t *pFields;
// added these for custom entity encode
int customEncode;
char funcName[32];
pfnDeltaEncode userCallback;
bool bInitialized;
} delta_info_t;
//
// net_encode.c
//
void Delta_Init( void );
void Delta_Shutdown( void );
void Delta_InitFields( void );
void MSG_DeltaAddEncoder( char *name, pfnDeltaEncode encodeFunc );
int MSG_DeltaFindField( delta_t *pFields, const char *fieldname );
void MSG_DeltaSetField( delta_t *pFields, const char *fieldname );
void MSG_DeltaUnsetField( delta_t *pFields, const char *fieldname );
void MSG_DeltaSetFieldByIndex( struct delta_s *pFields, int fieldNumber );
void MSG_DeltaUnsetFieldByIndex( struct delta_s *pFields, int fieldNumber );
// encode routines
void MSG_WriteDeltaUsercmd( bitbuf_t *msg, usercmd_t *from, usercmd_t *to );
void MSG_ReadDeltaUsercmd( bitbuf_t *msg, usercmd_t *from, usercmd_t *to );
void MSG_WriteDeltaEvent( bitbuf_t *msg, event_args_t *from, event_args_t *to );
void MSG_ReadDeltaEvent( bitbuf_t *msg, event_args_t *from, event_args_t *to );
void MSG_WriteClientData( bitbuf_t *msg, clientdata_t *from, clientdata_t *to, int timebase );
void MSG_ReadClientData( bitbuf_t *msg, clientdata_t *from, clientdata_t *to, int timebase );
void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, bitbuf_t *msg, bool force, int timebase );
void MSG_ReadDeltaEntity( bitbuf_t *msg, entity_state_t *from, entity_state_t *to, int number, int timebase );
#endif//NET_ENCODE_H

View File

@ -499,7 +499,7 @@ Compress message using dynamic Huffman tree,
beginning from specified offset
============
*/
void Huff_CompressPacket( sizebuf_t *msg, int offset )
void Huff_CompressPacket( bitbuf_t *msg, int offset )
{
tree_t tree;
byte buffer[MAX_MSGLEN];
@ -507,8 +507,8 @@ void Huff_CompressPacket( sizebuf_t *msg, int offset )
int outLen;
int i, inLen;
data = msg->data + offset;
inLen = msg->cursize - offset;
data = BF_GetData( msg ) + offset;
inLen = BF_GetNumBytesWritten( msg ) - offset;
if( inLen <= 0 || inLen >= MAX_MSGLEN )
return;
@ -525,7 +525,7 @@ void Huff_CompressPacket( sizebuf_t *msg, int offset )
}
outLen = (huffBitPos >> 3) + 1;
msg->cursize = offset + outLen;
msg->iCurBit = ( offset + outLen ) << 3;
Mem_Copy( data, buffer, outLen );
}
@ -538,7 +538,7 @@ Decompress message using dynamic Huffman tree,
beginning from specified offset
============
*/
void Huff_DecompressPacket( sizebuf_t *msg, int offset )
void Huff_DecompressPacket( bitbuf_t *msg, int offset )
{
tree_t tree;
byte buffer[MAX_MSGLEN];
@ -547,8 +547,8 @@ void Huff_DecompressPacket( sizebuf_t *msg, int offset )
int inLen;
int ch, i, j;
data = msg->data + offset;
inLen = msg->cursize - offset;
data = BF_GetData( msg ) + offset;
inLen = BF_GetMaxBytes( msg ) - offset;
if( inLen <= 0 ) return;
Huff_PrepareTree( tree );
@ -556,8 +556,8 @@ void Huff_DecompressPacket( sizebuf_t *msg, int offset )
outLen = (data[0] << 8) + data[1];
huffBitPos = 16;
if( outLen > msg->maxsize - offset )
outLen = msg->maxsize - offset;
if( outLen > BF_GetMaxBytes( msg ) - offset )
outLen = BF_GetMaxBytes( msg ) - offset;
for( i = 0; i < outLen; i++ )
{
@ -582,7 +582,8 @@ void Huff_DecompressPacket( sizebuf_t *msg, int offset )
Huff_AddReference( tree, ch );
}
msg->cursize = offset + outLen;
msg->nDataBytes = offset + outLen;
msg->nDataBits = ( msg->nDataBytes ) << 3;
Mem_Copy( data, buffer, outLen );
}

View File

@ -4,6 +4,7 @@
//=======================================================================
#include "common.h"
#include "protocol.h"
#include "byteorder.h"
#include "mathlib.h"
@ -13,100 +14,6 @@
#define ANGLE2SHORT(x) ((int)((x)*65536 / 360) & 65535)
#define SHORT2ANGLE(x) ((x)*(360.0f / 65536))
static net_field_t ent_fields[] =
{
{ ES_FIELD(ed_type), NET_BYTE, false }, // stateflags_t #0 (4 bytes)
{ ES_FIELD(ed_flags), NET_BYTE, false }, // stateflags_t #0 (4 bytes)
{ ES_FIELD(classname), NET_WORD, false },
{ ES_FIELD(angles[0]), NET_FLOAT, false },
{ ES_FIELD(angles[1]), NET_FLOAT, false },
{ ES_FIELD(angles[2]), NET_FLOAT, false },
{ ES_FIELD(velocity[0]), NET_FLOAT, false },
{ ES_FIELD(velocity[1]), NET_FLOAT, false },
{ ES_FIELD(velocity[2]), NET_FLOAT, false },
{ ES_FIELD(basevelocity[0]), NET_FLOAT, false },
{ ES_FIELD(basevelocity[1]), NET_FLOAT, false },
{ ES_FIELD(basevelocity[2]), NET_FLOAT, false },
{ ES_FIELD(modelindex), NET_WORD, false }, // 4096 models
{ ES_FIELD(colormap), NET_WORD, false }, // encoded as two shorts for top and bottom color
{ ES_FIELD(scale), NET_FLOAT, false }, // 0-255 values
{ ES_FIELD(frame), NET_FLOAT, false }, // interpolate value
{ ES_FIELD(animtime), NET_FLOAT, false }, // auto-animating time
{ ES_FIELD(framerate), NET_FLOAT, false }, // custom framerate
{ ES_FIELD(sequence), NET_WORD, false }, // 1024 sequences
{ ES_FIELD(gaitsequence), NET_WORD, false }, // 1024 gaitsequences
{ ES_FIELD(skin), NET_SHORT, false }, // beacuse negative skins are contents
{ ES_FIELD(body), NET_BYTE, false }, // 255 bodies
{ ES_FIELD(weaponmodel), NET_WORD, false }, // p_model index, not name
{ ES_FIELD(contents), NET_LONG, false }, // full range contents
{ ES_FIELD(blending[0]), NET_BYTE, false },
{ ES_FIELD(blending[1]), NET_BYTE, false }, // stateflags_t #1 (4 bytes)
{ ES_FIELD(blending[2]), NET_BYTE, false },
{ ES_FIELD(blending[3]), NET_BYTE, false },
{ ES_FIELD(blending[4]), NET_BYTE, false },
{ ES_FIELD(blending[5]), NET_BYTE, false },
{ ES_FIELD(blending[6]), NET_BYTE, false },
{ ES_FIELD(blending[7]), NET_BYTE, false },
{ ES_FIELD(blending[8]), NET_BYTE, false },
{ ES_FIELD(blending[9]), NET_BYTE, false },
{ ES_FIELD(controller[0]), NET_BYTE, false }, // bone controllers #
{ ES_FIELD(controller[1]), NET_BYTE, false },
{ ES_FIELD(controller[2]), NET_BYTE, false },
{ ES_FIELD(controller[3]), NET_BYTE, false },
{ ES_FIELD(controller[4]), NET_BYTE, false },
{ ES_FIELD(controller[5]), NET_BYTE, false },
{ ES_FIELD(controller[6]), NET_BYTE, false },
{ ES_FIELD(controller[7]), NET_BYTE, false },
{ ES_FIELD(controller[8]), NET_BYTE, false },
{ ES_FIELD(controller[9]), NET_BYTE, false },
{ ES_FIELD(solid), NET_BYTE, false },
{ ES_FIELD(flags), NET_LONG, false }, // misc edict flags
{ ES_FIELD(movetype), NET_BYTE, false },
{ ES_FIELD(gravity), NET_SHORT, false }, // gravity multiplier
{ ES_FIELD(friction), NET_FLOAT, false }, // friction for prediction
{ ES_FIELD(aiment), NET_SHORT, false }, // entity index
{ ES_FIELD(owner), NET_SHORT, false }, // entity owner index
{ ES_FIELD(groundent), NET_SHORT, false }, // ground entity index, if FL_ONGROUND is set
{ ES_FIELD(effects), NET_LONG, false }, // effect flags
{ ES_FIELD(mins[0]), NET_FLOAT, false },
{ ES_FIELD(mins[1]), NET_FLOAT, false },
{ ES_FIELD(mins[2]), NET_FLOAT, false },
{ ES_FIELD(maxs[0]), NET_FLOAT, false },
{ ES_FIELD(maxs[1]), NET_FLOAT, false },
{ ES_FIELD(maxs[2]), NET_FLOAT, false },
{ ES_FIELD(renderfx), NET_LONG, false }, // renderfx flags
{ ES_FIELD(renderamt), NET_FLOAT, false }, // alpha amount
{ ES_FIELD(rendercolor[0]), NET_FLOAT, false }, // stateflags_t #2 (4 bytes)
{ ES_FIELD(rendercolor[1]), NET_FLOAT, false },
{ ES_FIELD(rendercolor[2]), NET_FLOAT, false },
{ ES_FIELD(oldorigin[0]), NET_FLOAT, false },
{ ES_FIELD(oldorigin[1]), NET_FLOAT, false },
{ ES_FIELD(oldorigin[2]), NET_FLOAT, false },
{ ES_FIELD(origin[0]), NET_FLOAT, false },
{ ES_FIELD(origin[1]), NET_FLOAT, false },
{ ES_FIELD(origin[2]), NET_FLOAT, false },
{ ES_FIELD(rendermode), NET_BYTE, false }, // render mode (legacy stuff)
{ ES_FIELD(punch_angles[0]), NET_SCALE, false },
{ ES_FIELD(punch_angles[1]), NET_SCALE, false },
{ ES_FIELD(punch_angles[2]), NET_SCALE, false },
{ ES_FIELD(viewangles[0]), NET_FLOAT, false }, // for fixed views
{ ES_FIELD(viewangles[1]), NET_FLOAT, false },
{ ES_FIELD(viewangles[2]), NET_FLOAT, false },
{ ES_FIELD(viewoffset[0]), NET_SCALE, false },
{ ES_FIELD(viewoffset[1]), NET_SCALE, false },
{ ES_FIELD(viewoffset[2]), NET_FLOAT, false },
{ ES_FIELD(idealpitch), NET_SCALE, false },
{ ES_FIELD(viewmodel), NET_WORD, false },
{ ES_FIELD(maxspeed), NET_FLOAT, false }, // client maxspeed
{ ES_FIELD(fov), NET_FLOAT, false }, // client horizontal field of view
{ ES_FIELD(weapons), NET_LONG, false }, // client weapon 0-64
{ ES_FIELD(health), NET_FLOAT, false }, // client health
{ ES_FIELD(iStepLeft), NET_LONG, false }, // client footsteps
{ ES_FIELD(flFallVelocity), NET_FLOAT, false }, // client fallvelocity
// revision 6. reserve for 5 fields without enlarge null_msg_size
{ NULL }
};
// probably movevars_t never reached 32 field integer limit (in theory of course)
static net_field_t move_fields[] =
{
@ -129,48 +36,6 @@ static net_field_t move_fields[] =
{ NULL },
};
// probably event_info_t never reached 32 field integer limit (in theory of course)
static net_field_t ev_fields[] =
{
{ EV_FIELD(flags), NET_WORD, true },
{ EV_FIELD(entindex), NET_WORD, true },
{ EV_FIELD(origin[0]), NET_FLOAT, false },
{ EV_FIELD(origin[1]), NET_FLOAT, false },
{ EV_FIELD(origin[2]), NET_FLOAT, false },
{ EV_FIELD(angles[0]), NET_ANGLE, false },
{ EV_FIELD(angles[1]), NET_ANGLE, false },
{ EV_FIELD(angles[2]), NET_ANGLE, false },
{ EV_FIELD(velocity[0]), NET_FLOAT, false },
{ EV_FIELD(velocity[1]), NET_FLOAT, false },
{ EV_FIELD(velocity[2]), NET_FLOAT, false },
{ EV_FIELD(ducking), NET_BYTE, false },
{ EV_FIELD(fparam1), NET_FLOAT, false },
{ EV_FIELD(fparam2), NET_FLOAT, false },
{ EV_FIELD(iparam1), NET_LONG, false },
{ EV_FIELD(iparam2), NET_LONG, false },
{ EV_FIELD(bparam1), NET_BYTE, false }, // 0 - 255 brightness
{ EV_FIELD(bparam2), NET_BYTE, false },
{ NULL },
};
// probably usercmd_t never reached 32 field integer limit (in theory of course)
static net_field_t cmd_fields[] =
{
{ CM_FIELD(msec), NET_BYTE, true },
{ CM_FIELD(viewangles[0]), NET_ANGLE, false },
{ CM_FIELD(viewangles[1]), NET_ANGLE, false },
{ CM_FIELD(viewangles[2]), NET_ANGLE, false },
{ CM_FIELD(forwardmove), NET_FLOAT, false },
{ CM_FIELD(sidemove), NET_FLOAT, false },
{ CM_FIELD(upmove), NET_FLOAT, false },
{ CM_FIELD(buttons), NET_SHORT, false },
{ CM_FIELD(impulse), NET_BYTE, false },
{ CM_FIELD(lightlevel), NET_BYTE, false }, // 0 - 255 brightness
{ CM_FIELD(random_seed), NET_LONG, false },
{ CM_FIELD(target_edict), NET_SHORT, false },
{ NULL },
};
/*
=============================================================================
@ -249,13 +114,7 @@ void _MSG_WriteData( sizebuf_t *buf, const void *data, size_t length, const char
Mem_Copy( MSG_GetSpace( buf, length ), data, length );
}
/*
=======================
MSG_Clear
for clearing overflowed buffer
=======================
*/
void MSG_Clear( sizebuf_t *buf )
{
buf->cursize = 0;
@ -274,6 +133,7 @@ MSG_WriteBits
write # of bytes
=======================
*/
void _MSG_WriteBits( sizebuf_t *msg, long value, const char *name, int net_type, const char *filename, const int fileline )
{
ftol_t dat;
@ -287,7 +147,7 @@ void _MSG_WriteBits( sizebuf_t *msg, long value, const char *name, int net_type,
return;
}
dat.l = value;
/*
switch( net_type )
{
case NET_SCALE:
@ -344,7 +204,7 @@ void _MSG_WriteBits( sizebuf_t *msg, long value, const char *name, int net_type,
Host_Error( "MSG_WriteBits: bad net.type %i (called at %s:%i)\n", net_type, filename, fileline );
break;
}
*/
if((NWDesc[net_type].min_range + NWDesc[net_type].max_range) != 0 )
{
// check range
@ -369,7 +229,7 @@ long _MSG_ReadBits( sizebuf_t *msg, const char *name, int net_type, const char *
{
ftol_t dat;
long value = 0;
/*
switch( net_type )
{
case NET_SCALE:
@ -423,7 +283,7 @@ long _MSG_ReadBits( sizebuf_t *msg, const char *name, int net_type, const char *
Host_Error( "MSG_ReadBits: bad net.type %i, (called at %s:%i)\n", net_type, filename, fileline );
break;
}
*/
value = dat.l;
// end of message or error reading
@ -447,39 +307,6 @@ long _MSG_ReadBits( sizebuf_t *msg, const char *name, int net_type, const char *
Handles byte ordering and avoids alignment errors
==============================================================================
*/
/*
=======================
writing functions
=======================
*/
void _MSG_WriteAngle8( sizebuf_t *sb, float f, const char *filename, int fileline )
{
union { float f; int l; } dat;
dat.f = f;
_MSG_WriteBits( sb, dat.l, NWDesc[NET_ANGLE8].name, NET_ANGLE8, filename, fileline );
}
void _MSG_WriteAngle16( sizebuf_t *sb, float f, const char *filename, int fileline )
{
union { float f; int l; } dat;
dat.f = f;
_MSG_WriteBits( sb, dat.l, NWDesc[NET_ANGLE].name, NET_ANGLE, filename, fileline );
}
void _MSG_WriteCoord16( sizebuf_t *sb, float f, const char *filename, int fileline )
{
union { float f; int l; } dat;
dat.f = f;
_MSG_WriteBits( sb, dat.l, NWDesc[NET_COORD].name, NET_COORD, filename, fileline );
}
void _MSG_WriteFloat( sizebuf_t *sb, float f, const char *filename, int fileline )
{
union { float f; int l; } dat;
dat.f = f;
_MSG_WriteBits( sb, dat.l, NWDesc[NET_FLOAT].name, NET_FLOAT, filename, fileline );
}
void _MSG_WriteString( sizebuf_t *sb, const char *src, const char *filename, int fileline )
{
if( !src )
@ -555,46 +382,6 @@ void _MSG_WriteStringLine( sizebuf_t *sb, const char *src, const char *filename,
}
}
void _MSG_WritePos( sizebuf_t *sb, const vec3_t pos, const char *filename, int fileline )
{
_MSG_WriteFloat( sb, pos[0], filename, fileline );
_MSG_WriteFloat( sb, pos[1], filename, fileline );
_MSG_WriteFloat( sb, pos[2], filename, fileline );
}
/*
=======================
reading functions
=======================
*/
float MSG_ReadFloat( sizebuf_t *msg )
{
union { float f; int l; } dat;
dat.l = MSG_ReadBits( msg, NWDesc[NET_FLOAT].name, NET_FLOAT );
return dat.f;
}
float MSG_ReadAngle8( sizebuf_t *msg )
{
union { float f; int l; } dat;
dat.l = MSG_ReadBits( msg, NWDesc[NET_ANGLE8].name, NET_ANGLE8 );
return dat.f;
}
float MSG_ReadAngle16( sizebuf_t *msg )
{
union { float f; int l; } dat;
dat.l = MSG_ReadBits( msg, NWDesc[NET_ANGLE].name, NET_ANGLE );
return dat.f;
}
float MSG_ReadCoord16( sizebuf_t *msg )
{
union { float f; int l; } dat;
dat.l = MSG_ReadBits( msg, NWDesc[NET_COORD].name, NET_COORD );
return dat.f;
}
char *MSG_ReadString( sizebuf_t *msg )
{
static char string[MAX_SYSPATH];
@ -641,95 +428,6 @@ char *MSG_ReadStringLine( sizebuf_t *msg )
return string;
}
void MSG_ReadData( sizebuf_t *msg, void *data, size_t length )
{
int i;
for( i = 0; i < length; i++ )
((byte *)data)[i] = MSG_ReadByte( msg );
}
void MSG_ReadPos( sizebuf_t *msg_read, vec3_t pos )
{
pos[0] = MSG_ReadFloat( msg_read );
pos[1] = MSG_ReadFloat( msg_read );
pos[2] = MSG_ReadFloat( msg_read );
}
/*
=============================================================================
usercmd_t communication
=============================================================================
*/
/*
=====================
MSG_WriteDeltaUsercmd
=====================
*/
void _MSG_WriteDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to, const char *filename, const int fileline )
{
int num_fields;
net_field_t *field;
int *fromF, *toF;
int i, flags = 0;
num_fields = (sizeof( cmd_fields ) / sizeof( cmd_fields[0] )) - 1;
if( num_fields > MASK_FLAGS ) return; // this should never happen
// compare fields
for( i = 0, field = cmd_fields; i < num_fields; i++, field++ )
{
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if(*fromF != *toF || field->force) flags |= 1<<i;
}
if( flags == 0 )
{
// nothing at all changed
MSG_WriteLong( msg, -99 ); // no delta info
return;
}
MSG_WriteLong( msg, flags ); // send flags who indicates changes
for( i = 0, field = cmd_fields; i < num_fields; i++, field++ )
{
toF = (int *)((byte *)to + field->offset );
if( flags & 1<<i ) MSG_WriteBits( msg, *toF, field->name, field->bits );
}
}
/*
=====================
MSG_ReadDeltaUsercmd
=====================
*/
void MSG_ReadDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to )
{
net_field_t *field;
int i, flags;
int *fromF, *toF;
*to = *from;
if(*(int *)&msg->data[msg->readcount] == -99 )
{
MSG_ReadLong( msg );
return;
}
for( i = 0, field = cmd_fields; field->name; i++, field++ )
{
// get flags of next packet if LONG out of range
if(( i & MASK_FLAGS ) == 0) flags = MSG_ReadLong( msg );
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if( flags & ( 1<<( i & MASK_FLAGS )))
*toF = MSG_ReadBits( msg, field->name, field->bits );
else *toF = *fromF; // no change
}
}
/*
=============================================================================
@ -737,7 +435,7 @@ movevars_t communication
=============================================================================
*/
bool _MSG_WriteDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to, const char *filename, const int fileline )
bool BF_WriteDeltaMovevars( bitbuf_t *msg, movevars_t *from, movevars_t *to )
{
int num_fields;
net_field_t *field;
@ -758,17 +456,17 @@ bool _MSG_WriteDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to,
// nothing at all changed
if( flags == 0 ) return false;
MSG_WriteByte( msg, svc_movevars );
MSG_WriteLong( msg, flags ); // send flags who indicates changes
BF_WriteByte( msg, svc_movevars );
BF_WriteLong( msg, flags ); // send flags who indicates changes
for( i = 0, field = move_fields; i < num_fields; i++, field++ )
{
toF = (int *)((byte *)to + field->offset );
if( flags & 1<<i ) MSG_WriteBits( msg, *toF, field->name, field->bits );
if( flags & 1<<i ) BF_WriteBits( msg, toF, field->bits );
}
return true;
}
void MSG_ReadDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to )
void BF_ReadDeltaMovevars( bitbuf_t *msg, movevars_t *from, movevars_t *to )
{
net_field_t *field;
int i, flags;
@ -779,209 +477,12 @@ void MSG_ReadDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to )
for( i = 0, field = move_fields; field->name; i++, field++ )
{
// get flags of next packet if LONG out of range
if(( i & MASK_FLAGS ) == 0) flags = MSG_ReadLong( msg );
if(( i & MASK_FLAGS ) == 0) flags = BF_ReadLong( msg );
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if( flags & ( 1<<( i & MASK_FLAGS )))
*toF = MSG_ReadBits( msg, field->name, field->bits );
else *toF = *fromF; // no change
}
}
/*
=============================================================================
entity_state_t communication
=============================================================================
*/
/*
==================
MSG_WriteDeltaEntity
Writes part of a packetentities message, including the entity number.
Can delta from either a baseline or a previous packet_entity
If to is NULL, a remove entity update will be sent
If force is not set, then nothing at all will be generated if the entity is
identical, under the assumption that the in-order delta code will catch it.
==================
*/
void _MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, bool force, bool newentity, const char *filename, int fileline )
{
net_field_t *field, *field2;
int i, j, flags = 0;
int *fromF, *toF;
int num_fields;
size_t null_msg_size;
size_t start_size;
if( to == NULL )
{
if( from == NULL ) return;
// a NULL to is a delta remove message
MSG_WriteBits( msg, from->number, NWDesc[NET_WORD].name, NET_WORD );
MSG_WriteBits( msg, 0x1869F, NWDesc[NET_LONG].name, NET_LONG );
return;
}
num_fields = sizeof(ent_fields) / sizeof(net_field_t);
null_msg_size = (int)ceil( num_fields / 32.0f ) * sizeof( int ) + sizeof( short );
start_size = msg->cursize;
if( to->number < 0 || to->number >= GI->max_edicts )
Host_Error( "MSG_WriteDeltaEntity: Bad entity number: %i (called at %s:%i)\n", to->number, filename, fileline );
MSG_WriteBits( msg, to->number, "serialnumber", NET_WORD );
for( i = 0, field = field2 = ent_fields; field->name; i++, field++ )
{
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if( *fromF != *toF || ( newentity && field->force ))
flags |= (1<<( i & MASK_FLAGS ));
if((( i & MASK_FLAGS ) + 1 == MAX_FLAGS ) || !ent_fields[i+1].name ) // dump packet
{
MSG_WriteLong( msg, flags ); // send flags who indicates changes
for( j = 0; field2->name; j++, field2++ )
{
if( j == MAX_FLAGS ) break; // return to main cycle
toF = (int *)((byte *)to + field2->offset );
if( flags & (1<<( j & MASK_FLAGS )))
MSG_WriteBits( msg, *toF, field2->name, field2->bits );
}
flags = 0;
}
}
// NOTE: null_msg_size is number of (ent_fields / 32) + (1),
// who indicates flags count multiplied by sizeof(long)
// plus sizeof(short) (head number). if message equal null_message_size
// we will be ignore it
if( !force && (( msg->cursize - start_size ) == null_msg_size ))
msg->cursize = start_size; // kill message
}
/*
==================
MSG_ReadDeltaEntity
The entity number has already been read from the message, which
is how the from state is identified.
If the delta removes the entity, entity_state_t->number will be set to MAX_EDICTS - 1
Can go from either a baseline or a previous packet_entity
==================
*/
void MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state_t *to, int number )
{
net_field_t *field;
int i, flags;
int *fromF, *toF;
if( number < 0 || number >= GI->max_edicts )
Host_Error( "MSG_ReadDeltaEntity: bad delta entity number: %i\n", number );
*to = *from;
to->number = number;
if(*(int *)&msg->data[msg->readcount] == 0x1869F )
{
// check for a remove
MSG_ReadLong( msg );
Mem_Set( to, 0, sizeof( *to ));
to->number = MAX_EDICTS; // entity was removed
return;
}
for( i = 0, field = ent_fields; field->name; i++, field++ )
{
// get flags of next packet if LONG out of range
if(( i & MASK_FLAGS ) == 0 ) flags = MSG_ReadLong( msg );
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if( flags & ( 1<<( i & MASK_FLAGS )))
*toF = MSG_ReadBits( msg, field->name, field->bits );
else *toF = *fromF; // no change
}
}
/*
============================================================================
event_state_t communication
============================================================================
*/
/*
=====================
MSG_WriteDeltaEvent
=====================
*/
void _MSG_WriteDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to, const char *filename, const int fileline )
{
int num_fields;
net_field_t *field;
int *fromF, *toF;
int i, flags = 0;
num_fields = (sizeof( ev_fields ) / sizeof( ev_fields[0] )) - 1;
if( num_fields > MASK_FLAGS ) return; // this should never happen
// compare fields
for( i = 0, field = ev_fields; i < num_fields; i++, field++ )
{
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if(*fromF != *toF || field->force) flags |= 1<<i;
}
if( flags == 0 )
{
// nothing at all changed
MSG_WriteLong( msg, -99 ); // no delta info
return;
}
MSG_WriteLong( msg, flags ); // send flags who indicates changes
for( i = 0, field = ev_fields; i < num_fields; i++, field++ )
{
toF = (int *)((byte *)to + field->offset );
if( flags & 1<<i ) MSG_WriteBits( msg, *toF, field->name, field->bits );
}
}
/*
=====================
MSG_ReadDeltaEvent
=====================
*/
void MSG_ReadDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to )
{
net_field_t *field;
int i, flags;
int *fromF, *toF;
*to = *from;
if(*(int *)&msg->data[msg->readcount] == -99 )
{
MSG_ReadLong( msg );
return;
}
for( i = 0, field = ev_fields; field->name; i++, field++ )
{
// get flags of next packet if LONG out of range
if(( i & MASK_FLAGS ) == 0) flags = MSG_ReadLong( msg );
fromF = (int *)((byte *)from + field->offset );
toF = (int *)((byte *)to + field->offset );
if( flags & ( 1<<( i & MASK_FLAGS )))
*toF = MSG_ReadBits( msg, field->name, field->bits );
BF_ReadBits( msg, toF, field->bits );
else *toF = *fromF; // no change
}
}

View File

@ -8,17 +8,17 @@
enum net_types_e
{
NET_BAD = 0,
NET_CHAR,
NET_BYTE,
NET_SHORT,
NET_WORD,
NET_LONG,
NET_FLOAT,
NET_ANGLE8, // angle 2 char
NET_ANGLE, // angle 2 short
NET_SCALE,
NET_COORD,
NET_COLOR,
NET_CHAR = 8,
NET_BYTE = 8,
NET_SHORT = 16,
NET_WORD = 16,
NET_LONG = 32,
NET_FLOAT = 32,
NET_ANGLE8 = 8, // angle 2 char
NET_ANGLE = 16, // angle 2 short
NET_SCALE = 8,
NET_COORD = 32,
NET_COLOR = 8,
NET_TYPES,
};
@ -56,69 +56,6 @@ typedef struct net_field_s
bool force; // will be send for newentity
} net_field_t;
typedef struct delta_s
{
char *name;
int offset; // in bytes
int deltaType; // DT_INTEGER, DT_FLOAT etc
float multiplier;
int bits; // how many bits we send\receive
} delta_t;
typedef void (*pfnDeltaEncode)( delta_t *pFields, const byte *from, const byte *to );
// server to client
enum svc_ops_e
{
// user messages
svc_bad = 0, // don't send!
// engine messages
svc_nop = 201, // end of user messages
svc_disconnect, // kick client from server
svc_reconnect, // reconnecting server request
svc_stufftext, // [string] stuffed into client's console buffer, should be \n terminated
svc_serverdata, // [long] protocol ...
svc_configstring, // [short] [string]
svc_spawnbaseline, // valid only at spawn
svc_download, // [short] size [size bytes]
svc_changing, // changelevel by server request
svc_physinfo, // [physinfo string]
svc_usermessage, // [string][byte] REG_USER_MSG stuff
svc_packetentities, // [...]
svc_frame, // begin a new server frame
svc_sound, // <see code>
svc_ambientsound, // <see code>
svc_setangle, // [float float] set the view angle to this absolute value
svc_addangle, // [float] add angles when client turn on mover
svc_setview, // [short] entity number
svc_print, // [byte] id [string] null terminated string
svc_centerprint, // [string] to put in center of the screen
svc_crosshairangle, // [short][short][short]
svc_setpause, // [byte] 0 = unpaused, 1 = paused
svc_movevars, // [movevars_t]
svc_particle, // [float*3][char*3][byte][byte]
svc_soundfade, // [float*4] sound fade parms
svc_bspdecal, // [float*3][short][short][short]
svc_event, // playback event queue
svc_event_reliable, // playback event directly from message, not queue
svc_updateuserinfo, // [byte] playernum, [string] userinfo
svc_serverinfo, // [string] key [string] value
};
// client to server
enum clc_ops_e
{
clc_bad = 0,
// engine messages
clc_nop = 201,
clc_move, // [[usercmd_t]
clc_delta, // [byte] sequence number, requests delta compression of message
clc_userinfo, // [[userinfo string]
clc_stringcmd, // [string] message
};
static const net_desc_t NWDesc[] =
{
{ NET_BAD, "none", 0, 0 }, // full range
@ -147,6 +84,7 @@ static const net_desc_t NWDesc[] =
#include "event_api.h"
#include "pm_movevars.h"
#include "entity_state.h"
#include "net_buffer.h"
#define ES_FIELD( x ) #x,(int)&((entity_state_t*)0)->x
#define EV_FIELD( x ) #x,(int)&((event_args_t*)0)->x
@ -194,17 +132,8 @@ long _MSG_ReadBits( sizebuf_t *msg, const char *name, int bits, const char *file
void _MSG_Begin( int dest, const char *filename, int fileline );
void _MSG_WriteString( sizebuf_t *sb, const char *s, const char *filename, int fileline );
void _MSG_WriteStringLine( sizebuf_t *sb, const char *src, const char *filename, int fileline );
void _MSG_WriteFloat( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WriteDouble( sizebuf_t *sb, double f, const char *filename, int fileline );
void _MSG_WriteAngle8( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WriteAngle16( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WriteCoord16( sizebuf_t *sb, float f, const char *filename, int fileline );
void _MSG_WritePos( sizebuf_t *sb, const vec3_t pos, const char *filename, int fileline );
void _MSG_WriteData( sizebuf_t *sb, const void *data, size_t length, const char *filename, int fileline );
void _MSG_WriteDeltaUsercmd( sizebuf_t *sb, usercmd_t *from, usercmd_t *cmd, const char *filename, const int fileline );
bool _MSG_WriteDeltaMovevars( sizebuf_t *sb, movevars_t *from, movevars_t *cmd, const char *filename, const int fileline );
void _MSG_WriteDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to, const char *filename, const int fileline );
void _MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *msg, bool force, bool newentity, const char *file, int line );
bool _MSG_Send( int dest, const vec3_t origin, const edict_t *ent, bool direct, const char *filename, int fileline );
#define MSG_Begin( x ) _MSG_Begin( x, __FILE__, __LINE__)
@ -217,17 +146,8 @@ bool _MSG_Send( int dest, const vec3_t origin, const edict_t *ent, bool direct,
#define MSG_WriteDouble(x,y) _MSG_WriteDouble(x, y, __FILE__, __LINE__)
#define MSG_WriteString(x,y) _MSG_WriteString (x, y, __FILE__, __LINE__)
#define MSG_WriteStringLine(x,y) _MSG_WriteStringLine (x, y, __FILE__, __LINE__)
#define MSG_WriteCoord16(x, y) _MSG_WriteCoord16(x, y, __FILE__, __LINE__)
#define MSG_WriteCoord32(x, y) _MSG_WriteFloat(x, y, __FILE__, __LINE__)
#define MSG_WriteAngle8(x, y) _MSG_WriteAngle8(x, y, __FILE__, __LINE__)
#define MSG_WriteAngle16(x, y) _MSG_WriteAngle16(x, y, __FILE__, __LINE__)
#define MSG_WriteAngle32(x, y) _MSG_WriteFloat(x, y, __FILE__, __LINE__)
#define MSG_WritePos(x, y) _MSG_WritePos( x, y, __FILE__, __LINE__ )
#define MSG_WriteData(x,y,z) _MSG_WriteData( x, y, z, __FILE__, __LINE__)
#define MSG_WriteDeltaEvent(x, y, z) _MSG_WriteDeltaEvent(x, y, z, __FILE__, __LINE__)
#define MSG_WriteDeltaUsercmd(x, y, z) _MSG_WriteDeltaUsercmd(x, y, z, __FILE__, __LINE__)
#define MSG_WriteDeltaMovevars(x, y, z) _MSG_WriteDeltaMovevars(x, y, z, __FILE__, __LINE__)
#define MSG_WriteDeltaEntity(from, to, msg, force, new ) _MSG_WriteDeltaEntity (from, to, msg, force, new, __FILE__, __LINE__)
#define MSG_WriteBits( buf, value, name, bits ) _MSG_WriteBits( buf, value, name, bits, __FILE__, __LINE__ )
#define MSG_ReadBits( buf, name, bits ) _MSG_ReadBits( buf, name, bits, __FILE__, __LINE__ )
#define MSG_Send(x, y, z) _MSG_Send(x, y, z, false, __FILE__, __LINE__)
@ -239,26 +159,15 @@ void MSG_BeginReading (sizebuf_t *sb);
#define MSG_ReadShort( x) _MSG_ReadBits( x, NWDesc[NET_SHORT].name, NET_SHORT, __FILE__, __LINE__ )
#define MSG_ReadWord( x ) _MSG_ReadBits( x, NWDesc[NET_WORD].name, NET_WORD, __FILE__, __LINE__ )
#define MSG_ReadLong( x ) _MSG_ReadBits( x, NWDesc[NET_LONG].name, NET_LONG, __FILE__, __LINE__ )
#define MSG_ReadCoord32( x ) MSG_ReadFloat( x )
#define MSG_ReadAngle32( x ) MSG_ReadFloat( x )
float MSG_ReadFloat( sizebuf_t *msg );
char *MSG_ReadString( sizebuf_t *sb );
float MSG_ReadAngle8( sizebuf_t *msg );
float MSG_ReadAngle16( sizebuf_t *msg );
float MSG_ReadCoord16( sizebuf_t *msg );
double MSG_ReadDouble( sizebuf_t *msg );
char *MSG_ReadStringLine( sizebuf_t *sb );
void MSG_ReadPos( sizebuf_t *sb, vec3_t pos );
void MSG_ReadData( sizebuf_t *sb, void *buffer, size_t size );
void MSG_ReadDeltaUsercmd( sizebuf_t *sb, usercmd_t *from, usercmd_t *cmd );
void MSG_ReadDeltaMovevars( sizebuf_t *sb, movevars_t *from, movevars_t *cmd );
void MSG_ReadDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to );
void MSG_ReadDeltaEntity( sizebuf_t *sb, entity_state_t *from, entity_state_t *to, int number );
// huffman compression
void Huff_Init( void );
void Huff_CompressPacket( sizebuf_t *msg, int offset );
void Huff_DecompressPacket( sizebuf_t *msg, int offset );
void Huff_CompressPacket( bitbuf_t *msg, int offset );
void Huff_DecompressPacket( bitbuf_t *msg, int offset );
/*
==============================================================
@ -297,7 +206,7 @@ typedef struct netchan_s
int last_reliable_sequence; // sequence number of last send
// reliable staging and holding areas
sizebuf_t message; // writing buffer to send to server
bitbuf_t message; // writing buffer to send to server
byte message_buf[MAX_MSGLEN-16]; // leave space for header
// message is copied to this buffer when it is first transfered
@ -313,11 +222,10 @@ typedef struct netchan_s
} netchan_t;
extern netadr_t net_from;
extern sizebuf_t net_message;
extern bitbuf_t net_message;
extern byte net_message_buffer[MAX_MSGLEN];
extern cvar_t *net_speeds;
#define PROTOCOL_VERSION 38
#define PORT_MASTER 27900
#define PORT_CLIENT 27901
#define PORT_SERVER 27910
@ -329,19 +237,10 @@ extern cvar_t *net_speeds;
void Netchan_Init( void );
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport );
bool Netchan_NeedReliable( netchan_t *chan );
void Netchan_Transmit( netchan_t *chan, int length, byte *data );
void Netchan_Transmit( netchan_t *chan, int lengthInBytes, byte *data );
void Netchan_TransmitBits( netchan_t *chan, int lengthInBits, byte *data );
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data );
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, char *format, ... );
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg );
//
// net_encode.c
//
void MSG_DeltaAddEncoder( char *name, pfnDeltaEncode encodeFunc );
int MSG_DeltaFindField( delta_t *pFields, const char *fieldname );
void MSG_DeltaSetField( delta_t *pFields, const char *fieldname );
void MSG_DeltaUnsetField( delta_t *pFields, const char *fieldname );
void MSG_DeltaSetFieldByIndex( struct delta_s *pFields, int fieldNumber );
void MSG_DeltaUnsetFieldByIndex( struct delta_s *pFields, int fieldNumber );
bool Netchan_Process( netchan_t *chan, bitbuf_t *msg );
#endif//NET_MSG_H

56
engine/common/protocol.h Normal file
View File

@ -0,0 +1,56 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// protocol.h - communications protocols
//=======================================================================
#ifndef PROTOCOL_H
#define PROTOCOL_H
#define PROTOCOL_VERSION 38
// server to client
#define svc_bad 0 // immediately crash client when received
// space 1 - 200 it's reserved for user messages
#define svc_nop 201 // end of user messages
#define svc_disconnect 202 // kick client from server
#define svc_reconnect 203 // reconnecting server request
#define svc_stufftext 204 // [string] stuffed into client's console buffer, should be \n terminated
#define svc_serverdata 205 // [long] protocol ...
#define svc_configstring 206 // [short] [string]
#define svc_spawnbaseline 207 // valid only at spawn
#define svc_download 208 // [short] size [size bytes]
#define svc_changing 209 // changelevel by server request
#define svc_physinfo 210 // [physinfo string]
#define svc_usermessage 211 // [string][byte] REG_USER_MSG stuff
#define svc_packetentities 212 // [...]
#define svc_frame 213 // begin a new server frame
#define svc_sound 214 // <see code>
#define svc_ambientsound 215 // <see code>
#define svc_setangle 216 // [float float] set the view angle to this absolute value
#define svc_addangle 217 // [float] add angles when client turn on mover
#define svc_setview 218 // [short] entity number
#define svc_print 219 // [byte] id [string] null terminated string
#define svc_centerprint 220 // [string] to put in center of the screen
#define svc_crosshairangle 221 // [short][short][short]
#define svc_setpause 222 // [byte] 0 = unpaused, 1 = paused
#define svc_movevars 223 // [movevars_t]
#define svc_particle 224 // [float*3][char*3][byte][byte]
#define svc_soundfade 225 // [float*4] sound fade parms
#define svc_bspdecal 226 // [float*3][short][short][short]
#define svc_event 227 // playback event queue
#define svc_event_reliable 228 // playback event directly from message, not queue
#define svc_updateuserinfo 229 // [byte] playernum, [string] userinfo
#define svc_serverinfo 230 // [string] key [string] value
#define svc_clientdata 231 // [...]
// client to server
#define clc_bad 0 // immediately drop client when received
#define clc_nop 1
#define clc_move 2 // [[usercmd_t]
#define clc_delta 3 // [byte] sequence number, requests delta compression of message
#define clc_userinfo 4 // [[userinfo string]
#define clc_stringcmd 5 // [string] message
#define clc_random_seed 6 // [long] random seed
#define msg_end 255 // shared marker for end the message
#endif//PROTOCOL_H

View File

@ -294,10 +294,18 @@ SOURCE=.\common\net_buffer.h
# End Source File
# Begin Source File
SOURCE=.\common\net_encode.h
# End Source File
# Begin Source File
SOURCE=.\common\net_msg.h
# End Source File
# Begin Source File
SOURCE=.\common\protocol.h
# End Source File
# Begin Source File
SOURCE=.\server\server.h
# End Source File
# Begin Source File

View File

@ -765,8 +765,6 @@ Host_Init
*/
void Host_Init( const int argc, const char **argv )
{
char *s;
host.state = HOST_INIT; // initialzation started
host.type = g_Instance();
@ -797,9 +795,6 @@ void Host_Init( const int argc, const char **argv )
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
host_serverstate = Cvar_Get( "host_serverstate", "0", 0, "displays current server state" );
s = va( "Xash3D %i/%g (hw build ^3%i^7)", PROTOCOL_VERSION, SI->version, com_buildnum( ));
Cvar_Get( "version", s, CVAR_INIT, "engine current version" );
// content control
Cvar_Get( "violence_hgibs", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables human gibs" );
Cvar_Get( "violence_agibs", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables alien gibs" );

View File

@ -74,10 +74,10 @@ typedef struct server_s
// the multicast buffer is used to send a message to a set of clients
// it is only used to marshall data until SV_Message is called
sizebuf_t multicast;
bitbuf_t multicast;
byte multicast_buf[MAX_MSGLEN];
sizebuf_t signon;
bitbuf_t signon;
byte signon_buf[MAX_MSGLEN];
bool write_bad_message; // just for debug
@ -86,13 +86,11 @@ typedef struct server_s
typedef struct
{
entity_state_t ps; // player state
int num_entities;
int first_entity; // into the circular sv_packet_entities[]
int senttime; // time the message was transmitted
int latency;
int index; // client edict index
clientdata_t cd; // clientdata
} client_frame_t;
typedef struct sv_client_s
@ -106,6 +104,7 @@ typedef struct sv_client_s
bool sendmovevars;
bool sendinfo;
int random_seed; // fpr predictable random values
int lastframe; // for delta compression
usercmd_t lastcmd; // for filling in big drops
@ -130,12 +129,12 @@ typedef struct sv_client_s
// The reliable buf contain reliable user messages that must be followed
// after pvs frame
sizebuf_t reliable;
bitbuf_t reliable;
byte reliable_buf[MAX_MSGLEN];
// the datagram is written to by sound calls, prints, temp ents, etc.
// it can be harmlessly overflowed.
sizebuf_t datagram;
bitbuf_t datagram;
byte datagram_buf[MAX_MSGLEN];
client_frame_t *frames; // updates can be delta'd from here
@ -207,7 +206,7 @@ typedef struct
// user messages stuff
const char *msg_name; // just for debug
sv_user_message_t msg[MAX_USER_MESSAGES]; // user messages array
int msg_size_index; // write message size at this pos in sizebuf
int msg_size_index; // write message size at this pos in bitbuf
int msg_realsize; // left in bytes
int msg_index; // for debug messages
int msg_dest; // msg destination ( MSG_ONE, MSG_ALL etc )
@ -364,12 +363,12 @@ void SV_GetChallenge( netadr_t from );
void SV_DirectConnect( netadr_t from );
void SV_TogglePause( const char *msg );
void SV_PutClientInServer( edict_t *ent );
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg );
void SV_UpdatePhysinfo( sv_client_t *cl, sizebuf_t *msg );
void SV_FullClientUpdate( sv_client_t *cl, bitbuf_t *msg );
void SV_UpdatePhysinfo( sv_client_t *cl, bitbuf_t *msg );
bool SV_ClientConnect( edict_t *ent, char *userinfo );
void SV_ClientThink( sv_client_t *cl, usercmd_t *cmd );
void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg );
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg );
void SV_ExecuteClientMessage( sv_client_t *cl, bitbuf_t *msg );
void SV_ConnectionlessPacket( netadr_t from, bitbuf_t *msg );
edict_t *SV_FakeConnect( const char *netname );
void SV_PreRunCmd( sv_client_t *cl, usercmd_t *ucmd );
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd );
@ -387,7 +386,7 @@ void SV_Newgame_f( void );
//
// sv_frame.c
//
void SV_WriteFrameToClient( sv_client_t *client, sizebuf_t *msg );
void SV_WriteFrameToClient( sv_client_t *client, bitbuf_t *msg );
void SV_BuildClientFrame( sv_client_t *client );
void SV_InactivateClients( void );
void SV_SendMessagesToAll( void );
@ -407,7 +406,7 @@ void SV_SetModel( edict_t *ent, const char *name );
void SV_CopyTraceToGlobal( trace_t *trace );
void SV_SetMinMaxSize( edict_t *e, const float *min, const float *max );
void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags );
void SV_PlaybackEvent( sizebuf_t *msg, event_info_t *info );
void SV_PlaybackEvent( bitbuf_t *msg, event_info_t *info );
void SV_BaselineForEntity( edict_t *pEdict );
void SV_WriteEntityPatch( const char *filename );
script_t *SV_GetEntityScript( const char *filename );

View File

@ -6,6 +6,8 @@
#include "common.h"
#include "const.h"
#include "server.h"
#include "protocol.h"
#include "net_encode.h"
#define MAX_FORWARD 6
@ -203,8 +205,8 @@ gotnewcl:
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect" );
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport );
MSG_Init( &newcl->reliable, newcl->reliable_buf, sizeof( newcl->reliable_buf )); // reliable buf
MSG_Init( &newcl->datagram, newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf
BF_Init( &newcl->reliable, "Reliable", newcl->reliable_buf, sizeof( newcl->reliable_buf )); // reliable buf
BF_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf
newcl->state = cs_connected;
newcl->lastmessage = svs.realtime;
@ -333,7 +335,7 @@ void SV_DropClient( sv_client_t *drop )
// add the disconnect
if(!( drop->edict && (drop->edict->v.flags & FL_FAKECLIENT )))
MSG_WriteByte( &drop->netchan.message, svc_disconnect );
BF_WriteByte( &drop->netchan.message, svc_disconnect );
// let the game known about client state
if( drop->edict->v.flags & FL_SPECTATOR )
@ -403,9 +405,9 @@ void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
break;
case RD_CLIENT:
if( !sv_client ) return; // client not set
MSG_WriteByte( &sv_client->netchan.message, svc_print );
MSG_WriteByte( &sv_client->netchan.message, PRINT_HIGH );
MSG_WriteString( &sv_client->netchan.message, buf );
BF_WriteByte( &sv_client->netchan.message, svc_print );
BF_WriteByte( &sv_client->netchan.message, PRINT_HIGH );
BF_WriteString( &sv_client->netchan.message, buf );
break;
case RD_NONE:
MsgDev( D_ERROR, "SV_FlushRedirect: %s: invalid destination\n", NET_AdrToString( adr ));
@ -554,14 +556,14 @@ Shift down the remaining args
Redirect all printfs
===============
*/
void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
void SV_RemoteCommand( netadr_t from, bitbuf_t *msg )
{
char remaining[1024];
static char outputbuf[MAX_MSGLEN - 16];
int i;
if(!Rcon_Validate()) MsgDev(D_INFO, "Bad rcon from %s:\n%s\n", NET_AdrToString( from ), msg->data + 4 );
else MsgDev( D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString( from ), msg->data + 4 );
if(!Rcon_Validate()) MsgDev(D_INFO, "Bad rcon from %s:\n%s\n", NET_AdrToString( from ), BF_GetData( msg ) + 4 );
else MsgDev( D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString( from ), BF_GetData( msg ) + 4 );
SV_BeginRedirect( from, RD_PACKET, outputbuf, MAX_MSGLEN - 16, SV_FlushRedirect );
if( !Rcon_Validate( ))
@ -585,33 +587,33 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
===================
SV_FullClientUpdate
Writes all update values to a sizebuf
Writes all update values to a bitbuf
===================
*/
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg )
void SV_FullClientUpdate( sv_client_t *cl, bitbuf_t *msg )
{
int i;
char info[MAX_INFO_STRING];
i = cl - svs.clients;
MSG_WriteByte( msg, svc_updateuserinfo );
MSG_WriteByte( msg, i );
BF_WriteByte( msg, svc_updateuserinfo );
BF_WriteByte( msg, i );
if( cl->name[0] )
{
MSG_WriteByte( msg, true );
BF_WriteByte( msg, true );
com.strncpy( info, cl->userinfo, sizeof( info ));
// remove server passwords, etc.
Info_RemovePrefixedKeys( info, '_' );
MSG_WriteString( msg, info );
BF_WriteString( msg, info );
}
else MSG_WriteByte( msg, false );
else BF_WriteByte( msg, false );
MSG_DirectSend( MSG_ALL, vec3_origin, NULL );
MSG_Clear( msg );
BF_Clear( msg );
}
void SV_RefreshUserinfo( void )
@ -632,14 +634,14 @@ this is send all movevars values when client connected
otherwise see code SV_UpdateMovevars()
===================
*/
void SV_UpdatePhysinfo( sv_client_t *cl, sizebuf_t *msg )
void SV_UpdatePhysinfo( sv_client_t *cl, bitbuf_t *msg )
{
movevars_t nullmovevars;
Mem_Set( &nullmovevars, 0, sizeof( nullmovevars ));
MSG_WriteDeltaMovevars( msg, &nullmovevars, &svgame.movevars );
BF_WriteDeltaMovevars( msg, &nullmovevars, &svgame.movevars );
MSG_DirectSend( MSG_ONE, NULL, cl->edict );
MSG_Clear( msg );
BF_Clear( msg );
}
/*
@ -687,9 +689,9 @@ void SV_PutClientInServer( edict_t *ent )
// NOTE: we needs to setup angles on restore here
if( ent->v.fixangle == 1 )
{
MSG_WriteByte( &sv.multicast, svc_setangle );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[0] );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[1] );
BF_WriteByte( &sv.multicast, svc_setangle );
BF_WriteBitAngle( &sv.multicast, ent->v.angles[0], 16 );
BF_WriteBitAngle( &sv.multicast, ent->v.angles[1], 16 );
MSG_DirectSend( MSG_ONE, vec3_origin, client->edict );
ent->v.fixangle = 0;
}
@ -701,10 +703,10 @@ void SV_PutClientInServer( edict_t *ent )
if( !( ent->v.flags & FL_FAKECLIENT ))
{
// copy signon buffer
MSG_WriteData( &client->netchan.message, sv.signon.data, sv.signon.cursize );
BF_WriteBits( &client->netchan.message, BF_GetData( &sv.signon ), BF_GetNumBitsWritten( &sv.signon ));
MSG_WriteByte( &client->netchan.message, svc_setview );
MSG_WriteWord( &client->netchan.message, NUM_FOR_EDICT( client->edict ));
BF_WriteByte( &client->netchan.message, svc_setview );
BF_WriteWord( &client->netchan.message, NUM_FOR_EDICT( client->edict ));
MSG_Send( MSG_ONE, NULL, client->edict );
}
@ -728,8 +730,8 @@ void SV_TogglePause( const char *msg )
if( msg ) SV_BroadcastPrintf( PRINT_HIGH, "%s", msg );
// send notification to all clients
MSG_Begin( svc_setpause );
MSG_WriteByte( &sv.multicast, sv.paused );
BF_WriteByte( &sv.multicast, svc_setpause );
BF_WriteByte( &sv.multicast, sv.paused );
MSG_Send( MSG_ALL, vec3_origin, NULL );
}
@ -762,14 +764,14 @@ void SV_New_f( sv_client_t *cl )
playernum = cl - svs.clients;
// send the serverdata
MSG_WriteByte( &cl->netchan.message, svc_serverdata );
MSG_WriteLong( &cl->netchan.message, PROTOCOL_VERSION );
MSG_WriteLong( &cl->netchan.message, svs.spawncount );
MSG_WriteByte( &cl->netchan.message, playernum );
MSG_WriteByte( &cl->netchan.message, svgame.globals->maxClients );
MSG_WriteWord( &cl->netchan.message, svgame.globals->maxEntities );
MSG_WriteString( &cl->netchan.message, sv.configstrings[CS_NAME] );
MSG_WriteString( &cl->netchan.message, STRING( EDICT_NUM( 0 )->v.message )); // Map Message
BF_WriteByte( &cl->netchan.message, svc_serverdata );
BF_WriteLong( &cl->netchan.message, PROTOCOL_VERSION );
BF_WriteLong( &cl->netchan.message, svs.spawncount );
BF_WriteByte( &cl->netchan.message, playernum );
BF_WriteByte( &cl->netchan.message, svgame.globals->maxClients );
BF_WriteWord( &cl->netchan.message, svgame.globals->maxEntities );
BF_WriteString( &cl->netchan.message, sv.configstrings[CS_NAME] );
BF_WriteString( &cl->netchan.message, STRING( EDICT_NUM( 0 )->v.message )); // Map Message
// refresh userinfo on spawn
SV_RefreshUserinfo();
@ -784,8 +786,8 @@ void SV_New_f( sv_client_t *cl )
Mem_Set( &cl->lastcmd, 0, sizeof( cl->lastcmd ));
// begin fetching configstrings
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, va( "cmd configstrings %i %i\n", svs.spawncount, 0 ));
BF_WriteByte( &cl->netchan.message, svc_stufftext );
BF_WriteString( &cl->netchan.message, va( "cmd configstrings %i %i\n", svs.spawncount, 0 ));
}
}
@ -816,13 +818,13 @@ void SV_Configstrings_f( sv_client_t *cl )
start = com.atoi( Cmd_Argv( 2 ));
// write a packet full of data
while( cl->netchan.message.cursize < (MAX_MSGLEN / 2) && start < MAX_CONFIGSTRINGS )
while( BF_GetNumBytesWritten( &cl->netchan.message ) < ( MAX_MSGLEN / 2 ) && start < MAX_CONFIGSTRINGS )
{
if( sv.configstrings[start][0] )
{
MSG_WriteByte( &cl->netchan.message, svc_configstring );
MSG_WriteShort( &cl->netchan.message, start );
MSG_WriteString( &cl->netchan.message, sv.configstrings[start] );
BF_WriteByte( &cl->netchan.message, svc_configstring );
BF_WriteShort( &cl->netchan.message, start );
BF_WriteString( &cl->netchan.message, sv.configstrings[start] );
}
start++;
}
@ -831,8 +833,8 @@ void SV_Configstrings_f( sv_client_t *cl )
else com.snprintf( cmd, MAX_STRING, "cmd configstrings %i %i\n", svs.spawncount, start );
// send next command
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, cmd );
BF_WriteByte( &cl->netchan.message, svc_stufftext );
BF_WriteString( &cl->netchan.message, cmd );
}
/*
@ -863,15 +865,15 @@ void SV_UserMessages_f( sv_client_t *cl )
start = com.atoi( Cmd_Argv( 2 ));
// write a packet full of data
while( cl->netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_USER_MESSAGES )
while( BF_GetNumBytesWritten( &cl->netchan.message ) < ( MAX_MSGLEN / 2 ) && start < MAX_USER_MESSAGES )
{
message = &svgame.msg[start];
if( message->name[0] )
{
MSG_WriteByte( &cl->netchan.message, svc_usermessage );
MSG_WriteString( &cl->netchan.message, message->name );
MSG_WriteByte( &cl->netchan.message, message->number );
MSG_WriteByte( &cl->netchan.message, (byte)message->size );
BF_WriteByte( &cl->netchan.message, svc_usermessage );
BF_WriteString( &cl->netchan.message, message->name );
BF_WriteByte( &cl->netchan.message, message->number );
BF_WriteByte( &cl->netchan.message, (byte)message->size );
}
start++;
}
@ -880,8 +882,8 @@ void SV_UserMessages_f( sv_client_t *cl )
else com.snprintf( cmd, MAX_STRING, "cmd usermsgs %i %i\n", svs.spawncount, start );
// send next command
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, cmd );
BF_WriteByte( &cl->netchan.message, svc_stufftext );
BF_WriteString( &cl->netchan.message, cmd );
}
/*
@ -914,13 +916,13 @@ void SV_Baselines_f( sv_client_t *cl )
Mem_Set( &nullstate, 0, sizeof( nullstate ));
// write a packet full of data
while( cl->netchan.message.cursize < MAX_MSGLEN / 2 && start < svgame.globals->numEntities )
while( BF_GetNumBytesWritten( &cl->netchan.message ) < ( MAX_MSGLEN / 2 ) && start < svgame.globals->numEntities )
{
base = &svs.baselines[start];
if( base->modelindex || base->effects )
{
MSG_WriteByte( &cl->netchan.message, svc_spawnbaseline );
MSG_WriteDeltaEntity( &nullstate, base, &cl->netchan.message, true, true );
BF_WriteByte( &cl->netchan.message, svc_spawnbaseline );
MSG_WriteDeltaEntity( &nullstate, base, &cl->netchan.message, true, sv.time );
}
start++;
}
@ -929,8 +931,8 @@ void SV_Baselines_f( sv_client_t *cl )
else com.snprintf( cmd, MAX_STRING, "cmd baselines %i %i\n", svs.spawncount, start );
// send next command
MSG_WriteByte( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, cmd );
BF_WriteByte( &cl->netchan.message, svc_stufftext );
BF_WriteString( &cl->netchan.message, cmd );
}
/*
@ -954,8 +956,8 @@ void SV_Begin_f( sv_client_t *cl )
// if we are paused, tell the client
if( sv.paused )
{
MSG_Begin( svc_setpause );
MSG_WriteByte( &sv.multicast, sv.paused );
BF_WriteByte( &sv.multicast, svc_setpause );
BF_WriteByte( &sv.multicast, sv.paused );
MSG_Send( MSG_ONE, vec3_origin, cl->edict );
SV_ClientPrintf( cl, PRINT_HIGH, "Server is paused.\n" );
}
@ -976,15 +978,15 @@ void SV_NextDownload_f( sv_client_t *cl )
r = cl->downloadsize - cl->downloadcount;
if( r > 1024 ) r = 1024;
MSG_WriteByte( &cl->netchan.message, svc_download );
MSG_WriteShort( &cl->netchan.message, r );
BF_WriteByte( &cl->netchan.message, svc_download );
BF_WriteShort( &cl->netchan.message, r );
cl->downloadcount += r;
size = cl->downloadsize;
if( !size ) size = 1;
percent = cl->downloadcount * 100 / size;
MSG_WriteByte( &cl->netchan.message, percent );
MSG_WriteData( &cl->netchan.message, cl->download + cl->downloadcount - r, r );
BF_WriteByte( &cl->netchan.message, percent );
BF_WriteBytes( &cl->netchan.message, cl->download + cl->downloadcount - r, r );
if( cl->downloadcount == cl->downloadsize ) cl->download = NULL;
}
@ -1008,9 +1010,9 @@ void SV_BeginDownload_f( sv_client_t *cl )
{
MsgDev( D_ERROR, "SV_BeginDownload_f: couldn't download %s to %s\n", name, cl->name );
if( cl->download ) Mem_Free( cl->download );
MSG_WriteByte( &cl->netchan.message, svc_download );
MSG_WriteShort( &cl->netchan.message, -1 );
MSG_WriteByte( &cl->netchan.message, 0 );
BF_WriteByte( &cl->netchan.message, svc_download );
BF_WriteShort( &cl->netchan.message, -1 );
BF_WriteByte( &cl->netchan.message, 0 );
cl->download = NULL;
return;
}
@ -1186,19 +1188,6 @@ void SV_ExecuteClientCommand( sv_client_t *cl, char *s )
}
}
/*
=================
MSG_Begin
Misc helper function
=================
*/
void _MSG_Begin( int dest, const char *filename, int fileline )
{
_MSG_WriteBits( &sv.multicast, dest, "MSG_Begin", NET_BYTE, filename, fileline );
}
/*
=================
SV_Send
@ -1227,11 +1216,11 @@ bool _MSG_Send( int dest, const vec3_t origin, const edict_t *ent, bool direct,
if( sv.state == ss_loading )
{
// copy signon buffer
MSG_WriteData( &sv.signon, sv.multicast.data, sv.multicast.cursize );
MSG_Clear( &sv.multicast );
BF_WriteBits( &sv.signon, BF_GetData( &sv.multicast ), BF_GetNumBitsWritten( &sv.multicast ));
BF_Clear( &sv.multicast );
return true;
}
// intentional fallthrough (in-game MSG_INIT it's a MSG_ALL reliable)
// intentional fallthrough (in-game BF_INIT it's a BF_ALL reliable)
case MSG_ALL:
reliable = true;
// intentional fallthrough
@ -1295,21 +1284,21 @@ bool _MSG_Send( int dest, const vec3_t origin, const edict_t *ent, bool direct,
if( reliable )
{
if( direct ) MSG_WriteData( &cl->netchan.message, sv.multicast.data, sv.multicast.cursize );
else MSG_WriteData( &cl->reliable, sv.multicast.data, sv.multicast.cursize );
if( direct ) BF_WriteBits( &cl->netchan.message, BF_GetData( &sv.multicast ), BF_GetNumBitsWritten( &sv.multicast ));
else BF_WriteBits( &cl->reliable, BF_GetData( &sv.multicast ), BF_GetNumBitsWritten( &sv.multicast ));
}
else MSG_WriteData( &cl->datagram, sv.multicast.data, sv.multicast.cursize );
else BF_WriteBits( &cl->datagram, BF_GetData( &sv.multicast ), BF_GetNumBitsWritten( &sv.multicast ));
numsends++;
}
MSG_Clear( &sv.multicast );
BF_Clear( &sv.multicast );
// 25% chanse for simulate random network bugs
if( sv.write_bad_message && Com_RandomLong( 0, 32 ) <= 8 )
{
// just for network debugging (send only for local client)
MSG_WriteByte( &sv.multicast, svc_bad );
MSG_WriteLong( &sv.multicast, rand( )); // send some random data
MSG_WriteString( &sv.multicast, host.finalmsg ); // send final message
BF_WriteByte( &sv.multicast, svc_bad );
BF_WriteLong( &sv.multicast, rand( )); // send some random data
BF_WriteString( &sv.multicast, host.finalmsg ); // send final message
MSG_Send( MSG_ALL, vec3_origin, NULL );
sv.write_bad_message = false;
}
@ -1326,15 +1315,15 @@ Clients that are in the game can still send
connectionless packets.
=================
*/
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
void SV_ConnectionlessPacket( netadr_t from, bitbuf_t *msg )
{
char *s;
char *c;
MSG_BeginReading( msg );
MSG_ReadLong( msg );// skip the -1 marker
BF_Clear( msg );
BF_ReadLong( msg );// skip the -1 marker
s = MSG_ReadStringLine( msg );
s = BF_ReadStringLine( msg );
Cmd_TokenizeString( s );
c = Cmd_Argv( 0 );
@ -1357,13 +1346,13 @@ SV_SetIdealPitch
*/
void SV_SetIdealPitch( sv_client_t *cl )
{
float angleval, sinval, cosval;
trace_t tr;
vec3_t top, bottom;
float z[MAX_FORWARD];
int i, j;
int step, dir, steps;
edict_t *ent = cl->edict;
float angleval, sinval, cosval;
trace_t tr;
vec3_t top, bottom;
float z[MAX_FORWARD];
int i, j;
int step, dir, steps;
edict_t *ent = cl->edict;
if( !( ent->v.flags & FL_ONGROUND ))
return;
@ -1428,15 +1417,15 @@ On very fast clients, there may be multiple usercmd packed into
each of the backup packets.
==================
*/
static void SV_ReadClientMove( sv_client_t *cl, sizebuf_t *msg )
static void SV_ReadClientMove( sv_client_t *cl, bitbuf_t *msg )
{
int checksum1, checksum2;
int key, lastframe, net_drop;
int key, lastframe, net_drop, size;
usercmd_t oldest, oldcmd, newcmd, nulcmd;
key = msg->readcount;
checksum1 = MSG_ReadByte( msg );
lastframe = MSG_ReadLong( msg );
key = BF_GetNumBytesRead( msg );
checksum1 = BF_ReadByte( msg );
lastframe = BF_ReadLong( msg );
if( lastframe != cl->lastframe )
{
@ -1462,7 +1451,8 @@ static void SV_ReadClientMove( sv_client_t *cl, sizebuf_t *msg )
}
// if the checksum fails, ignore the rest of the packet
checksum2 = CRC_Sequence( msg->data + key + 1, msg->readcount - key - 1, cl->netchan.incoming_sequence );
size = BF_GetNumBytesRead( msg ) - key - 1;
checksum2 = CRC_Sequence( BF_GetData( msg ) + key + 1, size, cl->netchan.incoming_sequence );
if( checksum2 != checksum1 )
{
MsgDev( D_ERROR, "SV_UserMove: failed command checksum for %s (%d != %d)\n", cl->name, checksum2, checksum1 );
@ -1503,7 +1493,7 @@ SV_ExecuteClientMessage
Parse a client packet
===================
*/
void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
void SV_ExecuteClientMessage( sv_client_t *cl, bitbuf_t *msg )
{
int c, stringCmdCount = 0;
bool move_issued = false;
@ -1521,22 +1511,25 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
// read optional clientCommand strings
while( cl->state != cs_zombie )
{
c = MSG_ReadByte( msg );
if( c == -1 ) break;
if( msg->error )
if( BF_CheckOverflow( msg ))
{
MsgDev( D_ERROR, "SV_ReadClientMessage: clc_bad\n" );
SV_DropClient( cl );
return;
}
}
// end of message
if( BF_GetNumBitsLeft( msg ) < 8 )
break;
c = BF_ReadByte( msg );
switch( c )
{
case clc_nop:
break;
case clc_userinfo:
SV_UserinfoChanged( cl, MSG_ReadString( msg ));
SV_UserinfoChanged( cl, BF_ReadString( msg ));
break;
case clc_move:
if( move_issued ) return; // someone is trying to cheat...
@ -1544,11 +1537,14 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
SV_ReadClientMove( cl, msg );
break;
case clc_stringcmd:
s = MSG_ReadString( msg );
s = BF_ReadString( msg );
// malicious users may try using too many string commands
if( ++stringCmdCount < 8 ) SV_ExecuteClientCommand( cl, s );
if( cl->state == cs_zombie ) return; // disconnect command
break;
case clc_random_seed:
cl->random_seed = BF_ReadUBitLong( msg, 32 );
break;
default:
MsgDev( D_ERROR, "SV_ReadClientMessage: clc_bad\n" );
SV_DropClient( cl );

View File

@ -5,6 +5,7 @@
#include "common.h"
#include "server.h"
#include "protocol.h"
#include "byteorder.h"
sv_client_t *sv_client; // current client
@ -31,9 +32,9 @@ void SV_ClientPrintf( sv_client_t *cl, int level, char *fmt, ... )
com.vsprintf( string, fmt, argptr );
va_end( argptr );
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, level );
MSG_WriteString( &cl->netchan.message, string );
BF_WriteByte( &cl->netchan.message, svc_print );
BF_WriteByte( &cl->netchan.message, level );
BF_WriteString( &cl->netchan.message, string );
}
/*
@ -62,9 +63,9 @@ void SV_BroadcastPrintf( int level, char *fmt, ... )
if( cl->state != cs_spawned ) continue;
if( cl->edict && (cl->edict->v.flags & FL_FAKECLIENT ))
continue;
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, level );
MSG_WriteString( &cl->netchan.message, string );
BF_WriteByte( &cl->netchan.message, svc_print );
BF_WriteByte( &cl->netchan.message, level );
BF_WriteString( &cl->netchan.message, string );
}
}
@ -85,8 +86,8 @@ void SV_BroadcastCommand( char *fmt, ... )
com.vsprintf( string, fmt, argptr );
va_end( argptr );
MSG_Begin( svc_stufftext );
MSG_WriteString( &sv.multicast, string );
BF_WriteByte( &sv.multicast, svc_stufftext );
BF_WriteString( &sv.multicast, string );
MSG_Send( MSG_ALL, NULL, NULL );
}

View File

@ -6,6 +6,8 @@
#include "common.h"
#include "server.h"
#include "const.h"
#include "protocol.h"
#include "net_encode.h"
#define MAX_VISIBLE_PACKET 1024
typedef struct
@ -51,14 +53,14 @@ SV_EmitPacketEntities
Writes a delta update of an entity_state_t list to the message->
=============
*/
void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t *msg )
void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, bitbuf_t *msg )
{
entity_state_t *oldent, *newent;
int oldindex, newindex;
int oldnum, newnum;
int from_num_entities;
MSG_WriteByte( msg, svc_packetentities );
BF_WriteByte( msg, svc_packetentities );
if( !from ) from_num_entities = 0;
else from_num_entities = from->num_entities;
@ -95,7 +97,7 @@ void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t
// delta update from old position
// because the force parm is false, this will not result
// in any bytes being emited if the entity has not changed at all
MSG_WriteDeltaEntity( oldent, newent, msg, false, ( newent->number <= sv_maxclients->integer ));
MSG_WriteDeltaEntity( oldent, newent, msg, false, sv.time );
oldindex++;
newindex++;
continue;
@ -104,7 +106,7 @@ void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t
if( newnum < oldnum )
{
// this is a new entity, send it from the baseline
MSG_WriteDeltaEntity( &svs.baselines[newnum], newent, msg, true, true );
MSG_WriteDeltaEntity( &svs.baselines[newnum], newent, msg, true, sv.time );
newindex++;
continue;
}
@ -112,12 +114,12 @@ void SV_EmitPacketEntities( client_frame_t *from, client_frame_t *to, sizebuf_t
if( newnum > oldnum )
{
// remove from message
MSG_WriteDeltaEntity( oldent, NULL, msg, false, false );
MSG_WriteDeltaEntity( oldent, NULL, msg, false, sv.time );
oldindex++;
continue;
}
}
MSG_WriteBits( msg, 0, "svc_packetentities", NET_WORD ); // end of packetentities
BF_WriteWord( msg, 0 ); // end of packetentities
}
static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_frame_t *frame, sv_ents_t *ents, bool portal )
@ -207,7 +209,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
}
}
static void SV_EmitEvents( sv_client_t *cl, client_frame_t *frame, sizebuf_t *msg )
static void SV_EmitEvents( sv_client_t *cl, client_frame_t *frame, bitbuf_t *msg )
{
int i, ev;
event_state_t *es;
@ -232,8 +234,8 @@ static void SV_EmitEvents( sv_client_t *cl, client_frame_t *frame, sizebuf_t *ms
if( ev_count >= MAX_EVENT_QUEUE )
ev_count = MAX_EVENT_QUEUE - 1;
MSG_WriteByte( msg, svc_event ); // create message
MSG_WriteByte( msg, ev_count ); // Up to MAX_EVENT_QUEUE events
BF_WriteByte( msg, svc_event ); // create message
BF_WriteByte( msg, ev_count ); // Up to MAX_EVENT_QUEUE events
for( i = c = 0 ; i < MAX_EVENT_QUEUE; i++ )
{
@ -251,12 +253,36 @@ static void SV_EmitEvents( sv_client_t *cl, client_frame_t *frame, sizebuf_t *ms
}
}
/*
=============
SV_WriteClientData
=============
*/
void SV_WriteClientData( client_frame_t *from, client_frame_t *to, bitbuf_t *msg )
{
clientdata_t *cd, *ocd;
clientdata_t dummy;
cd = &to->cd;
if( !from )
{
Mem_Set( &dummy, 0, sizeof( dummy ));
ocd = &dummy;
}
else ocd = &from->cd;
BF_WriteByte( msg, svc_clientdata );
MSG_WriteClientData( msg, ocd, cd, sv.time );
}
/*
==================
SV_WriteFrameToClient
==================
*/
void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
void SV_WriteFrameToClient( sv_client_t *cl, bitbuf_t *msg )
{
client_frame_t *frame, *oldframe;
int lastframe;
@ -294,22 +320,24 @@ void SV_WriteFrameToClient( sv_client_t *cl, sizebuf_t *msg )
if( cl->physinfo_modified )
{
cl->physinfo_modified = false;
MSG_WriteByte( msg, svc_physinfo );
MSG_WriteString( msg, cl->physinfo );
BF_WriteByte( msg, svc_physinfo );
BF_WriteString( msg, cl->physinfo );
}
// delta encode the events
SV_EmitEvents( cl, frame, msg );
MSG_WriteByte( msg, svc_frame );
MSG_WriteLong( msg, sv.framenum );
MSG_WriteLong( msg, sv.time ); // send a servertime each frame
MSG_WriteLong( msg, lastframe ); // what we are delta'ing from
MSG_WriteByte( msg, sv.frametime );
MSG_WriteByte( msg, cl->surpressCount ); // rate dropped packets
MSG_WriteByte( msg, frame->index ); // send a client index
BF_WriteByte( msg, svc_frame );
BF_WriteLong( msg, sv.framenum );
BF_WriteLong( msg, sv.time ); // send a servertime each frame
BF_WriteLong( msg, lastframe ); // what we are delta'ing from
BF_WriteByte( msg, sv.frametime );
BF_WriteByte( msg, cl->surpressCount ); // rate dropped packets
cl->surpressCount = 0;
// delta encode the clientdata
SV_WriteClientData( oldframe, frame, msg );
// delta encode the entities
SV_EmitPacketEntities( oldframe, frame, msg );
}
@ -352,15 +380,15 @@ void SV_BuildClientFrame( sv_client_t *cl )
switch( clent->v.fixangle )
{
case 1:
MSG_WriteByte( &sv.multicast, svc_setangle );
MSG_WriteAngle32( &sv.multicast, clent->v.angles[0] );
MSG_WriteAngle32( &sv.multicast, clent->v.angles[1] );
BF_WriteByte( &sv.multicast, svc_setangle );
BF_WriteBitAngle( &sv.multicast, clent->v.angles[0], 16 );
BF_WriteBitAngle( &sv.multicast, clent->v.angles[1], 16 );
MSG_DirectSend( MSG_ONE, vec3_origin, clent );
clent->pvServerData->s.ed_flags |= ESF_NO_PREDICTION;
break;
case 2:
MSG_WriteByte( &sv.multicast, svc_addangle );
MSG_WriteAngle32( &sv.multicast, cl->addangle );
BF_WriteByte( &sv.multicast, svc_addangle );
BF_WriteBitAngle( &sv.multicast, cl->addangle, 16 );
MSG_DirectSend( MSG_ONE, vec3_origin, clent );
cl->addangle = 0;
break;
@ -376,8 +404,8 @@ void SV_BuildClientFrame( sv_client_t *cl )
frame_ents.num_entities = c_fullsend = 0;
if( !clent->pvServerData->client ) return; // not in game yet
// grab the current player index
frame->index = NUM_FOR_EDICT( clent );
// update clientdata_t
svgame.dllFuncs.pfnUpdateClientData( clent, false, &frame->cd );
// add all the entities directly visible to the eye, which
// may include portal entities that merge other viewpoints
@ -423,12 +451,12 @@ SV_SendClientDatagram
*/
bool SV_SendClientDatagram( sv_client_t *cl )
{
byte msg_buf[MAX_MSGLEN];
sizebuf_t msg;
byte msg_buf[MAX_MSGLEN];
bitbuf_t msg;
SV_BuildClientFrame( cl );
MSG_Init( &msg, msg_buf, sizeof( msg_buf ));
BF_Init( &msg, "Datagram", msg_buf, sizeof( msg_buf ));
// send over all the relevant entity_state_t
// and the player state
@ -438,37 +466,37 @@ bool SV_SendClientDatagram( sv_client_t *cl )
// for this client out to the message
// it is necessary for this to be after the WriteEntities
// so that entity references will be current
if( cl->reliable.overflowed ) MsgDev( D_ERROR, "reliable datagram overflowed for %s\n", cl->name );
else MSG_WriteData( &msg, cl->reliable.data, cl->reliable.cursize );
MSG_Clear( &cl->reliable );
if( BF_CheckOverflow( &cl->reliable )) MsgDev( D_ERROR, "reliable datagram overflowed for %s\n", cl->name );
else BF_WriteBits( &msg, BF_GetData( &cl->reliable ), BF_GetNumBitsWritten( &cl->reliable ));
BF_Clear( &cl->reliable );
if( msg.overflowed )
if( BF_CheckOverflow( &msg ))
{
// must have room left for the packet header
MsgDev( D_WARN, "msg overflowed for %s\n", cl->name );
MSG_Clear( &msg );
BF_Clear( &msg );
}
// copy the accumulated multicast datagram
// for this client out to the message
// it is necessary for this to be after the WriteEntities
// so that entity references will be current
if( cl->datagram.overflowed ) MsgDev( D_WARN, "datagram overflowed for %s\n", cl->name );
else MSG_WriteData( &msg, cl->datagram.data, cl->datagram.cursize );
MSG_Clear( &cl->datagram );
if( BF_CheckOverflow( &cl->datagram )) MsgDev( D_WARN, "datagram overflowed for %s\n", cl->name );
else BF_WriteBits( &msg, BF_GetData( &cl->datagram ), BF_GetNumBitsWritten( &cl->datagram ));
BF_Clear( &cl->datagram );
if( msg.overflowed )
if( BF_CheckOverflow( &msg ))
{
// must have room left for the packet header
MsgDev( D_WARN, "msg overflowed for %s\n", cl->name );
MSG_Clear( &msg );
BF_Clear( &msg );
}
// send the datagram
Netchan_Transmit( &cl->netchan, msg.cursize, msg.data );
Netchan_TransmitBits( &cl->netchan, BF_GetNumBitsWritten( &msg ), BF_GetData( &msg ));
// record the size for rate estimation
cl->message_size[sv.framenum % RATE_MESSAGES] = msg.cursize;
cl->message_size[sv.framenum % RATE_MESSAGES] = BF_GetNumBytesWritten( &msg );
return true;
}
@ -540,11 +568,11 @@ void SV_SendClientMessages( void )
}
// if the reliable message overflowed, drop the client
if( cl->netchan.message.overflowed )
if( BF_CheckOverflow( &cl->netchan.message ))
{
MSG_Clear( &cl->netchan.message );
MSG_Clear( &cl->reliable );
MSG_Clear( &cl->datagram );
BF_Clear( &cl->netchan.message );
BF_Clear( &cl->reliable );
BF_Clear( &cl->datagram );
SV_BroadcastPrintf( PRINT_HIGH, "%s overflowed\n", cl->name );
SV_DropClient( cl );
cl->send_message = true;
@ -561,7 +589,7 @@ void SV_SendClientMessages( void )
}
else
{
if( cl->netchan.message.cursize || svs.realtime - cl->netchan.last_sent > 1000 )
if( BF_GetNumBytesWritten( &cl->netchan.message ) || svs.realtime - cl->netchan.last_sent > 1000 )
Netchan_Transmit( &cl->netchan, 0, NULL );
}
// yes, message really sended
@ -619,6 +647,6 @@ void SV_InactivateClients( void )
svs.clients[i].state = cs_connected;
// clear netchan message (but keep other buffers)
MSG_Clear( &cl->netchan.message );
BF_Clear( &cl->netchan.message );
}
}

View File

@ -5,7 +5,9 @@
#include "common.h"
#include "server.h"
#include "protocol.h"
#include "net_sound.h"
#include "net_encode.h"
#include "byteorder.h"
#include "matrix_lib.h"
#include "pm_defs.h"
@ -153,10 +155,10 @@ void SV_ConfigString( int index, const char *val )
if( sv.state != ss_loading )
{
// send the update to everyone
MSG_Clear( &sv.multicast );
MSG_Begin( svc_configstring );
MSG_WriteShort( &sv.multicast, index );
MSG_WriteString( &sv.multicast, val );
BF_Clear( &sv.multicast );
BF_WriteByte( &sv.multicast, svc_configstring );
BF_WriteShort( &sv.multicast, index );
BF_WriteString( &sv.multicast, val );
MSG_Send( MSG_ALL, vec3_origin, NULL );
}
}
@ -166,13 +168,13 @@ void SV_CreateDecal( const float *origin, int decalIndex, int entityIndex, int m
ASSERT( origin );
// static decals are posters, it's always reliable
MSG_WriteByte( &sv.multicast, svc_bspdecal );
MSG_WritePos( &sv.multicast, origin );
MSG_WriteWord( &sv.multicast, decalIndex );
MSG_WriteShort( &sv.multicast, entityIndex );
BF_WriteByte( &sv.multicast, svc_bspdecal );
BF_WriteBitVec3Coord( &sv.multicast, origin );
BF_WriteWord( &sv.multicast, decalIndex );
BF_WriteShort( &sv.multicast, entityIndex );
if( entityIndex > 0 )
MSG_WriteWord( &sv.multicast, modelIndex );
MSG_WriteByte( &sv.multicast, flags );
BF_WriteWord( &sv.multicast, modelIndex );
BF_WriteByte( &sv.multicast, flags );
MSG_Send( MSG_INIT, NULL, NULL );
}
@ -505,7 +507,7 @@ void SV_FreeEdicts( void )
}
}
void SV_PlaybackEvent( sizebuf_t *msg, event_info_t *info )
void SV_PlaybackEvent( bitbuf_t *msg, event_info_t *info )
{
event_args_t nullargs;
@ -514,8 +516,8 @@ void SV_PlaybackEvent( sizebuf_t *msg, event_info_t *info )
Mem_Set( &nullargs, 0, sizeof( nullargs ));
MSG_WriteWord( msg, info->index ); // send event index
MSG_WriteWord( msg, (int)( info->fire_time * 100.0f )); // send event delay
BF_WriteWord( msg, info->index ); // send event index
BF_WriteWord( msg, (int)( info->fire_time * 100.0f )); // send event delay
MSG_WriteDeltaEvent( msg, &nullargs, &info->args ); // FIXME: zero-compressing
}
@ -616,8 +618,8 @@ void SV_BaselineForEntity( edict_t *pEdict )
entity_state_t nullstate;
Mem_Set( &nullstate, 0, sizeof( nullstate ));
MSG_WriteByte( &sv.multicast, svc_spawnbaseline );
MSG_WriteDeltaEntity( &nullstate, &sv_ent->s, &sv.multicast, true, true );
BF_WriteByte( &sv.multicast, svc_spawnbaseline );
MSG_WriteDeltaEntity( &nullstate, &sv_ent->s, &sv.multicast, true, sv.time );
MSG_DirectSend( MSG_ALL, vec3_origin, NULL );
}
}
@ -757,6 +759,7 @@ int pfnModelIndex( const char *m )
{
int index;
if( !m || !m[0] ) return 0;
index = SV_FindIndex( m, CS_MODELS, MAX_MODELS, false );
if( !index ) MsgDev( D_WARN, "SV_ModelIndex: %s not precached\n", m );
@ -1436,17 +1439,17 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
entityIndex = ent->v.aiment->serialnumber;
else entityIndex = ent->serialnumber;
MSG_Begin( svc_sound );
MSG_WriteWord( &sv.multicast, flags );
MSG_WriteWord( &sv.multicast, sound_idx );
MSG_WriteByte( &sv.multicast, chan );
BF_WriteByte( &sv.multicast, svc_sound );
BF_WriteWord( &sv.multicast, flags );
BF_WriteWord( &sv.multicast, sound_idx );
BF_WriteByte( &sv.multicast, chan );
if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 );
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
if( flags & SND_VOLUME ) BF_WriteByte( &sv.multicast, vol * 255 );
if( flags & SND_ATTENUATION ) BF_WriteByte( &sv.multicast, attn * 64 );
if( flags & SND_PITCH ) BF_WriteByte( &sv.multicast, pitch );
MSG_WriteWord( &sv.multicast, entityIndex );
if( flags & SND_FIXED_ORIGIN ) MSG_WritePos( &sv.multicast, origin );
BF_WriteWord( &sv.multicast, entityIndex );
if( flags & SND_FIXED_ORIGIN ) BF_WriteBitVec3Coord( &sv.multicast, origin );
MSG_Send( msg_dest, origin, NULL );
}
@ -1519,18 +1522,18 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vo
sound_idx = SV_SoundIndex( sample );
}
MSG_Begin( svc_ambientsound );
MSG_WriteWord( &sv.multicast, flags );
MSG_WriteWord( &sv.multicast, sound_idx );
MSG_WriteByte( &sv.multicast, CHAN_AUTO );
BF_WriteByte( &sv.multicast, svc_ambientsound );
BF_WriteWord( &sv.multicast, flags );
BF_WriteWord( &sv.multicast, sound_idx );
BF_WriteByte( &sv.multicast, CHAN_AUTO );
if( flags & SND_VOLUME ) MSG_WriteByte( &sv.multicast, vol * 255 );
if( flags & SND_ATTENUATION ) MSG_WriteByte( &sv.multicast, attn * 64 );
if( flags & SND_PITCH ) MSG_WriteByte( &sv.multicast, pitch );
if( flags & SND_VOLUME ) BF_WriteByte( &sv.multicast, vol * 255 );
if( flags & SND_ATTENUATION ) BF_WriteByte( &sv.multicast, attn * 64 );
if( flags & SND_PITCH ) BF_WriteByte( &sv.multicast, pitch );
// plays from fixed position
MSG_WriteWord( &sv.multicast, number );
MSG_WritePos( &sv.multicast, pos );
BF_WriteWord( &sv.multicast, number );
BF_WriteBitVec3Coord( &sv.multicast, pos );
MSG_Send( msg_dest, origin, NULL );
}
@ -1826,8 +1829,8 @@ void pfnClientCommand( edict_t* pEdict, char* szFmt, ... )
if( SV_IsValidCmd( buffer ))
{
MSG_WriteByte( &sv.multicast, svc_stufftext );
MSG_WriteString( &sv.multicast, buffer );
BF_WriteByte( &sv.multicast, svc_stufftext );
BF_WriteString( &sv.multicast, buffer );
MSG_Send( MSG_ONE, NULL, client->edict );
}
else MsgDev( D_ERROR, "Tried to stuff bad command %s\n", buffer );
@ -1851,16 +1854,16 @@ void pfnParticleEffect( const float *org, const float *dir, float color, float c
return;
}
MSG_WriteByte( &sv.multicast, svc_particle );
MSG_WritePos( &sv.multicast, org );
BF_WriteByte( &sv.multicast, svc_particle );
BF_WriteBitVec3Coord( &sv.multicast, org );
for( i = 0; i < 3; i++ )
{
v = bound( -128, dir[i] * 16, 127 );
MSG_WriteChar( &sv.multicast, v );
BF_WriteChar( &sv.multicast, v );
}
MSG_WriteByte( &sv.multicast, count );
MSG_WriteByte( &sv.multicast, color );
BF_WriteByte( &sv.multicast, count );
BF_WriteByte( &sv.multicast, color );
MSG_Send( MSG_ALL, org, NULL );
}
@ -1923,7 +1926,7 @@ void pfnMessageBegin( int msg_dest, int msg_num, const float *pOrigin, edict_t *
svgame.msg_name = svgame.msg[svgame.msg_index].name;
else svgame.msg_name = NULL;
MSG_Begin( svgame.msg_index );
BF_WriteByte( &sv.multicast, svgame.msg_index );
// save message destination
if( pOrigin ) VectorCopy( pOrigin, svgame.msg_org );
@ -1932,8 +1935,8 @@ void pfnMessageBegin( int msg_dest, int msg_num, const float *pOrigin, edict_t *
if( svgame.msg[svgame.msg_index].size == -1 )
{
// variable sized messages sent size as first byte
svgame.msg_size_index = sv.multicast.cursize;
MSG_WriteByte( &sv.multicast, 0 ); // reserve space for now
svgame.msg_size_index = BF_GetNumBytesWritten( &sv.multicast );
BF_WriteByte( &sv.multicast, 0 ); // reserve space for now
}
else svgame.msg_size_index = -1;
@ -1966,7 +1969,7 @@ void pfnMessageEnd( void )
if( expsize != realsize )
{
MsgDev( D_ERROR, "SV_Message: %s expected %i bytes, it written %i. Ignored.\n", name, expsize, realsize );
MSG_Clear( &sv.multicast );
BF_Clear( &sv.multicast );
return;
}
}
@ -1976,22 +1979,22 @@ void pfnMessageEnd( void )
if( svgame.msg_realsize > 255 )
{
MsgDev( D_ERROR, "SV_Message: %s too long (more than 255 bytes)\n", name );
MSG_Clear( &sv.multicast );
BF_Clear( &sv.multicast );
return;
}
else if( svgame.msg_realsize <= 0 )
{
MsgDev( D_ERROR, "SV_Message: %s writes NULL message\n", name );
MSG_Clear( &sv.multicast );
BF_Clear( &sv.multicast );
return;
}
sv.multicast.data[svgame.msg_size_index] = svgame.msg_realsize;
sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize;
}
else
{
// this should never happen
MsgDev( D_ERROR, "SV_Message: %s have encountered error\n", name );
MSG_Clear( &sv.multicast );
BF_Clear( &sv.multicast );
return;
}
@ -2009,7 +2012,7 @@ pfnWriteByte
void pfnWriteByte( int iValue )
{
if( iValue == -1 ) iValue = 0xFF; // convert char to byte
_MSG_WriteBits( &sv.multicast, (int)iValue, svgame.msg_name, NET_BYTE, __FILE__, __LINE__ );
BF_WriteByte( &sv.multicast, iValue );
svgame.msg_realsize++;
}
@ -2021,7 +2024,7 @@ pfnWriteChar
*/
void pfnWriteChar( int iValue )
{
_MSG_WriteBits( &sv.multicast, (int)iValue, svgame.msg_name, NET_CHAR, __FILE__, __LINE__ );
BF_WriteChar( &sv.multicast, iValue );
svgame.msg_realsize++;
}
@ -2033,7 +2036,7 @@ pfnWriteShort
*/
void pfnWriteShort( int iValue )
{
_MSG_WriteBits( &sv.multicast, (int)iValue, svgame.msg_name, NET_SHORT, __FILE__, __LINE__ );
BF_WriteShort( &sv.multicast, iValue );
svgame.msg_realsize += 2;
}
@ -2045,7 +2048,7 @@ pfnWriteLong
*/
void pfnWriteLong( int iValue )
{
_MSG_WriteBits( &sv.multicast, (int)iValue, svgame.msg_name, NET_LONG, __FILE__, __LINE__ );
BF_WriteLong( &sv.multicast, iValue );
svgame.msg_realsize += 4;
}
@ -2057,7 +2060,7 @@ pfnWriteAngle
*/
void pfnWriteAngle( float flValue )
{
MSG_WriteAngle16( &sv.multicast, flValue );
BF_WriteBitAngle( &sv.multicast, flValue, 16 );
svgame.msg_realsize += 2;
}
@ -2069,10 +2072,7 @@ pfnWriteCoord
*/
void pfnWriteCoord( float flValue )
{
ftol_t dat;
dat.f = flValue;
_MSG_WriteBits( &sv.multicast, dat.l, svgame.msg_name, NET_FLOAT, __FILE__, __LINE__ );
BF_WriteFloat( &sv.multicast, flValue );
svgame.msg_realsize += 4;
}
@ -2084,11 +2084,12 @@ pfnWriteString
*/
void pfnWriteString( const char *sz )
{
int cur_size = sv.multicast.cursize;
int cur_size = BF_GetNumBytesWritten( &sv.multicast );
int total_size;
MSG_WriteStringLine( &sv.multicast, sz ); // allow \n, \r, \t
total_size = sv.multicast.cursize - cur_size;
// FIXME: replace with BF_WriteStringLine
BF_WriteString( &sv.multicast, sz ); // allow \n, \r, \t
total_size = BF_GetNumBytesWritten( &sv.multicast ) - cur_size;
// NOTE: some messages with constant string length can be marked as known sized
svgame.msg_realsize += total_size;
@ -2103,8 +2104,8 @@ pfnWriteEntity
void pfnWriteEntity( int iValue )
{
if( iValue < 0 || iValue >= svgame.globals->numEntities )
Host_Error( "MSG_WriteEntity: invalid entnumber %i\n", iValue );
MSG_WriteShort( &sv.multicast, iValue );
Host_Error( "BF_WriteEntity: invalid entnumber %i\n", iValue );
BF_WriteShort( &sv.multicast, iValue );
svgame.msg_realsize += 2;
}
@ -2338,10 +2339,10 @@ int pfnRegUserMsg( const char *pszName, int iSize )
if( sv.state == ss_active )
{
MSG_WriteByte( &sv.multicast, svc_usermessage );
MSG_WriteString( &sv.multicast, pszName );
MSG_WriteByte( &sv.multicast, i );
MSG_WriteByte( &sv.multicast, (byte)iSize );
BF_WriteByte( &sv.multicast, svc_usermessage );
BF_WriteString( &sv.multicast, pszName );
BF_WriteByte( &sv.multicast, i );
BF_WriteByte( &sv.multicast, (byte)iSize );
MSG_Send( MSG_ALL, vec3_origin, NULL );
}
return i;
@ -2437,8 +2438,8 @@ void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
break;
case print_center:
if( fake ) return;
MSG_Begin( svc_centerprint );
MSG_WriteString( &sv.multicast, szMsg );
BF_WriteByte( &sv.multicast, svc_centerprint );
BF_WriteString( &sv.multicast, szMsg );
MSG_Send( MSG_ONE, NULL, client->edict );
break;
}
@ -2539,9 +2540,9 @@ void pfnCrosshairAngle( const edict_t *pClient, float pitch, float yaw )
// fakeclients ignore it silently
if( pClient->v.flags & FL_FAKECLIENT ) return;
MSG_Begin( svc_crosshairangle );
MSG_WriteAngle8( &sv.multicast, pitch );
MSG_WriteAngle8( &sv.multicast, yaw );
BF_WriteByte( &sv.multicast, svc_crosshairangle );
BF_WriteBitAngle( &sv.multicast, pitch, 8 );
BF_WriteBitAngle( &sv.multicast, yaw, 8 );
MSG_Send( MSG_ONE, vec3_origin, pClient );
}
@ -2580,8 +2581,8 @@ void pfnSetView( const edict_t *pClient, const edict_t *pViewent )
// fakeclients ignore to send client message
if( pClient->v.flags & FL_FAKECLIENT ) return;
MSG_WriteByte( &client->netchan.message, svc_setview );
MSG_WriteWord( &client->netchan.message, NUM_FOR_EDICT( pViewent ));
BF_WriteByte( &client->netchan.message, svc_setview );
BF_WriteWord( &client->netchan.message, NUM_FOR_EDICT( pViewent ));
MSG_Send( MSG_ONE, NULL, client->edict );
}
@ -2710,11 +2711,11 @@ void pfnFadeClientVolume( const edict_t *pEdict, float fadePercent, float fadeOu
return;
}
MSG_WriteByte( &sv.multicast, svc_soundfade );
MSG_WriteFloat( &sv.multicast, fadePercent );
MSG_WriteFloat( &sv.multicast, fadeOutSeconds );
MSG_WriteFloat( &sv.multicast, holdTime );
MSG_WriteFloat( &sv.multicast, fadeInSeconds );
BF_WriteByte( &sv.multicast, svc_soundfade );
BF_WriteFloat( &sv.multicast, fadePercent );
BF_WriteFloat( &sv.multicast, fadeOutSeconds );
BF_WriteFloat( &sv.multicast, holdTime );
BF_WriteFloat( &sv.multicast, fadeInSeconds );
MSG_Send( MSG_ONE, NULL, cl->edict );
}
@ -2778,9 +2779,10 @@ void pfnRunPlayerMove( edict_t *pClient, const float *v_angle, float fmove, floa
cmd.upmove = upmove;
cmd.buttons = buttons;
cmd.impulse = impulse;
cmd.random_seed = Com_RandomLong( 0, 0x7fffffff ); // full range
cmd.msec = msec;
cl->random_seed = Com_RandomLong( 0, 0x7fffffff ); // full range
SV_PreRunCmd( cl, &cmd );
SV_RunCmd( cl, &cmd );
SV_PostRunCmd( cl );
@ -3088,7 +3090,7 @@ static void pfnPlaybackEvent( int flags, const edict_t *pInvoker, word eventinde
info.flags = 0; // server ignore flags
// skipping queue, write in reliable datagram
MSG_WriteByte( &cl->reliable, svc_event_reliable );
BF_WriteByte( &cl->reliable, svc_event_reliable );
SV_PlaybackEvent( &cl->reliable, &info );
continue;
}
@ -3740,6 +3742,8 @@ void SV_UnloadProgs( void )
{
SV_DeactivateServer ();
Delta_Shutdown ();
svgame.dllFuncs.pfnGameShutdown ();
if( sys_sharedstrings->integer )
@ -3831,6 +3835,8 @@ bool SV_LoadProgs( const char *name )
// initialize pm_shared
SV_InitClientMove();
Delta_Init ();
// fire once
MsgDev( D_INFO, "Dll loaded for mod %s\n", svgame.dllFuncs.pfnGetGameDescription() );

View File

@ -5,6 +5,7 @@
#include "common.h"
#include "server.h"
#include "protocol.h"
int SV_UPDATE_BACKUP = SINGLEPLAYER_BACKUP;
@ -40,10 +41,10 @@ int SV_FindIndex( const char *name, int start, int end, bool create )
if( sv.state != ss_loading )
{
// send the update to everyone
MSG_Clear( &sv.multicast );
MSG_Begin( svc_configstring );
MSG_WriteShort( &sv.multicast, start + i );
MSG_WriteString( &sv.multicast, name );
BF_Clear( &sv.multicast );
BF_WriteByte( &sv.multicast, svc_configstring );
BF_WriteShort( &sv.multicast, start + i );
BF_WriteString( &sv.multicast, name );
MSG_Send( MSG_ALL, vec3_origin, NULL );
}
return i;
@ -315,8 +316,8 @@ bool SV_SpawnServer( const char *mapname, const char *startspot )
sv.time = 1000; // server spawn time it's always 1.0 second
// initialize buffers
MSG_Init( &sv.multicast, sv.multicast_buf, sizeof( sv.multicast_buf ));
MSG_Init( &sv.signon, sv.signon_buf, sizeof( sv.signon_buf ));
BF_Init( &sv.multicast, "Multicast", sv.multicast_buf, sizeof( sv.multicast_buf ));
BF_Init( &sv.signon, "Signon", sv.signon_buf, sizeof( sv.signon_buf ));
// leave slots at start for clients only
for( i = 0; i < sv_maxclients->integer; i++ )

View File

@ -5,6 +5,7 @@
#include "common.h"
#include "server.h"
#include "protocol.h"
#define HEARTBEAT_SECONDS (300 * 1000) // 300 seconds
@ -230,9 +231,9 @@ void SV_UpdateMovevars( void )
svgame.movevars.rollangle = sv_rollangle->value;
svgame.movevars.rollspeed = sv_rollspeed->value;
MSG_Clear( &sv.multicast );
BF_Clear( &sv.multicast );
if( MSG_WriteDeltaMovevars( &sv.multicast, &svgame.oldmovevars, &svgame.movevars ))
if( BF_WriteDeltaMovevars( &sv.multicast, &svgame.oldmovevars, &svgame.movevars ))
{
MSG_Send( MSG_ALL, vec3_origin, NULL );
Mem_Copy( &svgame.oldmovevars, &svgame.movevars, sizeof( movevars_t )); // oldstate changed
@ -246,9 +247,9 @@ void pfnUpdateServerInfo( const char *szKey, const char *szValue, const char *un
if( !cv || !cv->modified ) return; // this cvar not changed
MSG_WriteByte( &sv.multicast, svc_serverinfo );
MSG_WriteString( &sv.multicast, szKey );
MSG_WriteString( &sv.multicast, szValue );
BF_WriteByte( &sv.multicast, svc_serverinfo );
BF_WriteString( &sv.multicast, szKey );
BF_WriteString( &sv.multicast, szValue );
MSG_Send( MSG_ALL, vec3_origin, NULL );
cv->modified = false; // reset state
}
@ -295,14 +296,15 @@ SV_ReadPackets
*/
void SV_ReadPackets( void )
{
int i;
sv_client_t *cl;
int qport;
int i, qport, curSize;
while( NET_GetPacket( NS_SERVER, &net_from, net_message.data, &net_message.cursize ))
while( NET_GetPacket( NS_SERVER, &net_from, net_message_buffer, &curSize ))
{
BF_Init( &net_message, "ClientPacket", net_message_buffer, curSize );
// check for connectionless packet (0xffffffff) first
if( net_message.cursize >= 4 && *(int *)net_message.data == -1 )
if( BF_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 )
{
SV_ConnectionlessPacket( net_from, &net_message );
continue;
@ -310,10 +312,10 @@ void SV_ReadPackets( void )
// read the qport out of the message so we can fix up
// stupid address translating routers
MSG_BeginReading( &net_message );
MSG_ReadLong( &net_message ); // sequence number
MSG_ReadLong( &net_message ); // sequence number
qport = (int)MSG_ReadShort( &net_message ) & 0xffff;
BF_Clear( &net_message );
BF_ReadLong( &net_message ); // sequence number
BF_ReadLong( &net_message ); // sequence number
qport = (int)BF_ReadShort( &net_message ) & 0xffff;
// check for packets from connected clients
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
@ -680,7 +682,7 @@ void SV_Init( void )
sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE, "max reconnect attempts" );
SV_ClearSaveDir (); // delete all temporary *.hl files
MSG_Init( &net_message, net_message_buffer, sizeof( net_message_buffer ));
BF_Init( &net_message, "NetMessage", net_message_buffer, sizeof( net_message_buffer ));
}
/*
@ -697,34 +699,34 @@ void SV_FinalMessage( char *message, bool reconnect )
{
sv_client_t *cl;
byte msg_buf[MAX_MSGLEN];
sizebuf_t msg;
bitbuf_t msg;
int i;
MSG_Init( &msg, msg_buf, sizeof( msg_buf ));
MSG_WriteByte( &msg, svc_print );
MSG_WriteByte( &msg, PRINT_HIGH );
MSG_WriteString( &msg, message );
BF_Init( &msg, "FinalMessage", msg_buf, sizeof( msg_buf ));
BF_WriteByte( &msg, svc_print );
BF_WriteByte( &msg, PRINT_HIGH );
BF_WriteString( &msg, message );
if( reconnect )
{
if( sv.loadgame || sv_maxclients->integer > 1 )
MSG_WriteByte( &msg, svc_changing );
else MSG_WriteByte( &msg, svc_reconnect );
BF_WriteByte( &msg, svc_changing );
else BF_WriteByte( &msg, svc_reconnect );
}
else
{
MSG_WriteByte( &msg, svc_disconnect );
BF_WriteByte( &msg, svc_disconnect );
}
// 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->edict && cl->edict->v.flags & FL_FAKECLIENT ))
Netchan_Transmit( &cl->netchan, msg.cursize, msg.data );
Netchan_Transmit( &cl->netchan, BF_GetNumBytesWritten( &msg ), BF_GetData( &msg ));
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
if( cl->state >= cs_connected && !(cl->edict && cl->edict->v.flags & FL_FAKECLIENT ))
Netchan_Transmit( &cl->netchan, msg.cursize, msg.data );
Netchan_Transmit( &cl->netchan, BF_GetNumBytesWritten( &msg ), BF_GetData( &msg ));
}
/*

View File

@ -6,6 +6,7 @@
#include "common.h"
#include "mathlib.h"
#include "matrix_lib.h"
#include "protocol.h"
#include "server.h"
#include "const.h"
#include "pm_defs.h"
@ -337,9 +338,9 @@ static void PM_ClientPrintf( int index, char *fmt, ... )
com.vsprintf( string, fmt, argptr );
va_end( argptr );
MSG_WriteByte( &cl->netchan.message, svc_print );
MSG_WriteByte( &cl->netchan.message, PRINT_HIGH );
MSG_WriteString( &cl->netchan.message, string );
BF_WriteByte( &cl->netchan.message, svc_print );
BF_WriteByte( &cl->netchan.message, PRINT_HIGH );
BF_WriteString( &cl->netchan.message, string );
}
/*
@ -589,7 +590,7 @@ void SV_InitClientMove( void )
void SV_PreRunCmd( sv_client_t *cl, usercmd_t *ucmd )
{
svgame.pmove->runfuncs = true;
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, ucmd->random_seed );
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, cl->random_seed );
}
/*

View File

@ -1747,9 +1747,9 @@ void SV_SaveGame( const char *pName )
{
const char *pMsg = "GAMESAVED"; // defined in titles.txt
MSG_Begin( svgame.gmsgHudText );
MSG_WriteByte( &sv.multicast, com.strlen( pMsg ) + 1 );
MSG_WriteString( &sv.multicast, pMsg );
BF_WriteByte( &sv.multicast, svgame.gmsgHudText );
BF_WriteByte( &sv.multicast, com.strlen( pMsg ) + 1 );
BF_WriteString( &sv.multicast, pMsg );
MSG_Send( MSG_ONE, NULL, EDICT_NUM( 1 ));
}
}

View File

@ -132,6 +132,9 @@ static void UI_Controls_ParseKeysList( void )
if( !afile )
{
for( ; i < MAX_KEYS; i++ ) uiControls.keysDescriptionPtr[i] = NULL;
uiControls.keysList.itemNames = (const char **)uiControls.keysDescriptionPtr;
ALERT( at_error, "UI_Parse_KeysList: kb_act.lst not found\n" );
return;
}

View File

@ -13,7 +13,6 @@
// color packs
typedef struct { uint b:5; uint g:6; uint r:5; } color16;
typedef struct { byte r:8; byte g:8; byte b:8; } color24;
typedef struct { byte r; byte g; byte b; byte a; } color32;
// cubemap hints

View File

@ -163,39 +163,41 @@ size_t com_strncat(char *dst, const char *src, size_t size)
return(dlen + (s - src)); // count does not include NULL
}
size_t com_strcat(char *dst, const char *src )
size_t com_strcat( char *dst, const char *src )
{
return com_strncat( dst, src, 99999 );
}
size_t com_strncpy(char *dst, const char *src, size_t size)
size_t com_strncpy( char *dst, const char *src, size_t size )
{
register char *d = dst;
register const char *s = src;
register size_t n = size;
if(!dst || !src || !size) return 0;
if( !dst || !src || !size )
return 0;
// copy as many bytes as will fit
if (n != 0 && --n != 0)
if( n != 0 && --n != 0 )
{
do
{
if ((*d++ = *s++) == 0)
if(( *d++ = *s++ ) == 0 )
break;
} while (--n != 0);
} while( --n != 0 );
}
// not enough room in dst, add NULL and traverse rest of src
if (n == 0)
if( n == 0 )
{
if (size != 0) *d = '\0'; // NULL-terminate dst
while (*s++);
if( size != 0 )
*d = '\0'; // NULL-terminate dst
while( *s++ );
}
return(s - src - 1); // count does not include NULL
return( s - src - 1 ); // count does not include NULL
}
size_t com_strcpy(char *dst, const char *src )
size_t com_strcpy( char *dst, const char *src )
{
return com_strncpy( dst, src, 99999 );
}

View File

@ -1329,7 +1329,6 @@ addEntity:
state->rendermode = pEntity->pev->rendermode; // rendering mode
state->renderamt = pEntity->pev->renderamt; // alpha value
state->animtime = (int)(1000.0 * pEntity->pev->animtime) * 0.001; // sequence time
state->localtime = (int)(1000.0 * pEntity->pev->ltime) * 0.001; // movement time
state->scale = pEntity->pev->scale; // shared client and render flags
state->movetype = (movetype_t)pEntity->pev->movetype;
state->frame = pEntity->pev->frame; // any model current frame
@ -1337,18 +1336,21 @@ addEntity:
state->mins = pEntity->pev->mins;
state->maxs = pEntity->pev->maxs;
state->flags = pEntity->pev->flags;
state->rendercolor = pEntity->pev->rendercolor;
state->oldorigin = pEntity->pev->oldorigin;
state->colormap = pEntity->pev->colormap; // attachments
state->rendercolor.r = (byte)pEntity->pev->rendercolor.x;
state->rendercolor.g = (byte)pEntity->pev->rendercolor.y;
state->rendercolor.b = (byte)pEntity->pev->rendercolor.z;
if( pEntity->pev->groundentity )
state->groundent = ENTINDEX( pEntity->pev->groundentity );
else state->groundent = -1;
state->onground = ENTINDEX( pEntity->pev->groundentity );
else state->onground = 0;
// translate attached entity
if( pEntity->pev->aiment )
state->aiment = ENTINDEX( pEntity->pev->aiment );
else state->aiment = -1;
else state->aiment = 0;
// studio model sequence
if( pEntity->pev->sequence != -1 )
@ -1370,18 +1372,12 @@ addEntity:
pEntity->pev->teleport_time = 0.0f;
}
if( pEntity->pev->viewmodel )
state->viewmodel = MODEL_INDEX( STRING( pEntity->pev->viewmodel ));
else state->viewmodel = 0;
if( pEntity->pev->aiment )
state->aiment = ENTINDEX( pEntity->pev->aiment );
else state->aiment = -1;
else state->aiment = 0;
state->viewoffset = pEntity->pev->view_ofs;
state->viewangles = pEntity->pev->v_angle;
state->idealpitch = pEntity->pev->idealpitch;
state->punch_angles = pEntity->pev->punchangle;
state->velocity = pEntity->pev->velocity;
state->basevelocity = pEntity->pev->clbasevelocity;
state->iStepLeft = pEntity->pev->iStepLeft;
@ -1393,7 +1389,6 @@ addEntity:
if( pEntity->pev->weaponmodel != iStringNull )
state->weaponmodel = MODEL_INDEX( STRING( pEntity->pev->weaponmodel ));
else state->weaponmodel = 0;
state->weapons = pEntity->pev->weapons;
state->maxspeed = pEntity->pev->maxspeed;
// clamp fov
@ -1420,7 +1415,7 @@ addEntity:
// translate StartBeamEntity
if( pEntity->pev->owner )
state->owner = ENTINDEX( pEntity->pev->owner );
else state->owner = -1;
else state->owner = 0;
}
return 1;
@ -1446,9 +1441,9 @@ void CreateBaseline( entity_state_t *baseline, edict_t *entity, int playermodeli
// render information
baseline->rendermode = (byte)entity->v.rendermode;
baseline->renderamt = (byte)entity->v.renderamt;
baseline->rendercolor.x = (byte)entity->v.rendercolor.x;
baseline->rendercolor.y = (byte)entity->v.rendercolor.y;
baseline->rendercolor.z = (byte)entity->v.rendercolor.z;
baseline->rendercolor.r = (byte)entity->v.rendercolor.x;
baseline->rendercolor.g = (byte)entity->v.rendercolor.y;
baseline->rendercolor.b = (byte)entity->v.rendercolor.z;
baseline->renderfx = (byte)entity->v.renderfx;
baseline->mins = entity->v.mins;