16 Feb 2018

This commit is contained in:
g-cont 2018-02-16 00:00:00 +03:00 committed by Alibek Omarov
parent 69910228a0
commit 3090953beb
44 changed files with 840 additions and 369 deletions

View File

@ -80,9 +80,9 @@ void CL_PlayCDTrack_f( void )
if( Q_isdigit( pszTrack ))
{
track = bound( 1, Q_atoi( Cmd_Argv( 2 )), MAX_CDTRACKS );
S_StartBackgroundTrack( clgame.cdtracks[track-1], NULL, 0 );
S_StartBackgroundTrack( clgame.cdtracks[track-1], NULL, 0, false );
}
else S_StartBackgroundTrack( pszTrack, NULL, 0 );
else S_StartBackgroundTrack( pszTrack, NULL, 0, true );
paused = false;
looped = false;
}
@ -91,9 +91,9 @@ void CL_PlayCDTrack_f( void )
if( Q_isdigit( pszTrack ))
{
track = bound( 1, Q_atoi( Cmd_Argv( 2 )), MAX_CDTRACKS );
S_StartBackgroundTrack( clgame.cdtracks[track-1], clgame.cdtracks[track-1], 0 );
S_StartBackgroundTrack( clgame.cdtracks[track-1], clgame.cdtracks[track-1], 0, false );
}
else S_StartBackgroundTrack( pszTrack, pszTrack, 0 );
else S_StartBackgroundTrack( pszTrack, pszTrack, 0, true );
paused = false;
looped = true;
}

View File

@ -268,7 +268,7 @@ so that we can play the demo correctly.
*/
void CL_WriteDemoSequence( file_t *file )
{
Assert( file );
Assert( file != NULL );
FS_Write( file, &cls.netchan.incoming_sequence, sizeof( int ));
FS_Write( file, &cls.netchan.incoming_acknowledged, sizeof( int ));

View File

@ -28,7 +28,7 @@ CL_ResetEvent
void CL_ResetEvent( event_info_t *ei )
{
ei->index = 0;
memset( &ei->args, 0, sizeof( ei->args ) );
memset( &ei->args, 0, sizeof( ei->args ));
ei->fire_time = 0.0;
ei->flags = 0;
}

View File

@ -801,7 +801,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
// delta from previous state
bufStart = MSG_GetNumBytesRead( msg );
CL_DeltaEntity( msg, newframe, newnum, oldent, true );
if( CL_IsPlayerIndex( newnum ) )
if( CL_IsPlayerIndex( newnum ))
playerbytes += MSG_GetNumBytesRead( msg ) - bufStart;
oldindex++;
@ -822,7 +822,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
// delta from baseline ?
bufStart = MSG_GetNumBytesRead( msg );
CL_DeltaEntity( msg, newframe, newnum, NULL, true );
if( CL_IsPlayerIndex( newnum ) )
if( CL_IsPlayerIndex( newnum ))
playerbytes += MSG_GetNumBytesRead( msg ) - bufStart;
continue;
}

View File

@ -109,7 +109,7 @@ cl_entity_t *CL_GetEntityByIndex( int index )
return NULL;
if( index == 0 )
return cl.world;
return clgame.entities;
return CL_EDICT_NUM( index );
}
@ -1057,19 +1057,21 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
void CL_FreeEntity( cl_entity_t *pEdict )
{
Assert( pEdict );
Assert( pEdict != NULL );
R_RemoveEfrags( pEdict );
CL_KillDeadBeams( pEdict );
}
void CL_ClearWorld( void )
{
cl.world = clgame.entities;
cl.world->curstate.modelindex = 1; // world model
cl.world->curstate.solid = SOLID_BSP;
cl.world->curstate.movetype = MOVETYPE_PUSH;
cl.world->model = cl.worldmodel;
cl.world->index = 0;
cl_entity_t *world;
world = clgame.entities;
world->curstate.modelindex = 1; // world model
world->curstate.solid = SOLID_BSP;
world->curstate.movetype = MOVETYPE_PUSH;
world->model = cl.worldmodel;
world->index = 0;
clgame.ds.cullMode = GL_FRONT;
clgame.numStatics = 0;
@ -1615,7 +1617,7 @@ pfnServerCmd
*/
static int pfnServerCmd( const char *szCmdString )
{
string buf;
string buf;
if( !szCmdString || !szCmdString[0] )
return 0;
@ -2553,7 +2555,7 @@ void PlayerInfo_SetValueForKey( const char *key, const char *value )
convar_t *var;
if( !Q_strcmp( Info_ValueForKey( cls.userinfo, key ), value ))
return; // not changes ?
return; // no changes ?
var = Cvar_FindVar( key );
@ -2576,10 +2578,15 @@ pfnGetPlayerUniqueID
*/
qboolean pfnGetPlayerUniqueID( int iPlayer, char playerID[16] )
{
// TODO: implement
if( iPlayer < 1 || iPlayer > cl.maxclients )
return false;
playerID[0] = '\0';
return false;
// make sure there is a player here..
if( !cl.players[iPlayer-1].userinfo[0] || !cl.players[iPlayer-1].name[0] )
return false;
memcpy( playerID, cl.players[iPlayer-1].hashedcdkey, 16 );
return true;
}
/*
@ -3674,7 +3681,7 @@ void CL_UnloadProgs( void )
VGui_Shutdown();
// NOTE: HLFX 0.5 has strange bug: hanging on exit if no map was loaded
if( !( !Q_stricmp( GI->gamedir, "hlfx" ) && GI->version == 0.5f ))
if( Q_stricmp( GI->gamedir, "hlfx" ) || GI->version != 0.5f )
clgame.dllFuncs.pfnShutdown();
Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
@ -3705,10 +3712,6 @@ qboolean CL_LoadProgs( const char *name )
clgame.mempool = Mem_AllocPool( "Client Edicts Zone" );
clgame.entities = NULL;
// NOTE: important stuff! vgui must startup BEFORE loading client.dll
// to avoid get error ERROR_NOACESS during LoadLibrary
VGui_Startup ();
clgame.hInstance = Com_LoadLibrary( name, false );
if( !clgame.hInstance ) return false;
@ -3804,6 +3807,9 @@ qboolean CL_LoadProgs( const char *name )
CL_InitStudioAPI( );
// initialize VGui
VGui_Startup ();
// trying to grab them from client.dll
cl_righthand = Cvar_FindVar( "cl_righthand" );

View File

@ -896,7 +896,7 @@ pfnStartBackgroundTrack
*/
static void pfnStartBackgroundTrack( const char *introTrack, const char *mainTrack )
{
S_StartBackgroundTrack( introTrack, mainTrack, 0 );
S_StartBackgroundTrack( introTrack, mainTrack, 0, false );
// HACKHACK to remove glitches from background track while new game is started.
if( !introTrack && !mainTrack )

View File

@ -148,75 +148,6 @@ int CL_IsDevOverviewMode( void )
return 0;
}
/*
===============
CL_ChangeGame
This is experiment. Use with precaution
===============
*/
qboolean CL_ChangeGame( const char *gamefolder, qboolean bReset )
{
if( host.type == HOST_DEDICATED )
return false;
if( Q_stricmp( host.gamefolder, gamefolder ))
{
kbutton_t *mlook, *jlook;
qboolean mlook_active = false, jlook_active = false;
string mapname, maptitle;
int maxEntities;
mlook = (kbutton_t *)clgame.dllFuncs.KB_Find( "in_mlook" );
jlook = (kbutton_t *)clgame.dllFuncs.KB_Find( "in_jlook" );
if( mlook && ( mlook->state & 1 ))
mlook_active = true;
if( jlook && ( jlook->state & 1 ))
jlook_active = true;
// so reload all images (remote connect)
Mod_ClearAll( true );
R_ShutdownImages();
FS_LoadGameInfo( (bReset) ? host.gamefolder : gamefolder );
R_InitImages();
// save parms
maxEntities = clgame.maxEntities;
Q_strncpy( mapname, clgame.mapname, MAX_STRING );
Q_strncpy( maptitle, clgame.maptitle, MAX_STRING );
if( !CL_LoadProgs( va( "%s/client.dll", GI->dll_path )))
Host_Error( "can't initialize client.dll\n" );
// restore parms
clgame.maxEntities = maxEntities;
Q_strncpy( clgame.mapname, mapname, MAX_STRING );
Q_strncpy( clgame.maptitle, maptitle, MAX_STRING );
// invalidate fonts so we can reloading them again
memset( &cls.creditsFont, 0, sizeof( cls.creditsFont ));
SCR_InstallParticlePalette();
SCR_LoadCreditsFont();
Con_InvalidateFonts();
SCR_RegisterTextures ();
CL_FreeEdicts ();
SCR_VidInit ();
if( cls.key_dest == key_game ) // restore mouse state
clgame.dllFuncs.IN_ActivateMouse();
// restore mlook state
if( mlook_active ) Cmd_ExecuteString( "+mlook\n" );
if( jlook_active ) Cmd_ExecuteString( "+jlook\n" );
return true;
}
return false;
}
/*
===============
CL_CheckClientState
@ -231,13 +162,17 @@ void CL_CheckClientState( void )
{
// first update is the final signon stage
cls.state = ca_active;
cls.changelevel = false;
cls.changedemo = false;
cls.changelevel = false; // changelevel is done
cls.changedemo = false; // changedemo is done
cl.first_frame = true;
Cvar_SetValue( "scr_loading", 0.0f );
SCR_MakeLevelShot(); // make levelshot if needs
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
Netchan_ReportFlow( &cls.netchan );
SCR_MakeLevelShot();
if(( cls.demoplayback || cls.disable_servercount != cl.servercount ) && cl.video_prepped )
SCR_EndLoadingPlaque(); // get rid of loading plaque
cl.first_frame = true;
}
}
@ -266,7 +201,7 @@ static float CL_LerpPoint( void )
return 1.0f;
}
if( cl_interp->value > 0.001f )
if( cl_interp->value > 0.001f && !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
{
// manual lerp value (goldsrc mode)
frac = ( cl.time - cl.mtime[0] ) / cl_interp->value;
@ -623,13 +558,13 @@ void CL_CreateCmd( void )
// message we are constructing.
i = cls.netchan.outgoing_sequence & CL_UPDATE_MASK;
pcmd = &cl.commands[i];
pcmd->processedfuncs = false;
if( !cls.demoplayback )
{
pcmd->senttime = host.realtime;
memset( &pcmd->cmd, 0, sizeof( pcmd->cmd ));
pcmd->receivedtime = -1.0;
pcmd->processedfuncs = false;
pcmd->heldback = false;
pcmd->sendsize = 0;
CL_ApplyAddAngle();
@ -910,6 +845,38 @@ void CL_Drop( void )
CL_Disconnect();
}
/*
=======================
CL_GetCDKeyHash()
Connections will now use a hashed cd key value
=======================
*/
char *CL_GetCDKeyHash( void )
{
const char *keyBuffer;
static char szHashedKeyBuffer[256];
int nKeyLength = 0;
byte digest[17]; // The MD5 Hash
MD5Context_t ctx;
keyBuffer = Sys_GetMachineKey( &nKeyLength );
// now get the md5 hash of the key
memset( &ctx, 0, sizeof( ctx ));
memset( digest, 0, sizeof( digest ));
MD5Init( &ctx );
MD5Update( &ctx, (byte *)keyBuffer, nKeyLength );
MD5Final( digest, &ctx );
digest[16] = '\0';
memset( szHashedKeyBuffer, 0, 256 );
Q_strncpy( szHashedKeyBuffer, MD5_Print( digest ), sizeof( szHashedKeyBuffer ));
return szHashedKeyBuffer;
}
/*
=======================
CL_SendConnectPacket
@ -920,8 +887,10 @@ connect.
*/
void CL_SendConnectPacket( void )
{
char protinfo[MAX_INFO_STRING];
char *qport;
char *key;
netadr_t adr;
int port;
if( !NET_StringToAdr( cls.servername, &adr ))
{
@ -931,9 +900,14 @@ void CL_SendConnectPacket( void )
}
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
port = Cvar_VariableValue( "net_qport" );
qport = Cvar_VariableString( "net_qport" );
key = CL_GetCDKeyHash();
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i %i \"%s\"\n", PROTOCOL_VERSION, port, cls.challenge, cls.userinfo );
memset( protinfo, 0, sizeof( protinfo ));
Info_SetValueForKey( protinfo, "uuid", key, sizeof( protinfo ));
Info_SetValueForKey( protinfo, "qport", qport, sizeof( protinfo ));
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, cls.challenge, protinfo, cls.userinfo );
}
/*
@ -1167,9 +1141,6 @@ void CL_Disconnect( void )
cls.state = ca_disconnected;
cls.signon = 0;
// restore gamefolder here (in case client was connected to another game)
CL_ChangeGame( GI->gamefolder, true );
// back to menu if developer mode set to "player" or "mapper"
if( host.developer > 2 || CL_IsInMenu( ))
return;
@ -1179,7 +1150,9 @@ void CL_Disconnect( void )
void CL_Disconnect_f( void )
{
Host_Error( "Disconnected from server\n" );
if( Host_IsLocalClient( ))
Host_EndGame( "disconnected from server\n" );
else CL_Disconnect();
}
void CL_Crashed( void )
@ -1660,9 +1633,9 @@ void CL_PrepVideo( void )
if( host.developer <= 2 )
Con_ClearNotify(); // clear any lines of console text
SCR_UpdateScreen ();
cl.video_prepped = true;
SCR_UpdateScreen ();
}
/*
@ -1743,7 +1716,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !Q_strcmp( c, "print" ))
{
// print command from somewhere
Msg( "remote: %s\n", MSG_ReadString( msg ));
Msg( "%s", MSG_ReadString( msg ));
}
else if( !Q_strcmp( c, "ping" ))
{
@ -1766,7 +1739,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
{
// a disconnect message from the server, which will happen if the server
// dropped the connection but it is still getting packets from us
CL_Disconnect();
CL_Disconnect_f();
}
else if( !Q_strcmp( c, "f" ))
{
@ -2222,6 +2195,7 @@ void CL_InitLocal( void )
cl_lw = Cvar_Get( "cl_lw", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
Cvar_Get( "cl_lc", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable lag compensation" );
Cvar_Get( "msg", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "message filter for server notifications" );
Cvar_Get( "password", "", FCVAR_USERINFO, "server password" );
Cvar_Get( "team", "", FCVAR_USERINFO, "player team" );
Cvar_Get( "skin", "", FCVAR_USERINFO, "player skin" );

View File

@ -45,7 +45,7 @@ const char *svc_strings[256] =
"svc_updateuserinfo",
"svc_deltatable",
"svc_clientdata",
"svc_stopsound",
"svc_studiodecal",
"svc_pings",
"svc_particle",
"svc_restoresound",
@ -58,7 +58,7 @@ const char *svc_strings[256] =
"svc_centerprint",
"svc_modelindex",
"svc_soundindex",
"svc_ambientsound",
"svc_eventindex",
"svc_intermission",
"svc_finale",
"svc_cdtrack",
@ -81,9 +81,9 @@ const char *svc_strings[256] =
"svc_filetxferfailed",
"svc_hltv",
"svc_director",
"svc_studiodecal",
"svc_voiceinit",
"svc_voicedata",
"svc_eventindex",
"svc_unused54",
"svc_unused55",
"svc_resourcelocation",
"svc_querycvarvalue",
@ -267,15 +267,15 @@ void CL_ParseSoundPacket( sizebuf_t *msg )
sound = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
chan = MSG_ReadUBitLong( msg, MAX_SND_CHAN_BITS );
if( flags & SND_VOLUME )
if( FBitSet( flags, SND_VOLUME ))
volume = (float)MSG_ReadByte( msg ) / 255.0f;
else volume = VOL_NORM;
if( flags & SND_ATTENUATION )
if( FBitSet( flags, SND_ATTENUATION ))
attn = (float)MSG_ReadByte( msg ) / 64.0f;
else attn = ATTN_NONE;
if( flags & SND_PITCH )
if( FBitSet( flags, SND_PITCH ))
pitch = MSG_ReadByte( msg );
else pitch = PITCH_NORM;
@ -285,11 +285,11 @@ void CL_ParseSoundPacket( sizebuf_t *msg )
// positioned in space
MSG_ReadVec3Coord( msg, pos );
if( flags & SND_SENTENCE )
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
if( flags & SND_SEQUENCE )
if( FBitSet( flags, SND_SEQUENCE ))
Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound );
else Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
@ -303,6 +303,7 @@ void CL_ParseSoundPacket( sizebuf_t *msg )
return; // too early
}
// g-cont. sound and ambient sound have only difference with channel
if( chan == CHAN_STATIC )
{
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
@ -658,6 +659,28 @@ void CL_ParseCustomization( sizebuf_t *msg )
// TODO: ???
}
/*
==================
CL_ParseResourceRequest
==================
*/
void CL_ParseResourceRequest( sizebuf_t *msg )
{
// TODO: ???
}
/*
==================
CL_ParseFileTransferFailed
==================
*/
void CL_ParseFileTransferFailed( sizebuf_t *msg )
{
// TODO: ???
}
/*
=====================================================================
@ -729,6 +752,9 @@ void CL_ParseServerData( sizebuf_t *msg )
// multiplayer game?
if( cl.maxclients != 1 )
{
// loading user settings
CSCR_LoadDefaultCVars( "user.scr" );
if( r_decals->value > mp_decals.value )
Cvar_SetValue( "r_decals", mp_decals.value );
}
@ -752,10 +778,7 @@ void CL_ParseServerData( sizebuf_t *msg )
// continue playing if we are changing level
S_StopBackgroundTrack ();
}
#if 0
// NOTE: this is not tested as well. Use with precaution
CL_ChangeGame( gamefolder, false );
#endif
if( !cls.changedemo )
UI_SetActiveMenu( cl.background );
else if( !cls.demoplayback )
@ -1084,6 +1107,33 @@ void CL_ParseCrosshairAngle( sizebuf_t *msg )
cl.crosshairangle[2] = 0.0f; // not used for screen space
}
/*
================
CL_ParseRestore
reading decals, etc.
================
*/
void CL_ParseRestore( sizebuf_t *msg )
{
string filename;
int i, mapCount;
char *pMapName;
// mapname.HL2
Q_strncpy( filename, MSG_ReadString( msg ), sizeof( filename ));
mapCount = MSG_ReadByte( msg );
// g-cont. acutally in Xash3D this does nothing.
// decals already restored on a server, and correctly transferred through levels
// but i'm leave this message for backward compatibility
for( i = 0; i < mapCount; i++ )
{
pMapName = MSG_ReadString( msg );
MsgDev( D_INFO, "Loading decals from %s\n", pMapName );
}
}
/*
================
CL_RegisterUserMessage
@ -1137,6 +1187,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg )
player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" ));
player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" ));
player->spectator = Q_atoi( Info_ValueForKey( player->userinfo, "*hltv" ));
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
}
@ -1322,6 +1373,39 @@ void CL_ParseResourceList( sizebuf_t *msg )
}
}
/*
==================
CL_ParseVoiceInit
==================
*/
void CL_ParseVoiceInit( sizebuf_t *msg )
{
// TODO: ???
}
/*
==================
CL_ParseVoiceData
==================
*/
void CL_ParseVoiceData( sizebuf_t *msg )
{
// TODO: ???
}
/*
==================
CL_ParseResLocation
==================
*/
void CL_ParseResLocation( sizebuf_t *msg )
{
// TODO: ???
}
/*
==============
CL_ParseHLTV
@ -1675,6 +1759,8 @@ ACTION MESSAGES
/*
=====================
CL_ParseServerMessage
INTERNAL RESOURCE
=====================
*/
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
@ -1712,7 +1798,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
// mark start position
bufStart = MSG_GetNumBytesRead( msg );
// end of message
// end of message (align bits)
if( MSG_GetNumBitsLeft( msg ) < 8 )
break;
@ -1734,6 +1820,10 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
CL_Drop ();
Host_AbortCurrentFrame ();
break;
case svc_event:
CL_ParseEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_changing:
if( MSG_ReadOneBit( msg ))
{
@ -1763,7 +1853,6 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
CL_ParseViewEntity( msg );
break;
case svc_sound:
case svc_ambientsound:
CL_ParseSoundPacket( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
@ -1772,16 +1861,18 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
break;
case svc_print:
i = MSG_ReadByte( msg );
MsgDev( D_INFO, "^6%s", MSG_ReadString( msg ));
if( i == PRINT_CHAT ) S_StartLocalSound( "common/menu2.wav", VOL_NORM, false );
MsgDev( D_INFO, "^5%s", MSG_ReadString( msg ));
if( i == PRINT_CHAT )
{
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
S_StartLocalSound( "misc/talk.wav", VOL_NORM, false );
else S_StartLocalSound( "common/menu2.wav", VOL_NORM, false );
}
break;
case svc_stufftext:
s = MSG_ReadString( msg );
Cbuf_AddText( s );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
@ -1789,29 +1880,25 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
case svc_lightstyle:
CL_ParseLightStyle( msg );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
case svc_clientdata:
CL_ParseClientData( msg );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntities( msg, true );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
case svc_studiodecal:
CL_ParseStudioDecal( msg );
break;
case svc_pings:
CL_UpdateUserPings( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg );
break;
case svc_particle:
CL_ParseParticles( msg );
break;
@ -1822,8 +1909,9 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_spawnstatic:
CL_ParseStaticEntity( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
case svc_event_reliable:
CL_ParseReliableEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_ParseBaseline( msg );
@ -1838,56 +1926,36 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_signonnum:
CL_ParseSignon( msg );
break;
case svc_deltamovevars:
CL_ParseMovevars( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_event:
CL_ParseEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_modelindex:
CL_PrecacheModel( msg );
break;
case svc_soundindex:
CL_PrecacheSound( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
case svc_eventindex:
CL_PrecacheEvent( msg );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_cdtrack:
param1 = MSG_ReadByte( msg );
param1 = bound( 1, param1, MAX_CDTRACKS ); // tracknum
param2 = MSG_ReadByte( msg );
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0 );
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
break;
case svc_eventindex:
CL_PrecacheEvent( msg );
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_weaponanim:
param1 = MSG_ReadByte( msg ); // iAnim
@ -1901,6 +1969,22 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
param1 = MSG_ReadShort( msg );
Cvar_SetValue( "room_type", param1 );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntities( msg, true );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
@ -1908,14 +1992,38 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_resourcelist:
CL_ParseResourceList( msg );
break;
case svc_director:
CL_ParseDirector( msg );
case svc_deltamovevars:
CL_ParseMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_studiodecal:
CL_ParseStudioDecal( msg );
case svc_director:
CL_ParseDirector( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg );

View File

@ -1219,8 +1219,8 @@ void CL_PredictMovement( qboolean repredicting )
frame_t *frame = NULL;
int i, stoppoint;
qboolean runfuncs;
double f = 1.0;
double time;
float f;
if( cls.state != ca_active || cls.spectator )
return;
@ -1284,6 +1284,11 @@ void CL_PredictMovement( qboolean repredicting )
if( to_cmd->senttime >= host.realtime )
break;
// now interpolate some fraction of the final frame
if( to_cmd->senttime != from_cmd->senttime )
f = (host.realtime - from_cmd->senttime) / (to_cmd->senttime - from_cmd->senttime) * 0.1;
from = to;
from_cmd = to_cmd;
}
@ -1316,18 +1321,8 @@ void CL_PredictMovement( qboolean repredicting )
return;
}
// now interpolate some fraction of the final frame
if( to_cmd->senttime == from_cmd->senttime )
{
f = 0.0f;
}
else
{
f = (host.realtime - from_cmd->senttime) / (to_cmd->senttime - from_cmd->senttime);
f = bound( 0.0f, f, 1.0f );
}
if( f != 1.0f && f != 0.0f ) Msg( "Predict interp: %g\n", f );
f = bound( 0.0f, f, 1.0f );
f = 0.0; // FIXME: make work, do revision
if( CL_PlayerTeleported( from, to ))
{

View File

@ -2412,7 +2412,7 @@ void CL_SetLightstyle( int style, const char *s, float f )
lightstyle_t *ls;
float val1, val2;
Assert( s );
Assert( s != NULL );
Assert( style >= 0 && style < MAX_LIGHTSTYLES );
ls = &cl.lightstyles[style];

View File

@ -239,6 +239,9 @@ typedef struct
int maxclients;
int num_custombeams; // server beams count
entity_state_t instanced_baseline[MAX_CUSTOM_BASELINES];
int instanced_baseline_count;
char model_precache[MAX_MODELS][MAX_QPATH];
char sound_precache[MAX_SOUNDS][MAX_QPATH];
char event_precache[MAX_EVENTS][MAX_QPATH];
@ -247,7 +250,6 @@ typedef struct
short sound_index[MAX_SOUNDS];
short decal_index[MAX_DECALS];
cl_entity_t *world;
model_t *worldmodel; // pointer to world
} client_t;
@ -936,7 +938,7 @@ void Con_FastClose( void );
// s_main.c
//
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data );
void S_StartBackgroundTrack( const char *intro, const char *loop, long position );
void S_StartBackgroundTrack( const char *intro, const char *loop, long position, qboolean fullpath );
void S_StopBackgroundTrack( void );
void S_StreamSetPause( int pause );
void S_StartStreaming( void );

View File

@ -1180,11 +1180,16 @@ void R_SetupAliasFrame( cl_entity_t *e, aliashdr_t *paliashdr )
oldframe = e->latched.prevframe;
newframe = e->curstate.frame;
if(( newframe >= paliashdr->numframes ) || ( newframe < 0 ))
if( newframe < 0 )
{
MsgDev( D_ERROR, "R_SetupAliasFrame: no such frame %d\n", newframe );
newframe = 0;
}
else if( newframe >= paliashdr->numframes )
{
if( newframe > paliashdr->numframes )
MsgDev( D_WARN, "R_GetAliasFrame: no such frame %d (%s)\n", newframe, e->model->name );
newframe = paliashdr->numframes - 1;
}
if(( oldframe >= paliashdr->numframes ) || ( oldframe < 0 ))
oldframe = newframe;

View File

@ -693,7 +693,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
mplane_t *splitplane;
float dist;
Assert( node );
Assert( node != NULL );
if( node->contents < 0 )
{

View File

@ -2037,7 +2037,8 @@ void GL_RebuildLightmaps( void )
int i, j;
model_t *m;
if( !cl.world ) return; // wait for worldmodel
if( !cl.video_prepped )
return; // wait for worldmodel
ClearBits( vid_brightness->flags, FCVAR_CHANGED );
ClearBits( vid_gamma->flags, FCVAR_CHANGED );

View File

@ -477,7 +477,7 @@ mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw )
int i, numframes;
float targettime;
Assert( pModel );
Assert( pModel != NULL );
psprite = pModel->cache.data;
if( frame < 0 )
@ -486,7 +486,8 @@ mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw )
}
else if( frame >= psprite->numframes )
{
MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name );
if( frame > psprite->numframes )
MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name );
frame = psprite->numframes - 1;
}

View File

@ -1400,7 +1400,7 @@ void R_StudioBuildNormalTable( void )
mstudiomesh_t *pmesh;
int i, j;
Assert( m_pSubModel );
Assert( m_pSubModel != NULL );
// reset chrome cache
for( i = 0; i < m_pStudioHeader->numbones; i++ )
@ -1452,7 +1452,7 @@ void R_StudioGenerateNormals( void )
mstudiomesh_t *pmesh;
int i, j;
Assert( m_pSubModel );
Assert( m_pSubModel != NULL );
for( i = 0; i < m_pSubModel->numverts; i++ )
VectorClear( g_studio.norms[i] );
@ -3583,6 +3583,8 @@ void R_DrawStudioModel( cl_entity_t *e )
{
RI.currententity = parent;
R_StudioDrawModelInternal( RI.currententity, 0 );
VectorCopy( parent->curstate.origin, e->curstate.origin );
VectorCopy( parent->origin, e->origin );
RI.currententity = e;
}
}

View File

@ -2084,13 +2084,13 @@ void S_Music_f( void )
if( FS_FileExists( intro_path, false ) && FS_FileExists( main_path, false ))
{
// combined track with introduction and main loop theme
S_StartBackgroundTrack( intro, main, 0 );
S_StartBackgroundTrack( intro, main, 0, false );
break;
}
else if( FS_FileExists( va( "media/%s.%s", track, ext[i] ), false ))
{
// single non-looped theme
S_StartBackgroundTrack( track, NULL, 0 );
S_StartBackgroundTrack( track, NULL, 0, false );
break;
}
}
@ -2098,12 +2098,12 @@ void S_Music_f( void )
}
else if( c == 3 )
{
S_StartBackgroundTrack( Cmd_Argv( 1 ), Cmd_Argv( 2 ), 0 );
S_StartBackgroundTrack( Cmd_Argv( 1 ), Cmd_Argv( 2 ), 0, false );
}
else if( c == 4 && Q_atoi( Cmd_Argv( 3 )) != 0 )
{
// restore command for singleplayer: all arguments are valid
S_StartBackgroundTrack( Cmd_Argv( 1 ), Cmd_Argv( 2 ), Q_atoi( Cmd_Argv( 3 )));
S_StartBackgroundTrack( Cmd_Argv( 1 ), Cmd_Argv( 2 ), Q_atoi( Cmd_Argv( 3 )), false );
}
else Msg( "Usage: music <musicfile> [loopfile]\n" );
}

View File

@ -68,7 +68,7 @@ float S_GetMusicVolume( void )
S_StartBackgroundTrack
=================
*/
void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, long position )
void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, long position, qboolean fullpath )
{
S_StopBackgroundTrack();
@ -89,7 +89,7 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, long
if( !mainTrack || !*mainTrack ) s_bgTrack.loopName[0] = '\0';
else Q_strncpy( s_bgTrack.loopName, mainTrack, sizeof( s_bgTrack.loopName ));
if( fullpath ) Msg( "MP3:Playing: %s\n", introTrack );
// open stream
s_bgTrack.stream = FS_OpenStream( va( "media/%s", introTrack ));
Q_strncpy( s_bgTrack.current, introTrack, sizeof( s_bgTrack.current ));

View File

@ -457,7 +457,7 @@ void CEngineSurface :: popMakeCurrent( Panel *panel )
Assert( top >= 0 );
// didn't pop in reverse order of push?
Assert( paintStack[top]->m_pPanel == panel );
Assert( paintStack[top].m_pPanel == panel );
staticPaintStackPos--;

View File

@ -700,6 +700,9 @@ void Con_Printf( char *szFmt, ... )
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
va_end( args );
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
return; // hlrally spam
Sys_Print( buffer );
}
@ -721,6 +724,9 @@ void Con_DPrintf( char *szFmt, ... )
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
va_end( args );
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
return; // hlrally spam
Sys_Print( buffer );
}

View File

@ -655,7 +655,6 @@ void Host_EndGame( const char *message, ... );
void Host_AbortCurrentFrame( void );
void Host_RestartAmbientSounds( void );
void Host_RestartDecals( void );
qboolean CL_ChangeGame( const char *gamefolder, qboolean bReset );
void Host_WriteServerConfig( const char *name );
void Host_WriteOpenGLConfig( void );
void Host_WriteVideoConfig( void );
@ -747,6 +746,7 @@ void MD5Update( MD5Context_t *ctx, const byte *buf, uint len );
void MD5Final( byte digest[16], MD5Context_t *ctx );
qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] );
uint Com_HashKey( const char *string, uint hashSize );
char *MD5_Print( byte hash[16] );
//
// cfgscript.c

View File

@ -960,7 +960,6 @@ void Host_WriteServerConfig( const char *name )
// FIXME: move this out until menu parser is done
CSCR_LoadDefaultCVars( "settings.scr" );
CSCR_LoadDefaultCVars( "user.scr" );
if(( f = FS_Open( name, "w", false )) != NULL )
{
@ -969,7 +968,6 @@ void Host_WriteServerConfig( const char *name )
FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" );
FS_Printf( f, "//=======================================================================\n" );
Cvar_WriteVariables( f, FCVAR_SERVER );
CSCR_WriteGameCVars( f, "user.scr" );
CSCR_WriteGameCVars( f, "settings.scr" );
FS_Close( f );
}

View File

@ -562,6 +562,30 @@ qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] )
return true;
}
/*
=================
MD5_Print
transform hash to hexadecimal printable symbols
=================
*/
char *MD5_Print( byte hash[16] )
{
static char szReturn[64];
byte szChunk[10];
int i;
memset( szReturn, 0, 64 );
for( i = 0; i < 16; i++ )
{
Q_snprintf( szChunk, sizeof( szChunk ), "%02X", hash[i] );
Q_strncat( szReturn, szChunk, sizeof( szReturn ));
}
return szReturn;
}
/*
=================
Com_HashKey

View File

@ -517,6 +517,10 @@ void Key_Event( int key, qboolean down )
const char *kb;
char cmd[1024];
// key was pressed before engine was run
if( !keys[key].down && !down )
return;
// update auto-repeat status and BUTTON_ANY status
keys[key].down = down;

View File

@ -517,7 +517,8 @@ static void FreeNameFuncGlobals( dll_user_t *hInst )
char *GetMSVCName( const char *in_name )
{
char *pos, *out_name;
static string out_name;
char *pos;
if( in_name[0] == '?' ) // is this a MSVC C++ mangled name?
{
@ -526,12 +527,15 @@ char *GetMSVCName( const char *in_name )
int len = pos - in_name;
// strip off the leading '?'
out_name = copystring( in_name + 1 );
Q_strncpy( out_name, in_name + 1, sizeof( out_name ));
out_name[len-1] = 0; // terminate string at the "@@"
return out_name;
}
}
return copystring( in_name );
Q_strncpy( out_name, in_name, sizeof( out_name ));
return out_name;
}
qboolean LibraryLoadSymbols( dll_user_t *hInst )
@ -718,7 +722,7 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst )
if( FS_Seek( f, name_offset, SEEK_SET ) != -1 )
{
FsGetString( f, function_name );
hInst->names[i] = GetMSVCName( function_name );
hInst->names[i] = copystring( GetMSVCName( function_name ));
}
else break;
}
@ -819,7 +823,7 @@ void *Com_GetProcAddress( void *hInstance, const char *name )
if( hInst->custom_loader )
return (void *)MemoryGetProcAddress( hInst->hInstance, name );
return (void *)GetProcAddress( hInst->hInstance, name );
return (void *)GetProcAddress( hInst->hInstance, GetMSVCName( name ));
}
void Com_FreeLibrary( void *hInstance )

View File

@ -427,7 +427,9 @@ static void SV_StudioSetupBones( model_t *pModel, float frame, int sequence, con
if( sequence < 0 || sequence >= mod_studiohdr->numseq )
{
MsgDev( D_WARN, "SV_StudioSetupBones: sequence %i/%i out of range for model %s\n", sequence, mod_studiohdr->numseq, mod_studiohdr->name );
// only show warn if sequence that out of range was specified intentionally
if( sequence > mod_studiohdr->numseq )
MsgDev( D_WARN, "SV_StudioSetupBones: sequence %i/%i out of range for model %s\n", sequence, mod_studiohdr->numseq, mod_studiohdr->name );
sequence = 0;
}

View File

@ -81,6 +81,7 @@ GNU General Public License for more details.
#define CMD_BACKUP 64 // allow a lot of command backups for very fast systems
#define CMD_MASK (CMD_BACKUP - 1)
#define NUM_PACKET_ENTITIES 256 // 170 Mb for multiplayer with 32 players
#define MAX_CUSTOM_BASELINES 64
/*
==============================================================

View File

@ -35,7 +35,7 @@ GNU General Public License for more details.
#define svc_updateuserinfo 13 // [byte] playernum, [string] userinfo
#define svc_deltatable 14 // [table header][...]
#define svc_clientdata 15 // [...]
#define svc_stopsound 16 // <see code>
#define svc_studiodecal 16 // [float*3][float*3][short][short][byte]
#define svc_pings 17 // [bit][idx][ping][packet_loss]
#define svc_particle 18 // [float*3][char*3][byte][byte]
#define svc_restoresound 19 // <see code>
@ -48,7 +48,7 @@ GNU General Public License for more details.
#define svc_centerprint 26 // [string] to put in center of the screen
#define svc_modelindex 27 // [index][modelpath]
#define svc_soundindex 28 // [index][soundpath]
#define svc_ambientsound 29 // <see code>
#define svc_eventindex 29 // [index][eventname]
#define svc_intermission 30 // empty message (event)
#define svc_finale 31 // empty message (event)
#define svc_cdtrack 32 // [string] trackname
@ -71,9 +71,9 @@ GNU General Public License for more details.
#define svc_filetxferfailed 49 // [string]
#define svc_hltv 50 // sending from the game.dll
#define svc_director 51 // <variable sized>
#define svc_studiodecal 52 // [float*3][float*3][short][short][byte]
#define svc_voiceinit 52 // <see code>
#define svc_voicedata 53 // [byte][short][...]
#define svc_eventindex 54 // [index][eventname]
// reserved
// reserved
#define svc_resourcelocation 56 // [string]
#define svc_querycvarvalue 57 // [string]

View File

@ -143,6 +143,33 @@ char *Sys_GetCurrentUser( void )
return sys_user_name;
}
/*
=================
Sys_GetMachineKey
=================
*/
const char *Sys_GetMachineKey( int *nLength )
{
HINSTANCE rpcrt4_dll = LoadLibrary( "rpcrt4.dll" );
RPC_STATUS (_stdcall *pUuidCreateSequential)( UUID __RPC_FAR *Uuid ) = NULL;
static byte key[32];
byte mac[8];
UUID uuid;
int i;
if( rpcrt4_dll ) pUuidCreateSequential = (void *)GetProcAddress( rpcrt4_dll, "UuidCreateSequential" );
if( pUuidCreateSequential ) pUuidCreateSequential( &uuid ); // ask OS to create UUID
if( rpcrt4_dll ) FreeLibrary( rpcrt4_dll ); // no need anymore...
for( i = 2; i < 8; i++ ) // bytes 2 through 7 inclusive are MAC address
mac[i-2] = uuid.Data4[i];
Q_snprintf( key, sizeof( key ), "%02X-%02X-%02X-%02X-%02X-%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
if( nLength ) *nLength = Q_strlen( key );
return key;
}
/*
=================
Sys_ShellExecute
@ -542,9 +569,6 @@ void Sys_Print( const char *pMsg )
char *c = logbuf;
int i = 0;
if( pMsg[0] == '0' && pMsg[1] == '\n' && pMsg[2] == '\0' )
return; // hlrally spam
if( host.type == HOST_NORMAL )
Con_Print( pMsg );

View File

@ -82,6 +82,7 @@ void Sys_SetClipboardData( const byte *buffer, size_t size );
#define Sys_GetParmFromCmdLine( parm, out ) _Sys_GetParmFromCmdLine( parm, out, sizeof( out ))
qboolean _Sys_GetParmFromCmdLine( char *parm, char *out, size_t size );
void Sys_ShellExecute( const char *path, const char *parms, qboolean exit );
const char *Sys_GetMachineKey( int *nLength );
void Sys_SendKeyEvents( void );
void Sys_Print( const char *pMsg );
void Sys_PrintLog( const char *pMsg );

View File

@ -143,6 +143,10 @@ SOURCE=.\common\build.c
# End Source File
# Begin Source File
SOURCE=.\common\cfgscript.c
# End Source File
# Begin Source File
SOURCE=.\client\cl_cmds.c
# End Source File
# Begin Source File

View File

@ -85,8 +85,8 @@ typedef enum
typedef struct
{
int count;
string_t classnames[64];
entity_state_t baselines[64];
string_t classnames[MAX_CUSTOM_BASELINES];
entity_state_t baselines[MAX_CUSTOM_BASELINES];
} sv_baselines_t;
typedef struct
@ -96,6 +96,14 @@ typedef struct
vec3_t mins, maxs;
} sv_consistency_t;
typedef struct
{
qboolean active;
qboolean net_log;
netadr_t net_address;
file_t *file;
} server_log_t;
// like as entity_state_t in Quake
typedef struct
{
@ -213,6 +221,8 @@ typedef struct sv_client_s
double timebase; // client timebase
double lastservertime; // check if server time was not changed so no resaon to send update
char hashedcdkey[34]; // MD5 hash is 32 hex #'s, plus trailing 0
customization_t customdata; // player customization linked list
resource_t resourcesonhand;
resource_t resourcesneeded; // <mapname.res> from client (server downloading)
@ -362,6 +372,8 @@ typedef struct
int groupmask;
int groupop;
server_log_t log;
char serverinfo[MAX_SERVERINFO_STRING];
char localinfo[MAX_LOCALINFO_STRING];
@ -389,6 +401,8 @@ extern areanode_t sv_areanodes[]; // AABB dynamic tree
extern convar_t sv_lan;
extern convar_t sv_lan_rate;
extern convar_t mp_logecho;
extern convar_t mp_logfile;
extern convar_t sv_unlag;
extern convar_t sv_maxunlag;
extern convar_t sv_unlagpush;
@ -421,6 +435,7 @@ extern convar_t sv_skyangle;
extern convar_t sv_consistency;
extern convar_t sv_spawntime;
extern convar_t sv_changetime;
extern convar_t sv_password;
extern convar_t deathmatch;
extern convar_t skill;
extern convar_t coop;
@ -606,6 +621,14 @@ _inline edict_t *SV_EDICT_NUM( int n, const char * file, const int line )
return NULL;
}
//
// sv_log.c
//
void Log_Close( void );
void Log_Open( void );
void Log_PrintServerVars( void );
void SV_ServerLog_f( void );
//
// sv_save.c
//

View File

@ -107,6 +107,84 @@ int SV_GetFragmentSize( sv_client_t *cl )
return size;
}
/*
================
SV_RejectConnection
Rejects connection request and sends back a message
================
*/
void SV_RejectConnection( netadr_t from, char *fmt, ... )
{
char text[1024];
va_list argptr;
va_start( argptr, fmt );
Q_vsnprintf( text, sizeof( text ), fmt, argptr );
va_end( argptr );
MsgDev( D_REPORT, "%s connection refused. Reason: %s\n", NET_AdrToString( from ), text );
Netchan_OutOfBandPrint( NS_SERVER, from, "print\n^1Server was reject the connection:^7 %s", text );
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
}
/*
================
SV_CheckChallenge
Make sure connecting client is not spoofing
================
*/
int SV_CheckChallenge( netadr_t from, int challenge )
{
int i;
// see if the challenge is valid
// don't care if it is a local address.
if( NET_IsLocalAddress( from ))
return 1;
for( i = 0; i < MAX_CHALLENGES; i++ )
{
if( NET_CompareAdr( from, svs.challenges[i].adr ))
{
if( challenge == svs.challenges[i].challenge )
break; // valid challenge
#if 0
// g-cont. this breaks multiple connections from single machine
SV_RejectConnection( from, "bad challenge %i\n", challenge );
return 0;
#endif
}
}
if( i == MAX_CHALLENGES )
{
SV_RejectConnection( from, "no challenge for your address\n" );
return 0;
}
svs.challenges[i].connected = true;
return 1;
}
/*
================
SV_CheckIPRestrictions
Determine if client is outside appropriate address range
================
*/
int SV_CheckIPRestrictions( netadr_t from )
{
if( !sv_lan.value )
{
if( !NET_CompareClassBAdr( from, net_local ) && !NET_IsReservedAdr( from ))
return 0;
}
return 1;
}
/*
==================
SV_DirectConnect
@ -118,26 +196,71 @@ void SV_DirectConnect( netadr_t from )
{
char userinfo[MAX_INFO_STRING];
char physinfo[MAX_PHYSINFO_STRING];
char protinfo[MAX_INFO_STRING];
sv_client_t temp, *cl, *newcl;
int qport, version;
int i, edictnum;
int count = 0;
int challenge;
edict_t *ent;
char *s;
if( Cmd_Argc() < 5 )
{
SV_RejectConnection( from, "insufficient connection info\n" );
return;
}
version = Q_atoi( Cmd_Argv( 1 ));
if( version != PROTOCOL_VERSION )
{
Netchan_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i.\n", PROTOCOL_VERSION );
MsgDev( D_ERROR, "SV_DirectConnect: rejected connect from version %i\n", version );
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
SV_RejectConnection( from, "unsupported protocol (%i should be %i)\n", version, PROTOCOL_VERSION );
return;
}
qport = Q_atoi( Cmd_Argv( 2 ));
challenge = Q_atoi( Cmd_Argv( 3 ));
Q_strncpy( userinfo, Cmd_Argv( 4 ), sizeof( userinfo ));
challenge = Q_atoi( Cmd_Argv( 2 )); // get challenge
// see if the challenge is valid (local clients don't need to challenge)
if( !SV_CheckChallenge( from, challenge ))
return;
s = Cmd_Argv( 3 ); // protocol info
if( !Info_IsValid( s ))
{
SV_RejectConnection( from, "invalid protinfo in connect command\n" );
return;
}
Q_strncpy( protinfo, s, sizeof( protinfo ));
// extract qport from protocol info
qport = Q_atoi( Info_ValueForKey( protinfo, "qport" ));
s = Info_ValueForKey( protinfo, "uuid" );
if( Q_strlen( s ) != 32 )
{
SV_RejectConnection( from, "invalid authentication certificate length\n" );
return;
}
// LAN servers restrict to class b IP addresses
if( !SV_CheckIPRestrictions( from ))
{
SV_RejectConnection( from, "LAN servers are restricted to local clients (class C)\n" );
return;
}
s = Cmd_Argv( 4 ); // user info
if( Q_strlen( s ) > MAX_INFO_STRING || !Info_IsValid( s ))
{
SV_RejectConnection( from, "invalid userinfo in connect command\n" );
return;
}
Q_strncpy( userinfo, s, sizeof( userinfo ));
// quick reject
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
@ -149,35 +272,18 @@ void SV_DirectConnect( netadr_t from )
{
if( !NET_IsLocalAddress( from ) && ( host.realtime - cl->connection_started ) < sv_reconnect_limit->value )
{
MsgDev( D_INFO, "%s:reconnect rejected : too soon\n", NET_AdrToString( from ));
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
SV_RejectConnection( from, "too soon\n" );
return;
}
break;
}
}
// see if the challenge is valid (LAN clients don't need to challenge)
if( !NET_IsLocalAddress( from ))
// check connection password (don't verify local client)
if( !NET_IsLocalAddress( from ) && sv_password.string[0] && Q_stricmp( sv_password.string, Info_ValueForKey( userinfo, "password" )))
{
for( i = 0; i < MAX_CHALLENGES; i++ )
{
if( NET_CompareAdr( from, svs.challenges[i].adr ))
{
if( challenge == svs.challenges[i].challenge )
break; // valid challenge
}
}
if( i == MAX_CHALLENGES )
{
Netchan_OutOfBandPrint( NS_SERVER, from, "print\nNo or bad challenge for address.\n" );
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
return;
}
MsgDev( D_NOTE, "Client %i connecting with challenge %p\n", i, challenge );
svs.challenges[i].connected = true;
SV_RejectConnection( from, "invalid password\n" );
return;
}
// force the IP key/value pair so the game can filter based on ip
@ -214,9 +320,7 @@ void SV_DirectConnect( netadr_t from )
if( !newcl )
{
Netchan_OutOfBandPrint( NS_SERVER, from, "print\nServer is full.\n" );
MsgDev( D_INFO, "SV_DirectConnect: rejected a connection.\n" );
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
SV_RejectConnection( from, "server is full\n" );
return;
}
@ -252,15 +356,14 @@ gotnewcl:
if( !( SV_ClientConnect( ent, userinfo )))
{
if( *Info_ValueForKey( userinfo, "rejmsg" ))
Netchan_OutOfBandPrint( NS_SERVER, from, "print\n%s\nConnection refused.\n", Info_ValueForKey( userinfo, "rejmsg" ));
else Netchan_OutOfBandPrint( NS_SERVER, from, "print\nConnection refused.\n" );
MsgDev( D_ERROR, "SV_DirectConnect: game rejected a connection.\n");
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
SV_RejectConnection( from, "%s\n", Info_ValueForKey( userinfo, "rejmsg" ));
else SV_RejectConnection( from, "game rejected a connection\n" );
SV_DropClient( newcl );
return;
}
// after this point connection is accepted
// send the connect packet to the client
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect" );
@ -270,6 +373,9 @@ gotnewcl:
newcl->cl_updaterate = 0.05; // 20 fps as default
newcl->delta_sequence = -1;
Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 );
newcl->hashedcdkey[32] = '\0';
// parse some info from the info strings (this can override cl_updaterate)
Q_strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo ));
SV_UserinfoChanged( newcl, newcl->userinfo );
@ -282,6 +388,8 @@ gotnewcl:
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
if( cl->state >= cs_connected ) count++;
Log_Printf( "\"%s<%i><%i><>\" connected, address \"%s\"\n", newcl->name, newcl->userid, i, NET_AdrToString( newcl->netchan.remote_address ));
if( count == 1 || count == svs.maxclients )
svs.last_heartbeat = MAX_HEARTBEAT;
}
@ -769,6 +877,7 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
int i;
MsgDev( D_INFO, "Rcon from %s:\n%s\n", NET_AdrToString( from ), MSG_GetData( msg ) + 4 );
Log_Printf( "Rcon: \"%s\" from \"%s\"\n", MSG_GetData( msg ) + 4, NET_AdrToString( from ));
SV_BeginRedirect( from, RD_PACKET, outputbuf, sizeof( outputbuf ) - 16, SV_FlushRedirect );
if( Rcon_Validate( ))
@ -931,8 +1040,10 @@ Writes all update values to a bitbuf
*/
void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg )
{
char info[MAX_INFO_STRING];
int i;
char info[MAX_INFO_STRING];
char digest[16];
MD5Context_t ctx;
int i;
// process userinfo before updating
SV_UserinfoChanged( cl, cl->userinfo );
@ -952,6 +1063,12 @@ void SV_FullClientUpdate( sv_client_t *cl, sizebuf_t *msg )
// remove server passwords, etc.
Info_RemovePrefixedKeys( info, '_' );
MSG_WriteString( msg, info );
MD5Init( &ctx );
MD5Update( &ctx, cl->hashedcdkey, sizeof( cl->hashedcdkey ));
MD5Final( digest, &ctx );
MSG_WriteBytes( msg, digest, sizeof( digest ));
}
else MSG_WriteOneBit( msg, 0 );
}
@ -1109,6 +1226,28 @@ void SV_PutClientInServer( sv_client_t *cl )
ent->v.fixangle = 0;
}
if( svgame.dllFuncs.pfnParmsChangeLevel )
{
SAVERESTOREDATA levelData;
string name;
int i;
memset( &levelData, 0, sizeof( levelData ));
svgame.globals->pSaveData = &levelData;
svgame.dllFuncs.pfnParmsChangeLevel();
MSG_WriteByte( &cl->netchan.message, svc_restore );
Q_snprintf( name, sizeof( name ), "save/%s.HL2", sv.name );
COM_FixSlashes( name );
MSG_WriteString( &cl->netchan.message, name );
MSG_WriteByte( &cl->netchan.message, levelData.connectionCount );
for( i = 0; i < levelData.connectionCount; i++ )
MSG_WriteString( &cl->netchan.message, levelData.levelList[i].mapName );
svgame.globals->pSaveData = NULL;
}
// reset weaponanim
MSG_BeginServerCmd( &cl->netchan.message, svc_weaponanim );
MSG_WriteByte( &cl->netchan.message, 0 );
@ -2479,7 +2618,7 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg )
SV_ParseCvarValue2( cl, msg );
break;
default:
MsgDev( D_ERROR, "SV_ReadClientMessage: clc_bad\n" );
MsgDev( D_ERROR, "clc_bad\n" );
SV_DropClient( cl );
return;
}

View File

@ -344,28 +344,6 @@ void SV_HazardCourse_f( void )
else Host_NewGame( GI->trainmap, false );
}
/*
==============
SV_EndGame_f
==============
*/
void SV_EndGame_f( void )
{
Host_EndGame( Cmd_Argv( 1 ));
}
/*
==============
SV_KillGame_f
==============
*/
void SV_KillGame_f( void )
{
Host_EndGame( "The End" );
}
/*
==============
SV_Load_f
@ -630,6 +608,7 @@ void SV_Kick_f( void )
return;
}
Log_Printf( "Kick: \"%s<%i>\" was kicked\n", svs.currentPlayer->name, svs.currentPlayer->userid );
SV_BroadcastPrintf( svs.currentPlayer, PRINT_HIGH, "%s was kicked\n", svs.currentPlayer->name );
SV_ClientPrintf( svs.currentPlayer, PRINT_HIGH, "You were kicked from the game\n" );
SV_DropClient( svs.currentPlayer );
@ -753,7 +732,7 @@ void SV_ConSay_f( void )
return;
}
Q_strncpy( text, "console: ", MAX_SYSPATH );
Q_snprintf( text, sizeof( text ), "%s: ", Cvar_VariableString( "hostname" ));
p = Cmd_Args();
if( *p == '"' )
@ -771,6 +750,7 @@ void SV_ConSay_f( void )
SV_ClientPrintf( client, PRINT_CHAT, "%s\n", text );
}
Log_Printf( "Server say: \"%s\"\n", p );
}
/*
@ -1023,11 +1003,10 @@ void SV_InitOperatorCommands( void )
Cmd_AddCommand( "entpatch", SV_EntPatch_f, "write entity patch to allow external editing" );
Cmd_AddCommand( "edict_usage", SV_EdictUsage_f, "show info about edicts usage" );
Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" );
Cmd_AddCommand( "log", SV_ServerLog_f, "logging server events" );
if( host.type == HOST_NORMAL )
{
Cmd_AddCommand( "endgame", SV_EndGame_f, "end current game" );
Cmd_AddCommand( "killgame", SV_KillGame_f, "end current game" );
Cmd_AddCommand( "save", SV_Save_f, "save the game to a file" );
Cmd_AddCommand( "savequick", SV_QuickSave_f, "save the game to the quicksave" );
Cmd_AddCommand( "autosave", SV_AutoSave_f, "save the game to 'autosave' file" );
@ -1046,6 +1025,9 @@ SV_KillOperatorCommands
*/
void SV_KillOperatorCommands( void )
{
Cvar_Reset( "public" );
Cvar_Reset( "sv_lan" );
Cmd_RemoveCommand( "heartbeat" );
Cmd_RemoveCommand( "kick" );
Cmd_RemoveCommand( "kill" );
@ -1059,11 +1041,10 @@ void SV_KillOperatorCommands( void )
Cmd_RemoveCommand( "entpatch" );
Cmd_RemoveCommand( "edict_usage" );
Cmd_RemoveCommand( "entity_info" );
Cmd_RemoveCommand( "log" );
if( host.type == HOST_NORMAL )
{
Cmd_RemoveCommand( "endgame" );
Cmd_RemoveCommand( "killgame" );
Cmd_RemoveCommand( "save" );
Cmd_RemoveCommand( "savequick" );
Cmd_RemoveCommand( "killsave" );

View File

@ -75,6 +75,8 @@ TYPEDESCRIPTION *SV_GetEntvarsDescirption( int number )
void SV_SysError( const char *error_string )
{
Log_Printf( "FATAL ERROR (shutting down): %s\n", error_string );
if( svgame.hInstance != NULL )
svgame.dllFuncs.pfnSys_Error( error_string );
}
@ -1102,7 +1104,8 @@ void pfnSetModel( edict_t *e, const char *m )
if( e == svgame.edicts )
{
MsgDev( D_ERROR, "SV_SetModel: world model can't be changed\n" );
if( sv.state == ss_active )
MsgDev( D_ERROR, "SV_SetModel: world model can't be changed\n" );
return;
}
@ -2036,7 +2039,7 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vo
// not sending (because this is out of range)
flags &= ~SND_SPAWNING;
MSG_BeginServerCmd( &sv.multicast, svc_ambientsound );
MSG_BeginServerCmd( &sv.multicast, svc_sound );
MSG_WriteUBitLong( &sv.multicast, flags, MAX_SND_FLAGS_BITS );
MSG_WriteUBitLong( &sv.multicast, sound_idx, MAX_SOUND_BITS );
MSG_WriteUBitLong( &sv.multicast, CHAN_STATIC, MAX_SND_CHAN_BITS );
@ -2838,6 +2841,10 @@ static void pfnAlertMessage( ALERT_TYPE level, char *szFmt, ... )
if( host.developer < D_ERROR )
return;
break;
case at_logged:
if( svs.maxclients <= 1 )
return;
break;
}
va_start( args, szFmt );
@ -2848,10 +2855,14 @@ static void pfnAlertMessage( ALERT_TYPE level, char *szFmt, ... )
{
Sys_Print( va( "^3Warning:^7 %s", buffer ));
}
else if( level == at_error )
else if( level == at_error )
{
Sys_Print( va( "^1Error:^7 %s", buffer ));
}
else if( level == at_logged )
{
Log_Printf( "%s", buffer );
}
else
{
Sys_Print( buffer );
@ -3254,21 +3265,18 @@ void pfnClientPrintf( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg )
return;
}
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
switch( ptype )
{
case print_console:
if( FBitSet( client->flags, FCL_FAKECLIENT ))
MsgDev( D_INFO, "%s", szMsg );
else SV_ClientPrintf( client, PRINT_HIGH, "%s", szMsg );
SV_ClientPrintf( client, PRINT_HIGH, "%s", szMsg );
break;
case print_chat:
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
SV_ClientPrintf( client, PRINT_CHAT, "%s", szMsg );
break;
case print_center:
if( FBitSet( client->flags, FCL_FAKECLIENT ))
return;
MSG_BeginServerCmd( &client->netchan.message, svc_centerprint );
MSG_WriteString( &client->netchan.message, szMsg );
break;
@ -4125,19 +4133,15 @@ pfnCreateInstancedBaseline
*/
int pfnCreateInstancedBaseline( int classname, struct entity_state_s *baseline )
{
int i;
if( !baseline || sv.instanced.count >= MAX_CUSTOM_BASELINES )
return 0;
if( !baseline ) return -1;
i = sv.instanced.count;
if( i > 64 ) return 0;
Msg( "Added instanced baseline: %s [%i]\n", STRING( classname ), i );
sv.instanced.classnames[i] = classname;
sv.instanced.baselines[i] = *baseline;
Msg( "Added instanced baseline: %s [%i]\n", STRING( classname ), sv.instanced.count );
sv.instanced.classnames[sv.instanced.count] = classname;
sv.instanced.baselines[sv.instanced.count] = *baseline;
sv.instanced.count++;
return i+1;
return sv.instanced.count;
}
/*

View File

@ -363,6 +363,8 @@ void SV_ActivateServer( void )
MsgDev( D_INFO, "Game started\n" );
}
Log_Printf( "Started map \"%s\" (CRC \"%i\")\n", sv.name, world.checksum );
// dedicated server purge unused resources here
if( host.type == HOST_DEDICATED )
Mod_FreeUnused ();
@ -503,6 +505,10 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot )
if( !svs.initialized )
return false;
Log_Open();
Log_Printf( "Loading map \"%s\"\n", mapname );
Log_PrintServerVars();
svgame.globals->changelevel = false; // will be restored later if needed
svs.timestart = Sys_DoubleTime();
svs.spawncount++; // any partially connected client will be restarted

View File

@ -16,6 +16,77 @@ GNU General Public License for more details.
#include "common.h"
#include "server.h"
void Log_Open( void )
{
time_t ltime;
struct tm *today;
char szFileBase[ MAX_OSPATH ];
char szTestFile[ MAX_OSPATH ];
file_t *fp = NULL;
char *temp;
int i;
if( !svs.log.active )
return;
if( !mp_logfile.value )
{
Msg( "Server logging data to console.\n" );
return;
}
Log_Close();
// Find a new log file slot
time( &ltime );
today = localtime( &ltime );
temp = Cvar_VariableString( "logsdir" );
if( temp && Q_strlen( temp ) > 0 && !Q_strstr( temp, ":" ) && !Q_strstr( temp, ".." ))
Q_snprintf( szFileBase, sizeof( szFileBase ), "%s/L%02i%02i", temp, today->tm_mon + 1, today->tm_mday );
else Q_snprintf( szFileBase, sizeof( szFileBase ), "logs/L%02i%02i", today->tm_mon + 1, today->tm_mday );
for ( i = 0; i < 1000; i++ )
{
Q_snprintf( szTestFile, sizeof( szTestFile ), "%s%03i.log", szFileBase, i );
if( FS_FileExists( szTestFile, false ))
continue;
fp = FS_Open( szTestFile, "w", true );
if( fp )
{
Msg( "Server logging data to file %s\n", szTestFile );
}
else
{
i = 1000;
}
break;
}
if( i == 1000 )
{
Msg( "Unable to open logfiles under %s\nLogging disabled\n", szFileBase );
svs.log.active = false;
return;
}
if( fp ) svs.log.file = fp;
Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/%.2f/%d\")\n",
szTestFile, Info_ValueForKey( SV_Serverinfo(), "*gamedir" ), PROTOCOL_VERSION, XASH_VERSION, Q_buildnum() );
}
void Log_Close( void )
{
if( svs.log.file )
{
Log_Printf( "Log file closed\n" );
FS_Close( svs.log.file );
}
svs.log.file = NULL;
}
/*
==================
Log_Printf
@ -25,5 +96,93 @@ Prints a frag log message to the server's frag log file, console, and possible a
*/
void Log_Printf( const char *fmt, ... )
{
// TODO: implement
va_list argptr;
static char string[1024];
char *p;
time_t ltime;
struct tm *today;
if( !svs.log.active )
return;
time( &ltime );
today = localtime( &ltime );
Q_snprintf( string, sizeof( string ), "%02i/%02i/%04i - %02i:%02i:%02i: ",
today->tm_mon+1, today->tm_mday, 1900 + today->tm_year, today->tm_hour, today->tm_min, today->tm_sec );
p = string + Q_strlen( string );
va_start( argptr, fmt );
Q_vsnprintf( p, sizeof( string ) - Q_strlen( string ), fmt, argptr );
va_end( argptr );
if( svs.log.net_log )
Netchan_OutOfBandPrint( NS_SERVER, svs.log.net_address, "log %s", string );
if( svs.log.active && svs.maxclients > 1 )
{
// echo to server console
if( mp_logecho.value )
Msg( "%s", string );
// echo to log file
if( svs.log.file && mp_logfile.value )
FS_Printf( svs.log.file, "%s", string );
}
}
static void Log_PrintServerCvar( const char *var_name, const char *var_value, const char *unused2, void *unused3 )
{
Log_Printf( "Server cvar \"%s\" = \"%s\"\n", var_name, var_value );
}
/*
==================
Log_PrintServerVars
==================
*/
void Log_PrintServerVars( void )
{
if( !svs.log.active )
return;
Log_Printf( "Server cvars start\n" );
Cvar_LookupVars( FCVAR_SERVER, NULL, NULL, Log_PrintServerCvar );
Log_Printf( "Server cvars end\n" );
}
/*
====================
SV_ServerLog_f
====================
*/
void SV_ServerLog_f( void )
{
if( Cmd_Argc() != 2 )
{
Msg( "usage: log < on|off >\n" );
if( svs.log.active )
Msg( "currently logging\n" );
else Msg( "not currently logging\n" );
return;
}
if( !Q_stricmp( Cmd_Argv( 1 ), "off" ))
{
if( svs.log.active )
Log_Close();
}
else if( !Q_stricmp( Cmd_Argv( 1 ), "on" ))
{
svs.log.active = true;
Log_Open();
}
else
{
Msg( "log: unknown parameter %s\n", Cmd_Argv( 1 ));
}
}

View File

@ -50,6 +50,8 @@ CVAR_DEFINE_AUTO( sv_allow_upload, "1", FCVAR_SERVER, "allow uploading custom re
CVAR_DEFINE_AUTO( sv_allow_download, "1", FCVAR_SERVER, "allow downloading custom resources to the client" );
CVAR_DEFINE_AUTO( sv_downloadurl, "", FCVAR_PROTECTED, "location from which clients can download missing files" );
CVAR_DEFINE( sv_consistency, "mp_consistency", "1", FCVAR_SERVER, "enbale consistency check in multiplayer" );
CVAR_DEFINE_AUTO( mp_logecho, "1", 0, "log multiplayer frags to server logfile" );
CVAR_DEFINE_AUTO( mp_logfile, "1", 0, "log multiplayer frags to console" );
// game-related cvars
CVAR_DEFINE_AUTO( mapcyclefile, "mapcycle.txt", 0, "name of multiplayer map cycle configuration file" );
@ -707,13 +709,14 @@ void SV_Init( void )
Cvar_Get ("protocol", va( "%i", PROTOCOL_VERSION ), FCVAR_READ_ONLY, "displays server protocol version" );
Cvar_Get ("suitvolume", "0.25", FCVAR_ARCHIVE, "HEV suit volume" );
Cvar_Get ("sv_background", "0", FCVAR_READ_ONLY, "indicate what background map is running" );
Cvar_Get( "gamedir", GI->gamefolder, FCVAR_SERVER|FCVAR_READ_ONLY, "game folder" );
Cvar_Get( "gamedir", GI->gamefolder, FCVAR_SERVER, "game folder" );
Cvar_Get( "sv_alltalk", "1", 0, "allow to talking for all players (legacy, unused)" );
Cvar_Get( "sv_allow_PhysX", "1", FCVAR_ARCHIVE, "allow XashXT to usage PhysX engine" ); // XashXT cvar
Cvar_Get( "sv_precache_meshes", "1", FCVAR_ARCHIVE, "cache SOLID_CUSTOM meshes before level loading" ); // Paranoia 2 cvar
Cvar_Get ("mapcyclefile", "mapcycle.txt", 0, "name of config file for map changing rules" );
Cvar_Get ("servercfgfile","server.cfg", 0, "name of dedicated server configuration file" );
Cvar_Get ("lservercfgfile","listenserver.cfg", 0, "name of listen server configuration file" );
Cvar_Get ("logsdir","logs", 0, "default folder to write server logs" );
Cvar_RegisterVariable (&sv_zmax);
Cvar_RegisterVariable (&sv_wateramp);
@ -781,10 +784,12 @@ void SV_Init( void )
Cvar_RegisterVariable (&sv_send_logos);
Cvar_RegisterVariable (&sv_send_resources);
Cvar_RegisterVariable (&sv_version);
sv_sendvelocity = Cvar_Get( "sv_sendvelocity", "1", FCVAR_ARCHIVE, "force to send velocity for event_t structure across network" );
sv_sendvelocity = Cvar_Get( "sv_sendvelocity", "0", FCVAR_ARCHIVE, "force to send velocity for event_t structure across network" );
Cvar_RegisterVariable (&sv_consistency);
sv_novis = Cvar_Get( "sv_novis", "0", 0, "force to ignore server visibility" );
sv_hostmap = Cvar_Get( "hostmap", GI->startmap, 0, "keep name of last entered map" );
Cvar_RegisterVariable (&sv_password);
Cvar_RegisterVariable (&sv_lan);
Cvar_RegisterVariable (&sv_spawntime);
Cvar_RegisterVariable (&sv_changetime);
@ -793,6 +798,8 @@ void SV_Init( void )
Cvar_RegisterVariable (&violence_hblood);
Cvar_RegisterVariable (&violence_agibs);
Cvar_RegisterVariable (&violence_hgibs);
Cvar_RegisterVariable (&mp_logecho);
Cvar_RegisterVariable (&mp_logfile);
// when we in developer-mode automatically turn cheats on
if( host.developer > 1 ) Cvar_SetValue( "sv_cheats", 1.0f );
@ -882,6 +889,9 @@ void SV_Shutdown( qboolean reconnect )
memset( &sv, 0, sizeof( sv ));
Host_SetServerState( sv.state );
Log_Printf( "Server shutdown\n" );
Log_Close();
// free server static data
if( svs.clients )
{

View File

@ -374,19 +374,19 @@ SV_RecursiveWaterLevel
recursively recalculating the middle
=============
*/
float SV_RecursiveWaterLevel( vec3_t origin, float mins, float maxs, int depth )
float SV_RecursiveWaterLevel( vec3_t origin, float out, float in, int count )
{
vec3_t point;
float waterlevel;
float offset;
waterlevel = ((mins - maxs) * 0.5f) + maxs;
if( ++depth > 5 ) return waterlevel;
offset = ((out - in) * 0.5) + in;
if( ++count > 5 ) return offset;
VectorSet( point, origin[0], origin[1], origin[2] + waterlevel );
VectorSet( point, origin[0], origin[1], origin[2] + offset );
if( SV_PointContents( point ) == CONTENTS_WATER )
return SV_RecursiveWaterLevel( origin, mins, waterlevel, depth );
return SV_RecursiveWaterLevel( origin, waterlevel, maxs, depth );
return SV_RecursiveWaterLevel( origin, out, offset, count );
return SV_RecursiveWaterLevel( origin, offset, in, count );
}
/*
@ -398,31 +398,29 @@ determine how deep the entity is
*/
float SV_Submerged( edict_t *ent )
{
float start, bottom;
vec3_t point;
vec3_t halfmax;
float waterlevel;
vec3_t center;
VectorAverage( ent->v.absmin, ent->v.absmax, halfmax );
waterlevel = ent->v.absmin[2] - halfmax[2];
VectorAverage( ent->v.absmin, ent->v.absmax, center );
start = ent->v.absmin[2] - center[2];
switch( ent->v.waterlevel )
{
case 1:
return SV_RecursiveWaterLevel( halfmax, 0.0f, waterlevel, 0 ) - waterlevel;
bottom = SV_RecursiveWaterLevel( center, 0.0f, start, 0 );
return bottom - start;
case 3:
VectorSet( point, halfmax[0], halfmax[1], ent->v.absmax[2] );
VectorSet( point, center[0], center[1], ent->v.absmax[2] );
svs.groupmask = ent->v.groupinfo;
if( SV_PointContents( point ) == CONTENTS_WATER )
{
return (ent->v.maxs[2] - ent->v.mins[2]);
}
// intentionally fallthrough
case 2:
return SV_RecursiveWaterLevel( halfmax, ent->v.absmax[2] - halfmax[2], 0.0f, 0 ) - waterlevel;
default:
return 0.0f;
case 2: // intentionally fallthrough
bottom = SV_RecursiveWaterLevel( center, ent->v.absmax[2] - center[2], 0.0f, 0 );
return bottom - start;
}
return 0.0f;
}
/*

View File

@ -452,7 +452,7 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja
// NOTE: at this point all decal indexes is valid
decalIndex = pfnDecalIndex( entry->name );
if( flags & FDECAL_STUDIO )
if( FBitSet( flags, FDECAL_STUDIO ))
{
// NOTE: studio decal trace start saved into impactPlaneNormal
SV_CreateStudioDecal( &sv.signon, entry->position, entry->impactPlaneNormal, decalIndex, entityIndex, modelIndex, flags, &entry->studio_state );
@ -748,6 +748,8 @@ void SV_SaveFinish( SAVERESTOREDATA *pSaveData )
char **pTokens;
ENTITYTABLE *pEntityTable;
if( !pSaveData ) return;
pTokens = SaveRestore_DetachSymbolTable( pSaveData );
if( pTokens ) Mem_Free( pTokens );
@ -1448,6 +1450,9 @@ SAVERESTOREDATA *SV_SaveGameState( void )
int i, numents;
int id, version;
if( !svgame.dllFuncs.pfnParmsChangeLevel )
return NULL;
pSaveData = SV_SaveInit( 0 );
// Save the data

View File

@ -1255,6 +1255,7 @@ void UI_AddServerToList( netadr_t adr, const char *info )
if( uiStatic.numServers == UI_MAX_SERVERS )
return; // full
// ignore games from difference game folder
if( stricmp( gMenu.m_gameinfo.gamefolder, Info_ValueForKey( info, "gamedir" )))
return;

View File

@ -35,14 +35,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ID_MAXFPSMESSAGE 5
#define ID_HAND 6
#define ID_ALLOWDOWNLOAD 7
#define ID_ALWAYSRUN 8
typedef struct
{
float maxFPS;
int hand;
int allowDownload;
int alwaysRun;
} uiGameValues_t;
typedef struct
@ -59,7 +57,6 @@ typedef struct
menuAction_s maxFPSmessage;
menuCheckBox_s hand;
menuCheckBox_s allowDownload;
menuCheckBox_s alwaysRun;
} uiGameOptions_t;
static uiGameOptions_t uiGameOptions;
@ -77,10 +74,9 @@ static void UI_GameOptions_UpdateConfig( void )
sprintf( fpsText, "%.f", uiGameOptions.maxFPS.curValue );
uiGameOptions.maxFPS.generic.name = fpsText;
CVAR_SET_FLOAT( "hand", uiGameOptions.hand.enabled );
CVAR_SET_FLOAT( "cl_righthand", uiGameOptions.hand.enabled );
CVAR_SET_FLOAT( "sv_allow_download", uiGameOptions.allowDownload.enabled );
CVAR_SET_FLOAT( "fps_max", uiGameOptions.maxFPS.curValue );
CVAR_SET_FLOAT( "cl_run", uiGameOptions.alwaysRun.enabled );
}
/*
@ -90,10 +86,9 @@ UI_GameOptions_DiscardChanges
*/
static void UI_GameOptions_DiscardChanges( void )
{
CVAR_SET_FLOAT( "hand", uiGameInitial.hand );
CVAR_SET_FLOAT( "cl_righthand", uiGameInitial.hand );
CVAR_SET_FLOAT( "sv_allow_download", uiGameInitial.allowDownload );
CVAR_SET_FLOAT( "fps_max", uiGameInitial.maxFPS );
CVAR_SET_FLOAT( "cl_run", uiGameInitial.alwaysRun );
}
/*
@ -117,12 +112,9 @@ static void UI_GameOptions_GetConfig( void )
{
uiGameInitial.maxFPS = uiGameOptions.maxFPS.curValue = CVAR_GET_FLOAT( "fps_max" );
if( CVAR_GET_FLOAT( "hand" ))
if( CVAR_GET_FLOAT( "cl_righthand" ))
uiGameInitial.hand = uiGameOptions.hand.enabled = 1;
if( CVAR_GET_FLOAT( "cl_run" ))
uiGameInitial.alwaysRun = uiGameOptions.alwaysRun.enabled = 1;
if( CVAR_GET_FLOAT( "sv_allow_download" ))
uiGameInitial.allowDownload = uiGameOptions.allowDownload.enabled = 1;
@ -142,7 +134,6 @@ static void UI_GameOptions_Callback( void *self, int event )
{
case ID_HAND:
case ID_ALLOWDOWNLOAD:
case ID_ALWAYSRUN:
if( event == QM_PRESSED )
((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_PRESSED;
else ((menuCheckBox_s *)self)->focusPic = UI_CHECKBOX_FOCUS;
@ -262,15 +253,6 @@ static void UI_GameOptions_Init( void )
uiGameOptions.allowDownload.generic.callback = UI_GameOptions_Callback;
uiGameOptions.allowDownload.generic.statusText = "Allow download of files from servers";
uiGameOptions.alwaysRun.generic.id = ID_ALWAYSRUN;
uiGameOptions.alwaysRun.generic.type = QMTYPE_CHECKBOX;
uiGameOptions.alwaysRun.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW;
uiGameOptions.alwaysRun.generic.x = 280;
uiGameOptions.alwaysRun.generic.y = 450;
uiGameOptions.alwaysRun.generic.name = "Always run";
uiGameOptions.alwaysRun.generic.callback = UI_GameOptions_Callback;
uiGameOptions.alwaysRun.generic.statusText = "Switch between run/step models when pressed 'run' button";
UI_GameOptions_GetConfig();
UI_AddItem( &uiGameOptions.menu, (void *)&uiGameOptions.background );
@ -280,7 +262,6 @@ static void UI_GameOptions_Init( void )
UI_AddItem( &uiGameOptions.menu, (void *)&uiGameOptions.maxFPS );
UI_AddItem( &uiGameOptions.menu, (void *)&uiGameOptions.maxFPSmessage );
UI_AddItem( &uiGameOptions.menu, (void *)&uiGameOptions.hand );
UI_AddItem( &uiGameOptions.menu, (void *)&uiGameOptions.alwaysRun );
UI_AddItem( &uiGameOptions.menu, (void *)&uiGameOptions.allowDownload );
}

View File

@ -242,6 +242,7 @@ static void UI_InternetGames_Callback( void *self, int event )
break;
case ID_CREATEGAME:
CVAR_SET_FLOAT( "public", 1.0f );
CVAR_SET_FLOAT( "sv_lan", 0.0f );
UI_CreateGame_Menu();
break;
case ID_GAMEINFO:

View File

@ -242,6 +242,7 @@ static void UI_LanGame_Callback( void *self, int event )
break;
case ID_CREATEGAME:
CVAR_SET_FLOAT( "public", 0.0f );
CVAR_SET_FLOAT( "sv_lan", 1.0f );
UI_CreateGame_Menu();
break;
case ID_GAMEINFO: