X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=host.c;h=97b51e240bf6fd5e8c9ca56f24f974abcd99e304;hp=3a39f269c03b3c445877772e38dd848fdce4e466;hb=aa33d8f8642530f7f266d6cde1422f95aa74b2be;hpb=31bfe80dd809721f0665fbe58f8d4eb3160aeb14 diff --git a/host.c b/host.c index 3a39f269..97b51e24 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) @@ -158,53 +166,42 @@ 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); - svs.clients = Mem_Alloc(sv_mempool, sizeof(client_t) * svs.maxclients); + svs.clients = (client_t *)Mem_Alloc(sv_mempool, sizeof(client_t) * svs.maxclients); if (svs.maxclients > 1 && !deathmatch.integer) Cvar_SetValueQuick(&deathmatch, 1); @@ -394,7 +391,7 @@ 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) { @@ -415,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; @@ -457,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) @@ -479,15 +477,14 @@ void Host_ShutdownServer(qboolean crash) { int i, count; sizebuf_t buf; - char message[4]; + qbyte message[4]; Con_DPrintf("Host_ShutdownServer\n"); 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); @@ -502,18 +499,20 @@ 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)); + + SV_VM_End(); } @@ -651,7 +650,6 @@ void Host_GetConsoleCommands (void) } } - /* ================== Host_ServerFrame @@ -669,10 +667,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 @@ -703,7 +706,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; @@ -724,7 +732,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 @@ -858,8 +866,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(); } } @@ -957,8 +963,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(); @@ -1007,6 +1013,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"); @@ -1017,6 +1037,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) { @@ -1081,7 +1121,7 @@ void Host_Shutdown(void) CDAudio_Shutdown (); S_Terminate (); NetConn_Shutdown (); - PR_Shutdown (); + //PR_Shutdown (); if (cls.state != ca_dedicated) {