void __cdecl My_SV_ExecuteClientCommand(client_t *cl, const char *s, qboolean clientOK) { if (clientOK && cl->gentity) { int res = ClientCommandDispatcher(cl->gentity->s.clientNum, s); if (!res) return; } SV_ExecuteClientCommand(cl, s, clientOK); }
/* =============== SV_ClientCommand =============== */ static qboolean SV_ClientCommand( client_t *cl, msg_t *msg ) { int seq; const char *s; qboolean clientOk = qtrue; seq = MSG_ReadLong( msg ); s = MSG_ReadString( msg ); // see if we have already executed it if ( cl->lastClientCommand >= seq ) { return qtrue; } Com_DPrintf( "clientCommand: %s : %i : %s\n", cl->name, seq, s ); // drop the connection if we have somehow lost commands if ( seq > cl->lastClientCommand + 1 ) { Com_Printf( "Client %s lost %i clientCommands\n", cl->name, seq - cl->lastClientCommand + 1 ); SV_DropClient( cl, "Lost reliable commands" ); return qfalse; } // malicious users may try using too many string commands // to lag other players. If we decide that we want to stall // the command, we will stop processing the rest of the packet, // including the usercmd. This causes flooders to lag themselves // but not other people // We don't do this when the client hasn't been active yet since its // normal to spam a lot of commands when downloading // Applying floodprotect only to "CS_ACTIVE" clients leaves too much room for abuse. Extending floodprotect to clients pre CS_ACTIVE shouldn't cause any issues, as the download-commands are handled within the engine and floodprotect only filters calls to the VM. if ( !com_cl_running->integer && /* cl->state >= CS_ACTIVE && */ sv_floodProtect->integer ) { if ( sv_floodProtect->integer == 1 && svs.time < cl->nextReliableTime ) { clientOk = qfalse; } else if ( SVC_RateLimit(&cl->cmdBucket, sv_floodProtect->integer, 1000, svs.time) ) { clientOk = qfalse; } } // don't allow another command for one second cl->nextReliableTime = svs.time + 1000; SV_ExecuteClientCommand( cl, s, clientOk ); cl->lastClientCommand = seq; Com_sprintf(cl->lastClientCommandString, sizeof(cl->lastClientCommandString), "%s", s); return qtrue; // continue procesing }
/* =============== SV_ClientCommand =============== */ static qboolean SV_ClientCommand(client_t *cl, msg_t *msg) { int seq; const char *s; qboolean clientOk = qtrue; seq = MSG_ReadLong(msg); s = MSG_ReadString(msg); // see if we have already executed it if(cl->lastClientCommand >= seq) { return qtrue; } Com_DPrintf("clientCommand: %s : %i : %s\n", cl->name, seq, s); // drop the connection if we have somehow lost commands if(seq > cl->lastClientCommand + 1) { Com_Printf("Client %s lost %i clientCommands\n", cl->name, seq - cl->lastClientCommand + 1); SV_DropClient(cl, "Lost reliable commands"); return qfalse; } // malicious users may try using too many string commands // to lag other players. If we decide that we want to stall // the command, we will stop processing the rest of the packet, // including the usercmd. This causes flooders to lag themselves // but not other people // We don't do this when the client hasn't been active yet since its // normal to spam a lot of commands when downloading if(!com_cl_running->integer && cl->state >= CS_ACTIVE && // (SA) this was commented out in Wolf. Did we do that? sv_floodProtect->integer && svs.time < cl->nextReliableTime) { // ignore any other text messages from this client but let them keep playing clientOk = qfalse; Com_DPrintf("client text ignored for %s\n", cl->name); //return qfalse; // stop processing } // don't allow another command for one second cl->nextReliableTime = svs.time + 1000; SV_ExecuteClientCommand(cl, s, clientOk); cl->lastClientCommand = seq; Com_sprintf(cl->lastClientCommandString, sizeof(cl->lastClientCommandString), "%s", s); return qtrue; // continue procesing }
/** * @brief Request weapon stats data from mod */ void Tracker_requestWeaponStats(void) { int i; qboolean onlybots = qtrue; char *P; if (!maprunning) { return; } strcpy(infostring, Cvar_InfoString(CVAR_SERVERINFO | CVAR_SERVERINFO_NOUPDATE)); P = Info_ValueForKey(infostring, "P"); strcpy(expect, "ws"); for (i = 0; i < sv_maxclients->value; i++) { if (svs.clients[i].state == CS_ACTIVE) { if (svs.clients[i].netchan.remoteAddress.type != NA_BOT) { onlybots = qfalse; querycl = i; } expectnum++; } } if (expectnum > 0) { Tracker_Send("wsc %i", expectnum); for (i = 0; i < sv_maxclients->value; i++) { if (svs.clients[i].state == CS_ACTIVE) { // send basic data is client is spectator if (P[i] == '3' || (svs.clients[i].netchan.remoteAddress.type == NA_BOT && onlybots)) { Tracker_Send("ws %i 0 0 0\\%s", i, Tracker_createClientInfo(i)); } } } if (querycl >= 0) { SV_ExecuteClientCommand(&svs.clients[querycl], "statsall", qtrue, qfalse); } } }
static PyObject* PyMinqlx_ClientCommand(PyObject* self, PyObject* args) { int i; char* cmd; if (!PyArg_ParseTuple(args, "is:client_command", &i, &cmd)) return NULL; if (i >= 0 && i < sv_maxclients->integer) { if (svs->clients[i].state == CS_FREE || svs->clients[i].state == CS_ZOMBIE) Py_RETURN_FALSE; else { SV_ExecuteClientCommand(&svs->clients[i], cmd, qtrue); Py_RETURN_TRUE; } } PyErr_Format(PyExc_ValueError, "client_id needs to be a number from 0 to %d, or None.", sv_maxclients->integer); return NULL; }
/* =============== SV_ClientCommand =============== */ static void SV_ClientCommand( client_t *cl, msg_t *msg ) { int seq; const char *s; seq = MSG_ReadLong( msg ); s = MSG_ReadString( msg ); // see if we have already executed it if ( cl->lastClientCommand >= seq ) { return; } Com_DPrintf( "clientCommand: %s : %i : %s\n", cl->name, seq, s ); // drop the connection if we have somehow lost commands if ( seq > cl->lastClientCommand + 1 ) { Com_Printf( "Client %s lost %i clientCommands\n", cl->name, seq - cl->lastClientCommand + 1 ); } SV_ExecuteClientCommand( cl, s ); cl->lastClientCommand = seq; }
/* ================== SV_BotClientCommand ================== */ static void BotClientCommand( int client, char *command ) { SV_ExecuteClientCommand( &svs.clients[client], command, qtrue ); }
void BotClientCommand( int client, const char* command ) { SV_ExecuteClientCommand( &svs.clients[ client ], command, true, false ); }
/* =============== SV_ClientCommand =============== */ static bool SV_ClientCommand( client_t *cl, msg_t *msg, bool premaprestart ) { int seq; const char *s; bool clientOk = true; bool floodprotect = true; seq = MSG_ReadLong( msg ); s = MSG_ReadString( msg ); // see if we have already executed it if ( cl->lastClientCommand >= seq ) { return true; } Log::Debug( "clientCommand: %s^7 : %i : %s", cl->name, seq, s ); // drop the connection if we have somehow lost commands if ( seq > cl->lastClientCommand + 1 ) { Log::Notice( "Client %s lost %i clientCommands\n", cl->name, seq - cl->lastClientCommand + 1 ); SV_DropClient( cl, "Lost reliable commands" ); return false; } // Gordon: AHA! Need to steal this for some other stuff BOOKMARK // NERVE - SMF - some server game-only commands we cannot have flood protect if ( !Q_strncmp( "team", s, 4 ) || !Q_strncmp( "setspawnpt", s, 10 ) || !Q_strncmp( "score", s, 5 ) || !Q_stricmp( "forcetapout", s ) ) { // Log::Debug( "Skipping flood protection for: %s", s ); floodprotect = false; } // malicious users may try using too many string commands // to lag other players. If we decide that we want to stall // the command, we will stop processing the rest of the packet, // including the usercmd. This causes flooders to lag themselves // but not other people // We don't do this when the client hasn't been active yet, since it is // by protocol to spam a lot of commands when downloading if ( !com_cl_running->integer && cl->state >= clientState_t::CS_ACTIVE && // (SA) this was commented out in Wolf. Did we do that? sv_floodProtect->integer && svs.time < cl->nextReliableTime && floodprotect ) { // ignore any other text messages from this client but let them keep playing // TTimo - moved the ignored verbose to the actual processing in SV_ExecuteClientCommand, only printing if the core doesn't intercept clientOk = false; } // don't allow another command for 800 msec if ( floodprotect && svs.time >= cl->nextReliableTime ) { cl->nextReliableTime = svs.time + 800; } SV_ExecuteClientCommand( cl, s, clientOk, premaprestart ); cl->lastClientCommand = seq; Com_sprintf( cl->lastClientCommandString, sizeof( cl->lastClientCommandString ), "%s", s ); return true; // continue processing }