/* ================== SV_Kick_f Kick a user off of the server ================== */ void SV_Kick_f (void) { int i, j; client_t *cl; int uid; int c; int saved_state; char reason[80] = ""; c = Cmd_Argc (); if (c < 2) { #ifndef SERVERONLY // some mods use a "kick" alias for their own needs, sigh if (CL_ClientState() && Cmd_FindAlias("kick")) { Cmd_ExecuteString (Cmd_AliasString("kick"), false); return; } #endif Com_Printf ("kick <userid> [reason]\n"); return; } uid = atoi(Cmd_Argv(1)); for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (!cl->state) continue; if (cl->userid == uid) { if (c > 2) { strcpy (reason, " ("); for (j=2 ; j<c; j++) { strncat (reason, Cmd_Argv(j), sizeof(reason)-4); if (j < c-1) strncat (reason, " ", sizeof(reason)-4); } if (strlen(reason) < 3) reason[0] = '\0'; else strncat (reason, ")", sizeof(reason)); } saved_state = cl->state; cl->state = cs_free; // HACK: don't broadcast to this client SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked%s\n", cl->name, reason); cl->state = saved_state; SV_ClientPrintf (cl, PRINT_HIGH, "You were kicked from the game%s\n", reason); SV_DropClient (cl); return; } } Com_Printf ("Couldn't find user number %i\n", uid); }
// auto-tracking is a feature implemented in three different places in QW // - server side, client side (for a demo), recorded in a demo // this command will choose which feature is available // at the moment and will toggle it (on/off) void CL_Autotrack_f(void) { cmd_alias_t* at; extern cvar_t mvd_autotrack; extern cvar_t demo_autotrack; qbool mvda = mvd_autotrack.integer ? true : false; qbool demoa = demo_autotrack.integer ? true : false; if (cls.demoplayback) { if (cls.mvdplayback) { if (cl_hightrack.integer) { Cvar_SetValue(&cl_hightrack, 0); } if (!mvda && !demoa) { // we will turn on both features but if demo_autotrack info is found // it will turn off mvd_autotrack Cvar_SetValue(&mvd_autotrack, 4); Cvar_SetValue(&demo_autotrack, 1); Com_Printf("MVD Autotracking on\n"); } else if (mvda && !demoa) { Com_Printf("MVD Autotracking off\n"); Cvar_SetValue(&mvd_autotrack, 0); } else if (!mvda && demoa) { Com_Printf("Demo Autotracking off\n"); Cvar_SetValue(&demo_autotrack, 0); } else { // mvda && demoa Com_Printf("Autotracking off\n"); Cvar_SetValue(&mvd_autotrack, 0); Cvar_SetValue(&demo_autotrack, 0); } } else { Com_Printf("Only one point of view is recorded in this demo\n"); } } else { // not playing a demo if (cl.spectator) { if ((at = Cmd_FindAlias("autotrack")) != NULL) { // not very "clean" way to execute an alias, but sufficient for this purpose Cbuf_AddText(va("%s\n", at->value)); } else { if (!cl_hightrack.integer) { Com_Printf("Autotrack not supported here, tracking top fragger (Hightrack on)\n"); Cvar_SetValue(&cl_hightrack, 1); } else { Com_Printf("Hightrack off\n"); Cvar_SetValue(&cl_hightrack, 0); } } } } }
/* =============== Cmd_Alias_f Creates a new command that executes a command string (possibly ; separated) =============== */ void Cmd_Alias_f (void) { cmd_alias_t *a; int key; char *name; if (Cmd_Argc() == 1) { Com_Printf ("alias <name> <command> : create or modify an alias\n"); Com_Printf ("aliaslist : list all aliases\n"); return; } name = Cmd_Argv(1); // see if there's already an alias by that name a = Cmd_FindAlias(name); if (a) { // reuse it Q_free (a->name); Q_free (a->value); } else { // allocate a new one a = Q_malloc (sizeof(cmd_alias_t)); a->flags = 0; // link it in a->next = cmd_alias; cmd_alias = a; key = Com_HashKey(name); a->hash_next = cmd_alias_hash[key]; cmd_alias_hash[key] = a; } a->name = Q_strdup(name); a->value = Q_strdup(Cmd_MakeArgs(2)); // copy the rest of the command line #ifndef SERVERONLY if (cbuf_current == &cbuf_svc) a->flags |= ALIAS_STUFFED; else a->flags &= ALIAS_STUFFED; #endif if (!Q_stricmp(Cmd_Argv(0), "aliasa")) a->flags |= ALIAS_ARCHIVE; }
/* =============== Cmd_Viewalias_f =============== */ void Cmd_Viewalias_f (void) { cmd_alias_t *alias; if (Cmd_Argc() < 2) { Com_Printf ("viewalias <aliasname> : view body of alias\n"); return; } alias = Cmd_FindAlias(Cmd_Argv(1)); if (alias) Com_Printf ("%s : \"%s\"\n", Cmd_Argv(1), alias->value); else Com_Printf ("No such alias: %s\n", Cmd_Argv(1)); }
double Movie_StartFrame(void) { double time; int views = 1; if (cl_multiview.value) { views = cl_multiview.value; } if (Cmd_FindAlias("f_captureframe")) { Cbuf_AddTextEx (&cbuf_main, "f_captureframe\n"); } // Default to 30 fps. time = (movie_fps.value > 0) ? (1.0 / movie_fps.value) : (1 / 30.0); return bound(1.0 / 1000, time / views, 1.0); }
void Cam_Lock(int playernum) { char st[32]; if (Cmd_FindAlias("f_trackspectate")) { Cbuf_AddTextEx (&cbuf_main, "f_trackspectate\n"); } if (cl_multiview.value && cls.mvdplayback) return; snprintf(st, sizeof (st), "ptrack %i", playernum); if (cls.mvdplayback) { memcpy(cl.stats, cl.players[playernum].stats, sizeof(cl.stats)); ideal_track = playernum; } last_lock = cls.realtime; if (cls.mvdplayback == QTV_PLAYBACK) { // its not setinfo extension, but adding new extension just for this is stupid IMO QTV_Cmd_Printf(QTV_EZQUAKE_EXT_SETINFO, st); } else { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, st); } spec_track = playernum; locked = false; Sbar_Changed(); if (TP_NeedRefreshSkins()) TP_RefreshSkins(); }
void Cam_Unlock(void) { if (Cmd_FindAlias("f_freeflyspectate")) { Cbuf_AddTextEx (&cbuf_main, "f_freeflyspectate\n"); } if (!autocam) { return; } if (cls.mvdplayback == QTV_PLAYBACK) { // its not setinfo extension, but adding new extension just for this is stupid IMO QTV_Cmd_Printf(QTV_EZQUAKE_EXT_SETINFO, "ptrack"); } else { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, "ptrack"); } autocam = CAM_NONE; locked = false; Sbar_Changed(); if (cls.mvdplayback && cl.teamfortress) { V_TF_ClearGrenadeEffects (); } if (TP_NeedRefreshSkins()) { TP_RefreshSkins(); } }
void TP_ExecTrigger (char *trigger) { int i, j, numteammates = 0; cmd_alias_t *alias; if (!tp_triggers.value || ((cls.demoplayback || cl.spectator) && cl_restrictions.value)) return; for (i = 0; i < num_f_triggers; i++) { if (!strcmp (f_triggers[i].name, trigger)) break; } if (i == num_f_triggers) { Com_Printf ("Unknown f_trigger \"%s\"", trigger); return; } if (f_triggers[i].teamplay && !tp_forceTriggers.value) { if (!cl.teamplay) return; for (j = 0; j < MAX_CLIENTS; j++) if (cl.players[j].name[0] && !cl.players[j].spectator && j != cl.playernum) if (!strcmp(cl.players[j].team, cl.players[cl.playernum].team)) numteammates++; if (!numteammates) return; } if ((alias = Cmd_FindAlias (trigger))) { if (!(f_triggers[i].restricted && Rulesets_RestrictTriggers ())) { Cbuf_AddTextEx (&cbuf_main, va("%s\n", alias->value)); } } }
// auto-tracking is a feature implemented in three different places in QW // - server side, client side (for a demo), recorded in a demo // this command will choose which feature is available // at the moment and will toggle it (on/off) void CL_Autotrack_f(void) { cmd_alias_t* at; extern cvar_t mvd_autotrack; extern cvar_t demo_autotrack; qbool mvda = mvd_autotrack.integer ? true : false; qbool demoa = demo_autotrack.integer ? true : false; if (cls.demoplayback) { if (cls.mvdplayback) { if (cl_hightrack.integer) { Cvar_SetValue(&cl_hightrack, 0); } if (!mvda && !demoa) { // we will turn on both features but if demo_autotrack info is found // it will turn off mvd_autotrack Cvar_SetValue(&mvd_autotrack, 4); Cvar_SetValue(&demo_autotrack, 1); Com_Printf("MVD Autotracking on\n"); } else if (mvda && !demoa) { Com_Printf("MVD Autotracking off\n"); Cvar_SetValue(&mvd_autotrack, 0); } else if (!mvda && demoa) { Com_Printf("Demo Autotracking off\n"); Cvar_SetValue(&demo_autotrack, 0); } else { // mvda && demoa Com_Printf("Autotracking off\n"); Cvar_SetValue(&mvd_autotrack, 0); Cvar_SetValue(&demo_autotrack, 0); } } else { Com_Printf("Only one point of view is recorded in this demo\n"); } } else { // not playing a demo if (cl.spectator) { if ((at = Cmd_FindAlias("autotrack")) != NULL) { // not very "clean" way to execute an alias, but sufficient for this purpose Cbuf_AddText(va("%s\n", at->value)); // note KTX this is cmd 154, but we want to be compatible with other mods/versions /* Bugfix: When setting autotrack ON, make sure to set cl_hightrack 0. If player hits autotrack bind before KTX had a chance to stuff the impulse, then ezQuake would set cl_hightrack to 1. Then, if player hits autotrack again after KTX has finished stuffing, both autotrack and cl_hightrack would be on, creating chaos. HOWEVER, this creates a different, albeit less frustrating bug: if you have autotrack on first, then set cl_hightrack 1, then turn off autotrack, cl_hightrack gets set to 0. Currently there is no better way to solve this as autotrack is simply a command sent to the server.*/ if (cl_hightrack.integer) { Cvar_SetValue(&cl_hightrack, 0); Com_Printf("Hightrack off\n"); } } else { if (!cl_hightrack.integer) { Com_Printf("Autotrack not supported here, tracking top fragger (Hightrack on)\n"); Cvar_SetValue(&cl_hightrack, 1); } else { Com_Printf("Hightrack off\n"); Cvar_SetValue(&cl_hightrack, 0); } } } } }
qbool CL_SearchForReTriggers (const char *s, unsigned trigger_type) { pcre_trigger_t *rt; pcre_internal_trigger_t *irt; cmd_alias_t *trig_alias; qbool removestr = false; int result; int offsets[99]; int len = strlen(s); // internal triggers - always enabled if (trigger_type < RE_PRINT_ECHO) { allow_re_triggers = true; for (irt = internal_triggers; irt; irt = irt->next) { if (irt->flags & trigger_type) { result = pcre_exec (irt->regexp, irt->regexp_extra, s, len, 0, 0, offsets, 99); if (result >= 0) { Re_Trigger_Copy_Subpatterns (s, offsets, min(result,10), re_subi); irt->func (s); } } } if (!allow_re_triggers) return false; } // message triggers disabled if (!tp_msgtriggers.value) return false; // triggers banned by ruleset or FPD and we are a player if (((cl.fpd & FPD_NO_SOUNDTRIGGERS) || (cl.fpd & FPD_NO_TIMERS) || Rulesets_RestrictTriggers ()) && !cls.demoplayback && !cl.spectator) return false; // we are in spec/demo mode, so play triggers if user want it if ((cls.demoplayback || cl.spectator) && cl_restrictions.value) return false; // regexp triggers for (rt = re_triggers; rt; rt = rt->next) if ( (rt->flags & RE_ENABLED) && // enabled (rt->flags & trigger_type) && // mask fits rt->regexp && // regexp not empty (rt->min_interval == 0.0 || cls.realtime >= rt->min_interval + rt->lasttime)) // not too fast. // TODO: disable it ^^^ for FPD_NO_TIMERS case. // probably it dont solve re_trigger timers problem // you always trigger on statusbar(TF) or wp_stats (KTPro/KTX) messages and get 0.5~1.5 accuracy for your timer { result = pcre_exec (rt->regexp, rt->regexp_extra, s, len, 0, 0, offsets, 99); if (result >= 0) { rt->lasttime = cls.realtime; rt->counter++; Re_Trigger_Copy_Subpatterns (s, offsets, min(result,10), re_sub); if (!(rt->flags & RE_NOACTION)) { trig_alias = Cmd_FindAlias (rt->name); Print_current++; if (trig_alias) { Cbuf_InsertTextEx (&cbuf_safe, "\nwait\n"); Cbuf_InsertTextEx (&cbuf_safe, rt->name); Cbuf_ExecuteEx (&cbuf_safe); } else Com_Printf ("re_trigger \"%s\" has no matching alias\n", rt->name); Print_current--; } if (rt->flags & RE_REMOVESTR) removestr = true; if (rt->flags & RE_NOLOG) Print_flags[Print_current] |= PR_LOG_SKIP; if (rt->flags & RE_FINAL) break; } } if (removestr) Print_flags[Print_current] |= PR_SKIP; return removestr; }
void SV_Status_f (void) { int i, j, l; client_t *cl; float cpu, avg, pak; char *s; #ifndef SERVERONLY // some mods use a "status" alias for their own needs, sigh if (!sv_redirected && !strcasecmp(Cmd_Argv(0), "status") && CL_ClientState() && Cmd_FindAlias("status")) { Cmd_ExecuteString (Cmd_AliasString("status")); return; } #endif cpu = (svs.stats.latched_active + svs.stats.latched_idle); if (cpu) cpu = 100 * svs.stats.latched_active / cpu; avg = 1000 * svs.stats.latched_active / STATFRAMES; pak = (float) svs.stats.latched_packets / STATFRAMES; if (svs.socketip != INVALID_SOCKET && net_local_sv_ipadr.type != NA_LOOPBACK) Com_Printf ("ip address : %s\n",NET_AdrToString (net_local_sv_ipadr)); // TCPCONNECT --> if (svs.sockettcp != INVALID_SOCKET && net_local_sv_tcpipadr.type != NA_LOOPBACK) Com_Printf ("tcp address : %s\n",NET_AdrToString (net_local_sv_tcpipadr)); // <-- TCPCONNECT Com_Printf ("cpu utilization : %3i%%\n",(int)cpu); Com_Printf ("avg response time: %i ms\n",(int)avg); Com_Printf ("packets/frame : %5.2f (%d)\n", pak, num_prstr); // min fps lat drp if (sv_redirected != RD_NONE) { // most remote clients are 40 columns // 0123456789012345678901234567890123456789 Com_Printf ("name userid frags\n"); Com_Printf (" address rate ping drop\n"); Com_Printf (" ---------------- ---- ---- -----\n"); for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (!cl->state) continue; Com_Printf ("%-16.16s ", cl->name); Com_Printf ("%6i %5i", cl->userid, (int)cl->edict->v.frags); if (cl->spectator) Com_Printf (" (s)\n"); else Com_Printf ("\n"); s = NET_BaseAdrToString ( cl->netchan.remote_address); Com_Printf (" %-16.16s", s); if (cl->state == cs_connected) { Com_Printf ("CONNECTING\n"); continue; } if (cl->state == cs_zombie) { Com_Printf ("ZOMBIE\n"); continue; } Com_Printf ("%4i %4i %5.2f\n" , (int)(1000*cl->netchan.frame_rate) , (int)SV_CalcPing (cl) , 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence); } } else { Com_Printf ("frags userid address name rate ping drop qport\n"); Com_Printf ("----- ------ --------------- --------------- ---- ---- ----- -----\n"); for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (!cl->state) continue; Com_Printf ("%5i %6i ", (int)cl->edict->v.frags, cl->userid); s = NET_BaseAdrToString ( cl->netchan.remote_address); Com_Printf ("%s", s); l = 16 - strlen(s); for (j = 0; j < l; j++) Com_Printf (" "); Com_Printf ("%s", cl->name); l = 16 - strlen(cl->name); for (j = 0; j < l; j++) Com_Printf (" "); if (cl->state == cs_connected) { Com_Printf ("CONNECTING\n"); continue; } if (cl->state == cs_zombie) { Com_Printf ("ZOMBIE\n"); continue; } Com_Printf ("%4i %4i %3.1f %4i" , (int)(1000*cl->netchan.frame_rate) , (int)SV_CalcPing (cl) , 100.0*cl->netchan.drop_count / cl->netchan.incoming_sequence , cl->netchan.qport); if (cl->spectator) Com_Printf (" (s)\n"); else Com_Printf ("\n"); } } Com_Printf ("\n"); }
/* ============ Cmd_ExecuteString A complete command line has been parsed, so try to execute it FIXME: this function is getting really messy... ============ */ void Cmd_ExecuteString (char *text) { cmd_function_t *cmd; cmd_alias_t *a; int key; static char buf[1024]; cbuf_t *inserttarget; #ifndef SERVERONLY char **s; #endif Cmd_ExpandString (text, buf); Cmd_TokenizeString (buf); // execute the command line if (!Cmd_Argc()) return; // no tokens inserttarget = &cbuf_main; #ifndef SERVERONLY if (cbuf_current == &cbuf_safe) inserttarget = &cbuf_safe; if (cbuf_current == &cbuf_svc) { if (CL_CheckServerCommand()) return; } #endif key = Com_HashKey (cmd_argv[0]); // check functions for (cmd=cmd_hash_array[key] ; cmd ; cmd=cmd->hash_next) { if (!Q_stricmp (cmd_argv[0], cmd->name)) { #ifndef SERVERONLY // special check for msg_trigger commands if (cbuf_current == &cbuf_safe) { for (s = safe_commands; *s; s++) { if (!Q_stricmp(cmd_argv[0], *s)) break; } if (!*s) { if (cl_warncmd.value || developer.value) Com_Printf ("\"%s\" cannot be used in message triggers\n", cmd_argv[0]); return; } } #endif if (cmd->function) cmd->function (); else Cmd_ForwardToServer (); return; } } // some bright guy decided to use "skill" as a mod command in Custom TF, sigh if (!strcmp(Cmd_Argv(0), "skill") && Cmd_Argc() == 1 && Cmd_FindAlias("skill")) goto checkaliases; // check cvars if (Cvar_Command()) return; // check alias checkaliases: for (a=cmd_alias_hash[key] ; a ; a=a->hash_next) { if (!Q_stricmp (cmd_argv[0], a->name)) { #ifndef SERVERONLY if (cbuf_current == &cbuf_svc) { Cbuf_AddText (a->value); Cbuf_AddText ("\n"); } else #endif { Cbuf_InsertTextEx (inserttarget, "\n"); // if the alias value is a command or cvar and // the alias is called with parameters, add them if (Cmd_Argc() > 1 && !strchr(a->value, ' ') && !strchr(a->value, '\t') && (Cvar_FindVar(a->value) || (Cmd_FindCommand(a->value) && a->value[0] != '+' && a->value[0] != '-'))) { Cbuf_InsertTextEx (inserttarget, Cmd_Args()); Cbuf_InsertTextEx (inserttarget, " "); } Cbuf_InsertTextEx (inserttarget, a->value); } return; } } if (Cmd_LegacyCommand()) return; if (!host_initialized && Cmd_Argc() > 1) { if (Cvar_CreateTempVar()) return; } #ifndef SERVERONLY if (cbuf_current != &cbuf_svc) #endif if (cl_warncmd.value || developer.value) Com_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0)); }