in q_shared.c add
int CCM_stricmpn(const char *s1, const char *s2, int n)
{
int c1, c2;
if ( s1 == NULL ) {
if ( s2 == NULL )
return 0;
else
return -1;
}
else if ( s2 == NULL )
return 1;
do {
c1 = *s1++;
c2 = *s2++;
if (!n--) {
return 0; // strings are equal until end point
}
if (c1 != c2) {
if(c2 == '*')
{
c2 = *s2++;
if(!c2)
return 0;
do
{
c1 = *s1++;
if (c1 >= 'a' && c1 <= 'z') {
c1 -= ('a' - 'A');
}
if (c2 >= 'a' && c2 <= 'z') {
c2 -= ('a' - 'A');
}
if(c1 == c2)
{
break;
}
}
while(c1 && (c2 != c1));
return -1;
}
else if(c2 == '?')
{
c1 = *s1++;
c2 = *s2++;
continue;
}
else
{
if (c1 >= 'a' && c1 <= 'z') {
c1 -= ('a' - 'A');
}
if (c2 >= 'a' && c2 <= 'z') {
c2 -= ('a' - 'A');
}
if (c1 != c2) {
return c1 < c2 ? -1 : 1;
}
}
}
} while (c1);
return 0;
}
int CCM_stricmp (const char *s1, const char *s2) {
char string[MAX_STRING_CHARS];
Q_strncpyz(string, s1, sizeof(string));
Q_CleanStr(string);
return (s1 && s2) ? CCM_stricmpn (string, s2, 99999) : -1;
}
This is a Q_stricmp that handles wildcards (* and ?) and ignores color codes in names.
In q_shared.h add
int CCM_stricmp (const char *s1, const char *s2);
int CCM_stricmpn (const char *s1, const char *s2, int n);
Then in g_local.h add
qboolean admin;
to the clientSession_t struct
then in g_svcmd.c add
/*
=================
Svcmd_Admin_f
=================
*/
void Svcmd_Admin_f(void) {
char player[MAX_STRING_TOKENS];
char *ipnum;
char userinfo[MAX_INFO_STRING];
gentity_t *ent;
int i;
qboolean found = qfalse;
if (trap_Argc() < 2)
{
Com_Printf( "Usage: admin <player>\n" );
return;
}
trap_Argv( 1, player, sizeof( player ) );
for(i = 0; i < MAX_CLIENTS; i++)
{
ent = &g_entities[i];
if(ent && ent->client && ent->inuse)
{
if( CCM_stricmp(ent->client->pers.netname, player ) == 0 )
{
trap_GetUserinfo( ent->client->ps.clientNum, userinfo, sizeof( userinfo ) );
ipnum = Info_ValueForKey( userinfo, "ip" );
found = qtrue;
if(ent->client->sess.admin)
{
Com_Printf( "%s^7 is already an admin\n", ent->client->pers.netname );
continue;
}
if(ent->r.svFlags & SVF_BOT)
{
Com_Printf( "%s^7 is a bot\n", ent->client->pers.netname );
continue;
}
ent->client->sess.admin = qtrue;
trap_SendServerCommand( -1,va("cp \"%s\n^3has become an admin!\n\"", ent->client->pers.netname));
G_LogPrintf( "%s^7 %s has become an admin\n", ent->client->pers.netname, ipnum);
Info_SetValueForKey(userinfo, "admins", "1");
trap_SetUserinfo(ent-g_entities, userinfo);
ClientUserinfoChanged( ent-g_entities );
}
}
}
if(!found)
Com_Printf( "No such player: %s^7\n", player );
}
/*
=================
Svcmd_AdminClient_f
=================
*/
void Svcmd_AdminClient_f(void) {
char arg[MAX_STRING_TOKENS];
char *ipnum;
char userinfo[MAX_INFO_STRING];
gentity_t *ent;
int clientNum;
if (trap_Argc() < 2)
{
Com_Printf( "Usage: adminclient <clientnum>\n" );
return;
}
trap_Argv( 1, arg, sizeof( arg ) );
clientNum = atoi(arg);
ent = &g_entities[clientNum];
if(ent && ent->client && ent->inuse)
{
trap_GetUserinfo( ent->client->ps.clientNum, userinfo, sizeof( userinfo ) );
ipnum = Info_ValueForKey( userinfo, "ip" );
if(ent->client->sess.admin)
{
Com_Printf( "%s^7 is already an admin\n", ent->client->pers.netname );
return;
}
if(ent->r.svFlags & SVF_BOT)
{
Com_Printf( "%s^7 is a bot\n", ent->client->pers.netname );
return;
}
ent->client->sess.admin = qtrue;
trap_SendServerCommand( -1,va("cp \"%s\n^3has become an admin!\n\"", ent->client->pers.netname));
G_LogPrintf( "%s^7 %s has become an admin\n", ent->client->pers.netname, ipnum);
ClientUserinfoChanged( ent-g_entities );
}
else{
Com_Printf( "No such client: %i^7\n", clientNum );
}
}
/*
=================
Svcmd_DeAdmin_f
=================
*/
void Svcmd_DeAdmin_f(void) {
char player[MAX_STRING_TOKENS];
char *ipnum;
char userinfo[MAX_INFO_STRING];
gentity_t *ent;
int i;
qboolean found = qfalse;
if (trap_Argc() < 2)
{
Com_Printf( "Usage: deadmin <player>\n" );
return;
}
trap_Argv( 1, player, sizeof( player ) );
for(i = 0; i < MAX_CLIENTS; i++)
{
ent = &g_entities[i];
if(ent && ent->client && ent->inuse)
{
if( CCM_stricmp(ent->client->pers.netname, player ) == 0 )
{
trap_GetUserinfo( ent->client->ps.clientNum, userinfo, sizeof( userinfo ) );
ipnum = Info_ValueForKey( userinfo, "ip" );
found = qtrue;
if(!ent->client->sess.admin)
{
Com_Printf( "%s is not an admin\n", ent->client->pers.netname );
continue;
}
ent->client->sess.admin = 0;
trap_SendServerCommand( -1,va("cp \"%s\n^3is no longer an admin!\n\"", ent->client->pers.netname));
G_LogPrintf( "%s^7 %s is no longer an admin", ent->client->pers.netname, ipnum);
Info_SetValueForKey(userinfo, "admins", "0");
trap_SetUserinfo(ent-g_entities, userinfo);
ClientUserinfoChanged( ent-g_entities );
}
}
}
if(!found)
Com_Printf( "No such player: %s^7\n", player );
}
/*
=================
Svcmd_DeAdminClient_f
=================
*/
void Svcmd_DeAdminClient_f(void) {
char arg[MAX_STRING_TOKENS];
char *ipnum;
char userinfo[MAX_INFO_STRING];
gentity_t *ent;
int clientNum;
if (trap_Argc() < 2)
{
Com_Printf( "Usage: deadminclient <clientnum>\n" );
return;
}
trap_Argv( 1, arg, sizeof( arg ) );
clientNum = atoi(arg);
ent = &g_entities[clientNum];
if(ent && ent->client && ent->inuse)
{
trap_GetUserinfo( ent->client->ps.clientNum, userinfo, sizeof( userinfo ) );
ipnum = Info_ValueForKey( userinfo, "ip" );
if(!ent->client->sess.admin)
{
Com_Printf( "%s^7 is not an admin\n", ent->client->pers.netname );
return;
}
ent->client->sess.admin = 0;
trap_SendServerCommand( -1,va("cp \"%s\n^3is no longer an admin!\n\"", ent->client->pers.netname));
G_LogPrintf( "%s^7 %s is no longer an admin\n", ent->client->pers.netname, ipnum);
ClientUserinfoChanged( ent-g_entities );
}
else{
Com_Printf( "No such client: %i^7\n", clientNum );
}
}
That's basically it for the admin command