Guest User

host.c

a guest
Mar 5th, 2021
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 25.10 KB | None | 0 0
  1. /*
  2.  * host.c -- coordinates spawning and killing of local servers
  3.  * $Id: host.c 6015 2018-02-21 17:30:51Z sezero $
  4.  *
  5.  * Copyright (C) 1996-1997  Id Software, Inc.
  6.  * Copyright (C) 1997-1998  Raven Software Corp.
  7.  * Copyright (C) 2001 contributors of the Anvil of Thyrion project
  8.  * Copyright (C) 2005-2012  O.Sezer <[email protected]>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or (at
  13.  * your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful, but
  16.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18.  *
  19.  * See the GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License along
  22.  * with this program; if not, write to the Free Software Foundation, Inc.,
  23.  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  24.  */
  25.  
  26. #include "quakedef.h"
  27. #include "cfgfile.h"
  28. #include "debuglog.h"
  29. #include "bgmusic.h"
  30. #include "cdaudio.h"
  31. #include <setjmp.h>
  32.  
  33. /*
  34.  * A server can always be started, even if the system started out as a
  35.  * client to a remote system.
  36.  *
  37.  * A client can NOT be started if the system is started as a dedicated
  38.  * server.
  39.  *
  40.  * Memory is cleared / released when a server or client begins, not when
  41.  * they end.
  42.  */
  43.  
  44. static void Host_WriteConfiguration (const char *fname);
  45.  
  46. quakeparms_t    *host_parms;
  47.  
  48. qboolean    host_initialized;       // true if into command execution
  49.  
  50. static jmp_buf  host_abort;
  51.  
  52. double      host_frametime;
  53. double      realtime;           // without any filtering or bounding
  54. static double   oldrealtime;            // last frame run
  55. int     host_framecount;
  56.  
  57. int     host_hunklevel;
  58.  
  59. client_t    *host_client;           // current client
  60.  
  61. byte        *host_basepal;
  62. byte        *host_colormap;
  63.  
  64. cvar_t      sys_ticrate = {"sys_ticrate", "0.05", CVAR_NONE};
  65. static  cvar_t  sys_adaptive = {"sys_adaptive", "1", CVAR_ARCHIVE};
  66. static  cvar_t  host_framerate = {"host_framerate", "0", CVAR_NONE};    // set for slow motion
  67. static  cvar_t  host_speeds = {"host_speeds", "0", CVAR_NONE};      // set for running times
  68. static  cvar_t  host_maxfps = { "host_maxfps", "72", CVAR_ARCHIVE };
  69.  
  70. static  cvar_t  serverprofile = {"serverprofile", "0", CVAR_NONE};
  71.  
  72. cvar_t  fraglimit = {"fraglimit", "0", CVAR_NOTIFY|CVAR_SERVERINFO};
  73. cvar_t  timelimit = {"timelimit", "0", CVAR_NOTIFY|CVAR_SERVERINFO};
  74. cvar_t  teamplay = {"teamplay", "0", CVAR_NOTIFY|CVAR_SERVERINFO};
  75.  
  76. cvar_t  samelevel = {"samelevel", "0", CVAR_NONE};
  77. cvar_t  noexit = {"noexit", "0", CVAR_NOTIFY|CVAR_SERVERINFO};
  78.  
  79. cvar_t  developer = {"developer", "0", CVAR_ARCHIVE};
  80.  
  81. cvar_t  skill = {"skill", "1", CVAR_NONE};      // 0 - 3
  82. cvar_t  coop = {"coop", "0", CVAR_NONE};        // 0 or 1
  83. cvar_t  deathmatch = {"deathmatch", "0", CVAR_NONE};    // 0, 1, or 2
  84. cvar_t  randomclass = {"randomclass", "0", CVAR_NONE};  // 0, 1, or 2
  85.  
  86. cvar_t  pausable = {"pausable", "1", CVAR_NONE};
  87.  
  88. cvar_t  temp1 = {"temp1", "0", CVAR_NONE};
  89.  
  90.  
  91. /*
  92. ===============================================================================
  93.  
  94. SAVEGAME FILES HANDLING
  95.  
  96. ===============================================================================
  97. */
  98.  
  99. void Host_RemoveGIPFiles (const char *path)
  100. {
  101.     const char  *name;
  102.     char    tempdir[MAX_OSPATH], *p;
  103.     size_t  len;
  104.  
  105.     if (path)
  106.         q_strlcpy(tempdir, path, MAX_OSPATH);
  107.     else    q_strlcpy(tempdir, FS_GetUserdir(), MAX_OSPATH);
  108.  
  109.     len = strlen(tempdir);
  110.     p = tempdir + len;
  111.     len = sizeof(tempdir) - len;
  112.  
  113.     name = Sys_FindFirstFile (tempdir, "*.gip");
  114.     while (name)
  115.     {
  116.         q_snprintf (p, len, "/%s", name);
  117.         Sys_unlink (tempdir);
  118.         *p = '\0';
  119.         name = Sys_FindNextFile();
  120.     }
  121.  
  122.     Sys_FindClose();
  123. }
  124.  
  125. void Host_DeleteSave (const char *savepath)
  126. {
  127.     char    tmppath[MAX_OSPATH];
  128.  
  129.     if (strstr(savepath, FS_GetUserdir()) != savepath)
  130.         return;
  131.  
  132.     Host_RemoveGIPFiles (savepath);
  133.     q_snprintf (tmppath, sizeof(tmppath), "%s/info.dat", savepath);
  134.     Sys_unlink (tmppath);
  135.     Sys_rmdir (savepath);
  136. }
  137.  
  138.  
  139. int Host_CopyFiles (const char *source, const char *pat, const char *dest)
  140. {
  141.     const char  *name;
  142.     char    tempdir[MAX_OSPATH], tempdir2[MAX_OSPATH];
  143.     int error;
  144.  
  145.     name = Sys_FindFirstFile(source, pat);
  146.     error = 0;
  147.  
  148.     while (name)
  149.     {
  150.         if (q_snprintf(tempdir, sizeof(tempdir),"%s/%s", source, name) >= (int)sizeof(tempdir) ||
  151.             q_snprintf(tempdir2, sizeof(tempdir2),"%s/%s", dest, name) >= (int)sizeof(tempdir2))
  152.         {
  153.             Sys_FindClose();
  154.             Host_Error("%s: %d: string buffer overflow!", __thisfunc__, __LINE__);
  155.             return -1;
  156.         }
  157.  
  158.         error = FS_CopyFile (tempdir, tempdir2);
  159.         if (error)
  160.         {
  161.             Con_Printf ("Error copying %s to %s\n", tempdir, tempdir2);
  162.             goto error_out;
  163.         }
  164.  
  165.         name = Sys_FindNextFile();
  166.     }
  167.  
  168. error_out:
  169.     Sys_FindClose();
  170.  
  171.     return error;
  172. }
  173.  
  174.  
  175. //============================================================================
  176.  
  177. /*
  178. ================
  179. Host_EndGame
  180.  
  181. Does not return either due to Sys_Error() or longjmp()
  182. ================
  183. */
  184. void Host_EndGame (const char *message, ...)
  185. {
  186.     va_list     argptr;
  187.     char        string[1024];
  188.  
  189.     va_start (argptr,message);
  190.     q_vsnprintf (string, sizeof(string), message, argptr);
  191.     va_end (argptr);
  192.     Con_DPrintf ("%s: %s\n", __thisfunc__, string);
  193.  
  194.     if (sv.active)
  195.         Host_ShutdownServer (false);
  196.  
  197.     if (cls.state == ca_dedicated)
  198.         Sys_Error ("%s: %s", __thisfunc__, string); // dedicated servers exit
  199.  
  200.     if (cls.demonum != -1)
  201.         CL_NextDemo ();
  202.     else
  203.         CL_Disconnect ();
  204.  
  205.     longjmp (host_abort, 1);
  206. }
  207.  
  208. /*
  209. ================
  210. Host_Error
  211.  
  212. This shuts down both the client and server
  213. Does not return either due to Sys_Error() or longjmp()
  214. ================
  215. */
  216. void Host_Error (const char *error, ...)
  217. {
  218.     va_list     argptr;
  219.     char        string[1024];
  220.     static  qboolean inerror = false;
  221.  
  222.     if (inerror)
  223.         Sys_Error ("%s: recursive error!", __thisfunc__);
  224.     inerror = true;
  225.  
  226.     SCR_EndLoadingPlaque ();        // reenable screen updates
  227.  
  228.     va_start (argptr,error);
  229.     q_vsnprintf (string, sizeof(string), error, argptr);
  230.     va_end (argptr);
  231.     Con_Printf ("%s: %s\n", __thisfunc__, string);
  232.  
  233.     if (sv.active)
  234.         Host_ShutdownServer (false);
  235.  
  236.     if (cls.state == ca_dedicated)
  237.         Sys_Error ("%s: %s", __thisfunc__, string); // dedicated servers exit
  238.  
  239.     CL_Disconnect ();
  240.     cls.demonum = -1;
  241.  
  242.     inerror = false;
  243.  
  244.     longjmp (host_abort, 1);
  245. }
  246.  
  247. /*
  248. ================
  249. Host_FindMaxClients
  250. ================
  251. */
  252. static void Host_FindMaxClients (void)
  253. {
  254.     int     i;
  255.  
  256.     svs.maxclients = 1;
  257.  
  258.     i = COM_CheckParm ("-dedicated");
  259.     if (i)
  260.     {
  261.         cls.state = ca_dedicated;
  262.         if (i != (com_argc - 1))
  263.         {
  264.             svs.maxclients = atoi (com_argv[i+1]);
  265.             if (svs.maxclients < 2)
  266.                 svs.maxclients = 8;
  267.         }
  268.         else
  269.         {
  270.             svs.maxclients = 8;
  271.         }
  272.     }
  273.     else
  274.         cls.state = ca_disconnected;
  275.  
  276.     i = COM_CheckParm ("-listen");
  277.     if (i)
  278.     {
  279.         if (cls.state == ca_dedicated)
  280.             Sys_Error ("Only one of -dedicated or -listen can be specified");
  281.         if (i != (com_argc - 1))
  282.         {
  283.             svs.maxclients = atoi (com_argv[i+1]);
  284.             if (svs.maxclients < 2)
  285.                 svs.maxclients = 8;
  286.         }
  287.         else
  288.         {
  289.             svs.maxclients = 8;
  290.         }
  291.     }
  292.     if (svs.maxclients < 1)
  293.         svs.maxclients = 8;
  294.     else if (svs.maxclients > MAX_CLIENTS)
  295.         svs.maxclients = MAX_CLIENTS;
  296.  
  297.     svs.maxclientslimit = svs.maxclients;
  298.     if (svs.maxclientslimit < 4)
  299.         svs.maxclientslimit = 4;
  300.     svs.clients = (client_t *) Hunk_AllocName (svs.maxclientslimit*sizeof(client_t), "clients");
  301.  
  302.     if (svs.maxclients > 1)
  303.         Cvar_SetQuick (&deathmatch, "1");
  304.     else
  305.         Cvar_SetQuick (&deathmatch, "0");
  306. }
  307.  
  308. /*
  309. ===============
  310. Host_SaveConfig_f
  311. ===============
  312. */
  313. static void Host_SaveConfig_f (void)
  314. {
  315.     const char  *p;
  316.  
  317.     if (cmd_source != src_command)
  318.         return;
  319.  
  320.     if (Cmd_Argc() != 2)
  321.     {
  322.         Con_Printf ("saveConfig <savename> : save a config file\n");
  323.         return;
  324.     }
  325.  
  326.     p = Cmd_Argv(1);
  327.     if (*p == '.' || strstr(p, ".."))
  328.     {
  329.         Con_Printf ("Invalid config name.\n");
  330.         return;
  331.     }
  332.  
  333.     Host_WriteConfiguration (p);
  334. }
  335.  
  336. static void Host_Version_f (void)
  337. {
  338.     Con_Printf ("Version %4.2f\n", ENGINE_VERSION);
  339.     Con_Printf ("Exe: " __TIME__ " " __DATE__ "\n");
  340. }
  341.  
  342. /* cvar callback functions : */
  343. void Host_Callback_Notify (cvar_t *var)
  344. {
  345.     if (sv.active)
  346.         SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string);
  347. }
  348.  
  349. /*
  350. =======================
  351. Host_InitLocal
  352. ======================
  353. */
  354. static void Host_InitLocal (void)
  355. {
  356.     Cmd_AddCommand ("saveconfig", Host_SaveConfig_f);
  357.     Cmd_AddCommand ("version", Host_Version_f);
  358.  
  359.     Host_InitCommands ();
  360.  
  361.     Cvar_RegisterVariable (&developer);
  362.     if (COM_CheckParm("-developer"))
  363.     {
  364.         Cvar_Set ("developer", "1");
  365.         Cvar_LockVar ("developer");
  366.     }
  367.  
  368.     Cvar_RegisterVariable (&sys_nostdout);
  369.     Cvar_RegisterVariable (&sys_throttle);
  370.  
  371.     Cvar_RegisterVariable (&sys_ticrate);
  372.     Cvar_RegisterVariable (&sys_adaptive);
  373.     Cvar_RegisterVariable (&host_maxfps);
  374.     Cvar_RegisterVariable (&host_framerate);
  375.     Cvar_RegisterVariable (&host_speeds);
  376.  
  377.     Cvar_RegisterVariable (&serverprofile);
  378.  
  379.     Cvar_RegisterVariable (&fraglimit);
  380.     Cvar_RegisterVariable (&timelimit);
  381.     Cvar_RegisterVariable (&teamplay);
  382.     Cvar_SetCallback (&fraglimit, Host_Callback_Notify);
  383.     Cvar_SetCallback (&timelimit, Host_Callback_Notify);
  384.     Cvar_SetCallback (&teamplay, Host_Callback_Notify);
  385.     Cvar_RegisterVariable (&samelevel);
  386.     Cvar_RegisterVariable (&noexit);
  387.     Cvar_SetCallback (&noexit, Host_Callback_Notify);
  388.     Cvar_RegisterVariable (&skill);
  389.     Cvar_RegisterVariable (&coop);
  390.     Cvar_RegisterVariable (&deathmatch);
  391.     Cvar_RegisterVariable (&randomclass);
  392.  
  393.     Cvar_RegisterVariable (&pausable);
  394.  
  395.     Cvar_RegisterVariable (&temp1);
  396.  
  397.     Host_FindMaxClients ();
  398. }
  399.  
  400. /*
  401. ===============
  402. Host_WriteConfiguration
  403.  
  404. Writes key bindings and archived cvars to config.cfg
  405. ===============
  406. */
  407. static void Host_WriteConfiguration (const char *fname)
  408. {
  409.     FILE    *f;
  410.  
  411. // dedicated servers initialize the host but don't parse and set the
  412. // config.cfg cvars
  413.     if (host_initialized && !isDedicated && !host_parms->errstate)
  414.     {
  415.         f = fopen (FS_MakePath(FS_USERDIR,NULL,fname), "w");
  416.         if (!f)
  417.         {
  418.             Con_Printf ("Couldn't write %s.\n",fname);
  419.             return;
  420.         }
  421.  
  422.         Key_WriteBindings (f);
  423.         Cvar_WriteVariables (f);
  424.         // if mlook was down, keep it that way:
  425.         if (in_mlook.state & 1)
  426.             fprintf (f, "+mlook\n");
  427.  
  428.         fclose (f);
  429.     }
  430. }
  431.  
  432.  
  433. /*
  434. =================
  435. SV_ClientPrintf
  436.  
  437. Sends text across to be displayed
  438. FIXME: make this just a stuffed echo?
  439. =================
  440. */
  441. void SV_ClientPrintf (unsigned int unused, const char *fmt, ...)
  442. {
  443.     va_list     argptr;
  444.     char        string[1024];
  445.  
  446.     va_start (argptr,fmt);
  447.     q_vsnprintf (string, sizeof (string), fmt, argptr);
  448.     va_end (argptr);
  449.  
  450.     MSG_WriteByte (&host_client->message, svc_print);
  451.     MSG_WriteString (&host_client->message, string);
  452. }
  453.  
  454. /*
  455. =================
  456. SV_BroadcastPrintf
  457.  
  458. Sends text to all active clients
  459. =================
  460. */
  461. void SV_BroadcastPrintf (const char *fmt, ...)
  462. {
  463.     va_list     argptr;
  464.     char        string[1024];
  465.     int         i;
  466.  
  467.     va_start (argptr,fmt);
  468.     q_vsnprintf (string, sizeof (string), fmt, argptr);
  469.     va_end (argptr);
  470.  
  471.     for (i = 0; i < svs.maxclients; i++)
  472.     {
  473.         if (svs.clients[i].active && svs.clients[i].spawned)
  474.         {
  475.             MSG_WriteByte (&svs.clients[i].message, svc_print);
  476.             MSG_WriteString (&svs.clients[i].message, string);
  477.         }
  478.     }
  479. }
  480.  
  481. /*
  482. =================
  483. Host_ClientCommands
  484.  
  485. Send text over to the client to be executed
  486. =================
  487. */
  488. void Host_ClientCommands (const char *fmt, ...)
  489. {
  490.     va_list     argptr;
  491.     char        string[1024];
  492.  
  493.     va_start (argptr,fmt);
  494.     q_vsnprintf (string, sizeof (string), fmt, argptr);
  495.     va_end (argptr);
  496.  
  497.     MSG_WriteByte (&host_client->message, svc_stufftext);
  498.     MSG_WriteString (&host_client->message, string);
  499. }
  500.  
  501. /*
  502. =====================
  503. SV_DropClient
  504.  
  505. Called when the player is getting totally kicked off the host
  506. if (crash = true), don't bother sending signofs
  507. =====================
  508. */
  509. void SV_DropClient (qboolean crash)
  510. {
  511.     int     saveSelf;
  512.     int     i;
  513.     client_t *client;
  514.  
  515.     if (!crash)
  516.     {
  517.         // send any final messages (don't check for errors)
  518.         if (NET_CanSendMessage (host_client->netconnection))
  519.         {
  520.             MSG_WriteByte (&host_client->message, svc_disconnect);
  521.             NET_SendMessage (host_client->netconnection, &host_client->message);
  522.         }
  523.  
  524.         if (host_client->edict && host_client->spawned)
  525.         {
  526.         // call the prog function for removing a client
  527.         // this will set the body to a dead frame, among other things
  528.             saveSelf = *sv_globals.self;
  529.             *sv_globals.self = EDICT_TO_PROG(host_client->edict);
  530.             PR_ExecuteProgram (*sv_globals.ClientDisconnect);
  531.             *sv_globals.self = saveSelf;
  532.         }
  533.  
  534.         Sys_Printf ("Client %s removed\n",host_client->name);
  535.     }
  536.  
  537. // break the net connection
  538.     NET_Close (host_client->netconnection);
  539.     host_client->netconnection = NULL;
  540.  
  541. // free the client (the body stays around)
  542.     host_client->active = false;
  543.     host_client->name[0] = 0;
  544.     host_client->old_frags = -999999;
  545.     memset(&host_client->old_v,0,sizeof(host_client->old_v));
  546.     ED_ClearEdict(host_client->edict);
  547.     host_client->send_all_v = true;
  548.     net_activeconnections--;
  549.  
  550. // send notification to all clients
  551.     for (i = 0, client = svs.clients; i < svs.maxclients; i++, client++)
  552.     {
  553.         if (!client->active)
  554.             continue;
  555.         MSG_WriteByte (&client->message, svc_updatename);
  556.         MSG_WriteByte (&client->message, host_client - svs.clients);
  557.         MSG_WriteString (&client->message, "");
  558.         MSG_WriteByte (&client->message, svc_updatefrags);
  559.         MSG_WriteByte (&client->message, host_client - svs.clients);
  560.         MSG_WriteShort (&client->message, 0);
  561.         MSG_WriteByte (&client->message, svc_updatecolors);
  562.         MSG_WriteByte (&client->message, host_client - svs.clients);
  563.         MSG_WriteByte (&client->message, 0);
  564.     }
  565. }
  566.  
  567. /*
  568. ==================
  569. Host_ShutdownServer
  570.  
  571. This only happens at the end of a game, not between levels
  572. ==================
  573. */
  574. void Host_ShutdownServer(qboolean crash)
  575. {
  576.     int     i;
  577.     int     count;
  578.     sizebuf_t   buf;
  579.     byte        message[4];
  580.     double  start;
  581.  
  582.     if (!sv.active)
  583.         return;
  584.  
  585.     sv.active = false;
  586.  
  587. // stop all client sounds immediately
  588.     if (cls.state == ca_connected)
  589.         CL_Disconnect ();
  590.  
  591. // flush any pending messages - like the score!!!
  592.     start = Sys_DoubleTime();
  593.     do
  594.     {
  595.         count = 0;
  596.         for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
  597.         {
  598.             if (host_client->active && host_client->message.cursize)
  599.             {
  600.                 if (NET_CanSendMessage (host_client->netconnection))
  601.                 {
  602.                     NET_SendMessage(host_client->netconnection, &host_client->message);
  603.                     SZ_Clear (&host_client->message);
  604.                 }
  605.                 else
  606.                 {
  607.                     NET_GetMessage(host_client->netconnection);
  608.                     count++;
  609.                 }
  610.             }
  611.         }
  612.         if ((Sys_DoubleTime() - start) > 3.0)
  613.             break;
  614.     }
  615.     while (count);
  616.  
  617. // make sure all the clients know we're disconnecting
  618.     SZ_Init (&buf, message, sizeof(message));
  619.     MSG_WriteByte(&buf, svc_disconnect);
  620.     count = NET_SendToAll (&buf, 5.0);
  621.     if (count)
  622.         Con_Printf("%s: NET_SendToAll failed for %d clients\n", __thisfunc__, count);
  623.  
  624.     for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
  625.     {
  626.         if (host_client->active)
  627.             SV_DropClient(crash);
  628.     }
  629.  
  630. // clear structures
  631. //  memset (&sv, 0, sizeof(sv)); // ServerSpawn already do this by Host_ClearMemory
  632.     memset (svs.clients, 0, svs.maxclientslimit*sizeof(client_t));
  633. }
  634.  
  635.  
  636. /*
  637. ================
  638. Host_ClearMemory
  639.  
  640. This clears all the memory used by both the client and server, but does
  641. not reinitialize anything.
  642. ================
  643. */
  644. void Host_ClearMemory (void)
  645. {
  646.     Con_DPrintf ("Clearing memory\n");
  647.     D_FlushCaches ();
  648.     Mod_ClearAll ();
  649. /* host_hunklevel MUST be set at this point */
  650.     Hunk_FreeToLowMark (host_hunklevel);
  651.  
  652.     cls.signon = 0;
  653.     memset (&sv, 0, sizeof(sv));
  654.     memset (&cl, 0, sizeof(cl));
  655. }
  656.  
  657.  
  658. //============================================================================
  659.  
  660.  
  661. /*
  662. ===================
  663. Host_FilterTime
  664.  
  665. Returns false if the time is too short to run a frame
  666. ===================
  667. */
  668. static qboolean Host_FilterTime (float time)
  669. {
  670.     realtime += time;
  671.  
  672.     if (!cls.timedemo && realtime - oldrealtime < 1.0/host_maxfps.value)
  673.         return false;       // framerate is too high
  674.  
  675.     host_frametime = realtime - oldrealtime;
  676.     oldrealtime = realtime;
  677.  
  678.     if (host_framerate.value > 0)
  679.         host_frametime = host_framerate.value;
  680.     else
  681.     {   // don't allow really long or short frames
  682.         if (host_frametime > 0.05 && !sys_adaptive.integer)
  683.             host_frametime = 0.05;
  684.         if (host_frametime < 0.001)
  685.             host_frametime = 0.001;
  686.     }
  687.  
  688.     return true;
  689. }
  690.  
  691.  
  692. /*
  693. ===================
  694. Host_GetConsoleCommands
  695.  
  696. Add them exactly as if they had been typed at the console
  697. ===================
  698. */
  699. static void Host_GetConsoleCommands (void)
  700. {
  701.     const char  *cmd;
  702.  
  703.     if (!isDedicated)
  704.         return; // no stdin necessary in graphical mode
  705.  
  706.     while (1)
  707.     {
  708.         cmd = Sys_ConsoleInput ();
  709.         if (!cmd)
  710.             break;
  711.         Cbuf_AddText (cmd);
  712.     }
  713. }
  714.  
  715.  
  716. //#define FPS_20
  717.  
  718. /*
  719. ==================
  720. Host_ServerFrame
  721.  
  722. ==================
  723. */
  724. #ifdef FPS_20
  725.  
  726. static void _Host_ServerFrame (void)
  727. {
  728. // run the world state
  729.     *sv_globals.frametime = host_frametime;
  730.  
  731. // read client messages
  732.     SV_RunClients ();
  733.  
  734. // move things around and think
  735. // always pause in single player if in console or menus
  736.     if (!sv.paused && (svs.maxclients > 1 || Key_GetDest() == key_game))
  737.     {
  738.         SV_Physics ();
  739.  
  740.         R_UpdateParticles ();
  741.         CL_UpdateEffects ();
  742.     }
  743. }
  744.  
  745. static void Host_ServerFrame (void)
  746. {
  747.     float   save_host_frametime;
  748.     float   temp_host_frametime;
  749.  
  750. // run the world state
  751.     *sv_globals.frametime = host_frametime;
  752.  
  753. // set the time and clear the general datagram
  754.     SV_ClearDatagram ();
  755.  
  756. // check for new clients
  757.     SV_CheckForNewClients ();
  758.  
  759.     temp_host_frametime = save_host_frametime = host_frametime;
  760.     while (temp_host_frametime > (1.0/host_maxfps.value))
  761.     {
  762.         if (temp_host_frametime > 0.05)
  763.             host_frametime = 0.05;
  764.         else
  765.             host_frametime = temp_host_frametime;
  766.         temp_host_frametime -= host_frametime;
  767.         _Host_ServerFrame ();
  768.     }
  769.     host_frametime = save_host_frametime;
  770.  
  771. // send all messages to the clients
  772.     SV_SendClientMessages ();
  773. }
  774.  
  775. #else
  776.  
  777. static void Host_ServerFrame (void)
  778. {
  779. // run the world state
  780.     *sv_globals.frametime = host_frametime;
  781.  
  782. // set the time and clear the general datagram
  783.     SV_ClearDatagram ();
  784.  
  785. // check for new clients
  786.     SV_CheckForNewClients ();
  787.  
  788. // read client messages
  789.     SV_RunClients ();
  790.  
  791. // move things around and think
  792. // always pause in single player if in console or menus
  793.     if (!sv.paused && (svs.maxclients > 1 || Key_GetDest() == key_game))
  794.         SV_Physics ();
  795.  
  796. // send all messages to the clients
  797.     SV_SendClientMessages ();
  798. }
  799.  
  800. #endif
  801.  
  802. /*
  803. ==================
  804. Host_Frame
  805.  
  806. Runs all active servers
  807. ==================
  808. */
  809. static void _Host_Frame (float time)
  810. {
  811.     static double       time1 = 0;
  812.     static double       time2 = 0;
  813.     static double       time3 = 0;
  814.     int         pass1, pass2, pass3;
  815. #if !defined(FPS_20)
  816.     double  save_host_frametime,total_host_frametime;
  817. #endif
  818.  
  819.     if (setjmp(host_abort))
  820.         return;         // something bad happened, or the server disconnected
  821.  
  822. // keep the random time dependent
  823.     rand ();
  824.  
  825. // decide the simulation time
  826.     if (!Host_FilterTime (time))
  827.         return;         // don't run too fast, or packets will flood out
  828.  
  829. // get new key events
  830.     Sys_SendKeyEvents ();
  831.  
  832. // allow mice or other external controllers to add commands
  833.     IN_Commands ();
  834.  
  835. // process console commands
  836.     Cbuf_Execute ();
  837.  
  838.     NET_Poll();
  839.  
  840. // if running the server locally, make intentions now
  841.     if (sv.active)
  842.         CL_SendCmd ();
  843.  
  844. //-------------------
  845. //
  846. // server operations
  847. //
  848. //-------------------
  849.  
  850. // check for commands typed to the host
  851.     Host_GetConsoleCommands ();
  852.  
  853. #ifdef FPS_20
  854.     if (sv.active)
  855.         Host_ServerFrame ();
  856.  
  857. //-------------------
  858. //
  859. // client operations
  860. //
  861. //-------------------
  862.  
  863. // if running the server remotely, send intentions now after
  864. // the incoming messages have been read
  865.     if (!sv.active)
  866.         CL_SendCmd ();
  867.  
  868. // fetch results from server
  869.     if (cls.state == ca_connected)
  870.         CL_ReadFromServer ();
  871.  
  872. #else
  873.  
  874.     save_host_frametime = total_host_frametime = host_frametime;
  875.     if (sys_adaptive.integer)
  876.     {
  877.         if (host_frametime > 0.05)
  878.             host_frametime = 0.05;
  879.     }
  880.  
  881.     if (total_host_frametime > 1.0)
  882.         total_host_frametime = 0.05;
  883.  
  884.     do
  885.     {
  886.         if (sv.active)
  887.             Host_ServerFrame ();
  888.  
  889.     //-------------------
  890.     //
  891.     // client operations
  892.     //
  893.     //-------------------
  894.  
  895.     // if running the server remotely, send intentions now after
  896.     // the incoming messages have been read
  897.         if (!sv.active)
  898.             CL_SendCmd ();
  899.  
  900.     // fetch results from server
  901.         if (cls.state == ca_connected)
  902.             CL_ReadFromServer ();
  903.  
  904.         R_UpdateParticles ();
  905.         CL_UpdateEffects ();
  906.  
  907.         if (!sys_adaptive.integer)
  908.             break;
  909.  
  910.         total_host_frametime -= 0.05;
  911.         if (total_host_frametime > 0 && total_host_frametime < 0.05)
  912.         {
  913.             save_host_frametime -= total_host_frametime;
  914.             oldrealtime -= total_host_frametime;
  915.             break;
  916.         }
  917.  
  918.     } while (total_host_frametime > 0);
  919.  
  920.     host_frametime = save_host_frametime;
  921. #endif
  922.  
  923. // update video
  924.     if (host_speeds.integer)
  925.         time1 = Sys_DoubleTime ();
  926.  
  927.     SCR_UpdateScreen ();
  928.  
  929.     if (host_speeds.integer)
  930.         time2 = Sys_DoubleTime ();
  931.  
  932. // update audio
  933.     BGM_Update();   // adds music raw samples and/or advances midi driver
  934.     if (cls.signon == SIGNONS)
  935.     {
  936.         S_Update (r_origin, vpn, vright, vup);
  937.         CL_DecayLights ();
  938.     }
  939.     else
  940.         S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
  941.  
  942.     CDAudio_Update();
  943.  
  944.     if (host_speeds.integer)
  945.     {
  946.         pass1 = (time1 - time3)*1000;
  947.         time3 = Sys_DoubleTime ();
  948.         pass2 = (time2 - time1)*1000;
  949.         pass3 = (time3 - time2)*1000;
  950.         Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n",
  951.                     pass1+pass2+pass3, pass1, pass2, pass3);
  952.     }
  953.  
  954.     host_framecount++;
  955. }
  956.  
  957. void Host_Frame (float time)
  958. {
  959.     double  time1, time2;
  960.     static double   timetotal;
  961.     static int  timecount;
  962.     int     i, c, m;
  963.  
  964.     if (!serverprofile.integer)
  965.     {
  966.         _Host_Frame (time);
  967.         return;
  968.     }
  969.  
  970.     time1 = Sys_DoubleTime ();
  971.     _Host_Frame (time);
  972.     time2 = Sys_DoubleTime ();
  973.  
  974.     timetotal += time2 - time1;
  975.     timecount++;
  976.  
  977.     if (timecount < 1000)
  978.         return;
  979.  
  980.     m = timetotal*1000/timecount;
  981.     timecount = 0;
  982.     timetotal = 0;
  983.     c = 0;
  984.     for (i = 0; i < svs.maxclients; i++)
  985.     {
  986.         if (svs.clients[i].active)
  987.             c++;
  988.     }
  989.  
  990.     Con_Printf ("serverprofile: %2i clients %2i msec\n", c, m);
  991. }
  992.  
  993. //============================================================================
  994.  
  995. /*
  996. ====================
  997. Host_Init
  998. ====================
  999. */
  1000. void Host_Init (void)
  1001. {
  1002.     Sys_Printf ("Host_Init\n");
  1003.  
  1004.     Memory_Init (host_parms->membase, host_parms->memsize);
  1005.     Cbuf_Init ();
  1006.     Cmd_Init ();
  1007.     COM_Init ();
  1008.     SV_Init ();
  1009.     FS_Init ();
  1010.     CL_Cmd_Init ();
  1011.     Host_RemoveGIPFiles(NULL);
  1012.     CFG_OpenConfig ("config.cfg");
  1013.     Host_InitLocal ();
  1014.     PR_Init ();
  1015.     Mod_Init ();
  1016.     NET_Init ();
  1017.  
  1018.     Con_Printf ("Exe: " __TIME__ " " __DATE__ "\n");
  1019.     Con_Printf ("%4.1f megabyte heap\n", host_parms->memsize/(1024*1024.0));
  1020.  
  1021.     R_InitTextures ();      // needed even for dedicated servers
  1022.  
  1023.     if (cls.state != ca_dedicated)  // decided in Host_InitLocal() by calling Host_FindMaxClients()
  1024.     {
  1025.         V_Init ();
  1026.         Chase_Init ();
  1027.         W_LoadWadFile ("gfx.wad");
  1028.         Key_Init ();
  1029.         Con_Init ();
  1030.         M_Init ();
  1031.  
  1032.         host_basepal = (byte *)FS_LoadHunkFile ("gfx/palette.lmp", NULL);
  1033.         if (!host_basepal)
  1034.             Sys_Error ("Couldn't load gfx/palette.lmp");
  1035.  
  1036.         host_colormap = (byte *)FS_LoadHunkFile ("gfx/colormap.lmp", NULL);
  1037.         if (!host_colormap)
  1038.             Sys_Error ("Couldn't load gfx/colormap.lmp");
  1039.  
  1040.         VID_Init (host_basepal);
  1041.         Draw_Init ();
  1042.         SCR_Init ();
  1043.         R_Init ();
  1044.         Sbar_Init();
  1045.  
  1046.         S_Init ();
  1047.         CDAudio_Init();
  1048.         MIDI_Init();
  1049.         BGM_Init();
  1050.  
  1051.         CL_Init();
  1052.         IN_Init();
  1053.     }
  1054.  
  1055.     CFG_CloseConfig();
  1056.  
  1057. #ifdef GLQUAKE
  1058. /* analogous to host_hunklevel, this will mark OpenGL texture
  1059.  * beyond which everything will need to be purged on new map */
  1060.     gl_texlevel = numgltextures;
  1061. #endif
  1062.  
  1063.     Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
  1064.     host_hunklevel = Hunk_LowMark ();
  1065.  
  1066.     host_initialized = true;
  1067.     Con_Printf("\n======== Hexen II Initialized =========\n\n");
  1068.  
  1069. /* execute the hexen.rc file: a valid file runs default.cfg, config.cfg
  1070.  * and autoexec.cfg in this order, then processes the cmdline arguments
  1071.  * by sending "stuffcmds". */
  1072.     if (cls.state != ca_dedicated)
  1073.     {
  1074.         Cbuf_InsertText ("exec hexen.rc\n");
  1075.         if (!setjmp(host_abort))        /* in case exec fails with a longjmp(), e.g. Host_Error() */
  1076.             Cbuf_Execute ();
  1077.     }
  1078.  
  1079.     Cvar_UnlockAll ();              /* unlock the early-set cvars after init */
  1080.  
  1081.     if (cls.state == ca_dedicated)
  1082.     {
  1083.         Cmd_StuffCmds_f ();             /* process command line arguments */
  1084.         Cbuf_Execute ();
  1085.         if (!sv.active)
  1086.             Cbuf_AddText ("map demo1\n");
  1087.     }
  1088. }
  1089.  
  1090. /*
  1091. ===============
  1092. Host_Shutdown
  1093.  
  1094. FIXME: this is a callback from Sys_Quit and Sys_Error.  It would be better
  1095. to run quit through here before the final handoff to the sys code.
  1096. ===============
  1097. */
  1098. void Host_Shutdown(void)
  1099. {
  1100.     static qboolean isdown = false;
  1101.  
  1102.     if (isdown)
  1103.     {
  1104.         printf ("recursive shutdown\n");
  1105.         return;
  1106.     }
  1107.     isdown = true;
  1108.  
  1109. // keep Con_Printf from trying to update the screen
  1110.     scr_disabled_for_loading = true;
  1111.  
  1112.     Host_WriteConfiguration ("config.cfg");
  1113.  
  1114.     NET_Shutdown ();
  1115.  
  1116.     if (cls.state != ca_dedicated)
  1117.     {
  1118.         BGM_Shutdown();
  1119.         CDAudio_Shutdown ();
  1120.         MIDI_Cleanup();
  1121.         S_Shutdown();
  1122.         IN_Shutdown ();
  1123.         VID_Shutdown();
  1124.     }
  1125.  
  1126.     LOG_Close ();
  1127. }
  1128.  
  1129.  
Add Comment
Please, Sign In to add comment