20 Oct 2010

This commit is contained in:
g-cont 2010-10-20 00:00:00 +04:00 committed by Alibek Omarov
parent 6b87c02012
commit 19d558fbcd
17 changed files with 538 additions and 277 deletions

View File

@ -159,7 +159,7 @@ typedef struct enginefuncs_s
int (*pfnCompareFileTime)( const char *filename1, const char *filename2, int *iCompare );
void (*pfnGetGameDir)( char *szGetGameDir );
void (*pfnHostError)( const char *szFmt, ... );
void (*pfnFadeClientVolume)( const edict_t *pEdict, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds );
void (*pfnFadeClientVolume)( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds );
void (*pfnSetClientMaxspeed)( const edict_t *pEdict, float fNewMaxspeed );
edict_t *(*pfnCreateFakeClient)( const char *netname ); // returns NULL if fake client can't be created
void (*pfnRunPlayerMove)( edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, word buttons, byte impulse, byte msec );
@ -199,6 +199,8 @@ typedef struct enginefuncs_s
void (*pfnForceUnmodified)( FORCE_TYPE type, float *mins, float *maxs, const char *filename );
void (*pfnGetPlayerStats)( const edict_t *pClient, int *ping, int *packet_loss );
void (*pfnAddServerCommand)( const char *cmd_name, void (*function)(void), const char *cmd_desc );
int (*pfnVoice_GetClientListening)( int iReceiver, int iSender );
int (*pfnVoice_SetClientListening)( int iReceiver, int iSender, int bListen );
const char *(*pfnGetPlayerAuthId)( edict_t *e );
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
} enginefuncs_t;
@ -345,8 +347,8 @@ typedef struct
// returns string describing current .dll. E.g., TeamFotrress 2, Half-Life
const char *(*pfnGetGameDescription)( void );
// Notify dll about a player customization. (completely ignored in Xash3D)
void (*pfnPlayerCustomization)( edict_t *pEntity, void *pUnused );
// Notify dll about a player customization.
void (*pfnPlayerCustomization)( edict_t *pEntity, customization_t *pCustom );
// Spectator funcs
void (*pfnSpectatorConnect)( edict_t *pEntity );

View File

@ -854,11 +854,42 @@ void Sys_Error( const char *error_string )
================
PlayerCustomization
Completely ignored in Xash3D
A new player customization has been registered on the server
UNDONE: This only sets the # of frames of the spray can logo
animation right now.
================
*/
void PlayerCustomization( edict_t *pEntity, void *pCust )
void PlayerCustomization( edict_t *pEntity, customization_t *pCust )
{
entvars_t *pev = &pEntity->v;
CBasePlayer *pPlayer = (CBasePlayer *)GET_PRIVATE(pEntity);
if (!pPlayer)
{
ALERT(at_console, "PlayerCustomization: Couldn't get player!\n");
return;
}
if (!pCust)
{
ALERT(at_console, "PlayerCustomization: NULL customization!\n");
return;
}
switch (pCust->resource.type)
{
case t_decal:
pPlayer->SetCustomDecalFrames(pCust->nUserData2); // Second int is max # of frames.
break;
case t_sound:
case t_skin:
case t_model:
// Ignore for now.
break;
default:
ALERT(at_console, "PlayerCustomization: Unknown customization type!\n");
break;
}
}
/*

View File

@ -33,7 +33,7 @@ extern void ParmsChangeLevel( void );
extern void ClientPrecache( void );
extern const char *GetGameDescription( void );
extern void PlayerCustomization( edict_t *pEntity, void *pUnused );
extern void PlayerCustomization( edict_t *pEntity, customization_t *pCustom );
extern void SpectatorConnect ( edict_t *pEntity );
extern void SpectatorDisconnect ( edict_t *pEntity );

View File

@ -29,14 +29,14 @@ const char *svc_strings[256] =
"svc_serverdata",
"svc_restore",
"svc_updateuserinfo",
"svc_usermessage",
"svc_unused14",
"svc_clientdata",
"svc_download",
"svc_updatepings",
"svc_particle",
"svc_frame",
"svc_spawnstatic",
"svc_crosshairangle",
"svc_unused21",
"svc_spawnbaseline",
"svc_temp_entity",
"svc_setpause",
@ -46,7 +46,7 @@ const char *svc_strings[256] =
"svc_event_reliable",
"svc_ambientsound",
"svc_intermission",
"svc_soundfade",
"svc_unused31",
"svc_cdtrack",
"svc_serverinfo",
"svc_deltatable",
@ -54,7 +54,7 @@ const char *svc_strings[256] =
"svc_bspdecal",
"svc_roomtype",
"svc_addangle",
"svc_unused39",
"svc_usermessage",
"svc_packetentities",
"svc_deltapacketentities",
"svc_chokecount",
@ -62,8 +62,8 @@ const char *svc_strings[256] =
"svc_unused44",
"svc_unused45",
"svc_unused46",
"svc_unused47",
"svc_unused48",
"svc_crosshairangle",
"svc_soundfade",
"svc_unused49",
"svc_unused50",
"svc_director",
@ -521,10 +521,10 @@ void CL_ParseSoundFade( sizebuf_t *msg )
float fadePercent, fadeOutSeconds;
float holdTime, fadeInSeconds;
fadePercent = BF_ReadFloat( msg );
fadeOutSeconds = BF_ReadFloat( msg );
holdTime = BF_ReadFloat( msg );
fadeInSeconds = BF_ReadFloat( msg );
fadePercent = (float)BF_ReadByte( msg );
holdTime = (float)BF_ReadByte( msg );
fadeOutSeconds = (float)BF_ReadByte( msg );
fadeInSeconds = (float)BF_ReadByte( msg );
S_FadeClientVolume( fadePercent, fadeOutSeconds, holdTime, fadeInSeconds );
}
@ -807,6 +807,7 @@ void CL_ParseAddAngle( sizebuf_t *msg )
add_angle = BF_ReadBitAngle( msg, 16 );
cl.refdef.cl_viewangles[1] += add_angle;
}
/*
================
CL_ParseCrosshairAngle
@ -816,8 +817,8 @@ offset crosshair angles
*/
void CL_ParseCrosshairAngle( sizebuf_t *msg )
{
cl.refdef.crosshairangle[0] = BF_ReadBitAngle( msg, 8 );
cl.refdef.crosshairangle[1] = BF_ReadBitAngle( msg, 8 );
cl.refdef.crosshairangle[0] = BF_ReadChar( msg ) * 0.2f;
cl.refdef.crosshairangle[1] = BF_ReadChar( msg ) * 0.2f;
cl.refdef.crosshairangle[2] = 0.0f; // not used for screen space
}
@ -833,9 +834,9 @@ void CL_RegisterUserMessage( sizebuf_t *msg )
char *pszName;
int svc_num, size;
pszName = BF_ReadString( msg );
svc_num = BF_ReadByte( msg );
size = BF_ReadByte( msg );
pszName = BF_ReadString( msg );
// important stuff
if( size == 0xFF ) size = -1;

View File

@ -1,194 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2010 ©
// cm_light.c - lighting info for GETENTITYILLUM
//=======================================================================
#include "cm_local.h"
#include "edict.h"
#include "mathlib.h"
static vec3_t cm_pointColor;
static float cm_modulate;
/*
=================
CM_RecursiveLightPoint
=================
*/
static bool CM_RecursiveLightPoint( mnode_t *node, const vec3_t start, const vec3_t end )
{
int side;
mplane_t *plane;
msurface_t *surf;
mtexinfo_t *tex;
vec3_t mid, scale;
float front, back, frac;
int i, map, size, s, t;
byte *lm;
// didn't hit anything
if( !node->plane ) return false;
// calculate mid point
plane = node->plane;
if( plane->type < 3 )
{
front = start[plane->type] - plane->dist;
back = end[plane->type] - plane->dist;
}
else
{
front = DotProduct( start, plane->normal ) - plane->dist;
back = DotProduct( end, plane->normal ) - plane->dist;
}
side = front < 0;
if(( back < 0 ) == side )
return CM_RecursiveLightPoint( node->children[side], start, end );
frac = front / ( front - back );
VectorLerp( start, frac, end, mid );
// co down front side
if( CM_RecursiveLightPoint( node->children[side], start, mid ))
return true; // hit something
if(( back < 0 ) == side )
return false;// didn't hit anything
// check for impact on this node
surf = node->firstface;
for( i = 0; i < node->numfaces; i++, surf++ )
{
tex = surf->texinfo;
if( surf->flags & SURF_DRAWTILED )
continue; // no lightmaps
s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0];
t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1];
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
continue;
s >>= 4;
t >>= 4;
if( !surf->samples )
return true;
VectorClear( cm_pointColor );
lm = surf->samples + 3 * (t * ((surf->extents[0] >> 4) + 1) + s);
size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
for( map = 0; map < surf->numstyles; map++ )
{
VectorScale( cm.lightstyle[surf->styles[map]].rgb, cm_modulate, scale );
cm_pointColor[0] += lm[0] * scale[0];
cm_pointColor[1] += lm[1] * scale[1];
cm_pointColor[2] += lm[2] * scale[2];
lm += size; // skip to next lightmap
}
return true;
}
// go down back side
return CM_RecursiveLightPoint( node->children[!side], mid, end );
}
void CM_RunLightStyles( float time )
{
int i, ofs;
clightstyle_t *ls;
float l;
if( !worldmodel ) return;
// run lightstyles animation
ofs = (time * 10);
if( ofs == cm.lastofs ) return;
cm.lastofs = ofs;
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
{
if( ls->length == 0 ) l = 0.0f;
else if( ls->length == 1 ) l = ls->map[0];
else l = ls->map[ofs%ls->length];
VectorSet( ls->rgb, l, l, l );
}
}
/*
==================
CM_AddLightStyle
needs to get correct working SV_LightPoint
==================
*/
void CM_SetLightStyle( int style, const char* s )
{
int j, k;
j = com.strlen( s );
cm.lightstyle[style].length = j;
for( k = 0; k < j; k++ )
cm.lightstyle[style].map[k] = (float)( s[k]-'a' ) / (float)( 'm'-'a' );
}
void CM_ClearLightStyles( void )
{
clightstyle_t *ls;
int i;
Mem_Set( cm.lightstyle, 0, sizeof( cm.lightstyle ));
for( i = 0, ls = cm.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
VectorSet( cm.lightstyle[i].rgb, 1.0f, 1.0f, 1.0f );
cm.lastofs = -1;
}
/*
==================
CM_LightEntity
grab the ambient lighting color for current point
==================
*/
int CM_LightEntity( edict_t *pEdict )
{
vec3_t start, end;
if( !pEdict ) return 0;
if( pEdict->v.effects & EF_FULLBRIGHT || !worldmodel->lightdata )
{
return 255;
}
if( pEdict->v.flags & FL_CLIENT )
{
// client has more precision light level
// that come from client
return pEdict->v.light_level;
}
VectorCopy( pEdict->v.origin, start );
VectorCopy( pEdict->v.origin, end );
if( pEdict->v.effects & EF_INVLIGHT )
end[2] = start[2] + 8192;
else end[2] = start[2] - 8192;
VectorSet( cm_pointColor, 1.0f, 1.0f, 1.0f );
cm_modulate = cm_lighting_modulate->value * (1.0 / 255);
CM_RecursiveLightPoint( worldmodel->nodes, start, end );
return VectorAvg( cm_pointColor );
}

View File

@ -11,9 +11,6 @@
#include "eiface.h"
#include "com_model.h"
#define FMOVE_IGNORE_GLASS 0x100
#define FMOVE_SIMPLEBOX 0x200
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (1.0f / 32.0f)
#define FRAC_EPSILON (1.0f / 1024.0f)
@ -22,14 +19,6 @@
#define DVIS_PHS 1
extern cvar_t *cm_novis;
extern cvar_t *cm_lighting_modulate;
typedef struct
{
int length;
float map[MAX_STRING];
vec3_t rgb; // 0.0 - 2.0
} clightstyle_t;
typedef struct leaflist_s
{
@ -55,24 +44,12 @@ typedef struct clipmap_s
vec3_t hull_sizes[4]; // hull sizes
script_t *entityscript; // only actual for world
// run local lightstyles to get SV_LightPoint grab the actual information
clightstyle_t lightstyle[MAX_LIGHTSTYLES];
int lastofs;
} clipmap_t;
extern clipmap_t cm;
extern model_t *loadmodel;
extern model_t *worldmodel;
//
// cm_light.c
//
void CM_RunLightStyles( float time );
void CM_SetLightStyle( int style, const char* val );
int CM_LightEntity( edict_t *pEdict );
void CM_ClearLightStyles( void );
//
// cm_test.c
//

View File

@ -25,7 +25,6 @@ model_t *worldmodel;
// cvars
cvar_t *cm_novis;
cvar_t *cm_lighting_modulate;
/*
===============================================================================
@ -106,7 +105,6 @@ static void CM_FreeModel( model_t *mod )
bool CM_InitPhysics( void )
{
cm_novis = Cvar_Get( "cm_novis", "0", 0, "force to ignore server visibility" );
cm_lighting_modulate = Cvar_Get( "r_lighting_modulate", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lightstyles modulate scale" );
Mem_Set( cm.nullrow, 0xFF, MAX_MAP_LEAFS / 8 );
return true;
@ -1025,11 +1023,8 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
if( checksum ) *checksum = cm.checksum;
if( !clientload )
{
// reset entity script...
// reset the entity script
Com_ResetScript( cm.entityscript );
// ..and lightstyles
CM_ClearLightStyles();
}
sv_models[1] = cm_models; // make link to world
@ -1048,7 +1043,6 @@ void CM_BeginRegistration( const char *name, bool clientload, uint *checksum )
if( checksum ) *checksum = cm.checksum;
CM_ClearLightStyles();
CM_CalcPHS ();
}

View File

@ -22,14 +22,14 @@
#define svc_serverdata 11 // [long] protocol ...
#define svc_restore 12 // restore saved game on the client
#define svc_updateuserinfo 13 // [byte] playernum, [string] userinfo
#define svc_usermessage 14 // [string][byte] REG_USER_MSG stuff
#define svc_clientdata 15 // [...]
#define svc_download 16 // [short] size [size bytes]
#define svc_updatepings 17 // [bit][idx][ping][packet_loss]
#define svc_particle 18 // [float*3][char*3][byte][byte]
#define svc_frame 19 // <OBSOLETE>
#define svc_spawnstatic 20 // creates a static client entity
#define svc_crosshairangle 21 // [short][short][short]
#define svc_spawnbaseline 22 // <see code>
#define svc_temp_entity 23 // <variable sized>
#define svc_setpause 24 // [byte] 0 = unpaused, 1 = paused
@ -39,7 +39,7 @@
#define svc_event_reliable 28 // playback event directly from message, not queue
#define svc_ambientsound 29 // <see code>
#define svc_intermission 30 // empty message (event)
#define svc_soundfade 31 // [float*4] sound fade parms
#define svc_cdtrack 32 // [byte] track [byte] looptrack
#define svc_serverinfo 33 // [string] key [string] value
#define svc_deltatable 34 // [table header][...]
@ -47,11 +47,14 @@
#define svc_bspdecal 36 // [float*3][short][short][short]
#define svc_roomtype 37 // [short] room type
#define svc_addangle 38 // [angle] add angles when client turn on mover
#define svc_usermessage 39 // [byte][byte][string] REG_USER_MSG stuff
#define svc_packetentities 40 // [short][...]
#define svc_deltapacketentities 41 // [short][byte][...]
#define svc_chokecount 42 // [byte]
#define svc_crosshairangle 47 // [byte][byte]
#define svc_soundfade 48 // [float*4] sound fade parms
#define svc_director 51 // <variable sized>
#define svc_lastmsg 64 // start user messages at this point

View File

@ -10,6 +10,9 @@
#define MOVE_MISSILE 2 // extra size for monsters
#define MOVE_WORLDONLY 3 // clip only world
#define FMOVE_IGNORE_GLASS 0x100
#define FMOVE_SIMPLEBOX 0x200
#define CONTENTS_NONE 0 // no custom contents specified
/*

View File

@ -178,10 +178,6 @@ SOURCE=.\client\cl_world.c
# End Source File
# Begin Source File
SOURCE=.\common\cm_light.c
# End Source File
# Begin Source File
SOURCE=.\common\cm_model.c
# End Source File
# Begin Source File

View File

@ -63,6 +63,29 @@ typedef enum
cs_spawned // client is fully in game
} cl_state_t;
// server lightstyles (used for GetEntityIllum)
typedef struct
{
int length;
float map[MAX_STRING];
vec3_t rgb; // 0.0 - 2.0
} sv_lightstyle_t;
// instanced baselines container
typedef struct
{
int count;
string_t classnames[64];
entity_state_t baselines[64];
} sv_baselines_t;
typedef struct
{
const char *name;
FORCE_TYPE force_state;
vec3_t mins, maxs;
} sv_consistency_t;
typedef struct server_s
{
sv_state_t state; // precache commands are only valid during load
@ -80,6 +103,11 @@ typedef struct server_s
char configstrings[MAX_CONFIGSTRINGS][CS_SIZE];
sv_consistency_t consistency_files[MAX_MODELS];
int num_consistency_files;
sv_baselines_t instanced; // instanced baselines
// unreliable data to send to clients.
sizebuf_t datagram;
byte datagram_buf[NET_MAX_PAYLOAD];
@ -97,6 +125,9 @@ typedef struct server_s
model_t *worldmodel; // pointer to world
// run local lightstyles to let SV_LightPoint grab the actual information
sv_lightstyle_t lightstyle[MAX_LIGHTSTYLES];
bool write_bad_message; // just for debug
bool paused;
} server_t;
@ -179,6 +210,8 @@ typedef struct sv_client_s
int challenge; // challenge of this user, randomly generated
int userid; // identifying number on server
int authentication_method;
uint WonID; // WonID
} sv_client_t;
/*
@ -321,6 +354,7 @@ extern cvar_t *sv_gravity;
extern cvar_t *sv_stopspeed;
extern cvar_t *sv_check_errors;
extern cvar_t *sv_reconnect_limit;
extern cvar_t *sv_lighting_modulate;
extern cvar_t *rcon_password;
extern cvar_t *hostname;
extern cvar_t *sv_stepheight;
@ -407,6 +441,7 @@ void SV_DirectConnect( netadr_t from );
void SV_TogglePause( const char *msg );
void SV_PutClientInServer( edict_t *ent );
bool SV_ShouldUpdatePing( sv_client_t *cl );
const char *SV_GetClientIDString( sv_client_t *cl );
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg );
void SV_FullUpdateMovevars( sv_client_t *cl, sizebuf_t *msg );
void SV_GetPlayerStats( sv_client_t *cl, int *ping, int *packet_loss );
@ -523,5 +558,8 @@ void SV_LinkEdict( edict_t *ent, bool touch_triggers );
void SV_TouchLinks( edict_t *ent, areanode_t *node );
int SV_TruePointContents( const vec3_t p );
int SV_PointContents( const vec3_t p );
void SV_RunLightStyles( void );
void SV_SetLightStyle( int style, const char* s );
int SV_LightForEntity( edict_t *pEdict );
#endif//SERVER_H

View File

@ -252,6 +252,9 @@ edict_t *SV_FakeConnect( const char *netname )
// setup fake client name
Info_SetValueForKey( userinfo, "name", netname );
Info_SetValueForKey( userinfo, "model", "gordon" );
Info_SetValueForKey( userinfo, "topcolor", "1" );
Info_SetValueForKey( userinfo, "bottomcolor", "1" );
// force the IP key/value pair so the game can filter based on ip
Info_SetValueForKey( userinfo, "ip", "127.0.0.1" );
@ -287,6 +290,7 @@ edict_t *SV_FakeConnect( const char *netname )
newcl->challenge = -1; // fake challenge
newcl->fakeclient = true;
newcl->delta_sequence = -1;
newcl->userid = g_userid++; // create unique userid
ent->v.flags |= FL_FAKECLIENT; // mark it as fakeclient
// get the game a chance to reject this connection or modify the userinfo
@ -491,6 +495,50 @@ char *SV_StatusString( void )
return status;
}
/*
===============
SV_GetClientIDString
Returns a pointer to a static char for most likely only printing.
===============
*/
const char *SV_GetClientIDString( sv_client_t *cl )
{
static char result[CS_SIZE];
result[0] = '\0';
if( !cl )
{
MsgDev( D_ERROR, "SV_GetClientIDString: invalid client\n" );
return result;
}
if( cl->authentication_method == 0 )
{
// probably some old compatibility code.
com.snprintf( result, sizeof( result ), "%010lu", cl->WonID );
}
else if( cl->authentication_method == 2 )
{
if( NET_IsLocalAddress( cl->netchan.remote_address ))
{
com.strncpy( result, "VALVE_ID_LOOPBACK", sizeof( result ));
}
else if( cl->WonID == 0 )
{
com.strncpy( result, "VALVE_ID_PENDING", sizeof( result ));
}
else
{
com.snprintf( result, sizeof( result ), "VALVE_%010lu", cl->WonID );
}
}
else com.strncpy( result, "UNKNOWN", sizeof( result ));
return result;
}
/*
================
SV_Status
@ -1017,9 +1065,9 @@ void SV_UserMessages_f( sv_client_t *cl )
if( message->name[0] )
{
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 );
BF_WriteString( &cl->netchan.message, message->name );
}
start++;
}

View File

@ -1106,7 +1106,7 @@ int pfnGetEntityIllum( edict_t* pEnt )
MsgDev( D_WARN, "SV_GetEntityIllum: invalid entity %s\n", SV_ClassName( pEnt ));
return 0;
}
return CM_LightEntity( pEnt );
return SV_LightForEntity( pEnt );
}
/*
@ -2018,7 +2018,7 @@ void pfnLightStyle( int style, const char* val )
if( style >= MAX_LIGHTSTYLES )
Host_Error( "SV_LightStyle: style: %i >= %d", style, MAX_LIGHTSTYLES );
CM_SetLightStyle( style, val ); // update info for SV_LightPoint
SV_SetLightStyle( style, val ); // update info for SV_LightPoint
SV_ConfigString( CS_LIGHTSTYLES + style, val );
}
@ -2527,11 +2527,8 @@ edict_t* pfnFindEntityByVars( entvars_t *pvars )
for( i = 0; i < svgame.numEntities; i++ )
{
e = EDICT_NUM( i );
if( !memcmp( &e->v, pvars, sizeof( entvars_t )))
{
MsgDev( D_INFO, "FindEntityByVars: %s\n", SV_ClassName( e ));
if( &e->v == pvars )
return e; // found it
}
}
return NULL;
}
@ -2605,9 +2602,9 @@ int pfnRegUserMsg( const char *pszName, int iSize )
{
// tell the client about new user message
BF_WriteByte( &sv.reliable_datagram, svc_usermessage );
BF_WriteString( &sv.reliable_datagram, svgame.msg[i].name );
BF_WriteByte( &sv.reliable_datagram, svgame.msg[i].number );
BF_WriteByte( &sv.reliable_datagram, (byte)iSize );
BF_WriteString( &sv.reliable_datagram, svgame.msg[i].name );
}
return svgame.msg[i].number;
@ -2622,7 +2619,7 @@ animating studiomodel
*/
void pfnAnimationAutomove( const edict_t* pEdict, float flTime )
{
// FIXME: implement
// this is empty in the original HL
}
/*
@ -2801,9 +2798,14 @@ void pfnCrosshairAngle( const edict_t *pClient, float pitch, float yaw )
// fakeclients ignores it silently
if( client->fakeclient ) return;
if( pitch > 180.0f ) pitch -= 360;
if( pitch < -180.0f ) pitch += 360;
if( yaw > 180.0f ) yaw -= 360;
if( yaw < -180.0f ) yaw += 360;
BF_WriteByte( &client->netchan.message, svc_crosshairangle );
BF_WriteBitAngle( &client->netchan.message, pitch, 8 );
BF_WriteBitAngle( &client->netchan.message, yaw, 8 );
BF_WriteChar( &client->netchan.message, pitch * 5 );
BF_WriteChar( &client->netchan.message, yaw * 5 );
}
/*
@ -2916,7 +2918,22 @@ pfnGetPlayerWONId
*/
uint pfnGetPlayerWONId( edict_t *e )
{
// FIXME: implement
int i;
sv_client_t *cl;
if( sv.state != ss_active )
return -1;
if( !SV_ClientFromEdict( e, false ))
return -1;
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->edict == e && cl->authentication_method == 0 )
{
return cl->WonID;
}
}
return -1;
}
@ -2954,7 +2971,7 @@ pfnFadeClientVolume
=============
*/
void pfnFadeClientVolume( const edict_t *pEdict, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds )
void pfnFadeClientVolume( const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds )
{
sv_client_t *cl;
@ -2965,17 +2982,20 @@ void pfnFadeClientVolume( const edict_t *pEdict, float fadePercent, float fadeOu
return;
}
if( cl->fakeclient ) return;
BF_WriteByte( &cl->netchan.message, svc_soundfade );
BF_WriteFloat( &cl->netchan.message, fadePercent );
BF_WriteFloat( &cl->netchan.message, fadeOutSeconds );
BF_WriteFloat( &cl->netchan.message, holdTime );
BF_WriteFloat( &cl->netchan.message, fadeInSeconds );
BF_WriteByte( &cl->netchan.message, fadePercent );
BF_WriteByte( &cl->netchan.message, holdTime );
BF_WriteByte( &cl->netchan.message, fadeOutSeconds );
BF_WriteByte( &cl->netchan.message, fadeInSeconds );
}
/*
=============
pfnSetClientMaxspeed
fakeclients can be changed speed to
=============
*/
void pfnSetClientMaxspeed( const edict_t *pEdict, float fNewMaxspeed )
@ -3053,7 +3073,15 @@ returns actual entity count
*/
int pfnNumberOfEntities( void )
{
return svgame.numEntities;
int i, total = 0;
for( i = 0; i < svgame.numEntities; i++ )
{
if( !svgame.edicts[i].free )
total++;
}
return total;
}
/*
@ -3420,6 +3448,8 @@ pfnCheckVisibility
*/
int pfnCheckVisibility( const edict_t *ent, byte *pset )
{
int result = 0;
if( !SV_IsValidEdict( ent ))
{
MsgDev( D_WARN, "SV_CheckVisibility: invalid entity %s\n", SV_ClassName( ent ));
@ -3442,6 +3472,8 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
if( i == ent->num_leafs )
return 0; // not visible
result = 1; // visible passed by leafs
}
else
{
@ -3454,6 +3486,8 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
// too many leafs for individual check, go by headnode
if( !SV_HeadnodeVisible( node, pset ))
return 0;
result = 2; // visible passed by headnode
}
#if 0
@ -3462,9 +3496,10 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
{
if( !CM_BoxVisible( ent->v.absmin, ent->v.absmax, pset ))
return 0;
result = 3; // visible passed by BoxVisible
}
#endif
return 1;
return result;
}
/*
@ -3520,8 +3555,18 @@ pfnCreateInstancedBaseline
*/
int pfnCreateInstancedBaseline( int classname, struct entity_state_s *baseline )
{
// FIXME: implement
return 0;
int i;
if( !baseline ) return -1;
i = sv.instanced.count;
if( i > 62 ) return 0;
sv.instanced.classnames[i] = classname;
sv.instanced.baselines[i] = *baseline;
sv.instanced.count++;
return i+1;
}
/*
@ -3548,7 +3593,7 @@ int pfnGetPlayerUserId( edict_t *e )
sv_client_t *cl;
int i;
if( !svs.initialized )
if( sv.state != ss_active )
return -1;
if( !SV_ClientFromEdict( e, false ))
@ -3615,7 +3660,7 @@ void pfnGetPlayerStats( const edict_t *pClient, int *ping, int *packet_loss )
return;
}
if( ping ) *ping = cl->ping * 1000;
if( ping ) *ping = cl->ping * 1000; // this is should be cl->latency not ping!
if( packet_loss ) *packet_loss = cl->packet_loss;
}
@ -3638,7 +3683,46 @@ pfnForceUnmodified
*/
void pfnForceUnmodified( FORCE_TYPE type, float *mins, float *maxs, const char *filename )
{
// FIXME: implement
sv_consistency_t *pData;
int i;
if( !filename || !*filename )
{
Host_Error( "SV_ForceUnmodified: bad filename string.\n" );
}
if( sv.state == ss_loading )
{
for( i = 0, pData = sv.consistency_files; i < MAX_MODELS; i++, pData++ )
{
if( !pData->name )
{
pData->name = filename;
pData->force_state = type;
if( mins ) VectorCopy( mins, pData->mins );
if( maxs ) VectorCopy( maxs, pData->maxs );
return;
}
else if( !com.strcmp( filename, pData->name ))
{
return;
}
}
Host_Error( "SV_ForceUnmodified: MAX_MODELS limit exceeded\n" );
}
else
{
for( i = 0, pData = sv.consistency_files; i < MAX_MODELS; i++, pData++ )
{
if( !pData->name || com.strcmp( filename, pData->name ))
continue;
// if we are here' we found a match.
return;
}
Host_Error( "SV_ForceUnmodified: can only be done during precache\n" );
}
}
/*
@ -3652,6 +3736,56 @@ void pfnAddServerCommand( const char *cmd_name, void (*function)(void), const ch
Cmd_AddCommand( cmd_name, function, cmd_desc );
}
/*
=============
pfnVoice_GetClientListening
=============
*/
bool pfnVoice_GetClientListening( int iReceiver, int iSender )
{
int iMaxClients = sv_maxclients->integer;
if( !svs.initialized ) return false;
if( iReceiver <= 0 || iReceiver > iMaxClients || iSender <= 0 || iSender > iMaxClients )
{
MsgDev( D_ERROR, "Voice_GetClientListening: invalid client indexes (%i, %i).\n", iReceiver, iSender );
return false;
}
return ((svs.clients[iSender].listeners & ( 1 << iReceiver )) != 0 );
}
/*
=============
pfnVoice_SetClientListening
=============
*/
bool pfnVoice_SetClientListening( int iReceiver, int iSender, bool bListen )
{
int iMaxClients = sv_maxclients->integer;
if( !svs.initialized ) return false;
if( iReceiver <= 0 || iReceiver > iMaxClients || iSender <= 0 || iSender > iMaxClients )
{
MsgDev( D_ERROR, "Voice_SetClientListening: invalid client indexes (%i, %i).\n", iReceiver, iSender );
return false;
}
if( bListen )
{
svs.clients[iSender].listeners |= (1 << iReceiver);
}
else
{
svs.clients[iSender].listeners &= ~(1 << iReceiver);
}
return true;
}
/*
=============
pfnGetPlayerAuthId
@ -3663,7 +3797,38 @@ return nullstring for now
*/
const char *pfnGetPlayerAuthId( edict_t *e )
{
return "";
sv_client_t *cl;
static string result;
int i;
if( sv.state != ss_active || !SV_IsValidEdict( e ))
{
result[0] = '\0';
return result;
}
for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ )
{
if( cl->edict == e )
{
if( cl->fakeclient )
{
com.strncat( result, "BOT", sizeof( result ));
}
else if( cl->authentication_method == 0 )
{
com.snprintf( result, sizeof( result ), "%u", (uint)cl->WonID );
}
else
{
com.snprintf( result, sizeof( result ), "%s", SV_GetClientIDString( cl ));
}
return result;
}
}
result[0] = '\0';
return result;
}
// engine callbacks
@ -3810,6 +3975,8 @@ static enginefuncs_t gEngfuncs =
pfnForceUnmodified,
pfnGetPlayerStats,
pfnAddServerCommand,
pfnVoice_GetClientListening,
pfnVoice_SetClientListening,
pfnGetPlayerAuthId,
};

View File

@ -94,6 +94,9 @@ void SV_CreateBaseline( void )
if( !SV_IsValidEdict( pEdict )) continue;
SV_BaselineForEntity( pEdict );
}
// create the instanced baselines
svgame.dllFuncs.pfnCreateInstancedBaselines();
}
/*

View File

@ -40,6 +40,7 @@ cvar_t *sv_waterfriction;
cvar_t *sv_synchthink;
cvar_t *sv_stopspeed;
cvar_t *hostname;
cvar_t *sv_lighting_modulate;
cvar_t *sv_maxclients;
cvar_t *sv_check_errors;
cvar_t *sv_footsteps;
@ -621,6 +622,7 @@ void SV_Init( void )
physinfo = Cvar_Get( "@physinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
serverinfo = Cvar_Get( "@serverinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
public_server = Cvar_Get ("public", "0", 0, "change server type from private to public" );
sv_lighting_modulate = Cvar_Get( "r_lighting_modulate", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lightstyles modulate scale" );
sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE, "max reconnect attempts" );
sv_failuretime = Cvar_Get( "sv_failuretime", "0.5", 0, "after this long without a packet from client, don't send any more until client starts sending again" );
sv_unlag = Cvar_Get( "sv_unlag", "1", 0, "allow lag compensation on server-side" );

View File

@ -1577,7 +1577,7 @@ void SV_Physics( void )
}
// animate lightstyles (used for GetEntityIllum)
CM_RunLightStyles( sv.time );
SV_RunLightStyles ();
// at end of frame kill all entities which supposed to it
SV_FreeOldEntities();

View File

@ -28,6 +28,8 @@ typedef struct moveclip_s
int hull; // -1 to let entity select hull
} moveclip_t;
static int sv_lastofs; // lightstyles code use this
/*
===============================================================================
@ -336,9 +338,17 @@ SV_ClearWorld
*/
void SV_ClearWorld( void )
{
sv_lightstyle_t *ls;
int i;
SV_InitBoxHull(); // for box testing
SV_InitStudioHull(); // for hitbox testing
// clear lightstyles
for( i = 0, ls = sv.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
VectorSet( sv.lightstyle[i].rgb, 1.0f, 1.0f, 1.0f );
sv_lastofs = -1;
Mem_Set( sv_areanodes, 0, sizeof( sv_areanodes ));
sv_numareanodes = 0;
@ -1360,4 +1370,184 @@ trace_t SV_MoveToss( edict_t *tossent, edict_t *ignore )
VectorCopy( original_avelocity, tossent->v.avelocity );
return trace;
}
/*
===============================================================================
LIGHTING INFO
===============================================================================
*/
static vec3_t sv_pointColor;
static float sv_modulate;
/*
=================
SV_RecursiveLightPoint
=================
*/
static bool SV_RecursiveLightPoint( mnode_t *node, const vec3_t start, const vec3_t end )
{
int side;
mplane_t *plane;
msurface_t *surf;
mtexinfo_t *tex;
vec3_t mid, scale;
float front, back, frac;
int i, map, size, s, t;
byte *lm;
// didn't hit anything
if( !node->plane ) return false;
// calculate mid point
plane = node->plane;
if( plane->type < 3 )
{
front = start[plane->type] - plane->dist;
back = end[plane->type] - plane->dist;
}
else
{
front = DotProduct( start, plane->normal ) - plane->dist;
back = DotProduct( end, plane->normal ) - plane->dist;
}
side = front < 0;
if(( back < 0 ) == side )
return SV_RecursiveLightPoint( node->children[side], start, end );
frac = front / ( front - back );
VectorLerp( start, frac, end, mid );
// co down front side
if( SV_RecursiveLightPoint( node->children[side], start, mid ))
return true; // hit something
if(( back < 0 ) == side )
return false;// didn't hit anything
// check for impact on this node
surf = node->firstface;
for( i = 0; i < node->numfaces; i++, surf++ )
{
tex = surf->texinfo;
if( surf->flags & SURF_DRAWTILED )
continue; // no lightmaps
s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0];
t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1];
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
continue;
s >>= 4;
t >>= 4;
if( !surf->samples )
return true;
VectorClear( sv_pointColor );
lm = surf->samples + 3 * (t * ((surf->extents[0] >> 4) + 1) + s);
size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1) * 3;
for( map = 0; map < surf->numstyles; map++ )
{
VectorScale( sv.lightstyle[surf->styles[map]].rgb, sv_modulate, scale );
sv_pointColor[0] += lm[0] * scale[0];
sv_pointColor[1] += lm[1] * scale[1];
sv_pointColor[2] += lm[2] * scale[2];
lm += size; // skip to next lightmap
}
return true;
}
// go down back side
return SV_RecursiveLightPoint( node->children[!side], mid, end );
}
void SV_RunLightStyles( void )
{
int i, ofs;
sv_lightstyle_t *ls;
float l;
// run lightstyles animation
ofs = (sv.time * 10);
if( ofs == sv_lastofs ) return;
sv_lastofs = ofs;
for( i = 0, ls = sv.lightstyle; i < MAX_LIGHTSTYLES; i++, ls++ )
{
if( ls->length == 0 ) l = 0.0f;
else if( ls->length == 1 ) l = ls->map[0];
else l = ls->map[ofs%ls->length];
VectorSet( ls->rgb, l, l, l );
}
}
/*
==================
SV_AddLightStyle
needs to get correct working SV_LightPoint
==================
*/
void SV_SetLightStyle( int style, const char* s )
{
int j, k;
j = com.strlen( s );
sv.lightstyle[style].length = j;
for( k = 0; k < j; k++ )
sv.lightstyle[style].map[k] = (float)( s[k]-'a' ) / (float)( 'm'-'a' );
}
/*
==================
SV_LightForEntity
grab the ambient lighting color for current point
==================
*/
int SV_LightForEntity( edict_t *pEdict )
{
vec3_t start, end;
if( !pEdict ) return 0;
if( pEdict->v.effects & EF_FULLBRIGHT || !sv.worldmodel->lightdata )
{
return 255;
}
if( pEdict->v.flags & FL_CLIENT )
{
// client has more precision light level
// that come from client
return pEdict->v.light_level;
}
VectorCopy( pEdict->v.origin, start );
VectorCopy( pEdict->v.origin, end );
if( pEdict->v.effects & EF_INVLIGHT )
end[2] = start[2] + 8192;
else end[2] = start[2] - 8192;
VectorSet( sv_pointColor, 1.0f, 1.0f, 1.0f );
sv_modulate = sv_lighting_modulate->value * (1.0f / 255);
SV_RecursiveLightPoint( worldmodel->nodes, start, end );
return VectorAvg( sv_pointColor );
}