Quake II RTX doxygen  1.0 dev
common.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 Copyright (C) 2019, NVIDIA CORPORATION. All rights reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 //
21 // common.c -- misc functions used in client and server
22 //
23 
24 #include "shared/shared.h"
25 
26 #include "common/bsp.h"
27 #include "common/cmd.h"
28 #include "common/cmodel.h"
29 #include "common/common.h"
30 #include "common/cvar.h"
31 #include "common/error.h"
32 #include "common/field.h"
33 #include "common/fifo.h"
34 #include "common/files.h"
35 #include "common/math.h"
36 #include "common/mdfour.h"
37 #include "common/msg.h"
38 #include "common/net/net.h"
39 #include "common/net/chan.h"
40 #include "common/pmove.h"
41 #include "common/prompt.h"
42 #include "common/protocol.h"
43 #include "common/tests.h"
44 #include "common/utils.h"
45 #include "common/x86/fpu.h"
46 #include "common/zone.h"
47 
48 #include "client/client.h"
49 #include "client/keys.h"
50 #include "server/server.h"
51 #include "system/system.h"
52 
53 #include <setjmp.h>
54 
55 #ifdef _WIN32
56 #include <Windows.h>
57 #endif
58 
59 static jmp_buf com_abortframe; // an ERR_DROP occured, exit the entire frame
60 
61 static void (*com_abort_func)(void *);
62 static void *com_abort_arg;
63 
64 static qboolean com_errorEntered;
65 static char com_errorMsg[MAXERRORMSG]; // from Com_Printf/Com_Error
66 
67 static int com_printEntered;
68 
69 static qhandle_t com_logFile;
70 static qboolean com_logNewline;
71 
72 static char **com_argv;
73 static int com_argc;
74 
75 cvar_t *z_perturb;
76 
77 #ifdef _DEBUG
78 cvar_t *developer;
79 #endif
80 cvar_t *timescale;
81 cvar_t *fixedtime;
82 cvar_t *dedicated;
83 cvar_t *backdoor;
84 cvar_t *com_version;
85 
86 cvar_t *logfile_enable; // 1 = create new, 2 = append to existing
87 cvar_t *logfile_flush; // 1 = flush after each print
88 cvar_t *logfile_name;
90 
91 #if USE_CLIENT
92 cvar_t *cl_running;
93 cvar_t *cl_paused;
94 #endif
95 cvar_t *sv_running;
96 cvar_t *sv_paused;
97 cvar_t *com_timedemo;
100 #ifdef _DEBUG
101 cvar_t *com_debug_break;
102 #endif
104 
113 
115 
116 extern cvar_t *fs_shareware;
117 
118 const char com_version_string[] =
119  APPLICATION " " VERSION_STRING " " __DATE__ " " BUILDSTRING " " CPUSTRING;
120 
121 unsigned com_framenum;
122 unsigned com_eventTime;
123 unsigned com_localTime;
126 
127 #if USE_CLIENT
128 cvar_t *host_speeds;
129 
130 // host_speeds times
131 unsigned time_before_game;
132 unsigned time_after_game;
133 unsigned time_before_ref;
134 unsigned time_after_ref;
135 #endif
136 
137 /*
138 ============================================================================
139 
140 CLIENT / SERVER interactions
141 
142 ============================================================================
143 */
144 
145 static int rd_target;
146 static char *rd_buffer;
147 static size_t rd_buffersize;
148 static size_t rd_length;
149 static rdflush_t rd_flush;
150 
151 void Com_BeginRedirect(int target, char *buffer, size_t buffersize, rdflush_t flush)
152 {
153  if (rd_target || !target || !buffer || !buffersize || !flush) {
154  return;
155  }
156  rd_target = target;
157  rd_buffer = buffer;
158  rd_buffersize = buffersize;
159  rd_flush = flush;
160  rd_length = 0;
161 }
162 
163 static void Com_AbortRedirect(void)
164 {
165  rd_target = 0;
166  rd_buffer = NULL;
167  rd_buffersize = 0;
168  rd_flush = NULL;
169  rd_length = 0;
170 }
171 
172 void Com_EndRedirect(void)
173 {
174  if (!rd_target) {
175  return;
176  }
178  rd_target = 0;
179  rd_buffer = NULL;
180  rd_buffersize = 0;
181  rd_flush = NULL;
182  rd_length = 0;
183 }
184 
185 static void Com_Redirect(const char *msg, size_t total)
186 {
187  size_t length;
188 
189  while (total) {
190  length = total;
191  if (length > rd_buffersize) {
192  length = rd_buffersize;
193  }
194  if (rd_length > rd_buffersize - length) {
196  rd_length = 0;
197  }
198  memcpy(rd_buffer + rd_length, msg, length);
199  rd_length += length;
200  total -= length;
201  }
202 }
203 
204 static void logfile_close(void)
205 {
206  if (!com_logFile) {
207  return;
208  }
209 
210  Com_Printf("Closing console log.\n");
211 
213  com_logFile = 0;
214 }
215 
216 static void logfile_open(void)
217 {
218  char buffer[MAX_OSPATH];
219  unsigned mode;
220  qhandle_t f;
221 
222  mode = logfile_enable->integer > 1 ? FS_MODE_APPEND : FS_MODE_WRITE;
223  if (logfile_flush->integer > 0) {
224  if (logfile_flush->integer > 1) {
225  mode |= FS_BUF_NONE;
226  } else {
227  mode |= FS_BUF_LINE;
228  }
229  }
230 
231  f = FS_EasyOpenFile(buffer, sizeof(buffer), mode | FS_FLAG_TEXT,
232  "logs/", logfile_name->string, ".log");
233  if (!f) {
234  Cvar_Set("logfile", "0");
235  return;
236  }
237 
238  com_logFile = f;
239  com_logNewline = qtrue;
240  Com_Printf("Logging console to %s\n", buffer);
241 }
242 
243 static void logfile_enable_changed(cvar_t *self)
244 {
245  logfile_close();
246  if (self->integer) {
247  logfile_open();
248  }
249 }
250 
251 static void logfile_param_changed(cvar_t *self)
252 {
253  if (logfile_enable->integer) {
254  logfile_close();
255  logfile_open();
256  }
257 }
258 
259 static size_t format_local_time(char *buffer, size_t size, const char *fmt)
260 {
261  static struct tm cached_tm;
262  static time_t cached_time;
263  time_t now;
264  struct tm *tm;
265 
266  if (!size) {
267  return 0;
268  }
269 
270  buffer[0] = 0;
271 
272  now = time(NULL);
273  if (now == cached_time) {
274  // avoid calling localtime() too often since it is not that cheap
275  tm = &cached_tm;
276  } else {
277  tm = localtime(&now);
278  if (!tm) {
279  return 0;
280  }
281  cached_time = now;
282  cached_tm = *tm;
283  }
284 
285  return strftime(buffer, size, fmt, tm);
286 }
287 
288 static void logfile_write(print_type_t type, const char *s)
289 {
290  char text[MAXPRINTMSG];
291  char buf[MAX_QPATH];
292  char *p, *maxp;
293  size_t len;
294  ssize_t ret;
295  int c;
296 
297  if (logfile_prefix->string[0]) {
298  p = strchr(logfile_prefix->string, '@');
299  if (p) {
300  // expand it in place, hacky
301  switch (type) {
302  case PRINT_TALK: *p = 'T'; break;
303  case PRINT_DEVELOPER: *p = 'D'; break;
304  case PRINT_WARNING: *p = 'W'; break;
305  case PRINT_ERROR: *p = 'E'; break;
306  case PRINT_NOTICE: *p = 'N'; break;
307  default: *p = 'A'; break;
308  }
309  }
310  len = format_local_time(buf, sizeof(buf), logfile_prefix->string);
311  if (p) {
312  *p = '@';
313  }
314  } else {
315  len = 0;
316  }
317 
318  p = text;
319  maxp = text + sizeof(text) - 1;
320  while (*s) {
321  if (com_logNewline) {
322  if (len > 0 && p + len < maxp) {
323  memcpy(p, buf, len);
324  p += len;
325  }
326  com_logNewline = qfalse;
327  }
328 
329  if (p == maxp) {
330  break;
331  }
332 
333  c = *s++;
334  if (c == '\n') {
335  com_logNewline = qtrue;
336  } else {
337  c = Q_charascii(c);
338  }
339 
340  *p++ = c;
341  }
342  *p = 0;
343 
344  len = p - text;
345  ret = FS_Write(text, len, com_logFile);
346  if (ret != len) {
347  // zero handle BEFORE doing anything else to avoid recursion
348  qhandle_t tmp = com_logFile;
349  com_logFile = 0;
350  FS_FCloseFile(tmp);
351  Com_EPrintf("Couldn't write console log: %s\n", Q_ErrorString(ret));
352  Cvar_Set("logfile", "0");
353  }
354 }
355 
356 #ifndef _WIN32
357 /*
358 =============
359 Com_FlushLogs
360 
361 When called from SIGHUP handler on UNIX-like systems,
362 will close and reopen logfile handle for rotation.
363 =============
364 */
365 void Com_FlushLogs(void)
366 {
367  if (logfile_enable) {
369  }
370 }
371 #endif
372 
373 void Com_SetColor(color_index_t color)
374 {
375  if (rd_target) {
376  return;
377  }
379  Sys_SetConsoleColor(color);
380 }
381 
382 void Com_SetLastError(const char *msg)
383 {
384  if (msg) {
386  } else {
387  strcpy(com_errorMsg, "No error");
388  }
389 }
390 
391 char *Com_GetLastError(void)
392 {
393  return com_errorMsg;
394 }
395 
396 /*
397 =============
398 Com_Printf
399 
400 Both client and server can use this, and it will output
401 to the apropriate place.
402 =============
403 */
404 void Com_LPrintf(print_type_t type, const char *fmt, ...)
405 {
406  va_list argptr;
407  char msg[MAXPRINTMSG];
408  size_t len;
409 
410  // may be entered recursively only once
411  if (com_printEntered >= 2) {
412  return;
413  }
414 
416 
417  va_start(argptr, fmt);
418  len = Q_vscnprintf(msg, sizeof(msg), fmt, argptr);
419  va_end(argptr);
420 
421  if (type == PRINT_ERROR && !com_errorEntered && len) {
422  size_t errlen = len;
423 
424  if (errlen >= sizeof(com_errorMsg)) {
425  errlen = sizeof(com_errorMsg) - 1;
426  }
427 
428  // save error msg
429  memcpy(com_errorMsg, msg, errlen);
430  com_errorMsg[errlen] = 0;
431 
432  // strip trailing '\n'
433  if (com_errorMsg[errlen - 1] == '\n') {
434  com_errorMsg[errlen - 1] = 0;
435  }
436  }
437 
438  if (rd_target) {
439  Com_Redirect(msg, len);
440  } else {
441  switch (type) {
442  case PRINT_TALK:
443  Com_SetColor(COLOR_ALT);
444  break;
445  case PRINT_DEVELOPER:
446  Com_SetColor(COLOR_BLUE);
447  break;
448  case PRINT_WARNING:
449  Com_SetColor(COLOR_YELLOW);
450  break;
451  case PRINT_ERROR:
452  Com_SetColor(COLOR_RED);
453  break;
454  case PRINT_NOTICE:
455  Com_SetColor(COLOR_CYAN);
456  break;
457  default:
458  break;
459  }
460 
461  // graphical console
462  Con_Print(msg);
463 
464  // debugging console
465  Sys_ConsoleOutput(msg);
466 
467 #ifdef _WIN32
468  OutputDebugStringA(msg);
469 #endif
470 
471  // remote console
472  //SV_ConsoleOutput(msg);
473 
474  // logfile
475  if (com_logFile) {
476  logfile_write(type, msg);
477  }
478 
479  if (type) {
480  Com_SetColor(COLOR_NONE);
481  }
482  }
483 
485 }
486 
487 
488 /*
489 =============
490 Com_Error
491 
492 Both client and server can use this, and it will
493 do the apropriate things.
494 =============
495 */
496 void Com_Error(error_type_t code, const char *fmt, ...)
497 {
498  char msg[MAXERRORMSG];
499  va_list argptr;
500  size_t len;
501 
502  // may not be entered recursively
503  if (com_errorEntered) {
504 #ifdef _DEBUG
505  if (com_debug_break && com_debug_break->integer) {
506  Sys_DebugBreak();
507  }
508 #endif
509  Sys_Error("recursive error after: %s", com_errorMsg);
510  }
511 
512  com_errorEntered = qtrue;
513 
514  va_start(argptr, fmt);
515  len = Q_vscnprintf(msg, sizeof(msg), fmt, argptr);
516  va_end(argptr);
517 
518  // save error msg
519  // can't print into it directly since it may
520  // overlap with one of the arguments!
521  memcpy(com_errorMsg, msg, len + 1);
522 
523  // fix up drity message buffers
524  MSG_Init();
525 
526  // abort any console redirects
528 
529  // call custom cleanup function if set
530  if (com_abort_func) {
532  com_abort_func = NULL;
533  }
534 
535  // reset Com_Printf recursion level
536  com_printEntered = 0;
537 
538  X86_POP_FPCW;
539 
540  if (code == ERR_DISCONNECT || code == ERR_RECONNECT) {
541  Com_WPrintf("%s\n", com_errorMsg);
542  SV_Shutdown(va("Server was killed: %s\n", com_errorMsg), code);
543  CL_Disconnect(code);
544  goto abort;
545  }
546 
547 #ifdef _DEBUG
548  if (com_debug_break && com_debug_break->integer) {
549  Sys_DebugBreak();
550  }
551 #endif
552 
553  // make otherwise non-fatal errors fatal
554  if (com_fatal_error && com_fatal_error->integer) {
555  code = ERR_FATAL;
556  }
557 
558  if (code == ERR_DROP) {
559  Com_EPrintf("********************\n"
560  "ERROR: %s\n"
561  "********************\n", com_errorMsg);
562  SV_Shutdown(va("Server crashed: %s\n", com_errorMsg), ERR_DROP);
563  CL_Disconnect(ERR_DROP);
564  goto abort;
565  }
566 
567  if (com_logFile) {
568  FS_FPrintf(com_logFile, "FATAL: %s\n", com_errorMsg);
569  }
570 
571  SV_Shutdown(va("Server fatal crashed: %s\n", com_errorMsg), ERR_FATAL);
572  CL_Shutdown();
573  NET_Shutdown();
574  logfile_close();
575  FS_Shutdown();
576 
577  Sys_Error("%s", com_errorMsg);
578  // doesn't get there
579 
580 abort:
581  if (com_logFile) {
583  }
584  com_errorEntered = qfalse;
585  longjmp(com_abortframe, -1);
586 }
587 
588 void Com_AbortFunc(void (*func)(void *), void *arg)
589 {
590  com_abort_func = func;
591  com_abort_arg = arg;
592 }
593 
594 #ifdef _WIN32
595 void Com_AbortFrame(void)
596 {
597  longjmp(com_abortframe, -1);
598 }
599 #endif
600 
601 /*
602 =============
603 Com_Quit
604 
605 Both client and server can use this, and it will
606 do the apropriate things. This function never returns.
607 =============
608 */
609 void Com_Quit(const char *reason, error_type_t type)
610 {
611  char buffer[MAX_STRING_CHARS];
612  char *what = type == ERR_RECONNECT ? "restarted" : "quit";
613 
614  if (reason && *reason) {
615  Q_snprintf(buffer, sizeof(buffer),
616  "Server %s: %s\n", what, reason);
617  } else {
618  Q_snprintf(buffer, sizeof(buffer),
619  "Server %s\n", what);
620  }
621 
622  SV_Shutdown(buffer, type);
623  CL_Shutdown();
624  NET_Shutdown();
625  logfile_close();
626  FS_Shutdown();
627 
628  Sys_Quit();
629  // doesn't get there
630 }
631 
632 static void Com_Quit_f(void)
633 {
634  Com_Quit(Cmd_Args(), ERR_DISCONNECT);
635 }
636 
637 #if !USE_CLIENT
638 static void Com_Recycle_f(void)
639 {
640  Com_Quit(Cmd_Args(), ERR_RECONNECT);
641 }
642 #endif
643 
644 /*
645 ==============================================================================
646 
647  INIT / SHUTDOWN
648 
649 ==============================================================================
650 */
651 
652 size_t Com_Time_m(char *buffer, size_t size)
653 {
654  return format_local_time(buffer, size, com_time_format->string);
655 }
656 
657 static size_t Com_Date_m(char *buffer, size_t size)
658 {
659  return format_local_time(buffer, size, com_date_format->string);
660 }
661 
662 size_t Com_Uptime_m(char *buffer, size_t size)
663 {
664  return Com_TimeDiff(buffer, size, &com_startTime, time(NULL));
665 }
666 
667 size_t Com_UptimeLong_m(char *buffer, size_t size)
668 {
669  return Com_TimeDiffLong(buffer, size, &com_startTime, time(NULL));
670 }
671 
672 static size_t Com_Random_m(char *buffer, size_t size)
673 {
674  return Q_scnprintf(buffer, size, "%d", rand_byte() % 10);
675 }
676 
677 static size_t Com_MapList_m(char *buffer, size_t size)
678 {
679  int i, numFiles;
680  void **list;
681  char *s, *p;
682  size_t len, total = 0;
683 
684  list = FS_ListFiles("maps", ".bsp", 0, &numFiles);
685  for (i = 0; i < numFiles; i++) {
686  s = list[i];
687  p = COM_FileExtension(list[i]);
688  *p = 0;
689  len = strlen(s);
690  if (total + len + 1 < size) {
691  memcpy(buffer + total, s, len);
692  buffer[total + len] = ' ';
693  total += len + 1;
694  }
695  Z_Free(s);
696  }
697  buffer[total] = 0;
698 
699  Z_Free(list);
700  return total;
701 }
702 
703 static void Com_LastError_f(void)
704 {
705  Com_Printf("%s\n", com_errorMsg);
706 }
707 
708 #if 0
709 static void Com_Setenv_f(void)
710 {
711  int argc = Cmd_Argc();
712 
713  if (argc > 2) {
715  } else if (argc == 2) {
716  char *env = getenv(Cmd_Argv(1));
717 
718  if (env) {
719  Com_Printf("%s=%s\n", Cmd_Argv(1), env);
720  } else {
721  Com_Printf("%s undefined\n", Cmd_Argv(1));
722  }
723  } else {
724  Com_Printf("Usage: %s <name> [value]\n", Cmd_Argv(0));
725  }
726 }
727 #endif
728 
729 void Com_Address_g(genctx_t *ctx)
730 {
731  int i;
732  cvar_t *var;
733 
734  for (i = 0; i < 1024; i++) {
735  var = Cvar_FindVar(va("adr%d", i));
736  if (!var) {
737  break;
738  }
739  if (!var->string[0]) {
740  continue;
741  }
742  if (!Prompt_AddMatch(ctx, var->string)) {
743  break;
744  }
745  }
746 }
747 
748 void Com_Generic_c(genctx_t *ctx, int argnum)
749 {
750  xcompleter_t c;
751  xgenerator_t g;
752  cvar_t *var;
753  char *s;
754 
755  // complete command, alias or cvar name
756  if (!argnum) {
757  Cmd_Command_g(ctx);
758  Cvar_Variable_g(ctx);
759  Cmd_Alias_g(ctx);
760  return;
761  }
762 
763  // protect against possible duplicates
764  ctx->ignoredups = qtrue;
765 
766  s = Cmd_Argv(ctx->argnum - argnum);
767 
768  // complete command argument or cvar value
769  if ((c = Cmd_FindCompleter(s)) != NULL) {
770  c(ctx, argnum);
771  } else if (argnum == 1 && (var = Cvar_FindVar(s)) != NULL) {
772  g = var->generator;
773  if (g) {
774  ctx->data = var;
775  g(ctx);
776  }
777  }
778 }
779 
780 #if USE_CLIENT
781 void Com_Color_g(genctx_t *ctx)
782 {
783  int color;
784 
785  for (color = 0; color < 8; color++) {
786  if (!Prompt_AddMatch(ctx, colorNames[color])) {
787  break;
788  }
789  }
790 }
791 #endif
792 
793 /*
794 ===============
795 Com_AddEarlyCommands
796 
797 Adds command line parameters as script statements.
798 Commands lead with a +, and continue until another +
799 
800 Set commands are added early, so they are guaranteed to be set before
801 the client and server initialize for the first time.
802 
803 Other commands are added late, after all initialization is complete.
804 ===============
805 */
806 static void Com_AddEarlyCommands(qboolean clear)
807 {
808  int i;
809  char *s;
810 
811  for (i = 1; i < com_argc; i++) {
812  s = com_argv[i];
813  if (!s) {
814  continue;
815  }
816  if (strcmp(s, "+set")) {
817  continue;
818  }
819  if (i + 2 >= com_argc) {
820  Com_Printf("Usage: +set <variable> <value>\n");
821  com_argc = i;
822  break;
823  }
824  Cvar_SetEx(com_argv[i + 1], com_argv[i + 2], FROM_CMDLINE);
825  if (clear) {
826  com_argv[i] = com_argv[i + 1] = com_argv[i + 2] = NULL;
827  }
828  i += 2;
829  }
830 }
831 
832 /*
833 =================
834 Com_AddLateCommands
835 
836 Adds command line parameters as script statements
837 Commands lead with a + and continue until another +
838 
839 Returns qtrue if any late commands were added, which
840 will keep the demoloop from immediately starting
841 
842 Assumes +set commands are already filtered out
843 =================
844 */
845 static qboolean Com_AddLateCommands(void)
846 {
847  int i;
848  char *s;
849  qboolean ret = qfalse;
850 
851  for (i = 1; i < com_argc; i++) {
852  s = com_argv[i];
853  if (!s) {
854  continue;
855  }
856  if (*s == '+') {
857  if (ret) {
858  Cbuf_AddText(&cmd_buffer, "\n");
859  }
860  s++;
861  } else if (ret) {
862  Cbuf_AddText(&cmd_buffer, " ");
863  }
865  ret = qtrue;
866  }
867 
868  if (ret) {
869  Cbuf_AddText(&cmd_buffer, "\n");
871  }
872 
873  return ret;
874 }
875 
876 void Com_AddConfigFile(const char *name, unsigned flags)
877 {
878  qerror_t ret;
879 
880  ret = Cmd_ExecuteFile(name, flags);
881  if (ret == Q_ERR_SUCCESS) {
883  } else if (ret != Q_ERR_NOENT) {
884  Com_WPrintf("Couldn't exec %s: %s\n", name, Q_ErrorString(ret));
885  }
886 }
887 
888 /*
889 =================
890 Qcommon_Init
891 =================
892 */
893 void Qcommon_Init(int argc, char **argv)
894 {
895  if (setjmp(com_abortframe))
896  Sys_Error("Error during initialization: %s", com_errorMsg);
897 
898  com_argc = argc;
899  com_argv = argv;
900 
901  Com_SetLastError(NULL);
902 
903  X86_SetFPCW();
904 
905  srand(time(NULL));
906 
907  // prepare enough of the subsystems to handle
908  // cvar and command buffer management
909  Z_Init();
910  MSG_Init();
911  Cbuf_Init();
912  Cmd_Init();
913  Cvar_Init();
914  Key_Init();
915  Prompt_Init();
916  Con_Init();
917 
918  //
919  // init commands and vars
920  //
921  z_perturb = Cvar_Get("z_perturb", "0", 0);
922 #if USE_CLIENT
923  host_speeds = Cvar_Get("host_speeds", "0", 0);
924 #endif
925 #ifdef _DEBUG
926  developer = Cvar_Get("developer", "0", 0);
927 #endif
928  timescale = Cvar_Get("timescale", "1", CVAR_CHEAT);
929  fixedtime = Cvar_Get("fixedtime", "0", CVAR_CHEAT);
930  logfile_enable = Cvar_Get("logfile", "1", 0);
931  logfile_flush = Cvar_Get("logfile_flush", "1", 0);
932  logfile_name = Cvar_Get("logfile_name", "console", 0);
933  logfile_prefix = Cvar_Get("logfile_prefix", "[%Y-%m-%d %H:%M] ", 0);
934 #if USE_CLIENT
935  dedicated = Cvar_Get("dedicated", "0", CVAR_NOSET);
936  backdoor = Cvar_Get("backdoor", "0", CVAR_ARCHIVE);
937  cl_running = Cvar_Get("cl_running", "0", CVAR_ROM);
938  cl_paused = Cvar_Get("cl_paused", "0", CVAR_ROM);
939 #else
940  dedicated = Cvar_Get("dedicated", "1", CVAR_ROM);
941 #endif
942  sv_running = Cvar_Get("sv_running", "0", CVAR_ROM);
943  sv_paused = Cvar_Get("sv_paused", "0", CVAR_ROM);
944  com_timedemo = Cvar_Get("timedemo", "0", CVAR_CHEAT);
945  com_date_format = Cvar_Get("com_date_format", "%Y-%m-%d", 0);
946 #ifdef _WIN32
947  com_time_format = Cvar_Get("com_time_format", "%H.%M", 0);
948 #else
949  com_time_format = Cvar_Get("com_time_format", "%H:%M", 0);
950 #endif
951 #ifdef _DEBUG
952  com_debug_break = Cvar_Get("com_debug_break", "0", 0);
953 #endif
954  com_fatal_error = Cvar_Get("com_fatal_error", "0", 0);
955  com_version = Cvar_Get("version", com_version_string, CVAR_SERVERINFO | CVAR_USERINFO | CVAR_ROM);
956 
957  allow_download = Cvar_Get("allow_download", COM_DEDICATED ? "0" : "1", CVAR_ARCHIVE);
958  allow_download_players = Cvar_Get("allow_download_players", "1", CVAR_ARCHIVE);
959  allow_download_models = Cvar_Get("allow_download_models", "1", CVAR_ARCHIVE);
960  allow_download_sounds = Cvar_Get("allow_download_sounds", "1", CVAR_ARCHIVE);
961  allow_download_maps = Cvar_Get("allow_download_maps", "1", CVAR_ARCHIVE);
962  allow_download_textures = Cvar_Get("allow_download_textures", "1", CVAR_ARCHIVE);
963  allow_download_pics = Cvar_Get("allow_download_pics", "1", CVAR_ARCHIVE);
964  allow_download_others = Cvar_Get("allow_download_others", "0", 0);
965 
966  rcon_password = Cvar_Get("rcon_password", "", CVAR_ARCHIVE);
967 
968  Cmd_AddCommand("z_stats", Z_Stats_f);
969 
970  //Cmd_AddCommand("setenv", Com_Setenv_f);
971 
972  Cmd_AddMacro("com_date", Com_Date_m);
973  Cmd_AddMacro("com_time", Com_Time_m);
974  Cmd_AddMacro("com_uptime", Com_Uptime_m);
975  Cmd_AddMacro("com_uptime_long", Com_UptimeLong_m);
976  Cmd_AddMacro("random", Com_Random_m);
977  Cmd_AddMacro("com_maplist", Com_MapList_m);
978 
979  // add any system-wide configuration files
981 
982  // we need to add the early commands twice, because
983  // a basedir or cddir needs to be set before execing
984  // config files, but we want other parms to override
985  // the settings of the config files
986  Com_AddEarlyCommands(qfalse);
987 
988  Sys_Init();
989 
990  Sys_RunConsole();
991 
992  FS_Init();
993 
994  Sys_RunConsole();
995 
996  // no longer allow CVAR_NOSET modifications
997  com_initialized = qtrue;
998 
999  // after FS is initialized, open logfile
1004 
1005  // execute configs: default.cfg and q2rtx.cfg may come from the packfile, but config.cfg
1006  // and autoexec.cfg must be real files within the game directory
1007  Com_AddConfigFile(COM_DEFAULT_CFG, 0);
1008  Com_AddConfigFile(COM_Q2RTX_CFG, 0);
1009  Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME);
1010  Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_GAME);
1011  Com_AddConfigFile(COM_POSTEXEC_CFG, FS_TYPE_REAL);
1012 
1013  Com_AddEarlyCommands(qtrue);
1014 
1015  Cmd_AddCommand("lasterror", Com_LastError_f);
1016 
1017  Cmd_AddCommand("quit", Com_Quit_f);
1018 #if !USE_CLIENT
1019  Cmd_AddCommand("recycle", Com_Recycle_f);
1020 #endif
1021 
1022  Netchan_Init();
1023  NET_Init();
1024  BSP_Init();
1025  CM_Init();
1026  SV_Init();
1027  CL_Init();
1028  TST_Init();
1029 
1030  Sys_RunConsole();
1031 
1032  // add + commands from command line
1033  if (!Com_AddLateCommands()) {
1034  // if the user didn't give any commands, run default action
1035  char *cmd = COM_DEDICATED ? "dedicated_start" : "client_start";
1036 
1037  if ((cmd = Cmd_AliasCommand(cmd)) != NULL) {
1038  Cbuf_AddText(&cmd_buffer, cmd);
1040  }
1041  } else {
1042  // the user asked for something explicit
1043  // so drop the loading plaque
1045  }
1046 
1047  // even not given a starting map, dedicated server starts
1048  // listening for rcon commands (create socket after all configs
1049  // are executed to make sure port number is properly set)
1050  if (COM_DEDICATED || backdoor->integer) {
1051  NET_Config(NET_SERVER);
1052  }
1053 
1054  Com_AddConfigFile(COM_POSTINIT_CFG, FS_TYPE_REAL);
1055 
1056  Com_Printf("====== " PRODUCT " initialized ======\n\n");
1057  Com_LPrintf(PRINT_NOTICE, APPLICATION " " VERSION_STRING ", " __DATE__ "\n");
1058 
1059  if (fs_shareware->integer)
1060  {
1061  char* newgame = Cmd_AliasCommand("newgame");
1062  if (!strstr(newgame, "demo1"))
1063  {
1064  Com_WPrintf("\nWARNING: It looks like you have mixed game data files (.pak) from the shareware demo and the full game. The game might not function properly.\n\n");
1065  }
1066  }
1067 
1068  time(&com_startTime);
1069 
1071 }
1072 
1073 /*
1074 =================
1075 Qcommon_Frame
1076 =================
1077 */
1078 void Qcommon_Frame(void)
1079 {
1080 #if USE_CLIENT
1081  unsigned time_before, time_event, time_between, time_after;
1082  unsigned clientrem;
1083 #endif
1084  unsigned oldtime, msec;
1085  static unsigned remaining;
1086  static float frac;
1087 
1088  if (setjmp(com_abortframe)) {
1089  return; // an ERR_DROP was thrown
1090  }
1091 
1092 #if USE_CLIENT
1093  time_before = time_event = time_between = time_after = 0;
1094 
1095  if (host_speeds->integer)
1096  time_before = Sys_Milliseconds();
1097 #endif
1098 
1099  // sleep on network sockets when running a dedicated server
1100  // still do a select(), but don't sleep when running a client!
1101  NET_Sleep(remaining);
1102 
1103  // calculate time spent running last frame and sleeping
1104  oldtime = com_eventTime;
1106  if (oldtime > com_eventTime) {
1107  oldtime = com_eventTime;
1108  }
1109  msec = com_eventTime - oldtime;
1110 
1111 #if USE_CLIENT
1112  // spin until msec is non-zero if running a client
1113  if (!dedicated->integer && !com_timedemo->integer) {
1114  while (msec < 1) {
1115  qboolean break_now = CL_ProcessEvents();
1117  msec = com_eventTime - oldtime;
1118  if (break_now)
1119  break;
1120  }
1121  }
1122 #endif
1123 
1124  if (msec > 250) {
1125  Com_DPrintf("Hitch warning: %u msec frame time\n", msec);
1126  msec = 100; // time was unreasonable,
1127  // host OS was hibernated or something
1128  }
1129 
1130  if (fixedtime->integer) {
1131  Cvar_ClampInteger(fixedtime, 1, 1000);
1132  msec = fixedtime->integer;
1133  } else if (timescale->value > 0) {
1134  frac += msec * timescale->value;
1135  msec = frac;
1136  frac -= msec;
1137  }
1138 
1139  // run local time
1140  com_localTime += msec;
1141  com_framenum++;
1142 
1143 #if USE_CLIENT
1144  if (host_speeds->integer)
1145  time_event = Sys_Milliseconds();
1146 #endif
1147 
1148  // run system console
1149  Sys_RunConsole();
1150 
1151  NET_UpdateStats();
1152 
1153  remaining = SV_Frame(msec);
1154 
1155 #if USE_CLIENT
1156  if (host_speeds->integer)
1157  time_between = Sys_Milliseconds();
1158 
1159  clientrem = CL_Frame(msec);
1160  if (remaining > clientrem) {
1161  remaining = clientrem;
1162  }
1163 
1164  if (host_speeds->integer)
1165  time_after = Sys_Milliseconds();
1166 
1167  if (host_speeds->integer) {
1168  int all, ev, sv, gm, cl, rf;
1169 
1170  all = time_after - time_before;
1171  ev = time_event - time_before;
1172  sv = time_between - time_event;
1173  cl = time_after - time_between;
1174  gm = time_after_game - time_before_game;
1175  rf = time_after_ref - time_before_ref;
1176  sv -= gm;
1177  cl -= rf;
1178 
1179  Com_Printf("all:%3i ev:%3i sv:%3i gm:%3i cl:%3i rf:%3i\n",
1180  all, ev, sv, gm, cl, rf);
1181  }
1182 #endif
1183 }
1184 
CL_Shutdown
void CL_Shutdown(void)
Definition: main.c:3471
Cmd_Alias_g
void Cmd_Alias_g(genctx_t *ctx)
Definition: cmd.c:288
logfile_flush
cvar_t * logfile_flush
Definition: common.c:87
rd_buffersize
static size_t rd_buffersize
Definition: common.c:147
SV_Shutdown
void SV_Shutdown(const char *finalmsg, error_type_t type)
Definition: main.c:2252
Cmd_ExecuteFile
qerror_t Cmd_ExecuteFile(const char *path, unsigned flags)
Definition: cmd.c:1710
dedicated
cvar_t * dedicated
Definition: common.c:82
Cvar_Set
cvar_t * Cvar_Set(const char *var_name, const char *value)
Definition: cvar.c:466
FS_EasyOpenFile
qhandle_t FS_EasyOpenFile(char *buf, size_t size, unsigned mode, const char *dir, const char *name, const char *ext)
Definition: files.c:1846
com_initialized
qboolean com_initialized
Definition: common.c:124
NET_Init
void NET_Init(void)
Definition: net.c:1933
Com_TimeDiff
size_t Com_TimeDiff(char *buffer, size_t size, time_t *p, time_t now)
Definition: utils.c:443
com_errorEntered
static qboolean com_errorEntered
Definition: common.c:64
Com_LastError_f
static void Com_LastError_f(void)
Definition: common.c:703
allow_download_players
cvar_t * allow_download_players
Definition: common.c:106
Com_AddConfigFile
void Com_AddConfigFile(const char *name, unsigned flags)
Definition: common.c:876
Com_AbortFrame
void Com_AbortFrame(void)
Definition: common.c:595
logfile_name
cvar_t * logfile_name
Definition: common.c:88
Qcommon_Frame
void Qcommon_Frame(void)
Definition: common.c:1078
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
Cmd_FindCompleter
xcompleter_t Cmd_FindCompleter(const char *name)
Definition: cmd.c:1627
CL_ProcessEvents
qboolean CL_ProcessEvents(void)
Definition: main.c:3384
Netchan_Init
void Netchan_Init(void)
Definition: chan.c:116
Cmd_AddCommand
void Cmd_AddCommand(const char *name, xcommand_t function)
Definition: cmd.c:1562
Cmd_Command_g
void Cmd_Command_g(genctx_t *ctx)
Definition: cmd.c:1634
com_printEntered
static int com_printEntered
Definition: common.c:67
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
Cbuf_Init
void Cbuf_Init(void)
Definition: cmd.c:79
colorNames
const char *const colorNames[10]
Definition: utils.c:190
Com_AbortFunc
void Com_AbortFunc(void(*func)(void *), void *arg)
Definition: common.c:588
Com_Recycle_f
static void Com_Recycle_f(void)
Definition: common.c:638
FS_FPrintf
ssize_t FS_FPrintf(qhandle_t f, const char *format,...)
Definition: files.c:2039
com_fatal_error
cvar_t * com_fatal_error
Definition: common.c:103
com_abort_func
static void(* com_abort_func)(void *)
Definition: common.c:61
Com_Time_m
size_t Com_Time_m(char *buffer, size_t size)
Definition: common.c:652
com_errorMsg
static char com_errorMsg[MAXERRORMSG]
Definition: common.c:65
sv_paused
cvar_t * sv_paused
Definition: common.c:96
Q_setenv
void Q_setenv(const char *name, const char *value)
Definition: shared.c:909
Cmd_Args
char * Cmd_Args(void)
Definition: cmd.c:933
Com_Quit_f
static void Com_Quit_f(void)
Definition: common.c:632
logfile_param_changed
static void logfile_param_changed(cvar_t *self)
Definition: common.c:251
com_time_format
cvar_t * com_time_format
Definition: common.c:99
Key_Init
void Key_Init(void)
Definition: keys.c:520
Com_LPrintf
void Com_LPrintf(print_type_t type, const char *fmt,...)
Definition: common.c:404
SCR_EndLoadingPlaque
void SCR_EndLoadingPlaque(void)
Definition: screen.c:1456
logfile_enable_changed
static void logfile_enable_changed(cvar_t *self)
Definition: common.c:243
Sys_AddDefaultConfig
void Sys_AddDefaultConfig(void)
Definition: system.c:649
BSP_Init
void BSP_Init(void)
Definition: bsp.c:1477
com_timedemo
cvar_t * com_timedemo
Definition: common.c:97
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
Sys_Milliseconds
unsigned Sys_Milliseconds(void)
Definition: system.c:644
Sys_Error
void Sys_Error(const char *error,...)
Definition: system.c:574
CL_Disconnect
void CL_Disconnect(error_type_t type)
Definition: main.c:740
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
Prompt_AddMatch
qboolean Prompt_AddMatch(genctx_t *ctx, const char *s)
Definition: prompt.c:149
Z_Stats_f
void Z_Stats_f(void)
Definition: zone.c:229
logfile_write
static void logfile_write(print_type_t type, const char *s)
Definition: common.c:288
cmd_buffer
cmdbuf_t cmd_buffer
Definition: cmd.c:49
rcon_password
cvar_t * rcon_password
Definition: common.c:114
Com_Generic_c
void Com_Generic_c(genctx_t *ctx, int argnum)
Definition: common.c:748
Con_Init
void Con_Init(void)
Definition: console.c:436
Cmd_ArgsFrom
char * Cmd_ArgsFrom(int from)
Definition: cmd.c:981
com_version
cvar_t * com_version
Definition: common.c:84
com_startTime
time_t com_startTime
Definition: common.c:125
Cvar_Variable_g
void Cvar_Variable_g(genctx_t *ctx)
Definition: cvar.c:133
backdoor
cvar_t * backdoor
Definition: common.c:83
allow_download_maps
cvar_t * allow_download_maps
Definition: common.c:109
allow_download_textures
cvar_t * allow_download_textures
Definition: common.c:110
z_perturb
cvar_t * z_perturb
Definition: common.c:75
com_date_format
cvar_t * com_date_format
Definition: common.c:98
com_argc
static int com_argc
Definition: common.c:73
sv
server_t sv
Definition: init.c:22
com_argv
static char ** com_argv
Definition: common.c:72
Com_Error
void Com_Error(error_type_t code, const char *fmt,...)
Definition: common.c:496
Com_EndRedirect
void Com_EndRedirect(void)
Definition: common.c:172
Cbuf_AddText
void Cbuf_AddText(cmdbuf_t *buf, const char *text)
Definition: cmd.c:95
va
char * va(const char *format,...)
Definition: shared.c:429
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
FS_Init
void FS_Init(void)
Definition: files.c:3714
Con_Print
void Con_Print(const char *txt)
Definition: console.c:557
fs_shareware
cvar_t * fs_shareware
Definition: files.c:204
format_local_time
static size_t format_local_time(char *buffer, size_t size, const char *fmt)
Definition: common.c:259
logfile_close
static void logfile_close(void)
Definition: common.c:204
FS_ListFiles
void ** FS_ListFiles(const char *path, const char *filter, unsigned flags, int *count_p)
Definition: files.c:2716
Com_Address_g
void Com_Address_g(genctx_t *ctx)
Definition: common.c:729
Com_MapList_m
static size_t Com_MapList_m(char *buffer, size_t size)
Definition: common.c:677
com_logFile
static qhandle_t com_logFile
Definition: common.c:69
timescale
cvar_t * timescale
Definition: common.c:80
TST_Init
void TST_Init(void)
Definition: tests.c:527
Com_TimeDiffLong
size_t Com_TimeDiffLong(char *buffer, size_t size, time_t *p, time_t now)
Definition: utils.c:454
void
void(APIENTRY *qwglDrawBuffer)(GLenum mode)
NET_Config
void NET_Config(netflag_t flag)
Definition: net.c:1312
Q_strlcpy
size_t Q_strlcpy(char *dst, const char *src, size_t size)
Definition: shared.c:715
Com_Random_m
static size_t Com_Random_m(char *buffer, size_t size)
Definition: common.c:672
Com_GetLastError
char * Com_GetLastError(void)
Definition: common.c:391
logfile_enable
cvar_t * logfile_enable
Definition: common.c:86
rd_target
static int rd_target
Definition: common.c:145
Cmd_AliasCommand
char * Cmd_AliasCommand(const char *name)
Definition: cmd.c:251
CM_Init
void CM_Init(void)
Definition: cmodel.c:1102
MSG_Init
void MSG_Init(void)
Definition: msg.c:57
CL_Init
void CL_Init(void)
Definition: main.c:3414
FS_Shutdown
void FS_Shutdown(void)
Definition: files.c:3614
Cmd_Init
void Cmd_Init(void)
Definition: cmd.c:2046
com_localTime
unsigned com_localTime
Definition: common.c:123
Com_UptimeLong_m
size_t Com_UptimeLong_m(char *buffer, size_t size)
Definition: common.c:667
cl
client_state_t cl
Definition: main.c:99
FS_Write
ssize_t FS_Write(const void *buf, size_t len, qhandle_t f)
Definition: files.c:1643
com_version_string
const char com_version_string[]
Definition: common.c:118
allow_download_sounds
cvar_t * allow_download_sounds
Definition: common.c:108
CL_Frame
unsigned CL_Frame(unsigned msec)
Definition: main.c:3204
FS_Flush
void FS_Flush(qhandle_t f)
Definition: files.c:1617
c
statCounters_t c
Definition: main.c:30
allow_download_others
cvar_t * allow_download_others
Definition: common.c:112
Cvar_Init
void Cvar_Init(void)
Definition: cvar.c:1169
Z_Init
void Z_Init(void)
Definition: zone.c:392
Com_AbortRedirect
static void Com_AbortRedirect(void)
Definition: common.c:163
Com_Date_m
static size_t Com_Date_m(char *buffer, size_t size)
Definition: common.c:657
com_logNewline
static qboolean com_logNewline
Definition: common.c:70
NET_Shutdown
void NET_Shutdown(void)
Definition: net.c:1986
rd_flush
static rdflush_t rd_flush
Definition: common.c:149
Com_Quit
void Com_Quit(const char *reason, error_type_t type)
Definition: common.c:609
Cvar_ClampInteger
int Cvar_ClampInteger(cvar_t *var, int min, int max)
Definition: cvar.c:549
Prompt_Init
void Prompt_Init(void)
Definition: prompt.c:621
com_abort_arg
static void * com_abort_arg
Definition: common.c:62
SV_Init
void SV_Init(void)
Definition: main.c:2064
rd_buffer
static char * rd_buffer
Definition: common.c:146
Com_SetLastError
void Com_SetLastError(const char *msg)
Definition: common.c:382
Com_Uptime_m
size_t Com_Uptime_m(char *buffer, size_t size)
Definition: common.c:662
Q_vscnprintf
size_t Q_vscnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
Definition: shared.c:823
Com_SetColor
void Com_SetColor(color_index_t color)
Definition: common.c:373
allow_download_pics
cvar_t * allow_download_pics
Definition: common.c:111
Cbuf_Execute
void Cbuf_Execute(cmdbuf_t *buf)
Definition: cmd.c:152
client.h
allow_download
cvar_t * allow_download
Definition: common.c:105
Com_AddEarlyCommands
static void Com_AddEarlyCommands(qboolean clear)
Definition: common.c:806
msg
const char * msg
Definition: win.h:25
Qcommon_Init
void Qcommon_Init(int argc, char **argv)
Definition: common.c:893
Con_SetColor
void Con_SetColor(color_index_t color)
Definition: console.c:531
Sys_Init
void Sys_Init(void)
Definition: system.c:695
Com_BeginRedirect
void Com_BeginRedirect(int target, char *buffer, size_t buffersize, rdflush_t flush)
Definition: common.c:151
Cmd_AddMacro
void Cmd_AddMacro(const char *name, xmacro_t function)
Definition: cmd.c:770
sv_running
cvar_t * sv_running
Definition: common.c:95
NET_UpdateStats
void NET_UpdateStats(void)
Definition: net.c:472
Cvar_FindVar
cvar_t * Cvar_FindVar(const char *var_name)
Definition: cvar.c:45
color
static vec4_t color
Definition: mesh.c:33
Cvar_SetEx
cvar_t * Cvar_SetEx(const char *var_name, const char *value, from_t from)
Definition: cvar.c:417
FS_FCloseFile
void FS_FCloseFile(qhandle_t f)
Definition: files.c:759
allow_download_models
cvar_t * allow_download_models
Definition: common.c:107
NET_Sleep
int NET_Sleep(int msec)
Definition: net.c:712
Sys_Quit
void Sys_Quit(void)
Definition: system.c:619
fixedtime
cvar_t * fixedtime
Definition: common.c:81
server.h
Com_Redirect
static void Com_Redirect(const char *msg, size_t total)
Definition: common.c:185
COM_FileExtension
char * COM_FileExtension(const char *in)
Definition: shared.c:199
Q_scnprintf
size_t Q_scnprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:867
com_framenum
unsigned com_framenum
Definition: common.c:121
logfile_prefix
cvar_t * logfile_prefix
Definition: common.c:89
SV_Frame
unsigned SV_Frame(unsigned msec)
Definition: main.c:1830
rd_length
static size_t rd_length
Definition: common.c:148
Com_AddLateCommands
static qboolean Com_AddLateCommands(void)
Definition: common.c:845
com_eventTime
unsigned com_eventTime
Definition: common.c:122
com_abortframe
static jmp_buf com_abortframe
Definition: common.c:59
logfile_open
static void logfile_open(void)
Definition: common.c:216
Sys_DebugBreak
void Sys_DebugBreak(void)
Definition: system.c:639