]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_parse.c
changed brush model API - now uses function pointers for some of the brush model...
[xonotic/darkplaces.git] / cl_parse.c
index 7aee6a555440ffb0377ded50e1e17e4681beb63a..357b47c3783a60837bf10d8b0568e26432ae0257 100644 (file)
@@ -99,6 +99,8 @@ cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
 
+mempool_t *cl_scores_mempool;
+
 /*
 ==================
 CL_ParseStartSoundPacket
@@ -106,28 +108,39 @@ CL_ParseStartSoundPacket
 */
 void CL_ParseStartSoundPacket(int largesoundindex)
 {
-    vec3_t  pos;
-    int        channel, ent;
-    int        sound_num;
-    int        volume;
-    int        field_mask;
-    float      attenuation;
-       int             i;
-                  
-    field_mask = MSG_ReadByte();
-
-    if (field_mask & SND_VOLUME)
+       vec3_t  pos;
+       int     channel, ent;
+       int     sound_num;
+       int     volume;
+       int     field_mask;
+       float   attenuation;
+       int             i;
+
+       field_mask = MSG_ReadByte();
+
+       if (field_mask & SND_VOLUME)
                volume = MSG_ReadByte ();
        else
                volume = DEFAULT_SOUND_PACKET_VOLUME;
-       
-    if (field_mask & SND_ATTENUATION)
+
+       if (field_mask & SND_ATTENUATION)
                attenuation = MSG_ReadByte () / 64.0;
        else
                attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
-       
-       channel = MSG_ReadShort ();
-       if (largesoundindex)
+
+       if (field_mask & SND_LARGEENTITY)
+       {
+               ent = (unsigned short) MSG_ReadShort ();
+               channel = MSG_ReadByte ();
+       }
+       else
+       {
+               channel = (unsigned short) MSG_ReadShort ();
+               ent = channel >> 3;
+               channel &= 7;
+       }
+
+       if (largesoundindex || field_mask & SND_LARGESOUND)
                sound_num = (unsigned short) MSG_ReadShort ();
        else
                sound_num = MSG_ReadByte ();
@@ -135,16 +148,14 @@ void CL_ParseStartSoundPacket(int largesoundindex)
        if (sound_num >= MAX_SOUNDS)
                Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
 
-       ent = channel >> 3;
-       channel &= 7;
 
-       if (ent > MAX_EDICTS)
+       if (ent >= MAX_EDICTS)
                Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
-       
-       for (i=0 ; i<3 ; i++)
+
+       for (i = 0;i < 3;i++)
                pos[i] = MSG_ReadCoord ();
 
-    S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
+       S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
 }
 
 /*
@@ -155,59 +166,44 @@ When the client is taking a long time to load stuff, send keepalive messages
 so the server doesn't disconnect.
 ==================
 */
+
+static qbyte olddata[NET_MAXMESSAGE];
 void CL_KeepaliveMessage (void)
 {
-       float   time;
+       float time;
        static float lastmsg;
-       int             ret;
-       int             c;
-       sizebuf_t       old;
-       qbyte           olddata[8192];
-       
-       if (sv.active)
-               return;         // no need if server is local
-       if (cls.demoplayback)
+       int oldreadcount;
+       qboolean oldbadread;
+       sizebuf_t old;
+
+       // no need if server is local and definitely not if this is a demo
+       if (sv.active || cls.demoplayback)
                return;
 
 // read messages from server, should just be nops
+       oldreadcount = msg_readcount;
+       oldbadread = msg_badread;
        old = net_message;
-       memcpy (olddata, net_message.data, net_message.cursize);
-       
-       do
-       {
-               ret = CL_GetMessage ();
-               switch (ret)
-               {
-               default:
-                       Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
-               case 0:
-                       break;  // nothing waiting
-               case 1:
-                       Host_Error ("CL_KeepaliveMessage: received a message");
-                       break;
-               case 2:
-                       c = MSG_ReadByte();
-                       if (c != svc_nop)
-                               Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
-                       break;
-               }
-       } while (ret);
+       memcpy(olddata, net_message.data, net_message.cursize);
 
-       net_message = old;
-       memcpy (net_message.data, olddata, net_message.cursize);
+       NetConn_ClientFrame();
 
-// check time
-       time = Sys_DoubleTime ();
-       if (time - lastmsg < 5)
-               return;
-       lastmsg = time;
-
-// write out a nop
-       Con_Printf ("--> client to server keepalive\n");
+       msg_readcount = oldreadcount;
+       msg_badread = oldbadread;
+       net_message = old;
+       memcpy(net_message.data, olddata, net_message.cursize);
 
-       MSG_WriteByte (&cls.message, clc_nop);
-       NET_SendMessage (cls.netcon, &cls.message);
-       SZ_Clear (&cls.message);
+       if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5)
+       {
+               lastmsg = time;
+               // write out a nop
+               Con_Printf("--> client to server keepalive\n");
+               MSG_WriteByte(&cls.message, clc_nop);
+               NetConn_SendReliableMessage(cls.netcon, &cls.message);
+               SZ_Clear(&cls.message);
+               // try not to utterly crush the computer with work, that's just rude
+               Sys_Sleep();
+       }
 }
 
 void CL_ParseEntityLump(char *entdata)
@@ -311,13 +307,14 @@ CL_ParseServerInfo
 ==================
 */
 qbyte entlife[MAX_EDICTS];
+// FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
+static char parse_model_precache[MAX_MODELS][MAX_QPATH];
+static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
 void CL_ParseServerInfo (void)
 {
        char *str;
        int i;
        int nummodels, numsounds;
-       char model_precache[MAX_MODELS][MAX_QPATH];
-       char sound_precache[MAX_SOUNDS][MAX_QPATH];
        entity_t *ent;
 
        Con_DPrintf ("Serverinfo packet received.\n");
@@ -349,6 +346,7 @@ void CL_ParseServerInfo (void)
                Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
                return;
        }
+       Mem_EmptyPool(cl_scores_mempool);
        cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
 
 // parse gametype
@@ -387,7 +385,7 @@ void CL_ParseServerInfo (void)
                        Host_Error ("Server sent too many model precaches\n");
                if (strlen(str) >= MAX_QPATH)
                        Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
-               strcpy (model_precache[nummodels], str);
+               strcpy (parse_model_precache[nummodels], str);
                Mod_TouchModel (str);
        }
 
@@ -402,7 +400,7 @@ void CL_ParseServerInfo (void)
                        Host_Error ("Server sent too many sound precaches\n");
                if (strlen(str) >= MAX_QPATH)
                        Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
-               strcpy (sound_precache[numsounds], str);
+               strcpy (parse_sound_precache[numsounds], str);
                S_TouchSound (str);
        }
 
@@ -413,16 +411,16 @@ void CL_ParseServerInfo (void)
 
        // world model
        CL_KeepaliveMessage ();
-       cl.model_precache[1] = Mod_ForName (model_precache[1], false, false, true);
+       cl.model_precache[1] = Mod_ForName (parse_model_precache[1], false, false, true);
        if (cl.model_precache[1] == NULL)
-               Con_Printf("Map %s not found\n", model_precache[1]);
+               Con_Printf("Map %s not found\n", parse_model_precache[1]);
 
        // normal models
        for (i=2 ; i<nummodels ; i++)
        {
                CL_KeepaliveMessage ();
-               if ((cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, false)) == NULL)
-                       Con_Printf("Model %s not found\n", model_precache[i]);
+               if ((cl.model_precache[i] = Mod_ForName (parse_model_precache[i], false, false, false)) == NULL)
+                       Con_Printf("Model %s not found\n", parse_model_precache[i]);
        }
 
        // sounds
@@ -430,7 +428,7 @@ void CL_ParseServerInfo (void)
        for (i=1 ; i<numsounds ; i++)
        {
                CL_KeepaliveMessage ();
-               cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
+               cl.sound_precache[i] = S_PrecacheSound (parse_sound_precache[i], true);
        }
        S_EndPrecaching ();
 
@@ -439,15 +437,18 @@ void CL_ParseServerInfo (void)
        // entire entity array was cleared, so just fill in a few fields
        ent->state_current.active = true;
        ent->render.model = cl.worldmodel = cl.model_precache[1];
-       ent->render.scale = 1;
+       //ent->render.scale = 1;
        ent->render.alpha = 1;
+       ent->render.flags = RENDER_SHADOW;
+       Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
+       Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
        CL_BoundingBoxForEntity(&ent->render);
        // clear entlife array
        memset(entlife, 0, MAX_EDICTS);
 
        cl_num_entities = 1;
 
-       R_NewMap ();
+       R_Modules_NewMap ();
        CL_CGVM_Start();
 
        // noclip is turned off at start
@@ -500,7 +501,7 @@ void CL_MoveLerpEntityStates(entity_t *ent)
                VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
                VectorCopy(ent->state_current.angles, ent->persistent.newangles);
        }
-       else// if (ent->state_current.flags & RENDER_STEP)
+       else if (ent->state_current.flags & RENDER_STEP)
        {
                // monster interpolation
                if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
@@ -513,22 +514,20 @@ void CL_MoveLerpEntityStates(entity_t *ent)
                        VectorCopy(ent->state_current.angles, ent->persistent.newangles);
                }
        }
-       /*
        else
        {
                // not a monster
                ent->persistent.lerpstarttime = cl.mtime[1];
                // no lerp if it's singleplayer
-               //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
-               //      ent->persistent.lerpdeltatime = 0;
-               //else
+               if (sv.active && svs.maxclients == 1)
+                       ent->persistent.lerpdeltatime = 0;
+               else
                        ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
                VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
                VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
                VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
                VectorCopy(ent->state_current.angles, ent->persistent.newangles);
        }
-       */
 }
 
 /*
@@ -640,10 +639,10 @@ void CL_ParseUpdate (int bits)
        }
 }
 
+static entity_frame_t entityframe;
 void CL_ReadEntityFrame(void)
 {
        entity_t *ent;
-       entity_frame_t entityframe;
        int i;
        EntityFrame_Read(&cl.entitydatabase);
        EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
@@ -658,8 +657,6 @@ void CL_ReadEntityFrame(void)
                entlife[ent->state_current.number] = 2;
                cl_entities_active[ent->state_current.number] = true;
        }
-       VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
-       VectorCopy(entityframe.eye, cl.viewentoriginnew);
 }
 
 void CL_EntityUpdateSetup(void)
@@ -838,12 +835,13 @@ void CL_ParseStatic (int large)
        ent->render.skinnum = ent->state_baseline.skin;
        ent->render.effects = ent->state_baseline.effects;
        ent->render.alpha = 1;
-       ent->render.scale = 1;
-       ent->render.alpha = 1;
+       //ent->render.scale = 1;
 
-       VectorCopy (ent->state_baseline.origin, ent->render.origin);
-       VectorCopy (ent->state_baseline.angles, ent->render.angles);
+       //VectorCopy (ent->state_baseline.origin, ent->render.origin);
+       //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);
+       Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
        CL_BoundingBoxForEntity(&ent->render);
 
        // This is definitely cheating...
@@ -929,7 +927,7 @@ void CL_InitTEnts (void)
        cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
 }
 
-void CL_ParseBeam (model_t *m)
+void CL_ParseBeam (model_t *m, int lightning)
 {
        int i, ent;
        vec3_t start, end;
@@ -939,12 +937,20 @@ void CL_ParseBeam (model_t *m)
        MSG_ReadVector(start);
        MSG_ReadVector(end);
 
+       if (ent >= MAX_EDICTS)
+       {
+               Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
+               ent = 0;
+       }
+
        // override any beam with the same entity
        for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
        {
                if (b->entity == ent)
                {
                        //b->entity = ent;
+                       b->lightning = lightning;
+                       b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
                        b->model = m;
                        b->endtime = cl.time + 0.2;
                        VectorCopy (start, b->start);
@@ -959,6 +965,8 @@ void CL_ParseBeam (model_t *m)
                if (!b->model || b->endtime < cl.time)
                {
                        b->entity = ent;
+                       b->lightning = lightning;
+                       b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
                        b->model = m;
                        b->endtime = cl.time + 0.2;
                        VectorCopy (start, b->start);
@@ -987,7 +995,8 @@ void CL_ParseTempEntity (void)
        case TE_WIZSPIKE:
                // spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
+               CL_AllocDlight (NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
                CL_RunParticleEffect (pos, vec3_origin, 20, 30);
                S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
                break;
@@ -995,7 +1004,8 @@ void CL_ParseTempEntity (void)
        case TE_KNIGHTSPIKE:
                // spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
+               CL_AllocDlight (NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
                CL_RunParticleEffect (pos, vec3_origin, 226, 20);
                S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
                break;
@@ -1003,7 +1013,7 @@ void CL_ParseTempEntity (void)
        case TE_SPIKE:
                // spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                // LordHavoc: changed to spark shower
                CL_SparkShower(pos, vec3_origin, 15);
                if ( rand() % 5 )
@@ -1022,7 +1032,7 @@ void CL_ParseTempEntity (void)
        case TE_SPIKEQUAD:
                // quad spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                // LordHavoc: changed to spark shower
                CL_SparkShower(pos, vec3_origin, 15);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
@@ -1043,7 +1053,7 @@ void CL_ParseTempEntity (void)
        case TE_SUPERSPIKE:
                // super spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 30);
                if ( rand() % 5 )
@@ -1062,7 +1072,7 @@ void CL_ParseTempEntity (void)
        case TE_SUPERSPIKEQUAD:
                // quad super spike hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 30);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
@@ -1083,6 +1093,7 @@ void CL_ParseTempEntity (void)
        case TE_BLOOD:
                // blood puff
                MSG_ReadVector(pos);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                dir[0] = MSG_ReadChar ();
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
@@ -1092,22 +1103,23 @@ void CL_ParseTempEntity (void)
        case TE_BLOOD2:
                // blood puff
                MSG_ReadVector(pos);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                CL_BloodPuff(pos, vec3_origin, 10);
                break;
        case TE_SPARK:
                // spark shower
                MSG_ReadVector(pos);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                dir[0] = MSG_ReadChar ();
                dir[1] = MSG_ReadChar ();
                dir[2] = MSG_ReadChar ();
                count = MSG_ReadByte ();
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
                CL_SparkShower(pos, dir, count);
                break;
        case TE_PLASMABURN:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
-               CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
+               CL_AllocDlight(NULL, pos, 200, 1, 1, 1, 1000, 0.2);
                CL_PlasmaBurn(pos);
                break;
                // LordHavoc: added for improved gore
@@ -1154,7 +1166,7 @@ void CL_ParseTempEntity (void)
        case TE_GUNSHOT:
                // bullet hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                // LordHavoc: changed to dust shower
                CL_SparkShower(pos, vec3_origin, 15);
                break;
@@ -1162,7 +1174,7 @@ void CL_ParseTempEntity (void)
        case TE_GUNSHOTQUAD:
                // quad bullet hitting wall
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                CL_SparkShower(pos, vec3_origin, 15);
                CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
                break;
@@ -1170,7 +1182,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSION:
                // rocket explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_ParticleExplosion (pos);
                // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
                CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
@@ -1180,7 +1192,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSIONQUAD:
                // quad rocket explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_ParticleExplosion (pos);
                CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1189,7 +1201,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSION3:
                // Nehahra movie colored lighting explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_ParticleExplosion (pos);
                CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1198,7 +1210,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSIONRGB:
                // colored lighting explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_ParticleExplosion (pos);
                color[0] = MSG_ReadByte() * (1.0 / 255.0);
                color[1] = MSG_ReadByte() * (1.0 / 255.0);
@@ -1210,7 +1222,7 @@ void CL_ParseTempEntity (void)
        case TE_TAREXPLOSION:
                // tarbaby explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_BlobExplosion (pos);
 
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1220,13 +1232,13 @@ void CL_ParseTempEntity (void)
 
        case TE_SMALLFLASH:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
                break;
 
        case TE_CUSTOMFLASH:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                radius = MSG_ReadByte() * 8;
                velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
                color[0] = MSG_ReadByte() * (1.0 / 255.0);
@@ -1246,21 +1258,21 @@ void CL_ParseTempEntity (void)
                // lightning bolts
                if (!cl_model_bolt)
                        cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
-               CL_ParseBeam (cl_model_bolt);
+               CL_ParseBeam (cl_model_bolt, true);
                break;
 
        case TE_LIGHTNING2:
                // lightning bolts
                if (!cl_model_bolt2)
                        cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
-               CL_ParseBeam (cl_model_bolt2);
+               CL_ParseBeam (cl_model_bolt2, true);
                break;
 
        case TE_LIGHTNING3:
                // lightning bolts
                if (!cl_model_bolt3)
                        cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
-               CL_ParseBeam (cl_model_bolt3);
+               CL_ParseBeam (cl_model_bolt3, false);
                break;
 
 // PGM 01/21/97
@@ -1268,13 +1280,13 @@ void CL_ParseTempEntity (void)
                // grappling hook beam
                if (!cl_model_beam)
                        cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
-               CL_ParseBeam (cl_model_beam);
+               CL_ParseBeam (cl_model_beam, false);
                break;
 // PGM 01/21/97
 
 // LordHavoc: for compatibility with the Nehahra movie...
        case TE_LIGHTNING4NEH:
-               CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false));
+               CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
                break;
 
        case TE_LAVASPLASH:
@@ -1295,7 +1307,7 @@ void CL_ParseTempEntity (void)
        case TE_EXPLOSION2:
                // color mapped explosion
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                colorStart = MSG_ReadByte ();
                colorLength = MSG_ReadByte ();
                CL_ParticleExplosion2 (pos, colorStart, colorLength);
@@ -1316,13 +1328,13 @@ void CL_ParseTempEntity (void)
                MSG_ReadVector(pos);
                MSG_ReadVector(dir);
                count = MSG_ReadByte ();
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 4);
                CL_Tei_Smoke(pos, dir, count);
                break;
 
        case TE_TEI_BIGEXPLOSION:
                MSG_ReadVector(pos);
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 10);
                CL_ParticleExplosion (pos);
                CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
@@ -1332,7 +1344,7 @@ void CL_ParseTempEntity (void)
                MSG_ReadVector(pos);
                MSG_ReadVector(dir);
                count = MSG_ReadByte ();
-               Mod_FindNonSolidLocation(pos, cl.worldmodel);
+               if (cl.worldmodel) cl.worldmodel->FindNonSolidLocation(cl.worldmodel, pos, pos, 5);
                CL_Tei_PlasmaHit(pos, dir, count);
                CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
                break;
@@ -1352,7 +1364,7 @@ CL_ParseServerMessage
 =====================
 */
 int parsingerror = false;
-void CL_ParseServerMessage (void)
+void CL_ParseServerMessage(void)
 {
        int                     cmd;
        int                     i, entitiesupdated;
@@ -1360,11 +1372,16 @@ void CL_ParseServerMessage (void)
        char            *cmdlogname[32], *temp;
        int                     cmdindex, cmdcount = 0;
 
+       if (cls.demorecording)
+               CL_WriteDemoMessage ();
+
+       cl.last_received_message = realtime;
+
 //
 // if recording demos, copy the message out
 //
        if (cl_shownet.integer == 1)
-               Con_Printf ("%i ",net_message.cursize);
+               Con_Printf ("%f %i\n", realtime, net_message.cursize);
        else if (cl_shownet.integer == 2)
                Con_Printf ("------------------\n");
 
@@ -1372,7 +1389,7 @@ void CL_ParseServerMessage (void)
 //
 // parse the message
 //
-       MSG_BeginReading ();
+       //MSG_BeginReading ();
 
        entitiesupdated = false;
 
@@ -1449,6 +1466,8 @@ void CL_ParseServerMessage (void)
                        break;
 
                case svc_nop:
+                       if (cls.signon < SIGNONS)
+                               Con_Printf("<-- server to client keepalive\n");
                        break;
 
                case svc_time:
@@ -1558,9 +1577,6 @@ void CL_ParseServerMessage (void)
                        if (i >= cl.maxclients)
                                Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
                        cl.scores[i].colors = MSG_ReadByte ();
-                       // update our color cvar if our color changed
-                       if (i == cl.playerentity - 1)
-                               Cvar_SetValue ("_cl_color", cl.scores[i].colors);
                        break;
 
                case svc_particle:
@@ -1714,6 +1730,7 @@ void CL_Parse_DumpPacket(void)
 void CL_Parse_Init(void)
 {
        // LordHavoc: added demo_nehahra cvar
+       cl_scores_mempool = Mem_AllocPool("client player info");
        Cvar_RegisterVariable (&demo_nehahra);
        if (gamemode == GAME_NEHAHRA)
                Cvar_SetValue("demo_nehahra", 1);