X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=cl_parse.c;h=bee2cb533c4d08efcbca02f4ce858b439c79dcb7;hb=323b17db9329c0c4e1f3832f9cacf9102659b7c5;hp=45b1890c904ff8248af51b27722d0fd397802694;hpb=b4617522b3a3401b30e9c95b125a706d0a8113c0;p=xonotic%2Fdarkplaces.git diff --git a/cl_parse.c b/cl_parse.c index 45b1890c..bee2cb53 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -290,12 +290,25 @@ void CL_KeepaliveMessage (qboolean readmessages) { float time; static double nextmsg = -1; + static double nextupdate = -1; +#if 0 + static double lasttime = -1; +#endif int oldreadcount; qboolean oldbadread; sizebuf_t old; + if(cls.state != ca_dedicated) + { + if((time = Sys_DoubleTime()) >= nextupdate) + { + SCR_UpdateLoadingScreenIfShown(); + nextupdate = time + 2; + } + } + // no need if server is local and definitely not if this is a demo - if (!cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD) + if (!cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon >= SIGNONS) return; if (readmessages) @@ -314,6 +327,14 @@ void CL_KeepaliveMessage (qboolean readmessages) memcpy(net_message.data, olddata, net_message.cursize); } +#if 0 + if((time = Sys_DoubleTime()) >= lasttime + 1) + { + Con_Printf("long delta: %f\n", time - lasttime); + } + lasttime = Sys_DoubleTime(); +#endif + if (cls.netcon && (time = Sys_DoubleTime()) >= nextmsg) { sizebuf_t msg; @@ -411,9 +432,15 @@ static void CL_SetupWorldModel(void) // load or reload .loc file for team chat messages CL_Locs_Reload_f(); + // make sure we send enough keepalives + CL_KeepaliveMessage(false); + // reset particles and other per-level things R_Modules_NewMap(); + // make sure we send enough keepalives + CL_KeepaliveMessage(false); + // load the team chat beep if possible cl.foundtalk2wav = FS_FileExists("sound/misc/talk2.wav"); @@ -543,24 +570,26 @@ static void QW_CL_RequestNextDownload(void) if (!sv.active) Mod_ClearUsed(); for (i = 1;i < MAX_MODELS && cl.model_name[i][0];i++) - Mod_FindName(cl.model_name[i]); + Mod_FindName(cl.model_name[i], cl.model_name[i][0] == '*' ? cl.model_name[1] : NULL); // precache any models used by the client (this also marks them used) - cl.model_bolt = Mod_ForName("progs/bolt.mdl", false, false, false); - cl.model_bolt2 = Mod_ForName("progs/bolt2.mdl", false, false, false); - cl.model_bolt3 = Mod_ForName("progs/bolt3.mdl", false, false, false); - cl.model_beam = Mod_ForName("progs/beam.mdl", false, false, false); - Mod_PurgeUnused(); + cl.model_bolt = Mod_ForName("progs/bolt.mdl", false, false, NULL); + cl.model_bolt2 = Mod_ForName("progs/bolt2.mdl", false, false, NULL); + cl.model_bolt3 = Mod_ForName("progs/bolt3.mdl", false, false, NULL); + cl.model_beam = Mod_ForName("progs/beam.mdl", false, false, NULL); + + // we purge the models and sounds later in CL_SignonReply + //Mod_PurgeUnused(); // now we try to load everything that is new // world model - cl.model_precache[1] = Mod_ForName(cl.model_name[1], false, false, true); + cl.model_precache[1] = Mod_ForName(cl.model_name[1], false, false, NULL); if (cl.model_precache[1]->Draw == NULL) Con_Printf("Map %s could not be found or downloaded\n", cl.model_name[1]); // normal models for (i = 2;i < MAX_MODELS && cl.model_name[i][0];i++) - if ((cl.model_precache[i] = Mod_ForName(cl.model_name[i], false, false, false))->Draw == NULL) + if ((cl.model_precache[i] = Mod_ForName(cl.model_name[i], false, false, cl.model_name[i][0] == '*' ? cl.model_name[1] : NULL))->Draw == NULL) Con_Printf("Model %s could not be found or downloaded\n", cl.model_name[i]); // check memory integrity @@ -603,9 +632,8 @@ static void QW_CL_RequestNextDownload(void) cls.qw_downloadtype = dl_none; - // load new sounds and unload old ones - // FIXME: S_ServerSounds does not know about cl.sfx_ sounds - S_ServerSounds(cl.sound_name, cls.qw_downloadnumber); + // clear sound usage flags for purging of unused sounds + S_ClearUsed(); // precache any sounds used by the client cl.sfx_wizhit = S_PrecacheSound(cl_sound_wizardhit.string, false, true); @@ -616,12 +644,12 @@ static void QW_CL_RequestNextDownload(void) cl.sfx_ric3 = S_PrecacheSound(cl_sound_ric3.string, false, true); cl.sfx_r_exp3 = S_PrecacheSound(cl_sound_r_exp3.string, false, true); - // sounds + // sounds used by the game for (i = 1;i < MAX_SOUNDS && cl.sound_name[i][0];i++) - { - // Don't lock the sfx here, S_ServerSounds already did that - cl.sound_precache[i] = S_PrecacheSound(cl.sound_name[i], true, false); - } + cl.sound_precache[i] = S_PrecacheSound(cl.sound_name[i], true, true); + + // we purge the models and sounds later in CL_SignonReply + //S_PurgeUnused(); // check memory integrity Mem_CheckSentinelsGlobal(); @@ -960,6 +988,11 @@ static void CL_UpdateItemsAndWeapon(void) cl.activeweapon = cl.stats[STAT_ACTIVEWEAPON]; } +#define LOADPROGRESSWEIGHT_SOUND 1.0 +#define LOADPROGRESSWEIGHT_MODEL 4.0 +#define LOADPROGRESSWEIGHT_WORLDMODEL 30.0 +#define LOADPROGRESSWEIGHT_WORLDMODEL_INIT 2.0 + void CL_BeginDownloads(qboolean aborteddownload) { // quakeworld works differently @@ -975,6 +1008,8 @@ void CL_BeginDownloads(qboolean aborteddownload) // if we got here... // curl is done, so let's start with the business + if(!cl.loadbegun) + SCR_PushLoadingScreen(false, "Loading precaches", 1); cl.loadbegun = true; // if already downloading something from the previous level, don't stop it @@ -1006,18 +1041,68 @@ void CL_BeginDownloads(qboolean aborteddownload) if (cl.loadmodel_current < cl.loadmodel_total) { // loading models - + if(cl.loadmodel_current == 1) + { + // worldmodel counts as 16 models (15 + world model setup), for better progress bar + SCR_PushLoadingScreen(false, "Loading precached models", + ( + (cl.loadmodel_total - 1) * LOADPROGRESSWEIGHT_MODEL + + LOADPROGRESSWEIGHT_WORLDMODEL + + LOADPROGRESSWEIGHT_WORLDMODEL_INIT + ) / ( + (cl.loadmodel_total - 1) * LOADPROGRESSWEIGHT_MODEL + + LOADPROGRESSWEIGHT_WORLDMODEL + + LOADPROGRESSWEIGHT_WORLDMODEL_INIT + + cl.loadsound_total * LOADPROGRESSWEIGHT_SOUND + ) + ); + SCR_BeginLoadingPlaque(); + } for (;cl.loadmodel_current < cl.loadmodel_total;cl.loadmodel_current++) { + SCR_PushLoadingScreen(false, cl.model_name[cl.loadmodel_current], + ( + (cl.loadmodel_current == 1) ? LOADPROGRESSWEIGHT_WORLDMODEL : LOADPROGRESSWEIGHT_MODEL + ) / ( + (cl.loadmodel_total - 1) * LOADPROGRESSWEIGHT_MODEL + + LOADPROGRESSWEIGHT_WORLDMODEL + + LOADPROGRESSWEIGHT_WORLDMODEL_INIT + ) + ); if (cl.model_precache[cl.loadmodel_current] && cl.model_precache[cl.loadmodel_current]->Draw) + { + SCR_PopLoadingScreen(false); + if(cl.loadmodel_current == 1) + { + SCR_PushLoadingScreen(false, cl.model_name[cl.loadmodel_current], 1.0 / cl.loadmodel_total); + SCR_PopLoadingScreen(false); + } continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); - cl.model_precache[cl.loadmodel_current] = Mod_ForName(cl.model_name[cl.loadmodel_current], false, false, cl.loadmodel_current == 1); + } + CL_KeepaliveMessage(true); + + if(cl.loadmodel_current == 1) + { + // they'll be soon loaded, but make sure we apply freshly downloaded shaders from a curled pk3 + Mod_FreeQ3Shaders(); + } + + cl.model_precache[cl.loadmodel_current] = Mod_ForName(cl.model_name[cl.loadmodel_current], false, false, cl.model_name[cl.loadmodel_current][0] == '*' ? cl.model_name[1] : NULL); + SCR_PopLoadingScreen(false); if (cl.model_precache[cl.loadmodel_current] && cl.model_precache[cl.loadmodel_current]->Draw && cl.loadmodel_current == 1) { // we now have the worldmodel so we can set up the game world + SCR_PushLoadingScreen(true, "world model setup", + ( + LOADPROGRESSWEIGHT_WORLDMODEL_INIT + ) / ( + (cl.loadmodel_total - 1) * LOADPROGRESSWEIGHT_MODEL + + LOADPROGRESSWEIGHT_WORLDMODEL + + LOADPROGRESSWEIGHT_WORLDMODEL_INIT + ) + ); CL_SetupWorldModel(); + SCR_PopLoadingScreen(true); if (!cl.loadfinished && cl_joinbeforedownloadsfinish.integer) { cl.loadfinished = true; @@ -1027,24 +1112,37 @@ void CL_BeginDownloads(qboolean aborteddownload) } } } - + SCR_PopLoadingScreen(false); // finished loading models } if (cl.loadsound_current < cl.loadsound_total) { // loading sounds - + if(cl.loadsound_current == 1) + SCR_PushLoadingScreen(false, "Loading precached sounds", + ( + cl.loadsound_total * LOADPROGRESSWEIGHT_SOUND + ) / ( + (cl.loadmodel_total - 1) * LOADPROGRESSWEIGHT_MODEL + + LOADPROGRESSWEIGHT_WORLDMODEL + + LOADPROGRESSWEIGHT_WORLDMODEL_INIT + + cl.loadsound_total * LOADPROGRESSWEIGHT_SOUND + ) + ); for (;cl.loadsound_current < cl.loadsound_total;cl.loadsound_current++) { + SCR_PushLoadingScreen(false, cl.sound_name[cl.loadsound_current], 1.0 / cl.loadsound_total); if (cl.sound_precache[cl.loadsound_current] && S_IsSoundPrecached(cl.sound_precache[cl.loadsound_current])) + { + SCR_PopLoadingScreen(false); continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); - // Don't lock the sfx here, S_ServerSounds already did that - cl.sound_precache[cl.loadsound_current] = S_PrecacheSound(cl.sound_name[cl.loadsound_current], false, false); + } + CL_KeepaliveMessage(true); + cl.sound_precache[cl.loadsound_current] = S_PrecacheSound(cl.sound_name[cl.loadsound_current], false, true); + SCR_PopLoadingScreen(false); } - + SCR_PopLoadingScreen(false); // finished loading sounds } @@ -1069,9 +1167,11 @@ void CL_BeginDownloads(qboolean aborteddownload) { if (aborteddownload) { + if (cl.downloadmodel_current == 1) { // the worldmodel failed, but we need to set up anyway + Mod_FreeQ3Shaders(); CL_SetupWorldModel(); if (!cl.loadfinished && cl_joinbeforedownloadsfinish.integer) { @@ -1086,9 +1186,8 @@ void CL_BeginDownloads(qboolean aborteddownload) } if (cl.model_precache[cl.downloadmodel_current] && cl.model_precache[cl.downloadmodel_current]->Draw) continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); - if (strcmp(cl.model_name[cl.downloadmodel_current], "null") && !FS_FileExists(cl.model_name[cl.downloadmodel_current])) + CL_KeepaliveMessage(true); + if (cl.model_name[cl.downloadmodel_current][0] != '*' && strcmp(cl.model_name[cl.downloadmodel_current], "null") && !FS_FileExists(cl.model_name[cl.downloadmodel_current])) { if (cl.downloadmodel_current == 1) Con_Printf("Map %s not found\n", cl.model_name[cl.downloadmodel_current]); @@ -1102,7 +1201,14 @@ void CL_BeginDownloads(qboolean aborteddownload) return; } } - cl.model_precache[cl.downloadmodel_current] = Mod_ForName(cl.model_name[cl.downloadmodel_current], false, false, cl.downloadmodel_current == 1); + + if(cl.downloadmodel_current == 1) + { + // they'll be soon loaded, but make sure we apply freshly downloaded shaders from a curled pk3 + Mod_FreeQ3Shaders(); + } + + cl.model_precache[cl.downloadmodel_current] = Mod_ForName(cl.model_name[cl.downloadmodel_current], false, false, cl.model_name[cl.downloadmodel_current][0] == '*' ? cl.model_name[1] : NULL); if (cl.downloadmodel_current == 1) { // we now have the worldmodel so we can set up the game world @@ -1136,8 +1242,7 @@ void CL_BeginDownloads(qboolean aborteddownload) } if (cl.sound_precache[cl.downloadsound_current] && S_IsSoundPrecached(cl.sound_precache[cl.downloadsound_current])) continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); + CL_KeepaliveMessage(true); dpsnprintf(soundname, sizeof(soundname), "sound/%s", cl.sound_name[cl.downloadsound_current]); if (!FS_FileExists(soundname) && !FS_FileExists(cl.sound_name[cl.downloadsound_current])) { @@ -1149,13 +1254,14 @@ void CL_BeginDownloads(qboolean aborteddownload) return; } } - // Don't lock the sfx here, S_ServerSounds already did that - cl.sound_precache[cl.downloadsound_current] = S_PrecacheSound(cl.sound_name[cl.downloadsound_current], false, false); + cl.sound_precache[cl.downloadsound_current] = S_PrecacheSound(cl.sound_name[cl.downloadsound_current], false, true); } // finished loading sounds } + SCR_PopLoadingScreen(false); + if (!cl.loadfinished) { cl.loadfinished = true; @@ -1432,6 +1538,13 @@ static void CL_SignonReply (void) break; case 4: + // after the level has been loaded, we shouldn't need the shaders, and + // if they are needed again they will be automatically loaded... + // we also don't need the unused models or sounds from the last level + Mod_FreeQ3Shaders(); + Mod_PurgeUnused(); + S_PurgeUnused(); + Con_ClearNotify(); if (COM_CheckParm("-profilegameonly")) Sys_AllowProfiling(true); @@ -1458,6 +1571,8 @@ void CL_ParseServerInfo (void) { SCR_BeginLoadingPlaque(); S_StopAllSounds(); + // free q3 shaders so that any newly downloaded shaders will be active + Mod_FreeQ3Shaders(); } // check memory integrity @@ -1618,17 +1733,19 @@ void CL_ParseServerInfo (void) if (!sv.active) Mod_ClearUsed(); for (i = 1;i < nummodels;i++) - Mod_FindName(cl.model_name[i]); + Mod_FindName(cl.model_name[i], cl.model_name[i][0] == '*' ? cl.model_name[1] : NULL); // precache any models used by the client (this also marks them used) - cl.model_bolt = Mod_ForName("progs/bolt.mdl", false, false, false); - cl.model_bolt2 = Mod_ForName("progs/bolt2.mdl", false, false, false); - cl.model_bolt3 = Mod_ForName("progs/bolt3.mdl", false, false, false); - cl.model_beam = Mod_ForName("progs/beam.mdl", false, false, false); - Mod_PurgeUnused(); + cl.model_bolt = Mod_ForName("progs/bolt.mdl", false, false, NULL); + cl.model_bolt2 = Mod_ForName("progs/bolt2.mdl", false, false, NULL); + cl.model_bolt3 = Mod_ForName("progs/bolt3.mdl", false, false, NULL); + cl.model_beam = Mod_ForName("progs/beam.mdl", false, false, NULL); - // do the same for sounds - // FIXME: S_ServerSounds does not know about cl.sfx_ sounds - S_ServerSounds (cl.sound_name, numsounds); + // we purge the models and sounds later in CL_SignonReply + //Mod_PurgeUnused(); + //S_PurgeUnused(); + + // clear sound usage flags for purging of unused sounds + S_ClearUsed(); // precache any sounds used by the client cl.sfx_wizhit = S_PrecacheSound(cl_sound_wizardhit.string, false, true); @@ -1639,6 +1756,10 @@ void CL_ParseServerInfo (void) cl.sfx_ric3 = S_PrecacheSound(cl_sound_ric3.string, false, true); cl.sfx_r_exp3 = S_PrecacheSound(cl_sound_r_exp3.string, false, true); + // sounds used by the game + for (i = 1;i < MAX_SOUNDS && cl.sound_name[i][0];i++) + cl.sound_precache[i] = S_PrecacheSound(cl.sound_name[i], true, true); + // now we try to load everything that is new cl.loadmodel_current = 1; cl.downloadmodel_current = 1; @@ -1731,9 +1852,9 @@ void CL_MoveLerpEntityStates(entity_t *ent) VectorCopy(ent->state_current.origin, ent->persistent.neworigin); VectorCopy(ent->state_current.angles, ent->persistent.newangles); // reset animation interpolation as well - ent->render.frame1 = ent->render.frame2 = ent->state_current.frame; - ent->render.frame1time = ent->render.frame2time = cl.time; - ent->render.framelerp = 1; + ent->render.framegroupblend[0].frame = ent->render.framegroupblend[1].frame = ent->state_current.frame; + ent->render.framegroupblend[0].start = ent->render.framegroupblend[1].start = cl.time; + ent->render.framegroupblend[0].lerp = 1;ent->render.framegroupblend[1].lerp = 0; ent->render.shadertime = cl.time; // reset various persistent stuff ent->persistent.muzzleflash = 0; @@ -1750,13 +1871,14 @@ void CL_MoveLerpEntityStates(entity_t *ent) VectorCopy(ent->state_current.angles, ent->persistent.newangles); ent->persistent.trail_allowed = false; - if(ent->state_current.frame != ent->state_previous.frame) + // if(ent->state_current.frame != ent->state_previous.frame) + // do this even if we did change the frame + // teleport bit is only used if an animation restart, or a jump, is necessary + // so it should be always harmless to do this { - // if we ALSO changed animation frame in the process (but ONLY then!) - // then let's reset the animation interpolation too - ent->render.frame1 = ent->render.frame2 = ent->state_current.frame; - ent->render.frame1time = ent->render.frame2time = cl.time; - ent->render.framelerp = 1; + ent->render.framegroupblend[0].frame = ent->render.framegroupblend[1].frame = ent->state_current.frame; + ent->render.framegroupblend[0].start = ent->render.framegroupblend[1].start = cl.time; + ent->render.framegroupblend[0].lerp = 1;ent->render.framegroupblend[1].lerp = 0; } // note that this case must do everything the following case does too @@ -1994,10 +2116,10 @@ void CL_ParseStatic (int large) // copy it to the current state ent->render.model = cl.model_precache[ent->state_baseline.modelindex]; - ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame; - ent->render.framelerp = 0; + ent->render.framegroupblend[0].frame = ent->state_baseline.frame; + ent->render.framegroupblend[0].lerp = 1; // make torchs play out of sync - ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1); + ent->render.framegroupblend[0].start = lhrandom(-10, -1); ent->render.skinnum = ent->state_baseline.skin; ent->render.effects = ent->state_baseline.effects; ent->render.alpha = 1; @@ -2580,7 +2702,7 @@ void CL_ParseTempEntity(void) // LordHavoc: for compatibility with the Nehahra movie... case TE_LIGHTNING4NEH: - CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, false), false); + CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, NULL), false); break; case TE_LAVASPLASH: @@ -3091,8 +3213,7 @@ void CL_ParseServerMessage(void) cl.last_received_message = realtime; - if (cls.netcon && cls.signon < SIGNONS) - CL_KeepaliveMessage(false); + CL_KeepaliveMessage(false); // // if recording demos, copy the message out @@ -3647,7 +3768,7 @@ void CL_ParseServerMessage(void) { if (i >= 1 && i < MAX_MODELS) { - dp_model_t *model = Mod_ForName(s, false, false, i == 1); + dp_model_t *model = Mod_ForName(s, false, false, s[0] == '*' ? cl.model_name[1] : NULL); if (!model) Con_DPrintf("svc_precache: Mod_ForName(\"%s\") failed\n", s); cl.model_precache[i] = model; @@ -3660,7 +3781,7 @@ void CL_ParseServerMessage(void) i -= 32768; if (i >= 1 && i < MAX_SOUNDS) { - sfx_t *sfx = S_PrecacheSound (s, true, false); + sfx_t *sfx = S_PrecacheSound (s, true, true); if (!sfx && snd_initialized.integer) Con_DPrintf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s); cl.sound_precache[i] = sfx;