X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=host.c;h=d2d22bbaa3a6a5cd5035d663a18a9e9e20efe14b;hb=e572ffa56f0883c1ac7c9cca37da359ddbac551c;hp=b81831afe7917cd721b4e93f500755e62fe27635;hpb=d010b5177ed500178d3a40b49788c8093127ecf4;p=xonotic%2Fdarkplaces.git diff --git a/host.c b/host.c index b81831af..d2d22bba 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(); - - //PRVM_Crash(); // crash current prog + //PR_Crash(); - // crash all prvm progs - PRVM_CrashAll(); + // print out where the crash happened, if it was caused by QC (and do a cleanup) + PRVM_Crash(); - 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) @@ -158,49 +166,38 @@ void Host_ServerOptions (void) // COMMANDLINEOPTION: Server: -dedicated [playerlimit] starts a dedicated server (with a command console), default playerlimit is 8 // COMMANDLINEOPTION: Server: -listen [playerlimit] starts a multiplayer server with graphical client, like singleplayer but other players can connect, default playerlimit is 8 - if (cl_available) + // if no client is in the executable or -dedicated is specified on + // commandline, start a dedicated server + i = COM_CheckParm ("-dedicated"); + if (i || !cl_available) { - // client exists, check what mode the user wants - i = COM_CheckParm ("-dedicated"); + cls.state = ca_dedicated; + // check for -dedicated specifying how many players + if (i && i + 1 < com_argc && atoi (com_argv[i+1]) >= 1) + svs.maxclients = atoi (com_argv[i+1]); + if (COM_CheckParm ("-listen")) + Con_Printf ("Only one of -dedicated or -listen can be specified"); + // default sv_public on for dedicated servers (often hosted by serious administrators), off for listen servers (often hosted by clueless users) + Cvar_SetValue("sv_public", 1); + } + else if (cl_available) + { + // client exists and not dedicated, check if -listen is specified + cls.state = ca_disconnected; + i = COM_CheckParm ("-listen"); if (i) { - cls.state = ca_dedicated; // default players unless specified if (i + 1 < com_argc && atoi (com_argv[i+1]) >= 1) svs.maxclients = atoi (com_argv[i+1]); - if (COM_CheckParm ("-listen")) - Sys_Error ("Only one of -dedicated or -listen can be specified"); } else { - cls.state = ca_disconnected; - i = COM_CheckParm ("-listen"); - if (i) - { - // default players unless specified - if (i + 1 < com_argc && atoi (com_argv[i+1]) >= 1) - svs.maxclients = atoi (com_argv[i+1]); - } - else - { - // default players in some games, singleplayer in most - if (gamemode != GAME_GOODVSBAD2 && gamemode != GAME_NEXUIZ && gamemode != GAME_BATTLEMECH) - svs.maxclients = 1; - } + // default players in some games, singleplayer in most + if (gamemode != GAME_GOODVSBAD2 && gamemode != GAME_NEXUIZ && gamemode != GAME_BATTLEMECH) + svs.maxclients = 1; } } - else - { - // no client in the executable, always start dedicated server - if (COM_CheckParm ("-listen")) - Sys_Error ("-listen not available in a dedicated server executable"); - cls.state = ca_dedicated; - // check for -dedicated specifying how many players - i = COM_CheckParm ("-dedicated"); - // default players unless specified - if (i && i + 1 < com_argc && atoi (com_argv[i+1]) >= 1) - svs.maxclients = atoi (com_argv[i+1]); - } svs.maxclients = bound(1, svs.maxclients, MAX_SCOREBOARD); @@ -394,16 +391,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 +412,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_SetEngineString(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 +455,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 +484,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 +499,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 +652,6 @@ void Host_GetConsoleCommands (void) } } - /* ================== Host_ServerFrame @@ -667,10 +669,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 +692,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 +699,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 +708,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 +734,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 +805,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(); @@ -867,8 +868,6 @@ void Host_StartVideo(void) vid_opened = true; VID_Start(); CDAudio_Startup(); - CL_InitTEnts(); // We must wait after sound startup to load tent sounds - MR_Init(); } } @@ -966,8 +965,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 +1015,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"); @@ -1026,6 +1039,26 @@ void Host_Init (void) Cbuf_Execute(); } + // check for special demo mode +// COMMANDLINEOPTION: Client: -demo runs a playdemo and quits + i = COM_CheckParm("-demo"); + if (i && i + 1 < com_argc) + if (!sv.active && !cls.demoplayback && !cls.connect_trying) + { + Cbuf_AddText(va("playdemo %s\n", com_argv[i + 1])); + Cbuf_Execute(); + } + + // check for special demolooponly mode +// COMMANDLINEOPTION: Client: -demolooponly runs a playdemo and quits + i = COM_CheckParm("-demolooponly"); + if (i && i + 1 < com_argc) + if (!sv.active && !cls.demoplayback && !cls.connect_trying) + { + Cbuf_AddText(va("playdemo %s\n", com_argv[i + 1])); + Cbuf_Execute(); + } + if (cls.state == ca_dedicated || COM_CheckParm("-listen")) if (!sv.active && !cls.demoplayback && !cls.connect_trying) { @@ -1090,7 +1123,7 @@ void Host_Shutdown(void) CDAudio_Shutdown (); S_Terminate (); NetConn_Shutdown (); - PR_Shutdown (); + //PR_Shutdown (); if (cls.state != ca_dedicated) {