patch from div0 that makes curl downloads stay connected to the game server while...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 23 Feb 2007 10:46:00 +0000 (10:46 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 23 Feb 2007 10:46:00 +0000 (10:46 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6905 d7cf8633-e32d-0410-b094-e92efae38249

cl_main.c
cl_parse.c
client.h
libcurl.c
libcurl.h
sv_main.c

index 693caeb..b501d8e 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -289,6 +289,8 @@ void CL_Disconnect(void)
        if (cls.state == ca_dedicated)
                return;
 
+       Curl_Clear_forthismap();
+
        Con_DPrintf("CL_Disconnect\n");
 
        CL_VM_ShutDown();
index b33fd7e..794267b 100644 (file)
@@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "cdaudio.h"
 #include "cl_collision.h"
 #include "csprogs.h"
+#include "libcurl.h"
 
 char *svc_strings[128] =
 {
@@ -896,7 +897,16 @@ void CL_BeginDownloads(qboolean aborteddownload)
        if (cls.protocol == PROTOCOL_QUAKEWORLD)
                return;
 
-       // TODO: this would be a good place to do curl downloads
+       // this would be a good place to do curl downloads
+       if(Curl_Have_forthismap())
+       {
+               Curl_Register_predownload(); // come back later
+               return;
+       }
+
+       // if we got here...
+       // curl is done, so let's start with the business
+       cl.loadbegun = true;
 
        if (cl.downloadcsqc)
        {
@@ -1081,7 +1091,12 @@ void CL_BeginDownloads(qboolean aborteddownload)
 
 void CL_BeginDownloads_f(void)
 {
-       CL_BeginDownloads(false);
+       // prevent cl_begindownloads from being issued multiple times in one match
+       // to prevent accidentally cancelled downloads
+       if(cl.loadbegun)
+               Con_DPrintf("cl_begindownloads is only valid once per match\n");
+       else
+               CL_BeginDownloads(false);
 }
 
 void CL_StopDownload(int size, int crc)
@@ -1391,6 +1406,7 @@ void CL_ParseServerInfo (void)
                        MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, 0));
                }
 
+               cl.loadbegun = false;
                cl.loadfinished = false;
 
                cls.state = ca_connected;
@@ -1483,6 +1499,7 @@ void CL_ParseServerInfo (void)
                cl.downloadsound_current = 1;
                cl.loadsound_total = numsounds;
                cl.downloadcsqc = true;
+               cl.loadbegun = false;
                cl.loadfinished = false;
        }
 
@@ -1754,6 +1771,14 @@ void CL_ParseStatic (int large)
        ent = &cl.static_entities[cl.num_static_entities++];
        CL_ParseBaseline (ent, large);
 
+       if (ent->state_baseline.modelindex == 0)
+       {
+               Con_DPrintf("svc_parsestatic: static entity without model at %f %f %f\n", ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2]);
+               cl.num_static_entities--;
+               // This is definitely a cheesy way to conserve resources...
+               return;
+       }
+
 // copy it to the current state
        ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
        ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
@@ -1770,10 +1795,6 @@ void CL_ParseStatic (int large)
 
        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);
        CL_UpdateRenderEntity(&ent->render);
-
-       // This is definitely a cheesy way to conserve resources...
-       //if (ent->render.model == NULL)
-       //      cl.num_static_entities--;
 }
 
 /*
index 72ed2c7..80275a6 100644 (file)
--- a/client.h
+++ b/client.h
@@ -883,6 +883,7 @@ typedef struct client_state_s
        int downloadsound_current;
        int loadsound_total;
        qboolean downloadcsqc;
+       qboolean loadbegun;
        qboolean loadfinished;
 
        // quakeworld stuff
index ce5bf5e..3cabcef 100644 (file)
--- a/libcurl.c
+++ b/libcurl.c
@@ -185,6 +185,8 @@ downloadinfo;
 static downloadinfo *downloads = NULL;
 static int numdownloads = 0;
 
+static qboolean noclear = FALSE;
+
 static int numdownloads_fail = 0;
 static int numdownloads_success = 0;
 static int numdownloads_added = 0;
@@ -236,6 +238,8 @@ Clears the "will disconnect on failure" flags.
 void Curl_Clear_forthismap()
 {
        downloadinfo *di;
+       if(noclear)
+               return;
        for(di = downloads; di; di = di->next)
                di->forthismap = false;
        Curl_CommandWhenError(NULL);
@@ -245,16 +249,23 @@ void Curl_Clear_forthismap()
        numdownloads_added = 0;
 }
 
-/* obsolete: numdownloads_added contains the same
-static qboolean Curl_Have_forthismap()
+/*
+====================
+Curl_Have_forthismap
+
+Returns true if a download needed for the current game is running.
+====================
+*/
+qboolean Curl_Have_forthismap()
 {
-       downloadinfo *di;
-       for(di = downloads; di; di = di->next)
-               if(di->forthismap)
-                       return true;
-       return false;
+       return numdownloads_added;
+}
+
+void Curl_Register_predownload()
+{
+       Curl_CommandWhenDone("cl_begindownloads");
+       Curl_CommandWhenError("cl_begindownloads");
 }
-*/
 
 /*
 ====================
@@ -446,8 +457,6 @@ static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error
                        ++numdownloads_fail;
        }
        Z_Free(di);
-
-       Curl_CheckCommandWhenDone();
 }
 
 /*
@@ -709,12 +718,16 @@ blocking.
 */
 void Curl_Run()
 {
+       noclear = FALSE;
+
        if(!cl_curl_enabled.integer)
                return;
 
        if(!curl_dll)
                return;
 
+       Curl_CheckCommandWhenDone();
+
        if(!downloads)
                return;
 
@@ -1017,12 +1030,18 @@ void Curl_Curl_f(void)
                                char donecommand[256];
                                if(cls.netcon)
                                {
-                                       dpsnprintf(donecommand, sizeof(donecommand), "connect %s", cls.netcon->address);
-                                       Curl_CommandWhenDone(donecommand);
+                                       if(cls.signon >= 3)
+                                       {
+                                               dpsnprintf(donecommand, sizeof(donecommand), "connect %s", cls.netcon->address);
+                                               Curl_CommandWhenDone(donecommand);
+                                               noclear = TRUE;
+                                               CL_Disconnect();
+                                               noclear = FALSE;
+                                               Curl_CheckCommandWhenDone();
+                                       }
+                                       else
+                                               Curl_Register_predownload();
                                }
-                               CL_Disconnect();
-
-                               Curl_CheckCommandWhenDone();
                        }
                        return;
                }
@@ -1107,10 +1126,12 @@ Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **addition
                // TODO: can I clear command_when_done as soon as the first download fails?
                if(*command_when_done && !numdownloads_fail && numdownloads_added)
                {
-                       if(strncmp(command_when_done, "connect ", 8))
-                               dpsnprintf(addinfo, sizeof(addinfo), "(will do '%s' when done)", command_when_done);
-                       else
+                       if(!strncmp(command_when_done, "connect ", 8))
                                dpsnprintf(addinfo, sizeof(addinfo), "(will join %s when done)", command_when_done + 8);
+                       else if(!strcmp(command_when_done, "cl_begindownloads"))
+                               dpsnprintf(addinfo, sizeof(addinfo), "(will enter the game when done)");
+                       else
+                               dpsnprintf(addinfo, sizeof(addinfo), "(will do '%s' when done)", command_when_done);
                        *additional_info = addinfo;
                }
                else
index f92a238..a6cf982 100644 (file)
--- a/libcurl.h
+++ b/libcurl.h
@@ -6,6 +6,8 @@ void Curl_Init_Commands();
 void Curl_Shutdown();
 void Curl_CancelAll();
 void Curl_Clear_forthismap();
+qboolean Curl_Have_forthismap();
+void Curl_Register_predownload();
 
 void Curl_ClearRequirements();
 void Curl_RequireFile(const char *filename);
index bef7c41..ed61023 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -406,6 +406,15 @@ void SV_SendServerinfo (client_t *client)
                MSG_WriteString (&client->netconnection->message, "cl_serverextension_download 1");
        }
 
+       // send at this time so it's guaranteed to get executed at the right time
+       {
+               client_t *save;
+               save = host_client;
+               host_client = client;
+               Curl_SendRequirements();
+               host_client = save;
+       }
+
        MSG_WriteByte (&client->netconnection->message, svc_serverinfo);
        MSG_WriteLong (&client->netconnection->message, Protocol_NumberForEnum(sv.protocol));
        MSG_WriteByte (&client->netconnection->message, svs.maxclients);
@@ -437,14 +446,6 @@ void SV_SendServerinfo (client_t *client)
        MSG_WriteByte (&client->netconnection->message, svc_signonnum);
        MSG_WriteByte (&client->netconnection->message, 1);
 
-       {
-               client_t *save;
-               save = host_client;
-               host_client = client;
-               Curl_SendRequirements();
-               host_client = save;
-       }
-
        client->spawned = false;                // need prespawn, spawn, etc
 }