cvar_t csqc_progname = {0, "csqc_progname","csprogs.dat","name of csprogs.dat file to load"}; //[515]: csqc crc check and right csprogs name according to progs.dat
cvar_t csqc_progcrc = {CVAR_READONLY, "csqc_progcrc","-1","CRC of csprogs.dat file to load (-1 is none), only used during level changes and then reset to -1"};
+cvar_t csqc_progsize = {CVAR_READONLY, "csqc_progsize","-1","file size of csprogs.dat file to load (-1 is none), only used during level changes and then reset to -1"};
cvar_t cl_shownet = {0, "cl_shownet","0","1 = print packet size, 2 = print packet message list"};
cvar_t cl_nolerp = {0, "cl_nolerp", "0","network update smoothing"};
// TODO: this would be a good place to do curl downloads
+ if (cl.downloadcsqc)
+ {
+ size_t progsize;
+ cl.downloadcsqc = false;
+ if (cls.netcon
+ && !sv.active
+ && csqc_progname.string
+ && csqc_progname.string[0]
+ && csqc_progcrc.integer >= 0
+ && cl_serverextension_download.integer
+ && (FS_CRCFile(csqc_progname.string, &progsize) != csqc_progcrc.integer || ((int)progsize != csqc_progsize.integer && csqc_progsize.integer != -1))
+ && !FS_FileExists(va("dlcache/%s.%i.%i", csqc_progname.string, csqc_progsize.integer, csqc_progcrc.integer)))
+ Cmd_ForwardStringToServer(va("download %s", csqc_progname.string));
+ }
+
if (cl.loadmodel_current < cl.loadmodel_total)
{
// loading models
{
if (cls.qw_downloadmemory && cls.qw_downloadmemorycursize == size && CRC_Block(cls.qw_downloadmemory, size) == crc)
{
+ int existingcrc;
+ size_t existingsize;
+ const char *extension;
+
// finished file
// save to disk only if we don't already have it
// (this is mainly for playing back demos)
- if (!FS_FileExists(cls.qw_downloadname))
+ existingcrc = FS_CRCFile(cls.qw_downloadname, &existingsize);
+ if (existingsize)
{
- const char *extension;
-
+ if ((int)existingsize != size || existingcrc != crc)
+ {
+ // we have a mismatching file, pick another name for it
+ char name[MAX_QPATH*2];
+ dpsnprintf(name, sizeof(name), "dlcache/%s.%i.%i", cls.qw_downloadname, size, crc);
+ if (!FS_FileExists(name))
+ {
+ Con_Printf("Downloaded \"%s\" (%i bytes, %i CRC)\n", name, size, crc);
+ FS_WriteFile(name, cls.qw_downloadmemory, cls.qw_downloadmemorycursize);
+ }
+ }
+ }
+ else
+ {
+ // we either don't have it or have a mismatching file...
+ // so it's time to accept the file
+ // but if we already have a mismatching file we need to rename
+ // this new one, and if we already have this file in renamed form,
+ // we do nothing
Con_Printf("Downloaded \"%s\" (%i bytes, %i CRC)\n", cls.qw_downloadname, size, crc);
-
FS_WriteFile(cls.qw_downloadname, cls.qw_downloadmemory, cls.qw_downloadmemorycursize);
-
extension = FS_FileExtension(cls.qw_downloadname);
if (!strcasecmp(extension, "pak") || !strcasecmp(extension, "pk3"))
FS_Rescan();
cl.loadsound_current = 1;
cl.downloadsound_current = 1;
cl.loadsound_total = numsounds;
+ cl.downloadcsqc = true;
cl.loadfinished = false;
}
int loadsound_current;
int downloadsound_current;
int loadsound_total;
+ qboolean downloadcsqc;
qboolean loadfinished;
// quakeworld stuff
Mem_FreePool(&csqc_mempool);
Cvar_SetValueQuick(&csqc_progcrc, -1);
+ Cvar_SetValueQuick(&csqc_progsize, -1);
// Host_AbortCurrentFrame(); //[515]: hmmm... if server says it needs csqc then client MUST disconnect
Host_Error(va("CL_VM_Error: %s", errorstring));
// if this is setting a csqc variable, deprotect csqc_progcrc
// temporarily so that it can be set by the cvar command,
// and then reprotect it afterwards
- int flags = csqc_progcrc.flags;
+ int crcflags = csqc_progcrc.flags;
+ int sizeflags = csqc_progcrc.flags;
csqc_progcrc.flags &= ~CVAR_READONLY;
+ csqc_progsize.flags &= ~CVAR_READONLY;
Cmd_ExecuteString (msg, src_command);
- csqc_progcrc.flags = flags;
+ csqc_progcrc.flags = crcflags;
+ csqc_progsize.flags = sizeflags;
return;
}
if(!csqc_loaded || !CSQC_Parse_StuffCmd)
unsigned char *csprogsdata;
fs_offset_t csprogsdatasize;
int csprogsdatacrc, requiredcrc;
+ int requiredsize;
entity_t *ent;
// reset csqc_progcrc after reading it, so that changing servers doesn't
// expect csqc on the next server
requiredcrc = csqc_progcrc.integer;
+ requiredsize = csqc_progsize.integer;
Cvar_SetValueQuick(&csqc_progcrc, -1);
+ Cvar_SetValueQuick(&csqc_progsize, -1);
csqc_loaded = false;
memset(cl.csqc_model_precache, 0, sizeof(cl.csqc_model_precache));
// see if the requested csprogs.dat file matches the requested crc
csprogsdatacrc = -1;
- csprogsdata = FS_LoadFile(csqc_progname.string, tempmempool, true, &csprogsdatasize);
+ csprogsdata = FS_LoadFile(va("dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc), tempmempool, true, &csprogsdatasize);
+ if (!csprogsdata)
+ csprogsdata = FS_LoadFile(csqc_progname.string, tempmempool, true, &csprogsdatasize);
if (csprogsdata)
{
csprogsdatacrc = CRC_Block(csprogsdata, csprogsdatasize);
Mem_Free(csprogsdata);
- if (csprogsdatacrc != requiredcrc)
+ 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 is %i but should be %i)\n", csqc_progname.string, csprogsdatacrc, requiredcrc);
+ 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;
}
else
{
- Con_Printf("^1Your %s is not the same version as the server (CRC is %i but should be %i)\n", csqc_progname.string, csprogsdatacrc, requiredcrc);
+ 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;
}
PRVM_LoadProgs(csqc_progname.string, cl_numrequiredfunc, cl_required_func, 0, NULL);
if(prog->loaded)
- Con_Printf("CSQC ^5loaded (crc=%i)\n", csprogsdatacrc);
+ Con_Printf("CSQC ^5loaded (crc=%i, size=%i)\n", csprogsdatacrc, (int)csprogsdatasize);
else
{
CL_VM_Error("CSQC ^2failed to load\n");
{
Cmd_ClearCsqcFuncs();
Cvar_SetValueQuick(&csqc_progcrc, -1);
+ Cvar_SetValueQuick(&csqc_progsize, -1);
if(!csqc_loaded)
return;
CSQC_BEGIN
extern int csqc_fieldoff_dphitcontentsmask;
extern cvar_t csqc_progname; //[515]: csqc crc check and right csprogs name according to progs.dat
extern cvar_t csqc_progcrc;
+extern cvar_t csqc_progsize;
extern qboolean csqc_usecsqclistener;
extern matrix4x4_t csqc_listenermatrix;
return false;
}
+
+int FS_CRCFile(const char *filename, size_t *filesizepointer)
+{
+ int crc = -1;
+ unsigned char *filedata;
+ fs_offset_t filesize;
+ if (filesizepointer)
+ *filesizepointer = 0;
+ if (!filename || !*filename)
+ return crc;
+ filedata = FS_LoadFile(filename, tempmempool, true, &filesize);
+ if (filedata)
+ {
+ if (filesizepointer)
+ *filesizepointer = filesize;
+ crc = CRC_Block(filedata, filesize);
+ Mem_Free(filedata);
+ }
+ return crc;
+}
+
qboolean FS_CheckGameDir(const char *gamedir);
qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean complain, qboolean failmissing);
qboolean FS_IsRegisteredQuakePack(const char *name);
+int FS_CRCFile(const char *filename, size_t *filesizepointer);
void FS_Rescan(void);
typedef struct fssearch_s
// crc of clientside progs at time of level start
int csqc_progcrc; // -1 = no progs
+ int csqc_progsize; // -1 = no progs
char csqc_progname[MAX_QPATH]; // copied from csqc_progname at level start
// map name
// TODO: fix this since this is a quick hack to make some of [515]'s broken code run ;) [9/13/2006 Black]
extern cvar_t csqc_progname; //[515]: csqc crc check and right csprogs name according to progs.dat
extern cvar_t csqc_progcrc;
+ extern cvar_t csqc_progsize;
Cvar_RegisterVariable (&csqc_progname);
Cvar_RegisterVariable (&csqc_progcrc);
+ Cvar_RegisterVariable (&csqc_progsize);
Cmd_AddCommand("sv_saveentfile", SV_SaveEntFile_f, "save map entities to .ent file (to allow external editing)");
Cmd_AddCommand_WithClientCommand("sv_startdownload", NULL, SV_StartDownload_f, "begins sending a file to the client (network protocol use only)");
MSG_WriteString (&client->netconnection->message,message);
//[515]: init csprogs according to version of svprogs, check the crc, etc.
- if (sv.csqc_progcrc >= 0)
+ if (sv.csqc_progname[0])
{
prvm_eval_t *val;
- Con_DPrintf("sending csqc info to client (\"%s\" with crc %i)\n", sv.csqc_progname, sv.csqc_progcrc);
+ Con_DPrintf("sending csqc info to client (\"%s\" with size %i and crc %i)\n", sv.csqc_progname, sv.csqc_progsize, sv.csqc_progcrc);
//[515]: init stufftext string (it is sent before svc_serverinfo)
val = PRVM_GETGLOBALFIELDVALUE(PRVM_ED_FindGlobalOffset("SV_InitCmd"));
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
MSG_WriteString (&client->netconnection->message, va("csqc_progname %s\n", sv.csqc_progname));
MSG_WriteByte (&client->netconnection->message, svc_stufftext);
+ MSG_WriteString (&client->netconnection->message, va("csqc_progsize %i\n", sv.csqc_progsize));
+ MSG_WriteByte (&client->netconnection->message, svc_stufftext);
MSG_WriteString (&client->netconnection->message, va("csqc_progcrc %i\n", sv.csqc_progcrc));
if (val)
{
{
extern cvar_t csqc_progname; //[515]: csqc crc check and right csprogs name according to progs.dat
extern cvar_t csqc_progcrc;
+ extern cvar_t csqc_progsize;
unsigned char *csprogsdata;
fs_offset_t csprogsdatasize;
PRVM_Begin;
PRVM_End;
// see if there is a csprogs.dat installed, and if so, set the csqc_progcrc accordingly, this will be sent to connecting clients to tell them to only load a matching csprogs.dat file
- sv.csqc_progcrc = -1;
sv.csqc_progname[0] = 0;
- csprogsdata = FS_LoadFile(csqc_progname.string, tempmempool, true, &csprogsdatasize);
- if (csprogsdata)
+ sv.csqc_progcrc = FS_CRCFile(csqc_progname.string, &csprogsdatasize);
+ sv.csqc_progsize = csprogsdatasize;
+ if (sv.csqc_progsize > 0)
{
strlcpy(sv.csqc_progname, csqc_progname.string, sizeof(sv.csqc_progname));
- sv.csqc_progcrc = CRC_Block(csprogsdata, csprogsdatasize);
- Mem_Free(csprogsdata);
- Con_DPrintf("server detected csqc progs file \"%s\" with crc %i\n", sv.csqc_progname, sv.csqc_progcrc);
+ Con_DPrintf("server detected csqc progs file \"%s\" with size %i and crc %i\n", sv.csqc_progname, sv.csqc_progsize, sv.csqc_progcrc);
}
}