diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 6bc6afb5d..385175fb5 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -7059,6 +7059,7 @@ double Host_Frame (double time) if (r_blockvidrestart) { + Cbuf_Execute(); if (waitingformanifest) { COM_MainThreadWork(); diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 560257fd5..80b008ad1 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -79,6 +79,7 @@ cvar_t pkg_autoupdate = CVARFD("pkg_autoupdate", "-1", CVAR_NOTFROMSERVER|CVAR_N #define DPF_SIGNATUREACCEPTED (1u<<18) //signature is good (required for dll/so/exe files) #define DPF_SIGNATUREUNKNOWN (1u<<19) //signature is unknown #define DPF_HIDEUNLESSPRESENT (1u<<20) //hidden in the ui, unless present. +#define DPF_PENDING (1u<<21) //started a download (required due to threading sillyness). #define DPF_MARKED (DPF_USERMARKED|DPF_AUTOMARKED) //flags that will enable it #define DPF_ALLMARKED (DPF_USERMARKED|DPF_AUTOMARKED|DPF_MANIMARKED) //flags that will download it without necessarily enabling it. @@ -181,7 +182,7 @@ typedef struct package_s { } *deps; #ifdef WEBCLIENT - struct dl_download *download; + struct dl_download *curdownload; unsigned int trymirrors; #endif @@ -290,10 +291,10 @@ static void PM_FreePackage(package_t *p) } #ifdef WEBCLIENT - if (p->download) + if (p->curdownload) { //if its currently downloading, cancel it. - DL_Close(p->download); - p->download = NULL; + DL_Close(p->curdownload); + p->curdownload = NULL; } for (i = 0; i < countof(p->mirror); i++) @@ -864,7 +865,7 @@ static package_t *PM_InsertPackage(package_t *p) } else { - if ((p->flags & DPF_GUESSED) && (prev->flags & DPF_PRESENT)) + if (((p->flags & DPF_GUESSED) && (prev->flags & (DPF_USERMARKED|DPF_MANIMARKED|DPF_PENDING))) || prev->curdownload) { //the new one was also guessed. just return the existing package instead. prev->flags |= p->flags&(DPF_PRESENT|DPF_ALLMARKED|DPF_ENABLED); PM_FreePackage(p); @@ -2555,11 +2556,12 @@ static void PM_UnmarkPackage(package_t *package, unsigned int markflag) #ifdef WEBCLIENT //Is this safe? package->trymirrors = 0; //if its enqueued, cancel that quickly... - if (package->download) + if (package->curdownload) { //if its currently downloading, cancel it. - DL_Close(package->download); - package->download = NULL; + DL_Close(package->curdownload); + package->curdownload = NULL; } + package->flags &= ~DPF_PENDING; #endif //remove stuff that depends on us @@ -3852,11 +3854,12 @@ static void PM_Download_Got(int iarg, void *data) if (p) { - p->download = NULL; + p->flags &= ~DPF_PENDING; + p->curdownload = NULL; //just in case. if (!successful) { - Con_Printf("Couldn't download %s (from %s)\n", p->name, info->url); + Con_Printf(CON_ERROR"Couldn't download %s (from %s)\n", p->name, info->url); FS_Remove (tempname, temproot); Z_Free(tempname); PM_StartADownload(); @@ -3924,7 +3927,7 @@ static void PM_Download_Got(int iarg, void *data) if (success) for (p2 = availablepackages; p2; p2=p2->next) { - if (p2->download || //only if they've not already started downloading separately... + if ((p2->flags&DPF_PENDING) || //only if they've not already started downloading separately... !p2->trymirrors //ignore ones that are not pending. ) continue; @@ -3959,10 +3962,10 @@ static void PM_Download_Got(int iarg, void *data) return; } } - Con_Printf("menu_download: %s has no filename info\n", p->name); + Con_Printf(CON_ERROR"PM_Download_Got: %s has no filename info\n", p->name); } else - Con_Printf("menu_download: Can't figure out where %s came from (url: %s)\n", info->localname, info->url); + Con_Printf(CON_ERROR"PM_Download_Got: Can't figure out where \"%s\"(%s) came from (url: %s)\n", info->localname, tempname, info->url); FS_Remove (tempname, temproot); Z_Free(tempname); @@ -3983,9 +3986,9 @@ static void PM_Download_PreliminaryGot(struct dl_download *dl) for (info.p = availablepackages; info.p ; info.p=info.p->next) { - if (info.p->download == dl) + if (info.p->curdownload == dl) { - info.p->download = NULL; + info.p->curdownload = NULL; //have to clear it here, because this pointer will no longer be valid after (which could result in segfaults) break; } } @@ -4294,7 +4297,7 @@ static unsigned int PM_DownloadingCount(void) unsigned int count = 0; for (p = availablepackages; p ; p=p->next) { - if (p->download) + if (p->flags&DPF_PENDING) count++; } return count; @@ -4313,7 +4316,7 @@ static void PM_StartADownload(void) for (p = availablepackages; p && simultaneous > PM_DownloadingCount(); p=p->next) { - if (p->download) + if (p->curdownload) downloading = true; else if (p->trymirrors) { //flagged for a (re?)download @@ -4375,7 +4378,7 @@ static void PM_StartADownload(void) { //don't allow multiple of these at a time... so we can download a single file and extract two packages from it. package_t *p2; for (p2 = availablepackages; p2; p2=p2->next) - if (p2->download) //only skip if the other one is already downloading. + if (p2->flags&DPF_PENDING) //only skip if the other one is already downloading. if (PM_DownloadSharesSource(p2, p)) break; if (p2) @@ -4427,8 +4430,8 @@ static void PM_StartADownload(void) if (tmpfile) { - p->download = HTTP_CL_Get(mirror, NULL, PM_Download_PreliminaryGot); - if (!p->download) + p->curdownload = HTTP_CL_Get(mirror, NULL, PM_Download_PreliminaryGot); + if (!p->curdownload) Con_Printf("Unable to download %s (%s)\n", p->name, mirror); } else @@ -4437,18 +4440,20 @@ static void PM_StartADownload(void) Con_Printf("Unable to write %s. Fix permissions before trying to download %s\n", FS_DisplayPath(temp, temproot, displaypath, sizeof(displaypath))?displaypath:p->name, p->name); p->trymirrors = 0; //don't bother trying other mirrors if we can't write the file or understand its type. } - if (p->download) + if (p->curdownload) { Con_Printf("Downloading %s\n", p->name); - p->download->file = tmpfile; - p->download->user_ctx = temp; - p->download->user_num = temproot; + p->flags |= DPF_PENDING; + p->curdownload->file = tmpfile; + p->curdownload->user_ctx = temp; + p->curdownload->user_num = temproot; - DL_CreateThread(p->download, NULL, NULL); + DL_CreateThread(p->curdownload, NULL, NULL); downloading = true; } else { + p->flags &= ~DPF_PENDING; p->flags &= ~DPF_MARKED; //can't do it. if (tmpfile) VFS_CLOSE(tmpfile); @@ -4536,7 +4541,7 @@ void PM_ApplyChanges(void) { p = *link; #ifdef WEBCLIENT - if (p->download) + if (p->flags&DPF_PENDING) ; //erk, dude, don't do two! else #endif @@ -4665,7 +4670,7 @@ void PM_ApplyChanges(void) //and flag any new/updated ones for a download for (p = availablepackages; p ; p=p->next) { - if (!p->download) + if (!(p->flags & DPF_PENDING)) if (((p->flags & DPF_MANIMARKED) && !(p->flags&DPF_PRESENT)) || //satisfying a manifest merely requires that it be present, not actually enabled. ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED))) //actually enabled stuff requires actual enablement { @@ -4985,13 +4990,15 @@ static void PM_Pkg_ListPackage(package_t *p, const char **category) else Con_Printf(" ^&0EUnsigned"); - if (p->download) + if (p->curdownload) { - if (p->download->totalsize==0) - Con_Printf(" Downloading %s/unknown", FS_AbbreviateSize(quoted,sizeof(quoted), p->download->completed)); + if (p->curdownload->totalsize==0) + Con_Printf(" Downloading %s/unknown", FS_AbbreviateSize(quoted,sizeof(quoted), p->curdownload->completed)); else - Con_Printf(" Downloading %i%% (%s total)", (int)(100*(double)p->download->completed/(double)p->download->totalsize), FS_AbbreviateSize(quoted,sizeof(quoted), p->download->totalsize)); + Con_Printf(" Downloading %i%% (%s total)", (int)(100*(double)p->curdownload->completed/(double)p->curdownload->totalsize), FS_AbbreviateSize(quoted,sizeof(quoted), p->curdownload->totalsize)); } + else if (p->flags & DPF_PENDING) + Con_Printf(" Finalising..."); else if (p->trymirrors) Con_Printf(" Pending..."); @@ -5691,13 +5698,15 @@ void QCBUILTIN PF_cl_getpackagemanagerinfo(pubprogfuncs_t *prinst, struct global else if (p->flags & DPF_PRESENT) RETURN_SSTRING("present"); //its there (but ignored) #ifdef WEBCLIENT - else if (p->download) + else if (p->curdownload) { //we're downloading it - if (p->download->qdownload.sizeunknown&&cls.download->size==0 && p->filesize>0 && p->extract==EXTRACT_COPY) - RETURN_TSTRING(va("%i%%", (int)((100*p->download->qdownload.completedbytes)/p->filesize))); //server didn't report total size, but we know how big its meant to be. + if (p->curdownload->qdownload.sizeunknown&&cls.download->size==0 && p->filesize>0 && p->extract==EXTRACT_COPY) + RETURN_TSTRING(va("%i%%", (int)((100*p->curdownload->qdownload.completedbytes)/p->filesize))); //server didn't report total size, but we know how big its meant to be. else - RETURN_TSTRING(va("%i%%", (int)p->download->qdownload.percent)); //we're downloading it. + RETURN_TSTRING(va("%i%%", (int)p->curdownload->qdownload.percent)); //we're downloading it. } + else if (p->flags & DPF_PENDING) + RETURN_TSTRING("100%"); //finalising shouldn't stay in this state long... else if (p->trymirrors) RETURN_SSTRING("pending"); //its queued. #endif @@ -5836,9 +5845,9 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m) } else #ifdef WEBCLIENT - if (p->download) - Draw_FunStringWidth (x, y, va("%i%%", (int)p->download->qdownload.percent), 48, 2, false); - else if (p->trymirrors) + if (p->curdownload) + Draw_FunStringWidth (x, y, va("%i%%", (int)p->curdownload->qdownload.percent), 48, 2, false); + else if (p->trymirrors || (p->flags&DPF_PENDING)) Draw_FunStringWidth (x, y, "PND", 48, 2, false); else #endif @@ -6582,7 +6591,7 @@ static void MD_Download_UpdateStatus(struct emenu_s *m) totalpackages++; #ifdef WEBCLIENT - if (p->download || p->trymirrors) + if ((p->flags&DPF_PENDING) || p->trymirrors) downloads++; //downloading or pending #endif if (p->flags & DPF_MARKED) diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 5d7cc3079..44e72bae2 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -2711,7 +2711,9 @@ void M_Menu_Main_f (void) y = 36; mainm->selecteditem = (menuoption_t *) //skip menu_single if we don't seem to have any content. +#ifdef CL_MASTER MC_AddConsoleCommandQBigFont (mainm, 72, y, localtext("Join server"), "menu_servers\n"); y += 20; +#endif MC_AddConsoleCommandQBigFont (mainm, 72, y, localtext("^bOptions"), "menu_options\n"); y += 20; y = M_Main_AddExtraOptions(mainm, y); MC_AddConsoleCommandQBigFont (mainm, 72, y, localtext("Quit"), "menu_quit\n"); y += 20; diff --git a/engine/common/net_ssl_gnutls.c b/engine/common/net_ssl_gnutls.c index 95ff8d72c..82bca79ba 100644 --- a/engine/common/net_ssl_gnutls.c +++ b/engine/common/net_ssl_gnutls.c @@ -1220,7 +1220,12 @@ static qboolean SSL_InitConnection(gnutlsfile_t *newf, qboolean isserver, qboole qgnutls_credentials_set (newf->session, GNUTLS_CRD_ANON, anoncred[isserver]); #else #ifdef HAVE_DTLS + +#if defined(MASTERONLY) + qgnutls_certificate_server_set_request(newf->session, GNUTLS_CERT_IGNORE); //don't request a cert. masters don't really need it and chrome bugs out if you connect to a websocket server that offers for the client to provide one. chrome users will just have to stick to webrtc. +#else qgnutls_certificate_server_set_request(newf->session, GNUTLS_CERT_REQUEST); //request a cert, we'll use it for fingerprints. +#endif if (datagram && !isserver) { //do psk as needed. we can still do the cert stuff if the server isn't doing psk. diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 51cde6ef1..c196768fd 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -84,9 +84,9 @@ int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float size_t Fragment_ClipPlaneToBrush(vecV_t *points, size_t maxpoints, void *planes, size_t planestride, size_t numplanes, vec4_t face) { int p, a; - vec4_t verts[MAXFRAGMENTVERTS]; - vec4_t verts2[MAXFRAGMENTVERTS]; - vec4_t *cverts; + vecV_t verts[MAXFRAGMENTVERTS]; + vecV_t verts2[MAXFRAGMENTVERTS]; + vecV_t *cverts; int flip; // vec3_t d1, d2, n; size_t numverts; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index a71edc063..cea624ea3 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -6302,7 +6302,7 @@ static brushes_t *Terr_Brush_Insert(model_t *model, heightmap_t *hm, brushes_t * } //generate points now (so we know the correct mins+maxs for the brush, and whether the plane is relevent) - numpoints = Fragment_ClipPlaneToBrush(facepoints, sizeof(facepoints)/sizeof(facepoints[0]), brush->planes, sizeof(*brush->planes), brush->numplanes, brush->planes[iface]); + numpoints = Fragment_ClipPlaneToBrush(facepoints, countof(facepoints), brush->planes, sizeof(*brush->planes), brush->numplanes, brush->planes[iface]); if (!numpoints) { Con_DPrintf("redundant face\n"); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 67e2add18..023088440 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -1018,6 +1018,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, flocation_t loc; time_t filetime; char *mod = NULL; + Q_snprintfz (sv.modelname, sizeof(sv.modelname), exts[1], server); // `map foo.map` can bypass earlier checks, so don't get too screwed up by that. if (bestdepth == FDEPTH_MISSING) { //not an exact name, scan the maps subdir. for (i = 0; exts[i]; i++) diff --git a/engine/web/ftejslib.js b/engine/web/ftejslib.js index 564ebf1d8..09fd7d3f4 100644 --- a/engine/web/ftejslib.js +++ b/engine/web/ftejslib.js @@ -435,25 +435,29 @@ mergeInto(LibraryManager.library, { //with events, we can do unplug stuff properly. //otherwise hot unplug might be buggy. - var gamepads; + let gamepads; // if (FTEH.gamepads !== undefined) // gamepads = FTEH.gamepads; // else + try + { gamepads = navigator.getGamepads ? navigator.getGamepads() : []; + } + catch(e){} if (gamepads !== undefined) { - for (var i = 0; i < gamepads.length; i+=1) + for (let i = 0; i < gamepads.length; i+=1) { const gp = gamepads[i]; if (gp === undefined) continue; if (gp == null) continue; //xbox controllers tend to have 4 and exactly 4. on the plus side indexes won't change. - for (var j = 0; j < gp.buttons.length; j+=1) + for (let j = 0; j < gp.buttons.length; j+=1) { - var b = gp.buttons[j]; - var p; + const b = gp.buttons[j]; + let p; if (typeof(b) == "object") p = b.pressed; //.value is a fractional thing. oh well. else @@ -465,7 +469,7 @@ mergeInto(LibraryManager.library, {{{makeDynCall('viiii','FTEC.evcb.jbutton')}}}(gp.index, j, p, gp.mapping=="standard"); } } - for (var j = 0; j < gp.axes.length; j+=1) + for (let j = 0; j < gp.axes.length; j+=1) {{{makeDynCall('viifi','FTEC.evcb.jaxis')}}}(gp.index, j, gp.axes[j], gp.mapping=="standard"); } } @@ -473,12 +477,12 @@ mergeInto(LibraryManager.library, if (FTEC.xrsession != null && FTEC.xrframe != null && FTEC.referenceSpace != null) { //try and figure out the head angles according to where we're told the eyes are - var count = 0; - var org={x:0,y:0,z:0}, quat={x:0,y:0,z:0,w:0}; + let count = 0; + let org={x:0,y:0,z:0}, quat={x:0,y:0,z:0,w:0}; const pose = FTEC.xrframe.getViewerPose(FTEC.referenceSpace); if (pose) { - for (var view of pose.views) + for (let view of pose.views) { org.x += view.transform.position.x; org.y += view.transform.position.y; @@ -511,7 +515,7 @@ mergeInto(LibraryManager.library, continue; //webxr doesn't really do indexes, so make em up from hands.. - var idx; + let idx; if (is.handedness == "right") //is.targetRayMode=="tracked-pointer" idx = -1; else if (is.handedness == "left") //is.targetRayMode=="tracked-pointer" @@ -540,10 +544,10 @@ mergeInto(LibraryManager.library, if (gp.mapping != "xr-standard") continue; - for (var j = 0; j < gp.buttons.length; j+=1) + for (let j = 0; j < gp.buttons.length; j+=1) { - var b = gp.buttons[j]; - var p; + const b = gp.buttons[j]; + let p; p = b.pressed; //.value is a fractional thing. oh well. if (b.lastframe != p) @@ -553,7 +557,7 @@ console.log("jbutton dev:" + idx + " btn:"+j+" dn:"+p+" mapping:"+gp.mapping); {{{makeDynCall('viiii','FTEC.evcb.jbutton')}}}(idx, j, p, gp.mapping=="standard"); } } - for (var j = 0; j < gp.axes.length; j+=1) + for (let j = 0; j < gp.axes.length; j+=1) { console.log("jaxis dev:" + idx + " axis:"+j+" val:"+gp.axes[j]+" mapping:"+gp.mapping); {{{makeDynCall('viifi','FTEC.evcb.jaxis')}}}(idx, j, gp.axes[j], gp.mapping=="standard"); diff --git a/engine/web/sys_web.c b/engine/web/sys_web.c index 8e5ae19e3..14aff7320 100644 --- a/engine/web/sys_web.c +++ b/engine/web/sys_web.c @@ -352,10 +352,13 @@ static void Sys_Register_File_Associations_f(void) for (s = schemes; (s=COM_ParseOut(s,scheme,sizeof(scheme)));) { EM_ASM({ + try{ + if (navigator.registerProtocolHandler) navigator.registerProtocolHandler( UTF8ToString($0), document.location.origin+document.location.pathname+"?%s"+document.location.hash, UTF8ToString($1)); + } catch(e){} }, va("%s%s", strncmp(scheme,"web+",4)?"web+":"", scheme), fs_manifest->formalname?fs_manifest->formalname:fs_manifest->installation); } }