1 // ====================================================
2 // Shared code for server commands, written by Samual
3 // Last updated: December 17th, 2011
4 // ====================================================
6 string GetCommandPrefix(entity caller)
14 string GetCallerName(entity caller)
17 return caller.netname;
19 return ((autocvar_sv_adminnick != "") ? autocvar_sv_adminnick : autocvar_hostname);
22 entity GetFilteredEntity(string input)
24 entity tmp_player, selection;
27 if(substring(input, 0, 1) == "#")
28 tmp_number = stof(substring(input, 1, -1));
30 tmp_number = stof(input);
34 selection = edict_num(tmp_number);
38 FOR_EACH_CLIENT(tmp_player)
39 if (strdecolorize(tmp_player.netname) == strdecolorize(input))
40 selection = tmp_player;
46 // find a player which matches the input string, and return their entity number
47 float GetFilteredNumber(string input)
49 entity selection = GetFilteredEntity(input);
52 if(selection) { output = num_for_edict(selection); }
54 print(strcat("input: ", input, ", output: ", ftos(output), ",\n")); // todo remove after done debugging
58 // switch between sprint and print depending on whether the reciever is the server or a player
59 void print_to(entity to, string input)
62 sprint(to, strcat(input, "\n"));
68 // ===================================================
69 // Common commands used in both sv_cmd.qc and cmd.qc
70 // ===================================================
72 void CommonCommand_cvar_changes(float request, entity caller)
76 case CMD_REQUEST_COMMAND:
78 print_to(caller, cvar_changes);
79 return; // never fall through to usage
83 case CMD_REQUEST_USAGE:
85 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " cvar_changes"));
86 print_to(caller, " No arguments required.");
87 print_to(caller, "See also: ^2cvar_purechanges^7");
93 void CommonCommand_cvar_purechanges(float request, entity caller)
97 case CMD_REQUEST_COMMAND:
99 print_to(caller, cvar_purechanges);
100 return; // never fall through to usage
104 case CMD_REQUEST_USAGE:
106 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " cvar_purechanges"));
107 print_to(caller, " No arguments required.");
108 print_to(caller, "See also: ^2cvar_changes^7");
114 void CommonCommand_info(float request, entity caller, float argc) // todo: figure out how this works?
118 case CMD_REQUEST_COMMAND:
122 command = builtin_cvar_string(strcat("sv_info_", argv(1)));
124 wordwrap_sprint(command, 1111); // why 1111?
126 print_to(caller, "ERROR: unsupported info command");
128 return; // never fall through to usage
132 case CMD_REQUEST_USAGE:
134 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " info request"));
135 print_to(caller, " Where 'request' is the suffixed string appended onto the request for cvar.");
141 void CommonCommand_ladder(float request, entity caller)
145 case CMD_REQUEST_COMMAND:
147 print_to(caller, ladder_reply);
148 return; // never fall through to usage
152 case CMD_REQUEST_USAGE:
154 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " ladder"));
155 print_to(caller, " No arguments required.");
161 void CommonCommand_lsmaps(float request, entity caller)
165 case CMD_REQUEST_COMMAND:
167 print_to(caller, lsmaps_reply);
168 return; // never fall through to usage
172 case CMD_REQUEST_USAGE:
174 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " lsmaps"));
175 print_to(caller, " No arguments required.");
181 void CommonCommand_lsnewmaps(float request, entity caller)
185 case CMD_REQUEST_COMMAND:
187 print_to(caller, lsnewmaps_reply);
188 return; // never fall through to usage
192 case CMD_REQUEST_USAGE:
194 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " lsnewmaps"));
195 print_to(caller, " No arguments required.");
201 void CommonCommand_maplist(float request, entity caller)
205 case CMD_REQUEST_COMMAND:
207 print_to(caller, maplist_reply);
208 return; // never fall through to usage
212 case CMD_REQUEST_USAGE:
214 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " maplist"));
215 print_to(caller, " No arguments required.");
221 void GameCommand_rankings(float request) // this is OLD.... jeez.
225 case CMD_REQUEST_COMMAND:
227 strunzone(rankings_reply);
228 rankings_reply = strzone(getrankings());
229 print(rankings_reply);
234 case CMD_REQUEST_USAGE:
236 print("\nUsage:^3 sv_cmd rankings");
237 print(" No arguments required.");
243 void CommonCommand_rankings(float request, entity caller)
247 case CMD_REQUEST_COMMAND:
249 print_to(caller, rankings_reply);
250 return; // never fall through to usage
254 case CMD_REQUEST_USAGE:
256 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " rankings"));
257 print_to(caller, " No arguments required.");
263 void CommonCommand_records(float request, entity caller) // TODO: Isn't this flooding with the sprint messages? Old code, but perhaps bad?
267 case CMD_REQUEST_COMMAND:
271 for(i = 0; i < 10; ++i)
272 print_to(caller, records_reply[i]);
274 return; // never fall through to usage
278 case CMD_REQUEST_USAGE:
280 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " records"));
281 print_to(caller, " No arguments required.");
287 void CommonCommand_teamstatus(float request, entity caller)
291 case CMD_REQUEST_COMMAND:
293 Score_NicePrint(caller);
294 return; // never fall through to usage
298 case CMD_REQUEST_USAGE:
300 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " teamstatus"));
301 print_to(caller, " No arguments required.");
307 void CommonCommand_time(float request, entity caller)
311 case CMD_REQUEST_COMMAND:
313 print_to(caller, strcat("time = ", ftos(time), "\n"));
314 print_to(caller, strcat("frame start = ", ftos(gettime(GETTIME_FRAMESTART)), "\n"));
315 print_to(caller, strcat("realtime = ", ftos(gettime(GETTIME_REALTIME)), "\n"));
316 print_to(caller, strcat("hires = ", ftos(gettime(GETTIME_HIRES)), "\n"));
317 print_to(caller, strcat("uptime = ", ftos(gettime(GETTIME_UPTIME)), "\n"));
318 print_to(caller, strcat("localtime = ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); // todo: Why is strftime broken? is engine problem, I think.
319 print_to(caller, strcat("gmtime = ", strftime(FALSE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
324 case CMD_REQUEST_USAGE:
326 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " time"));
327 print_to(caller, " No arguments required.");
333 void CommonCommand_timein(float request, entity caller)
337 case CMD_REQUEST_COMMAND:
339 if(caller.flags & FL_CLIENT)
341 if(autocvar_sv_timeout)
344 return print_to(caller, "^7Error: There is no active timeout which could be aborted!");
345 if (caller != timeoutInitiator)
346 return print_to(caller, "^7Error: You may not abort the active timeout. Only the player who called it can do that!");
348 if (timeoutStatus == 1)
350 remainingTimeoutTime = timeoutStatus = 0;
351 timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately
352 bprint(strcat("^7The timeout was aborted by ", caller.netname, " !\n"));
354 else if (timeoutStatus == 2)
356 //only shorten the remainingTimeoutTime if it makes sense
357 if( remainingTimeoutTime > (autocvar_sv_timeout_resumetime + 1) )
359 bprint(strcat("^1Attention: ^7", caller.netname, " resumed the game! Prepare for battle!\n"));
360 remainingTimeoutTime = autocvar_sv_timeout_resumetime;
361 timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately
364 print_to(caller, "^7Error: Your resumegame call was discarded!");
368 return; // never fall through to usage
372 case CMD_REQUEST_USAGE:
374 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " timein"));
375 print_to(caller, " No arguments required.");
381 void CommonCommand_timeout(float request, entity caller) // DEAR GOD THIS COMMAND IS TERRIBLE.
385 case CMD_REQUEST_COMMAND:
387 if(caller.flags & FL_CLIENT)
389 if(autocvar_sv_timeout)
391 if(caller.classname == "player")
394 print_to(caller, "^7Error: you can not call a timeout while a vote is active!");
397 if (inWarmupStage && !g_warmup_allow_timeout)
398 return print_to(caller, "^7Error: You can not call a timeout in warmup-stage!");
399 if (time < game_starttime )
400 return print_to(caller, "^7Error: You can not call a timeout while the map is being restarted!");
402 if (timeoutStatus != 2) {
403 //if the map uses a timelimit make sure that timeout cannot be called right before the map ends
404 if (autocvar_timelimit) {
405 //a timelimit was used
407 myTl = autocvar_timelimit;
409 float lastPossibleTimeout;
410 lastPossibleTimeout = (myTl*60) - autocvar_sv_timeout_leadtime - 1;
412 if (lastPossibleTimeout < time - game_starttime)
413 return print_to(caller, "^7Error: It is too late to call a timeout now!");
417 //player may not call a timeout if he has no calls left
418 if (caller.allowedTimeouts < 1)
419 return print_to(caller, "^7Error: You already used all your timeout calls for this map!");
422 //now all required checks are passed
423 caller.allowedTimeouts -= 1;
424 bprint(caller.netname, " ^7called a timeout (", ftos(caller.allowedTimeouts), " timeouts left)!\n"); //write a bprint who started the timeout (and how many he has left)
425 remainingTimeoutTime = autocvar_sv_timeout_length;
426 remainingLeadTime = autocvar_sv_timeout_leadtime;
427 timeoutInitiator = caller;
428 if (timeoutStatus == 0) { //if another timeout was already active, don't change its status (which was 1 or 2) to 1, only change it to 1 if no timeout was active yet
430 //create the timeout indicator which centerprints the information to all players and takes care of pausing/unpausing
431 timeoutHandler = spawn();
432 timeoutHandler.think = timeoutHandler_Think;
434 timeoutHandler.nextthink = time; //always let the entity think asap
436 //inform all connected clients about the timeout call
437 Announce("timeoutcalled");
441 print_to(caller, "^7Error: only players can call a timeout!");
444 return; // never fall through to usage
448 case CMD_REQUEST_USAGE:
450 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " timeout"));
451 print_to(caller, " No arguments required.");
457 void CommonCommand_who(float request, entity caller)
461 case CMD_REQUEST_COMMAND:
463 float total_listed_players, tmp_hours, tmp_minutes, tmp_seconds;
465 //string tmp_player_name;
467 print_to(caller, strcat("List of client information", (autocvar_sv_status_privacy ? " (some data is hidden for privacy)" : string_null), ":"));
468 print_to(caller, sprintf(" %-4s %-20s %-5s %-3s %-9s %-16s %s", "ent", "nickname", "ping", "pl", "time", "ip", "crypto_id"));
470 FOR_EACH_CLIENT(tmp_player)
472 tmp_hours = tmp_minutes = tmp_seconds = 0;
474 tmp_seconds = floor(time - tmp_player.jointime);
475 tmp_minutes = floor(tmp_seconds / 60);
476 tmp_hours = floor(tmp_minutes / 60);
478 if(tmp_minutes) { tmp_seconds -= (tmp_minutes * 60); }
479 if(tmp_hours) { tmp_minutes -= (tmp_hours * 60); }
481 print_to(caller, sprintf(" %-4s %-20s %-5d %-3d %-9s %-16s %s",
482 strcat("#", ftos(num_for_edict(tmp_player))),
483 tmp_player.netname, //strcat(tmp_player_name, sprintf("%*s", (20 - strlen(strdecolorize(tmp_player_name))), "")),
484 tmp_player.ping, tmp_player.ping_packetloss,
485 sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds),
486 (autocvar_sv_status_privacy ? "hidden" : tmp_player.netaddress),
487 (autocvar_sv_status_privacy ? "hidden" : tmp_player.crypto_idfp)));
489 ++total_listed_players;
492 print_to(caller, strcat("Finished listing ", ftos(total_listed_players), " client(s)."));
494 return; // never fall through to usage
498 case CMD_REQUEST_USAGE:
500 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " who"));
501 print_to(caller, " No arguments required.");
507 /* use this when creating a new command, making sure to place it in alphabetical order.
508 void CommonCommand_(float request, entity caller)
512 case CMD_REQUEST_COMMAND:
515 return; // never fall through to usage
519 case CMD_REQUEST_USAGE:
521 print_to(caller, strcat("\nUsage:^3 ", GetCommandPrefix(caller), " "));
522 print_to(caller, " No arguments required.");