From 1b8e779b9bed4cb37cbfadc9cc171731f19b9ebd Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 29 Jul 2019 05:28:20 +0000 Subject: [PATCH] Last fix for skyrooms. Should now show entities in the skyroom. Fix a couple of valgrind issues. Added reason info for when a download fails. Downloading models now forgets failed-to-load state, fixing a downloaded-but-still-missing bug. Use anisotropic filtering in more fps_presets. Fix significant fps loss when using the modelviewer. First attempt at automatic LOD (supported for md3s and extended-iqms for now). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5494 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- CMakeLists.txt | 65 +++++++++++++----- engine/client/cl_ents.c | 3 + engine/client/cl_main.c | 9 ++- engine/client/cl_parse.c | 92 +++++++++++++++++++++---- engine/client/cl_pred.c | 17 +++-- engine/client/client.h | 15 +++- engine/client/clq3_parse.c | 7 +- engine/client/m_options.c | 19 +++--- engine/client/merged.h | 1 + engine/client/pr_csqc.c | 2 + engine/client/renderer.c | 17 +++-- engine/common/com_mesh.c | 136 ++++++++++++++++++++++++++++--------- engine/common/net_wins.c | 4 +- engine/common/plugin.c | 7 -- engine/common/protocol.h | 8 ++- engine/common/qvm.c | 42 +++++++----- engine/common/zone.h | 7 ++ engine/gl/gl_alias.c | 73 +++++++++++++++----- engine/gl/gl_model.c | 19 ++++++ engine/gl/gl_model.h | 1 + engine/gl/gl_vidcommon.c | 11 ++- engine/gl/gl_vidlinuxglx.c | 4 +- engine/gl/gl_warp.c | 31 +++++++-- engine/qclib/pr_edict.c | 4 ++ engine/server/pr_cmds.c | 36 +++++++--- engine/server/server.h | 3 + engine/server/sv_ents.c | 15 +++- engine/server/sv_main.c | 8 +-- engine/server/sv_user.c | 2 + engine/vk/vk_init.c | 9 ++- plugins/models/gltf.c | 5 +- 31 files changed, 498 insertions(+), 174 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcf0cf88a..8a1fed1d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,6 +381,22 @@ ELSE() # engine/gl/gl_vidwayland.c ENDIF() +SET(FTE_GL_FILES +#These are GL-specific, but can be left even if no gl is supported. + engine/gl/gl_backend.c + engine/gl/gl_bloom.c + engine/gl/gl_draw.c + engine/gl/gl_rmain.c + engine/gl/gl_rmisc.c + engine/gl/gl_rsurf.c + engine/gl/gl_screen.c + engine/gl/gl_vidcommon.c + engine/gl/glmod_doom.c +) +SET(FTE_VK_FILES + engine/vk/vk_backend.c + engine/vk/vk_init.c +) SET(FTE_COMMON_FILES #these files are common to both server-only and client+server builds. engine/common/cmd.c @@ -617,13 +633,12 @@ SET(FTE_CLIENT_FILES engine/client/snd_ov.c engine/client/textedit.c engine/client/valid.c - engine/client/vid_headless.c engine/client/view.c engine/client/wad.c engine/client/zqtp.c -#These are generic renderer files +#These are generic renderer files and no longer gl-specific (for the most part) engine/gl/gl_alias.c engine/gl/gl_font.c engine/gl/gl_ngraph.c @@ -633,19 +648,10 @@ SET(FTE_CLIENT_FILES engine/gl/gl_warp.c engine/gl/ltface.c -#These are GL-specific, but can be left even if no gl is supported. - engine/gl/gl_backend.c - engine/gl/gl_bloom.c - engine/gl/gl_draw.c - engine/gl/gl_rmain.c - engine/gl/gl_rmisc.c - engine/gl/gl_rsurf.c - engine/gl/gl_screen.c - engine/gl/gl_vidcommon.c - engine/gl/glmod_doom.c - - engine/vk/vk_backend.c - engine/vk/vk_init.c +#these are renderer-specific + engine/client/vid_headless.c + ${FTE_GL_FILES} + ${FTE_VK_FILES} ) ADD_LIBRARY(fteq3bot MODULE @@ -705,6 +711,7 @@ ELSE() SET_TARGET_PROPERTIES(bullet PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(bullet PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(bullet m ${BULLET_LIBRARIES}) + SET(INSTALLTARGS ${INSTALLTARGS} bullet) ENDIF() ENDIF() @@ -717,6 +724,7 @@ IF(ANDROID) ) SET_TARGET_PROPERTIES(ftedroid PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}") TARGET_LINK_LIBRARIES(ftedroid ${FTE_LIBS} ) + SET(INSTALLTARGS ${INSTALLTARGS} ftedroid) ELSE() #systems that actually have executables... ADD_EXECUTABLE(fteqw WIN32 @@ -726,6 +734,7 @@ ELSE() ) SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}") TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS} ) + SET(INSTALLTARGS ${INSTALLTARGS} fteqw) ADD_EXECUTABLE(fteqw-sv ${FTESV_ARCH_FILES} @@ -733,12 +742,14 @@ ELSE() ) SET_TARGET_PROPERTIES(fteqw-sv PROPERTIES COMPILE_DEFINITIONS "SERVERONLY;${FTE_LIB_DEFINES};${FTESV_DEFINES};${FTE_REVISON}") TARGET_LINK_LIBRARIES(fteqw-sv ${FTESV_LIBS}) + SET(INSTALLTARGS ${INSTALLTARGS} fteqw-sv) ADD_EXECUTABLE(iqmtool iqm/iqm.cpp iqm/iqm.h ) SET_TARGET_PROPERTIES(iqmtool PROPERTIES COMPILE_DEFINITIONS "${FTE_REVISON}") + SET(INSTALLTARGS ${INSTALLTARGS} iqmtool) ADD_EXECUTABLE(qtv fteqtv/netchan.c @@ -764,6 +775,7 @@ ELSE() ELSE() TARGET_LINK_LIBRARIES(qtv m) ENDIF() + SET(INSTALLTARGS ${INSTALLTARGS} qtv) IF(NOT WIN32) ADD_EXECUTABLE(ftemaster @@ -784,6 +796,7 @@ ELSE() ) SET_TARGET_PROPERTIES(ftemaster PROPERTIES COMPILE_DEFINITIONS "MASTERONLY;${FTE_LIB_DEFINES};${FTESV_DEFINES};${FTE_REVISON}") TARGET_LINK_LIBRARIES(ftemaster ${FTESV_LIBS}) + SET(INSTALLTARGS ${INSTALLTARGS} ftemaster) ENDIF() ADD_EXECUTABLE(httpserver @@ -796,6 +809,7 @@ ELSE() IF(WIN32) TARGET_LINK_LIBRARIES(httpserver ${ZLIB_LIBRARIES} ws2_32) ENDIF() + #SET(INSTALLTARGS ${INSTALLTARGS} httpserver) ADD_EXECUTABLE(fteqcc engine/qclib/qcctui.c @@ -809,6 +823,7 @@ ELSE() ) SET_TARGET_PROPERTIES(fteqcc PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON}") TARGET_LINK_LIBRARIES(fteqcc ${ZLIB_LIBRARIES} m) + SET(INSTALLTARGS ${INSTALLTARGS} fteqcc) IF(${WIN32}) ADD_EXECUTABLE(fteqccgui WIN32 @@ -826,6 +841,7 @@ ELSE() ) SET_TARGET_PROPERTIES(fteqccgui PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON}") TARGET_LINK_LIBRARIES(fteqccgui ${ZLIB_LIBRARIES} shlwapi ole32 comctl32 comdlg32) + SET(INSTALLTARGS ${INSTALLTARGS} fteqccgui) ELSE() FIND_PACKAGE(Qt5Widgets) IF (Qt5Widgets_FOUND) @@ -846,16 +862,16 @@ ELSE() SET_TARGET_PROPERTIES(fteqccgui PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON};${Qt5Widgets_COMPILE_DEFINITIONS}") SET_PROPERTY(TARGET fteqccgui PROPERTY POSITION_INDEPENDENT_CODE TRUE) TARGET_LINK_LIBRARIES(fteqccgui ${ZLIB_LIBRARIES} ${Qt5Widgets_LIBRARIES} qscintilla2_qt5) + SET(INSTALLTARGS ${INSTALLTARGS} fteqccgui) ENDIF() ENDIF() ENDIF() - #Quake Injector Alike plugin ADD_LIBRARY(qi MODULE plugins/qvm_api.c plugins/plugin.c - plugins/qi/qi.c + plugins/qi/qi.c plugins/emailnot/md5.c plugins/jabber/xml.c ) @@ -863,6 +879,7 @@ SET_TARGET_PROPERTIES(qi PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEF SET_TARGET_PROPERTIES(qi PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(qi PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(qi m) +SET(INSTALLTARGS ${INSTALLTARGS} qi) #ODE Physics library plugin FIND_PATH(LIBODE_INCLUDE_DIR ode/ode.h) @@ -879,6 +896,7 @@ IF (LIBODE_INCLUDE_DIR) SET_TARGET_PROPERTIES(ode PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(ode PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(ode m ${LIBODE_LIBRARY}) + SET(INSTALLTARGS ${INSTALLTARGS} ode) ENDIF() #EzQuake Hud port plugin @@ -894,6 +912,7 @@ SET_TARGET_PROPERTIES(ezhud PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_ SET_TARGET_PROPERTIES(ezhud PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(ezhud PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(ezhud m) +SET(INSTALLTARGS ${INSTALLTARGS} ezhud) #IRC client plugin ADD_LIBRARY(irc MODULE @@ -905,6 +924,7 @@ SET_TARGET_PROPERTIES(irc PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DE SET_TARGET_PROPERTIES(irc PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(irc PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(irc m) +SET(INSTALLTARGS ${INSTALLTARGS} irc) #model formats plugin ADD_LIBRARY(models MODULE @@ -917,6 +937,7 @@ SET_TARGET_PROPERTIES(models PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB SET_TARGET_PROPERTIES(models PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(models PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(models m) +SET(INSTALLTARGS ${INSTALLTARGS} models) #x11 server plugin (note: for displaying other programs) ADD_LIBRARY(x11 MODULE @@ -931,6 +952,7 @@ SET_TARGET_PROPERTIES(x11 PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DE SET_TARGET_PROPERTIES(x11 PROPERTIES PREFIX "fteplug_") SET_TARGET_PROPERTIES(x11 PROPERTIES LINK_FLAGS "-Wl,--no-undefined") TARGET_LINK_LIBRARIES(x11 m) +SET(INSTALLTARGS ${INSTALLTARGS} x11) #ffmpeg client plugin. no proper way to detect dependancies right now, so I've gotta try the manual way. FIND_PATH(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h) @@ -955,6 +977,7 @@ IF((AVFORMAT_INCLUDE_DIR) AND (AVSWSCALE_INCLUDE_DIR)) TARGET_LINK_LIBRARIES(ffmpeg m ${AVFORMAT_LIBRARY} ${AVCODEC_LIBRARY} ${AVUTIL_LIBRARY} ${AVSWSCALE_LIBRARY}) SET_TARGET_PROPERTIES(ffmpeg PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;${FTE_LIB_DEFINES}") SET_TARGET_PROPERTIES(ffmpeg PROPERTIES PREFIX "fteplug_") + SET(INSTALLTARGS ${INSTALLTARGS} ffmpeg) ELSE() MESSAGE(WARNING "ffmpeg library NOT available. Quake shouldn't be playing fmv anyway.") ENDIF() @@ -978,6 +1001,14 @@ IF(NOT ANDROID) ELSE() TARGET_LINK_LIBRARIES(xmpp m resolv) ENDIF() + SET(INSTALLTARGS ${INSTALLTARGS} xmpp) ENDIF() +INCLUDE(GNUInstallDirs) +SET(FTE_INSTALL_BINDIR games CACHE STRING "Binary dir to install to.") +INSTALL(TARGETS ${INSTALLTARGS} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}${FTE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}" +) + #cef plugin diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 0406356aa..fad7b0b42 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -5641,6 +5641,9 @@ void CL_SetSolidEntities (void) physent_t *pent; model_t *mod; + VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove)); + pmove.world = &csqc_world; + memset(&pmove.physents[0], 0, sizeof(physent_t)); pmove.physents[0].model = cl.worldmodel; VectorClear (pmove.physents[0].origin); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 6c898dcee..4a7329575 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3047,6 +3047,7 @@ void CL_ConnectionlessPacket (void) int candtls = 0; //0=no,1=optional,2=mandatory #endif char guidhash[256]; + *guidhash = 0; s = MSG_ReadString (); COM_Parse(s); @@ -4090,6 +4091,8 @@ void CL_Download_f (void) if (!strnicmp(url, "qw://", 5) || !strnicmp(url, "q2://", 5)) { url += 5; + if (*url == '/') //a conforming url should always have a host section, an empty one is simply three slashes. + url++; } if (!*localname) @@ -4146,14 +4149,14 @@ void CL_DownloadSize_f(void) if (!strcmp(size, "e")) { Con_Printf("Download of \"%s\" failed. Not found.\n", rname); - CL_DownloadFailed(rname, NULL); + CL_DownloadFailed(rname, NULL, DLFAIL_SERVERFILE); } else if (!strcmp(size, "p")) { if (cls.download && stricmp(cls.download->remotename, rname)) { Con_Printf("Download of \"%s\" failed. Not allowed.\n", rname); - CL_DownloadFailed(rname, NULL); + CL_DownloadFailed(rname, NULL, DLFAIL_SERVERCVAR); } } else if (!strcmp(size, "r")) @@ -4163,7 +4166,7 @@ void CL_DownloadSize_f(void) if (!CL_AllowArbitaryDownload(rname, redirection)) return; - dl = CL_DownloadFailed(rname, NULL); + dl = CL_DownloadFailed(rname, NULL, DLFAIL_REDIRECTED); Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", rname, redirection); CL_CheckOrEnqueDownloadFile(redirection, NULL, dl->flags); } diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 7a96239d2..a5579ffc3 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -564,12 +564,14 @@ qboolean CL_EnqueDownload(const char *filename, const char *localname, unsigned COM_FileExtension(localname, ext, sizeof(ext)); if (!stricmp(ext, "dll") || !stricmp(ext, "so") || strchr(localname, '\\') || strchr(localname, ':') || strstr(localname, "..")) { + CL_DownloadFailed(filename, NULL, DLFAIL_UNTRIED); Con_Printf("Denying download of \"%s\"\n", filename); return false; } if (!(flags & DLLF_USEREXPLICIT) && !cl_downloads.ival) { + CL_DownloadFailed(filename, NULL, DLFAIL_CLIENTCVAR); if (flags & DLLF_VERBOSE) Con_Printf("cl_downloads setting prevents download of \"%s\"\n", filename); return false; @@ -581,7 +583,10 @@ qboolean CL_EnqueDownload(const char *filename, const char *localname, unsigned #ifdef NQPROT if (!webdl && cls.protocol == CP_NETQUAKE) if (!cl_dp_serverextension_download) + { + CL_DownloadFailed(filename, NULL, DLFAIL_UNSUPPORTED); return false; + } #endif for (dl = cl.faileddownloads; dl; dl = dl->next) //yeah, so it failed... Ignore it. @@ -701,7 +706,10 @@ static void CL_WebDownloadFinished(struct dl_download *dl) { if (dl->status == DL_FAILED) { - CL_DownloadFailed(dl->url, &dl->qdownload); + if (dl->replycode == 404) //regular file-not-found + CL_DownloadFailed(dl->url, &dl->qdownload, DLFAIL_SERVERFILE); + else //other stuff is PROBABLY 403forbidden, but lets blame the server's config if its a tls issue etc. + CL_DownloadFailed(dl->url, &dl->qdownload, DLFAIL_SERVERCVAR); if (dl->qdownload.flags & DLLF_ALLOWWEB) //re-enqueue it if allowed, but this time not from the web server. CL_EnqueDownload(dl->qdownload.localname, dl->qdownload.localname, dl->qdownload.flags & ~DLLF_ALLOWWEB); } @@ -745,7 +753,7 @@ static void CL_SendDownloadStartRequest(char *filename, char *localname, unsigne cls.download = &wdl->qdownload; } else - CL_DownloadFailed(filename, NULL); + CL_DownloadFailed(filename, NULL, DLFAIL_CLIENTCVAR); return; } #endif @@ -813,6 +821,8 @@ void CL_DownloadFinished(qdownload_t *dl) else { CL_CheckModelResources(filename); + + Mod_FileWritten(filename); if (!cl.sendprespawn) { /* @@ -827,6 +837,7 @@ void CL_DownloadFinished(qdownload_t *dl) } } */ + for (i = 0; i < MAX_PRECACHE_MODELS; i++) //go and load this model now. { if (!strcmp(cl.model_name[i], filename)) @@ -1707,7 +1718,43 @@ void CL_RequestNextDownload (void) if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED) { - Con_Printf("\n\n-------------\n" CON_ERROR "Couldn't download \"%s\" - cannot fully connect\n", cl.worldmodel?cl.worldmodel->name:"unknown"); + downloadlist_t *dl = NULL; + const char *worldname = cl.worldmodel?cl.worldmodel->name:"unknown"; + if (cl.worldmodel) + for (dl = cl.faileddownloads; dl; dl = dl->next) //yeah, so it failed... Ignore it. + if (!strcmp(dl->rname, cl.worldmodel->name)) + break; + Con_Printf("\n\n-------------\n"); + switch (dl?dl->failreason:DLFAIL_UNTRIED) + { + case DLFAIL_UNSUPPORTED: + Con_Printf(CON_ERROR "Download of \"%s\" not supported on this server - cannot fully connect\n", worldname); + break; + case DLFAIL_CORRUPTED: + Con_Printf(CON_ERROR "Download of \"%s\" corrupt/failed - cannot fully connect\n", worldname); + break; + case DLFAIL_CLIENTCVAR: + Con_Printf(CON_ERROR "Downloading of \"%s\" blocked by clientside cvars - tweak cl_download* before retrying\n", worldname); + break; + case DLFAIL_CLIENTFILE: + Con_Printf(CON_ERROR "Disk error downloading \"%s\" - cannot fully connect\n", worldname); + break; + case DLFAIL_SERVERCVAR: + Con_Printf(CON_ERROR "Download of \"%s\" denied by server - cannot fully connect\n", worldname); + break; + case DLFAIL_SERVERFILE: + Con_Printf(CON_ERROR "Download of \"%s\" unavailable - cannot fully connect\n", worldname); + break; + case DLFAIL_REDIRECTED: + Con_Printf(CON_ERROR "Redirection failure downloading \"%s\" - cannot fully connect\n", worldname); + break; + case DLFAIL_UNTRIED: + if (COM_FCheckExists(worldname)) + Con_Printf(CON_ERROR "Couldn't load \"%s\" - corrupt? - cannot fully connect\n", worldname); + else + Con_Printf(CON_ERROR "Couldn't find \"%s\" - cannot fully connect\n", worldname); + break; + } #ifdef HAVE_MEDIA_ENCODER if (cls.demoplayback && Media_Capturing()) { @@ -1838,7 +1885,7 @@ static char *ZLibDownloadDecode(int *messagesize, char *input, int finalsize) } #endif -downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl) +downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl, enum dlfailreason_e failreason) { //add this to our failed list. (so we don't try downloading it again...) downloadlist_t *failed, **link, *dl; @@ -1846,6 +1893,7 @@ downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl) failed->next = cl.faileddownloads; cl.faileddownloads = failed; Q_strncpyz(failed->rname, name, sizeof(failed->rname)); + failed->failreason = failreason; //if this is what we're currently downloading, close it up now. //don't do this if we're just marking the file as unavailable for download. @@ -2148,10 +2196,12 @@ static void CL_ParseChunkedDownload(qdownload_t *dl) if (flag < 0) { + enum dlfailreason_e failreason; if (flag == DLERR_REDIRECTFILE) { if (CL_AllowArbitaryDownload(dl->remotename, svname)) { + failreason = DLFAIL_REDIRECTED; Con_Printf("Download of \"%s\" redirected to \"%s\"\n", dl->remotename, svname); if (!strncmp(svname, "package/", 8)) { @@ -2182,20 +2232,32 @@ static void CL_ParseChunkedDownload(qdownload_t *dl) } } else if (CL_CheckOrEnqueDownloadFile(svname, NULL, 0)) + { Con_Printf("However, \"%s\" already exists. You may need to delete it.\n", svname); + failreason = DLFAIL_CLIENTFILE; + } } svname = dl->remotename; } else if (flag == DLERR_UNKNOWN) + { Con_Printf("Server reported an error when downloading file \"%s\"\n", svname); + failreason = DLFAIL_CORRUPTED; + } else if (flag == DLERR_PERMISSIONS) + { Con_Printf("Server permissions deny downloading file \"%s\"\n", svname); + failreason = DLFAIL_SERVERCVAR; + } else //if (flag == DLERR_FILENOTFOUND) + { Con_Printf("Couldn't find file \"%s\" on the server\n", svname); + failreason = DLFAIL_SERVERFILE; + } if (dl) { - CL_DownloadFailed(svname, dl); + CL_DownloadFailed(svname, dl, failreason); CL_RequestNextDownload(); } @@ -2233,7 +2295,7 @@ static void CL_ParseChunkedDownload(qdownload_t *dl) if (!DL_Begun(dl)) { - CL_DownloadFailed(svname, dl); + CL_DownloadFailed(svname, dl, DLFAIL_CLIENTFILE); return; } @@ -2578,7 +2640,7 @@ static void CL_ParseDownload (qboolean zlib) Con_DPrintf("Download for %s redirected to %s\n", requestedname, name); /*quakeforge http download redirection*/ if (dl) - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_REDIRECTED); //FIXME: find some safe way to do this and actually test it. we should already know the local name, but we might have gained a .gz or something (this is quakeforge after all). // CL_CheckOrEnqueDownloadFile(name, localname, DLLF_IGNOREFAILED); return; @@ -2603,7 +2665,7 @@ static void CL_ParseDownload (qboolean zlib) Con_TPrintf ("File not found.\n"); if (dl) - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_SERVERFILE); return; } @@ -2615,7 +2677,7 @@ static void CL_ParseDownload (qboolean zlib) { msg_readcount += size; Con_TPrintf ("Failed to open %s\n", dl->tempname); - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_CLIENTFILE); CL_RequestNextDownload (); return; } @@ -2835,7 +2897,7 @@ static void CLDP_ParseDownloadBegin(char *s) dl->size = size; if (!DL_Begun(dl)) { - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_CLIENTFILE); return; } @@ -2884,7 +2946,7 @@ static void CLDP_ParseDownloadFinished(char *s) else { Con_Printf("Download failed: unable to check CRC of download\n"); - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_CLIENTFILE); return; } @@ -2892,13 +2954,13 @@ static void CLDP_ParseDownloadFinished(char *s) if (size != atoi(Cmd_Argv(1))) { Con_Printf("Download failed: wrong file size\n"); - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_CORRUPTED); return; } if (runningcrc != atoi(Cmd_Argv(2))) { Con_Printf("Download failed: wrong crc\n"); - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_CORRUPTED); return; } @@ -3085,7 +3147,7 @@ static void CLQW_ParseServerData (void) { //if we didn't actually start downloading it yet, cancel the current download. //this is to avoid qizmo not responding to the download command, resulting in hanging downloads that cause the client to then be unable to connect anywhere simply because someone's skin was set. - CL_DownloadFailed(cls.download->remotename, cls.download); + CL_DownloadFailed(cls.download->remotename, cls.download, DLFAIL_CORRUPTED); } Con_DPrintf ("Serverdata packet %s.\n", cls.demoplayback?"read":"received"); @@ -6368,7 +6430,7 @@ static void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds else if (cls.protocol == CP_NETQUAKE && !strcmp(stufftext, "stopdownload")) //download command reported failure. safe to request the next. { if (cls.download) - CL_DownloadFailed(cls.download->remotename, cls.download); + CL_DownloadFailed(cls.download->remotename, cls.download, DLFAIL_CORRUPTED); } //DP servers use these to report the correct csprogs.dat file+version to use. diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index b5144b951..e4c25e34c 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -1219,13 +1219,14 @@ void CL_PredictMovePNum (int seat) //just in case we don't run any prediction VectorCopy(tostate->gravitydir, pmove.gravitydir); - if (nopred) - { //still need the player's size for onground detection and bobbing. - VectorCopy(tostate->szmins, pmove.player_mins); - VectorCopy(tostate->szmaxs, pmove.player_maxs); - } - else - { + //if all else fails... + pmove.pm_type = tostate->pm_type; + pmove.onground = tostate->onground; + VectorCopy(tostate->szmins, pmove.player_mins); + VectorCopy(tostate->szmaxs, pmove.player_maxs); + + if (!nopred) + { for (i=1 ; isize == (unsigned int)-1) - { + { //the only downloads we should be getting is pk3s. + //if they're advertised-but-failing then its probably due to permissions rather than file-not-found s = MSG_ReadString(); - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_SERVERCVAR); Host_EndGame("%s", s); return; } @@ -398,7 +399,7 @@ void CLQ3_ParseDownload(void) { if (!DL_Begun(dl)) { - CL_DownloadFailed(dl->remotename, dl); + CL_DownloadFailed(dl->remotename, dl, DLFAIL_CLIENTFILE); return; } } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index dca3db017..77eef8584 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -921,6 +921,7 @@ const char *presetexec[] = //"d_mipcap \"0 3\";" //logically correct, but will fuck up on ATI drivers if increased mid-map, because ATI will just ignore any levels that are not currently enabled. "cl_gibfilter 0;" "seta cl_deadbodyfilter 0;" + "gl_texture_anisotropic_filtering 4;" "cl_fullpitch 1;maxpitch 90;seta minpitch -90;" //QS has cheaty viewpitch range. some maps require it. , //vanilla-esque options (for purists). @@ -982,7 +983,6 @@ const char *presetexec[] = // "gl_detail 1;" "r_lightstylesmooth 1;" "r_deluxemapping 2;" - "gl_texture_anisotropic_filtering 4;" , // realtime options "r_bloom 1;" @@ -3495,15 +3495,15 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ vec3_t dir; float f; - VectorAdd(v1, ent.origin, v1); - VectorAdd(v2, ent.origin, v2); - VectorAdd(tr.endpos, ent.origin, tr.endpos); + VectorMA(ent.origin, ent.scale, v1, v1); + VectorMA(ent.origin, ent.scale, v2, v2); + VectorMA(ent.origin, ent.scale, tr.endpos, tr.endpos); VectorSubtract(tr.endpos, v1, dir); f = DotProduct(dir, tr.plane.normal) * -2; VectorMA(dir, f, tr.plane.normal, v2); VectorAdd(v2, tr.endpos, v2); - + CLQ1_DrawLine(s, v1, tr.endpos, 0, 1, 0, 1); CLQ1_DrawLine(s, tr.endpos, v2, 1, 0, 0, 1); } @@ -3545,14 +3545,14 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ Mod_GetTag(ent.model, b, &ent.framestate, boneinfo); //fixme: no axis transform VectorSet(start, boneinfo[3], boneinfo[7], boneinfo[11]); - VectorAdd(start, ent.origin, start); + VectorMA(ent.origin, ent.scale, start, start); if (p) { Mod_GetTag(ent.model, p, &ent.framestate, boneinfo); //fixme: no axis transform VectorSet(end, boneinfo[3], boneinfo[7], boneinfo[11]); - VectorAdd(end, ent.origin, end); + VectorMA(ent.origin, ent.scale, end, end); CLQ1_DrawLine(lineshader, start, end, 1, (b-1 == mods->boneidx)?0:1, 1, 1); } if (b-1 == mods->boneidx) @@ -3567,7 +3567,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ } } - V_AddEntity(&ent); + V_AddAxisEntity(&ent); R_RenderView(); @@ -3670,6 +3670,8 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ #ifdef SKELETALMODELS "numbones: %i\n" #endif + "minlod: %g\n" + "maxlod: %g%s\n" , ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2], contents, inf->csurface.flags, @@ -3679,6 +3681,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ #ifdef SKELETALMODELS ,inf->numbones #endif + ,inf->mindist,inf->maxdist,inf->maxdist?"":" (infinite)" ) , CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs); } diff --git a/engine/client/merged.h b/engine/client/merged.h index c0699bb1b..402cd0bcb 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -181,6 +181,7 @@ extern qboolean Mod_PurgeModel (struct model_s *mod, enum mod_purge_e ptype) extern struct model_s *Mod_FindName (const char *name); //find without loading. needload should be set. extern struct model_s *Mod_ForName (const char *name, enum mlverbosity_e verbosity); //finds+loads extern struct model_s *Mod_LoadModel (struct model_s *mod, enum mlverbosity_e verbose); //makes sure a model is loaded +extern void Mod_FileWritten (const char *filename); extern void *Mod_Extradata (struct model_s *mod); // handles caching extern void Mod_TouchModel (const char *name); extern const char *Mod_FixName (const char *modname, const char *worldname); //remaps the name appropriately diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 3381d6a05..e2bb674b6 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3570,6 +3570,8 @@ static void QCBUILTIN PF_cs_runplayerphysics (pubprogfuncs_t *prinst, struct glo if (!cl.worldmodel) return; //urm.. + VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove)); + //debugging field pmove.sequence = *csqcg.clientcommandframe; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index adb0ddbbc..35bc70b39 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -255,11 +255,11 @@ cvar_t scr_sshot_prefix = CVAR ("scr_sshot_prefix", "screenshots/fte-"); cvar_t scr_viewsize = CVARFC("viewsize", "100", CVAR_ARCHIVE, SCR_Viewsize_Callback); #ifdef ANDROID -cvar_t vid_conautoscale = CVARF ("vid_conautoscale", "2", - CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); +cvar_t vid_conautoscale = CVARAF ("vid_conautoscale", "2", + "scr_conscale"/*qs*/ /*"vid_conscale"ez*/, CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); #else -cvar_t vid_conautoscale = CVARFD ("vid_conautoscale", "0", - CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, "Changes the 2d scale, including hud, console, and fonts. To specify an explicit font size, divide the desired 'point' size by 8 to get the scale. High values will be clamped to maintain at least a 320*200 virtual size."); +cvar_t vid_conautoscale = CVARAFD ("vid_conautoscale", "0", + "scr_conscale"/*qs*/ /*"vid_conscale"ez*/, CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, "Changes the 2d scale, including hud, console, and fonts. To specify an explicit font size, divide the desired 'point' size by 8 to get the scale. High values will be clamped to maintain at least a 320*200 virtual size."); #endif cvar_t vid_conheight = CVARF ("vid_conheight", "0", CVAR_ARCHIVE); @@ -407,8 +407,8 @@ cvar_t gl_specular_fallbackexp = CVARF ("gl_specular_fallbackexp", "1", CVAR #endif // The callbacks are not in D3D yet (also ugly way of seperating this) -cvar_t gl_texture_anisotropic_filtering = CVARFCD("gl_texture_anisotropic_filtering", "0", - CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, +cvar_t gl_texture_anisotropic_filtering = CVARAFCD("gl_texture_anisotropy", "4", + "gl_texture_anisotropic_filtering"/*old*/, CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, Image_TextureMode_Callback, "Allows for higher quality textures on surfaces that slope away from the camera (like the floor). Set to 16 or something. Only supported with trilinear filtering."); cvar_t gl_texturemode = CVARFCD("gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK | CVAR_SAVE, Image_TextureMode_Callback, @@ -430,6 +430,8 @@ cvar_t r_portalrecursion = CVARD ("r_portalrecursion", "1", "The number of cvar_t r_portaldrawplanes = CVARD ("r_portaldrawplanes", "0", "Draw front and back planes in portals. Debug feature."); cvar_t r_portalonly = CVARD ("r_portalonly", "0", "Don't draw things which are not portals. Debug feature."); cvar_t r_noaliasshadows = CVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE); +cvar_t r_lodscale = CVARFD ("r_lodscale", "5", CVAR_ARCHIVE, "Scales the level-of-detail reduction on models (for those that have lod)."); +cvar_t r_lodbias = CVARFD ("r_lodbias", "0", CVAR_ARCHIVE, "Biases the level-of-detail on models (for those that have lod)."); cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting."); cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground."); cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc."); @@ -537,6 +539,9 @@ void GLRenderer_Init(void) Cvar_Register (&r_portalonly, GLRENDEREROPTIONS); Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS); + Cvar_Register (&r_lodscale, GRAPHICALNICETIES); + Cvar_Register (&r_lodbias, GRAPHICALNICETIES); + Cvar_Register (&gl_motionblur, GLRENDEREROPTIONS); Cvar_Register (&gl_motionblurscale, GLRENDEREROPTIONS); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index ec5afe137..56a08a2ba 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -2047,7 +2047,7 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool galiasinfo_t *mod; scenetris_t *t; vecV_t *posedata = NULL; - vec3_t *normdata = NULL; + vec3_t *normdata = NULL, tmp; int surfnum = 0, i; #ifdef SKELETALMODELS int cursurfnum = -1; @@ -2113,7 +2113,6 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool if (normals && normdata) { //pegs, one on each vertex. - vec3_t push; if (cl_numstris == cl_maxstris) { cl_maxstris+=8; @@ -2135,14 +2134,15 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool cl_stris_ExpandVerts(cl_numstrisvert+t->numvert); for (i = 0; i < mod->numverts; i++) { - VectorMA(ent->origin, posedata[i][0], ent->axis[0], cl_strisvertv[t->firstvert+i*2+0]); - VectorMA(cl_strisvertv[t->firstvert+i*2+0], posedata[i][1], ent->axis[1], cl_strisvertv[t->firstvert+i*2+0]); - VectorMA(cl_strisvertv[t->firstvert+i*2+0], posedata[i][2], ent->axis[2], cl_strisvertv[t->firstvert+i*2+0]); + VectorMA(ent->origin, posedata[i][0], ent->axis[0], tmp); + VectorMA(tmp, posedata[i][1], ent->axis[1], tmp); + VectorMA(tmp, posedata[i][2], ent->axis[2], tmp); + VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i*2+0]); - VectorMA(posedata[i], 0.1, normdata[i], push); - VectorMA(ent->origin, push[0], ent->axis[0], cl_strisvertv[t->firstvert+i*2+1]); - VectorMA(cl_strisvertv[t->firstvert+i*2+1], push[1], ent->axis[1], cl_strisvertv[t->firstvert+i*2+1]); - VectorMA(cl_strisvertv[t->firstvert+i*2+1], push[2], ent->axis[2], cl_strisvertv[t->firstvert+i*2+1]); + VectorMA(tmp, 0.1*normdata[i][0], ent->axis[0], tmp); + VectorMA(tmp, 0.1*normdata[i][1], ent->axis[1], tmp); + VectorMA(tmp, 0.1*normdata[i][2], ent->axis[2], tmp); + VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i*2+1]); Vector2Set(cl_strisvertt[t->firstvert+i*2+0], 0.0, 0.0); Vector2Set(cl_strisvertt[t->firstvert+i*2+1], 1.0, 1.0); @@ -2182,10 +2182,10 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool cl_stris_ExpandVerts(cl_numstrisvert+mod->numverts); for (i = 0; i < mod->numverts; i++) { - VectorMA(ent->origin, posedata[i][0], ent->axis[0], cl_strisvertv[t->firstvert+i]); - VectorMA(cl_strisvertv[t->firstvert+i], posedata[i][1], ent->axis[1], cl_strisvertv[t->firstvert+i]); - VectorMA(cl_strisvertv[t->firstvert+i], posedata[i][2], ent->axis[2], cl_strisvertv[t->firstvert+i]); - // VectorAdd(ent->origin, posedata[i], cl_strisvertv[t->firstvert+i]); + VectorMA(vec3_origin, posedata[i][0], ent->axis[0], tmp); + VectorMA(tmp, posedata[i][1], ent->axis[1], tmp); + VectorMA(tmp, posedata[i][2], ent->axis[2], tmp); + VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i]); Vector2Set(cl_strisvertt[t->firstvert+i], 0.5, 0.5); Vector4Set(cl_strisvertc[t->firstvert+i], (mod->contents?1:0), 1, 1, 0.1); @@ -5171,7 +5171,8 @@ typedef struct { } md3Shader_t; //End of Tenebrae 'assistance' -static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) +//q3 loads foo.md3, foo_1.md3, foo_2.md3 etc +static galiasinfo_t *Mod_LoadQ3ModelLod(model_t *mod, int *surfcount, void *buffer, size_t fsize) { #ifndef SERVERONLY galiasskin_t *skin; @@ -5194,13 +5195,14 @@ static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) vec3_t max; galiaspose_t *pose; - galiasinfo_t *parent, *root; galiasanimation_t *group; vecV_t *verts; md3Triangle_t *intris; md3XyzNormal_t *invert; + galiasinfo_t *first = NULL; + galiasinfo_t **surflink = &first; int size; @@ -5218,20 +5220,16 @@ static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) // if (header->version != sdfs) // Sys_Error("GL_LoadQ3Model: Bad version\n"); - parent = NULL; - root = NULL; - #ifndef SERVERONLY externalskins = Mod_CountSkinFiles(mod); #endif - min[0] = min[1] = min[2] = 0; - max[0] = max[1] = max[2] = 0; - framegroups = ParseFrameInfo(mod->name, &numgroups); + ClearBounds(min, max); + surf = (md3Surface_t *)((qbyte *)header + LittleLong(header->ofsSurfaces)); - for (s = 0; s < LittleLong(header->numSurfaces); s++) + for (s = 0; s < LittleLong(header->numSurfaces); s++, *surfcount+=1) { if (LittleLong(surf->ident) != MD3_IDENT) Con_Printf(CON_WARNING "Warning: md3 sub-surface doesn't match ident\n"); @@ -5248,12 +5246,13 @@ static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) galias->numanimations = numgroups; galias->numverts = numverts; galias->numindexes = LittleLong(surf->numTriangles)*3; - galias->shares_verts = s; //with itself, so no sharing. - if (parent) - parent->nextsurf = galias; - else - root = galias; - parent = galias; + galias->shares_verts = *surfcount; //with itself, so no sharing. + + if (!first) + first = galias; + *surflink = galias; + surflink = &galias->nextsurf; + galias->nextsurf = NULL; //load the texcoords #ifndef SERVERONLY @@ -5403,16 +5402,83 @@ static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) } #endif - VectorCopy(min, mod->mins); - VectorCopy(max, mod->maxs); - - Mod_CompileTriangleNeighbours (mod, galias); Mod_BuildTextureVectors(galias); + //if the surfacename is eg _1 then strip that off. + //this works around q3data requiring different surface names in higher lod levels (and matches q3). + size = strlen(galias->surfacename); + if (size>2 && galias->surfacename[size-2] == '_') + galias->surfacename[size-2] = 0; + surf = (md3Surface_t *)((qbyte *)surf + LittleLong(surf->ofsEnd)); } + AddPointToBounds(min, mod->mins, mod->maxs); + AddPointToBounds(max, mod->mins, mod->maxs); + return first; +} +static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) +{ +// int version; + + galiasinfo_t *root; + md3Header_t *header; + + int lod; + int surfcount = 0; + + header = buffer; + +// if (header->version != sdfs) +// Sys_Error("GL_LoadQ3Model: Bad version\n"); + + root = NULL; + + ClearBounds(mod->mins, mod->maxs); + + mod->meshinfo = Mod_LoadQ3ModelLod(mod, &surfcount, buffer, fsize); + if (mod->meshinfo) + { + const char *ext = COM_GetFileExtension(mod->name, NULL); + if (*ext == '.' && ext-mod->name < MAX_QPATH) + { + galiasinfo_t *sublod; + sublod = mod->meshinfo; + for(lod = 1; lod > 0; lod++) + { + size_t s; + char *f; + char basename[MAX_QPATH]; + memcpy(basename, mod->name, ext-mod->name); + basename[ext-mod->name] = 0; + f = FS_LoadMallocFile(va("%s_%i.%s", basename, lod, ext), &s); + if (!f) + break; + root = sublod; + sublod = Mod_LoadQ3ModelLod(mod, &surfcount, f, s); + if (sublod) + { + for(;;) + { + root->maxdist = lod; + if (!root->nextsurf) + break; + root = root->nextsurf; + } + root->nextsurf = sublod; + for (root = sublod; root; root = root->nextsurf) + root->mindist = lod; + mod->maxlod = lod+1; + } + else + lod = -1; + FS_FreeFile(f); + } + } + } + + root = mod->meshinfo; if (!root) { root = ZG_Malloc(&mod->memgroup, sizeof(galiasinfo_t)); @@ -5426,6 +5492,7 @@ static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) { md3tag_t *src; md3tag_t *dst; + int s, i, j; src = (md3tag_t *)((char*)header+LittleLong(header->ofsTags)); dst = root->ofstags; @@ -5450,6 +5517,8 @@ static qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer, size_t fsize) } } + mod->radius = RadiusFromBounds(mod->mins, mod->maxs); + #ifndef SERVERONLY if (mod_md3flags.value) mod->flags = LittleLong(header->flags); @@ -7810,6 +7879,9 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz gai[i].surfaceid = ftemesh[i].surfaceid; gai[i].mindist = ftemesh[i].mindist; gai[i].maxdist = ftemesh[i].maxdist; + + mod->maxlod = max(mod->maxlod, gai[i].mindist); + mod->maxlod = max(mod->maxlod, gai[i].maxdist); } } gai[i-1].nextsurf = NULL; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 8e0f02fcd..e552b04f3 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -134,9 +134,9 @@ cvar_t net_enable_tls = CVARD("net_enable_tls", "1", "If enabled, binary dat #endif #ifdef HAVE_HTTPSV #ifdef SV_MASTER -cvar_t net_enable_http = CVARD("net_enable_http", "1", "If enabled, tcp ports will accept http clients, potentially serving large files which could distrupt gameplay."); +cvar_t net_enable_http = CVARD("net_enable_http", "1", "If enabled, tcp ports will accept inbound http clients, potentially serving large files which could distrupt gameplay (This does not affect outgoing http(s) requests)."); #else -cvar_t net_enable_http = CVARD("net_enable_http", "0", "If enabled, tcp ports will accept http clients, potentially serving large files which could distrupt gameplay."); +cvar_t net_enable_http = CVARD("net_enable_http", "0", "If enabled, tcp ports will accept inbound http clients, potentially serving large files which could distrupt gameplay (This does not affect outgoing http(s) requests)."); #endif cvar_t net_enable_websockets = CVARD("net_enable_websockets", "1", "If enabled, tcp ports will accept websocket game clients."); cvar_t net_enable_webrtcbroker = CVARD("net_enable_webrtcbroker", "0", "If 1, tcp ports will accept websocket connections from clients trying to broker direct webrtc connections. This should be low traffic, but might involve a lot of mostly-idle connections."); diff --git a/engine/common/plugin.c b/engine/common/plugin.c index db677c3ba..ad6935f4c 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -288,13 +288,6 @@ static plugin_t *Plug_Load(const char *file, int type) COM_StripExtension(file, temp, sizeof(temp)); newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL); } -#ifndef ANDROID - if (!newplug->vm && (type & PLUG_NATIVE)) - { - Q_snprintfz(temp, sizeof(temp), PLUGINPREFIX"%s_", file); - newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL); - } -#endif if (!newplug->vm && (type & PLUG_NATIVE)) { Q_snprintfz(temp, sizeof(temp), PLUGINPREFIX"%s", file); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index ee6d2b8fb..7e4fed47a 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -18,6 +18,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // protocol.h -- communications protocols + +#include "bothdefs.h" + #define PEXT_SETVIEW 0x00000001 #define PEXT_SCALE 0x00000002 @@ -79,7 +82,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PEXT2_PREDINFO 0x00000020 //movevar stats, NQ input sequences+acks. #define PEXT2_NEWSIZEENCODING 0x00000040 //richer size encoding. #define PEXT2_INFOBLOBS 0x00000080 //serverinfo+userinfo lengths can be MUCH higher (protocol is unbounded, but expect low sanity limits on userinfo), and contain nulls etc. -//#define PEXT2_NEWINTENTS 0x00000100 //clc_move changes +//#define PEXT2_NEWINTENTS 0x00000100 //clc_move changes, more buttons etc #define PEXT2_CLIENTSUPPORT (PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS|PEXT2_PREDINFO|PEXT2_NEWSIZEENCODING|PEXT2_INFOBLOBS) //EzQuake/Mvdsv extensions. (use ezquake name, to avoid confusion about .mvd format and its protocol differences) @@ -141,6 +144,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PORT_QWCLIENT 27001 #define PORT_QWMASTER 27000 #define PORT_QWSERVER 27500 +#define PORT_H2SERVER 26900 #define PORT_Q2CLIENT 27901 #define PORT_Q2SERVER 27910 #define PORT_Q3MASTER 27950 @@ -152,8 +156,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PORT_DEFAULTSERVER PORT_QWSERVER #endif -//hexen2: 26900 - //========================================= // out of band message id bytes diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 28b683554..93905eb90 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -76,11 +76,6 @@ struct vm_s { qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain, sys_calldll_t syscall) { void (EXPORT_FN *dllEntry)(sys_calldll_t syscall); - char dllname_archpri[MAX_OSPATH]; //id compatible -#ifdef ARCH_ALTCPU_POSTFIX - char dllname_archsec[MAX_OSPATH]; //id compatible -#endif - char dllname_anycpu[MAX_OSPATH];//simple dllhandle_t *hVM; char fname[MAX_OSPATH*2]; @@ -94,12 +89,6 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain {NULL, NULL}, }; - snprintf(dllname_archpri, sizeof(dllname_archpri), "%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name); -#ifdef ARCH_ALTCPU_POSTFIX - snprintf(dllname_archsec, sizeof(dllname_archsec), "%s"ARCH_ALTCPU_POSTFIX ARCH_DL_POSTFIX, name); -#endif - snprintf(dllname_anycpu, sizeof(dllname_anycpu), "%s" ARCH_DL_POSTFIX, name); - hVM=NULL; *fname = 0; @@ -143,14 +132,19 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname))) hVM = Sys_LoadLibrary(fname, funcs); #else - if (!hVM && FS_NativePath(dllname_archpri, FS_BINARYPATH, fname, sizeof(fname))) + + if (!hVM && FS_NativePath(va("%s_"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name), FS_BINARYPATH, fname, sizeof(fname))) hVM = Sys_LoadLibrary(fname, funcs); - if (!hVM && FS_NativePath(dllname_anycpu, FS_BINARYPATH, fname, sizeof(fname))) + if (!hVM && FS_NativePath(va("%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name), FS_BINARYPATH, fname, sizeof(fname))) + hVM = Sys_LoadLibrary(fname, funcs); + if (!hVM && FS_NativePath(va("%s" ARCH_DL_POSTFIX, name), FS_BINARYPATH, fname, sizeof(fname))) hVM = Sys_LoadLibrary(fname, funcs); - if (!hVM && FS_NativePath(dllname_archpri, FS_ROOT, fname, sizeof(fname))) + if (!hVM && FS_NativePath(va("%s_"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name), FS_ROOT, fname, sizeof(fname))) hVM = Sys_LoadLibrary(fname, funcs); - if (!hVM && FS_NativePath(dllname_anycpu, FS_ROOT, fname, sizeof(fname))) + if (!hVM && FS_NativePath(va("%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, name), FS_ROOT, fname, sizeof(fname))) + hVM = Sys_LoadLibrary(fname, funcs); + if (!hVM && FS_NativePath(va("%s" ARCH_DL_POSTFIX, name), FS_ROOT, fname, sizeof(fname))) hVM = Sys_LoadLibrary(fname, funcs); #endif } @@ -165,7 +159,13 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain { if (!hVM) { - snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_archpri); + snprintf (fname, sizeof(fname), "%s%s_"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, gpath, name); + Con_DLPrintf(2, "Loading native: %s\n", fname); + hVM = Sys_LoadLibrary(fname, funcs); + } + if (!hVM) + { + snprintf (fname, sizeof(fname), "%s%s"ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, gpath, name); Con_DLPrintf(2, "Loading native: %s\n", fname); hVM = Sys_LoadLibrary(fname, funcs); } @@ -173,7 +173,13 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain #ifdef ARCH_ALTCPU_POSTFIX if (!hVM) { - snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_archsec); + snprintf (fname, sizeof(fname), "%s%s_"ARCH_ALTCPU_POSTFIX ARCH_DL_POSTFIX, gpath, name); + Con_DLPrintf(2, "Loading native: %s\n", fname); + hVM = Sys_LoadLibrary(fname, funcs); + } + if (!hVM) + { + snprintf (fname, sizeof(fname), "%s%s"ARCH_ALTCPU_POSTFIX ARCH_DL_POSTFIX, gpath, name); Con_DLPrintf(2, "Loading native: %s\n", fname); hVM = Sys_LoadLibrary(fname, funcs); } @@ -181,7 +187,7 @@ qboolean QVM_LoadDLL(vm_t *vm, const char *name, qboolean binroot, void **vmMain if (!hVM) { - snprintf (fname, sizeof(fname), "%s%s", gpath, dllname_anycpu); + snprintf (fname, sizeof(fname), "%s%s"ARCH_DL_POSTFIX, gpath, name); Con_DLPrintf(2, "Loading native: %s\n", fname); hVM = Sys_LoadLibrary(fname, funcs); } diff --git a/engine/common/zone.h b/engine/common/zone.h index 4c8da9aad..ae1747097 100644 --- a/engine/common/zone.h +++ b/engine/common/zone.h @@ -83,6 +83,13 @@ Zone block */ +#if 0//defined(_DEBUG) && defined(__linux__) && !defined(ANDROID) + #include +#else + #define VALGRIND_MAKE_MEM_UNDEFINED(ptr,sz) //as an alternative to memzero.. + #define VALGRIND_MAKE_MEM_NOACCESS(ptr,sz) +#endif + void Memory_Init (void); void Memory_DeInit(void); diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 2c30f97a1..8417c74e5 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -39,7 +39,7 @@ typedef struct extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models, ruleset_allow_fbmodels; extern cvar_t r_noaliasshadows; - +extern cvar_t r_lodscale, r_lodbias; extern cvar_t gl_ati_truform; extern cvar_t r_vertexdlights; @@ -715,24 +715,12 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e galiascolourmapped_t *cm; char hashname[512]; - if (plskin) - { - snprintf(hashname, sizeof(hashname), "%s$%s$%i", model->name, plskin->name, surfnum); - skinname = hashname; - } - else if (surfnum) - { - snprintf(hashname, sizeof(hashname), "%s$%i", model->name, surfnum); - skinname = hashname; - } - else - skinname = model->name; - if (!skincolourmapped.numbuckets) { - void *buckets = BZ_Malloc(Hash_BytesForBuckets(256)); - memset(buckets, 0, Hash_BytesForBuckets(256)); - Hash_InitTable(&skincolourmapped, 256, buckets); + int bucketcount = 256; + void *buckets = BZ_Malloc(Hash_BytesForBuckets(bucketcount)); + memset(buckets, 0, Hash_BytesForBuckets(bucketcount)); + Hash_InitTable(&skincolourmapped, bucketcount, buckets); } if (!inf->numskins) @@ -779,8 +767,27 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e bc = 0xfe000000; generateupperlower = true; } + if (!skins || !skins->numframes || !skins->frame[subframe].texels) + { //no top/bottom colourmapping possible here. don't cache a million different values. + tc = 0xfe000000; + bc = 0xfe000000; + generateupperlower = true; + } } + if (plskin) + { + snprintf(hashname, sizeof(hashname), "%s$%s$%i", model->name, plskin->name, surfnum); + skinname = hashname; + } + else if (surfnum) + { + snprintf(hashname, sizeof(hashname), "%s$%i", model->name, surfnum); + skinname = hashname; + } + else + skinname = model->name; + for (cm = Hash_Get(&skincolourmapped, skinname); cm; cm = Hash_GetNext(&skincolourmapped, skinname, cm)) { if (cm->tcolour == tc && cm->bcolour == bc && cm->skinnum == e->skinnum && cm->subframe == subframe && cm->pclass == pc) @@ -1685,6 +1692,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) batch_t *b; int surfnum, j; shadersort_t sort; + float lod; texnums_t *skin; @@ -1732,8 +1740,39 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) inf = Mod_Extradata (clmodel); + if (clmodel->maxlod) + { + vec3_t v; + float z; + + VectorSubtract(e->origin, r_refdef.vieworg, v); + z = DotProduct(v, vpn); + if (z < -clmodel->radius) + return; //furthest extent of bounding sphere is nearer than the near clip plane, and thus completely invisible + else if (z < 0) + lod = 0; //nearer than the camera, use the highest lod + else + { + //if the ent is in the middle of the screen, then the right edge of its sphere is at what percentage of the width of the screen...? + + //simplified Matrix4x4_CM_Transform4 + float coverage = (r_refdef.m_projection_std[5]*clmodel->radius + r_refdef.m_projection_std[ 9]*-z + r_refdef.m_projection_std[13]) / + (r_refdef.m_projection_std[7]*clmodel->radius + r_refdef.m_projection_std[11]*-z + r_refdef.m_projection_std[15]); + lod = 1-(coverage*r_lodscale.value); + lod = bound(0, lod, 1); //so lodbias is a little more reliable. + lod *= clmodel->maxlod; + lod += r_lodbias.value; + lod = max(0, lod); //never nearer than 0, the min value check wouldn't cope. + } + } + else + lod = 0; + for(surfnum=0; inf; inf=inf->nextsurf, surfnum++) { + if (lod < inf->mindist || (inf->maxdist && lod >= inf->maxdist)) + continue; + regshader = GL_ChooseSkin(inf, clmodel, surfnum, e, &skin); if (!regshader) continue; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index f08800b1e..d8fa5fb04 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -976,6 +976,21 @@ const char *Mod_FixName(const char *modname, const char *worldname) } return modname; } + +//Called when the given file was (re)written. +// +void Mod_FileWritten (const char *filename) +{ + int i; + model_t *mod; + for (i=0 , mod=mod_known ; ipublicname, filename) ) + { + if (mod->loadstate != MLS_NOTLOADED) + Mod_PurgeModel(mod, MP_RESET); + } +} + /* ================== Mod_FindName @@ -1262,6 +1277,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b) // // load the file // + mod->maxlod = 0; // set necessary engine flags for loading purposes if (!strcmp(mod->publicname, "progs/player.mdl")) mod->engineflags |= MDLF_PLAYER | MDLF_DOCRC; @@ -2293,6 +2309,7 @@ static void Mod_ShowEnt_f(void) static void Mod_SaveEntFile_f(void) { char fname[MAX_QPATH]; + char nname[MAX_OSPATH]; model_t *mod = NULL; char *n = Cmd_Argv(1); const char *ents; @@ -2333,6 +2350,8 @@ static void Mod_SaveEntFile_f(void) } COM_WriteFile(fname, FS_GAMEONLY, ents, strlen(ents)); + if (FS_NativePath(fname, FS_GAMEONLY, nname, sizeof(nname))) + Con_Printf("Wrote %s\n", nname); } /* diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 60348cb43..6201e8c8f 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -934,6 +934,7 @@ typedef struct model_s vec3_t mins, maxs; float radius; float clampscale; + float maxlod; // // solid volume for clipping diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 94a6df9db..42692cbf4 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -692,11 +692,10 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) gl_config.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil"); - if (GL_CheckExtension("GL_EXT_texture_filter_anisotropic")) + if ((!gl_config.gles && gl_config.glversion >= 4.6) || GL_CheckExtension("GL_EXT_texture_filter_anisotropic") || GL_CheckExtension("GL_ARB_texture_filter_anisotropic")) { qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_config.ext_texture_filter_anisotropic); - - Con_DPrintf("Anisotropic filter extension found (%dx max).\n",gl_config.ext_texture_filter_anisotropic); + Con_DPrintf("Anisotropic filtering supported (%dx max).\n",gl_config.ext_texture_filter_anisotropic); } if ((!gl_config.gles && gl_config.glversion >= 2) || GL_CheckExtension("GL_ARB_texture_non_power_of_two")) @@ -707,6 +706,12 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) if (!gl_config.gles && gl_config.glversion >= 3) { //GL_ARB_texture_non_power_of_two is supposed to be mandatory in gl2+ and thus checking for it is redundant and not forwards-compatible //geforcefx apparently software emulates it, so only activate it unconditionally on gl3+ hardware. + //gl2 drivers will likely still be explicitly advertising GL_ARB_texture_non_power_of_two so there's probably no great loss from requiring a higher version. + sh_config.texture_non_power_of_two = true; + sh_config.texture_non_power_of_two_pic = true; + } + else if (gl_config.gles && gl_config.glversion >= 3) + { //gles3 is meant to have full npot support (like gl2+ was meant to). sh_config.texture_non_power_of_two = true; sh_config.texture_non_power_of_two_pic = true; } diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index 7b3246d18..195aa626c 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -3220,15 +3220,13 @@ static Cursor CreateNullCursor(Display *display, Window root) Pixmap cursormask; XGCValues xgc; GC gc; - XColor dummycolour; + XColor dummycolour = {0}; Cursor cursor; cursormask = x11.pXCreatePixmap(display, root, 1, 1, 1/*depth*/); xgc.function = GXclear; gc = x11.pXCreateGC(display, cursormask, GCFunction, &xgc); x11.pXFillRectangle(display, cursormask, gc, 0, 0, 1, 1); - dummycolour.pixel = 0; - dummycolour.red = 0; dummycolour.flags = 04; cursor = x11.pXCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,&dummycolour, 0,0); diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index c271cc66b..c8852910e 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -77,7 +77,7 @@ void R_SetSky(const char *sky) tex.reflectcube = R_LoadHiResTexture(sky, "env:gfx/env", IF_LOADNOW|IF_CUBEMAP|IF_CLAMP); if (tex.reflectcube->width) { - forcedsky = R_RegisterShader(va("skybox_%s", sky), 0, "{\nsort sky\nprogram defaultskybox\n{\nmap \"$cube:$reflectcube\"\ntcgen skybox\n}\nsurfaceparm nodlight\nsurfaceparm sky\n}"); + forcedsky = R_RegisterShader(va("skybox_%s", sky), 0, "{\nsort sky\nprogram defaultskybox\n{\ndepthwrite\nmap \"$cube:$reflectcube\"\ntcgen skybox\n}\nsurfaceparm nodlight\nsurfaceparm sky\n}"); R_BuildDefaultTexnums(&tex, forcedsky, IF_WORLDTEX); return; } @@ -116,12 +116,20 @@ void R_DrawFastSky(batch_t *batch) BE_SubmitBatch(&b); } +//annoyingly sky does not always write depth values. +//this can allow entities to appear beyond it. +//this can include (massive) entities outside of the skyroom. +//so, we can only draw entities in skyrooms if: +//1) either the ents have robust pvs info and we can draw ONLY the ones actually inside the skyroom +//2) or if r_ignoreentpvs==1 we must mask depth and waste a whole load of batches drawing invisible ents in the sky +extern cvar_t r_ignoreentpvs; + void R_RenderScene (void); qboolean R_DrawSkyroom(shader_t *skyshader) { float vmat[16]; refdef_t oldrefdef; - extern cvar_t r_ignoreentpvs; //legacy value is 1... +// extern cvar_t r_ignoreentpvs; //legacy value is 1... extern cvar_t v_skyroom_orientation; if (r_viewcluster == -1) @@ -135,8 +143,8 @@ qboolean R_DrawSkyroom(shader_t *skyshader) oldrefdef = r_refdef; r_refdef.recurse+=1; - if (r_ignoreentpvs.ival) //if we're ignoring ent pvs then we're probably drawing lots of ents in the skybox that shouldn't be there - r_refdef.firstvisedict = cl_numvisedicts; +// if (r_ignoreentpvs.ival) //if we're ignoring ent pvs then we're probably drawing lots of ents in the skybox that shouldn't be there +// r_refdef.firstvisedict = cl_numvisedicts; r_refdef.externalview = true; //an out-of-body experience... r_refdef.skyroom_enabled = false; r_refdef.forcevis = false; @@ -187,6 +195,10 @@ qboolean R_DrawSkyroom(shader_t *skyshader) return true; } +//q3 mustn't mask sky (breaks q3map2's invisible skyportals), whereas q1 must (or its a cheat). halflife doesn't normally expect masking. +//we also MUST mask any sky inside skyrooms, or you'll see all the entities outside of the skyroom through the room's own sky (q3map2 skyportals are hopefully irrelevant in this case). +#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && !r_ignoreentpvs.ival)) + /* ================= GL_DrawSkyChain @@ -207,6 +219,13 @@ qboolean R_DrawSkyChain (batch_t *batch) { skyshader = forcedsky; + if (r_refdef.flags & RDF_SKIPSKY) + { + if (r_worldentity.model->fromgame != fg_quake3) + GL_SkyForceDepth(batch); + return true; + } + if (forcedsky->numpasses && !forcedsky->skydome) { //cubemap skies! //this is just a simple pass. we use glsl/texgen for any actual work @@ -225,7 +244,7 @@ qboolean R_DrawSkyChain (batch_t *batch) { if (r_refdef.flags & RDF_SKIPSKY) { - if (r_worldentity.model->fromgame != fg_quake3) + if (SKYMUSTBEMASKED) GL_SkyForceDepth(batch); return true; } @@ -290,7 +309,7 @@ qboolean R_DrawSkyChain (batch_t *batch) //See: The Edge Of Forever (motef, by sock) for an example of where this needs to be skipped. //See dm3 for an example of where the depth needs to be correct (OMG THERE'S PLAYERS IN MY SKYBOX! WALLHAXX!). //you can't please them all. - if (r_worldentity.model->fromgame != fg_quake3) + if (SKYMUSTBEMASKED) GL_SkyForceDepth(batch); return true; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 342cad471..f5e6be7f4 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -1410,7 +1410,11 @@ static const char *ED_ParseEdict (progfuncs_t *progfuncs, const char *data, edic // keynames with a leading underscore are used for utility comments, // and are immediately discarded by quake if (keyname[0] == '_') + { + if (externs->badfield) + externs->badfield(&progfuncs->funcs, (struct edict_s*)ent, keyname, qcc_token); continue; + } if (!strcmp(keyname, "angle")) //Quake anglehack - we've got to leave it in cos it doesn't work for quake otherwise, and this is a QuakeC lib! { diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index e97e0a3e6..12532223a 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -503,6 +503,20 @@ static void ASMCALL ThinkTimeOp (pubprogfuncs_t *prinst, edict_t *ed, float var) static int SV_ParticlePrecache_Add(const char *pname); static pbool PDECL SV_BadField(pubprogfuncs_t *inst, edict_t *foo, const char *keyname, const char *value) { + if (!strcmp(keyname, "traileffect")) + { + foo->xv->traileffectnum = SV_ParticlePrecache_Add(value); + return true; + } + if (!strcmp(keyname, "emiteffect")) + { + foo->xv->emiteffectnum = SV_ParticlePrecache_Add(value); + return true; + } + + if (*keyname == '_') + keyname++; + #ifdef HEXEN2 /*Worldspawn only fields...*/ if (NUM_FOR_EDICT(inst, foo) == 0) @@ -522,20 +536,18 @@ static pbool PDECL SV_BadField(pubprogfuncs_t *inst, edict_t *foo, const char *k } #endif - if (!strcmp(keyname, "traileffect")) - { - foo->xv->traileffectnum = SV_ParticlePrecache_Add(value); - return true; - } - if (!strcmp(keyname, "emiteffect")) - { - foo->xv->emiteffectnum = SV_ParticlePrecache_Add(value); - return true; - } - if (!strcmp(keyname, "sky") || !strcmp(keyname, "fog")) return true; //these things are handled in the client, so don't warn if they're used. + if (!strcmp(keyname, "skyroom")) + { + value = COM_Parse(value);sv.skyroom_pos[0] = atof(com_token); + value = COM_Parse(value);sv.skyroom_pos[1] = atof(com_token); + value = COM_Parse(value);sv.skyroom_pos[2] = atof(com_token); + sv.skyroom_pos_known = true; + return true; + } + //don't spam warnings about missing fields if we failed to load the progs. if (!svs.numprogs) return true; @@ -9817,6 +9829,8 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars return; } + VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove)); + if (pr_global_ptrs->clientcommandframe) pmove.sequence = *pr_global_ptrs->clientcommandframe; else diff --git a/engine/server/server.h b/engine/server/server.h index af3d87521..a6f0ff613 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -170,6 +170,9 @@ typedef struct qbyte h2cdtrack; #endif + vec3_t skyroom_pos; //parsed from world._skyroom + qboolean skyroom_pos_known; + int allocated_client_slots; //number of slots available. (used mostly to stop single player saved games cacking up) int spawned_client_slots; //number of PLAYER slots which are active (ie: putclientinserver was called) int spawned_observer_slots; diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 358f93123..afb5c637f 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -3868,10 +3868,15 @@ void SV_AddCameraEntity(pvscamera_t *cameras, edict_t *ent, vec3_t viewofs) return; //don't add the same ent multiple times (.view2 or portals that can see themselves through other portals). } - if (viewofs) - VectorAdd (ent->v->origin, viewofs, org); + if (ent) + { + if (viewofs) + VectorAdd (ent->v->origin, viewofs, org); + else + VectorCopy (ent->v->origin, org); + } else - VectorCopy (ent->v->origin, org); + VectorCopy (viewofs, org); sv.world.worldmodel->funcs.ClusterForPoint(sv.world.worldmodel, org, &area); for (i = 1; ; i++) @@ -3912,6 +3917,10 @@ void SV_Snapshot_SetupPVS(client_t *client, pvscamera_t *camera) if (client->edict->xv->view2) SV_AddCameraEntity(camera, PROG_TO_EDICT(svprogfuncs, client->edict->xv->view2), NULL); } + + //hack for skyrooms, open up the pvs. + if (sv.skyroom_pos_known) + SV_AddCameraEntity(camera, NULL, sv.skyroom_pos); } void SV_Snapshot_Clear(packet_entities_t *pack) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 1f867fa26..9318b58e0 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2796,13 +2796,13 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info) if (newcl->zquake_extensions & (Z_EXT_PF_SOLID|Z_EXT_PF_ONGROUND)) { if (newcl->fteprotocolextensions & PEXT_HULLSIZE) - Con_TPrintf("%s: ignoring ezquake hullsize extension (conflicts with z_ext_pf_onground).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); + Con_TPrintf("%s: ezquake - ignoring hullsize extension (conflicts with z_ext_pf_onground).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); if (newcl->fteprotocolextensions & PEXT_SCALE) - Con_TPrintf("%s: ignoring ezquake scale extension (conflicts with z_ext_pf_solid).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); + Con_TPrintf("%s: ezquake - ignoring scale extension (conflicts with z_ext_pf_solid).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); if (newcl->fteprotocolextensions & PEXT_FATNESS) - Con_TPrintf("%s: ignoring ezquake fatness extension (conflicts with z_ext_pf_solid).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); + Con_TPrintf("%s: ezquake - ignoring fatness extension (conflicts with z_ext_pf_solid).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); if (newcl->fteprotocolextensions & PEXT_TRANS) - Con_TPrintf("%s: ignoring ezquake transparency extension (buggy on players, conflicts with z_ext_pf_solid).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); + Con_TPrintf("%s: ezquake - ignoring transparency extension (buggy on players, conflicts with z_ext_pf_solid).\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &info->adr)); newcl->fteprotocolextensions &= ~(PEXT_HULLSIZE|PEXT_TRANS|PEXT_SCALE|PEXT_FATNESS); } } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index ba4a6bff2..419badaca 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -7052,6 +7052,8 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) return; } + VALGRIND_MAKE_MEM_UNDEFINED(&pmove, sizeof(pmove)); + host_frametime = ucmd->msec * 0.001; host_frametime *= sv.gamespeed; if (host_frametime > 0.1) diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index d0c19c255..150d2db22 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -2059,12 +2059,15 @@ void VK_Set2D(void) static void VK_Shutdown_PostProc(void) { unsigned int i; - for (i = 0; i < countof(postproc); i++) - VKBE_RT_Gen(&postproc[i], 0, 0, true, RT_IMAGEFLAGS); + if (vk.device) + { + for (i = 0; i < countof(postproc); i++) + VKBE_RT_Gen(&postproc[i], 0, 0, true, RT_IMAGEFLAGS); + VK_R_BloomShutdown(); + } vk.scenepp_waterwarp = NULL; vk.scenepp_antialias = NULL; - VK_R_BloomShutdown(); } static void VK_Init_PostProc(void) { diff --git a/plugins/models/gltf.c b/plugins/models/gltf.c index 86b6e8774..2f736bcc9 100644 --- a/plugins/models/gltf.c +++ b/plugins/models/gltf.c @@ -1985,9 +1985,10 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize, break; } if (j==countof(extensions) || !extensions[j].supported) + { Con_Printf(CON_ERROR "%s: Required gltf2 extension \"%s\" not supported\n", mod->name, extname); - - goto abort; + goto abort; + } } for(n = JSON_FindIndexedChild(gltf.r, "extensionsUsed", 0); n; n = n->sibling)