From 3e2bffdddcdd5508c6dd43a215d3dc75276cd8d6 Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 11 Dec 2014 16:26:26 +0000 Subject: [PATCH] preliminary first real attempt at letting the csqc draw loading screens. added some serverkey fields to query load progress. misc fixes for the webgl port. silence some warnings reported by llvm. hide windows cursor in webgl port. use software cursor for now. will need to use url+dataurl at some point. ignore f11 key, because it makes firefox a bit unusable in certain situations. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4801 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 172 +++++++++++++++++++------------------ engine/client/cl_screen.c | 4 + engine/client/client.h | 2 + engine/client/image.c | 4 + engine/client/m_items.c | 5 +- engine/client/m_single.c | 5 +- engine/client/menu.c | 2 + engine/client/p_script.c | 14 ++- engine/client/pr_csqc.c | 49 ++++++++++- engine/client/pr_skelobj.c | 2 +- engine/common/bspfile.h | 10 ++- engine/common/gl_q2bsp.c | 20 +++-- engine/common/pr_bgcmd.c | 8 +- engine/gl/gl_shadow.c | 4 - engine/qclib/initlib.c | 1 + engine/server/pr_cmds.c | 10 +++ engine/server/sv_init.c | 4 +- engine/web/ftejslib.h | 3 +- engine/web/ftejslib.js | 23 ++++- engine/web/gl_vidweb.c | 10 ++- engine/web/sys_web.c | 18 +++- 21 files changed, 247 insertions(+), 123 deletions(-) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 5b2a6622d..2ccaa33dd 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1535,18 +1535,6 @@ void CL_ReRecord_f (void) CL_BeginServerReconnect(); } -#ifdef WEBCLIENT -void CL_PlayDownloadedDemo(char *name, qboolean success) -{ - if (success == false) - Con_Printf("Failed to download %s\n", name); - else - { - Cbuf_AddText(va("playdemo %s\n", name), RESTRICT_LOCAL); - } -} -#endif - /* ==================== CL_PlayDemo_f @@ -1554,6 +1542,7 @@ CL_PlayDemo_f play [demoname] ==================== */ +void CL_PlayDownloadedDemo(struct dl_download *dl); void CL_PlayDemo_f (void) { char *demoname; @@ -1567,10 +1556,7 @@ void CL_PlayDemo_f (void) cls.state = ca_disconnected; #ifdef WEBCLIENT -#ifdef warningmsg -#pragma warningmsg("playdemo http://blah is broken right now") -#endif -#if 0 +#if 1 if (!strncmp(Cmd_Argv(1), "ftp://", 6) || !strncmp(Cmd_Argv(1), "http://", 7)) { if (Cmd_ExecLevel == RESTRICT_LOCAL) @@ -1682,10 +1668,92 @@ vfsfile_t *CL_OpenFileInZipOrSys(char *name) else return CL_OpenFileInPackage(NULL, name); } +//tries to determine the demo type +void CL_PlayDemoFile(vfsfile_t *f, char *demoname) +{ + qofs_t start; + + if (!VFS_GETLEN (f)) + { + VFS_CLOSE(f); + Con_Printf ("demo \"%s\" is empty.\n", demoname); + return; + } + + //figure out where we started + start = VFS_TELL(f); + +#ifdef Q2CLIENT + { + int len; + char type; + int protocol; + //check if its a quake2 demo. + VFS_READ(f, &len, sizeof(len)); + VFS_READ(f, &type, sizeof(type)); + VFS_READ(f, &protocol, sizeof(protocol)); + VFS_SEEK(f, start); + if (len > 5 && type == svcq2_serverdata && protocol == PROTOCOL_VERSION_Q2) + { + CL_PlayDemoStream(f, NULL, demoname, DPB_QUAKE2, 0); + return; + } + } +#endif + +#ifdef NQPROT + { + int ft = 0, neg = false; + char chr; + //not quake2, check if its NQ + //work out if the first line is a int for the track number. + while ((VFS_READ(f, &chr, 1)==1) && (chr != '\n')) + { + if (chr == ' ') + ; + else if (chr == '-') + neg = true; + else if (chr < '0' || chr > '9') + break; + else + ft = ft * 10 + ((int)chr - '0'); + } + if (neg) + ft *= -1; + if (chr == '\n') + { + CL_PlayDemoStream(f, NULL, demoname, DPB_NETQUAKE, 0); + return; + } + VFS_SEEK(f, start); + } +#endif + + //its not NQ then. must be QuakeWorld, either .qwd or .mvd + //could also be .qwz or .dmz or whatever that nq extension is. we don't support either. + + //mvd and qwd have no identifying markers, other than the extension. + if (!Q_strcasecmp(demoname + strlen(demoname) - 3, "mvd") || + !Q_strcasecmp(demoname + strlen(demoname) - 6, "mvd.gz")) + CL_PlayDemoStream(f, NULL, demoname, DPB_MVD, 0); + else + CL_PlayDemoStream(f, NULL, demoname, DPB_QUAKEWORLD, 0); +} +#ifdef WEBCLIENT +void CL_PlayDownloadedDemo(struct dl_download *dl) +{ + if (dl->status != DL_FINISHED || !dl->file) + Con_Printf("Failed to download %s\n", dl->url); + else + { + CL_PlayDemoFile(dl->file, dl->url); + dl->file = NULL; + } +} +#endif void CL_PlayDemo(char *demoname) { char name[256]; - qofs_t start; vfsfile_t *f; // @@ -1720,71 +1788,7 @@ void CL_PlayDemo(char *demoname) } Q_strncpyz (lastdemoname, demoname, sizeof(lastdemoname)); - if (!VFS_GETLEN (f)) - { - VFS_CLOSE(f); - Con_Printf ("demo \"%s\" is empty.\n", demoname); - return; - } - - //figure out where we started - start = VFS_TELL(f); - -#ifdef Q2CLIENT - { - int len; - char type; - int protocol; - //check if its a quake2 demo. - VFS_READ(f, &len, sizeof(len)); - VFS_READ(f, &type, sizeof(type)); - VFS_READ(f, &protocol, sizeof(protocol)); - VFS_SEEK(f, start); - if (len > 5 && type == svcq2_serverdata && protocol == PROTOCOL_VERSION_Q2) - { - CL_PlayDemoStream(f, NULL, name, DPB_QUAKE2, 0); - return; - } - } -#endif - -#ifdef NQPROT - { - int ft = 0, neg = false; - char chr; - //not quake2, check if its NQ - //work out if the first line is a int for the track number. - while ((VFS_READ(f, &chr, 1)==1) && (chr != '\n')) - { - if (chr == ' ') - ; - else if (chr == '-') - neg = true; - else if (chr < '0' || chr > '9') - break; - else - ft = ft * 10 + ((int)chr - '0'); - } - if (neg) - ft *= -1; - if (chr == '\n') - { - CL_PlayDemoStream(f, NULL, name, DPB_NETQUAKE, 0); - return; - } - VFS_SEEK(f, start); - } -#endif - - //its not NQ then. must be QuakeWorld, either .qwd or .mvd - //could also be .qwz or .dmz or whatever that nq extension is. we don't support either. - - //mvd and qwd have no identifying markers, other than the extension. - if (!Q_strcasecmp(name + strlen(name) - 3, "mvd") || - !Q_strcasecmp(name + strlen(name) - 6, "mvd.gz")) - CL_PlayDemoStream(f, NULL, name, DPB_MVD, 0); - else - CL_PlayDemoStream(f, NULL, name, DPB_QUAKEWORLD, 0); + CL_PlayDemoFile(f, name); } /*used with qtv*/ @@ -1914,7 +1918,7 @@ void CL_QTVPoll (void) colon = ""; if (!strcmp(s, "PERROR")) - { //printable error + { //permanent printable error Con_Printf("QTV Error:\n%s\n", colon); } else if (!strcmp(s, "PRINT")) @@ -1922,7 +1926,7 @@ void CL_QTVPoll (void) Con_Printf("QTV:\n%s\n", colon); } else if (!strcmp(s, "TERROR")) - { //printable error + { //temporary printable error Con_Printf("QTV Error:\n%s\n", colon); } else if (!strcmp(s, "ADEMO")) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index f17b12906..085524291 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1543,6 +1543,10 @@ void SCR_DrawLoading (qboolean opaque) char *s; int qdepth; int h2depth; + + if (CSQC_UseGamecodeLoadingScreen()) + return; + //int mtype = M_GameType(); //unused variable y = vid.height/2; diff --git a/engine/client/client.h b/engine/client/client.h index 6b01888bb..3457d94c0 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1213,6 +1213,7 @@ qboolean CSQC_ConsoleLink(char *text, char *info); void CSQC_RegisterCvarsAndThings(void); qboolean CSQC_SetupToRenderPortal(int entnum); qboolean CSQC_DrawView(void); +qboolean CSQC_UseGamecodeLoadingScreen(void); void CSQC_Shutdown(void); qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend); qboolean CSQC_LoadResource(char *resname, char *restype); @@ -1241,6 +1242,7 @@ void CSQC_CvarChanged(cvar_t *var); #else #define CSQC_UnconnectedOkay(inprinciple) false #define CSQC_UnconnectedInit() false +#define CSQC_UseGamecodeLoadingScreen() false #endif // diff --git a/engine/client/image.c b/engine/client/image.c index f03542ab0..d2d365bd7 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -3569,6 +3569,10 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag case PTI_BGRA8: mips->encoding = PTI_RGBX8; break; + case PTI_RGBA16F: + case PTI_RGBA32F: + case PTI_ARGB4444: + case PTI_ARGB1555: case PTI_RGBA4444: case PTI_RGBA5551: break; //erk diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 3ac1bfa31..142c8670e 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -124,10 +124,11 @@ void Draw_Hexen2BigFontString(int x, int y, const char *text) { unsigned int w = ((unsigned int*)file)[0]; unsigned int h = ((unsigned int*)file)[1]; - p->defaulttextures.base = R_LoadReplacementTexture("gfx/menu/bigfont.lmp", NULL, IF_NOPCX|IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP, (qbyte*)file+8, w, h, TF_H2_TRANS8_0); + if (8+w*h==fsize) + p->defaulttextures.base = R_LoadReplacementTexture("gfx/menu/bigfont.lmp", NULL, IF_NOPCX|IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP, (qbyte*)file+8, w, h, TF_H2_TRANS8_0); FS_FreeFile(file); //got image data } - else + if (!p->defaulttextures.base) p->defaulttextures.base = R_LoadHiResTexture("gfx/menu/bigfont.lmp", NULL, IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP); } diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 9c727b94e..693dc2b21 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -714,7 +714,10 @@ static void ShowDemoMenu (menu_t *menu, const char *path) } if (info->fsroot == FS_SYSTEM) { - Q_snprintfz(match, sizeof(match), *info->path?"%s*":"/*", info->path); + if (info->path) + Q_snprintfz(match, sizeof(match), "%s*", info->path); + else + Q_snprintfz(match, sizeof(match), "/*"); Sys_EnumerateFiles("", match, DemoAddItem, info, NULL); } else diff --git a/engine/client/menu.c b/engine/client/menu.c index c25b1bd3f..12f03b0e0 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -1334,6 +1334,7 @@ void M_Draw (int uimenu) switch (m_state) { + default: case m_none: break; @@ -1371,6 +1372,7 @@ void M_Keydown (int key, int unicode) { switch (m_state) { + default: case m_none: Key_Dest_Remove(kdm_menu); return; diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 76b7ad62f..ecbb5a43b 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -2023,9 +2023,19 @@ qboolean PScript_Query(int typenum, int body, char *outstr, int outstrlen) Q_strncatz(outstr, va("spawnorg %g %g\n", ptype->areaspread, ptype->areaspreadvert), outstrlen); if (ptype->veladd || ptype->randomveladd) - Q_strncatz(outstr, va(ptype->randomveladd?"veladd %g %g\n":"veladd %g\n", ptype->veladd, ptype->veladd+ptype->randomveladd), outstrlen); + { + if (ptype->randomveladd) + Q_strncatz(outstr, va("veladd %g %g\n", ptype->veladd, ptype->veladd+ptype->randomveladd), outstrlen); + else + Q_strncatz(outstr, va("veladd %g\n", ptype->veladd), outstrlen); + } if (ptype->orgadd || ptype->randomorgadd) - Q_strncatz(outstr, va(ptype->randomorgadd?"orgadd %g %g\n":"orgadd %g\n", ptype->orgadd, ptype->orgadd+ptype->randomorgadd), outstrlen); + { + if (ptype->randomorgadd) + Q_strncatz(outstr, va("orgadd %g %g\n", ptype->orgadd, ptype->orgadd+ptype->randomorgadd), outstrlen); + else + Q_strncatz(outstr, va("orgadd %g\n", ptype->orgadd), outstrlen); + } if (ptype->randomvel || ptype->randomvelvert || ptype->randomvelvertbias) Q_strncatz(outstr, va("randomvel %g %g %g\n", ptype->randomvel, ptype->randomvelvertbias - ptype->randomvelvert, ptype->randomvelvertbias + ptype->randomvelvert), outstrlen); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index a26dd2941..0a8d947a6 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -101,7 +101,8 @@ extern sfx_t *cl_sfx_r_exp3; globalfunction(init_function, "CSQC_Init"); \ globalfunction(worldloaded, "CSQC_WorldLoaded"); \ globalfunction(shutdown_function, "CSQC_Shutdown"); \ - globalfunction(draw_function, "CSQC_UpdateView"); \ + globalfunction(f_updateview, "CSQC_UpdateView"); \ + globalfunction(f_updateviewloading, "CSQC_UpdateViewLoading"); \ globalfunction(parse_stuffcmd, "CSQC_Parse_StuffCmd"); \ globalfunction(parse_centerprint, "CSQC_Parse_CenterPrint"); \ globalfunction(parse_print, "CSQC_Parse_Print"); \ @@ -2791,6 +2792,8 @@ static void QCBUILTIN PF_cs_serverkey (pubprogfuncs_t *prinst, struct globalvars else ret = NET_AdrToString(adr, sizeof(adr), &cls.netchan.remote_address); } + else if (!strcmp(keyname, "servername")) + ret = cls.servername; else if (!strcmp(keyname, "constate")) { if (cls.state == ca_disconnected @@ -2804,6 +2807,36 @@ static void QCBUILTIN PF_cs_serverkey (pubprogfuncs_t *prinst, struct globalvars else ret = "connecting"; } + else if (!strcmp(keyname, "loadstate")) + { + extern int total_loading_size, current_loading_size, loading_stage; + extern char levelshotname[MAX_QPATH]; + ret = va("%i %u %u \"%s\"", loading_stage, current_loading_size, total_loading_size, levelshotname); + } + else if (!strcmp(keyname, "transferring")) + { + ret = CL_TryingToConnect(); + if (!ret) + ret = ""; + } + else if (!strcmp(keyname, "dlstate")) + { + if (!cl.downloadlist && !cls.download) + ret = ""; //nothing being downloaded right now + else + { + unsigned int fcount; + qofs_t tsize; + qboolean sizeextra; + CL_GetDownloadSizes(&fcount, &tsize, &sizeextra); + if (cls.download) //downloading something + ret = va("%u %g %u \"%s\" \"%s\" %g %i %g %g", fcount, (float)tsize, sizeextra?1u:0u, cls.download->localname, cls.download->remotename, cls.download->percent, cls.download->rate, (float)cls.download->completedbytes, (float)cls.download->size); + else //not downloading anything right now + ret = va("%u %g %u", fcount, (float)tsize, sizeextra?1u:0u); + } + } + else if (!strcmp(keyname, "pausestate")) + ret = cl.paused?"1":"0"; else if (!strcmp(keyname, "protocol")) { //using this is pretty acedemic, really. Not particuarly portable. switch (cls.protocol) @@ -5520,8 +5553,10 @@ qbyte *PDECL CSQC_PRLoadFile (const char *path, void *buffer, int bufsize, size_ return NULL; //not valid } +#ifndef FTE_TARGET_WEB //back it up COM_WriteFile(newname, file, *sz); +#endif } } @@ -6145,6 +6180,11 @@ void CSQC_CvarChanged(cvar_t *var) } } +qboolean CSQC_UseGamecodeLoadingScreen(void) +{ + return csqcprogs && csqcg.f_updateviewloading; +} + //evil evil function. calling qc from inside the renderer is BAD. qboolean CSQC_SetupToRenderPortal(int entkeynum) { @@ -6195,7 +6235,7 @@ qboolean CSQC_DrawView(void) csqc_resortfrags = true; csqctime = Sys_DoubleTime(); - if (!csqcg.draw_function || !csqcprogs) + if (!csqcg.f_updateview || !csqcprogs) return false; if (cls.state < ca_active && !CSQC_UnconnectedOkay(false)) @@ -6301,7 +6341,10 @@ qboolean CSQC_DrawView(void) G_FLOAT(OFS_PARM2) = !m_state; } //end EXT_CSQC_1 - PR_ExecuteProgram(csqcprogs, csqcg.draw_function); + if (csqcg.f_updateviewloading && cls.state && cls.state < ca_active) + PR_ExecuteProgram(csqcprogs, csqcg.f_updateviewloading); + else + PR_ExecuteProgram(csqcprogs, csqcg.f_updateview); return true; } diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c index e7fd93465..85b29d566 100644 --- a/engine/client/pr_skelobj.c +++ b/engine/client/pr_skelobj.c @@ -834,7 +834,7 @@ void skel_generateragdoll_f(void) { char *modname = Cmd_Argv(1); char *outname; - model_t *mod = Mod_ForName(modname, false); + model_t *mod = Mod_ForName(modname, MLV_SILENT); galiasbone_t *bones; vfsfile_t *f; int i; diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 37e708e64..81ec85a0b 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -413,15 +413,19 @@ typedef struct q2miptex_s // leaffaces, leafbrushes, planes, and verts are still bounded by // 16 bit short limits #define SANITY_MAX_Q2MAP_MODELS 1024 -#define MAX_Q2MAP_ENTITIES 2048 +//#define MAX_Q2MAP_ENTITIES 2048 #define SANITY_MAX_MAP_BRUSHES 0x10000 #define MAX_Q2MAP_AREAS 256 #define MAX_Q2MAP_AREAPORTALS 1024 -#define MAX_Q2MAP_VERTS MAX_MAP_VERTS -#define MAX_Q2MAP_FACES MAX_MAP_FACES +//#define MAX_Q2MAP_VERTS MAX_MAP_VERTS +//#define MAX_Q2MAP_FACES MAX_MAP_FACES #define SANITY_MAX_MAP_LEAFFACES 262144 //sanity only +#ifdef FTE_TARGET_WEB +#define MAX_Q2MAP_LEAFBRUSHES (32768) //used in an array +#else #define MAX_Q2MAP_LEAFBRUSHES (65536*2) //used in an array +#endif //#define MAX_Q2MAP_PORTALS 65536 //unused //#define MAX_Q2MAP_EDGES 128000 //unused //#define MAX_Q2MAP_SURFEDGES 256000 //unused diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index a75a4ea07..530cb2961 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -12,10 +12,14 @@ #define MAX_Q3MAP_INDICES 0x8000000 //just a sanity limit #define MAX_Q3MAP_VERTEXES 0x800000 //just a sanity limit -#define MAX_CM_PATCH_VERTS (4096) -#define MAX_CM_FACES (MAX_Q2MAP_FACES) -#define MAX_CM_PATCHES (0x10000) -#define MAX_CM_LEAFFACES (MAX_Q2MAP_LEAFFACES) +//#define MAX_CM_PATCH_VERTS (4096) +//#define MAX_CM_FACES (MAX_Q2MAP_FACES) +#ifdef FTE_TARGET_WEB +#define MAX_CM_PATCHES (0x1000) //fixme +#else +#define MAX_CM_PATCHES (0x10000) //fixme +#endif +//#define MAX_CM_LEAFFACES (MAX_Q2MAP_LEAFFACES) #define MAX_CM_AREAS MAX_Q2MAP_AREAS //#define Q3SURF_NODAMAGE 0x00000001 @@ -6296,9 +6300,9 @@ CM_WritePortalState Writes the portal state to a savegame file =================== */ -void CM_WritePortalState (FILE *f) +void CM_WritePortalState (vfsfile_t *f) { - fwrite (portalopen, sizeof(portalopen), 1, f); + VFS_WRITE(f, portalopen, sizeof(portalopen)); } /* @@ -6309,11 +6313,11 @@ Reads the portal state from a savegame file and recalculates the area connections =================== */ -void CM_ReadPortalState (FILE *f) +void CM_ReadPortalState (vfsfile_t *f) { size_t result; - result = fread (portalopen, 1, sizeof(portalopen), f); // do something with result + result = VFS_READ(f, portalopen, sizeof(portalopen)); // do something with result if (result != sizeof(portalopen)) Con_Printf("CM_ReadPortalState() fread: expected %lu, result was %u\n",(long unsigned int)sizeof(portalopen),(unsigned int)result); diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index a48199772..924720b4b 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1605,11 +1605,11 @@ void QCBUILTIN PF_fopen (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals break; case FRIK_FILE_READ: //read case FRIK_FILE_READNL: //read whole file - fsize = FS_LoadFile(pf_fopen_files[i].name, &pf_fopen_files[i].data); + fsize = FS_LoadFile(pf_fopen_files[i].name, (void**)&pf_fopen_files[i].data); if (!pf_fopen_files[i].data && fallbackread) { Q_strncpyz(pf_fopen_files[i].name, fallbackread, sizeof(pf_fopen_files[i].name)); - fsize = FS_LoadFile(pf_fopen_files[i].name, &pf_fopen_files[i].data); + fsize = FS_LoadFile(pf_fopen_files[i].name, (void**)&pf_fopen_files[i].data); } if (pf_fopen_files[i].data) @@ -3473,12 +3473,12 @@ void QCBUILTIN PF_buf_writefile (pubprogfuncs_t *prinst, struct globalvars_s *p G_FLOAT(OFS_RETURN) = 0; - if ((unsigned int)bufno >= NUMSTRINGBUFS) + if ((unsigned int)bufno >= (unsigned int)NUMSTRINGBUFS) return; if (strbuflist[bufno].prinst != prinst) return; - if (fnum < 0 || fnum >= MAX_QC_FILES) + if ((unsigned int)fnum >= (unsigned int)MAX_QC_FILES) return; if (pf_fopen_files[fnum].prinst != prinst) return; diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 24488b130..d47087598 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -55,11 +55,7 @@ cvar_t r_shadow_scissor = CVAR("r_shadow_scissor", "1"); cvar_t r_shadow_realtime_world = CVARF ("r_shadow_realtime_world", "0", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_shadows = CVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_lightmaps = CVARF ("r_shadow_realtime_world_lightmaps", "0", 0); -#ifdef FTE_TARGET_WEB -cvar_t r_shadow_realtime_dlight = CVARF ("r_shadow_realtime_dlight", "0", CVAR_ARCHIVE); -#else cvar_t r_shadow_realtime_dlight = CVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE); -#endif cvar_t r_shadow_realtime_dlight_shadows = CVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambient", "0"); cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1"); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index fd32d8ff7..e9918af35 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -1218,6 +1218,7 @@ static void PDECL qclib_free(void *ptr) free(ptr); } #ifdef FTE_TARGET_WEB +#undef printf #define printf NULL //should be some null wrapper instead #endif diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 8c2b1247f..782104124 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -10496,6 +10496,7 @@ void PR_DumpPlatform_f(void) {"CSQC_WorldLoaded", "noref void()", CS, "Called after model+sound precaches have been executed. Gives a chance for the qc to read the entity lump from the bsp."}, {"CSQC_Shutdown", "noref void()", CS, "Specifies that the csqc is going down. Save your persistant settings here."}, {"CSQC_UpdateView", "noref void(float vwidth, float vheight, float notmenu)", CS, "Called every single video frame. The CSQC is responsible for rendering the entire screen."}, + {"CSQC_UpdateViewLoading", "noref void(float vwidth, float vheight, float notmenu)", CS, "Alternative to CSQC_UpdateView, called when the engine thinks there should be a loading screen. If present, will inhibit the engine's normal loading screen, deferring to qc to draw it."}, {"CSQC_Parse_StuffCmd", "noref void(string msg)", CS, "Gives the CSQC a chance to intercept stuffcmds. Use the tokenize builtin to parse the message. Unrecognised commands would normally be localcmded, but its probably better to drop unrecognised stuffcmds completely."}, {"CSQC_Parse_CenterPrint", "noref float(string msg)", CS, "Gives the CSQC a chance to intercept centerprints. Return true if you wish the engine to otherwise ignore the centerprint."}, {"CSQC_Parse_Print", "noref void(string printmsg, float printlvl)", CS, "Gives the CSQC a chance to intercept sprint/bprint builtin calls. CSQC should filter by the client's current msg setting and then pass the message on to the print command, or handle them itself."}, @@ -10683,6 +10684,15 @@ void PR_DumpPlatform_f(void) {"INFOKEY_P_VOIPSPEAKING","const string", CS, "Boolean value that says whether the given player is currently sending voice information.", 0, "\"voipspeaking\""}, {"INFOKEY_P_VOIPLOUDNESS","const string", CS, "Only valid for the local player. Gives a value between 0 and 1 to indicate to the user how loud their mic is.", 0, "\"voiploudness\""}, + {"SERVERKEY_IP", "const string", CS,"The address of the server we connected to.", 0, "\"ip\""}, + {"SERVERKEY_SERVERNAME","const string", CS,"The hostname that was last passed to the connect command.", 0, "\"servername\""}, + {"SERVERKEY_CONSTATE", "const string", CS,"The current connection state. Will be set to one of: disconnected (menu-only mode), active (gamestate received and loaded), connecting(connecting, downloading, or precaching content, aka: loading screen).", 0, "\"constate\""}, + {"SERVERKEY_TRANSFERRING","const string",CS,"Set to the hostname of the server that we are attempting to connect or transfer to.", 0, "\"transferring\""}, + {"SERVERKEY_LOADSTATE", "const string", CS, "loadstage, loading image name, current step, max steps\nStages are: 1=connecting, 2=serverside, 3=clientside\nKey will be empty if we are not loading.", 0, "\"loadstate\""}, + {"SERVERKEY_PAUSESTATE","const string", CS, "1 if the server claimed to be paused. 0 otherwise", 0, "\"pausestate\""}, + {"SERVERKEY_DLSTATE", "const string", CS, "The progress of any current downloads. Empty string if no download is active, otherwise a tokenizable string containing this info:\nfiles-remaining, total-size, unknown-sizes-flag, file-localname, file-remotename, file-percent, file-rate, file-received-bytes, file-total-bytes\nIf the current file info is omitted, then we are waiting for a download to start.", 0, "\"dlstate\""}, + {"SERVERKEY_PROTOCOL", "const string", CS, "The protocol we are connected to the server with.", 0, "\"protocol\""}, + // edict.flags {"FL_FLY", "const float", QW|NQ|CS, NULL, FL_FLY}, {"FL_SWIM", "const float", QW|NQ|CS, NULL, FL_SWIM}, diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 0721bd24e..c2bf7a759 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -922,13 +922,13 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us #if defined(Q2BSPS) if (usecinematic) { - qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer); + qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer, size_t fsize); Q_strncpyz (sv.name, server, sizeof(sv.name)); Q_strncpyz (sv.modelname, "", sizeof(sv.modelname)); sv.world.worldmodel = Mod_FindName (sv.modelname); - if (Mod_LoadQ2BrushModel (sv.world.worldmodel, NULL)) + if (Mod_LoadQ2BrushModel (sv.world.worldmodel, NULL, 0)) sv.world.worldmodel->loadstate = MLS_LOADED; else sv.world.worldmodel->loadstate = MLS_FAILED; diff --git a/engine/web/ftejslib.h b/engine/web/ftejslib.h index ce9611cf4..c41ebc952 100644 --- a/engine/web/ftejslib.h +++ b/engine/web/ftejslib.h @@ -40,6 +40,7 @@ int emscriptenfte_setupcanvas( int(*Keyboard)(int devid, int down, int keycode, int unicode), void(*LoadFile)(char *newhash, int filehandle), void(*buttonevent)(int joydev, int button, int ispressed), - void(*axisevent)(int joydev, int axis, float value) + void(*axisevent)(int joydev, int axis, float value), + int (*ShouldSwitchToFullscreen)(void) ); diff --git a/engine/web/ftejslib.js b/engine/web/ftejslib.js index 7cabd3555..84e4a038e 100644 --- a/engine/web/ftejslib.js +++ b/engine/web/ftejslib.js @@ -66,7 +66,12 @@ mergeInto(LibraryManager.library, evcb: { resize:0, mouse:0, - key:0 + button:0, + key:0, + loadfile:0, + jbutton:0, + jaxis:0, + wantfullscreen:0 }, loadurl : function(url, arraybuf) @@ -114,6 +119,8 @@ mergeInto(LibraryManager.library, break; case 'mousedown': if (Browser.isFullScreen == 0) + if (FTEC.evcb.wantfullscreen != 0) + if (Runtime.dynCall('i', FTEC.evcb.wantfullscreen, [])) { Browser.requestFullScreen(true, true); Module['canvas'].requestPointerLock(); @@ -143,8 +150,10 @@ mergeInto(LibraryManager.library, case 'keypress': if (FTEC.evcb.key != 0) { - Runtime.dynCall('viiii', FTEC.evcb.key, [0, 1, 0, event.charCode]); - Runtime.dynCall('viiii', FTEC.evcb.key, [0, 0, 0, event.charCode]); + if (event.charCode >= 122 && event.charCode <= 123) //no f11/f12 + break; + Runtime.dynCall('iiiii', FTEC.evcb.key, [0, 1, 0, event.charCode]); + Runtime.dynCall('iiiii', FTEC.evcb.key, [0, 0, 0, event.charCode]); event.preventDefault(); } break; @@ -264,7 +273,7 @@ mergeInto(LibraryManager.library, } }, emscriptenfte_setupcanvas__deps: ['$FTEC', '$Browser', 'emscriptenfte_buf_createfromarraybuf'], - emscriptenfte_setupcanvas : function(nw,nh,evresize,evmouse,evmbutton,evkey,evfile,evjbutton,evjaxis) + emscriptenfte_setupcanvas : function(nw,nh,evresize,evmouse,evmbutton,evkey,evfile,evjbutton,evjaxis,evwantfullscreen) { FTEC.evcb.resize = evresize; FTEC.evcb.mouse = evmouse; @@ -273,6 +282,7 @@ mergeInto(LibraryManager.library, FTEC.evcb.loadfile = evfile; FTEC.evcb.jbutton = evjbutton; FTEC.evcb.jaxis = evjaxis; + FTEC.evcb.wantfullscreen = evwantfullscreen; if ('GamepadEvent' in window) FTEH.gamepads = []; //don't bother ever trying to poll if we can use gamepad events. this will hopefully avoid weirdness. @@ -327,6 +337,11 @@ mergeInto(LibraryManager.library, }; window.onresize(); + if (evmouse) + Module.canvas.style.cursor = "none"; //hide the cursor, we'll do a soft-cursor when one is needed. + else + Module.canvas.style.cursor = "default"; //restore the cursor + if (FTEC.evcb.hashchange) { window.onhashchange = function() diff --git a/engine/web/gl_vidweb.c b/engine/web/gl_vidweb.c index 226553d7a..dfbc7940d 100644 --- a/engine/web/gl_vidweb.c +++ b/engine/web/gl_vidweb.c @@ -172,6 +172,11 @@ void DOM_LoadFile(char *loc, int handle) VFS_CLOSE(file); } } +int VID_ShouldSwitchToFullscreen(void) +{ //if false, mouse grabs won't work and we'll be forced to touchscreen mode. + extern cvar_t vid_fullscreen; + return !!vid_fullscreen.value; +} qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) { vid_isfullscreen = true; @@ -185,7 +190,8 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) DOM_KeyEvent, DOM_LoadFile, IN_JoystickButtonEvent, - IN_JoystickAxisEvent + IN_JoystickAxisEvent, + VID_ShouldSwitchToFullscreen )) { Con_Printf("Couldn't set up canvas\n"); @@ -209,7 +215,7 @@ void GLVID_DeInit (void) { ActiveApp = false; - emscriptenfte_setupcanvas(-1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + emscriptenfte_setupcanvas(-1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } diff --git a/engine/web/sys_web.c b/engine/web/sys_web.c index a1cfc49d5..6e32a627f 100644 --- a/engine/web/sys_web.c +++ b/engine/web/sys_web.c @@ -100,9 +100,17 @@ qboolean Sys_Rename (char *oldfname, char *newfname) } //someone used the 'quit' command +#include "glquake.h" void Sys_Quit (void) { - Host_Shutdown(); + if (host_initialized) + { + qglClearColor(0,0,0,1); + qglClear(GL_COLOR_BUFFER_BIT); + Draw_FunString (0, 0, "Reload the page to restart"); + + Host_Shutdown(); + } exit (0); } @@ -110,7 +118,7 @@ void Sys_Quit (void) int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, qofs_t, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath) { Con_DPrintf("Warning: Sys_EnumerateFiles not implemented\n"); - return false; + return true; } //blink window if possible (it's not) @@ -136,6 +144,12 @@ void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname) void Sys_Init(void) { + extern cvar_t vid_width, vid_height, vid_fullscreen; + //vid_fullscreen takes effect only on mouse clicks, any suggestion to do a vid_restart is pointless. + vid_fullscreen.flags &= CVAR_RENDERERLATCH; + //these are not really supported. so silence any spam that suggests we do something about something not even supported. + vid_width.flags &= CVAR_RENDERERLATCH; + vid_height.flags &= CVAR_RENDERERLATCH; } void Sys_Shutdown(void) {