From 9aed521689ba5c3036c4ca5bf7dbb86aee5569b6 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 4 Mar 2017 19:36:06 +0000 Subject: [PATCH] make developer a little less spammy. move much of it to developer 2. net_mtu "" now means something large for servers and something smaller for clients. this should give clients more freedom to screw up their connections as much as they want when servers are not configured. I dunno. package manager now tries to include packages listed from default.fmf. note that this may include dlls etc so this isn't available for any other fmf (ie: ones specified via the commandline/file associations). fix up trace logic to use skeletal data for skeletal models, finally fixing toneddu's big hitmodel crash. hopefully. console links inherit background text colours, where possible. fix text background colour weirdness for both freetype2 fonts and spaces. qcc: implement support for mac line endings, matching scintilla's line numbers, although this breaks rogue due to stray carrage returns inside a single-line comment (easy to fix, assuming some scintilla-based editor, anyway). server: reworked deltas overflow to do round-robin properly with priority for players, so things shouldn't stall when overloaded. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5067 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_input.c | 4 +- engine/client/cl_main.c | 26 ++++++---- engine/client/cl_parse.c | 2 +- engine/client/console.c | 40 +++++++++++++- engine/client/m_download.c | 80 +++++++++++++++++----------- engine/client/menu.c | 7 +-- engine/client/pr_menu.c | 2 +- engine/common/bothdefs.h | 4 +- engine/common/com_mesh.c | 8 +-- engine/common/com_mesh.h | 10 ++-- engine/common/common.c | 2 + engine/common/common.h | 7 ++- engine/common/console.h | 3 +- engine/common/fs.c | 24 +++++---- engine/common/fs.h | 2 +- engine/common/net_chan.c | 2 +- engine/gl/gl_font.c | 68 +++++++++++++++++++----- engine/gl/gl_model.c | 2 +- engine/qclib/cmdlib.h | 1 + engine/qclib/qcc.h | 1 + engine/qclib/qcc_pr_comp.c | 18 +++++-- engine/qclib/qcc_pr_lex.c | 8 +-- engine/qclib/qccguistuff.c | 30 +++++------ engine/qclib/qccmain.c | 64 ++++++++++++++++------- engine/server/pr_cmds.c | 77 +++++++++++++-------------- engine/server/server.h | 2 + engine/server/sv_ents.c | 103 +++++++++++++++++++++---------------- engine/server/sv_main.c | 6 ++- engine/server/sv_send.c | 47 +++++++++++++++-- engine/server/sv_user.c | 2 +- 30 files changed, 432 insertions(+), 220 deletions(-) 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;