X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=cl_parse.c;h=e924b18776551cdaa3b859640f6b1307fc35b405;hb=0f4c8bdd8ede5278bd3ee4ea912d66044dc5b42b;hp=3d0688174a88bc88f236bee3795d4dfc0d1e40bc;hpb=02fbf74f00e8f81d6e4cbb9ebdf93f6eb374a8da;p=xonotic%2Fdarkplaces.git diff --git a/cl_parse.c b/cl_parse.c index 3d068817..e924b187 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -290,6 +290,7 @@ void CL_KeepaliveMessage (qboolean readmessages) { float time; static double nextmsg = -1; + static double nextupdate = -1; #if 0 static double lasttime = -1; #endif @@ -297,6 +298,15 @@ void CL_KeepaliveMessage (qboolean readmessages) 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 || cls.signon >= SIGNONS) return; @@ -381,10 +391,12 @@ void CL_ParseEntityLump(char *entdata) r_refdef.fog_start = 0; r_refdef.fog_alpha = 1; r_refdef.fog_end = 16384; + r_refdef.fog_height = 1<<30; + r_refdef.fog_fadedepth = 128; #if _MSC_VER >= 1400 #define sscanf sscanf_s #endif - sscanf(value, "%f %f %f %f %f %f %f", &r_refdef.fog_density, &r_refdef.fog_red, &r_refdef.fog_green, &r_refdef.fog_blue, &r_refdef.fog_alpha, &r_refdef.fog_start, &r_refdef.fog_end); + sscanf(value, "%f %f %f %f %f %f %f %f %f", &r_refdef.fog_density, &r_refdef.fog_red, &r_refdef.fog_green, &r_refdef.fog_blue, &r_refdef.fog_alpha, &r_refdef.fog_start, &r_refdef.fog_end, &r_refdef.fog_height, &r_refdef.fog_fadedepth); } else if (!strcmp("fog_density", key)) r_refdef.fog_density = atof(value); @@ -400,6 +412,10 @@ void CL_ParseEntityLump(char *entdata) r_refdef.fog_start = atof(value); else if (!strcmp("fog_end", key)) r_refdef.fog_end = atof(value); + else if (!strcmp("fog_height", key)) + r_refdef.fog_height = atof(value); + else if (!strcmp("fog_fadedepth", key)) + r_refdef.fog_fadedepth = atof(value); } } @@ -410,7 +426,7 @@ static const vec3_t defaultmaxs = {4096, 4096, 4096}; static void CL_SetupWorldModel(void) { // update the world model - cl.entities[0].render.model = cl.worldmodel = cl.model_precache[1]; + cl.entities[0].render.model = cl.worldmodel = CL_GetModelByIndex(1); CL_UpdateRenderEntity(&cl.entities[0].render); // set up csqc world for collision culling @@ -418,6 +434,7 @@ static void CL_SetupWorldModel(void) World_SetSize(&cl.world, cl.worldmodel->name, cl.worldmodel->normalmins, cl.worldmodel->normalmaxs); else World_SetSize(&cl.world, "", defaultmins, defaultmaxs); + World_Start(&cl.world); // load or reload .loc file for team chat messages CL_Locs_Reload_f(); @@ -566,7 +583,9 @@ static void QW_CL_RequestNextDownload(void) 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); - Mod_PurgeUnused(); + + // we purge the models and sounds later in CL_SignonReply + //Mod_PurgeUnused(); // now we try to load everything that is new @@ -620,9 +639,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); @@ -633,12 +651,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(); @@ -977,6 +995,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 @@ -1028,12 +1051,31 @@ void CL_BeginDownloads(qboolean aborteddownload) 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 + 15) / (float) (cl.loadmodel_total + cl.loadsound_total + 15)); + 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(true, cl.model_name[cl.loadmodel_current], (cl.loadmodel_current == 1 ? 15.0 : 1.0) / cl.loadmodel_total); + 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); @@ -1057,7 +1099,15 @@ void CL_BeginDownloads(qboolean aborteddownload) 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", 1.0 / cl.loadmodel_total); + 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) @@ -1077,18 +1127,26 @@ void CL_BeginDownloads(qboolean aborteddownload) { // loading sounds if(cl.loadsound_current == 1) - SCR_PushLoadingScreen(false, "Loading precached sounds", cl.loadsound_total / (float) (cl.loadmodel_total + cl.loadsound_total + 15)); + 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(true, cl.sound_name[cl.loadsound_current], 1.0 / cl.loadsound_total); + 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; } 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.sound_precache[cl.loadsound_current] = S_PrecacheSound(cl.sound_name[cl.loadsound_current], false, true); SCR_PopLoadingScreen(false); } SCR_PopLoadingScreen(false); @@ -1151,7 +1209,7 @@ void CL_BeginDownloads(qboolean aborteddownload) } } - if(cl.loadmodel_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(); @@ -1203,8 +1261,7 @@ 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 @@ -1249,9 +1306,18 @@ void CL_StopDownload(int size, int crc) size_t inflated_size; out = FS_Inflate(cls.qw_downloadmemory, cls.qw_downloadmemorycursize, &inflated_size, tempmempool); Mem_Free(cls.qw_downloadmemory); - Con_Printf("Inflated download: new size: %u (%g%%)\n", (unsigned)inflated_size, 100.0 - 100.0*(cls.qw_downloadmemorycursize / (float)inflated_size)); - cls.qw_downloadmemory = out; - cls.qw_downloadmemorycursize = inflated_size; + if(out) + { + Con_Printf("Inflated download: new size: %u (%g%%)\n", (unsigned)inflated_size, 100.0 - 100.0*(cls.qw_downloadmemorycursize / (float)inflated_size)); + cls.qw_downloadmemory = out; + cls.qw_downloadmemorycursize = inflated_size; + } + else + { + cls.qw_downloadmemory = NULL; + cls.qw_downloadmemorycursize = 0; + Con_Printf("Cannot inflate download, possibly corrupt or zlib not present\n"); + } } if(!cls.qw_downloadmemory) @@ -1314,7 +1380,7 @@ void CL_StopDownload(int size, int crc) void CL_ParseDownload(void) { int i, start, size; - unsigned char data[65536]; + unsigned char data[NET_MAXMESSAGE]; start = MSG_ReadLong(); size = (unsigned short)MSG_ReadShort(); @@ -1490,7 +1556,10 @@ static void CL_SignonReply (void) 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")) @@ -1686,11 +1755,13 @@ void CL_ParseServerInfo (void) 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); - Mod_PurgeUnused(); - // 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); @@ -1701,6 +1772,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; @@ -1771,7 +1846,7 @@ void CL_ValidateState(entity_state_t *s) if (!(s->flags & RENDER_COLORMAPPED) && s->colormap > cl.maxclients) Con_DPrintf("CL_ValidateState: colormap (%i) > cl.maxclients (%i)\n", s->colormap, cl.maxclients); - model = cl.model_precache[s->modelindex]; + model = CL_GetModelByIndex(s->modelindex); if (model && model->type && s->frame >= model->numframes) Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\" (which has %i frames)\n", s->frame, model->name, model->numframes); if (model && model->type && s->skin > 0 && s->skin >= model->numskins && !(s->lightpflags & PFLAGS_FULLDYNAMIC)) @@ -1812,10 +1887,11 @@ 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.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; @@ -1823,6 +1899,14 @@ void CL_MoveLerpEntityStates(entity_t *ent) // note that this case must do everything the following case does too } + else if ((ent->state_previous.effects & EF_RESTARTANIM_BIT) != (ent->state_current.effects & EF_RESTARTANIM_BIT)) + { + ent->render.framegroupblend[1] = ent->render.framegroupblend[0]; + ent->render.framegroupblend[1].lerp = 1; + ent->render.framegroupblend[0].frame = ent->state_current.frame; + ent->render.framegroupblend[0].start = cl.time; + ent->render.framegroupblend[0].lerp = 0; + } else if (DotProduct(odelta, odelta) > 1000*1000 || (cl.fixangle[0] && !cl.fixangle[1]) || (ent->state_previous.tagindex != ent->state_current.tagindex) @@ -2055,7 +2139,7 @@ void CL_ParseStatic (int large) } // copy it to the current state - ent->render.model = cl.model_precache[ent->state_baseline.modelindex]; + ent->render.model = CL_GetModelByIndex(ent->state_baseline.modelindex); ent->render.framegroupblend[0].frame = ent->state_baseline.frame; ent->render.framegroupblend[0].lerp = 1; // make torchs play out of sync @@ -2068,6 +2152,7 @@ void CL_ParseStatic (int large) //VectorCopy (ent->state_baseline.angles, ent->render.angles); Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2], ent->state_baseline.angles[0], ent->state_baseline.angles[1], ent->state_baseline.angles[2], 1); + ent->render.allowdecals = true; CL_UpdateRenderEntity(&ent->render); } @@ -2925,7 +3010,7 @@ qboolean CL_ExaminePrintString(const char *text) if (cl.parsingtextmode == CL_PARSETEXTMODE_PING) { // if anything goes wrong, we'll assume this is not a ping report - qboolean expected = cl.parsingtextexpectingpingforscores; + qboolean expected = cl.parsingtextexpectingpingforscores != 0; cl.parsingtextexpectingpingforscores = 0; cl.parsingtextmode = CL_PARSETEXTMODE_NONE; t = text; @@ -3043,7 +3128,7 @@ static void CL_NetworkTimeReceived(double newtime) double timehigh; cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = newtime; - if (cls.timedemo || (cl.islocalgame && !sv_fixedframeratesingleplayer.integer) || cl.mtime[1] == cl.mtime[0] || cls.signon < SIGNONS) + if (cl_nolerp.integer || cls.timedemo || (cl.islocalgame && !sv_fixedframeratesingleplayer.integer) || cl.mtime[1] == cl.mtime[0] || cls.signon < SIGNONS) cl.time = cl.mtime[1] = newtime; else if (cls.demoplayback) { @@ -3117,6 +3202,9 @@ static void CL_NetworkTimeReceived(double newtime) VectorCopy(cl.mviewangles[0], cl.mviewangles[1]); // update the csqc's server timestamps, critical for proper sync CSQC_UpdateNetworkTimes(cl.mtime[0], cl.mtime[1]); + + if (cl.mtime[0] > cl.mtime[1]) + World_Physics_Frame(&cl.world, cl.mtime[0] - cl.mtime[1], cl.movevars_gravity); } #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf("%3i:%s(%i)\n", msg_readcount-1, x, cmd); @@ -3507,7 +3595,7 @@ void CL_ParseServerMessage(void) break; case qw_svc_setpause: - cl.paused = MSG_ReadByte (); + cl.paused = MSG_ReadByte () != 0; if (cl.paused) CDAudio_Pause (); else @@ -3721,7 +3809,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; @@ -3798,7 +3886,7 @@ void CL_ParseServerMessage(void) break; case svc_setpause: - cl.paused = MSG_ReadByte (); + cl.paused = MSG_ReadByte () != 0; if (cl.paused) CDAudio_Pause (); else