1 // ====================================================
2 // Shared code for server commands, written by Samual
3 // Last updated: December 13th, 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 // find a player which matches the input string, and return their entity number
23 float GetFilteredNumber(string input)
25 entity tmp_player, selection;
26 float output, matches;
28 // check and see if we can get a number from input like "#3" or "3"
29 if(substring(input, 0, 1) == "#")
30 output = stof(substring(input, 1, -1));
34 // if we can't, check and see if we can match the input to the netname of any player in the game
37 FOR_EACH_CLIENT(tmp_player)
38 if (strdecolorize(tmp_player.netname) == strdecolorize(input))
39 selection = tmp_player;
41 if (selection) { output = num_for_edict(selection); }
44 print(strcat("input: ", input, ", output: ", ftos(output), ",\n"));
48 // switch between sprint and print depending on whether the reciever is the server or a player
49 void print_to(entity to, string input)
52 sprint(to, strcat(input, "\n"));
58 // ===================================================
59 // Common commands used in both sv_cmd.qc and cmd.qc
60 // ===================================================
62 void CommonCommand_cvar_changes(float request)
66 case CMD_REQUEST_COMMAND:
68 print_to(self, cvar_changes);
69 return; // never fall through to usage
73 case CMD_REQUEST_USAGE:
75 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " cvar_changes"));
76 print_to(self, " No arguments required.");
77 print_to(self, "See also: ^2cvar_purechanges^7");
83 void CommonCommand_cvar_purechanges(float request)
87 case CMD_REQUEST_COMMAND:
89 print_to(self, cvar_purechanges);
90 return; // never fall through to usage
94 case CMD_REQUEST_USAGE:
96 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " cvar_purechanges"));
97 print_to(self, " No arguments required.");
98 print_to(self, "See also: ^2cvar_changes^7");
104 void CommonCommand_info(float request, float argc) // todo: figure out how this works?
108 case CMD_REQUEST_COMMAND:
112 command = builtin_cvar_string(strcat("sv_info_", argv(1)));
114 wordwrap_sprint(command, 1111); // why 1111?
116 print_to(self, "ERROR: unsupported info command");
118 return; // never fall through to usage
122 case CMD_REQUEST_USAGE:
124 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " info request"));
125 print_to(self, " Where 'request' is the suffixed string appended onto the request for cvar.");
131 void CommonCommand_ladder(float request)
135 case CMD_REQUEST_COMMAND:
137 print_to(self, ladder_reply);
138 return; // never fall through to usage
142 case CMD_REQUEST_USAGE:
144 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " ladder"));
145 print_to(self, " No arguments required.");
151 void CommonCommand_lsmaps(float request)
155 case CMD_REQUEST_COMMAND:
157 print_to(self, lsmaps_reply);
158 return; // never fall through to usage
162 case CMD_REQUEST_USAGE:
164 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " lsmaps"));
165 print_to(self, " No arguments required.");
171 void CommonCommand_lsnewmaps(float request)
175 case CMD_REQUEST_COMMAND:
177 print_to(self, lsnewmaps_reply);
178 return; // never fall through to usage
182 case CMD_REQUEST_USAGE:
184 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " lsnewmaps"));
185 print_to(self, " No arguments required.");
191 void CommonCommand_maplist(float request)
195 case CMD_REQUEST_COMMAND:
197 print_to(self, maplist_reply);
198 return; // never fall through to usage
202 case CMD_REQUEST_USAGE:
204 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " maplist"));
205 print_to(self, " No arguments required.");
211 void GameCommand_rankings(float request) // this is OLD.... jeez.
215 case CMD_REQUEST_COMMAND:
217 strunzone(rankings_reply);
218 rankings_reply = strzone(getrankings());
219 print(rankings_reply);
224 case CMD_REQUEST_USAGE:
226 print("\nUsage:^3 sv_cmd rankings");
227 print(" No arguments required.");
233 void CommonCommand_rankings(float request)
237 case CMD_REQUEST_COMMAND:
239 print_to(self, rankings_reply);
240 return; // never fall through to usage
244 case CMD_REQUEST_USAGE:
246 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " rankings"));
247 print_to(self, " No arguments required.");
253 void CommonCommand_records(float request) // TODO: Isn't this flooding with the sprint messages? Old code, but perhaps bad?
257 case CMD_REQUEST_COMMAND:
261 for(i = 0; i < 10; ++i)
262 print_to(self, records_reply[i]);
264 return; // never fall through to usage
268 case CMD_REQUEST_USAGE:
270 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " records"));
271 print_to(self, " No arguments required.");
277 void CommonCommand_teamstatus(float request)
281 case CMD_REQUEST_COMMAND:
283 Score_NicePrint(self);
284 return; // never fall through to usage
288 case CMD_REQUEST_USAGE:
290 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " teamstatus"));
291 print_to(self, " No arguments required.");
297 void CommonCommand_time(float request)
301 case CMD_REQUEST_COMMAND:
303 print_to(self, strcat("time = ", ftos(time), "\n"));
304 print_to(self, strcat("frame start = ", ftos(gettime(GETTIME_FRAMESTART)), "\n"));
305 print_to(self, strcat("realtime = ", ftos(gettime(GETTIME_REALTIME)), "\n"));
306 print_to(self, strcat("hires = ", ftos(gettime(GETTIME_HIRES)), "\n"));
307 print_to(self, strcat("uptime = ", ftos(gettime(GETTIME_UPTIME)), "\n"));
308 print_to(self, strcat("localtime = ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); // todo: Why is strftime broken? is engine problem, I think.
309 print_to(self, strcat("gmtime = ", strftime(FALSE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
314 case CMD_REQUEST_USAGE:
316 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " time"));
317 print_to(self, " No arguments required.");
323 void CommonCommand_timein(float request)
327 case CMD_REQUEST_COMMAND:
329 if(self.flags & FL_CLIENT)
331 if(autocvar_sv_timeout)
334 return print_to(self, "^7Error: There is no active timeout which could be aborted!");
335 if (self != timeoutInitiator)
336 return print_to(self, "^7Error: You may not abort the active timeout. Only the player who called it can do that!");
338 if (timeoutStatus == 1)
340 remainingTimeoutTime = timeoutStatus = 0;
341 timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately
342 bprint(strcat("^7The timeout was aborted by ", self.netname, " !\n"));
344 else if (timeoutStatus == 2)
346 //only shorten the remainingTimeoutTime if it makes sense
347 if( remainingTimeoutTime > (autocvar_sv_timeout_resumetime + 1) )
349 bprint(strcat("^1Attention: ^7", self.netname, " resumed the game! Prepare for battle!\n"));
350 remainingTimeoutTime = autocvar_sv_timeout_resumetime;
351 timeoutHandler.nextthink = time; //timeoutHandler has to take care of it immediately
354 print_to(self, "^7Error: Your resumegame call was discarded!");
358 return; // never fall through to usage
362 case CMD_REQUEST_USAGE:
364 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " timein"));
365 print_to(self, " No arguments required.");
371 void CommonCommand_timeout(float request) // DEAR GOD THIS COMMAND IS TERRIBLE.
375 case CMD_REQUEST_COMMAND:
377 if(self.flags & FL_CLIENT)
379 if(autocvar_sv_timeout)
381 if(self.classname == "player")
384 print_to(self, "^7Error: you can not call a timeout while a vote is active!");
387 if (inWarmupStage && !g_warmup_allow_timeout)
388 return print_to(self, "^7Error: You can not call a timeout in warmup-stage!");
389 if (time < game_starttime )
390 return print_to(self, "^7Error: You can not call a timeout while the map is being restarted!");
392 if (timeoutStatus != 2) {
393 //if the map uses a timelimit make sure that timeout cannot be called right before the map ends
394 if (autocvar_timelimit) {
395 //a timelimit was used
397 myTl = autocvar_timelimit;
399 float lastPossibleTimeout;
400 lastPossibleTimeout = (myTl*60) - autocvar_sv_timeout_leadtime - 1;
402 if (lastPossibleTimeout < time - game_starttime)
403 return print_to(self, "^7Error: It is too late to call a timeout now!");
407 //player may not call a timeout if he has no calls left
408 if (self.allowedTimeouts < 1)
409 return print_to(self, "^7Error: You already used all your timeout calls for this map!");
412 //now all required checks are passed
413 self.allowedTimeouts -= 1;
414 bprint(self.netname, " ^7called a timeout (", ftos(self.allowedTimeouts), " timeouts left)!\n"); //write a bprint who started the timeout (and how many he has left)
415 remainingTimeoutTime = autocvar_sv_timeout_length;
416 remainingLeadTime = autocvar_sv_timeout_leadtime;
417 timeoutInitiator = self;
418 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
420 //create the timeout indicator which centerprints the information to all players and takes care of pausing/unpausing
421 timeoutHandler = spawn();
422 timeoutHandler.think = timeoutHandler_Think;
424 timeoutHandler.nextthink = time; //always let the entity think asap
426 //inform all connected clients about the timeout call
427 Announce("timeoutcalled");
431 print_to(self, "^7Error: only players can call a timeout!");
434 return; // never fall through to usage
438 case CMD_REQUEST_USAGE:
440 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " timeout"));
441 print_to(self, " No arguments required.");
447 void CommonCommand_who(float request)
451 case CMD_REQUEST_COMMAND:
453 float total_listed_players, tmp_hours, tmp_minutes, tmp_seconds;
455 //string tmp_player_name;
457 print_to(self, strcat("List of client information", (autocvar_sv_status_privacy ? " (some data is hidden for privacy)" : string_null), ":\n"));
458 print_to(self, sprintf(" %-4s %-20s %-5s %-3s %-9s %-16s %s\n", "ent", "nickname", "ping", "pl", "time", "ip", "crypto_id"));
460 FOR_EACH_CLIENT(tmp_player)
462 //tmp_player_name = strlimitedlen(tmp_player.netname, "...", TRUE, 20);
464 tmp_hours = tmp_minutes = tmp_seconds = 0;
466 tmp_seconds = (time - tmp_player.jointime);
467 tmp_minutes = (tmp_seconds / 60);
471 tmp_seconds -= (tmp_minutes * 60);
472 tmp_hours = (tmp_minutes / 60);
474 if(tmp_hours) { tmp_minutes -= (tmp_hours * 60); }
477 print_to(self, sprintf(" %-4s %-20s %-5d %-3d %-9s %-16s %s\n",
478 strcat("#", ftos(num_for_edict(tmp_player))),
479 tmp_player.netname, //strcat(tmp_player_name, sprintf("%*s", (20 - strlen(strdecolorize(tmp_player_name))), "")),
480 tmp_player.ping, tmp_player.ping_packetloss,
481 sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds),
482 (autocvar_sv_status_privacy ? "hidden" : tmp_player.netaddress),
483 (autocvar_sv_status_privacy ? "hidden" : tmp_player.crypto_idfp)));
485 ++total_listed_players;
488 print_to(self, strcat("Finished listing ", ftos(total_listed_players), " client(s). \n"));
490 return; // never fall through to usage
494 case CMD_REQUEST_USAGE:
496 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " who"));
497 print_to(self, " No arguments required.");
503 /* use this when creating a new command, making sure to place it in alphabetical order.
504 void CommonCommand_(float request)
508 case CMD_REQUEST_COMMAND:
511 return; // never fall through to usage
515 case CMD_REQUEST_USAGE:
517 print_to(self, strcat("\nUsage:^3 ", GetCommandPrefix(self), " "));
518 print_to(self, " No arguments required.");