X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=host.c;h=385a1c2bbd20092067566345577d41eac7a172d1;hb=01095c29fa18e3eaece7a3eeacd201c03f49803c;hp=0300386c20d9c472b89518e0fe8a9c4c3e3a88bb;hpb=df8727697622029dd7a03047999ffc19b49e44ea;p=xonotic%2Fdarkplaces.git diff --git a/host.c b/host.c index 0300386c..385a1c2b 100644 --- a/host.c +++ b/host.c @@ -56,7 +56,7 @@ int forcedeveloper; // current client client_t *host_client; -jmp_buf host_abortserver; +jmp_buf host_abortframe; // pretend frames take this amount of time (in seconds), 0 = realtime cvar_t host_framerate = {0, "host_framerate","0"}; @@ -93,6 +93,18 @@ cvar_t temp1 = {0, "temp1","0"}; cvar_t timestamps = {CVAR_SAVE, "timestamps", "0"}; cvar_t timeformat = {CVAR_SAVE, "timeformat", "[%b %e %X] "}; +/* +================ +Host_AbortCurrentFrame + +aborts the current host frame and goes on with the next one +================ +*/ +void Host_AbortCurrentFrame(void) +{ + longjmp (host_abortframe, 1); +} + /* ================ Host_Error @@ -100,12 +112,11 @@ Host_Error This shuts down both the client and server ================ */ -void PRVM_ProcessError(void); -static char hosterrorstring1[4096]; -static char hosterrorstring2[4096]; -static qboolean hosterror = false; void Host_Error (const char *error, ...) { + static char hosterrorstring1[4096]; + static char hosterrorstring2[4096]; + static qboolean hosterror = false; va_list argptr; va_start (argptr,error); @@ -127,14 +138,11 @@ void Host_Error (const char *error, ...) CL_Parse_DumpPacket(); - PR_Crash(); + //PR_Crash(); - //PRVM_Crash(); // crash current prog + // print out where the crash happened, if it was caused by QC (and do a cleanup) + PRVM_Crash(); - // crash all prvm progs - PRVM_CrashAll(); - - PRVM_ProcessError(); Host_ShutdownServer (false); @@ -146,7 +154,7 @@ void Host_Error (const char *error, ...) hosterror = false; - longjmp (host_abortserver, 1); + Host_AbortCurrentFrame(); } void Host_ServerOptions (void) @@ -394,16 +402,18 @@ void SV_DropClient(qboolean crash) Con_Printf("Client \"%s\" dropped\n", host_client->name); // make sure edict is not corrupt (from a level change for example) - host_client->edict = EDICT_NUM(host_client - svs.clients + 1); + host_client->edict = PRVM_EDICT_NUM(host_client - svs.clients + 1); if (host_client->netconnection) { // free the client (the body stays around) if (!crash) { - // LordHavoc: no opportunity for resending, so use unreliable + // LordHavoc: no opportunity for resending, so use unreliable 3 times MSG_WriteByte(&host_client->message, svc_disconnect); NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); + NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); + NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message); } // break the net connection NetConn_Close(host_client->netconnection); @@ -413,21 +423,22 @@ void SV_DropClient(qboolean crash) // call qc ClientDisconnect function // LordHavoc: don't call QC if server is dead (avoids recursive // Host_Error in some mods when they run out of edicts) - if (host_client->active && sv.active && host_client->edict && host_client->spawned) + if (host_client->clientconnectcalled && sv.active && host_client->edict) { // call the prog function for removing a client // this will set the body to a dead frame, among other things - int saveSelf = pr_global_struct->self; - pr_global_struct->self = EDICT_TO_PROG(host_client->edict); - PR_ExecuteProgram(pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing"); - pr_global_struct->self = saveSelf; + int saveSelf = prog->globals.server->self; + host_client->clientconnectcalled = false; + prog->globals.server->self = PRVM_EDICT_TO_PROG(host_client->edict); + PRVM_ExecuteProgram(prog->globals.server->ClientDisconnect, "QC function ClientDisconnect is missing"); + prog->globals.server->self = saveSelf; } // remove leaving player from scoreboard - //host_client->edict->v->netname = PR_SetString(host_client->name); - //if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors))) + //host_client->edict->fields.server->netname = PRVM_SetEngineString(host_client->name); + //if ((val = PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors))) // val->_float = 0; - //host_client->edict->v->frags = 0; + //host_client->edict->fields.server->frags = 0; host_client->name[0] = 0; host_client->colors = 0; host_client->frags = 0; @@ -455,7 +466,7 @@ void SV_DropClient(qboolean crash) if (sv.active) { // clear a fields that matter to DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS, and also frags - ED_ClearEdict(host_client->edict); + PRVM_ED_ClearEdict(host_client->edict); } // clear the client struct (this sets active to false) @@ -484,8 +495,7 @@ void Host_ShutdownServer(qboolean crash) if (!sv.active) return; - // print out where the crash happened, if it was caused by QC - PR_Crash(); + SV_VM_Begin(); NetConn_Heartbeat(2); NetConn_Heartbeat(2); @@ -500,18 +510,22 @@ void Host_ShutdownServer(qboolean crash) Con_Printf("Host_ShutdownServer: NetConn_SendToAll failed for %u clients\n", count); for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) - if (host_client->active) + if (host_client->active) { SV_DropClient(crash); // server shutdown + } NetConn_CloseServerPorts(); sv.active = false; - // // clear structures // memset(&sv, 0, sizeof(sv)); memset(svs.clients, 0, svs.maxclients*sizeof(client_t)); + + PRVM_ResetProg(); + + SV_VM_End(); } @@ -649,7 +663,6 @@ void Host_GetConsoleCommands (void) } } - /* ================== Host_ServerFrame @@ -667,10 +680,15 @@ void Host_ServerFrame (void) return; } sv.timer += host_realframetime; + + // run the world state // don't allow simulation to run too fast or too slow or logic glitches can occur for (framecount = 0;framecount < framelimit && sv.timer > 0;framecount++) { + // setup the VM frame + SV_VM_Begin(); + if (cl.islocalgame) advancetime = min(sv.timer, sys_ticrate.value); else @@ -685,8 +703,6 @@ void Host_ServerFrame (void) if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive))) sv.frametime = 0; - pr_global_struct->frametime = sv.frametime; - // set the time and clear the general datagram SV_ClearDatagram(); @@ -694,9 +710,6 @@ void Host_ServerFrame (void) // come in midframe (particularly if host is running really slow) NetConn_ServerFrame(); - // read client messages - SV_RunClients(); - // move things around and think unless paused if (sv.frametime) SV_Physics(); @@ -706,7 +719,12 @@ void Host_ServerFrame (void) // send an heartbeat if enough time has passed since the last one NetConn_Heartbeat(0); + + // end the server VM frame + SV_VM_End(); } + + // if we fell behind too many frames just don't worry about it if (sv.timer > 0) sv.timer = 0; @@ -727,7 +745,7 @@ void _Host_Frame (float time) static double time3 = 0; int pass1, pass2, pass3; - if (setjmp(host_abortserver)) + if (setjmp(host_abortframe)) return; // something bad happened, or the server disconnected // decide the simulation time @@ -798,13 +816,7 @@ void _Host_Frame (float time) time2 = Sys_DoubleTime(); // update audio - if (cls.signon == SIGNONS && cl_entities[cl.viewentity].state_current.active) - { - // LordHavoc: this used to use renderer variables (eww) - S_Update(&cl_entities[cl.viewentity].render.matrix); - } - else - S_Update(&identitymatrix); + S_Update(&r_refdef.viewentitymatrix); CDAudio_Update(); @@ -868,7 +880,6 @@ void Host_StartVideo(void) VID_Start(); CDAudio_Startup(); CL_InitTEnts(); // We must wait after sound startup to load tent sounds - MR_Init(); } } @@ -966,8 +977,8 @@ void Host_Init (void) Mathlib_Init(); NetConn_Init(); - PR_Init(); - PR_Cmd_Init(); + //PR_Init(); + //PR_Cmd_Init(); PRVM_Init(); Mod_Init(); SV_Init(); @@ -1016,6 +1027,20 @@ void Host_Init (void) // save console log up to this point to log_file if it was set by configs Log_Start(); + // FIXME: put this into some neat design, but the menu should be allowed to crash + // without crashing the whole game, so this should just be a short-time solution + Host_StartVideo(); + + // here comes the not so critical stuff + if (setjmp(host_abortframe)) { + return; + } + + if (cls.state != ca_dedicated) + { + MR_Init(); + } + // check for special benchmark mode // COMMANDLINEOPTION: Client: -benchmark runs a timedemo and quits, results of any timedemo can be found in gamedir/benchmark.log (for example id1/benchmark.log) i = COM_CheckParm("-benchmark"); @@ -1067,6 +1092,9 @@ void Host_Shutdown(void) } isdown = true; + // be quiet while shutting down + S_StopAllSounds(); + // disconnect client from server if active CL_Disconnect(); @@ -1087,7 +1115,7 @@ void Host_Shutdown(void) CDAudio_Shutdown (); S_Terminate (); NetConn_Shutdown (); - PR_Shutdown (); + //PR_Shutdown (); if (cls.state != ca_dedicated) {