2004-08-23 00:15:46 +00:00
# include "qwsvdef.h"
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
# if defined(_WIN32) && !defined(MINGW)
# define inline //_inline //fix for stupid VC
2009-06-08 08:10:32 +00:00
# elif defined(CLANG)
# define inline // fix for stupid clang
2004-08-23 00:15:46 +00:00
# endif
# ifdef SVRANKING
typedef struct {
2005-06-22 17:10:13 +00:00
int ident ;
int version ;
2004-08-23 00:15:46 +00:00
int usedslots ;
int leader ;
int freeslot ;
} rankfileheader_t ;
//endian
# define swaplong LittleLong
# define swapfloat LittleFloat
rankfileheader_t rankfileheader ;
2012-04-24 07:59:11 +00:00
vfsfile_t * rankfile ;
2004-08-23 00:15:46 +00:00
2011-09-03 03:49:43 +00:00
cvar_t rank_autoadd = CVARD ( " rank_autoadd " , " 1 " , " Automatically register players into the ranking system " ) ;
cvar_t rank_needlogin = CVARD ( " rank_needlogin " , " 0 " , " If set to 1, prohibits players from joining if they're not already registered. " ) ;
cvar_t rank_filename = CVARD ( " rank_filename " , " " , " Specifies which file to use as a rankings database. Enables the ranking system if set. " ) ;
cvar_t rank_parms_first = CVARD ( " rank_parms_first " , " 0 " , " Mod setting: first parm saved " ) ;
cvar_t rank_parms_last = CVARD ( " rank_parms_last " , " 31 " , " Mod setting: the index of the last parm to be saved. Clamped to 32. " ) ;
2004-08-23 00:15:46 +00:00
char rank_cvargroup [ ] = " server rankings " ;
2009-11-05 03:07:52 +00:00
# define RANKFILE_VERSION ((NUM_RANK_SPAWN_PARMS==32)?0:0x00000001)
2005-06-22 17:10:13 +00:00
# define RANKFILE_IDENT *(int*)"RANK"
2004-08-23 00:15:46 +00:00
void inline READ_PLAYERSTATS ( int x , rankstats_t * os )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
int i ;
2011-05-15 13:23:13 +00:00
size_t result ;
2004-08-23 00:15:46 +00:00
2012-04-24 07:59:11 +00:00
VFS_SEEK ( rankfile , sizeof ( rankfileheader_t ) + sizeof ( rankheader_t ) + ( ( x - 1 ) * sizeof ( rankinfo_t ) ) ) ;
result = VFS_READ ( rankfile , os , sizeof ( rankstats_t ) ) ;
2011-05-15 13:23:13 +00:00
2011-05-30 04:32:04 +00:00
if ( result ! = sizeof ( rankstats_t ) )
2012-04-24 07:59:11 +00:00
Con_Printf ( " READ_PLAYERSTATS() fread: expected %lu, result was %u \n " , ( long unsigned int ) sizeof ( rankstats_t ) , ( unsigned int ) result ) ;
2004-08-23 00:15:46 +00:00
os - > kills = swaplong ( os - > kills ) ;
os - > deaths = swaplong ( os - > deaths ) ;
2009-11-05 03:07:52 +00:00
for ( i = 0 ; i < NUM_RANK_SPAWN_PARMS ; i + + )
2004-08-23 00:15:46 +00:00
os - > parm [ i ] = swapfloat ( os - > parm [ i ] ) ;
os - > timeonserver = swapfloat ( os - > timeonserver ) ;
// os->flags1 = (os->flags1);
2006-01-27 08:06:48 +00:00
// os->trustlevel = (os->trustlevel);
// os->pad2 = (os->pad2);
2004-08-23 00:15:46 +00:00
// os->pad3 = (os->pad3);
}
void inline WRITE_PLAYERSTATS ( int x , rankstats_t * os )
{
rankstats_t ns ;
int i ;
2012-04-24 07:59:11 +00:00
VFS_SEEK ( rankfile , sizeof ( rankfileheader_t ) + sizeof ( rankheader_t ) + ( ( x - 1 ) * sizeof ( rankinfo_t ) ) ) ;
2004-08-23 00:15:46 +00:00
ns . kills = swaplong ( os - > kills ) ;
ns . deaths = swaplong ( os - > deaths ) ;
2009-11-05 03:07:52 +00:00
for ( i = 0 ; i < NUM_RANK_SPAWN_PARMS ; i + + )
2004-08-23 00:15:46 +00:00
ns . parm [ i ] = swapfloat ( os - > parm [ i ] ) ;
ns . timeonserver = swapfloat ( os - > timeonserver ) ;
ns . flags1 = ( os - > flags1 ) ;
2006-01-27 08:06:48 +00:00
ns . trustlevel = ( os - > trustlevel ) ;
ns . pad2 = ( os - > pad2 ) ;
2004-08-23 00:15:46 +00:00
ns . pad3 = ( os - > pad3 ) ;
2012-04-24 07:59:11 +00:00
VFS_WRITE ( rankfile , & ns , sizeof ( rankstats_t ) ) ;
2004-08-23 00:15:46 +00:00
}
void inline READ_PLAYERHEADER ( int x , rankheader_t * oh )
2006-01-27 08:06:48 +00:00
{
2011-05-15 13:23:13 +00:00
size_t result ;
2012-04-24 07:59:11 +00:00
VFS_SEEK ( rankfile , sizeof ( rankfileheader_t ) + ( ( x - 1 ) * sizeof ( rankinfo_t ) ) ) ;
2004-08-23 00:15:46 +00:00
2012-04-24 07:59:11 +00:00
result = VFS_READ ( rankfile , oh , sizeof ( rankheader_t ) ) ;
2011-05-15 13:23:13 +00:00
2011-05-30 04:32:04 +00:00
if ( result ! = sizeof ( rankheader_t ) )
2012-04-24 07:59:11 +00:00
Con_Printf ( " READ_PLAYERHEADER() fread: expected %lu, result was %u \n " , ( long unsigned int ) sizeof ( rankheader_t ) , ( unsigned int ) result ) ;
2004-08-23 00:15:46 +00:00
oh - > prev = swaplong ( oh - > prev ) ; //score is held for convineance.
oh - > next = swaplong ( oh - > next ) ;
// strcpy(oh->name, oh->name);
oh - > pwd = swaplong ( oh - > pwd ) ;
2006-01-27 08:06:48 +00:00
oh - > score = swapfloat ( oh - > score ) ;
2004-08-23 00:15:46 +00:00
}
void inline WRITE_PLAYERHEADER ( int x , rankheader_t * oh )
{
rankheader_t nh ;
2012-04-24 07:59:11 +00:00
VFS_SEEK ( rankfile , sizeof ( rankfileheader_t ) + ( ( x - 1 ) * sizeof ( rankinfo_t ) ) ) ;
2004-08-23 00:15:46 +00:00
nh . prev = swaplong ( oh - > prev ) ; //score is held for convineance.
nh . next = swaplong ( oh - > next ) ;
Q_strncpyz ( nh . name , oh - > name , sizeof ( nh . name ) ) ;
nh . pwd = swaplong ( oh - > pwd ) ;
nh . score = swapfloat ( oh - > score ) ;
2012-04-24 07:59:11 +00:00
VFS_WRITE ( rankfile , & nh , sizeof ( rankheader_t ) ) ;
2004-08-23 00:15:46 +00:00
}
void inline READ_PLAYERINFO ( int x , rankinfo_t * inf )
{
READ_PLAYERHEADER ( x , & inf - > h ) ;
READ_PLAYERSTATS ( x , & inf - > s ) ;
}
void inline WRITEHEADER ( void )
{
rankfileheader_t nh ;
2005-06-22 17:10:13 +00:00
nh . ident = RANKFILE_IDENT ;
nh . version = swaplong ( RANKFILE_VERSION ) ;
2004-08-23 00:15:46 +00:00
nh . usedslots = swaplong ( rankfileheader . usedslots ) ;
nh . leader = swaplong ( rankfileheader . leader ) ;
nh . freeslot = swaplong ( rankfileheader . freeslot ) ;
2012-04-24 07:59:11 +00:00
VFS_SEEK ( rankfile , 0 ) ;
VFS_WRITE ( rankfile , & nh , sizeof ( rankfileheader_t ) ) ;
2004-08-23 00:15:46 +00:00
}
2011-09-03 03:49:43 +00:00
//#define WRITEHEADER() {fseek(rankfile, 0, SEEK_SET);fwrite(&rankfileheader, 1, sizeof(rankfileheader_t), rankfile);}
2004-08-23 00:15:46 +00:00
# define NAMECMP(saved, against) Q_strncasecmp(saved, against, 31)
qboolean Rank_OpenRankings ( void )
{
2009-04-01 22:03:56 +00:00
char syspath [ MAX_OSPATH ] ;
2011-05-15 13:23:13 +00:00
size_t result ;
2005-06-22 17:10:13 +00:00
qboolean created ;
2004-08-23 00:15:46 +00:00
if ( ! rankfile )
{
if ( ! * rank_filename . string )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
return false ;
}
2009-04-01 22:03:56 +00:00
if ( ! FS_NativePath ( rank_filename . string , FS_GAMEONLY , syspath , sizeof ( syspath ) ) )
2004-08-23 00:15:46 +00:00
return false ;
2012-04-24 07:59:11 +00:00
rankfile = FS_OpenVFS ( rank_filename . string , " r+b " , FS_GAMEONLY ) ;
2004-08-23 00:15:46 +00:00
if ( ! rankfile ) //hmm... try creating
2005-06-22 17:10:13 +00:00
{
2012-04-24 07:59:11 +00:00
rankfile = FS_OpenVFS ( rank_filename . string , " w+b " , FS_GAMEONLY ) ;
2005-06-22 17:10:13 +00:00
created = true ;
}
else
created = false ;
2004-08-23 00:15:46 +00:00
if ( ! rankfile )
return false ; //couldn't open file.
memset ( & rankfileheader , 0 , sizeof ( rankfileheader ) ) ;
2012-04-24 07:59:11 +00:00
VFS_SEEK ( rankfile , 0 ) ;
result = VFS_READ ( rankfile , & rankfileheader , sizeof ( rankfileheader_t ) ) ;
2011-05-15 13:23:13 +00:00
2011-05-30 04:32:04 +00:00
if ( result ! = sizeof ( rankfileheader_t ) )
2012-04-24 07:59:11 +00:00
Con_Printf ( " Rank_OpenRankings() fread: expected %lu, result was %u (%s) \n " , ( long unsigned int ) sizeof ( rankfileheader_t ) , ( unsigned int ) result ) ;
2004-08-23 00:15:46 +00:00
2005-06-22 17:10:13 +00:00
rankfileheader . version = swaplong ( rankfileheader . version ) ;
2004-08-23 00:15:46 +00:00
rankfileheader . usedslots = swaplong ( rankfileheader . usedslots ) ;
rankfileheader . leader = swaplong ( rankfileheader . leader ) ;
rankfileheader . freeslot = swaplong ( rankfileheader . freeslot ) ;
2005-06-22 17:10:13 +00:00
if ( ! created & & ( rankfileheader . version ! = RANKFILE_VERSION | | rankfileheader . ident ! = RANKFILE_IDENT ) )
{
2009-10-06 00:38:42 +00:00
Con_Printf ( " Rank file is version %i not %i \n Either delete the file or use an equivelent version of " DISTRIBUTION " \n " , rankfileheader . version , RANKFILE_VERSION ) ;
2012-04-24 07:59:11 +00:00
VFS_CLOSE ( rankfile ) ;
2005-06-22 17:10:13 +00:00
rankfile = NULL ;
return false ;
}
2004-08-23 00:15:46 +00:00
return true ; //success.
}
return true ; //already open
}
void LINKUN ( int id )
{
int idnext , idprev ;
2006-01-27 08:06:48 +00:00
rankheader_t hnext = { 0 } , hprev = { 0 } , info ;
2004-08-23 00:15:46 +00:00
READ_PLAYERHEADER ( id , & info ) ;
idnext = info . next ;
if ( idnext )
READ_PLAYERHEADER ( idnext , & hnext ) ;
idprev = info . prev ;
if ( idprev )
READ_PLAYERHEADER ( idprev , & hprev ) ;
if ( idnext )
{
hnext . prev = idprev ;
WRITE_PLAYERHEADER ( idnext , & hnext ) ;
}
if ( idprev )
{
2006-01-27 08:06:48 +00:00
hprev . next = idnext ;
2004-08-23 00:15:46 +00:00
WRITE_PLAYERHEADER ( idprev , & hprev ) ;
}
else if ( rankfileheader . leader = = id ) //ensure header is accurate
{
rankfileheader . leader = info . next ;
WRITEHEADER ( ) ;
}
else if ( rankfileheader . freeslot = = id )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
rankfileheader . freeslot = info . next ;
WRITEHEADER ( ) ;
}
info . next = 0 ;
info . prev = 0 ;
WRITE_PLAYERHEADER ( id , & info ) ;
}
void LINKBEFORE ( int bef , int id , rankheader_t * info )
{
int idnext , idprev ;
2006-01-27 08:06:48 +00:00
rankheader_t hnext , hprev = { 0 } ;
2004-08-23 00:15:46 +00:00
if ( ! bef )
Sys_Error ( " Cannot link before no entry \n " ) ;
idnext = bef ;
READ_PLAYERHEADER ( idnext , & hnext ) ;
idprev = hnext . prev ;
if ( idprev )
READ_PLAYERHEADER ( idprev , & hprev ) ;
//now we know the before and after entries.
2006-01-27 08:06:48 +00:00
hnext . prev = id ;
2004-08-23 00:15:46 +00:00
WRITE_PLAYERHEADER ( idnext , & hnext ) ;
if ( idprev )
{
hprev . next = id ;
WRITE_PLAYERHEADER ( idprev , & hprev ) ;
}
else if ( rankfileheader . leader = = bef )
{
rankfileheader . leader = id ;
WRITEHEADER ( ) ;
}
else if ( rankfileheader . freeslot = = bef )
{
rankfileheader . freeslot = id ;
WRITEHEADER ( ) ;
}
info - > next = idnext ;
info - > prev = idprev ;
WRITE_PLAYERHEADER ( id , info ) ;
}
void LINKAFTER ( int aft , int id , rankheader_t * info )
{
int idnext , idprev ;
2006-01-27 08:06:48 +00:00
rankheader_t hnext = { 0 } , hprev = { 0 } ;
2004-08-23 00:15:46 +00:00
idprev = aft ;
if ( idprev )
{
READ_PLAYERHEADER ( idprev , & hprev ) ;
2006-01-27 08:06:48 +00:00
idnext = hprev . next ;
2004-08-23 00:15:46 +00:00
}
else
idnext = rankfileheader . leader ;
if ( idnext )
READ_PLAYERHEADER ( idnext , & hnext ) ;
//now we know the before and after entries.
if ( idnext )
{
hnext . prev = id ;
WRITE_PLAYERHEADER ( idnext , & hnext ) ;
}
if ( idprev )
{
hprev . next = id ;
WRITE_PLAYERHEADER ( idprev , & hprev ) ;
}
else if ( rankfileheader . leader = = idnext )
{
rankfileheader . leader = id ;
WRITEHEADER ( ) ;
}
else if ( rankfileheader . freeslot = = idnext )
{
rankfileheader . freeslot = id ;
WRITEHEADER ( ) ;
}
info - > next = idnext ;
info - > prev = idprev ;
WRITE_PLAYERHEADER ( id , info ) ;
}
rankstats_t * Rank_GetPlayerStats ( int id , rankstats_t * buffer ) //returns the players persistant stats.
{
if ( ! Rank_OpenRankings ( ) )
return NULL ;
if ( ! id )
{
Con_Printf ( " WARNING: Rank_GetPlayerStats with id 0 \n " ) ;
memset ( buffer , 0 , sizeof ( rankstats_t ) ) ;
return NULL ;
}
READ_PLAYERSTATS ( id , buffer ) ;
return buffer ;
}
rankinfo_t * Rank_GetPlayerInfo ( int id , rankinfo_t * buffer ) //return stats + rankings.
{
if ( ! id )
{
Con_Printf ( " WARNING: Rank_GetPlayerInfo with id 0 \n " ) ;
memset ( buffer , 0 , sizeof ( rankinfo_t ) ) ;
return NULL ;
}
if ( ! Rank_OpenRankings ( ) )
return NULL ;
READ_PLAYERINFO ( id , buffer ) ;
return buffer ;
}
void Rank_SetPlayerStats ( int id , rankstats_t * stats )
{
//rewrite to seek in a proper direction.
int nid ;
rankheader_t rh , nh ;
if ( ! id )
{
2006-01-27 08:06:48 +00:00
Con_Printf ( " WARNING: Rank_SetPlayerStats with id 0 \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
//write
WRITE_PLAYERSTATS ( id , stats ) ;
//now re-sort.
READ_PLAYERHEADER ( id , & nh ) ;
nh . score = ( stats - > kills + 1 ) / ( ( float ) stats - > deaths + 1 ) ;
//WRITE_PLAYERHEADER(id, &nh); //saved on link.
2006-01-27 08:06:48 +00:00
2004-08-23 00:15:46 +00:00
LINKUN ( id ) ;
2006-01-27 08:06:48 +00:00
2004-08-23 00:15:46 +00:00
nid = rankfileheader . leader ;
if ( ! nid ) //Hmm. First player!
{
LINKAFTER ( 0 , id , & nh ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return ;
}
while ( nid )
{
READ_PLAYERHEADER ( nid , & rh ) ;
if ( rh . score < nh . score )
{
LINKAFTER ( rh . prev , id , & nh ) ;
//LINKBEFORE(nid, id, &nh); //we are doing better than this guy.
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( ! rh . next )
{
LINKAFTER ( nid , id , & nh ) ; //Bum. We got to the end of the list and we are the WORST player!
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return ;
}
nid = rh . next ;
2006-01-27 08:06:48 +00:00
}
2004-08-23 00:15:46 +00:00
}
2011-09-03 03:49:43 +00:00
int Rank_GetPlayerID ( char * guid , char * name , int pwd , qboolean allowadd , qboolean requirepasswordtobeset )
2004-08-23 00:15:46 +00:00
{
rankstats_t rs ;
rankheader_t rh ;
int id ;
2005-03-12 23:40:42 +00:00
if ( requirepasswordtobeset )
if ( ! pwd )
return 0 ;
2004-08-23 00:15:46 +00:00
if ( ! Rank_OpenRankings ( ) )
return 0 ;
id = rankfileheader . leader ; //assumtion. A leader is more likly to be logging in than a begginer.
while ( id )
{
READ_PLAYERHEADER ( id , & rh ) ;
if ( ! NAMECMP ( rh . name , name ) )
{
if ( rh . pwd = = pwd | | ! rh . pwd )
2005-03-12 23:40:42 +00:00
{
if ( ! rh . pwd & & requirepasswordtobeset )
return 0 ;
2004-08-23 00:15:46 +00:00
return id ;
2005-03-12 23:40:42 +00:00
}
2004-08-23 00:15:46 +00:00
return 0 ;
}
id = rh . next ;
}
if ( ! rank_autoadd . value | | ! allowadd )
return 0 ;
id = rankfileheader . freeslot ;
if ( id )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
READ_PLAYERHEADER ( id , & rh ) ;
rankfileheader . freeslot = rh . next ;
WRITEHEADER ( ) ;
memset ( & rh , 0 , sizeof ( rh ) ) ;
Q_strncpyz ( rh . name , name , sizeof ( rh . name ) ) ;
rh . pwd = pwd ;
rh . prev = 0 ;
2006-01-27 08:06:48 +00:00
rh . next = rankfileheader . usedslots ;
2004-08-23 00:15:46 +00:00
rankfileheader . usedslots = id ;
WRITEHEADER ( ) ;
WRITE_PLAYERHEADER ( id , & rh ) ;
memset ( & rs , 0 , sizeof ( rs ) ) ;
rs . trustlevel = 1 ;
Rank_SetPlayerStats ( id , & rs ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return id ;
}
id = + + rankfileheader . usedslots ;
WRITEHEADER ( ) ;
memset ( & rh , 0 , sizeof ( rh ) ) ;
Q_strncpyz ( rh . name , name , sizeof ( rh . name ) ) ;
rh . prev = 0 ;
rh . pwd = pwd ;
rh . next = 0 ;
WRITE_PLAYERHEADER ( id , & rh ) ;
memset ( & rs , 0 , sizeof ( rs ) ) ;
rs . trustlevel = 1 ;
WRITE_PLAYERSTATS ( id , & rs ) ;
Rank_SetPlayerStats ( id , & rs ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return id ;
}
void Rank_AddUser_f ( void )
{
rankstats_t rs ;
rankheader_t rh ;
int id ;
char * name = Cmd_Argv ( 1 ) ;
int pwd = atoi ( Cmd_Argv ( 2 ) ) ;
int userlevel = atoi ( Cmd_Argv ( 3 ) ) ;
if ( Cmd_Argc ( ) < 2 )
{
2005-08-14 03:39:49 +00:00
Con_Printf ( " %s: <name> [pwd] [rights] \n " , Cmd_Argv ( 0 ) ) ;
2004-08-23 00:15:46 +00:00
return ;
}
//2
if ( Cmd_Argc ( ) > = 4 )
{
if ( userlevel > = Cmd_ExecLevel )
{
Con_Printf ( " You cannot add a user of equal or higher rank. \n " ) ;
return ;
}
else if ( userlevel < RESTRICT_MIN )
userlevel = RESTRICT_MIN ;
}
if ( Cmd_Argc ( ) > 4 )
{
Con_Printf ( " Too many arguments \n " ) ;
return ;
}
2008-08-23 19:17:19 +00:00
SV_FixupName ( name , name , sizeof ( name ) ) ;
2004-08-23 00:15:46 +00:00
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
id = rankfileheader . leader ;
while ( id )
{
READ_PLAYERHEADER ( id , & rh ) ;
if ( ! NAMECMP ( rh . name , name ) )
{
Con_Printf ( " User %s already exists \n " , name ) ;
return ;
}
id = rh . next ;
}
id = rankfileheader . freeslot ;
if ( id )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
READ_PLAYERHEADER ( id , & rh ) ;
rankfileheader . freeslot = rh . next ;
WRITEHEADER ( ) ;
memset ( & rh , 0 , sizeof ( rh ) ) ;
Q_strncpyz ( rh . name , name , sizeof ( rh . name ) ) ;
2006-01-27 08:06:48 +00:00
rh . pwd = pwd ;
2004-08-23 00:15:46 +00:00
rh . prev = 0 ;
2006-01-27 08:06:48 +00:00
rh . next = rankfileheader . usedslots ;
2004-08-23 00:15:46 +00:00
rankfileheader . usedslots = id ;
WRITEHEADER ( ) ;
WRITE_PLAYERHEADER ( id , & rh ) ;
memset ( & rs , 0 , sizeof ( rs ) ) ;
rs . trustlevel = userlevel ;
Rank_SetPlayerStats ( id , & rs ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return ;
}
id = + + rankfileheader . usedslots ;
WRITEHEADER ( ) ;
memset ( & rh , 0 , sizeof ( rh ) ) ;
Q_strncpyz ( rh . name , name , sizeof ( rh . name ) ) ;
rh . prev = 0 ;
rh . pwd = pwd ;
rh . next = 0 ;
WRITE_PLAYERHEADER ( id , & rh ) ;
memset ( & rs , 0 , sizeof ( rs ) ) ;
rs . trustlevel = userlevel ;
WRITE_PLAYERSTATS ( id , & rs ) ;
Rank_SetPlayerStats ( id , & rs ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
}
void Rank_SetPass_f ( void )
{
rankheader_t rh ;
char * name = Cmd_Argv ( 1 ) ;
int newpass = atoi ( Cmd_Argv ( 2 ) ) ;
int id ;
if ( Cmd_Argc ( ) ! = 3 )
{
Con_Printf ( " setpass <name> <newpass> \n " ) ;
return ;
}
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
2008-08-23 19:17:19 +00:00
SV_FixupName ( name , name , sizeof ( name ) ) ;
2004-08-23 00:15:46 +00:00
id = rankfileheader . leader ;
while ( id )
{
READ_PLAYERHEADER ( id , & rh ) ;
if ( ! NAMECMP ( rh . name , name ) )
{
Con_Printf ( " Changing passcode of user %s. \n " , rh . name ) ;
rh . pwd = newpass ;
WRITE_PLAYERHEADER ( id , & rh ) ;
return ;
}
id = rh . next ;
}
}
int Rank_GetPass ( char * name )
{
rankheader_t rh ;
int id ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return 0 ;
}
2008-08-23 19:17:19 +00:00
SV_FixupName ( name , name , sizeof ( name ) ) ;
2004-08-23 00:15:46 +00:00
id = rankfileheader . leader ;
while ( id )
{
READ_PLAYERHEADER ( id , & rh ) ;
if ( ! NAMECMP ( rh . name , name ) )
{
return rh . pwd ;
}
id = rh . next ;
}
return 0 ;
}
int Rank_Enumerate ( unsigned int first , unsigned int last , void ( * callback ) ( const rankinfo_t * ri ) ) //leader first.
{
rankinfo_t ri ;
int id ;
int num ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return 0 ;
}
id = rankfileheader . leader ; //start at the leaders
num = 1 ;
while ( id )
{
READ_PLAYERINFO ( id , & ri ) ;
if ( num > = last )
return num - first ;
if ( num > = first )
callback ( & ri ) ;
num + + ;
id = ri . h . next ;
}
return num - first ;
}
void Rank_RankingList_f ( void )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
rankinfo_t ri ;
int id ;
int num ;
FILE * outfile ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
outfile = fopen ( " list.txt " , " wb " ) ;
fprintf ( outfile , " %5s: %32s, %5s %5s \r \n " , " " , " Name " , " Kills " , " Deaths " ) ;
id = rankfileheader . leader ; //start at the leaders
num = 1 ;
while ( id )
{
READ_PLAYERINFO ( id , & ri ) ;
fprintf ( outfile , " %5i: %32s, %5i %5i \r \n " , num , ri . h . name , ri . s . kills , ri . s . deaths ) ;
num + + ;
id = ri . h . next ;
}
fclose ( outfile ) ;
}
void Rank_Remove_f ( void )
{
rankinfo_t ri ;
int id ;
int num ;
int remnum ;
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Removes a ranking entry. \n Use ranklist to find the entry number. " ) ;
return ;
}
remnum = atoi ( Cmd_Argv ( 1 ) ) ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
id = rankfileheader . leader ; //start at the leaders
num = 1 ;
while ( id )
{
READ_PLAYERINFO ( id , & ri ) ;
if ( num = = remnum )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
LINKUN ( id ) ;
ri . h . next = rankfileheader . freeslot ;
ri . h . prev = 0 ;
rankfileheader . freeslot = id ;
WRITE_PLAYERHEADER ( id , & ri . h ) ;
WRITEHEADER ( ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
Con_Printf ( " Client %s removed from rankings \n " , ri . h . name ) ;
return ;
}
num + + ;
id = ri . h . next ;
}
Con_Printf ( " Client %i not found \n " , remnum ) ;
}
void Rank_ListTop10_f ( void )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
rankinfo_t ri ;
int id ;
int num ;
extern redirect_t sv_redirected ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
id = rankfileheader . leader ; //start at the leaders
num = 1 ;
while ( id )
{
READ_PLAYERINFO ( id , & ri ) ;
if ( sv_redirected )
Con_Printf ( " %2i: %5i %5i %s \n " , num , ri . s . kills , ri . s . deaths , ri . h . name ) ;
else
Con_Printf ( " %2i: %32s, %5i %5i \n " , num , ri . h . name , ri . s . kills , ri . s . deaths ) ;
if ( num > = 10 )
break ;
num + + ;
id = ri . h . next ;
}
if ( num < 10 )
Con_Printf ( " END \n " ) ;
}
void Rank_Find_f ( void )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
rankinfo_t ri ;
int id ;
char * match = Cmd_Argv ( 1 ) ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
id = rankfileheader . leader ; //start at the leaders
while ( id )
{
READ_PLAYERINFO ( id , & ri ) ;
if ( strstr ( ri . h . name , match ) )
{
Con_Printf ( " %i %s \n " , id , ri . h . name ) ;
}
id = ri . h . next ;
}
}
void Rank_Refresh_f ( void )
{
int i ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
for ( i = 0 , host_client = svs . clients ; i < MAX_CLIENTS ; i + + , host_client + + )
{
if ( host_client - > state ! = cs_spawned )
continue ;
if ( host_client - > rankid )
{
2006-01-27 08:06:48 +00:00
rankstats_t rs = { 0 } ;
2004-08-23 00:15:46 +00:00
Rank_GetPlayerStats ( host_client - > rankid , & rs ) ;
rs . timeonserver + = realtime - host_client - > stats_started ;
host_client - > stats_started = realtime ;
rs . kills + = host_client - > kills ;
rs . deaths + = host_client - > deaths ;
host_client - > kills = 0 ;
host_client - > deaths = 0 ;
Rank_SetPlayerStats ( host_client - > rankid , & rs ) ;
}
}
if ( rankfile )
{
2012-04-24 07:59:11 +00:00
VFS_CLOSE ( rankfile ) ;
2004-08-23 00:15:46 +00:00
rankfile = NULL ;
}
}
void Rank_RCon_f ( void )
{
int gofor , num , id ;
int newlevel ;
2006-01-27 08:06:48 +00:00
rankstats_t rs = { 0 } ;
2004-08-23 00:15:46 +00:00
rankinfo_t ri ;
if ( ! Rank_OpenRankings ( ) )
{
Con_Printf ( " Failed to open rankings file. \n " ) ;
return ;
}
gofor = atoi ( Cmd_Argv ( 1 ) ) ;
newlevel = atoi ( Cmd_Argv ( 2 ) ) ;
if ( newlevel > = Cmd_ExecLevel )
{
Con_Printf ( " You cannot promote a user to the same level as you \n " ) ;
return ;
}
else if ( newlevel < RESTRICT_MIN )
newlevel = RESTRICT_MIN ;
//get user id
id = rankfileheader . leader ; //start at the leaders
num = 1 ;
while ( id )
{
READ_PLAYERINFO ( id , & ri ) ;
if ( num = = gofor )
2006-01-27 08:06:48 +00:00
{
2004-08-23 00:15:46 +00:00
//save new level
Rank_GetPlayerStats ( id , & rs ) ;
if ( rs . trustlevel > = Cmd_ExecLevel )
{
Con_Printf ( " You cannot demote a higher or equal user. \n " ) ;
return ;
}
rs . trustlevel = newlevel ;
Rank_SetPlayerStats ( id , & rs ) ;
if ( ! ri . h . pwd & & newlevel > 1 )
Con_Printf ( " WARNING: user has no password set \n " ) ;
2012-04-24 07:59:11 +00:00
VFS_FLUSH ( rankfile ) ;
2004-08-23 00:15:46 +00:00
return ;
}
num + + ;
id = ri . h . next ;
}
Con_Printf ( " Couldn't find ranked user %i \n " , gofor ) ;
}
void Rank_RegisterCommands ( void )
{
Cmd_AddCommand ( " ranklist " , Rank_RankingList_f ) ;
Cmd_AddCommand ( " ranktopten " , Rank_ListTop10_f ) ;
Cmd_AddCommand ( " rankfind " , Rank_Find_f ) ;
Cmd_AddCommand ( " rankremove " , Rank_Remove_f ) ;
Cmd_AddCommand ( " rankrefresh " , Rank_Refresh_f ) ;
Cmd_AddCommand ( " rankrconlevel " , Rank_RCon_f ) ;
Cmd_AddCommand ( " rankadd " , Rank_AddUser_f ) ;
Cmd_AddCommand ( " adduser " , Rank_AddUser_f ) ;
2006-01-27 08:06:48 +00:00
Cmd_AddCommand ( " setpass " , Rank_SetPass_f ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & rank_autoadd , rank_cvargroup ) ;
Cvar_Register ( & rank_needlogin , rank_cvargroup ) ;
Cvar_Register ( & rank_filename , rank_cvargroup ) ;
2011-09-03 03:49:43 +00:00
Cvar_Register ( & rank_parms_first , rank_cvargroup ) ;
Cvar_Register ( & rank_parms_last , rank_cvargroup ) ;
2004-08-23 00:15:46 +00:00
}
void Rank_Flush ( void ) //new game dir?
{
if ( rankfile )
{
Rank_Refresh_f ( ) ;
if ( ! rankfile )
return ;
2012-04-24 07:59:11 +00:00
VFS_CLOSE ( rankfile ) ;
2004-08-23 00:15:46 +00:00
rankfile = NULL ;
}
}
# endif
2004-11-29 01:21:00 +00:00
# endif