DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
sv_ccmds.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3Copyright (C) 2020-2024 DarkPlaces Contributors
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20*/
21
22#include "quakedef.h"
23#include "utf8lib.h"
24#include "server.h"
25#include "sv_demo.h"
26
28cvar_t sv_cheats = {CF_SERVER | CF_NOTIFY, "sv_cheats", "0", "enables cheat commands in any game, and cheat impulses in dpmod"};
29cvar_t sv_adminnick = {CF_SERVER | CF_ARCHIVE, "sv_adminnick", "", "nick name to use for admin messages instead of host name"};
30cvar_t sv_status_privacy = {CF_SERVER | CF_ARCHIVE, "sv_status_privacy", "0", "do not show IP addresses in 'status' replies to clients"};
31cvar_t sv_status_show_qcstatus = {CF_SERVER | CF_ARCHIVE, "sv_status_show_qcstatus", "0", "show the 'qcstatus' field in status replies, not the 'frags' field. Turn this on if your mod uses this field, and the 'frags' field on the other hand has no meaningful value."};
32cvar_t sv_namechangetimer = {CF_SERVER | CF_ARCHIVE, "sv_namechangetimer", "5", "how often to allow name changes, in seconds (prevents people from using animated names and other tricks"};
33
34/*
35===============================================================================
36
37SERVER TRANSITIONS
38
39===============================================================================
40*/
41
42/*
43======================
44SV_Map_f
45
46handle a
47map <servername>
48command from the console. Active clients are kicked off.
49======================
50*/
52{
53 if (Cmd_Argc(cmd) != 2)
54 {
55 Con_Print("map <levelname> : start a new game (kicks off all players)\n");
56 return;
57 }
58
59 // GAME_DELUXEQUAKE - clear warpmark (used by QC)
61 Cvar_Set(&cvars_all, "warpmark", "");
62
64 host.hook.Disconnect(false, NULL);
65
67
69 {
71 if (svs.clients)
74 }
75
78
79 svs.serverflags = 0; // haven't completed an episode yet
81
84}
85
86/*
87==================
88SV_Changelevel_f
89
90Goes to a new map, taking all clients along
91==================
92*/
94{
95 if (Cmd_Argc(cmd) != 2)
96 {
97 Con_Print("changelevel <levelname> : continue game on a new level\n");
98 return;
99 }
100
101 if (!sv.active)
102 {
103 SV_Map_f(cmd);
104 return;
105 }
106
109
112
115}
116
117/*
118==================
119SV_Restart_f
120
121Restarts the current server for a dead player
122==================
123*/
125{
126 if (Cmd_Argc(cmd) != 1)
127 {
128 Con_Print("restart : restart current level\n");
129 return;
130 }
131 if (!sv.active)
132 {
133 Con_Print("Only the server may restart\n");
134 return;
135 }
136
139
141
144}
145
146//===========================================================================
147
148// Disable cheats if sv_cheats is turned off
149static void SV_DisableCheats_c(cvar_t *var)
150{
151 prvm_prog_t *prog = SVVM_prog;
152 int i;
153
154 if (prog->loaded && var->value == 0)
155 {
156 for (i = 0; i < svs.maxclients; ++i)
157 {
158 if (((int)PRVM_serveredictfloat(svs.clients[i].edict, flags) & FL_GODMODE))
160 if (((int)PRVM_serveredictfloat(svs.clients[i].edict, flags) & FL_NOTARGET))
164 {
165 noclip_anglehack = false;
167 }
168 }
169 }
170}
171
172/*
173==================
174SV_God_f
175
176Sets client to godmode
177==================
178*/
180{
181 prvm_prog_t *prog = SVVM_prog;
182
185 SV_ClientPrint("godmode OFF\n");
186 else
187 SV_ClientPrint("godmode ON\n");
188}
189
191
193{
194 prvm_prog_t *prog = SVVM_prog;
195
197 {
198 noclip_anglehack = true;
200 SV_ClientPrint("noclip ON\n");
201 }
202 else
203 {
204 noclip_anglehack = false;
206 SV_ClientPrint("noclip OFF\n");
207 }
208}
209
210/*
211==================
212SV_Give_f
213==================
214*/
216{
217 prvm_prog_t *prog = SVVM_prog;
218 const char *t;
219 int v;
220 int player_items;
221
222 t = Cmd_Argv(cmd, 1);
223 v = atoi (Cmd_Argv(cmd, 2));
224
225 switch (t[0])
226 {
227 case '0':
228 case '1':
229 case '2':
230 case '3':
231 case '4':
232 case '5':
233 case '6':
234 case '7':
235 case '8':
236 case '9':
237 // MED 01/04/97 added hipnotic give stuff
239 {
240 if (t[0] == '6')
241 {
242 if (t[1] == 'a')
244 else
246 }
247 else if (t[0] == '9')
249 else if (t[0] == '0')
251 else if (t[0] >= '2')
253 }
254 else
255 {
256 if (t[0] >= '2')
258 }
259 break;
260
261 case 's':
262 if (gamemode == GAME_ROGUE)
263 PRVM_serveredictfloat(host_client->edict, ammo_shells1) = v;
264
266 break;
267 case 'n':
268 if (gamemode == GAME_ROGUE)
269 {
270 PRVM_serveredictfloat(host_client->edict, ammo_nails1) = v;
273 }
274 else
275 {
277 }
278 break;
279 case 'l':
280 if (gamemode == GAME_ROGUE)
281 {
282 PRVM_serveredictfloat(host_client->edict, ammo_lava_nails) = v;
285 }
286 break;
287 case 'r':
288 if (gamemode == GAME_ROGUE)
289 {
290 PRVM_serveredictfloat(host_client->edict, ammo_rockets1) = v;
293 }
294 else
295 {
297 }
298 break;
299 case 'm':
300 if (gamemode == GAME_ROGUE)
301 {
302 PRVM_serveredictfloat(host_client->edict, ammo_multi_rockets) = v;
305 }
306 break;
307 case 'h':
309 break;
310 case 'c':
311 if (gamemode == GAME_ROGUE)
312 {
313 PRVM_serveredictfloat(host_client->edict, ammo_cells1) = v;
316 }
317 else
318 {
320 }
321 break;
322 case 'p':
323 if (gamemode == GAME_ROGUE)
324 {
325 PRVM_serveredictfloat(host_client->edict, ammo_plasma) = v;
328 }
329 break;
330 case 'a':
331 //
332 // Set the player armour value to the number specified and then adjust the armour type/colour based on the value
333 //
336
337 // Remove whichever armour item the player currently has
338 if (gamemode == GAME_ROGUE)
339 player_items &= ~(RIT_ARMOR1 | RIT_ARMOR2 | RIT_ARMOR3);
340 else
341 player_items &= ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3);
342
343 if (v > 150)
344 {
345 // Give red armour
347 if (gamemode == GAME_ROGUE)
348 player_items |= RIT_ARMOR3;
349 else
350 player_items |= IT_ARMOR3;
351 }
352 else if (v > 100)
353 {
354 // Give yellow armour
356 if (gamemode == GAME_ROGUE)
357 player_items |= RIT_ARMOR2;
358 else
359 player_items |= IT_ARMOR2;
360 }
361 else if (v >= 0)
362 {
363 // Give green armour
365 if (gamemode == GAME_ROGUE)
366 player_items |= RIT_ARMOR1;
367 else
368 player_items |= IT_ARMOR1;
369 }
370
372 break;
373 }
374}
375
376/*
377==================
378SV_Fly_f
379
380Sets client to flymode
381==================
382*/
384{
385 prvm_prog_t *prog = SVVM_prog;
386
388 {
390 SV_ClientPrint("flymode ON\n");
391 }
392 else
393 {
395 SV_ClientPrint("flymode OFF\n");
396 }
397}
398
400{
401 prvm_prog_t *prog = SVVM_prog;
402
405 SV_ClientPrint("notarget OFF\n");
406 else
407 SV_ClientPrint("notarget ON\n");
408}
409
410/*
411==================
412SV_Kill_f
413==================
414*/
416{
417 prvm_prog_t *prog = SVVM_prog;
419 {
420 SV_ClientPrint("Can't suicide -- already dead!\n");
421 return;
422 }
423
426 prog->ExecuteProgram(prog, PRVM_serverfunction(ClientKill), "QC function ClientKill is missing");
427}
428
429/*
430==================
431SV_Pause_f
432==================
433*/
435{
436 void (*print) (const char *fmt, ...);
437 if (cmd->source == src_local)
439 else
441
443 {
444 print("Pause not allowed.\n");
445 return;
446 }
447
448 sv.paused ^= 1;
449 if (cmd->source != src_local)
450 SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
451 else if(*(sv_adminnick.string))
452 SV_BroadcastPrintf("%s %spaused the game\n", sv_adminnick.string, sv.paused ? "" : "un");
453 else
454 SV_BroadcastPrintf("%s %spaused the game\n", hostname.string, sv.paused ? "" : "un");
455 // send notification to all clients
458}
459
460static void SV_Say(cmd_state_t *cmd, qbool teamonly)
461{
462 prvm_prog_t *prog = SVVM_prog;
463 client_t *save;
464 int j, quoted;
465 const char *p1;
466 char *p2;
467 // LadyHavoc: long say messages
468 char text[1024];
469 qbool fromServer = false;
470
471 if (cmd->source == src_local)
472 {
473 fromServer = true;
474 teamonly = false;
475 }
476
477 if (Cmd_Argc (cmd) < 2)
478 return;
479
480 if (!teamplay.integer)
481 teamonly = false;
482
483 p1 = Cmd_Args(cmd);
484 quoted = false;
485 if (*p1 == '\"')
486 {
487 quoted = true;
488 p1++;
489 }
490 // note this uses the chat prefix \001
491 if (!fromServer && !teamonly)
492 dpsnprintf (text, sizeof(text), "\001%s: %s", host_client->name, p1);
493 else if (!fromServer && teamonly)
494 dpsnprintf (text, sizeof(text), "\001(%s): %s", host_client->name, p1);
495 else if(*(sv_adminnick.string))
496 dpsnprintf (text, sizeof(text), "\001<%s> %s", sv_adminnick.string, p1);
497 else
498 dpsnprintf (text, sizeof(text), "\001<%s> %s", hostname.string, p1);
499 p2 = text + strlen(text);
500 while ((const char *)p2 > (const char *)text && (p2[-1] == '\r' || p2[-1] == '\n' || (p2[-1] == '\"' && quoted)))
501 {
502 if (p2[-1] == '\"' && quoted)
503 quoted = false;
504 p2[-1] = 0;
505 p2--;
506 }
507 dp_strlcat(text, "\n", sizeof(text));
508
509 // note: save is not a valid edict if fromServer is true
510 save = host_client;
511 for (j = 0, host_client = svs.clients;j < svs.maxclients;j++, host_client++)
513 SV_ClientPrint(text);
514 host_client = save;
515
517 Con_Print(&text[1]);
518}
519
521{
522 SV_Say(cmd, false);
523}
524
526{
527 SV_Say(cmd, true);
528}
529
531{
532 const char *playername_start = NULL;
533 size_t playername_length = 0;
534 int playernumber = 0;
535 client_t *save;
536 int j;
537 const char *p1, *p2;
538 char text[MAX_INPUTLINE]; // LadyHavoc: FIXME: temporary buffer overflow fix (was 64)
539 qbool fromServer = false;
540
541 if (cmd->source == src_local)
542 fromServer = true;
543
544 if (Cmd_Argc (cmd) < 2)
545 return;
546
547 // note this uses the chat prefix \001
548 if (!fromServer)
549 dpsnprintf (text, sizeof(text), "\001%s tells you: ", host_client->name);
550 else if(*(sv_adminnick.string))
551 dpsnprintf (text, sizeof(text), "\001<%s tells you> ", sv_adminnick.string);
552 else
553 dpsnprintf (text, sizeof(text), "\001<%s tells you> ", hostname.string);
554
555 p1 = Cmd_Args(cmd);
556 p2 = p1 + strlen(p1);
557 // remove the target name
558 while (p1 < p2 && *p1 == ' ')
559 p1++;
560 if(*p1 == '#')
561 {
562 ++p1;
563 while (p1 < p2 && *p1 == ' ')
564 p1++;
565 while (p1 < p2 && isdigit(*p1))
566 {
567 playernumber = playernumber * 10 + (*p1 - '0');
568 p1++;
569 }
570 --playernumber;
571 }
572 else if(*p1 == '"')
573 {
574 ++p1;
575 playername_start = p1;
576 while (p1 < p2 && *p1 != '"')
577 p1++;
578 playername_length = p1 - playername_start;
579 if(p1 < p2)
580 p1++;
581 }
582 else
583 {
584 playername_start = p1;
585 while (p1 < p2 && *p1 != ' ')
586 p1++;
587 playername_length = p1 - playername_start;
588 }
589 while (p1 < p2 && *p1 == ' ')
590 p1++;
591 if(playername_start)
592 {
593 // set playernumber to the right client
594 char namebuf[128];
595 if(playername_length >= sizeof(namebuf))
596 {
597 if (fromServer)
598 Con_Print("Host_Tell: too long player name/ID\n");
599 else
600 SV_ClientPrint("Host_Tell: too long player name/ID\n");
601 return;
602 }
603 memcpy(namebuf, playername_start, playername_length);
604 namebuf[playername_length] = 0;
605 for (playernumber = 0; playernumber < svs.maxclients; playernumber++)
606 {
607 if (!svs.clients[playernumber].active)
608 continue;
609 if (strcasecmp(svs.clients[playernumber].name, namebuf) == 0)
610 break;
611 }
612 }
613 if(playernumber < 0 || playernumber >= svs.maxclients || !(svs.clients[playernumber].active))
614 {
615 if (fromServer)
616 Con_Print("Host_Tell: invalid player name/ID\n");
617 else
618 SV_ClientPrint("Host_Tell: invalid player name/ID\n");
619 return;
620 }
621 // remove trailing newlines
622 while (p2 > p1 && (p2[-1] == '\n' || p2[-1] == '\r'))
623 p2--;
624 // remove quotes if present
625 if (*p1 == '"')
626 {
627 p1++;
628 if (p2[-1] == '"')
629 p2--;
630 else if (fromServer)
631 Con_Print("Host_Tell: missing end quote\n");
632 else
633 SV_ClientPrint("Host_Tell: missing end quote\n");
634 }
635 while (p2 > p1 && (p2[-1] == '\n' || p2[-1] == '\r'))
636 p2--;
637 if(p1 == p2)
638 return; // empty say
639 for (j = (int)strlen(text);j < (int)(sizeof(text) - 2) && p1 < p2;)
640 text[j++] = *p1++;
641 text[j++] = '\n';
642 text[j++] = 0;
643
644 save = host_client;
645 host_client = svs.clients + playernumber;
646 SV_ClientPrint(text);
647 host_client = save;
648}
649
650/*
651==================
652SV_Ping_f
653
654==================
655*/
657{
658 int i;
659 client_t *client;
660 void (*print) (const char *fmt, ...);
661
662 if (cmd->source == src_local)
664 else
666
667 if (!sv.active)
668 return;
669
670 print("Client ping times:\n");
671 for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
672 {
673 if (!client->active)
674 continue;
675 print("%4i %s\n", bound(0, (int)floor(client->ping*1000+0.5), 9999), client->name);
676 }
677}
678
679/*
680====================
681SV_Pings_f
682
683Send back ping and packet loss update for all current players to this player
684====================
685*/
687{
688 int i, j, ping, packetloss, movementloss;
689 char temp[128];
690
692 return;
693
695 {
698 }
699 for (i = 0;i < svs.maxclients;i++)
700 {
701 packetloss = 0;
702 movementloss = 0;
703 if (svs.clients[i].netconnection)
704 {
705 for (j = 0;j < NETGRAPH_PACKETS;j++)
706 if (svs.clients[i].netconnection->incoming_netgraph[j].unreliablebytes == NETGRAPH_LOSTPACKET)
707 packetloss++;
708 for (j = 0;j < NETGRAPH_PACKETS;j++)
709 if (svs.clients[i].movement_count[j] < 0)
710 movementloss++;
711 }
712 packetloss = (packetloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
713 movementloss = (movementloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
714 ping = (int)floor(svs.clients[i].ping*1000+0.5);
715 ping = bound(0, ping, 9999);
717 {
718 // send qw_svc_updateping and qw_svc_updatepl messages
723 }
724 else
725 {
726 // write the string into the packet as multiple unterminated strings to avoid needing a local buffer
727 if(movementloss)
728 dpsnprintf(temp, sizeof(temp), " %d %d,%d", ping, packetloss, movementloss);
729 else
730 dpsnprintf(temp, sizeof(temp), " %d %d", ping, packetloss);
732 }
733 }
736}
737
738/*
739==================
740SV_Status_f
741==================
742*/
744{
745 prvm_prog_t *prog = SVVM_prog;
746 char qcstatus[256];
747 client_t *client;
748 int seconds = 0, minutes = 0, hours = 0, i, j, k, in, players, ping = 0, packetloss = 0;
749 void (*print) (const char *fmt, ...);
750 char ip[48]; // can contain a full length v6 address with [] and a port
751 int frags;
752 char vabuf[1024];
753
754 if (cmd->source == src_local)
756 else
758
759 if (!sv.active)
760 return;
761
762 in = 0;
763 if (Cmd_Argc(cmd) == 2)
764 {
765 if (strcmp(Cmd_Argv(cmd, 1), "1") == 0)
766 in = 1;
767 else if (strcmp(Cmd_Argv(cmd, 1), "2") == 0)
768 in = 2;
769 }
770
771 for (players = 0, i = 0;i < svs.maxclients;i++)
772 if (svs.clients[i].active)
773 players++;
774
775 print ("host: %s\n", Cvar_VariableString (&cvars_all, "hostname", CF_SERVER));
776 print ("version: %s\n", engineversion);
778 print ("map: %s\n", sv.worldbasename);
779 print ("timing: %s\n", SV_TimingReport(vabuf, sizeof(vabuf)));
780 print ("players: %i active (%i max)\n\n", players, svs.maxclients);
781
782 if (in == 1)
783 print ("^2IP %%pl ping time frags no name\n");
784 else if (in == 2)
785 print ("^5IP no name\n");
786
787 for (i = 0, k = 0, client = svs.clients;i < svs.maxclients;i++, client++)
788 {
789 if (!client->active)
790 continue;
791
792 ++k;
793
794 if (in == 0 || in == 1)
795 {
796 seconds = (int)(host.realtime - client->connecttime);
797 minutes = seconds / 60;
798 if (minutes)
799 {
800 seconds -= (minutes * 60);
801 hours = minutes / 60;
802 if (hours)
803 minutes -= (hours * 60);
804 }
805 else
806 hours = 0;
807
808 packetloss = 0;
809 if (client->netconnection)
810 for (j = 0;j < NETGRAPH_PACKETS;j++)
812 packetloss++;
813 packetloss = (packetloss * 100 + NETGRAPH_PACKETS - 1) / NETGRAPH_PACKETS;
814 ping = bound(0, (int)floor(client->ping*1000+0.5), 9999);
815 }
816
818 dp_strlcpy(ip, client->netconnection ? "hidden" : "botclient", 48);
819 else
820 dp_strlcpy(ip, (client->netconnection && *client->netconnection->address) ? client->netconnection->address : "botclient", 48);
821
822 frags = client->frags;
823
825 {
826 prvm_edict_t *ed = PRVM_EDICT_NUM(i + 1);
827 const char *str = PRVM_GetString(prog, PRVM_serveredictstring(ed, clientstatus));
828 if(str && *str)
829 {
830 char *p;
831 const char *q;
832 p = qcstatus;
833 for(q = str; *q && p != qcstatus + sizeof(qcstatus) - 1; ++q)
834 if(*q != '\\' && *q != '"' && !ISWHITESPACE(*q))
835 *p++ = *q;
836 *p = 0;
837 if(*qcstatus)
838 frags = atoi(qcstatus);
839 }
840 }
841
842 if (in == 0) // default layout
843 {
844 if (sv.protocol == PROTOCOL_QUAKE && svs.maxclients <= 99)
845 {
846 // LadyHavoc: this is very touchy because we must maintain ProQuake compatible status output
847 print ("#%-2u %-16.16s %3i %2i:%02i:%02i\n", i+1, client->name, frags, hours, minutes, seconds);
848 print (" %s\n", ip);
849 }
850 else
851 {
852 // LadyHavoc: no real restrictions here, not a ProQuake-compatible protocol anyway...
853 print ("#%-3u %-16.16s %4i %2i:%02i:%02i\n", i+1, client->name, frags, hours, minutes, seconds);
854 print (" %s\n", ip);
855 }
856 }
857 else if (in == 1) // extended layout
858 {
859 print ("%s%-47s %2i %4i %2i:%02i:%02i %4i #%-3u ^7%s\n", k%2 ? "^3" : "^7", ip, packetloss, ping, hours, minutes, seconds, frags, i+1, client->name);
860 }
861 else if (in == 2) // reduced layout
862 {
863 print ("%s%-47s #%-3u ^7%s\n", k%2 ? "^3" : "^7", ip, i+1, client->name);
864 }
865 }
866}
867
884
885/*
886======================
887SV_Name_f
888======================
889*/
891{
892 int i, j;
893 qbool valid_colors;
894 const char *newNameSource;
895 char newName[sizeof(host_client->name)];
896
897 if (Cmd_Argc (cmd) == 1)
898 return;
899
900 if (Cmd_Argc (cmd) == 2)
901 newNameSource = Cmd_Argv(cmd, 1);
902 else
903 newNameSource = Cmd_Args(cmd);
904
905 dp_strlcpy(newName, newNameSource, sizeof(newName));
906
907 if (cmd->source == src_local)
908 return;
909
910 if (host.realtime < host_client->nametime && strcmp(newName, host_client->name))
911 {
912 SV_ClientPrintf("You can't change name more than once every %.1f seconds!\n", max(0.0f, sv_namechangetimer.value));
913 return;
914 }
915
917
918 // point the string back at updateclient->name to keep it safe
919 dp_strlcpy (host_client->name, newName, sizeof (host_client->name));
920
921 for (i = 0, j = 0;host_client->name[i];i++)
922 if (host_client->name[i] != '\r' && host_client->name[i] != '\n')
924 host_client->name[j] = 0;
925
926 if(host_client->name[0] == 1 || host_client->name[0] == 2)
927 // may interfere with chat area, and will needlessly beep; so let's add a ^7
928 {
929 memmove(host_client->name + 2, host_client->name, sizeof(host_client->name) - 2);
930 host_client->name[sizeof(host_client->name) - 1] = 0;
933 }
934
935 u8_COM_StringLengthNoColors(host_client->name, 0, &valid_colors);
936 if(!valid_colors) // NOTE: this also proves the string is not empty, as "" is a valid colored string
937 {
938 size_t l;
939 l = strlen(host_client->name);
940 if(l < sizeof(host_client->name) - 1)
941 {
942 // duplicate the color tag to escape it
944 host_client->name[i+1] = 0;
945 //Con_DPrintf("abuse detected, adding another trailing color tag\n");
946 }
947 else
948 {
949 // remove the last character to fix the color code
950 host_client->name[l-1] = 0;
951 //Con_DPrintf("abuse detected, removing a trailing color tag\n");
952 }
953 }
954
955 // find the last color tag offset and decide if we need to add a reset tag
956 for (i = 0, j = -1;host_client->name[i];i++)
957 {
959 {
960 if (host_client->name[i+1] >= '0' && host_client->name[i+1] <= '9')
961 {
962 j = i;
963 // if this happens to be a reset tag then we don't need one
964 if (host_client->name[i+1] == '0' + STRING_COLOR_DEFAULT)
965 j = -1;
966 i++;
967 continue;
968 }
969 if (host_client->name[i+1] == STRING_COLOR_RGB_TAG_CHAR && isxdigit(host_client->name[i+2]) && isxdigit(host_client->name[i+3]) && isxdigit(host_client->name[i+4]))
970 {
971 j = i;
972 i += 4;
973 continue;
974 }
976 {
977 i++;
978 continue;
979 }
980 }
981 }
982 // does not end in the default color string, so add it
983 if (j >= 0 && strlen(host_client->name) < sizeof(host_client->name) - 2)
985
987}
988
990{
991 int rate;
992
993 rate = atoi(Cmd_Argv(cmd, 1));
994
995 if (cmd->source == src_local)
996 return;
997
998 host_client->rate = rate;
999}
1000
1002{
1003 int rate_burstsize;
1004
1005 if (Cmd_Argc(cmd) != 2)
1006 return;
1007
1008 rate_burstsize = atoi(Cmd_Argv(cmd, 1));
1009
1010 host_client->rate_burstsize = rate_burstsize;
1011}
1012
1014{
1015 prvm_prog_t *prog = SVVM_prog;
1016
1017 int top, bottom, playercolor;
1018
1019 top = atoi(Cmd_Argv(cmd, 1));
1020 bottom = atoi(Cmd_Argv(cmd, 2));
1021
1022 top &= 15;
1023 bottom &= 15;
1024
1025 playercolor = top*16 + bottom;
1026
1027 if (host_client->edict && PRVM_serverfunction(SV_ChangeTeam))
1028 {
1029 Con_DPrint("Calling SV_ChangeTeam\n");
1030 prog->globals.fp[OFS_PARM0] = playercolor;
1033 prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
1034 }
1035 else
1036 {
1037 if (host_client->edict)
1038 {
1041 }
1042 host_client->colors = playercolor;
1044 {
1046 // send notification to all clients
1050 }
1051 }
1052}
1053
1054/*
1055==================
1056SV_Kick_f
1057
1058Kicks a user off of the server
1059==================
1060*/
1062{
1063 const char *who;
1064 const char *message = NULL;
1065 char reason[512];
1066 client_t *save;
1067 int i;
1068 qbool byNumber = false;
1069
1070 if (!sv.active)
1071 return;
1072
1073 save = host_client;
1074
1075 if (Cmd_Argc(cmd) > 2 && strcmp(Cmd_Argv(cmd, 1), "#") == 0)
1076 {
1077 i = (int)(atof(Cmd_Argv(cmd, 2)) - 1);
1078 if (i < 0 || i >= svs.maxclients || !(host_client = svs.clients + i)->active)
1079 return;
1080 byNumber = true;
1081 }
1082 else
1083 {
1084 for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++)
1085 {
1086 if (!host_client->active)
1087 continue;
1088 if (strcasecmp(host_client->name, Cmd_Argv(cmd, 1)) == 0)
1089 break;
1090 }
1091 }
1092
1093 if (i < svs.maxclients)
1094 {
1095 if (cmd->source == src_local)
1096 {
1098 who = "Console";
1099 else
1100 who = cl_name.string;
1101 }
1102 else
1103 who = save->name;
1104
1105 // can't kick yourself!
1106 if (host_client == save)
1107 return;
1108
1109 if (Cmd_Argc(cmd) > 2)
1110 {
1111 message = Cmd_Args(cmd);
1112 COM_ParseToken_Simple(&message, false, false, true);
1113 if (byNumber)
1114 {
1115 message++; // skip the #
1116 while (*message == ' ') // skip white space
1117 message++;
1118 message += strlen(Cmd_Argv(cmd, 2)); // skip the number
1119 }
1120 while (*message && *message == ' ')
1121 message++;
1122 }
1123 if (message)
1124 SV_DropClient (false, va(reason, sizeof(reason), "Kicked by %s: %s", who, message)); // kicked
1125 //SV_ClientPrintf("Kicked by %s: %s\n", who, message);
1126 else
1127 //SV_ClientPrintf("Kicked by %s\n", who);
1128 SV_DropClient (false, va(reason, sizeof(reason), "Kicked by %s", who)); // kicked
1129 }
1130
1131 host_client = save;
1132}
1133
1135{
1136 int n;
1137
1138 if (Cmd_Argc(cmd) != 2)
1139 {
1140 Con_Printf("\"maxplayers\" is \"%u\"\n", svs.maxclients_next);
1141 return;
1142 }
1143
1144 if (sv.active)
1145 {
1146 Con_Print("maxplayers can not be changed while a server is running.\n");
1147 Con_Print("It will be changed on next server startup (\"map\" command).\n");
1148 }
1149
1150 n = atoi(Cmd_Argv(cmd, 1));
1151 n = bound(1, n, MAX_SCOREBOARD);
1152 Con_Printf("\"maxplayers\" set to \"%u\"\n", n);
1153
1155 if (n == 1)
1157 else
1159}
1160
1161/*
1162======================
1163SV_Playermodel_f
1164======================
1165*/
1166// the old playermodel in cl_main has been renamed to __cl_playermodel
1168{
1169 prvm_prog_t *prog = SVVM_prog;
1170 int i, j;
1171 char newPath[sizeof(host_client->playermodel)];
1172
1173 if (Cmd_Argc (cmd) == 1)
1174 return;
1175
1176 if (Cmd_Argc (cmd) == 2)
1177 dp_strlcpy (newPath, Cmd_Argv(cmd, 1), sizeof (newPath));
1178 else
1179 dp_strlcpy (newPath, Cmd_Args(cmd), sizeof (newPath));
1180
1181 for (i = 0, j = 0;newPath[i];i++)
1182 if (newPath[i] != '\r' && newPath[i] != '\n')
1183 newPath[j++] = newPath[i];
1184 newPath[j] = 0;
1185
1186 /*
1187 if (host.realtime < host_client->nametime)
1188 {
1189 SV_ClientPrintf("You can't change playermodel more than once every 5 seconds!\n");
1190 return;
1191 }
1192
1193 host_client->nametime = host.realtime + 5;
1194 */
1195
1196 // point the string back at updateclient->name to keep it safe
1200 {
1202 /*// send notification to all clients
1203 MSG_WriteByte (&sv.reliable_datagram, svc_updatepmodel);
1204 MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
1205 MSG_WriteString (&sv.reliable_datagram, host_client->playermodel);*/
1206 }
1207}
1208
1209/*
1210======================
1211SV_Playerskin_f
1212======================
1213*/
1215{
1216 prvm_prog_t *prog = SVVM_prog;
1217 int i, j;
1218 char newPath[sizeof(host_client->playerskin)];
1219
1220 if (Cmd_Argc (cmd) == 1)
1221 return;
1222
1223 if (Cmd_Argc (cmd) == 2)
1224 dp_strlcpy (newPath, Cmd_Argv(cmd, 1), sizeof (newPath));
1225 else
1226 dp_strlcpy (newPath, Cmd_Args(cmd), sizeof (newPath));
1227
1228 for (i = 0, j = 0;newPath[i];i++)
1229 if (newPath[i] != '\r' && newPath[i] != '\n')
1230 newPath[j++] = newPath[i];
1231 newPath[j] = 0;
1232
1233 /*
1234 if (host.realtime < host_client->nametime)
1235 {
1236 SV_ClientPrintf("You can't change playermodel more than once every 5 seconds!\n");
1237 return;
1238 }
1239
1240 host_client->nametime = host.realtime + 5;
1241 */
1242
1243 // point the string back at updateclient->name to keep it safe
1247 {
1248 //if (host_client->begun)
1249 // SV_BroadcastPrintf("%s changed skin to %s\n", host_client->name, host_client->playerskin);
1251 /*// send notification to all clients
1252 MSG_WriteByte (&sv.reliable_datagram, svc_updatepskin);
1253 MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
1254 MSG_WriteString (&sv.reliable_datagram, host_client->playerskin);*/
1255 }
1256}
1257
1258/*
1259======================
1260SV_PModel_f
1261LadyHavoc: only supported for Nehahra, I personally think this is dumb, but Mindcrime won't listen.
1262LadyHavoc: correction, Mindcrime will be removing pmodel in the future, but it's still stuck here for compatibility.
1263======================
1264*/
1266{
1267 prvm_prog_t *prog = SVVM_prog;
1268
1269 if (Cmd_Argc (cmd) == 1)
1270 return;
1271
1272 PRVM_serveredictfloat(host_client->edict, pmodel) = atoi(Cmd_Argv(cmd, 1));
1273}
1274
1275/*
1276===============================================================================
1277
1278DEBUGGING TOOLS
1279
1280===============================================================================
1281*/
1282
1284{
1285 int i;
1286 prvm_edict_t *e;
1287
1288 for (i=0 ; i<prog->num_edicts ; i++)
1289 {
1290 e = PRVM_EDICT_NUM(i);
1291 if (!strcmp (PRVM_GetString(prog, PRVM_serveredictstring(e, classname)), "viewthing"))
1292 return e;
1293 }
1294 Con_Print("No viewthing on map\n");
1295 return NULL;
1296}
1297
1298/*
1299==================
1300SV_Viewmodel_f
1301==================
1302*/
1304{
1305 prvm_prog_t *prog = SVVM_prog;
1306 prvm_edict_t *e;
1307 model_t *m;
1308
1309 if (!sv.active)
1310 return;
1311
1312 e = FindViewthing(prog);
1313 if (e)
1314 {
1315 m = Mod_ForName (Cmd_Argv(cmd, 1), false, true, NULL);
1316 if (m && m->loaded && m->Draw)
1317 {
1320 }
1321 else
1322 Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(cmd, 1));
1323 }
1324}
1325
1326/*
1327==================
1328SV_Viewframe_f
1329==================
1330*/
1332{
1333 prvm_prog_t *prog = SVVM_prog;
1334 prvm_edict_t *e;
1335 int f;
1336 model_t *m;
1337
1338 if (!sv.active)
1339 return;
1340
1341 e = FindViewthing(prog);
1342 if (e)
1343 {
1345
1346 f = atoi(Cmd_Argv(cmd, 1));
1347 if (f >= m->numframes)
1348 f = m->numframes-1;
1349
1351 }
1352}
1353
1354static void PrintFrameName (model_t *m, int frame)
1355{
1356 if (m->animscenes)
1357 Con_Printf("frame %i: %s\n", frame, m->animscenes[frame].name);
1358 else
1359 Con_Printf("frame %i\n", frame);
1360}
1361
1362/*
1363==================
1364SV_Viewnext_f
1365==================
1366*/
1368{
1369 prvm_prog_t *prog = SVVM_prog;
1370 prvm_edict_t *e;
1371 model_t *m;
1372
1373 if (!sv.active)
1374 return;
1375
1376 e = FindViewthing(prog);
1377 if (e)
1378 {
1380
1384
1386 }
1387}
1388
1389/*
1390==================
1391SV_Viewprev_f
1392==================
1393*/
1395{
1396 prvm_prog_t *prog = SVVM_prog;
1397 prvm_edict_t *e;
1398 model_t *m;
1399
1400 if (!sv.active)
1401 return;
1402
1403 e = FindViewthing(prog);
1404 if (e)
1405 {
1407
1409 if (PRVM_serveredictfloat(e, frame) < 0)
1411
1413 }
1414}
1415
1417{
1418 int i;
1419 const char *cvarname;
1420 client_t *old;
1421
1422 if(Cmd_Argc(cmd) != 2)
1423 return;
1424
1425 if(!sv.active)// || !PRVM_serverfunction(SV_ParseClientCommand))
1426 return;
1427
1428 cvarname = Cmd_Argv(cmd, 1);
1429
1430 old = host_client;
1432 i = 1;
1433 else
1434 i = 0;
1435 for(;i<svs.maxclients;i++)
1436 if(svs.clients[i].active && svs.clients[i].netconnection)
1437 {
1439 SV_ClientCommands("sendcvar %s\n", cvarname);
1440 }
1441 host_client = old;
1442}
1443
1445{
1446 prvm_prog_t *prog = SVVM_prog;
1447 prvm_edict_t *ed;
1448 mdef_t *key;
1449 int i;
1450 qbool haveorigin;
1451
1452 void (*print)(const char *, ...) = (cmd->source == src_client ? SV_ClientPrintf : Con_Printf);
1453
1454 if(Cmd_Argc(cmd) == 1)
1455 {
1456 print("Usage: ent_create <classname> [<key> <value> ... ]\n\nIf executing as a player, an entity of classname will spawn where you're aiming.\nOptional key-value pairs can be provided. If origin is provided, it will spawn the entity at that coordinate.\nHowever, an origin is required if the command is executed from a dedicated server console.\n");
1457 return;
1458 }
1459
1461
1462 PRVM_ED_ParseEpair(prog, ed, PRVM_ED_FindField(prog, "classname"), Cmd_Argv(cmd, 1), false);
1463
1464 // Spawn where the player is aiming. We need a view matrix first.
1465 if(cmd->source == src_client)
1466 {
1467 vec3_t org, temp, dest;
1468 matrix4x4_t view;
1469 trace_t trace;
1470 char buf[128];
1471
1472 SV_GetEntityMatrix(prog, host_client->edict, &view, true);
1473
1474 Matrix4x4_OriginFromMatrix(&view, org);
1475 VectorSet(temp, 65536, 0, 0);
1476 Matrix4x4_Transform(&view, temp, dest);
1477
1479
1480 dpsnprintf(buf, sizeof(buf), "%g %g %g", trace.endpos[0], trace.endpos[1], trace.endpos[2]);
1481 PRVM_ED_ParseEpair(prog, ed, PRVM_ED_FindField(prog, "origin"), buf, false);
1482
1483 haveorigin = true;
1484 }
1485 // Or spawn at a specified origin.
1486 else
1487 haveorigin = false;
1488
1489 // Allow more than one key/value pair by cycling between expecting either one.
1490 for(i = 2; i < Cmd_Argc(cmd); i += 2)
1491 {
1492 if(!(key = PRVM_ED_FindField(prog, Cmd_Argv(cmd, i))))
1493 {
1494 print("Key %s not found!\n", Cmd_Argv(cmd, i));
1495 PRVM_ED_Free(prog, ed);
1496 return;
1497 }
1498
1499 /*
1500 * This is mostly for dedicated server console, but if the
1501 * player gave a custom origin, we can ignore the traceline.
1502 */
1503 if(!strcmp(Cmd_Argv(cmd, i), "origin"))
1504 haveorigin = true;
1505
1506 if (i + 1 < Cmd_Argc(cmd))
1507 PRVM_ED_ParseEpair(prog, ed, key, Cmd_Argv(cmd, i+1), false);
1508 }
1509
1510 if(!haveorigin)
1511 {
1512 print("Missing origin\n");
1513 PRVM_ED_Free(prog, ed);
1514 return;
1515 }
1516
1517 // Spawn it
1519
1520 if(!PRVM_ED_CallSpawnFunction(prog, ed, NULL, NULL))
1521 {
1522 print("Could not spawn a \"%s\". No such entity or it has no spawn function\n", Cmd_Argv(cmd, 1));
1523 if(cmd->source == src_client)
1524 Con_Printf("%s tried to spawn a \"%s\"\n", host_client->name, Cmd_Argv(cmd, 1));
1525 // CallSpawnFunction already freed the edict for us.
1526 return;
1527 }
1528
1530
1531 // Make it appear in the world
1532 SV_LinkEdict(ed);
1533
1534 if(cmd->source == src_client)
1535 Con_Printf("%s spawned a \"%s\"\n", host_client->name, Cmd_Argv(cmd, 1));
1536}
1537
1539{
1540 prvm_prog_t *prog = SVVM_prog;
1541 prvm_edict_t *ed;
1542 int i, ednum = 0;
1543 void (*print)(const char *, ...) = (cmd->source == src_client ? SV_ClientPrintf : Con_Printf);
1544
1545 if(!Cmd_Argc(cmd))
1546 return;
1547
1548 // Allow specifying edict by number
1549 if(Cmd_Argc(cmd) > 1 && Cmd_Argv(cmd, 1))
1550 {
1551 ednum = atoi(Cmd_Argv(cmd, 1));
1552 if(!ednum)
1553 {
1554 print("Cannot remove the world\n");
1555 return;
1556 }
1557 }
1558 // Or trace a line if it's a client who didn't specify one.
1559 else if(cmd->source == src_client)
1560 {
1561 vec3_t org, temp, dest;
1562 matrix4x4_t view;
1563 trace_t trace;
1564
1565 SV_GetEntityMatrix(prog, host_client->edict, &view, true);
1566
1567 Matrix4x4_OriginFromMatrix(&view, org);
1568 VectorSet(temp, 65536, 0, 0);
1569 Matrix4x4_Transform(&view, temp, dest);
1570
1572
1573 if(trace.ent)
1574 ednum = (int)PRVM_EDICT_TO_PROG(trace.ent);
1575 if(!trace.ent || !ednum)
1576 // Don't remove the world, but don't annoy players with a print if they miss
1577 return;
1578 }
1579 else
1580 {
1581 // Only a dedicated server console should be able to reach this.
1582 print("No edict given\n");
1583 return;
1584 }
1585
1586 ed = PRVM_EDICT_NUM(ednum);
1587
1588 if(ed)
1589 {
1590 // Skip players
1591 for (i = 0; i < svs.maxclients; i++)
1592 {
1593 if(ed == svs.clients[i].edict)
1594 return;
1595 }
1596
1597 if(!ed->free)
1598 {
1599 print("Removed a \"%s\"\n", PRVM_GetString(prog, PRVM_serveredictstring(ed, classname)));
1600 PRVM_ED_ClearEdict(prog, ed);
1601 PRVM_ED_Free(prog, ed);
1602 }
1603 }
1604 else
1605 {
1606 // This should only be reachable if an invalid edict number was given
1607 print("No such entity\n");
1608 return;
1609 }
1610}
1611
1613{
1614 prvm_prog_t *prog = SVVM_prog;
1615 int i, rmcount;
1616 prvm_edict_t *ed;
1617 void (*print)(const char *, ...) = (cmd->source == src_client ? SV_ClientPrintf : Con_Printf);
1618
1619 for (i = 0, rmcount = 0, ed = PRVM_EDICT_NUM(i); i < prog->num_edicts; i++, ed = PRVM_NEXT_EDICT(ed))
1620 {
1621 if(!ed->free && !strcmp(PRVM_GetString(prog, PRVM_serveredictstring(ed, classname)), Cmd_Argv(cmd, 1)))
1622 {
1623 if(!i)
1624 {
1625 print("Cannot remove the world\n");
1626 return;
1627 }
1628 PRVM_ED_ClearEdict(prog, ed);
1629 PRVM_ED_Free(prog, ed);
1630 rmcount++;
1631 }
1632 }
1633
1634 if(!rmcount)
1635 print("No \"%s\" found\n", Cmd_Argv(cmd, 1));
1636 else
1637 print("Removed %i of \"%s\"\n", rmcount, Cmd_Argv(cmd, 1));
1638}
1639
1641{
1648
1649 Cmd_AddCommand(CF_SERVER | CF_SERVER_FROM_CLIENT, "status", SV_Status_f, "print server status information");
1650 Cmd_AddCommand(CF_SHARED, "map", SV_Map_f, "kick everyone off the server and start a new level");
1651 Cmd_AddCommand(CF_SHARED, "restart", SV_Restart_f, "restart current level");
1652 Cmd_AddCommand(CF_SHARED, "changelevel", SV_Changelevel_f, "change to another level, bringing along all connected clients (or start a new level if none is loaded)");
1653 Cmd_AddCommand(CF_SHARED | CF_SERVER_FROM_CLIENT, "say", SV_Say_f, "send a chat message to everyone on the server");
1654 Cmd_AddCommand(CF_SERVER_FROM_CLIENT, "say_team", SV_Say_Team_f, "send a chat message to your team on the server");
1655 Cmd_AddCommand(CF_SHARED | CF_SERVER_FROM_CLIENT, "tell", SV_Tell_f, "send a chat message to only one person on the server");
1656 Cmd_AddCommand(CF_SERVER | CF_SERVER_FROM_CLIENT, "pause", SV_Pause_f, "pause the game (if the server allows pausing)");
1657 Cmd_AddCommand(CF_SHARED, "kick", SV_Kick_f, "kick a player off the server by number or name");
1658 Cmd_AddCommand(CF_SHARED | CF_SERVER_FROM_CLIENT, "ping", SV_Ping_f, "print ping times of all players on the server");
1659 Cmd_AddCommand(CF_SERVER, "load", SV_Loadgame_f, "load a saved game file");
1660 Cmd_AddCommand(CF_SERVER, "save", SV_Savegame_f, "save the game to a file");
1661 Cmd_AddCommand(CF_SHARED, "viewmodel", SV_Viewmodel_f, "change model of viewthing entity in current level");
1662 Cmd_AddCommand(CF_SHARED, "viewframe", SV_Viewframe_f, "change animation frame of viewthing entity in current level");
1663 Cmd_AddCommand(CF_SHARED, "viewnext", SV_Viewnext_f, "change to next animation frame of viewthing entity in current level");
1664 Cmd_AddCommand(CF_SHARED, "viewprev", SV_Viewprev_f, "change to previous animation frame of viewthing entity in current level");
1665 Cmd_AddCommand(CF_SHARED, "maxplayers", SV_MaxPlayers_f, "sets limit on how many players (or bots) may be connected to the server at once");
1667
1668 // commands that do not have automatic forwarding from cmd_local, these are internal details of the network protocol and not of interest to users (if they know what they are doing they can still use a generic "cmd prespawn" or similar)
1669 Cmd_AddCommand(CF_SERVER_FROM_CLIENT, "prespawn", SV_PreSpawn_f, "internal use - signon 1 (client acknowledges that server information has been received)");
1670 Cmd_AddCommand(CF_SERVER_FROM_CLIENT, "spawn", SV_Spawn_f, "internal use - signon 2 (client has sent player information, and is asking server to send scoreboard rankings)");
1671 Cmd_AddCommand(CF_SERVER_FROM_CLIENT, "begin", SV_Begin_f, "internal use - signon 3 (client asks server to start sending entities, and will go to signon 4 (playing) when the first entity update is received)");
1672 Cmd_AddCommand(CF_SERVER_FROM_CLIENT, "pings", SV_Pings_f, "internal use - command sent by clients to request updated ping and packetloss of players on scoreboard (originally from QW, but also used on NQ servers)");
1673
1674 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "god", SV_God_f, "god mode (invulnerability)");
1675 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "notarget", SV_Notarget_f, "notarget mode (monsters do not see you)");
1676 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "fly", SV_Fly_f, "fly mode (flight)");
1677 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "noclip", SV_Noclip_f, "noclip mode (flight without collisions, move through walls)");
1678 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "give", SV_Give_f, "alter inventory");
1679 Cmd_AddCommand(CF_SERVER_FROM_CLIENT, "kill", SV_Kill_f, "die instantly");
1680
1681 Cmd_AddCommand(CF_USERINFO, "color", SV_Color_f, "change your player shirt and pants colors");
1682 Cmd_AddCommand(CF_USERINFO, "name", SV_Name_f, "change your player name");
1683 Cmd_AddCommand(CF_USERINFO, "rate", SV_Rate_f, "change your network connection speed");
1684 Cmd_AddCommand(CF_USERINFO, "rate_burstsize", SV_Rate_BurstSize_f, "change your network connection speed");
1685 Cmd_AddCommand(CF_USERINFO, "pmodel", SV_PModel_f, "(Nehahra-only) change your player model choice");
1686 Cmd_AddCommand(CF_USERINFO, "playermodel", SV_Playermodel_f, "change your player model");
1687 Cmd_AddCommand(CF_USERINFO, "playerskin", SV_Playerskin_f, "change your player skin number");
1688
1689 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "ent_create", SV_Ent_Create_f, "Creates an entity at the specified coordinate, of the specified classname. If executed from a server, origin has to be specified manually.");
1690 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "ent_remove_all", SV_Ent_Remove_All_f, "Removes all entities of the specified classname");
1691 Cmd_AddCommand(CF_CHEAT | CF_SERVER_FROM_CLIENT, "ent_remove", SV_Ent_Remove_f, "Removes an entity by number, or the entity you're aiming at");
1692}
#define SUPERCONTENTS_BODY
Definition bspfile.h:201
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
cvar_t cl_name
User-visible names of these CF_USERINFO cvars must be matched in CL_SetInfo()!
Definition cl_cmd.c:32
client_state_t cl
Definition cl_main.c:117
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
#define CF_SHARED
Definition cmd.h:67
@ src_client
came in over a net connection as a clc_stringcmd host_client will be valid during this state.
Definition cmd.h:73
@ src_local
from the command buffer
Definition cmd.h:75
#define CF_NOTIFY
cvar should trigger a chat notification to all connected clients when changed
Definition cmd.h:55
#define CF_USERINFO
command or cvar used to communicate userinfo to the server
Definition cmd.h:57
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
#define CF_SERVER_FROM_CLIENT
command the client is allowed to execute on the server as a stringcmd
Definition cmd.h:51
#define CF_CHEAT
command or cvar that gives an unfair advantage over other players and is blocked unless sv_cheats is ...
Definition cmd.h:52
static const char * Cmd_Args(cmd_state_t *cmd)
Definition cmd.h:260
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53
cvar_t collision_extendmovelength
Definition collision.c:14
gamemode_t gamemode
Definition com_game.c:26
@ GAME_QUOTH
Definition com_game.h:31
@ GAME_ROGUE
Definition com_game.h:30
@ GAME_DELUXEQUAKE
Definition com_game.h:45
@ GAME_HIPNOTIC
Definition com_game.h:29
void MSG_WriteShort(sizebuf_t *sb, int c)
Definition com_msg.c:138
void MSG_WriteString(sizebuf_t *sb, const char *s)
Definition com_msg.c:173
void MSG_WriteByte(sizebuf_t *sb, int c)
Definition com_msg.c:130
void MSG_WriteUnterminatedString(sizebuf_t *sb, const char *s)
Definition com_msg.c:181
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
Definition common.c:463
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
@ PROTOCOL_QUAKE
quake (aka netquake/normalquake/nq) protocol
Definition common.h:144
@ PROTOCOL_QUAKEWORLD
quakeworld protocol
Definition common.h:145
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
void Con_DPrint(const char *msg)
A Con_Print that only shows up if the "developer" cvar is set.
Definition console.c:1531
unsigned int seconds
string classname
float movetype
float flags
float modelindex
entity self
string netname
void() predraw
float time
float frame
void Cvar_SetQuick(cvar_t *var, const char *value)
Definition cvar.c:436
cvar_state_t cvars_all
Definition cvar.c:28
const char * Cvar_VariableString(cvar_state_t *cvars, const char *var_name, unsigned neededflags)
Definition cvar.c:149
void Cvar_Set(cvar_state_t *cvars, const char *var_name, const char *value)
equivelant to "<name> <variable>" typed at the console
Definition cvar.c:456
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
void Cvar_RegisterCallback(cvar_t *variable, void(*callback)(cvar_t *))
Definition cvar.c:495
char engineversion[128]
version string for the corner of the console, crash messages, status command, etc
Definition host.c:304
string clientstatus
float ping
string playerskin
string playermodel
float clientcolors
#define STRING_COLOR_RGB_TAG_CHAR
Definition draw.h:143
#define STRING_COLOR_DEFAULT_STR
Definition draw.h:142
#define STRING_COLOR_DEFAULT
Definition draw.h:141
#define STRING_COLOR_TAG
Definition draw.h:140
#define n(x, y)
static int(ZEXPORT *qz_inflate)(z_stream *strm
const GLdouble * v
Definition glquake.h:762
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
host_static_t host
Definition host.c:41
cvar_t host_isclient
Definition host.c:61
@ LHNETADDRESSTYPE_LOOP
Definition lhnet.h:13
static lhnetaddresstype_t LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
Definition lhnet.h:31
#define max(A, B)
Definition mathlib.h:38
#define bound(min, num, max)
Definition mathlib.h:34
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
void Matrix4x4_Transform(const matrix4x4_t *in, const float v[3], float out[3])
Definition matrixlib.c:1657
void Matrix4x4_OriginFromMatrix(const matrix4x4_t *in, float *out)
Definition matrixlib.c:1792
float strlen(string s)
void cmd(string command,...)
void print(string text,...)
float floor(float f)
model_t * Mod_ForName(const char *name, qbool crash, qbool checkdisk, const char *parentname)
cvar_t hostname
Definition netconn.c:88
#define NETGRAPH_PACKETS
Definition netconn.h:222
#define NETGRAPH_LOSTPACKET
Definition netconn.h:224
#define OFS_PARM0
Definition pr_comp.h:34
float ammo_rockets
Definition progsdefs.qc:143
float frags
Definition progsdefs.qc:138
float weapon
Definition progsdefs.qc:139
float ammo_shells
Definition progsdefs.qc:143
float team
Definition progsdefs.qc:172
float deathmatch
Definition progsdefs.qc:29
float health
Definition progsdefs.qc:137
float items
Definition progsdefs.qc:145
float armorvalue
Definition progsdefs.qc:179
float ammo_nails
Definition progsdefs.qc:143
float teamplay
Definition progsdefs.qc:31
float ammo_cells
Definition progsdefs.qc:143
string message
Definition progsdefs.qc:205
float armortype
Definition progsdefs.qc:178
void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e)
Definition prvm_edict.c:210
void PRVM_ED_CallPostspawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
#define PRVM_serverglobaledict(fieldname)
Definition progsvm.h:180
#define PRVM_EDICT_TO_PROG(e)
Definition progsvm.h:875
int PRVM_SetEngineString(prvm_prog_t *prog, const char *s)
#define PRVM_EDICT_NUM(n)
Definition progsvm.h:867
qbool PRVM_ED_ParseEpair(prvm_prog_t *prog, prvm_edict_t *ent, mdef_t *key, const char *s, qbool parsebackslash)
Definition prvm_edict.c:991
#define PRVM_NEXT_EDICT(e)
Definition progsvm.h:873
const char * PRVM_GetString(prvm_prog_t *prog, int num)
mdef_t * PRVM_ED_FindField(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:376
#define PRVM_serverglobalfloat(fieldname)
Definition progsvm.h:177
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
#define PRVM_serverfunction(funcname)
Definition progsvm.h:182
qbool PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char *data, const char *start)
#define PRVM_serveredictstring(ed, fieldname)
Definition progsvm.h:174
void PRVM_ED_Free(prvm_prog_t *prog, prvm_edict_t *ed)
Definition prvm_edict.c:314
void PRVM_ED_CallPrespawnFunction(prvm_prog_t *prog, prvm_edict_t *ent)
#define SVVM_prog
Definition progsvm.h:766
prvm_edict_t * PRVM_ED_Alloc(prvm_prog_t *prog)
Definition prvm_edict.c:269
int Protocol_NumberForEnum(protocolversion_t p)
Definition protocol.c:95
const char * Protocol_NameForEnum(protocolversion_t p)
Definition protocol.c:77
#define qw_svc_updatepl
Definition protocol.h:951
#define svc_setpause
Definition protocol.h:246
#define qw_svc_updateping
Definition protocol.h:934
#define svc_stufftext
Definition protocol.h:223
#define svc_updatecolors
Definition protocol.h:236
#define svc_updatename
Definition protocol.h:232
int i
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define ISWHITESPACE(ch)
Definition qdefs.h:184
#define MAX_SCOREBOARD
max number of players in game at once (255 protocol limit)
Definition qdefs.h:110
#define NULL
Definition qtypes.h:12
vec_t vec3_t[3]
Definition qtypes.h:71
bool qbool
Definition qtypes.h:9
#define IT_LIGHTNING
Definition quakedef.h:44
#define IT_GRENADE_LAUNCHER
Definition quakedef.h:42
#define IT_ARMOR3
Definition quakedef.h:53
#define IT_SHOTGUN
Definition quakedef.h:38
#define HIT_MJOLNIR
Definition quakedef.h:118
#define RIT_ARMOR3
Definition quakedef.h:103
#define IT_ARMOR2
Definition quakedef.h:52
#define RIT_ARMOR1
Definition quakedef.h:101
#define HIT_PROXIMITY_GUN
Definition quakedef.h:117
#define IT_ARMOR1
Definition quakedef.h:51
#define RIT_ARMOR2
Definition quakedef.h:102
#define HIT_LASER_CANNON
Definition quakedef.h:119
server_t sv
local server
Definition sv_main.c:223
void SV_SaveSpawnparms(void)
Definition sv_main.c:1761
void SV_Begin_f(cmd_state_t *cmd)
Definition sv_user.c:204
#define MOVETYPE_NOCLIP
Definition server.h:320
void SV_BroadcastPrintf(const char *fmt,...) DP_FUNC_PRINTF(1)
Definition sv_send.c:116
void SV_Spawn_f(cmd_state_t *cmd)
Definition sv_user.c:62
void SV_Loadgame_f(cmd_state_t *cmd)
Definition sv_save.c:240
#define MOVETYPE_WALK
gravity
Definition server.h:315
void SV_SpawnServer(const char *map)
Definition sv_main.c:1811
mempool_t * sv_mempool
Definition sv_main.c:226
trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float extend)
Definition sv_phys.c:256
void SV_LinkEdict(prvm_edict_t *ent)
Definition sv_phys.c:804
#define MOVETYPE_FLY
Definition server.h:317
void SV_ClientPrint(const char *msg)
Definition sv_send.c:55
void SV_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qbool viewmatrix)
Definition svvm_cmds.c:2518
const char * SV_TimingReport(char *buf, size_t buflen)
for output in SV_Status_f
Definition sv_main.c:2521
void SV_DropClient(qbool leaving, const char *reason,...)
Definition sv_main.c:1018
void SV_Savegame_f(cmd_state_t *cmd)
Definition sv_save.c:188
cvar_t pausable
Definition sv_main.c:49
server_static_t svs
persistant server info
Definition sv_main.c:224
#define FL_NOTARGET
Definition server.h:364
void SV_Shutdown(void)
Definition sv_main.c:2128
void SV_ClientCommands(const char *fmt,...) DP_FUNC_PRINTF(1)
Definition sv_send.c:135
client_t * host_client
Definition sv_main.c:29
void SV_PreSpawn_f(cmd_state_t *cmd)
Definition sv_user.c:36
#define FL_GODMODE
Definition server.h:363
void SV_ClientPrintf(const char *fmt,...) DP_FUNC_PRINTF(1)
Definition sv_send.c:72
float f
char name[32]
struct model_s * model_precache[MAX_MODELS]
Definition client.h:888
char playermodel[MAX_QPATH]
Definition server.h:238
qbool active
false = empty client slot
Definition server.h:185
int colors
Definition server.h:236
qbool begun
false = don't send datagrams
Definition server.h:193
int old_colors
Definition server.h:236
int frags
Definition server.h:237
float nametime
prevent animated names
Definition server.h:260
int rate
requested rate in bytes per second
Definition server.h:198
char old_name[MAX_SCOREBOARDNAME]
Definition server.h:235
char playerskin[MAX_QPATH]
Definition server.h:239
char name[MAX_SCOREBOARDNAME]
Definition server.h:235
netconn_t * netconnection
communications handle
Definition server.h:210
int rate_burstsize
temporarily exceed rate by this amount of bytes
Definition server.h:201
char old_model[MAX_QPATH]
Definition server.h:238
char old_skin[MAX_QPATH]
Definition server.h:239
prvm_edict_t * edict
PRVM_EDICT_NUM(clientnum+1)
Definition server.h:221
double connecttime
realtime this client connected
Definition server.h:204
float ping
LadyHavoc: can be used for prediction or whatever...
Definition server.h:224
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
const char * string
Definition cvar.h:71
void(* ConnectLocal)(void)
Definition host.h:55
void(* SV_SendCvar)(struct cmd_state_s *)
Definition host.h:59
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46
void(* ToggleMenu)(void)
Definition host.h:57
struct host_static_t::@12 hook
void(* Disconnect)(qbool, const char *,...)
Definition host.h:56
qbool loaded
void(* Draw)(struct entity_render_s *ent)
animscene_t * animscenes
int numframes
netgraphitem_t incoming_netgraph[NETGRAPH_PACKETS]
Definition netconn.h:227
lhnetaddress_t peeraddress
Definition netconn.h:147
sizebuf_t message
writing buffer to send to peer as the next reliable message can be added to at any time,...
Definition netconn.h:161
char address[128]
Definition netconn.h:231
int unreliablebytes
Definition netconn.h:136
qbool free
true if this edict is unused
Definition progsvm.h:93
qbool loaded
used to indicate whether a prog is loaded
Definition progsvm.h:710
prvm_vec_t * fp
Definition progsvm.h:580
int num_edicts
copies of some vars that were former read from sv
Definition progsvm.h:671
void(* ExecuteProgram)(struct prvm_prog_s *prog, func_t fnum, const char *errormessage)
pointer to one of the *VM_ExecuteProgram functions
Definition progsvm.h:749
union prvm_prog_t::@31 globals
int maxclients_next
Definition server.h:28
struct client_s * clients
client slots
Definition server.h:30
int maxclients
number of svs.clients slots (updated by maxplayers command)
Definition server.h:28
int serverflags
episode completion information
Definition server.h:32
double time
Definition server.h:76
char worldbasename[MAX_QPATH]
Definition server.h:109
qbool paused
Definition server.h:68
qbool active
false if only a net client
Definition server.h:66
sizebuf_t reliable_datagram
Definition server.h:130
protocolversion_t protocol
one of the PROTOCOL_ values
Definition server.h:74
void * ent
Definition collision.h:47
double endpos[3]
Definition collision.h:42
static void SV_Viewframe_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1331
static void SV_SendCvar_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1416
static void SV_Notarget_f(cmd_state_t *cmd)
Definition sv_ccmds.c:399
cvar_t sv_status_show_qcstatus
Definition sv_ccmds.c:31
static void SV_Ping_f(cmd_state_t *cmd)
Definition sv_ccmds.c:656
static void SV_Viewmodel_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1303
cvar_t sv_namechangetimer
Definition sv_ccmds.c:32
static void PrintFrameName(model_t *m, int frame)
Definition sv_ccmds.c:1354
static void SV_Map_f(cmd_state_t *cmd)
Definition sv_ccmds.c:51
static void SV_Color_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1013
static void SV_Ent_Remove_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1538
qbool noclip_anglehack
Definition sv_ccmds.c:190
static void SV_PModel_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1265
static void SV_Say_Team_f(cmd_state_t *cmd)
Definition sv_ccmds.c:525
static void SV_Status_f(cmd_state_t *cmd)
Definition sv_ccmds.c:743
static void SV_Changelevel_f(cmd_state_t *cmd)
Definition sv_ccmds.c:93
static void SV_Pings_f(cmd_state_t *cmd)
Definition sv_ccmds.c:686
static void SV_Playerskin_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1214
static void SV_Kill_f(cmd_state_t *cmd)
Definition sv_ccmds.c:415
static void SV_Say(cmd_state_t *cmd, qbool teamonly)
Definition sv_ccmds.c:460
void SV_Name(int clientnum)
Definition sv_ccmds.c:868
void SV_InitOperatorCommands(void)
Definition sv_ccmds.c:1640
static void SV_Restart_f(cmd_state_t *cmd)
Definition sv_ccmds.c:124
static void SV_Give_f(cmd_state_t *cmd)
Definition sv_ccmds.c:215
static void SV_Ent_Remove_All_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1612
static void SV_Rate_BurstSize_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1001
static void SV_Viewnext_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1367
int current_skill
skill level for currently loaded level (in case the user changes the cvar while the level is running,...
Definition sv_ccmds.c:27
static void SV_Noclip_f(cmd_state_t *cmd)
Definition sv_ccmds.c:192
static void SV_Viewprev_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1394
static void SV_Playermodel_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1167
static void SV_Kick_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1061
static void SV_DisableCheats_c(cvar_t *var)
Definition sv_ccmds.c:149
static void SV_Rate_f(cmd_state_t *cmd)
Definition sv_ccmds.c:989
cvar_t sv_status_privacy
Definition sv_ccmds.c:30
static void SV_Name_f(cmd_state_t *cmd)
Definition sv_ccmds.c:890
static prvm_edict_t * FindViewthing(prvm_prog_t *prog)
Definition sv_ccmds.c:1283
static void SV_Pause_f(cmd_state_t *cmd)
Definition sv_ccmds.c:434
cvar_t sv_cheats
Definition sv_ccmds.c:28
static void SV_God_f(cmd_state_t *cmd)
Definition sv_ccmds.c:179
static void SV_MaxPlayers_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1134
static void SV_Say_f(cmd_state_t *cmd)
Definition sv_ccmds.c:520
cvar_t sv_adminnick
Definition sv_ccmds.c:29
static void SV_Fly_f(cmd_state_t *cmd)
Definition sv_ccmds.c:383
static void SV_Ent_Create_f(cmd_state_t *cmd)
Definition sv_ccmds.c:1444
static void SV_Tell_f(cmd_state_t *cmd)
Definition sv_ccmds.c:530
void SV_WriteNetnameIntoDemo(client_t *client)
Definition sv_demo.c:82
size_t u8_COM_StringLengthNoColors(const char *_s, size_t size_s, qbool *valid)
Definition utf8lib.c:777
#define MOVE_NORMAL
Definition world.h:28
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92