]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - csprogs.c
fix broken demos with csqc code
[xonotic/darkplaces.git] / csprogs.c
index cfc47d6e754c964605b38e62110677e099a230b0..203e107056862d9f5c0d712431874f543a85d34d 100644 (file)
--- a/csprogs.c
+++ b/csprogs.c
@@ -272,6 +272,9 @@ qboolean CL_VM_UpdateView (void)
                // CSQC_UpdateView function does not call R_ClearScene as it should
                r_refdef.scene.numentities = 0;
                r_refdef.scene.numlights = 0;
+               // pass in width and height as parameters (EXT_CSQC_1)
+               PRVM_G_FLOAT(OFS_PARM0) = vid.width;
+               PRVM_G_FLOAT(OFS_PARM1) = vid.height;
                PRVM_ExecuteProgram(prog->funcoffsets.CSQC_UpdateView, "QC function CSQC_UpdateView is missing");
                //VectorCopy(oldangles, cl.viewangles);
                // Dresk : Reset Dmg Globals Here
@@ -415,7 +418,7 @@ void CL_VM_Parse_CenterPrint (const char *msg)
        int restorevm_tempstringsbuf_cursize;
        if(!cl.csqc_loaded)
        {
-               SCR_CenterPrint((char*)msg);
+               SCR_CenterPrint(msg);
                return;
        }
        CSQC_BEGIN
@@ -429,7 +432,7 @@ void CL_VM_Parse_CenterPrint (const char *msg)
                vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
        }
        else
-               SCR_CenterPrint((char*)msg);
+               SCR_CenterPrint(msg);
        CSQC_END
 }
 
@@ -563,7 +566,13 @@ void CSQC_ReadEntities (void)
                                        cl.csqc_server2csqcentitynumber[realentnum] = 0;
                                }
                                else
-                                       Con_Printf("Bad csqc_server2csqcentitynumber map\n");   //[515]: never happens ?
+                               {
+                                       // LordHavoc: removing an entity that is already gone on
+                                       // the csqc side is possible for legitimate reasons (such
+                                       // as a repeat of the remove message), so no warning is
+                                       // needed
+                                       //Con_Printf("Bad csqc_server2csqcentitynumber map\n"); //[515]: never happens ?
+                               }
                        }
                        else
                        {
@@ -658,6 +667,46 @@ qboolean CL_VM_CB_LoadEdict(prvm_edict_t *ent)
 
 void Cmd_ClearCsqcFuncs (void);
 
+// returns true if the packet is valid, false if end of file is reached
+// used for dumping the CSQC download into demo files
+qboolean MakeDownloadPacket(const char *filename, unsigned char *data, unsigned long len, int crc, int cnt, sizebuf_t *buf, int protocol)
+{
+       int packetsize = buf->maxsize - 7; // byte short long
+       int npackets = (len + packetsize - 1) / (packetsize);
+
+       if(protocol == PROTOCOL_QUAKEWORLD)
+               return false; // CSQC can't run in QW anyway
+
+       SZ_Clear(buf);
+       if(cnt == 0)
+       {
+               MSG_WriteByte(buf, svc_stufftext);
+               MSG_WriteString(buf, va("\ncl_downloadbegin %lu %s\n", len, filename));
+               return true;
+       }
+       else if(cnt >= 1 && cnt <= npackets)
+       {
+               unsigned long thispacketoffset = (cnt - 1) * packetsize;
+               int thispacketsize = len - thispacketoffset;
+               if(thispacketsize > packetsize)
+                       thispacketsize = packetsize;
+
+               MSG_WriteByte(buf, svc_downloaddata);
+               MSG_WriteLong(buf, thispacketoffset);
+               MSG_WriteShort(buf, thispacketsize);
+               SZ_Write(buf, data + thispacketoffset, thispacketsize);
+
+               return true;
+       }
+       else if(cnt == npackets + 1)
+       {
+               MSG_WriteByte(buf, svc_stufftext);
+               MSG_WriteString(buf, va("\ncl_downloadfinished %lu %d\n", len, crc));
+               return true;
+       }
+       return false;
+}
+
 void CL_VM_Init (void)
 {
        const char* csprogsfn;
@@ -690,16 +739,19 @@ void CL_VM_Init (void)
        if (csprogsdata)
        {
                csprogsdatacrc = CRC_Block(csprogsdata, csprogsdatasize);
-               Mem_Free(csprogsdata);
                if (csprogsdatacrc != requiredcrc || csprogsdatasize != requiredsize)
                {
                        if (cls.demoplayback)
                        {
                                Con_Printf("^1Warning: Your %s is not the same version as the demo was recorded with (CRC/size are %i/%i but should be %i/%i)\n", csqc_progname.string, csprogsdatacrc, (int)csprogsdatasize, requiredcrc, requiredsize);
-                               return;
+                               // Mem_Free(csprogsdata);
+                               // return;
+                               // We WANT to continue here, and play the demo with different csprogs!
+                               // After all, this is just a warning. Sure things may go wrong from here.
                        }
                        else
                        {
+                               Mem_Free(csprogsdata);
                                Con_Printf("^1Your %s is not the same version as the server (CRC is %i/%i but should be %i/%i)\n", csqc_progname.string, csprogsdatacrc, (int)csprogsdatasize, requiredcrc, requiredsize);
                                CL_Disconnect();
                                return;
@@ -753,11 +805,36 @@ void CL_VM_Init (void)
                CL_VM_Error("CSQC %s ^2failed to load\n", csprogsfn);
                if(!sv.active)
                        CL_Disconnect();
+               Mem_Free(csprogsdata);
                return;
        }
 
        Con_Printf("CSQC %s ^5loaded (crc=%i, size=%i)\n", csprogsfn, csprogsdatacrc, (int)csprogsdatasize);
 
+       if(cls.demorecording)
+       {
+               if(cls.demo_lastcsprogssize != csprogsdatasize || cls.demo_lastcsprogscrc != csprogsdatacrc)
+               {
+                       int i;
+                       char buf[NET_MAXMESSAGE];
+                       sizebuf_t sb;
+                       unsigned char *demobuf; fs_offset_t demofilesize;
+
+                       sb.data = (void *) buf;
+                       sb.maxsize = sizeof(buf);
+                       i = 0;
+
+                       CL_CutDemo(&demobuf, &demofilesize);
+                       while(MakeDownloadPacket(csqc_progname.string, csprogsdata, csprogsdatasize, csprogsdatacrc, i++, &sb, cls.protocol))
+                               CL_WriteDemoMessage(&sb);
+                       CL_PasteDemo(&demobuf, &demofilesize);
+
+                       cls.demo_lastcsprogssize = csprogsdatasize;
+                       cls.demo_lastcsprogscrc = csprogsdatacrc;
+               }
+       }
+       Mem_Free(csprogsdata);
+
        // check if OP_STATE animation is possible in this dat file
        if (prog->fieldoffsets.nextthink >= 0 && prog->fieldoffsets.frame >= 0 && prog->fieldoffsets.think >= 0 && prog->globaloffsets.self >= 0)
                prog->flag |= PRVM_OP_STATE;
@@ -792,8 +869,8 @@ void CL_VM_Init (void)
 void CL_VM_ShutDown (void)
 {
        Cmd_ClearCsqcFuncs();
-       Cvar_SetValueQuick(&csqc_progcrc, -1);
-       Cvar_SetValueQuick(&csqc_progsize, -1);
+       //Cvar_SetValueQuick(&csqc_progcrc, -1);
+       //Cvar_SetValueQuick(&csqc_progsize, -1);
        if(!cl.csqc_loaded)
                return;
        CSQC_BEGIN