/* ================== SV_ConSay_f ================== */ static void SV_ConSay_f(void) { char *p; char text[1024]; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc () < 2 ) { return; } strcpy (text, sv_sayprefix->string); p = Cmd_Args(); if ( *p == '"' ) { p++; p[strlen(p)-1] = 0; } strcat(text, p); SV_SendServerCommand(NULL, "chat \"%s\n\"", text); }
/* ================== SV_KickNum_f Kick a user off of the server FIXME: move to game ================== */ static void SV_KickNum_f( void ) { client_t *cl; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() != 2 ) { Com_Printf ("Usage: kicknum <client number>\n"); return; } cl = SV_GetPlayerByNum(); if ( !cl ) { return; } if ( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); return; } SV_DropClient( cl, "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie }
/* ================== SV_UpdateUserinfo_f ================== */ static void SV_UpdateUserinfo_f( client_t *cl ) { char *arg = Cmd_Argv(1); // Stop random empty /userinfo calls without hurting anything if( !arg || !*arg ) return; Q_strncpyz( cl->userinfo, arg, sizeof(cl->userinfo) ); #ifdef FINAL_BUILD if (cl->lastUserInfoChange > svs.time) { cl->lastUserInfoCount++; if (cl->lastUserInfoCount >= INFO_CHANGE_MAX_COUNT) { // SV_SendServerCommand(cl, "print \"Warning: Too many info changes, last info ignored\n\"\n"); SV_SendServerCommand(cl, "print \"@@@TOO_MANY_INFO\n\"\n"); return; } } else #endif { cl->lastUserInfoCount = 0; cl->lastUserInfoChange = svs.time + INFO_CHANGE_MIN_INTERVAL; } SV_UserinfoChanged( cl ); // call prog code to allow overrides GVM_ClientUserinfoChanged( cl - svs.clients ); }
/* ================== SV_Kick_f Kick a user off of the server FIXME: move to game ================== */ static void SV_Kick_f(void) { client_t *cl; int i; // make sure server is running if (!com_sv_running->integer) { Com_Printf("Server is not running.\n"); return; } if (Cmd_Argc() <= 1 || Cmd_Argc() > 3) { Com_Printf("Usage: kick <player> [reason]\nkick all [reason] = kick everyone\nkick allbots = kick all bots\n"); return; } cl = SV_GetPlayerByHandle(); if (!cl) { if (!Q_stricmp(Cmd_Argv(1), "all")) { for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) { if (!cl->state) { continue; } if (cl->netchan.remoteAddress.type == NA_LOOPBACK) { continue; } if (Cmd_Argv(2) && Q_stricmp(Cmd_Argv(2), "") && Q_stricmp(Cmd_Argv(2), " ")) { SV_DropClient(cl, va("was kicked (%s)", Cmd_Argv(2))); } else { SV_DropClient(cl, "was kicked"); } cl->lastPacketTime = svs.time; // in case there is a funny zombie } } else if (!Q_stricmp(Cmd_Argv(1), "allbots")) { for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) { if (!cl->state) { continue; } if (cl->netchan.remoteAddress.type != NA_BOT) { continue; } SV_DropClient(cl, "was kicked"); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } return; } if (cl->netchan.remoteAddress.type == NA_LOOPBACK) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); return; } if (Cmd_Argv(2) && Q_stricmp(Cmd_Argv(2), "") && Q_stricmp(Cmd_Argv(2), " ")) { SV_DropClient(cl, va("was kicked (%s)", Cmd_Argv(2))); } else { SV_DropClient(cl, "was kicked"); } cl->lastPacketTime = svs.time; // in case there is a funny zombie }
static void SV_KickByName( const char *name ) { client_t *cl; int i; // make sure server is running if ( !com_sv_running->integer ) { return; } cl = SV_GetPlayerByFedName(name); if ( !cl ) { if ( !Q_stricmp(name, "all") ) { for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { continue; } SV_DropClient( cl, SV_GetStripEdString("SVINGAME","WAS_KICKED")); // "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } else if ( !Q_stricmp(name, "allbots") ) { for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if( cl->netchan.remoteAddress.type != NA_BOT ) { continue; } SV_DropClient( cl, SV_GetStripEdString("SVINGAME","WAS_KICKED")); // "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } return; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { // SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); SV_SendServerCommand(NULL, "print \"%s\"", SV_GetStripEdString("SVINGAME","CANNOT_KICK_HOST")); return; } SV_DropClient( cl, SV_GetStripEdString("SVINGAME","WAS_KICKED")); // "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie }
/* =============== SV_SendConfigstring Creates and sends the server command necessary to update the CS index for the given client =============== */ static void SV_SendConfigstring(client_t *client, int index) { int maxChunkSize = MAX_STRING_CHARS - 24; int len; if( sv.configstrings[index].restricted && Com_ClientListContains( &sv.configstrings[index].clientList, client - svs.clients ) ) { // Send a blank config string for this client if it's listed SV_SendServerCommand( client, -1, "cs %i \"\"\n", index ); return; } len = strlen(sv.configstrings[index].s); if( len >= maxChunkSize ) { int sent = 0; int remaining = len; char *cmd; char buf[MAX_STRING_CHARS]; while (remaining > 0 ) { if ( sent == 0 ) { cmd = "bcs0"; } else if( remaining < maxChunkSize ) { cmd = "bcs2"; } else { cmd = "bcs1"; } Q_strncpyz( buf, &sv.configstrings[index].s[sent], maxChunkSize ); SV_SendServerCommand( client, -1, "%s %i \"%s\"\n", cmd, index, buf ); sent += (maxChunkSize - 1); remaining -= (maxChunkSize - 1); } } else { // standard cs, just send it SV_SendServerCommand( client, -1, "cs %i \"%s\"\n", index, sv.configstrings[index].s ); } }
/* =============== SV_SendConfigstring Creates and sends the server command necessary to update the CS index for the given client =============== */ static void SV_SendConfigstring( client_t* client, int index ) { int maxChunkSize = MAX_STRING_CHARS - 24; int len; len = strlen( sv.configstrings[index] ); if ( len >= maxChunkSize ) { int sent = 0; int remaining = len; char* cmd; char buf[MAX_STRING_CHARS]; while ( remaining > 0 ) { if ( sent == 0 ) { cmd = "bcs0"; } else if ( remaining < maxChunkSize ) { cmd = "bcs2"; } else { cmd = "bcs1"; } Q_strncpyz( buf, &sv.configstrings[index][sent], maxChunkSize ); SV_SendServerCommand( client, "%s %i \"%s\"\n", cmd, index, buf ); sent += ( maxChunkSize - 1 ); remaining -= ( maxChunkSize - 1 ); } } else { // standard cs, just send it SV_SendServerCommand( client, "cs %i \"%s\"\n", index, sv.configstrings[index] ); } }
/* ================== SV_FinalMessage Used by SV_Shutdown to send a final message to all connected clients before the server goes down. The messages are sent immediately, not just stuck on the outgoing message list, because the server is going to totally exit after returning from this function. ================== */ void SV_FinalMessage( char *message ) { int i, j; client_t *cl; SV_SendServerCommand( NULL, "print \"%s\"", message ); SV_SendServerCommand( NULL, "disconnect" ); // send it twice, ignoring rate for ( j = 0 ; j < 2 ; j++ ) { for (i=0, cl = svs.clients ; i < 1 ; i++, cl++) { if (cl->state >= CS_CONNECTED) { // force a snapshot to be sent cl->nextSnapshotTime = -1; SV_SendClientSnapshot( cl ); } } } }
/* * SV_DenyDownload * Helper function for generating initdownload packets for denying download */ static void SV_DenyDownload( client_t *client, const char *reason ) { // size -1 is used to signal that it's refused // URL field is used for deny reason SV_InitClientMessage( client, &tmpMessage, NULL, 0 ); SV_SendServerCommand( client, "initdownload \"%s\" %i %u %i \"%s\"", "", -1, 0, qfalse, reason ? reason : "" ); SV_AddReliableCommandsToMessage( client, &tmpMessage ); SV_SendMessageToClient( client, &tmpMessage ); }
/* ================== SV_Kick_f Kick a user off of the server FIXME: move to game ================== */ static void SV_Kick_f( void ) { client_t *cl; int i; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() != 2 ) { Com_Printf ("Usage: kick <player name>\nkick all = kick everyone\nkick allbots = kick all bots\n"); return; } if (!Q_stricmp(Cmd_Argv(1), "Padawan")) { //if you try to kick the default name, also try to kick "" SV_KickByName(""); } cl = SV_GetPlayerByName(); if ( !cl ) { if ( !Q_stricmp(Cmd_Argv(1), "all") ) { for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { continue; } SV_DropClient( cl, SV_GetStripEdString("SVINGAME","WAS_KICKED")); // "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } else if ( !Q_stricmp(Cmd_Argv(1), "allbots") ) { for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if( cl->netchan.remoteAddress.type != NA_BOT ) { continue; } SV_DropClient( cl, SV_GetStripEdString("SVINGAME","WAS_KICKED")); // "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } return; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { // SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); SV_SendServerCommand(NULL, "print \"%s\"", SV_GetStripEdString("SVINGAME","CANNOT_KICK_HOST")); return; } SV_DropClient( cl, SV_GetStripEdString("SVINGAME","WAS_KICKED")); // "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie }
/* ================== SV_Ban_f Ban a user from being able to play on this server through the auth server ================== */ static void SV_Ban_f( void ) { client_t *cl; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() != 2 ) { Com_Printf ("Usage: banUser <player name>\n"); return; } cl = SV_GetPlayerByHandle(); if (!cl) { return; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); return; } // look up the authorize server's IP if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) { Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME ); if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP ) ) { Com_Printf( "Couldn't resolve address\n" ); return; } svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE ); Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME, svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1], svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3], BigShort( svs.authorizeAddress.port ) ); } // otherwise send their ip to the authorize server if ( svs.authorizeAddress.type != NA_BAD ) { #ifndef SMOKINGUNS NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, "banUser %i.%i.%i.%i", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1], cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3] ); #else // Tequila comment: Provide also the guid to ban in case of ip change char *guid = Info_ValueForKey ( cl->userinfo, "cl_guid" ); NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, "banUser %i.%i.%i.%i %s", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1], cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3], guid ); #endif Com_Printf("%s was banned from coming back\n", cl->name); } }
/* ================== SV_Ban_f Ban a user from being able to play on this server through the auth server ================== */ static void SV_Ban_f(void) { client_t *cl; // make sure server is running if (!com_sv_running->integer) { Com_Printf("Server is not running.\n"); return; } if (Cmd_Argc() != 2) { Com_Printf("Usage: banUser <player name>\n"); return; } cl = SV_GetPlayerByName(); if (!cl) { return; } if (cl->netchan.remoteAddress.type == NA_LOOPBACK) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); return; } // look up the authorize server's IP if (!svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD) { Com_Printf("Resolving %s\n", AUTHORIZE_SERVER_NAME); if (!NET_StringToAdr(AUTHORIZE_SERVER_NAME, &svs.authorizeAddress)) { Com_Printf("Couldn't resolve address\n"); return; } svs.authorizeAddress.port = BigShort(PORT_AUTHORIZE); Com_Printf("%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME, svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1], svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3], BigShort(svs.authorizeAddress.port)); } // otherwise send their ip to the authorize server if (svs.authorizeAddress.type != NA_BAD) { NET_OutOfBandPrint(NS_SERVER, svs.authorizeAddress, "banUser %i.%i.%i.%i", cl->netchan.remoteAddress.ip[0], cl->netchan.remoteAddress.ip[1], cl->netchan.remoteAddress.ip[2], cl->netchan.remoteAddress.ip[3]); Com_Printf("%s was banned from coming back\n", rc(cl->name)); } }
void PHandler_BoldPrintf(int slot, char *fmt, ... ) { char str[256]; client_t *cl; va_list vl; cl = slot >=0 ? &(svs.clients[slot]) : NULL; va_start(vl,fmt); vsprintf(str,fmt,vl); va_end(vl); SV_SendServerCommand(cl, "c \"%s\"", str); }
/* ================== SV_FinalMessage Used by SV_Shutdown to send a final message to all connected clients before the server goes down. The messages are sent immediately, not just stuck on the outgoing message list, because the server is going to totally exit after returning from this function. ================== */ void SV_FinalMessage( char *message ) { int i, j; client_t *cl; // send it twice, ignoring rate for ( j = 0 ; j < 2 ; j++ ) { for (i=0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++) { if (cl->state >= CS_CONNECTED) { // don't send a disconnect to a local client if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { SV_SendServerCommand( cl, "print \"%s\"", message ); SV_SendServerCommand( cl, "disconnect" ); } // force a snapshot to be sent cl->nextSnapshotTime = -1; SV_SendClientSnapshot( cl ); } } } }
/* ===================== SV_DropClient Called when the player is totally leaving the server, either willingly or unwillingly. This is NOT called if the entire server is quiting or crashing -- SV_FinalMessage() will handle that ===================== */ void SV_DropClient( client_t *drop, const char *reason ) { if ( drop->state == CS_ZOMBIE ) { return; // already dropped } drop->state = CS_ZOMBIE; // become free in a few seconds if (drop->download) { FS_FreeFile (drop->download); drop->download = NULL; } // call the prog function for removing a client // this will remove the body, among other things ge->ClientDisconnect( drop - svs.clients ); // tell everyone why they got dropped SV_SendServerCommand( NULL, "print \"%s %s\n\"", drop->name, reason ); // add the disconnect command SV_SendServerCommand( drop, "disconnect" ); }
/* ================== SV_Auth_Ban_f Ban a user from the server and the group ================== */ static void SV_Auth_Ban_f( void ) { client_t *cl; int idnum = -1; char *days; char *hours; char *mins; if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } days = Cmd_Argv( 2 ); hours = Cmd_Argv( 3 ); mins = Cmd_Argv( 4 ); if ( Cmd_Argc() < 5 ) { Com_Printf ("Usage: auth-ban <client number|name> <days> <hours> <mins>\n"); return; } idnum = SV_Argc_to_idnum( 1 ); if( idnum == -1 ) { Com_Printf("Client not found\n"); return; } cl = &svs.clients[idnum]; if ( !cl ) { Com_Printf("Client not found\n"); return; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot ban host players.\n"); return; } if ( Cvar_VariableValue("auth_enable") >= 1 ) { VM_Call(gvm, GAME_AUTH_BAN, idnum, atoi(days), atoi(hours), atoi(mins)); } else { Com_Printf( "Auth services disabled\n" ); return; } }
/* * SV_CvarCheck_f * Ask the client to inform us of the current value of a cvar */ static void SV_CvarCheck_f( void ) { client_t *client; int i; if( !svs.initialized ) return; if( Cmd_Argc() != 3 ) { Com_Printf( "Usage: cvarcheck <userid> <cvar name>\n" ); return; } if( !Q_stricmp( Cmd_Argv( 1 ), "all" ) ) { for( i = 0, client = svs.clients; i < sv_maxclients->integer; i++, client++ ) { if( !client->state ) continue; if( client->tvclient ) continue; SV_SendServerCommand( client, "cvarinfo \"%s\"", Cmd_Argv( 2 ) ); } return; } client = SV_FindPlayer( Cmd_Argv( 1 ) ); if( !client ) { Com_Printf( "%s is not valid client id\n", Cmd_Argv( 1 ) ); return; } SV_SendServerCommand( client, "cvarinfo \"%s\"", Cmd_Argv( 2 ) ); }
/* ================== SV_Kick_f Kick a user off of the server FIXME: move to game ================== */ static void SV_Kick_f( void ) { client_t *cl; int i; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() != 2 ) { // Com_Printf ("Usage: kick <player name>\nkick all = kick everyone\nkick allbots = kick all bots\n"); Com_Printf( "Usage: kick <player name>\nkick all = kick everyone\n" ); return; } cl = SV_GetPlayerByName(); if ( !cl ) { if ( !Q_stricmp( Cmd_Argv( 1 ), "all" ) ) { for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if ( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { continue; } SV_DropClient( cl, "player kicked" ); // JPW NERVE to match front menu message cl->lastPacketTime = svs.time; // in case there is a funny zombie } } else if ( !Q_stricmp( Cmd_Argv( 1 ), "allbots" ) ) { for ( i = 0, cl = svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if ( cl->netchan.remoteAddress.type != NA_BOT ) { continue; } SV_DropClient( cl, "was kicked" ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } return; } if ( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { SV_SendServerCommand( NULL, "print \"%s\"", "Cannot kick host player\n" ); return; } SV_DropClient( cl, "player kicked" ); // JPW NERVE to match front menu message cl->lastPacketTime = svs.time; // in case there is a funny zombie }
/* ================== SV_UpdateUserinfo_f ================== */ static void SV_UpdateUserinfo_f( client_t *cl ) { #if 0 /* TODO */ if( cl->lastUserInfoChange > svs.time && cl->lastUserInfoCount > 5 ) { SV_SendServerCommand( cl, "print \"@@@TOO_MANY_INFO\n\"" ); return; } #endif Q_strncpyz( cl->userinfo, Cmd_Argv(1), sizeof(cl->userinfo) ); SV_UserinfoChanged( cl ); // call prog code to allow overrides VM_Call( gvm, GAME_CLIENT_USERINFO_CHANGED, cl - svs.clients ); }
/* ================== SV_UpdateUserinfo_f ================== */ void SV_UpdateUserinfo_f( client_t *cl ) { if ( (sv_floodProtect->integer) && (cl->state >= CS_ACTIVE) && (svs.time < cl->nextReliableUserTime) ) { Q_strncpyz( cl->userinfobuffer, Cmd_Argv(1), sizeof(cl->userinfobuffer) ); SV_SendServerCommand(cl, "print \"^7Command ^1delayed^7 due to sv_floodprotect.\""); return; } cl->userinfobuffer[0]=0; cl->nextReliableUserTime = svs.time + 5000; Q_strncpyz( cl->userinfo, Cmd_Argv(1), sizeof(cl->userinfo) ); SV_UserinfoChanged( cl ); // call prog code to allow overrides VM_Call( gvm, GAME_CLIENT_USERINFO_CHANGED, cl - svs.clients ); }
/* * SV_FinalMessage * * Used by SV_ShutdownGame to send a final message to all * connected clients before the server goes down. The messages are sent immediately, * not just stuck on the outgoing message list, because the server is going * to totally exit after returning from this function. */ static void SV_FinalMessage( const char *message, bool reconnect ) { int i, j; client_t *cl; for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { if( cl->edict && ( cl->edict->r.svflags & SVF_FAKECLIENT ) ) { continue; } if( cl->state >= CS_CONNECTING ) { if( reconnect ) { SV_SendServerCommand( cl, "forcereconnect \"%s\"", message ); } else { SV_SendServerCommand( cl, "disconnect %i \"%s\"", DROP_TYPE_GENERAL, message ); } SV_InitClientMessage( cl, &tmpMessage, NULL, 0 ); SV_AddReliableCommandsToMessage( cl, &tmpMessage ); // send it twice for( j = 0; j < 2; j++ ) SV_SendMessageToClient( cl, &tmpMessage ); } } }
/* ================== SV_Incognito_f Pretend that you disconnect, but really go to spec. ================== */ static void SV_Incognito_f(void) { client_t *cl; int i; char cmd[64]; // Make sure server is running. if (!com_sv_running->integer) { Com_Printf("Server is not running.\n"); return; } if (!in_redirect) { Com_Printf("The incognito command can only be run through rcon\n"); return; } if (Cmd_Argc() != 1) { Com_Printf("No arguments expected for incognito command\n"); return; } // Find the person connected to server who issued the incognito command. for (i = 0, cl = svs.clients;; i++, cl++) { if (i == sv_maxclients->integer) { cl = NULL; break; } if (cl->state >= CS_ACTIVE && NET_CompareAdr(cl->netchan.remoteAddress, svs.redirectAddress)) { break; // found } } if (cl != NULL) { sv.incognitoJoinSpec = qtrue; Com_sprintf(cmd, sizeof(cmd), "forceteam %i spectator\n", i); Cmd_ExecuteString(cmd); sv.incognitoJoinSpec = qfalse; SV_SendServerCommand(NULL, "print \"%s" S_COLOR_WHITE " disconnected\n\"", cl->name); // color OK Com_sprintf(cmd, sizeof(cmd), "sendclientcommand all cs %i \"\"\n", 548 + i); Cmd_ExecuteString(cmd); } else { Com_Printf("Must be connected to server for incognito to work\n"); } }
static void SV_ConBig_f(void) { char *p; char text[1024]; client_t *cl; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() < 3 ) { Com_Printf ("Usage: big <clientid> <text>\n"); return; } cl = SV_GetPlayerByNum(); if (atoi(Cmd_Argv(1)) < 0) { cl = NULL; } // if (atoi(Cmd_Argv(1))) { // Com_Printf ("Hi1 -1\n"); //// Com_Printf ("Hi2 -1\n"); // if ( !cl ) { // return; // } //// Com_Printf ("Hi3 -1\n"); // } strcpy (text, "^3"); p = Cmd_ArgsFrom(2); if ( *p == '"' ) { p++; p[strlen(p)-1] = 0; } strcat(text, p); SV_SendServerCommand(cl, "cp \"" S_COLOR_WHITE "%s\n\"", text); }
P_P_F void Plugin_BoldPrintf(int slot, const char *fmt, ... ) { char str[256]; client_t *cl; va_list vl; if(slot < 0) cl = NULL; else if( slot < sv_maxclients->integer) cl = &svs.clients[slot]; else return; va_start(vl,fmt); Q_vsnprintf(str, sizeof(str), fmt, vl); va_end(vl); SV_SendServerCommand(cl, "c \"%s\"", str); }
/* ================== SV_KickNum_f Kick a user off of the server FIXME: move to game ================== */ static void SV_KickNum_f( void ) { client_t *cl; char cmd_args[MAX_STRING_CHARS];// patch servercommands: enable the ability to provide a reason with clientkicks int i; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() < 2 ) { #ifndef SMOKINGUNS Com_Printf ("Usage: kicknum <client number>\n"); #else Com_Printf ("Usage: clientkick <client number> [<reason>]\n"); #endif return; } cl = SV_GetPlayerByNum(); if ( !cl ) { return; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); return; } if ( Cmd_Argc() == 2 ) { SV_DropClient( cl, "was ^3kicked^7!"); cl->lastPacketTime = svs.time; // in case there is a funny zombie } else { cmd_args[0]=0; for ( i=2 ; i<Cmd_Argc() ; i++ ) { Q_strcat( cmd_args, sizeof(cmd_args), Cmd_Argv(i) ); if ( i != Cmd_Argc()-1 ) { Q_strcat( cmd_args, sizeof(cmd_args), " " ); } } SV_DropClient( cl, cmd_args); cl->lastPacketTime = svs.time; // in case there is a funny zombie } }
/* ================== SV_Kick_f Kick a user off of the server FIXME: move to game ================== */ static void SV_KickUnpure_f( void ) { client_t *cl; int i; // make sure server is running if ( !com_sv_running->integer ) { Com_Printf( "Server is not running.\n" ); return; } if ( Cmd_Argc() != 2 ) { Com_Printf ("Usage: kick <player name>\nkick all = kick everyone\n"); return; } cl = SV_GetPlayerByHandle(); if ( !cl ) { if ( !Q_stricmp(Cmd_Argv(1), "all") ) { for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { if ( !cl->state ) { continue; } if ( cl->pureAuthentic != 2 || cl->netchan.remoteAddress.type == NA_BOT) { continue; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { continue; } SV_DropClient( cl, "missed the correct .PK3 files. ^rPlease ^ropen ^rconsole ^r(^gShift^r+^gEsc^r) ^rand ^rtype ^g\\seta ^gcg_allowDownload ^g1 ^rand ^g\\reconnect^r." ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } } return; } if( cl->netchan.remoteAddress.type == NA_LOOPBACK ) { SV_SendServerCommand(NULL, "print \"%s\"", "Cannot kick host player\n"); return; } if ( cl->pureAuthentic == 2 ) { SV_DropClient( cl, "missed the correct .PK3 files. ^rPlease ^ropen ^rconsole ^r(^gShift^r+^gEsc^r) ^rand ^rtype ^g\\seta ^gcg_allowDownload ^g1 ^rand ^g\\reconnect^r." ); cl->lastPacketTime = svs.time; // in case there is a funny zombie } }
/* ================== SV_MapChange Used by SV_SpawnServer to send a final message to all connected clients before the server changes maps. The messages are sent immediately, not just stuck on the outgoing message list. FIXME: Not base client compatible Assumes svs.clients is valid and not com_errorEntered. ================== */ void SV_MapChange( void ) { int i, j; client_t *cl; // send it 4 times, ignoring rate for ( j = 0 ; j < 4 ; j++ ) { for (i=0, cl = svs.clients ; i < sv_maxclients->integer ; i++, cl++) { if (cl->state >= CS_CONNECTED) { // don't send a mapchange to a local client if ( cl->netchan.remoteAddress.type != NA_LOOPBACK ) { SV_SendServerCommand( cl, "mapchange\n" ); } // force a snapshot to be sent cl->lastSnapshotTime = 0; SV_SendClientSnapshot( cl ); } } } }
void __cdecl My_SV_SendServerCommand(client_t* cl, const char* fmt, ...) { int res = 1; va_list argptr; char buffer[MAX_MSGLEN]; va_start(argptr, fmt); vsnprintf((char *)buffer, sizeof(buffer), fmt, argptr); va_end(argptr); if (cl && cl->gentity) res = ServerCommandDispatcher(cl->gentity->s.clientNum, buffer); else if (cl == NULL) res = ServerCommandDispatcher(-1, buffer); if (!res) return; SV_SendServerCommand(cl, buffer); }
void __cdecl Slay(void) { int argc = Cmd_Argc(); if (argc < 2) { Com_Printf("Usage: %s <client_id>\n", Cmd_Argv(0)); return; } int i = atoi(Cmd_Argv(1)); if (i < 0 || i > sv_maxclients->integer) { Com_Printf("client_id must be a number between 0 and %d\n.", sv_maxclients->integer); return; } else if (g_entities[i].inuse && g_entities[i].health > 0) { Com_Printf("Slaying player...\n"); SV_SendServerCommand(NULL, "print \"%s^7 was slain!\n\"\n", svs->clients[i].name); DebugPrint("Slaying '%s'!\n", svs->clients[i].name); g_entities[i].health = -40; G_AddEvent(&g_entities[i], EV_GIB_PLAYER, g_entities[i].s.number); } else Com_Printf("The player is currently not active.\n"); }
/* * SV_BroadcastCommand * * Sends a command to all connected clients. Ignores client->state < CS_SPAWNED check */ void SV_BroadcastCommand( const char *format, ... ) { client_t *client; int i; va_list argptr; char string[1024]; if( !sv.state ) return; va_start( argptr, format ); Q_vsnprintfz( string, sizeof( string ), format, argptr ); va_end( argptr ); for( i = 0, client = svs.clients; i < sv_maxclients->integer; i++, client++ ) { if( client->state < CS_CONNECTING ) continue; SV_SendServerCommand( client, string ); } }