X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=host.c;h=b419f8a963b8c75c55458689ec740051d1e6673d;hb=6fa2a4c4c869043c2b63f96aea7b861fe011e237;hp=a1fc8a578a3c4aa2323c80f58bba0c39c98ee895;hpb=cecffffdd5310e387e8b910735ff77aa329cdb43;p=xonotic%2Fdarkplaces.git diff --git a/host.c b/host.c index a1fc8a57..b419f8a9 100644 --- a/host.c +++ b/host.c @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* -A server can allways be started, even if the system started out as a client +A server can always be started, even if the system started out as a client to a remote system. A client can NOT be started if the system started as a dedicated server. @@ -35,13 +35,16 @@ Memory is cleared / released when a server or client begins, not when they end. quakeparms_t host_parms; qboolean host_initialized; // true if into command execution +qboolean hostloopactive = 0; // LordHavoc: used to turn Host_Error into Sys_Error if Host_Frame has not yet run double host_frametime; -double host_time; +double host_realframetime; // LordHavoc: the real frametime, before slowmo and clamping are applied (used for console scrolling) double realtime; // without any filtering or bounding double oldrealtime; // last frame run int host_framecount; +double sv_frametime; + int host_hunklevel; int minimum_memory; @@ -50,12 +53,11 @@ client_t *host_client; // current client jmp_buf host_abortserver; -byte *host_basepal; -byte *host_colormap; - cvar_t host_framerate = {"host_framerate","0"}; // set for slow motion cvar_t host_speeds = {"host_speeds","0"}; // set for running times cvar_t slowmo = {"slowmo", "1.0"}; // LordHavoc: framerate independent slowmo +cvar_t host_minfps = {"host_minfps", "10"}; // LordHavoc: game logic lower cap on framerate (if framerate is below this is, it pretends it is this, so game logic will run normally) +cvar_t host_maxfps = {"host_maxfps", "1000"}; // LordHavoc: framerate upper cap cvar_t sys_ticrate = {"sys_ticrate","0.05"}; cvar_t serverprofile = {"serverprofile","0"}; @@ -77,6 +79,8 @@ cvar_t pausable = {"pausable","1"}; cvar_t temp1 = {"temp1","0"}; +cvar_t timestamps = {"timestamps", "0", true}; +cvar_t timeformat = {"timeformat", "[%b %e %X] ", true}; /* ================ @@ -114,28 +118,44 @@ Host_Error This shuts down both the client and server ================ */ +char hosterrorstring[4096]; void Host_Error (char *error, ...) { va_list argptr; - char string[1024]; static qboolean inerror = false; - + + // LordHavoc: if host_frame loop has not been run yet, do a Sys_Error instead + if (!hostloopactive) + { + char string[4096]; + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + Sys_Error ("%s", string); + } + if (inerror) - Sys_Error ("Host_Error: recursively entered"); + { + char string[4096]; + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + Sys_Error ("Host_Error: recursively entered (original error was: %s new error is: %s)", hosterrorstring, string); + } inerror = true; - SCR_EndLoadingPlaque (); // reenable screen updates +// SCR_EndLoadingPlaque (); // reenable screen updates va_start (argptr,error); - vsprintf (string,error,argptr); + vsprintf (hosterrorstring,error,argptr); va_end (argptr); - Con_Printf ("Host_Error: %s\n",string); + Con_Printf ("Host_Error: %s\n",hosterrorstring); if (sv.active) Host_ShutdownServer (false); if (cls.state == ca_dedicated) - Sys_Error ("Host_Error: %s\n",string); // dedicated servers exit + Sys_Error ("Host_Error: %s\n",hosterrorstring); // dedicated servers exit CL_Disconnect (); cls.demonum = -1; @@ -209,6 +229,8 @@ void Host_InitLocal (void) Cvar_RegisterVariable (&host_framerate); Cvar_RegisterVariable (&host_speeds); Cvar_RegisterVariable (&slowmo); + Cvar_RegisterVariable (&host_minfps); + Cvar_RegisterVariable (&host_maxfps); Cvar_RegisterVariable (&sys_ticrate); Cvar_RegisterVariable (&serverprofile); @@ -227,9 +249,10 @@ void Host_InitLocal (void) Cvar_RegisterVariable (&temp1); + Cvar_RegisterVariable (×tamps); + Cvar_RegisterVariable (&timeformat); + Host_FindMaxClients (); - - host_time = 1.0; // so a think at time 0 won't get called } @@ -242,13 +265,13 @@ Writes key bindings and archived cvars to config.cfg */ void Host_WriteConfiguration (void) { - FILE *f; + QFile *f; // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized & !isDedicated) { - f = fopen (va("%s/config.cfg",com_gamedir), "w"); + f = Qopen (va("%s/config.cfg",com_gamedir), "w"); if (!f) { Con_Printf ("Couldn't write config.cfg.\n"); @@ -258,7 +281,7 @@ void Host_WriteConfiguration (void) Key_WriteBindings (f); Cvar_WriteVariables (f); - fclose (f); + Qclose (f); } } @@ -352,13 +375,13 @@ void SV_DropClient (qboolean crash) NET_SendMessage (host_client->netconnection, &host_client->message); } - if (host_client->edict && host_client->spawned) + if (sv.active && host_client->edict && host_client->spawned) // LordHavoc: don't call QC if server is dead (avoids recursive Host_Error in some mods when they run out of edicts) { // call the prog function for removing a client // this will set the body to a dead frame, among other things saveSelf = pr_global_struct->self; pr_global_struct->self = EDICT_TO_PROG(host_client->edict); - PR_ExecuteProgram (pr_global_struct->ClientDisconnect); + PR_ExecuteProgram (pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing"); pr_global_struct->self = saveSelf; } @@ -417,7 +440,7 @@ void Host_ShutdownServer(qboolean crash) CL_Disconnect (); // flush any pending messages - like the score!!! - start = Sys_FloatTime(); + start = Sys_DoubleTime(); do { count = 0; @@ -437,7 +460,7 @@ void Host_ShutdownServer(qboolean crash) } } } - if ((Sys_FloatTime() - start) > 3.0) + if ((Sys_DoubleTime() - start) > 3.0) break; } while (count); @@ -474,7 +497,6 @@ not reinitialize anything. void Host_ClearMemory (void) { Con_DPrintf ("Clearing memory\n"); - D_FlushCaches (); Mod_ClearAll (); if (host_hunklevel) Hunk_FreeToLowMark (host_hunklevel); @@ -494,25 +516,45 @@ Host_FilterTime Returns false if the time is too short to run a frame =================== */ -qboolean Host_FilterTime (float time) +qboolean Host_FilterTime (double time) { + double timecap; realtime += time; -// if (!cls.timedemo && realtime - oldrealtime < (1.0 / 72.0)) -// return false; // framerate is too high + if (slowmo.value < 0.0f) + Cvar_SetValue("slowmo", 0.0f); + if (host_minfps.value < 10.0f) + Cvar_SetValue("host_minfps", 10.0f); + if (host_maxfps.value < host_minfps.value) + Cvar_SetValue("host_maxfps", host_minfps.value); - host_frametime = (realtime - oldrealtime) * slowmo.value; // LordHavoc: slowmo cvar + // check if framerate is too high + if (!cls.timedemo) + { + timecap = sys_ticrate.value; + if (cls.state == ca_connected) + timecap = 1.0 / host_maxfps.value; + + if ((realtime - oldrealtime) < timecap) + return false; + } + + host_realframetime = host_frametime = realtime - oldrealtime; // LordHavoc: copy into host_realframetime as well oldrealtime = realtime; + if (cls.timedemo) + return true; // disable time effects + if (host_framerate.value > 0) host_frametime = host_framerate.value; else - { // don't allow really long or short frames - if (host_frametime > 0.1) - host_frametime = 0.1; - if (host_frametime < 0.001) - host_frametime = 0.001; + { + // don't allow really short frames + if (host_frametime > (1.0 / host_minfps.value)) + host_frametime = (1.0 / host_minfps.value); } + + cl.frametime = host_frametime = bound(0, host_frametime * slowmo.value, 0.1f); // LordHavoc: the QC code relies on no less than 10fps return true; } @@ -545,84 +587,17 @@ Host_ServerFrame ================== */ -#ifdef FPS_20 - -void _Host_ServerFrame (void) -{ -// run the world state - pr_global_struct->frametime = host_frametime; - -// read client messages - SV_RunClients (); - -// move things around and think -// always pause in single player if in console or menus - if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) - SV_Physics (); -} - -void Host_ServerFrame (void) -{ - float save_host_frametime; - float temp_host_frametime; - static float host_serverframe_timevalue; - -// run the world state - pr_global_struct->frametime = host_frametime; - -// set the time and clear the general datagram - SV_ClearDatagram (); - -// check for new clients - SV_CheckForNewClients (); - - temp_host_frametime = save_host_frametime = host_frametime; - // LordHavoc: the results of my attempts to mangle this code to process no more than sys_ticrate, - // when I found that was too choppy, I changed it back to processing at least 20fps, - // I consider it a bit of a failure... because I felt a little out of control in singleplayer - // (sliding around) - //if (host_serverframe_timevalue < -0.2) // don't let it get way out of range - // host_serverframe_timevalue = -0.2; - //host_serverframe_timevalue += host_frametime; - // process frames (several if rendering is too slow to run well as a server) - while(temp_host_frametime > 0.0) - { - host_frametime = temp_host_frametime; - if (host_frametime > 0.05) - host_frametime = 0.05; - temp_host_frametime -= host_frametime; - // host_serverframe_timevalue -= host_frametime; - _Host_ServerFrame (); - } - host_frametime = save_host_frametime; - -// send all messages to the clients - SV_SendClientMessages (); -// LordHavoc: sadly, this didn't look good to the person running the server in listen mode - /* -// wait until enough time has built up when the framerate exceeds sys_ticrate - if (host_serverframe_timevalue >= sys_ticrate.value) - //{ - // while(host_serverframe_timevalue >= sys_ticrate.value) - // host_serverframe_timevalue -= sys_ticrate.value; -// send all messages to the clients - SV_SendClientMessages (); - } - */ -} - -#else - -double frametimetotal = 0, lastservertime = 0; void Host_ServerFrame (void) { + static double frametimetotal = 0, lastservertime = 0; frametimetotal += host_frametime; // LordHavoc: cap server at sys_ticrate in listen games if (!isDedicated && svs.maxclients > 1 && ((realtime - lastservertime) < sys_ticrate.value)) return; // run the world state - pr_global_struct->frametime = frametimetotal; + sv.frametime = pr_global_struct->frametime = frametimetotal; frametimetotal = 0; + lastservertime = realtime; // pr_global_struct->frametime = host_frametime; // set the time and clear the general datagram @@ -643,8 +618,6 @@ void Host_ServerFrame (void) SV_SendClientMessages (); } -#endif - /* ================== @@ -662,13 +635,18 @@ void _Host_Frame (float time) if (setjmp (host_abortserver) ) return; // something bad happened, or the server disconnected + hostloopactive = 1; // keep the random time dependent rand (); // decide the simulation time if (!Host_FilterTime (time)) - return; // don't run too fast, or packets will flood out + { + // if time was rejected, don't totally hog the CPU + Sys_Sleep(); + return; + } // get new key events Sys_SendKeyEvents (); @@ -708,22 +686,18 @@ void _Host_Frame (float time) if (!sv.active) CL_SendCmd (); - host_time += host_frametime; - // fetch results from server if (cls.state == ca_connected) - { CL_ReadFromServer (); - } // update video if (host_speeds.value) - time1 = Sys_FloatTime (); + time1 = Sys_DoubleTime (); SCR_UpdateScreen (); if (host_speeds.value) - time2 = Sys_FloatTime (); + time2 = Sys_DoubleTime (); // update audio if (cls.signon == SIGNONS) @@ -738,11 +712,11 @@ void _Host_Frame (float time) if (host_speeds.value) { - pass1 = (time1 - time3)*1000; - time3 = Sys_FloatTime (); - pass2 = (time2 - time1)*1000; - pass3 = (time3 - time2)*1000; - Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n", + pass1 = (time1 - time3)*1000000; + time3 = Sys_DoubleTime (); + pass2 = (time2 - time1)*1000000; + pass3 = (time3 - time2)*1000000; + Con_Printf ("%6ius total %6ius server %6ius gfx %6ius snd\n", pass1+pass2+pass3, pass1, pass2, pass3); } @@ -762,9 +736,9 @@ void Host_Frame (float time) return; } - time1 = Sys_FloatTime (); + time1 = Sys_DoubleTime (); _Host_Frame (time); - time2 = Sys_FloatTime (); + time2 = Sys_DoubleTime (); timetotal += time2 - time1; timecount++; @@ -787,100 +761,56 @@ void Host_Frame (float time) //============================================================================ - -extern int vcrFile; -#define VCR_SIGNATURE 0x56435231 -// "VCR1" - -void Host_InitVCR (quakeparms_t *parms) -{ - int i, len, n; - char *p; - - if (COM_CheckParm("-playback")) - { - if (com_argc != 2) - Sys_Error("No other parameters allowed with -playback\n"); - - Sys_FileOpenRead("quake.vcr", &vcrFile); - if (vcrFile == -1) - Sys_Error("playback file not found\n"); - - Sys_FileRead (vcrFile, &i, sizeof(int)); - if (i != VCR_SIGNATURE) - Sys_Error("Invalid signature in vcr file\n"); - - Sys_FileRead (vcrFile, &com_argc, sizeof(int)); - com_argv = malloc(com_argc * sizeof(char *)); - com_argv[0] = parms->argv[0]; - for (i = 0; i < com_argc; i++) - { - Sys_FileRead (vcrFile, &len, sizeof(int)); - p = malloc(len); - Sys_FileRead (vcrFile, p, len); - com_argv[i+1] = p; - } - com_argc++; /* add one for arg[0] */ - parms->argc = com_argc; - parms->argv = com_argv; - } - - if ( (n = COM_CheckParm("-record")) != 0) - { - vcrFile = Sys_FileOpenWrite("quake.vcr"); - - i = VCR_SIGNATURE; - Sys_FileWrite(vcrFile, &i, sizeof(int)); - i = com_argc - 1; - Sys_FileWrite(vcrFile, &i, sizeof(int)); - for (i = 1; i < com_argc; i++) - { - if (i == n) - { - len = 10; - Sys_FileWrite(vcrFile, &len, sizeof(int)); - Sys_FileWrite(vcrFile, "-playback", len); - continue; - } - len = strlen(com_argv[i]) + 1; - Sys_FileWrite(vcrFile, &len, sizeof(int)); - Sys_FileWrite(vcrFile, com_argv[i], len); - } - } - -} +void Render_Init(void); /* ==================== Host_Init ==================== */ -void Host_Init (quakeparms_t *parms) +void Host_Init (void) { - + int i; + /* if (standard_quake) minimum_memory = MINIMUM_MEMORY; else minimum_memory = MINIMUM_MEMORY_LEVELPAK; if (COM_CheckParm ("-minmemory")) - parms->memsize = minimum_memory; + host_parms.memsize = minimum_memory; + + if (host_parms.memsize < minimum_memory) + Sys_Error ("Only %4.1f megs of memory available, can't execute game", host_parms.memsize / (float)0x100000); + */ - host_parms = *parms; + host_parms.memsize = DEFAULTMEM * 1024 * 1024; - if (parms->memsize < minimum_memory) - Sys_Error ("Only %4.1f megs of memory available, can't execute game", parms->memsize / (float)0x100000); + i = COM_CheckParm("-mem"); + if (i) + host_parms.memsize = (int) (atof(com_argv[i+1]) * 1024 * 1024); - com_argc = parms->argc; - com_argv = parms->argv; + i = COM_CheckParm("-winmem"); + if (i) + host_parms.memsize = (int) (atof(com_argv[i+1]) * 1024 * 1024); - Memory_Init (parms->membase, parms->memsize); + i = COM_CheckParm("-heapsize"); + if (i) + host_parms.memsize = (int) (atof(com_argv[i+1]) * 1024); + + host_parms.membase = qmalloc(host_parms.memsize); + if (!host_parms.membase) + Sys_Error("Not enough memory free, close some programs and try again, or free disk space\n"); + + com_argc = host_parms.argc; + com_argv = host_parms.argv; + + Memory_Init (host_parms.membase, host_parms.memsize); Cbuf_Init (); Cmd_Init (); V_Init (); Chase_Init (); - Host_InitVCR (parms); - COM_Init (parms->basedir); + COM_Init (host_parms.basedir); Host_InitLocal (); W_LoadWadFile ("gfx.wad"); Key_Init (); @@ -892,27 +822,22 @@ void Host_Init (quakeparms_t *parms) SV_Init (); Con_Printf ("Exe: "__TIME__" "__DATE__"\n"); - Con_Printf ("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0)); + Con_Printf ("%4.1f megabyte heap\n",host_parms.memsize/(1024*1024.0)); - R_InitTextures (); // needed even for dedicated servers - if (cls.state != ca_dedicated) { - host_basepal = (byte *)COM_LoadHunkFile ("gfx/palette.lmp", false); - if (!host_basepal) - Sys_Error ("Couldn't load gfx/palette.lmp"); - host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp", false); - if (!host_colormap) - Sys_Error ("Couldn't load gfx/colormap.lmp"); + VID_InitCvars(); + + Gamma_Init(); + + Palette_Init(); #ifndef _WIN32 // on non win32, mouse comes before video for security reasons IN_Init (); #endif - VID_Init (host_basepal); + VID_Init (); - Draw_Init (); - SCR_Init (); - R_Init (); + Render_Init(); S_Init (); CDAudio_Init (); Sbar_Init (); @@ -929,8 +854,7 @@ void Host_Init (quakeparms_t *parms) host_initialized = true; -// Sys_Printf ("========Quake Initialized=========\n"); -// printf("========Quake Initialized=========\n"); + Sys_Printf ("========Quake Initialized=========\n"); } @@ -965,6 +889,7 @@ void Host_Shutdown(void) if (cls.state != ca_dedicated) { + R_Modules_Shutdown(); VID_Shutdown(); } }