diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index e7caaaaf2..5f9f281a6 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1781,7 +1781,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) { next = clientcmdlist->next; CL_Demo_ClientCommand(clientcmdlist->command); - Con_DPrintf("Sending stringcmd %s\n", clientcmdlist->command); + Con_DLPrintf(2, "Sending stringcmd %s\n", clientcmdlist->command); Z_Free(clientcmdlist); clientcmdlist = next; } @@ -1946,7 +1946,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) MSG_WriteString (&buf, clientcmdlist->command); } } - Con_DPrintf("Sending stringcmd %s\n", clientcmdlist->command); + Con_DLPrintf(2, "Sending stringcmd %s\n", clientcmdlist->command); Z_Free(clientcmdlist); clientcmdlist = next; } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d5eef9305..2a32ed7cb 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -680,18 +680,23 @@ void CL_SendConnectPacket (netadr_t *to, int mtu, Q_strncatz(data, va("0x%x 0x%x\n", PROTOCOL_VERSION_FTE2, fteprotextsupported2), sizeof(data)); #endif - if (mtu > 0) { + int ourmtu; if (to->type == NA_LOOPBACK) - mtu = MAX_UDP_PACKET; - else if (net_mtu.ival > 64 && mtu > net_mtu.ival) - mtu = net_mtu.ival; - mtu &= ~7; - Q_strncatz(data, va("0x%x %i\n", PROTOCOL_VERSION_FRAGMENT, mtu), sizeof(data)); - connectinfo.mtu = mtu; + ourmtu = MAX_UDP_PACKET; + else if (*net_mtu.string) + ourmtu = net_mtu.ival; + else + ourmtu = 1440; //a safe bet. servers have an unsafe bet by default + if (ourmtu < 0) + ourmtu = 0; + if (mtu > ourmtu) + mtu = ourmtu; + connectinfo.mtu = mtu & ~7; + + if (connectinfo.mtu > 0) + Q_strncatz(data, va("0x%x %i\n", PROTOCOL_VERSION_FRAGMENT, connectinfo.mtu), sizeof(data)); } - else - connectinfo.mtu = 0; #ifdef HUFFNETWORK if (compressioncrc && net_compress.ival && Huff_CompressionCRC(compressioncrc)) @@ -5665,6 +5670,9 @@ void Host_FinishLoading(void) IPLog_Merge_File("iplog.dat"); //legacy crap, for compat with proquake } + if (PM_IsApplying(true)) + return; + #ifdef ANDROID //android needs to wait a bit longer before it's allowed to init its video properly. extern int sys_glesversion; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 14acb5606..5caabe043 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -6203,7 +6203,7 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n while((msg = strchr(stufftext, '\n'))) { *msg = '\0'; - Con_DPrintf("stufftext: %s\n", stufftext); + Con_DLPrintf((cls.state==ca_active)?1:2, "stufftext: %s\n", stufftext); if (!strncmp(stufftext, "fullserverinfo ", 15)) { Cmd_ExecuteString(stufftext, RESTRICT_SERVER+destsplit); //do this NOW so that it's done before any models or anything are loaded diff --git a/engine/client/console.c b/engine/client/console.c index a314d2286..c1dedbd54 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -1067,7 +1067,7 @@ static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b) { if (log_developer.ival) Con_Log(data); - if (developer.ival) + if (developer.ival >= (int)a) { Sys_Printf ("%s", (const char*)data); // also echo to debugging console Con_PrintCon(&con_main, data, con_main.parseflags); @@ -1103,7 +1103,7 @@ void VARGS Con_DPrintf (const char *fmt, ...) if (!Sys_IsMainThread()) { - COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), 0, 0); + COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), 1, 0); return; } @@ -1116,6 +1116,42 @@ void VARGS Con_DPrintf (const char *fmt, ...) Con_PrintCon(&con_main, msg, con_main.parseflags); } } +void VARGS Con_DLPrintf (int level, const char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + +#ifdef CRAZYDEBUGGING + va_start (argptr,fmt); + vsnprintf (msg,sizeof(msg)-1, fmt,argptr); + va_end (argptr); + Sys_Printf("%s", msg); + return; +#else + if (developer.ival= level) + { + Sys_Printf ("%s", msg); // also echo to debugging console + if (con_initialized) + Con_PrintCon(&con_main, msg, con_main.parseflags); + } +} + /*description text at the bottom of the console*/ void Con_Footerf(console_t *con, qboolean append, const char *fmt, ...) diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 535f67e23..0901a4f63 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -180,7 +180,7 @@ static qboolean loadedinstalled; static package_t *availablepackages; static int numpackages; static char *manifestpackage; //metapackage named by the manicfest. -static qboolean domanifestinstall; +static int domanifestinstall; //SECURITY_MANIFEST_* static qboolean doautoupdate; //updates will be marked (but not applied without the user's actions) @@ -1211,6 +1211,23 @@ static unsigned int PM_MarkUpdates (void) { unsigned int changecount = 0; package_t *p, *o, *b, *e = NULL; + + if (manifestpackage) + { + p = PM_MarkedPackage(manifestpackage); + if (!p) + { + p = PM_FindPackage(manifestpackage); + if (p) + { + PM_MarkPackage(p); + changecount++; + } + } + else if (!(p->flags & DPF_PRESENT)) + changecount++; + } + for (p = availablepackages; p; p = p->next) { if ((p->flags & DPF_ENGINE) && !(p->flags & DPF_HIDDEN)) @@ -1318,38 +1335,40 @@ static void PM_ListDownloaded(struct dl_download *dl) if (!downloadablelist[i].received) break; } - if (domanifestinstall) + if (domanifestinstall == MANIFEST_SECURITY_INSTALLER) { package_t *meta; meta = PM_MarkedPackage(manifestpackage); if (!meta) - meta = PM_FindPackage(manifestpackage); - if (meta) { - PM_RevertChanges(); - PM_MarkPackage(meta); - PM_ApplyChanges(); + meta = PM_FindPackage(manifestpackage); + if (meta) + { + PM_RevertChanges(); + PM_MarkPackage(meta); + PM_ApplyChanges(); #ifdef DOWNLOADMENU - if (!isDedicated) - { - if (Key_Dest_Has(kdm_emenu)) + if (!isDedicated) { - Key_Dest_Remove(kdm_emenu); - m_state = m_none; - } + if (Key_Dest_Has(kdm_emenu)) + { + Key_Dest_Remove(kdm_emenu); + m_state = m_none; + } #ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu)) - MP_Toggle(0); + if (Key_Dest_Has(kdm_gmenu)) + MP_Toggle(0); #endif - Cmd_ExecuteString("menu_download\n", RESTRICT_LOCAL); - + Cmd_ExecuteString("menu_download\n", RESTRICT_LOCAL); + + } +#endif + return; } -#endif - return; } } - if (doautoupdate && i == numdownloadablelists) + if ((doautoupdate || domanifestinstall == MANIFEST_SECURITY_DEFAULT) && i == numdownloadablelists) { if (PM_MarkUpdates()) { @@ -1863,15 +1882,18 @@ static char *PM_GetTempName(package_t *p) p->previewimage = NULL; }*/ -int PM_IsApplying(void) +int PM_IsApplying(qboolean listsonly) { package_t *p; int count = 0; int i; - for (p = availablepackages; p ; p=p->next) + if (!listsonly) { - if (p->download) - count++; + for (p = availablepackages; p ; p=p->next) + { + if (p->download) + count++; + } } for (i = 0; i < numdownloadablelists; i++) { @@ -1887,10 +1909,10 @@ static void PM_StartADownload(void) vfsfile_t *tmpfile; char *temp; package_t *p; - const int simultaneous = 1; + const int simultaneous = PM_IsApplying(true)?1:2; int i; - for (p = availablepackages; p && simultaneous > PM_IsApplying(); p=p->next) + for (p = availablepackages; p && simultaneous > PM_IsApplying(false); p=p->next) { if (p->trymirrors) { //flagged for a (re?)download @@ -2096,14 +2118,14 @@ static void PM_ApplyChanges(void) //names packages that were listed from the manifest. //if 'mark' is true, then this is an initial install. -void PM_ManifestPackage(const char *metaname, qboolean mark) +void PM_ManifestPackage(const char *metaname, int security) { - domanifestinstall = mark; + domanifestinstall = security; Z_Free(manifestpackage); if (metaname) { manifestpackage = Z_StrDup(metaname); - if (mark) + if (security) PM_UpdatePackageList(false, false); } else diff --git a/engine/client/menu.c b/engine/client/menu.c index a48196023..2c8c2385f 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -1259,11 +1259,8 @@ void M_Shutdown(qboolean total) #ifdef MENU_DAT MP_Shutdown(); #endif - if (total) - { - M_RemoveAllMenus(false); - M_DeInit_Internal(); - } + M_RemoveAllMenus(!total); + M_DeInit_Internal(); } void M_Reinit(void) diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index cefb505c9..68de3ad9d 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -2679,7 +2679,7 @@ void MP_CoreDump_f(void) void MP_Reload_f(void) { - M_Shutdown(true); + M_Shutdown(false); M_Reinit(); } diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 7439dc653..e905ce298 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -771,13 +771,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ON_EPSILON 0.1 // point on plane side epsilon -#define MAX_NQMSGLEN 65536 // max length of a reliable message +#define MAX_NQMSGLEN 65536 // max length of a reliable message. FIXME: should be 8000 to play safe with proquake #define MAX_Q2MSGLEN 1400 #define MAX_QWMSGLEN 1450 #define MAX_OVERALLMSGLEN 65536 // mvdsv sends packets this big #define MAX_DATAGRAM 1450 // max length of unreliable message #define MAX_Q2DATAGRAM MAX_Q2MSGLEN -#define MAX_NQDATAGRAM 1024 // max length of unreliable message +#define MAX_NQDATAGRAM 1024 // max length of unreliable message with vanilla nq protocol #define MAX_OVERALLDATAGRAM MAX_DATAGRAM #define MAX_BACKBUFLEN 1200 diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 958105ea4..3e1f99930 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -2296,9 +2296,9 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, framestate_t *framestate, v indexes = mod->ofs_indexes; #ifdef SKELETALMODELS - if (mod->numbones) + if (mod->ofs_skel_xyz) { - if (!mod->ofs_skel_idx || !framestate) + if (!mod->ofs_skel_idx || !framestate || !mod->numbones) posedata = mod->ofs_skel_xyz; //if there's no weights, don't try animating anything. else if (mod->shares_verts != cursurfnum || !posedata) { @@ -2330,6 +2330,8 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, framestate_t *framestate, v if (!group->numposes) continue; pose = group->poseofs; + if (!pose) + continue; //error... if (framestate) pose += (int)(framestate->g[FS_REG].frametime[0] * group->rate)%group->numposes; posedata = pose->ofsverts; @@ -7056,7 +7058,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsi } else fuckedevents = true; //we're not using the animation data from the model, so ignore any events because they won't make sense any more. - if (!numgroups) + if (!numgroups && !noweights && h->num_joints) { /*base frame only*/ numgroups = 1; framegroups = malloc(sizeof(*framegroups)); diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index b332b644a..7acb3bfc0 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -116,6 +116,8 @@ typedef struct unsigned int subframe; bucket_t bucket; } galiascolourmapped_t; +#else +typedef void galiasskin_t; #endif typedef struct @@ -145,20 +147,20 @@ typedef struct galiasinfo_s float lerpcutoff; //hack. should probably be part of the entity structure, but I really don't want new models (and thus code) to have access to this ugly inefficient hack. make your models properly in the first place. int numskins; -#ifndef SERVERONLY +//#ifndef SERVERONLY galiasskin_t *ofsskins; -#endif +//#endif int shares_verts; //used with models with two shaders using the same vertex. set to the surface number to inherit from (or itself). int shares_bones; //use last mesh's bones. set to the surface number to inherit from (or itself). int numverts; -#ifndef SERVERONLY +//#ifndef SERVERONLY vec2_t *ofs_st_array; vec4_t *ofs_rgbaf; byte_vec4_t *ofs_rgbaub; -#endif +//#endif int numanimations; galiasanimation_t *ofsanimations; diff --git a/engine/common/common.c b/engine/common/common.c index 1276ebadd..cca6b6883 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -3252,6 +3252,8 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t //preserved flags and reset to white. links must contain their own colours. linkinitflags = ext; ext = COLOR_RED << CON_FGSHIFT; + if (!(linkinitflags & CON_RICHFORECOLOUR)) + ext |= linkinitflags & (CON_NONCLEARBG|CON_HALFALPHA|CON_BGMASK); linkstart = out; *out++ = '['; diff --git a/engine/common/common.h b/engine/common/common.h index e34dd7422..a56ae0626 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -600,7 +600,12 @@ enum manifestdeptype_e typedef struct { qboolean blockupdate; //set to block the updateurl from being used this session. this avoids recursive updates when manifests contain the same update url. - qboolean doinstall; //manifest was embedded in the engine. don't assume its already installed, but ask to install it (also, enable some extra permissions for writing dlls) + enum + { + MANIFEST_SECURITY_NOT, //don't trust it, don't even allow downloadsurl. + MANIFEST_SECURITY_DEFAULT, //the default.fmf file may suggest packages + MANIFEST_SECURITY_INSTALLER //built-in fmf files can force packages + } security; //manifest was embedded in the engine. don't assume its already installed, but ask to install it (also, enable some extra permissions for writing dlls) enum { diff --git a/engine/common/console.h b/engine/common/console.h index 95a7638f8..b166dc695 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -225,7 +225,8 @@ void Con_CenterPrint(const char *txt); void Con_PrintFlags(const char *text, unsigned int setflags, unsigned int clearflags); void VARGS Con_Printf (const char *fmt, ...) LIKEPRINTF(1); void VARGS Con_TPrintf (translation_t text, ...); -void VARGS Con_DPrintf (const char *fmt, ...) LIKEPRINTF(1); +void VARGS Con_DPrintf (const char *fmt, ...) LIKEPRINTF(1); //developer>=1, for stuff that's probably actually slightly useful +void VARGS Con_DLPrintf (int level, const char *fmt, ...) LIKEPRINTF(2); //developer>=2, for spammy stuff void VARGS Con_SafePrintf (const char *fmt, ...) LIKEPRINTF(1); void Con_Footerf(console_t *con, qboolean append, const char *fmt, ...) LIKEPRINTF(3); void Con_Clear_f (void); diff --git a/engine/common/fs.c b/engine/common/fs.c index b45764c41..8832b2cd0 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2977,14 +2977,14 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths) FS_ChangeGame(man, cfg_reload_on_gamedir.ival, false); } -#ifdef NOLEGACY +#if defined(NOLEGACY) || defined(SERVERONLY) #define ZFIXHACK #elif defined(ANDROID) //on android, these numbers seem to be generating major weirdness, so disable these. #define ZFIXHACK #elif defined(FTE_TARGET_WEB) //on firefox (but not chrome or ie), these numbers seem to be generating major weirdness, so tone them down significantly by default. - #define ZFIXHACK "r_polygonoffset_submodel_offset 1\nr_polygonoffset_submodel_factor 0.05\n" + #define ZFIXHACK "set r_polygonoffset_submodel_offset 1\nset r_polygonoffset_submodel_factor 0.05\n" #else //many quake maps have hideous z-fighting. this provides a way to work around it, although the exact numbers are gpu and bitdepth dependant, and trying to fix it can actually break other things. - #define ZFIXHACK "r_polygonoffset_submodel_offset 25\nr_polygonoffset_submodel_factor 0.05\n" + #define ZFIXHACK "set r_polygonoffset_submodel_offset 25\nset r_polygonoffset_submodel_factor 0.05\n" #endif /*quake requires a few settings for compatibility*/ @@ -4190,6 +4190,7 @@ static ftemanifest_t *FS_GenerateLegacyManifest(char *newbasedir, int sizeof_new FS_Manifest_ParseTokens(man); } } + man->security = MANIFEST_SECURITY_INSTALLER; return man; } @@ -4290,7 +4291,7 @@ static char fspdl_finalpath[MAX_OSPATH]; static void FS_BeginNextPackageDownload(void); qboolean FS_DownloadingPackage(void) { - if (PM_IsApplying()) + if (PM_IsApplying(false)) return true; return !fs_manifest || !!curpackagedownload; } @@ -4718,7 +4719,7 @@ static void FS_BeginNextPackageDownload(void) if (curpackagedownload || !man || com_installer) return; - if (man->doinstall) + if (man->security != MANIFEST_SECURITY_NOT) { for (j = 0; j < sizeof(fs_manifest->package) / sizeof(fs_manifest->package[0]); j++) { @@ -4824,7 +4825,7 @@ static void FS_ManifestUpdated(struct dl_download *dl) void FS_BeginManifestUpdates(void) { ftemanifest_t *man = fs_manifest; - PM_ManifestPackage(man->installupd, man->doinstall); + PM_ManifestPackage(man->installupd, man->security); if (curpackagedownload || !man) return; @@ -4877,6 +4878,7 @@ ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, q VFS_READ(f, fdata, len); fdata[len] = 0; man = FS_Manifest_Parse(NULL, fdata); + man->security = MANIFEST_SECURITY_DEFAULT; BZ_Free(fdata); } VFS_CLOSE(f); @@ -4900,7 +4902,7 @@ ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, q { man = FS_Manifest_Parse(va("%sdefault.fmf", newbasedir), host_parms.manifest); if (man) - man->doinstall = true; + man->security = MANIFEST_SECURITY_INSTALLER; } if (!man) @@ -5047,7 +5049,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean } fs_manifest = man; - if (!man->doinstall && strcmp(man->downloadsurl?man->downloadsurl:"", olddownloadsurl?olddownloadsurl:"")) + if (man->security == MANIFEST_SECURITY_NOT && strcmp(man->downloadsurl?man->downloadsurl:"", olddownloadsurl?olddownloadsurl:"")) { //make sure we only fuck over the user if this is a 'secure' manifest, and not hacked in some way. Z_Free(man->downloadsurl); man->downloadsurl = olddownloadsurl; @@ -5094,7 +5096,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean builtingame = true; if (!fixedbasedir && !FS_DirHasGame(newbasedir, i)) - if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), !man->doinstall) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasGame(realpath, i)) + if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), man->security != MANIFEST_SECURITY_INSTALLER) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasGame(realpath, i)) Q_strncpyz (newbasedir, realpath, sizeof(newbasedir)); break; } @@ -5105,7 +5107,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean { if (!builtingame && !fixedbasedir && !FS_DirHasAPackage(newbasedir, man)) { - if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), !man->doinstall) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasAPackage(realpath, man)) + if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), man->security != MANIFEST_SECURITY_INSTALLER) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasAPackage(realpath, man)) Q_strncpyz (newbasedir, realpath, sizeof(newbasedir)); #ifndef SERVERONLY else @@ -5279,7 +5281,7 @@ void FS_CreateBasedir(const char *path) com_installer = false; Q_strncpyz (com_gamepath, path, sizeof(com_gamepath)); COM_CreatePath(com_gamepath); - fs_manifest->doinstall = true; + fs_manifest->security = MANIFEST_SECURITY_INSTALLER; FS_ChangeGame(fs_manifest, true, false); if (host_parms.manifest) diff --git a/engine/common/fs.h b/engine/common/fs.h index b6189ed60..32656d089 100644 --- a/engine/common/fs.h +++ b/engine/common/fs.h @@ -68,7 +68,7 @@ void FS_UnRegisterFileSystemModule(void *module); void FS_AddHashedPackage(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, const char *pakpath, const char *qhash, const char *pakprefix); void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, int minpri, int maxpri); -int PM_IsApplying(void); +int PM_IsApplying(qboolean listsonly); void PM_ManifestPackage(const char *name, qboolean doinstall); qboolean PM_FindUpdatedEngine(char *syspath, size_t syspathsize); //names the engine we should be running void Menu_Download_Update(void); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index c88522c19..2b4e75b94 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -811,7 +811,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) e = NET_SendPacket (chan->sock, (no - offset) + hsz, send.data + offset, &chan->remote_address); if (e == NETERR_MTU && !offset && chan->fragmentsize > 560) { - chan->fragmentsize -= 10; + chan->fragmentsize -= 16; Con_Printf("Reducing MSS to %i\n", chan->fragmentsize); no = offset; more = true; diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 3a10c4433..bf6b744a9 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -248,6 +248,7 @@ static fontplanes_t fontplanes; #define FONT_CHAR_BUFFER 512 static index_t font_indicies[FONT_CHAR_BUFFER*6]; static vecV_t font_coord[FONT_CHAR_BUFFER*4]; +static vecV_t font_backcoord[FONT_CHAR_BUFFER*4]; static vec2_t font_texcoord[FONT_CHAR_BUFFER*4]; static byte_vec4_t font_forecoloura[FONT_CHAR_BUFFER*4]; static byte_vec4_t font_backcoloura[FONT_CHAR_BUFFER*4]; @@ -338,7 +339,7 @@ void Font_Init(void) font_foremesh.colors4b_array = font_forecoloura; font_backmesh.indexes = font_indicies; - font_backmesh.xyz_array = font_coord; + font_backmesh.xyz_array = font_backcoord; font_backmesh.st_array = font_texcoord; font_backmesh.colors4b_array = font_backcoloura; @@ -400,7 +401,7 @@ static void Font_Flush(void) fontplanes.planechanged = false; } font_foremesh.istrifan = (font_foremesh.numvertexes == 4); - if ((font_colourmask & CON_NONCLEARBG) && font_foremesh.numindexes) + if ((font_colourmask & (CON_RICHFORECOLOUR|CON_NONCLEARBG)) == CON_NONCLEARBG && font_foremesh.numindexes) { font_backmesh.numindexes = font_foremesh.numindexes; font_backmesh.numvertexes = font_foremesh.numvertexes; @@ -1872,7 +1873,7 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint if (codepoint == '\t') return Font_TabWidth(px); - if (codepoint == ' ') + if (codepoint == ' ' && (charflags & (CON_RICHFORECOLOUR|CON_NONCLEARBG)) != CON_NONCLEARBG) return nextx; /* if (charcode & CON_BLINKTEXT) @@ -2052,10 +2053,29 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint *(int*)font_forecoloura[v+1] = *(int*)font_forecolour; *(int*)font_forecoloura[v+2] = *(int*)font_forecolour; *(int*)font_forecoloura[v+3] = *(int*)font_forecolour; - *(int*)font_backcoloura[v+0] = *(int*)font_backcolour; - *(int*)font_backcoloura[v+1] = *(int*)font_backcolour; - *(int*)font_backcoloura[v+2] = *(int*)font_backcolour; - *(int*)font_backcoloura[v+3] = *(int*)font_backcolour; + + if (font_colourmask & CON_NONCLEARBG) + { + sx = ((px+dxbias)*(int)vid.width) / (float)vid.rotpixelwidth; + sy = ((py+dxbias)*(int)vid.height) / (float)vid.rotpixelheight; + sw = sx + ((c->advance)*vid.width) / (float)vid.rotpixelwidth; + sh = sy + ((font->charheight)*vid.height) / (float)vid.rotpixelheight; + + //don't care about texcoords + font_backcoord[v+0][0] = sx; + font_backcoord[v+0][1] = sy; + font_backcoord[v+1][0] = sw; + font_backcoord[v+1][1] = sy; + font_backcoord[v+2][0] = sw; + font_backcoord[v+2][1] = sh; + font_backcoord[v+3][0] = sx; + font_backcoord[v+3][1] = sh; + + *(int*)font_backcoloura[v+0] = *(int*)font_backcolour; + *(int*)font_backcoloura[v+1] = *(int*)font_backcolour; + *(int*)font_backcoloura[v+2] = *(int*)font_backcolour; + *(int*)font_backcoloura[v+3] = *(int*)font_backcolour; + } return nextx; } @@ -2102,7 +2122,7 @@ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned in nextx = px + c->advance*cw; - if (codepoint == ' ') + if (codepoint == ' ' && (charflags & (CON_RICHFORECOLOUR|CON_NONCLEARBG)) != CON_NONCLEARBG) return nextx; if (charflags & CON_BLINKTEXT) @@ -2261,10 +2281,34 @@ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned in *(int*)font_forecoloura[v+1] = *(int*)font_forecolour; *(int*)font_forecoloura[v+2] = *(int*)font_forecolour; *(int*)font_forecoloura[v+3] = *(int*)font_forecolour; - *(int*)font_backcoloura[v+0] = *(int*)font_backcolour; - *(int*)font_backcoloura[v+1] = *(int*)font_backcolour; - *(int*)font_backcoloura[v+2] = *(int*)font_backcolour; - *(int*)font_backcoloura[v+3] = *(int*)font_backcolour; + + if (font_colourmask & CON_NONCLEARBG) + { + sx = px + dxbias; + sy = py + dxbias; + sw = sx + c->advance; + sh = sy + font->charheight; + + sx *= (int)vid.width / (float)vid.rotpixelwidth; + sy *= (int)vid.height / (float)vid.rotpixelheight; + sw *= (int)vid.width / (float)vid.rotpixelwidth; + sh *= (int)vid.height / (float)vid.rotpixelheight; + + //don't care about texcoords + font_backcoord[v+0][0] = sx; + font_backcoord[v+0][1] = sy; + font_backcoord[v+1][0] = sw; + font_backcoord[v+1][1] = sy; + font_backcoord[v+2][0] = sw; + font_backcoord[v+2][1] = sh; + font_backcoord[v+3][0] = sx; + font_backcoord[v+3][1] = sh; + + *(int*)font_backcoloura[v+0] = *(int*)font_backcolour; + *(int*)font_backcoloura[v+1] = *(int*)font_backcolour; + *(int*)font_backcoloura[v+2] = *(int*)font_backcolour; + *(int*)font_backcoloura[v+3] = *(int*)font_backcolour; + } return nextx; } diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index b83996817..03543ed28 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -649,7 +649,7 @@ void Mod_Purge(enum mod_purge_e ptype) } if (unused) - Con_DPrintf("model \"%s\" no longer needed\n", mod->name); + Con_DLPrintf(2, "model \"%s\" no longer needed\n", mod->name); #ifdef TERRAIN //we can safely flush all terrain sections at any time diff --git a/engine/qclib/cmdlib.h b/engine/qclib/cmdlib.h index d57bdbe53..4b74bf563 100644 --- a/engine/qclib/cmdlib.h +++ b/engine/qclib/cmdlib.h @@ -111,6 +111,7 @@ extern int qcc_eof; #define qcc_iswhite(c) ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == '\t' || (c) == '\v') #define qcc_iswhitesameline(c) ((c) == ' ' || (c) == '\t') +#define qcc_islineending(c,n) ((c) == '\n' || ((c) == '\r' && (n) != '\n')) //to try to handle mac line endings, especially if they're in the middle of a line enum diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 570d09324..5093ac22f 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -749,6 +749,7 @@ enum { WARN_FTE_SPECIFIC, //extension that only FTEQCC will have a clue about. WARN_EXTENSION_USED, //extension that frikqcc also understands WARN_IFSTRING_USED, + WARN_IFVECTOR_DISABLED, //if(vector) does if(vector_x) if ifvector is disabled WARN_LAXCAST, //some errors become this with a compiler flag WARN_TYPEMISMATCHREDECOPTIONAL, WARN_UNDESIRABLECONVENTION, diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 0fb72fabb..b110fcd92 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1679,6 +1679,8 @@ QCC_sref_t QCC_MakeSRefForce(QCC_def_t *def, unsigned int ofs, QCC_type_t *type) QCC_sref_t QCC_MakeSRef(QCC_def_t *def, unsigned int ofs, QCC_type_t *type); //we're about to overwrite the given def, so if there's any aliases to it, we need to clear them out. +//if def == NULL, then clobber all. +//def should never be a temp... static void QCC_ClobberDef(QCC_def_t *def) { QCC_def_t *a, **link; @@ -1708,7 +1710,7 @@ static void QCC_ClobberDef(QCC_def_t *def) statements[st].c.sym = a->generatedfor; } tmp.sym->refcount = a->symbolheader->refcount; - a->symbolheader = tmp.sym; + a->symbolheader = tmp.sym; //the alias now refers to a temp from = QCC_MakeSRefForce(a->generatedfor, 0, a->type); a->generatedfor = tmp.sym; a->name = tmp.sym->name; @@ -1736,6 +1738,7 @@ static QCC_sref_t QCC_GetAliasTemp(QCC_sref_t ref) def->name = ref.sym->name; def->referenced = true; def->fromstatement = numstatements; + def->scope = pr_scope; //allaliases allows them to be finalized correctly def->strip = true; @@ -1831,6 +1834,7 @@ void QCC_FinaliseTemps(void) //finalize alises so they map correctly. while(allaliases) { + allaliases->symbolheader = allaliases->generatedfor->symbolheader; allaliases->ofs = allaliases->generatedfor->ofs; allaliases = allaliases->next; } @@ -1948,7 +1952,7 @@ static QCC_def_t *QCC_MakeLocked(gofs_t tofs, gofs_t tsize, QCC_def_t *tmp) for (link = &allaliases; *link;) { a = *link; - if (a->generatedfor == tmp) + if (a->generatedfor == tmp && a->scope == pr_scope) { // *link = a->next; // a->next = NULL; @@ -4079,9 +4083,6 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ if (!pr_scope) QCC_PR_ParseError(ERR_BADEXTENSION, "Unable to generate statements at global scope.\n"); - if (outstatement) - QCC_ClobberDef(NULL); - if (op->type_c == &type_void || op->associative==ASSOC_RIGHT || op->type_c == NULL) { QCC_FreeTemp(var_b); //returns a instead of some result/temp @@ -4094,6 +4095,9 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ QCC_FreeTemp(var_b); } + if (outstatement) + QCC_ClobberDef(NULL); + statement = &statements[numstatements++]; if (outstatement) @@ -9573,7 +9577,10 @@ QCC_statement_t *QCC_Generate_OP_IFNOT(QCC_sref_t e, pbool preserve) op = OP_IF_I; } else + { + QCC_PR_ParseWarning(WARN_IFVECTOR_DISABLED, "if (vector) tests only the first element with the current compiler flags"); op = OP_IFNOT_I; + } break; case ev_variant: @@ -11578,6 +11585,7 @@ void QCC_WriteGUIAsmFunction(QCC_function_t *sc, unsigned int firststatement) for (i = firststatement; i < (unsigned int)numstatements; i++) { line[0] = 0; +// QC_snprintfz(line, sizeof(line), "%i ", QCC_VarAtOffset(statements[i].a)); QC_strlcat(line, pr_opcodes[statements[i].op].opname, sizeof(line)); if (pr_opcodes[statements[i].op].type_a != &type_void) { diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index e23e67ad9..09a47c437 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -2223,7 +2223,7 @@ void QCC_PR_LexWhitespace (pbool inhibitpreprocessor) // skip whitespace while ((c = *pr_file_p) && qcc_iswhite(c)) { - if (c=='\n') + if (qcc_islineending(c, pr_file_p[1])) { pr_file_p++; if (!inhibitpreprocessor) @@ -2242,10 +2242,10 @@ void QCC_PR_LexWhitespace (pbool inhibitpreprocessor) // skip // comments if (c=='/' && pr_file_p[1] == '/') { - while (*pr_file_p && *pr_file_p != '\n') + while (*pr_file_p && !qcc_islineending(pr_file_p[0], pr_file_p[1])) pr_file_p++; - if (*pr_file_p == '\n') + if (*pr_file_p) pr_file_p++; //don't break on eof. if (!inhibitpreprocessor) QCC_PR_NewLine(false); @@ -2261,7 +2261,7 @@ void QCC_PR_LexWhitespace (pbool inhibitpreprocessor) do { pr_file_p++; - if (pr_file_p[0]=='\n') + if (qcc_islineending(pr_file_p[0], pr_file_p[1])) { if (!inhibitpreprocessor) QCC_PR_NewLine(true); diff --git a/engine/qclib/qccguistuff.c b/engine/qclib/qccguistuff.c index 3d284b7f8..55c0938e2 100644 --- a/engine/qclib/qccguistuff.c +++ b/engine/qclib/qccguistuff.c @@ -716,21 +716,6 @@ int GUI_BuildParms(char *args, char **argv, pbool quick)//, char *forceoutputfil paramlen += strlen(param+paramlen)+1; } - while(*args) - { - while (*args <= ' '&& *args) - args++; - - for (next = args; *next>' '; next++) - ; - strncpy(param+paramlen, args, next-args); - param[paramlen+next-args] = '\0'; - argv[argc++] = param+paramlen; - paramlen += strlen(param+paramlen)+1; - - args=next; - } - targ = 0; targ |= fl_hexen2?1:0; targ |= fl_ftetarg?2:0; @@ -796,5 +781,20 @@ int GUI_BuildParms(char *args, char **argv, pbool quick)//, char *forceoutputfil argv[argc++] = progssrcdir; } + while(*args) + { + while (*args <= ' '&& *args) + args++; + + for (next = args; *next>' '; next++) + ; + strncpy(param+paramlen, args, next-args); + param[paramlen+next-args] = '\0'; + argv[argc++] = param+paramlen; + paramlen += strlen(param+paramlen)+1; + + args=next; + } + return argc; } diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index c9ffbd08d..7f8cd3742 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -26,6 +26,12 @@ extern int optres_test2; pbool writeasm; pbool verbose; +#define VERBOSE_STANDARD 1 +#define VERBOSE_FILELIST 2 +#define VERBOSE_FIELDLIST 2 +#define VERBOSE_AUTOCVARLIST 2 +#define VERBOSE_DEBUG 3 +#define VERBOSE_DEBUGSTATEMENTS 4 //figuring out the files can be expensive. pbool qcc_nopragmaoptimise; pbool opt_stripunusedfields; extern unsigned int locals_marshalled; @@ -1036,7 +1042,7 @@ void QCC_FinaliseDef(QCC_def_t *def) if (!def->symbolheader->used) { - if (verbose >= 3) + if (verbose >= VERBOSE_DEBUG) printf("not needed: %s\n", def->name); return; } @@ -1105,7 +1111,7 @@ void QCC_UnmarshalLocals(void) #endif for (d = functions[i].firstlocal; d; d = d->nextlocal) QCC_FinaliseDef(d); - if (verbose >= 3) + if (verbose >= VERBOSE_DEBUG) { if (onum == numpr_globals) printf("code: %s:%i: function %s no private locals\n", functions[i].filen, functions[i].line, functions[i].name); @@ -1127,7 +1133,7 @@ void QCC_UnmarshalLocals(void) if (biggest < numpr_globals) biggest = numpr_globals; - if (verbose >= 3) + if (verbose >= VERBOSE_DEBUG) { if (onum == numpr_globals) printf("code: %s:%i: function %s no locals\n", functions[i].filen, functions[i].line, functions[i].name); @@ -1194,6 +1200,22 @@ static void QCC_GenerateFieldDefs(QCC_def_t *def, char *fieldname, int ofs, QCC_ dd->s_name = sname; } +char *QCC_FileForStatement(int st) +{ + char *ret = "???"; + int i; + for (i = 0; i < numfunctions; i++) + { + if (functions[i].code > 0) + { + if (st < functions[i].code) + break; + ret = functions[i].filen; + } + } + return ret; +} + CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def); pbool QCC_WriteData (int crc) @@ -1469,9 +1491,11 @@ pbool QCC_WriteData (int crc) if (funcs[i].locals && !funcs[i].parm_start) QCC_PR_Warning(0, strings + funcs[i].s_file, functions[i].line, "%s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].filen, functions[i].line, strings+funcs[i].s_name, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms); -#ifdef DEBUG_DUMP - printf("code: %s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].file, functions[i].line, strings+funcs[i].s_named, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms); -#endif + if (verbose >= VERBOSE_DEBUG) + { + printf("code: %s:%i: func %s @%i locals@%i+%i, %i parms\n", functions[i].filen, functions[i].line, strings+funcs[i].s_name, funcs[i].first_statement, funcs[i].parm_start, funcs[i].locals, funcs[i].numparms); + printf("code: %s:%i: (%i,%i,%i,%i,%i,%i,%i,%i)\n", functions[i].filen, functions[i].line, funcs[i].parm_size[0], funcs[i].parm_size[1], funcs[i].parm_size[2], funcs[i].parm_size[3], funcs[i].parm_size[4], funcs[i].parm_size[5], funcs[i].parm_size[6], funcs[i].parm_size[7]); + } } funcdata = funcs; funcdatasize = numfunctions*sizeof(*funcs); @@ -1844,9 +1868,8 @@ strofs = (strofs+3)&~3; statements32[i].b = PRLittleLong((statements[i].b.sym?statements[i].b.sym->ofs:0) + statements[i].b.ofs); statements32[i].c = PRLittleLong((statements[i].c.sym?statements[i].c.sym->ofs:0) + statements[i].c.ofs); -#ifdef DEBUG_DUMP - printf("code: %s:%i: @%i %s %i %i %i\n", "???", statements[i].linenum, i, pr_opcodes[statements[i].op].name, statements32[i].a, statements32[i].b, statements32[i].c); -#endif + if (verbose >= VERBOSE_DEBUGSTATEMENTS) + printf("code: %s:%i: @%i %s %i %i %i\n", QCC_FileForStatement(i), statements[i].linenum, i, pr_opcodes[statements[i].op].name, statements32[i].a, statements32[i].b, statements32[i].c); } if (progs.blockscompressed&1) @@ -1913,19 +1936,22 @@ strofs = (strofs+3)&~3; unsigned int c = (statements[i].c.sym?statements[i].c.sym->ofs:0) + statements[i].c.ofs; statements16[i].op = PRLittleShort((unsigned short)statements[i].op); -#if defined(DISASM) && !defined(DEBUG_DUMP) - if (i >= start && i < end) + if ( +#if defined(DISASM) + (i >= start && i < end) || #endif -#if defined(DEBUG_DUMP) || defined(DISASM) + verbose >= VERBOSE_DEBUGSTATEMENTS) { + char line[2048]; char *astr = statements[i].a.sym?statements[i].a.sym->name:""; char *bstr = statements[i].b.sym?statements[i].b.sym->name:""; char *cstr = statements[i].c.sym?statements[i].c.sym->name:""; - printf("code: %s:%i: @%i\t%s\t%i\t%i\t%i\t(%s", "???", statements[i].linenum, i, pr_opcodes[statements[i].op].opname, a, b, c, QCC_VarAtOffset(statements[i].a, 1)); - printf(" %s", QCC_VarAtOffset(statements[i].b, 1)); - printf(" %s)\n", QCC_VarAtOffset(statements[i].c, 1)); + + QC_snprintfz(line, sizeof(line), "code: %s:%i: @%i %s t%i t%i %i (%s", QCC_FileForStatement(i), statements[i].linenum, i, pr_opcodes[statements[i].op].opname, a, b, c, QCC_VarAtOffset(statements[i].a)); + QC_snprintfz(line+strlen(line), sizeof(line)-strlen(line), " %s", QCC_VarAtOffset(statements[i].b)); + QC_snprintfz(line+strlen(line), sizeof(line)-strlen(line), " %s)\n", QCC_VarAtOffset(statements[i].c)); + printf("%s", line); } -#endif #ifdef _DEBUG if (((signed)a >= (signed)numpr_globals && statements[i].a.sym) || ((signed)b >= (signed)numpr_globals && statements[i].b.sym) || ((signed)c >= (signed)numpr_globals && statements[i].c.sym)) printf("invalid offset on %s instruction\n", pr_opcodes[statements[i].op].opname); @@ -1977,13 +2003,13 @@ strofs = (strofs+3)&~3; else SafeWrite (h, funcdata, funcdatasize); - if (verbose >= 2) + if (verbose >= VERBOSE_FILELIST) QCC_PrintFiles(); - if (verbose >= 2) + if (verbose >= VERBOSE_FIELDLIST) QCC_PrintFields(); - if (verbose >= 2) + if (verbose >= VERBOSE_AUTOCVARLIST) QCC_PrintAutoCvars(); switch(outputsttype) diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 11b5c2df7..1a06a484b 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -1095,7 +1095,7 @@ progsnum_t AddProgs(const char *name) Q_strncpyz(gamedir, loc.search->purepath, sizeof(gamedir)); *COM_SkipPath(gamedir) = 0; } - Con_TPrintf("Loaded progs %s%s\n", gamedir, name); + Con_DPrintf("Loaded progs %s%s\n", gamedir, name); PR_ProgsAdded(svprogfuncs, num, name); @@ -12555,47 +12555,44 @@ void PR_DumpPlatform_f(void) VFS_PRINTF(f, "#endif\n"); } - if (accessors) - { - VFS_PRINTF(f, "#ifdef _ACCESSORS\n"); - VFS_PRINTF(f, - "accessor strbuf : float\n{\n" - "\tinline get float asfloat[float idx] = {return stof(bufstr_get(this, idx));};\n" - "\tinline set float asfloat[float idx] = {bufstr_set(this, idx, ftos(value));};\n" - "\tget string[float] = bufstr_get;\n" - "\tset string[float] = bufstr_set;\n" - "\tget float length = buf_getsize;\n" - "};\n"); - VFS_PRINTF(f, - "accessor searchhandle : float\n{\n" - "\tget string[float] = search_getfilename;\n" - "\tget float length = search_getsize;\n" - "};\n"); - VFS_PRINTF(f, - "accessor hashtable : float\n{\n" - "\tinline get vector v[string key] = {return hash_get(this, key, '0 0 0', EV_VECTOR);};\n" - "\tinline set vector v[string key] = {hash_add(this, key, value, HASH_REPLACE|EV_VECTOR);};\n" - "\tinline get string s[string key] = {return hash_get(this, key, \"\", EV_STRING);};\n" - "\tinline set string s[string key] = {hash_add(this, key, value, HASH_REPLACE|EV_STRING);};\n" - "\tinline get string f[string key] = {return hash_get(this, key, 0.0, EV_FLOAT);};\n" - "\tinline set string f[string key] = {hash_add(this, key, value, HASH_REPLACE|EV_FLOAT);};\n" - "\tinline get __variant[string key] = {return hash_get(this, key, __NULL__);};\n" - "\tinline set __variant[string key] = {hash_add(this, key, value, HASH_REPLACE);};\n" - "};\n"); - VFS_PRINTF(f, - "accessor infostring : string\n{\n" - "\tget string[string] = infoget;\n" + VFS_PRINTF(f, "#ifdef _ACCESSORS\n"); + VFS_PRINTF(f, + "accessor strbuf : float\n{\n" + "\tinline get float asfloat[float idx] = {return stof(bufstr_get(this, idx));};\n" + "\tinline set float asfloat[float idx] = {bufstr_set(this, idx, ftos(value));};\n" + "\tget string[float] = bufstr_get;\n" + "\tset string[float] = bufstr_set;\n" + "\tget float length = buf_getsize;\n" + "};\n"); + VFS_PRINTF(f, + "accessor searchhandle : float\n{\n" + "\tget string[float] = search_getfilename;\n" + "\tget float length = search_getsize;\n" + "};\n"); + VFS_PRINTF(f, + "accessor hashtable : float\n{\n" + "\tinline get vector v[string key] = {return hash_get(this, key, '0 0 0', EV_VECTOR);};\n" + "\tinline set vector v[string key] = {hash_add(this, key, value, HASH_REPLACE|EV_VECTOR);};\n" + "\tinline get string s[string key] = {return hash_get(this, key, \"\", EV_STRING);};\n" + "\tinline set string s[string key] = {hash_add(this, key, value, HASH_REPLACE|EV_STRING);};\n" + "\tinline get float f[string key] = {return hash_get(this, key, 0.0, EV_FLOAT);};\n" + "\tinline set float f[string key] = {hash_add(this, key, value, HASH_REPLACE|EV_FLOAT);};\n" + "\tinline get __variant[string key] = {return hash_get(this, key, __NULL__);};\n" + "\tinline set __variant[string key] = {hash_add(this, key, value, HASH_REPLACE);};\n" + "};\n"); + VFS_PRINTF(f, + "accessor infostring : string\n{\n" + "\tget string[string] = infoget;\n" #ifdef QCGC - "\tinline set* string[string fld] = {(*this) = infoadd(*this, fld, value);};\n" + "\tinline set* string[string fld] = {(*this) = infoadd(*this, fld, value);};\n" #endif - "};\n"); - VFS_PRINTF(f, - "accessor filestream : float\n{\n" - "\tget string = fgets;\n" - "\tinline set string = {fputs(this,value);};\n" - "};\n"); - VFS_PRINTF(f, "#endif\n"); - } + "};\n"); + VFS_PRINTF(f, + "accessor filestream : float\n{\n" + "\tget string = fgets;\n" + "\tinline set string = {fputs(this,value);};\n" + "};\n"); + VFS_PRINTF(f, "#endif\n"); VFS_PRINTF(f, "#pragma noref 0\n"); diff --git a/engine/server/server.h b/engine/server/server.h index c323c1a27..b44315506 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -504,6 +504,8 @@ typedef struct client_s packet_entities_t sentents; unsigned int *pendingdeltabits; unsigned int *pendingcsqcbits; + unsigned int nextdeltaindex; //splurged round-robin to deal with overflows + unsigned int nextcsqcindex; //splurged round-robin #define SENDFLAGS_USABLE 0x3fffffffu //this number of bits are actually safe in a float. not all together, but otherwise safe. #define SENDFLAGS_PRESENT 0x80000000u //this entity is present on that client #define SENDFLAGS_REMOVED 0x40000000u //to handle remove packetloss diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 5467ad6e2..07fb28db8 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1562,7 +1562,6 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb SVFTE_ExpandFrames(client, outno+1); break; } - client->pendingdeltabits[j] = 0; if (bits & UF_REMOVE) { //if reset is set, then reset was set eroneously. @@ -1572,6 +1571,11 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb } else if (client->sentents.entities[j].number) /*only send a new copy of the ent if they actually have one already*/ { + //if we didn't reach the end in the last packet, start at that point to avoid spam + //player slots are exempt from this, so they are in every packet (strictly speaking only the local player 'needs' this, but its nice to have it for high-priority targets too) + if (j < client->nextdeltaindex && j > svs.allocated_client_slots) + continue; + if (bits & UF_RESET2) { /*if reset2, then this is the second packet sent to the client and should have a forced reset (but which isn't tracked)*/ @@ -1593,11 +1597,19 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb SV_EmitDeltaEntIndex(msg, j, false, true); SVFTE_WriteUpdate(bits, &client->sentents.entities[j], msg, client->fteprotocolextensions2, client->sentents.bonedata); } + + client->pendingdeltabits[j] = 0; + resend[outno].flags = 0; resend[outno++].entnum = j; } MSG_WriteShort(msg, 0); + if (j == client->sentents.num_entities) //looks like we sent them all + client->nextdeltaindex = 0; //start afresh with the next packet. + else + client->nextdeltaindex = j; //we overflowed or something, start going round-robin + client->frameunion.frames[sequence & UPDATE_MASK].entities.num_entities = outno; client->frameunion.frames[sequence & UPDATE_MASK].sequence = sequence; return overflow; @@ -3984,60 +3996,61 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore client->netchan.incoming_sequence++; } SV_EmitCSQCUpdate(client, msg, svcdp_csqcentities); - return; - } -#endif - - // encode the packet entities as a delta from the - // last packetentities acknowledged by the client - - if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) - { - SVFTE_EmitPacketEntities(client, pack, msg); } else +#endif { -#ifdef QUAKESTATS - // Z_EXT_TIME protocol extension - // every now and then, send an update so that extrapolation - // on client side doesn't stray too far off - if (ISQWCLIENT(client)) + // encode the packet entities as a delta from the + // last packetentities acknowledged by the client + + if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) { - if (client->fteprotocolextensions & PEXT_ACCURATETIMINGS && sv.world.physicstime - client->nextservertimeupdate > 0) - { //the fte pext causes the server to send out accurate timings, allowing for perfect interpolation. - MSG_WriteByte (msg, svcqw_updatestatlong); - MSG_WriteByte (msg, STAT_TIME); - MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000)); - - client->nextservertimeupdate = sv.world.physicstime; - } - else if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.world.physicstime - client->nextservertimeupdate > 0) - { //the zquake ext causes the server to send out peridoic timings, allowing for moderatly accurate game time. - MSG_WriteByte (msg, svcqw_updatestatlong); - MSG_WriteByte (msg, STAT_TIME); - MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000)); - - client->nextservertimeupdate = sv.world.physicstime+10; - } + SVFTE_EmitPacketEntities(client, pack, msg); } + else + { +#ifdef QUAKESTATS + // Z_EXT_TIME protocol extension + // every now and then, send an update so that extrapolation + // on client side doesn't stray too far off + if (ISQWCLIENT(client)) + { + if (client->fteprotocolextensions & PEXT_ACCURATETIMINGS && sv.world.physicstime - client->nextservertimeupdate > 0) + { //the fte pext causes the server to send out accurate timings, allowing for perfect interpolation. + MSG_WriteByte (msg, svcqw_updatestatlong); + MSG_WriteByte (msg, STAT_TIME); + MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000)); + + client->nextservertimeupdate = sv.world.physicstime; + } + else if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.world.physicstime - client->nextservertimeupdate > 0) + { //the zquake ext causes the server to send out peridoic timings, allowing for moderatly accurate game time. + MSG_WriteByte (msg, svcqw_updatestatlong); + MSG_WriteByte (msg, STAT_TIME); + MSG_WriteLong (msg, (int)(sv.world.physicstime * 1000)); + + client->nextservertimeupdate = sv.world.physicstime+10; + } + } #endif - // send over the players in the PVS - if (svs.gametype != GT_HALFLIFE) - { - if (client == &demo.recorder) - SV_WritePlayersToMVD(client, frame, msg); - else - SV_WritePlayersToClient (client, frame, clent, cameras, msg); + // send over the players in the PVS + if (svs.gametype != GT_HALFLIFE) + { + if (client == &demo.recorder) + SV_WritePlayersToMVD(client, frame, msg); + else + SV_WritePlayersToClient (client, frame, clent, cameras, msg); + } + + SVQW_EmitPacketEntities (client, pack, msg); } - SVQW_EmitPacketEntities (client, pack, msg); + SV_EmitCSQCUpdate(client, msg, svcfte_csqcentities); + + // now add the specialized nail update + SV_EmitNailUpdate (msg, ignorepvs); } - - SV_EmitCSQCUpdate(client, msg, svcfte_csqcentities); - - // now add the specialized nail update - SV_EmitNailUpdate (msg, ignorepvs); } //just goes and makes sure each client tracks all the right SendFlags. diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index f429b198b..6a8cc3c10 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1488,8 +1488,10 @@ void SVC_GetChallenge (qboolean nodpresponse) over+=sizeof(lng); } #endif - - mask = net_mtu.ival&~7; + if (*net_mtu.string) + mask = net_mtu.ival&~7; + else + mask = 8192; if (mask > 64) { lng = LittleLong(PROTOCOL_VERSION_FRAGMENT); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 60f969cc9..4c242e050 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -237,7 +237,7 @@ A Con_Printf that only shows up if the "developer" cvar is set */ static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b) { - Con_DPrintf("%s", (char*)data); + Con_DLPrintf(level, "%s", (char*)data); BZ_Free(data); } void Con_DPrintf (const char *fmt, ...) @@ -275,6 +275,41 @@ void Con_DPrintf (const char *fmt, ...) if (log_developer.value) Con_Log(msg); // log to console } +void Con_DLPrintf (int level, const char *fmt, ...) +{ + va_list argptr; + char msg[MAXPRINTMSG]; + extern cvar_t log_developer; + + if (developer.ival < level && !log_developer.value) + return; + + va_start (argptr,fmt); + vsnprintf (msg,sizeof(msg)-1, fmt,argptr); + va_end (argptr); + + if (!Sys_IsMainThread()) + { + COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), level, 0); + return; + } + + // add to redirected message + if (sv_redirected) + { + if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1) + SV_FlushRedirect (); + strcat (sv_redirected_buf, msg); + if (sv_redirected != -1) + return; + } + + if (developer.ival >= level) + Sys_Printf ("%s", msg); // also echo to debugging console + + if (log_developer.value) + Con_Log(msg); // log to console +} #endif /* @@ -2547,8 +2582,14 @@ qboolean SV_SendClientDatagram (client_t *client) client->edict->v->goalentity = 0; } -// if (client->protocol != SCP_FITZ666 && !client->netchan.fragmentsize) - msg.maxsize = MAX_DATAGRAM; + if (client->netchan.fragmentsize) + msg.maxsize = client->netchan.fragmentsize; //try not to overflow + else if (client->protocol == SCP_NETQUAKE) + msg.maxsize = MAX_NQDATAGRAM; //vanilla client is limited. + else + msg.maxsize = MAX_DATAGRAM; //udp limit, ish. + if (msg.maxsize > countof(buf)) + msg.maxsize = countof(buf); if (sv.world.worldmodel && !client->controller) { diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 6bac2b561..0a3ca036b 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -5991,7 +5991,7 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC) if (host_client->state < cs_connected) return; - Con_DPrintf("Client command: %s\n", s); + Con_DLPrintf((host_client->netchan.remote_address.type==NA_LOOPBACK)?2:1, "Client command: %s\n", s); Cmd_TokenizeString (s, false, false); sv_player = host_client->edict;