/* ====================== CL_RegisterSounds ====================== */ void CL_RegisterSounds (void) { int32_t i; S_BeginRegistration (); CL_RegisterTEntSounds (); // Knightmare- 1/2/2002- ULTRA-CHEESY HACK for old demos or // connected to server using old protocol // Changed config strings require different offsets if ( LegacyProtocol() ) { for (i=1; i < OLD_MAX_SOUNDS; i++) { if (!cl.configstrings[OLD_CS_SOUNDS+i][0]) break; cl.sound_precache[i] = S_RegisterSound (cl.configstrings[OLD_CS_SOUNDS+i]); Sys_SendKeyEvents (); // pump message loop } } else { for (i=1; i < MAX_SOUNDS; i++) { if (!cl.configstrings[CS_SOUNDS+i][0]) break; cl.sound_precache[i] = S_RegisterSound (cl.configstrings[CS_SOUNDS+i]); Sys_SendKeyEvents (); // pump message loop } } //end Knightmare S_EndRegistration (); }
/* ================== Host_Frame Runs all active servers ================== */ void _Host_Frame (float time) { if (setjmp (host_abortserver)) return; // something bad happened, or the server disconnected // 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 // get new key events Sys_SendKeyEvents (); // process console commands Cbuf_Execute (); NET_Poll(); // check for commands typed to the host Host_GetConsoleCommands (); if (sv.active) Host_ServerFrame (); }
/* ================ Sys_GetEvent ================ */ sysEvent_t Sys_GetEvent( void ) { sysEvent_t ev; char *s; msg_t netmsg; netadr_t adr; // return if we have data if ( eventHead > eventTail ) { eventTail++; return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ]; } // pump the message loop // in vga this calls KBD_Update, under X, it calls GetEvent Sys_SendKeyEvents (); // check for console commands s = Sys_ConsoleInput(); if ( s ) { char *b; int len; len = strlen( s ) + 1; b = (char *)malloc( len ); strcpy( b, s ); Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b ); } // check for other input devices IN_Frame(); // check for network packets MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) ); #if 0 if ( Sys_GetPacket ( &adr, &netmsg ) ) { netadr_t *buf; int len; // copy out to a seperate buffer for qeueing len = sizeof( netadr_t ) + netmsg.cursize; buf = malloc( len ); *buf = adr; memcpy( buf+1, netmsg.data, netmsg.cursize ); Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf ); } #endif // return if we have data if ( eventHead > eventTail ) { eventTail++; return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ]; } // create an empty event to return memset( &ev, 0, sizeof( ev ) ); ev.evTime = Sys_Milliseconds(); return ev; }
/* ================== SCR_ModalMessage Displays a text string in the center of the screen and waits for a Y or N keypress. ================== */ int SCR_ModalMessage (char *text) { scr_notifystring = text; // draw a fresh screen scr_fullupdate = 0; scr_drawdialog = true; SCR_UpdateScreen (); #if !defined (__APPLE__) && !defined (MACOSX) scr_drawdialog = false; #endif /* !__APPLE__ && !MACOSX */ S_ClearBuffer (); // so dma doesn't loop current sound do { key_count = -1; // wait for a key down and up Sys_SendKeyEvents (); } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE); #if defined (__APPLE__) || defined (MACOSX) scr_drawdialog = false; #endif /* __APPLE__ || MACOSX */ scr_fullupdate = 0; SCR_UpdateScreen (); return key_lastpress == 'y'; }
/* ================== SCR_ModalMessage Displays a text string in the center of the screen and waits for a Y or N keypress. ================== */ int SCR_ModalMessage (char *text) { if (cls.state == ca_dedicated) return true; scr_notifystring = text; // draw a fresh screen scr_fullupdate = 0; scr_drawdialog = true; SCR_UpdateScreen (); scr_drawdialog = false; S_ClearBuffer (); // so dma doesn't loop current sound do { key_count = -1; // wait for a key down and up Sys_SendKeyEvents (); } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE); scr_fullupdate = 0; SCR_UpdateScreen (); return key_lastpress == 'y'; }
void Host_Frame(float timestep) { if (!Host_FilterTime(timestep)) { return; } Sys_SendKeyEvents(); VID_Update(); }
/* ================== SCR_ModalMessage Displays a text string in the center of the screen and waits for a Y or N keypress. ================== */ int SCR_ModalMessage (char *text) { if (cls.state == ca_dedicated) return true; scr_notifystring = text; // draw a fresh screen scr_fullupdate = 0; scr_drawdialog = true; SCR_UpdateScreen (); scr_drawdialog = false; S_ClearBuffer (); // so dma doesn't loop current sound // Wait for keys to be released. while (keydown['y'] || keydown['n'] || keydown[K_JOY1] || keydown[K_JOY2]) { key_count = INT_MIN; Sys_SendKeyEvents(); IN_Commands(); } // Wait for keys to be pressed. while (!keydown['y'] && !keydown['n'] && !keydown[K_JOY1] && !keydown[K_JOY2]) { key_count = INT_MIN; Sys_SendKeyEvents(); IN_Commands(); } key_count = 0; scr_fullupdate = 0; SCR_UpdateScreen (); return (key_lastpress == 'y') || (key_lastpress == K_JOY1); }
/* * CL_UserInputFrame */ void CL_UserInputFrame( void ) { // let the mouse activate or deactivate IN_Frame(); // get new key events Sys_SendKeyEvents(); // get new key events from mice or external controllers IN_Commands(); // process console commands Cbuf_Execute(); }
/* ====================== CL_RegisterSounds ====================== */ void CL_RegisterSounds (void) { int i; S_BeginRegistration (); CL_RegisterTEntSounds (); for (i=1 ; i<MAX_SOUNDS ; i++) { if (!cl.configstrings[CS_SOUNDS+i][0]) break; cl.sound_precache[i] = S_RegisterSound (cl.configstrings[CS_SOUNDS+i]); Sys_SendKeyEvents (); // pump message loop } S_EndRegistration (); }
sysEvent_t Sys_GetEvent( void ) { sysEvent_t ev; char *s; msg_t netmsg; // return if we have data if ( eventHead > eventTail ) { eventTail++; return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ]; } // pump the message loop // in vga this calls KBD_Update, under X, it calls GetEvent Sys_SendKeyEvents (); // check for console commands s = Sys_ConsoleInput(); if ( s ) { char *b; int len; len = strlen( s ) + 1; b = (char *)Z_Malloc( len,TAG_EVENT,qfalse ); strcpy( b, s ); Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b ); } // check for other input devices IN_Frame(); // check for network packets MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) ); // return if we have data if ( eventHead > eventTail ) { eventTail++; return eventQue[ ( eventTail - 1 ) & MASK_QUED_EVENTS ]; } // create an empty event to return memset( &ev, 0, sizeof( ev ) ); ev.evTime = Sys_Milliseconds(); return ev; }
/* * CL_UserInputFrame */ void CL_UserInputFrame( void ) { // let the mouse activate or deactivate IN_Frame(); // get new key events Sys_SendKeyEvents(); // get new key events from mice or external controllers IN_Commands(); // let the game handle touch events if( cls.key_dest == key_game ) CL_GameModule_TouchFrame(); // process console commands Cbuf_Execute(); }
/* ================== SCR_ModalMessage Displays a text string in the center of the screen and waits for a Y or N keypress. ================== */ int SCR_ModalMessage (const char *text, float timeout) //johnfitz -- timeout { double time1, time2; //johnfitz -- timeout int lastkey, lastchar; if (cls.state == ca_dedicated) return true; scr_notifystring = text; // draw a fresh screen scr_drawdialog = true; SCR_UpdateScreen (); scr_drawdialog = false; S_ClearBuffer (); // so dma doesn't loop current sound time1 = Sys_DoubleTime () + timeout; //johnfitz -- timeout time2 = 0.0f; //johnfitz -- timeout Key_BeginInputGrab (); do { Sys_SendKeyEvents (); Key_GetGrabbedInput (&lastkey, &lastchar); Sys_Sleep (16); if (timeout) time2 = Sys_DoubleTime (); //johnfitz -- zero timeout means wait forever. } while (lastchar != 'y' && lastchar != 'Y' && lastchar != 'n' && lastchar != 'N' && lastkey != K_ESCAPE && lastkey != K_ABUTTON && lastkey != K_BBUTTON && time2 <= time1); Key_EndInputGrab (); // SCR_UpdateScreen (); //johnfitz -- commented out //johnfitz -- timeout if (time2 > time1) return false; //johnfitz return (lastchar == 'y' || lastchar == 'Y' || lastkey == K_ABUTTON); }
/* ================== SCR_ModalMessage Displays a text string in the center of the screen and waits for a Y or N keypress. ================== */ int SCR_ModalMessage (const char *text, float timeout) //johnfitz -- timeout { double time1, time2; //johnfitz -- timeout if (cls.state == ca_dedicated) return true; scr_notifystring = text; // draw a fresh screen scr_drawdialog = true; SCR_UpdateScreen (); scr_drawdialog = false; S_ClearBuffer (); // so dma doesn't loop current sound time1 = Sys_DoubleTime () + timeout; //johnfitz -- timeout time2 = 0.0f; //johnfitz -- timeout do { key_count = -1; // wait for a key down and up Sys_SendKeyEvents (); Sys_Sleep(16); if (timeout) time2 = Sys_DoubleTime (); //johnfitz -- zero timeout means wait forever. } while (key_lastpress != 'y' && key_lastpress != 'n' && key_lastpress != K_ESCAPE && time2 <= time1); // make sure we don't ignore the next keypress if (key_count < 0) key_count = 0; // SCR_UpdateScreen (); //johnfitz -- commented out //johnfitz -- timeout if (time2 > time1) return false; //johnfitz return key_lastpress == 'y'; }
/* ================= Sys_PumpEvents ================= */ void Sys_PumpEvents( void ) { char *s; msg_t netmsg; netadr_t adr; // pump the message loop Sys_SendKeyEvents(); // check for console commands s = Sys_ConsoleInput(); if ( s ) { char *b; int len; len = strlen( s ) + 1; b = malloc( len ); if ( !b ) { Com_Error( ERR_FATAL, "malloc failed in Sys_PumpEvents" ); } strcpy( b, s ); Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b ); } // check for other input devices Sys_Input(); // check for network packets MSG_Init( &netmsg, sys_packetReceived, sizeof( sys_packetReceived ) ); if ( Sys_GetPacket ( &adr, &netmsg ) ) { netadr_t *buf; int len; // copy out to a seperate buffer for qeueing len = sizeof( netadr_t ) + netmsg.cursize; buf = malloc( len ); if ( !buf ) { Com_Error( ERR_FATAL, "malloc failed in Sys_PumpEvents" ); } *buf = adr; memcpy( buf+1, netmsg.data, netmsg.cursize ); Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf ); } }
/* * Load or download any custom player skins and models */ void CL_Skins_f(void) { int i; for (i = 0; i < MAX_CLIENTS; i++) { if (!cl.configstrings[CS_PLAYERSKINS + i][0]) { continue; } Com_Printf("client %i: %s\n", i, cl.configstrings[CS_PLAYERSKINS + i]); SCR_UpdateScreen(); Sys_SendKeyEvents(); /* pump message loop */ CL_ParseClientinfo(i); } }
void CL_SendCommand(void) { /* update windowed_mouse cvar */ CL_UpdateWindowedMouse(); /* get new key events */ Sys_SendKeyEvents(); /* process console commands */ Cbuf_Execute(); /* fix any cheating cvars */ CL_FixCvarCheats(); /* send intentions now */ CL_SendCmd(); /* resend a connection request if necessary */ CL_CheckForResend(); }
/* ================== Host_Frame Runs all active servers ================== */ void _Host_Frame (double time) { static double time1 = 0; static double time2 = 0; static double time3 = 0; int pass1, pass2, pass3; if (setjmp (host_abortserver) ) return; // something bad happened, or the server disconnected // keep the random time dependent rand (); // decide the simulation time if (!Host_FilterTime (time)) { #ifdef PROQUAKE_EXTENSION // JPG - if we're not doing a frame, still check for lagged moves to send if (!sv.active && (cl.movemessages > 2)) CL_SendLagMove(); #endif return; // don't run too fast, or packets will flood out } // get new key events #if !defined(MACOSX) Sys_SendKeyEvents (); #endif // This is done in Windows and Linux. Confirmed from pq350src // allow mice or other external controllers to add commands IN_Commands (); // Baker: This is ONLY joystick // process console commands Cbuf_Execute (); NET_Poll(); // if running the server locally, make intentions now if (sv.active) CL_SendCmd (); // This is where mouse input is read #ifdef WINDOWS_SCROLLWHEEL_PEEK else if (con_forcedup && key_dest == key_game) // Allows console scrolling when con_forcedup IN_MouseWheel (); // Grab mouse wheel input #endif //------------------- // // server operations // //------------------- // check for commands typed to the host Host_GetConsoleCommands (); if (sv.active) Host_ServerFrame (); //------------------- // // client operations // //------------------- // if running the server remotely, send intentions now after // the incoming messages have been read if (!sv.active) CL_SendCmd (); host_time += host_frametime; // fetch results from server if (cls.state == ca_connected) CL_ReadFromServer (); if (host_speeds.value) time1 = Sys_DoubleTime (); // update video SCR_UpdateScreen (); if (host_speeds.value) time2 = Sys_DoubleTime (); if (cls.signon == SIGNONS) { // update audio S_Update (r_origin, vpn, vright, vup); CL_DecayLights (); } else { S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin); } #ifdef PSP_MP3_SUPPORT if (bmg_type_changed == true) { #endif CDAudio_Update(); #ifdef PSP_MP3_SUPPORT bmg_type_changed = false; } #endif if (host_speeds.value) { pass1 = (time1 - time3)*1000; time3 = Sys_DoubleTime (); pass2 = (time2 - time1)*1000; pass3 = (time3 - time2)*1000; Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n", pass1+pass2+pass3, pass1, pass2, pass3); } #ifdef SUPPORTS_DEMO_CONTROLS if (!cls.demoplayback && cl_demorewind.value) { Cvar_SetValueByRef (&cl_demorewind, 0); Con_Printf ("Demorewind is only enabled during playback\n"); } #endif host_framecount++; //frame speed counter fps_count++;//muff }
int TTY_Connect(int handle, char *host) { double start; ComPort *p; char *response = NULL; keydest_t save_key_dest; char dialstring[64]; byte b; p = handleToPort[handle]; if ((p->modemStatus & MODEM_STATUS_MASK) != MODEM_STATUS_MASK) { Con_Printf ("Serial: line not ready ("); if ((p->modemStatus & MSR_CTS) == 0) Con_Printf(" CTS"); if ((p->modemStatus & MSR_DSR) == 0) Con_Printf(" DSR"); if ((p->modemStatus & MSR_CD) == 0) Con_Printf(" CD"); Con_Printf(" )"); return -1; } // discard any scraps in the input buffer while (! EMPTY (p->inputQueue)) DEQUEUE (p->inputQueue, b); CheckStatus (p); if (p->useModem) { save_key_dest = key_dest; key_dest = key_console; key_count = -2; Con_Printf ("Dialing...\n"); sprintf(dialstring, "AT D%c %s\r", p->dialType, host); Modem_Command (p, dialstring); start = Sys_FloatTime(); while(1) { if ((Sys_FloatTime() - start) > 60.0) { Con_Printf("Dialing failure!\n"); break; } Sys_SendKeyEvents (); if (key_count == 0) { if (key_lastpress != K_ESCAPE) { key_count = -2; continue; } Con_Printf("Aborting...\n"); while ((Sys_FloatTime() - start) < 5.0) ; disable(); p->outputQueue.head = p->outputQueue.tail = 0; p->inputQueue.head = p->inputQueue.tail = 0; outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) & ~MCR_DTR); enable(); start = Sys_FloatTime(); while ((Sys_FloatTime() - start) < 0.75) ; outportb(p->uart + MODEM_CONTROL_REGISTER, inportb(p->uart + MODEM_CONTROL_REGISTER) | MCR_DTR); response = "Aborted"; break; } response = Modem_Response(p); if (!response) continue; if (Q_strncmp(response, "CONNECT", 7) == 0) { disable(); p->modemRang = true; p->modemConnected = true; p->outputQueue.head = p->outputQueue.tail = 0; p->inputQueue.head = p->inputQueue.tail = 0; enable(); key_dest = save_key_dest; key_count = 0; m_return_onerror = false; return 0; } if (Q_strncmp(response, "NO CARRIER", 10) == 0) break; if (Q_strncmp(response, "NO DIALTONE", 11) == 0) break; if (Q_strncmp(response, "NO DIAL TONE", 12) == 0) break; if (Q_strncmp(response, "NO ANSWER", 9) == 0) break; if (Q_strncmp(response, "BUSY", 4) == 0) break; if (Q_strncmp(response, "ERROR", 5) == 0) break; } key_dest = save_key_dest; key_count = 0; if (m_return_onerror) { key_dest = key_menu; m_state = m_return_state; m_return_onerror = false; Q_strncpy(m_return_reason, response, 31); } return -1; } m_return_onerror = false; return 0; }
/* ================== Host_Frame Runs all active servers ================== */ void _Host_Frame(float time) { /* something bad happened, or the server disconnected */ if (setjmp(host_abort)) return; /* keep the random time dependent */ rand(); /* * Decide the simulation time. Don't run too fast, or packets will flood * out. */ if (!Host_FilterTime(time)) return; /* get new key events */ Sys_SendKeyEvents(); /* allow mice or other external controllers to add commands */ IN_Commands(); /* process console commands */ Cbuf_Execute(); NET_Poll(); /* if running the server locally, make intentions now */ if (sv.active) CL_SendCmd(); //------------------- // // server operations // //------------------- /* check for commands typed to the host */ Host_GetConsoleCommands(); if (sv.active) Host_ServerFrame(); //------------------- // // client operations // //------------------- /* * if running the server remotely, send intentions now after the incoming * messages have been read */ if (!sv.active) CL_SendCmd(); host_time += host_frametime; /* fetch results from server */ if (cls.state >= ca_connected) CL_ReadFromServer(); SCR_UpdateScreen(); CL_RunParticles(); host_framecount++; fps_count++; }
/* ================== Host_Frame Runs all active servers ================== */ void _Host_Frame (float time) { static double time1 = 0; static double time2 = 0; static double time3 = 0; int pass1, pass2, pass3; if (setjmp (host_abortserver) ) return; // something bad happened, or the server disconnected // 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 // get new key events Sys_SendKeyEvents (); // allow mice or other external controllers to add commands IN_Commands (); // process console commands Cbuf_Execute (); NET_Poll(); // if running the server locally, make intentions now if (sv.active) CL_SendCmd (); //------------------- // // server operations // //------------------- // check for commands typed to the host Host_GetConsoleCommands (); if (sv.active) Host_ServerFrame (); //------------------- // // client operations // //------------------- // if running the server remotely, send intentions now after // the incoming messages have been read 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 (); SCR_UpdateScreen (); if (host_speeds.value) time2 = Sys_FloatTime (); // update audio if (cls.signon == SIGNONS) { S_Update (r_origin, vpn, vright, vup); CL_DecayLights (); } else S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin); // jkrige - fmod sound system (music) //CDAudio_Update(); FMOD_MusicUpdate(); // jkrige - fmod sound system (music) 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+pass2+pass3, pass1, pass2, pass3); } host_framecount++; fps_count++; // jkrige - fps counter }
void Host_Main(void) { double time1 = 0; double time2 = 0; double time3 = 0; double cl_timer = 0, sv_timer = 0; double clframetime, deltacleantime, olddirtytime, dirtytime; double wait; int pass1, pass2, pass3, i; char vabuf[1024]; qboolean playing; Host_Init(); realtime = 0; host_dirtytime = Sys_DirtyTime(); for (;;) { if (setjmp(host_abortframe)) { SCR_ClearLoadingScreen(false); continue; // something bad happened, or the server disconnected } olddirtytime = host_dirtytime; dirtytime = Sys_DirtyTime(); deltacleantime = dirtytime - olddirtytime; if (deltacleantime < 0) { // warn if it's significant if (deltacleantime < -0.01) Con_Printf("Host_Mingled: time stepped backwards (went from %f to %f, difference %f)\n", olddirtytime, dirtytime, deltacleantime); deltacleantime = 0; } else if (deltacleantime >= 1800) { Con_Printf("Host_Mingled: time stepped forward (went from %f to %f, difference %f)\n", olddirtytime, dirtytime, deltacleantime); deltacleantime = 0; } realtime += deltacleantime; host_dirtytime = dirtytime; cl_timer += deltacleantime; sv_timer += deltacleantime; if (!svs.threaded) { svs.perf_acc_realtime += deltacleantime; // Look for clients who have spawned playing = false; for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) if(host_client->begun) if(host_client->netconnection) playing = true; if(sv.time < 10) { // don't accumulate time for the first 10 seconds of a match // so things can settle svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0; } else if(svs.perf_acc_realtime > 5) { svs.perf_cpuload = 1 - svs.perf_acc_sleeptime / svs.perf_acc_realtime; svs.perf_lost = svs.perf_acc_lost / svs.perf_acc_realtime; if(svs.perf_acc_offset_samples > 0) { svs.perf_offset_max = svs.perf_acc_offset_max; svs.perf_offset_avg = svs.perf_acc_offset / svs.perf_acc_offset_samples; svs.perf_offset_sdev = sqrt(svs.perf_acc_offset_squared / svs.perf_acc_offset_samples - svs.perf_offset_avg * svs.perf_offset_avg); } if(svs.perf_lost > 0 && developer_extra.integer) if(playing) // only complain if anyone is looking Con_DPrintf("Server can't keep up: %s\n", Host_TimingReport(vabuf, sizeof(vabuf))); svs.perf_acc_realtime = svs.perf_acc_sleeptime = svs.perf_acc_lost = svs.perf_acc_offset = svs.perf_acc_offset_squared = svs.perf_acc_offset_max = svs.perf_acc_offset_samples = 0; } } if (slowmo.value < 0.00001 && slowmo.value != 0) Cvar_SetValue("slowmo", 0); if (host_framerate.value < 0.00001 && host_framerate.value != 0) Cvar_SetValue("host_framerate", 0); // keep the random time dependent, but not when playing demos/benchmarking if(!*sv_random_seed.string && !cls.demoplayback) rand(); // get new key events Key_EventQueue_Unblock(); SndSys_SendKeyEvents(); Sys_SendKeyEvents(); NetConn_UpdateSockets(); Log_DestBuffer_Flush(); // receive packets on each main loop iteration, as the main loop may // be undersleeping due to select() detecting a new packet if (sv.active && !svs.threaded) NetConn_ServerFrame(); Curl_Run(); // check for commands typed to the host Host_GetConsoleCommands(); // when a server is running we only execute console commands on server frames // (this mainly allows frikbot .way config files to work properly by staying in sync with the server qc) // otherwise we execute them on client frames if (sv.active ? sv_timer > 0 : cl_timer > 0) { // process console commands // R_TimeReport("preconsole"); CL_VM_PreventInformationLeaks(); Cbuf_Frame(); // R_TimeReport("console"); } //Con_Printf("%6.0f %6.0f\n", cl_timer * 1000000.0, sv_timer * 1000000.0); // if the accumulators haven't become positive yet, wait a while if (cls.state == ca_dedicated) wait = sv_timer * -1000000.0; else if (!sv.active || svs.threaded) wait = cl_timer * -1000000.0; else wait = max(cl_timer, sv_timer) * -1000000.0; if (!cls.timedemo && wait >= 1) { double time0, delta; if(host_maxwait.value <= 0) wait = min(wait, 1000000.0); else wait = min(wait, host_maxwait.value * 1000.0); if(wait < 1) wait = 1; // because we cast to int time0 = Sys_DirtyTime(); if (sv_checkforpacketsduringsleep.integer && !sys_usenoclockbutbenchmark.integer && !svs.threaded) { NetConn_SleepMicroseconds((int)wait); if (cls.state != ca_dedicated) NetConn_ClientFrame(); // helps server browser get good ping values // TODO can we do the same for ServerFrame? Probably not. } else Sys_Sleep((int)wait); delta = Sys_DirtyTime() - time0; if (delta < 0 || delta >= 1800) delta = 0; if (!svs.threaded) svs.perf_acc_sleeptime += delta; // R_TimeReport("sleep"); continue; } // limit the frametime steps to no more than 100ms each if (cl_timer > 0.1) cl_timer = 0.1; if (sv_timer > 0.1) { if (!svs.threaded) svs.perf_acc_lost += (sv_timer - 0.1); sv_timer = 0.1; } R_TimeReport("---"); //------------------- // // server operations // //------------------- // limit the frametime steps to no more than 100ms each if (sv.active && sv_timer > 0 && !svs.threaded) { // execute one or more server frames, with an upper limit on how much // execution time to spend on server frames to avoid freezing the game if // the server is overloaded, this execution time limit means the game will // slow down if the server is taking too long. int framecount, framelimit = 1; double advancetime, aborttime = 0; float offset; prvm_prog_t *prog = SVVM_prog; // run the world state // don't allow simulation to run too fast or too slow or logic glitches can occur // stop running server frames if the wall time reaches this value if (sys_ticrate.value <= 0) advancetime = sv_timer; else if (cl.islocalgame && !sv_fixedframeratesingleplayer.integer) { // synchronize to the client frametime, but no less than 10ms and no more than 100ms advancetime = bound(0.01, cl_timer, 0.1); } else { advancetime = sys_ticrate.value; // listen servers can run multiple server frames per client frame framelimit = cl_maxphysicsframesperserverframe.integer; aborttime = Sys_DirtyTime() + 0.1; } if(slowmo.value > 0 && slowmo.value < 1) advancetime = min(advancetime, 0.1 / slowmo.value); else advancetime = min(advancetime, 0.1); if(advancetime > 0) { offset = Sys_DirtyTime() - dirtytime;if (offset < 0 || offset >= 1800) offset = 0; offset += sv_timer; ++svs.perf_acc_offset_samples; svs.perf_acc_offset += offset; svs.perf_acc_offset_squared += offset * offset; if(svs.perf_acc_offset_max < offset) svs.perf_acc_offset_max = offset; } // only advance time if not paused // the game also pauses in singleplayer when menu or console is used sv.frametime = advancetime * slowmo.value; if (host_framerate.value) sv.frametime = host_framerate.value; if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused))) sv.frametime = 0; for (framecount = 0;framecount < framelimit && sv_timer > 0;framecount++) { sv_timer -= advancetime; // move things around and think unless paused if (sv.frametime) SV_Physics(); // if this server frame took too long, break out of the loop if (framelimit > 1 && Sys_DirtyTime() >= aborttime) break; } R_TimeReport("serverphysics"); // send all messages to the clients SV_SendClientMessages(); if (sv.paused == 1 && realtime > sv.pausedstart && sv.pausedstart > 0) { prog->globals.fp[OFS_PARM0] = realtime - sv.pausedstart; PRVM_serverglobalfloat(time) = sv.time; prog->ExecuteProgram(prog, PRVM_serverfunction(SV_PausedTic), "QC function SV_PausedTic is missing"); } // send an heartbeat if enough time has passed since the last one NetConn_Heartbeat(0); R_TimeReport("servernetwork"); } else if (!svs.threaded) { // don't let r_speeds display jump around R_TimeReport("serverphysics"); R_TimeReport("servernetwork"); } //------------------- // // client operations // //------------------- if (cls.state != ca_dedicated && (cl_timer > 0 || cls.timedemo || ((vid_activewindow ? cl_maxfps : cl_maxidlefps).value < 1))) { R_TimeReport("---"); Collision_Cache_NewFrame(); R_TimeReport("photoncache"); // decide the simulation time if (cls.capturevideo.active) { //*** if (cls.capturevideo.realtime) clframetime = cl.realframetime = max(cl_timer, 1.0 / cls.capturevideo.framerate); else { clframetime = 1.0 / cls.capturevideo.framerate; cl.realframetime = max(cl_timer, clframetime); } } else if (vid_activewindow && cl_maxfps.value >= 1 && !cls.timedemo) { clframetime = cl.realframetime = max(cl_timer, 1.0 / cl_maxfps.value); // when running slow, we need to sleep to keep input responsive wait = bound(0, cl_maxfps_alwayssleep.value * 1000, 100000); if (wait > 0) Sys_Sleep((int)wait); } else if (!vid_activewindow && cl_maxidlefps.value >= 1 && !cls.timedemo) clframetime = cl.realframetime = max(cl_timer, 1.0 / cl_maxidlefps.value); else clframetime = cl.realframetime = cl_timer; // apply slowmo scaling clframetime *= cl.movevars_timescale; // scale playback speed of demos by slowmo cvar if (cls.demoplayback) { clframetime *= slowmo.value; // if demo playback is paused, don't advance time at all if (cls.demopaused) clframetime = 0; } else { // host_framerate overrides all else if (host_framerate.value) clframetime = host_framerate.value; if (cl.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive || cl.csqc_paused))) clframetime = 0; } if (cls.timedemo) clframetime = cl.realframetime = cl_timer; // deduct the frame time from the accumulator cl_timer -= cl.realframetime; cl.oldtime = cl.time; cl.time += clframetime; // update video if (host_speeds.integer) time1 = Sys_DirtyTime(); R_TimeReport("pre-input"); // Collect input into cmd CL_Input(); R_TimeReport("input"); // check for new packets NetConn_ClientFrame(); // read a new frame from a demo if needed CL_ReadDemoMessage(); R_TimeReport("clientnetwork"); // now that packets have been read, send input to server CL_SendMove(); R_TimeReport("sendmove"); // update client world (interpolate entities, create trails, etc) CL_UpdateWorld(); R_TimeReport("lerpworld"); CL_Video_Frame(); R_TimeReport("client"); CL_UpdateScreen(); CL_MeshEntities_Reset(); R_TimeReport("render"); if (host_speeds.integer) time2 = Sys_DirtyTime(); // update audio if(cl.csqc_usecsqclistener) { S_Update(&cl.csqc_listenermatrix); cl.csqc_usecsqclistener = false; } else S_Update(&r_refdef.view.matrix); CDAudio_Update(); R_TimeReport("audio"); // reset gathering of mouse input in_mouse_x = in_mouse_y = 0; if (host_speeds.integer) { pass1 = (int)((time1 - time3)*1000000); time3 = Sys_DirtyTime(); pass2 = (int)((time2 - time1)*1000000); pass3 = (int)((time3 - time2)*1000000); Con_Printf("%6ius total %6ius server %6ius gfx %6ius snd\n", pass1+pass2+pass3, pass1, pass2, pass3); } } #if MEMPARANOIA Mem_CheckSentinelsGlobal(); #else if (developer_memorydebug.integer) Mem_CheckSentinelsGlobal(); #endif // if there is some time remaining from this frame, reset the timers if (cl_timer >= 0) cl_timer = 0; if (sv_timer >= 0) { if (!svs.threaded) svs.perf_acc_lost += sv_timer; sv_timer = 0; } host_framecount++; } }
/* * CL_GameModule_Init */ void CL_GameModule_Init( void ) { int apiversion, oldState; unsigned int start; cgame_import_t import; void *( *builtinAPIfunc )(void *) = NULL; #ifdef CGAME_HARD_LINKED builtinAPIfunc = GetCGameAPI; #endif // stop all playing sounds CL_SoundModule_StopAllSounds(); CL_GameModule_Shutdown(); // disable reading of client game module chat cvars Cvar_ForceSet( "con_chatCGame", "0" ); cl_gamemodulepool = _Mem_AllocPool( NULL, "Client Game Progs", MEMPOOL_CLIENTGAME, __FILE__, __LINE__ ); import.Error = CL_GameModule_Error; import.Print = CL_GameModule_Print; import.PrintToLog = CL_GameModule_PrintToLog; import.Dynvar_Create = Dynvar_Create; import.Dynvar_Destroy = Dynvar_Destroy; import.Dynvar_Lookup = Dynvar_Lookup; import.Dynvar_GetName = Dynvar_GetName; import.Dynvar_GetValue = Dynvar_GetValue; import.Dynvar_SetValue = Dynvar_SetValue; import.Dynvar_AddListener = Dynvar_AddListener; import.Dynvar_RemoveListener = Dynvar_RemoveListener; import.Cvar_Get = Cvar_Get; import.Cvar_Set = Cvar_Set; import.Cvar_SetValue = Cvar_SetValue; import.Cvar_ForceSet = Cvar_ForceSet; import.Cvar_String = Cvar_String; import.Cvar_Value = Cvar_Value; import.Cmd_TokenizeString = Cmd_TokenizeString; import.Cmd_Argc = Cmd_Argc; import.Cmd_Argv = Cmd_Argv; import.Cmd_Args = Cmd_Args; import.Cmd_AddCommand = Cmd_AddCommand; import.Cmd_RemoveCommand = Cmd_RemoveCommand; import.Cmd_ExecuteText = Cbuf_ExecuteText; import.Cmd_Execute = Cbuf_Execute; import.Cmd_SetCompletionFunc = Cmd_SetCompletionFunc; import.FS_FOpenFile = FS_FOpenFile; import.FS_Read = FS_Read; import.FS_Write = FS_Write; import.FS_Print = FS_Print; import.FS_Tell = FS_Tell; import.FS_Seek = FS_Seek; import.FS_Eof = FS_Eof; import.FS_Flush = FS_Flush; import.FS_FCloseFile = FS_FCloseFile; import.FS_RemoveFile = FS_RemoveFile; import.FS_GetFileList = FS_GetFileList; import.FS_FirstExtension = FS_FirstExtension; import.FS_IsPureFile = FS_IsPureFile; import.FS_MoveFile = FS_MoveFile; import.FS_IsUrl = FS_IsUrl; import.FS_FileMTime = FS_BaseFileMTime; import.FS_RemoveDirectory = FS_RemoveDirectory; import.Key_GetBindingBuf = Key_GetBindingBuf; import.Key_KeynumToString = Key_KeynumToString; import.GetConfigString = CL_GameModule_GetConfigString; import.Milliseconds = Sys_Milliseconds; import.DownloadRequest = CL_DownloadRequest; import.Hash_BlockChecksum = Com_MD5Digest32; import.Hash_SuperFastHash = Com_SuperFastHash; import.NET_GetUserCmd = CL_GameModule_NET_GetUserCmd; import.NET_GetCurrentUserCmdNum = CL_GameModule_NET_GetCurrentUserCmdNum; import.NET_GetCurrentState = CL_GameModule_NET_GetCurrentState; import.RefreshMouseAngles = CL_GameModule_RefreshMouseAngles; import.R_UpdateScreen = SCR_UpdateScreen; import.R_GetClippedFragments = R_GetClippedFragments; import.R_ClearScene = R_ClearScene; import.R_AddEntityToScene = R_AddEntityToScene; import.R_AddLightToScene = R_AddLightToScene; import.R_AddPolyToScene = R_AddPolyToScene; import.R_AddLightStyleToScene = R_AddLightStyleToScene; import.R_RenderScene = R_RenderScene; import.R_SpeedsMessage = R_SpeedsMessage; import.R_RegisterWorldModel = CL_GameModule_R_RegisterWorldModel; import.R_ModelBounds = R_ModelBounds; import.R_ModelFrameBounds = R_ModelFrameBounds; import.R_RegisterModel = R_RegisterModel; import.R_RegisterPic = R_RegisterPic; import.R_RegisterRawPic = R_RegisterRawPic; import.R_RegisterLevelshot = R_RegisterLevelshot; import.R_RegisterSkin = R_RegisterSkin; import.R_RegisterSkinFile = R_RegisterSkinFile; import.R_LerpTag = R_LerpTag; import.R_LightForOrigin = R_LightForOrigin; import.R_SetCustomColor = R_SetCustomColor; import.R_DrawStretchPic = R_DrawStretchPic; import.R_DrawStretchPoly = R_DrawStretchPoly; import.R_DrawRotatedStretchPic = R_DrawRotatedStretchPic; import.R_SetScissorRegion = R_SetScissorRegion; import.R_GetShaderDimensions = R_GetShaderDimensions; import.R_TransformVectorToScreen = R_TransformVectorToScreen; import.R_SkeletalGetNumBones = R_SkeletalGetNumBones; import.R_SkeletalGetBoneInfo = R_SkeletalGetBoneInfo; import.R_SkeletalGetBonePose = R_SkeletalGetBonePose; import.VID_FlashWindow = VID_FlashWindow; import.CM_NumInlineModels = CL_GameModule_CM_NumInlineModels; import.CM_InlineModel = CL_GameModule_CM_InlineModel; import.CM_TransformedBoxTrace = CL_GameModule_CM_TransformedBoxTrace; import.CM_RoundUpToHullSize = CL_GameModule_CM_RoundUpToHullSize; import.CM_TransformedPointContents = CL_GameModule_CM_TransformedPointContents; import.CM_ModelForBBox = CL_GameModule_CM_ModelForBBox; import.CM_OctagonModelForBBox = CL_GameModule_CM_OctagonModelForBBox; import.CM_InlineModelBounds = CL_GameModule_CM_InlineModelBounds; import.S_RegisterSound = CL_SoundModule_RegisterSound; import.S_StartFixedSound = CL_SoundModule_StartFixedSound; import.S_StartRelativeSound = CL_SoundModule_StartRelativeSound; import.S_StartGlobalSound = CL_SoundModule_StartGlobalSound; import.S_Update = CL_GameModule_SoundUpdate; import.S_AddLoopSound = CL_SoundModule_AddLoopSound; import.S_StartBackgroundTrack = CL_SoundModule_StartBackgroundTrack; import.S_StopBackgroundTrack = CL_SoundModule_StopBackgroundTrack; import.SCR_RegisterFont = SCR_RegisterFont; import.SCR_DrawString = SCR_DrawString; import.SCR_DrawStringWidth = SCR_DrawStringWidth; import.SCR_DrawClampString = SCR_DrawClampString; import.SCR_strHeight = SCR_strHeight; import.SCR_strWidth = SCR_strWidth; import.SCR_StrlenForWidth = SCR_StrlenForWidth; import.Mem_Alloc = CL_GameModule_MemAlloc; import.Mem_Free = CL_GameModule_MemFree; cge = (cgame_export_t *)Com_LoadGameLibrary( "cgame", "GetCGameAPI", &module_handle, &import, builtinAPIfunc, cls.sv_pure, NULL ); if( !cge ) Com_Error( ERR_DROP, "Failed to load client game DLL" ); AC_LoadLibrary( (void *) &import, (void *) cge, ANTICHEAT_CLIENT ); // impulZ: Refire AC Init apiversion = cge->API(); if( apiversion != CGAME_API_VERSION ) { Com_UnloadGameLibrary( &module_handle ); Mem_FreePool( &cl_gamemodulepool ); cge = NULL; Com_Error( ERR_DROP, "Client game is version %i, not %i", apiversion, CGAME_API_VERSION ); } oldState = cls.state; cls.state = CA_LOADING; start = Sys_Milliseconds(); cge->Init( cl.playernum, viddef.width, viddef.height, cls.demo.playing, cls.sv_pure, cl.snapFrameTime, APP_PROTOCOL_VERSION, cls.mediaRandomSeed ); Com_DPrintf( "CL_GameModule_Init: %.2f seconds\n", (float)( Sys_Milliseconds() - start ) * 0.001f ); cls.state = oldState; cls.cgameActive = qtrue; // check memory integrity Mem_CheckSentinelsGlobal(); Sys_SendKeyEvents(); // pump message loop }