From b29c68ef92b01e4a3546c5eb3986a5566461453c Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 20 Sep 2014 04:11:39 +0000 Subject: [PATCH] try to be more strict/paranoid with cvars. load q2 game dlls from the binarydir in preference to gamedir (allows such dlls to be distributed with the engine). add small emscripten msvc project so I can build the web port a little more conveniently. require mouse releases to have had a corresponding mouse press while in the menu. this solves issues with mouse clicks triggering the load menu while dead and instantlyish loading one, and alt-tab issues too. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4755 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 41 +++++++++++++---- engine/client/cl_main.c | 7 ++- engine/client/menu.c | 9 +++- engine/client/pr_csqc.c | 2 +- engine/client/pr_menu.c | 14 ++++-- engine/common/common.h | 2 +- engine/common/cvar.h | 4 +- engine/common/fs.c | 25 ++++++++--- engine/common/fs_pak.c | 2 +- engine/common/pr_bgcmd.c | 25 ++++++----- engine/common/qvm.c | 2 +- engine/dotnet2005/emscripten.vcproj | 65 +++++++++++++++++++++++++++ engine/dotnet2005/ftequake.sln | 45 +++++++++++++++++++ engine/gl/gl_alias.c | 23 ++++------ engine/gl/gl_heightmap.c | 17 +++---- engine/gl/gl_rmain.c | 2 +- engine/gl/gl_rmisc.c | 2 +- engine/server/pr_cmds.c | 55 ++++++++++++++++++++--- engine/server/sv_main.c | 21 +++++---- engine/server/svq2_game.c | 31 ++++++++++--- engine/server/world.c | 70 ++++++++++++++++++++++++++--- 21 files changed, 376 insertions(+), 88 deletions(-) create mode 100644 engine/dotnet2005/emscripten.vcproj diff --git a/engine/Makefile b/engine/Makefile index 25d26ac47..cd6a7dc53 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -666,7 +666,7 @@ BOTLIB_OBJS = \ l_struct.o #the defaults for sdl come first -CC_MACHINE:=$(shell $(CC) -dumpmachine) +#CC_MACHINE:=$(shell TESTamch $(CC) -dumpmachine) ifeq ($(FTE_TARGET),SDL2) SDLCONFIG?=sdl2-config FTE_FULLTARGET?=sdl2$(BITS) @@ -796,7 +796,7 @@ ifeq (win_SDL,$(findstring win,$(FTE_TARGET))$(findstring _SDL,$(FTE_TARGET))) EXEPOSTFIX=.exe - CC_MACHINE:=$(shell $(CC) -dumpmachine) + CC_MACHINE:=$(shell TESTaseh $(CC) -dumpmachine) ARCH_PREDEP=$(BASE_DIR)/libs/SDL2-2.0.1/$(CC_MACHINE)/bin/sdl2-config SDLCONFIG=$(ARCH_PREDEP) --prefix=$(BASE_DIR)/libs/SDL2-2.0.1/$(CC_MACHINE) ARCH_CFLAGS=`$(SDLCONFIG) --cflags` @@ -1226,11 +1226,11 @@ ifeq ($(FTE_TARGET),web) JSLIBS=--js-library web/ftejslib.js -s LEGACY_GL_EMULATION=0 EMCC_ARGS=$(JSLIBS) $(WEB_PREJS) --shell-file web/fteshell.html -s ERROR_ON_UNDEFINED_SYMBOLS=1 RELEASE_CFLAGS=-DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB - DEBUG_CFLAGS=-g -g4 -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB + DEBUG_CFLAGS=-g -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB RELEASE_LDFLAGS=-s ASM_JS=1 -O3 -s TOTAL_MEMORY=$(ASMJS_MEMORY) $(EMCC_ARGS) # RELEASE_LDFLAGS=-s ASM_JS=0 -O1 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS) - DEBUG_LDLAGS=-O0 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS) - CC=emcc + DEBUG_LDFLAGS=-O0 -g4 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS) + CC?=emcc #BASELDFLAGS= PRECOMPHEADERS= @@ -1291,6 +1291,7 @@ releases: # -$(MAKE) FTE_TARGET=linux64 relcl # -$(MAKE) FTE_TARGET=win32 relcl -$(MAKE) droid-rel + -$(MAKE) web-rel -$(MAKE) FTE_TARGET=win32 npfte-rel autoconfig: clean @@ -1329,7 +1330,7 @@ $(OUT_DIR)/npplug.o : ftequake/npplug.rc $(OUT_DIR)/%.o $(OUT_DIR)/%.d : %.c ifneq ($(DEPCC),) - @set -e; rm -f $@.d; \ + @-set -e; rm -f $@.d; \ $(DEPCC) -MM $(ALL_CFLAGS) $< > $@.d.$$$$; \ sed 's,\($*\)\.o[ :]*,$@ $@.d : ,g' < $@.d.$$$$ > $@.d; \ sed -e 's/.*://' -e 's/\\$$//' < $@.d.$$$$ | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $@.d; \ @@ -1339,7 +1340,7 @@ endif $(OUT_DIR)/%.o $(OUT_DIR)/%.d : %.cpp ifneq ($(DEPCC),) - @set -e; rm -f $@.d; \ + @-set -e; rm -f $@.d; \ $(DEPCC) -MM $(ALL_CFLAGS) $< > $@.d.$$$$; \ sed 's,\($*\)\.o[ :]*,$@ $@.d : ,g' < $@.d.$$$$ > $@.d; \ sed -e 's/.*://' -e 's/\\$$//' < $@.d.$$$$ | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $@.d; \ @@ -1349,7 +1350,7 @@ endif $(OUT_DIR)/%.oo $(OUT_DIR)/%.d : %.c ifneq ($(DEPCC),) - @set -e; rm -f $@.d; \ + @-set -e; rm -f $@.d; \ $(DEPCC) -MM $(ALL_CFLAGS) $< > $@.d.$$$$; \ sed 's,\($*\)\.oo[ :]*,$@ $@.d : ,g' < $@.d.$$$$ > $@.d; \ sed -e 's/.*://' -e 's/\\$$//' < $@.d.$$$$ | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $@.d; \ @@ -1358,7 +1359,7 @@ endif $(DO_CC) -I$(OUT_DIR) $(OUT_DIR)/%.mo $(OUT_DIR)/%.d : %.m - @set -e; rm -f $@.d; \ + @-set -e; rm -f $@.d; \ $(DEPCC) -MM $(ALL_CFLAGS) $< > $@.d.$$$$; \ sed 's,\($*\)\.mo[ :]*,$@ $@.d : ,g' < $@.d.$$$$ > $@.d; \ sed -e 's/.*://' -e 's/\\$$//' < $@.d.$$$$ | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $@.d; \ @@ -1542,6 +1543,7 @@ help: @-echo "'mcl-???' (currently broken)" @-echo "'glcl-???' (currently broken)" @-echo "'droid-???' (cross compiles Android package)" + @-echo "'web-???' (compiles javascript/emscripten page)" @-echo "'npfte-???' (cross compiles QuakeTV Firefox/Netscape browser plugin)" @-echo "'nacl-???' (cross compiles QuakeTV Firefox/Netscape browser plugin)" @-echo "" @@ -1617,6 +1619,27 @@ nacl-dbg: @$(MAKE) gl-dbg FTE_TARGET=nacl NARCH=arm @$(MAKE) gl-dbg FTE_TARGET=nacl NARCH=pnacl +################################################# +#webgl helpers + +#just adds some extra paths (WINDOWS HOST ONLY) +#assumes you installed the emscripten 1.22.0 sdk to EMSCRIPTENROOT +#if you have a different version installed, you will need to fix up the paths yourself (or just use fte_target explicitly yourself). +EMSCRIPTENROOT?=C:/Games/tools/Emscripten +EMSCRIPTENPATH=$(realpath $(EMSCRIPTENROOT)):$(realpath $(EMSCRIPTENROOT)/clang/e1.22.0_64bit):$(realpath $(EMSCRIPTENROOT)/node/0.10.17_64bit):$(realpath $(EMSCRIPTENROOT)/python/2.7.5.3_64bit):$(realpath $(EMSCRIPTENROOT)/emscripten/1.22.0):$(PATH) + +web-rel: + @$(MAKE) gl-rel FTE_TARGET=web PATH="$(EMSCRIPTENPATH)" CC="emcc.bat" + @gzip -f $(RELEASE_DIR)/ftewebgl.html + @gzip -f $(RELEASE_DIR)/ftewebgl.js + @gzip -f $(RELEASE_DIR)/ftewebgl.html.mem + +web-dbg: + @$(MAKE) gl-dbg FTE_TARGET=web PATH="$(EMSCRIPTENPATH)" CC="emcc.bat" + @gzip -f $(DEBUG_DIR)/ftewebgl.html + @gzip -f $(DEBUG_DIR)/ftewebgl.js + @gzip -f $(DEBUG_DIR)/ftewebgl.html.map + ################################################# #android diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 9850f05bc..7bd07dd87 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -145,7 +145,7 @@ cvar_t cl_gunanglex = CVAR("cl_gunanglex", "0"); cvar_t cl_gunangley = CVAR("cl_gunangley", "0"); cvar_t cl_gunanglez = CVAR("cl_gunanglez", "0"); -cvar_t cl_sendguid = CVARD("cl_sendguid", "0", "Send a randomly generated 'globally unique' id to servers, which can be used by servers for score rankings and stuff. Different servers will see different guids. Delete the 'qkey' file in order to appear as a different user."); +cvar_t cl_sendguid = CVARD("cl_sendguid", "0", "Send a randomly generated 'globally unique' id to servers, which can be used by servers for score rankings and stuff. Different servers will see different guids. Delete the 'qkey' file in order to appear as a different user.\nIf set to 2, all servers will see the same guid. Be warned that this can show other people the guid that you're using."); cvar_t cl_downloads = CVARFD("cl_downloads", "1", CVAR_NOTFROMSERVER, "Allows you to block all automatic downloads."); cvar_t cl_download_csprogs = CVARFD("cl_download_csprogs", "1", CVAR_NOTFROMSERVER, "Download updated client gamecode if available. Warning: If you clear this to avoid downloading vm code, you should also clear cl_download_packages."); cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "2", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files. 2 allows redirection only to named packages files. Also allows the server to send nearly arbitary download commands."); @@ -437,7 +437,10 @@ char *CL_GUIDString(netadr_t *adr) } } - NET_AdrToString(serveraddr, sizeof(serveraddr), adr); + if (cl_sendguid.ival == 2) + *serveraddr = 0; + else + NET_AdrToString(serveraddr, sizeof(serveraddr), adr); blocks[0] = buf;lens[0] = buflen; blocks[1] = serveraddr;lens[1] = strlen(serveraddr); diff --git a/engine/client/menu.c b/engine/client/menu.c index a89567472..d7e685dcf 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "shader.h" m_state_t m_state; +qboolean menu_mousedown; void M_DrawScalePic (int x, int y, int w, int h, mpic_t *pic) { @@ -1275,6 +1276,7 @@ void M_Draw (int uimenu) if (m_state != m_complex) { M_RemoveAllMenus(); + menu_mousedown = false; } #endif @@ -1352,7 +1354,9 @@ void M_Keydown (int key, int unicode) return; case m_complex: - if (key != K_MOUSE1) //mouse clicks are deferred until the release event. this is for touch screens and aiming. + if (key == K_MOUSE1) //mouse clicks are deferred until the release event. this is for touch screens and aiming. + menu_mousedown = true; + else M_Complex_Key (key, unicode); return; #endif @@ -1383,8 +1387,9 @@ void M_Keyup (int key, int unicode) { #ifndef NOBUILTINMENUS case m_complex: - if (key == K_MOUSE1) + if (key == K_MOUSE1 && menu_mousedown) M_Complex_Key (key, unicode); + menu_mousedown = false; return; #endif #ifdef PLUGINS diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 671197050..14fa1e6e9 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -534,7 +534,7 @@ static void QCBUILTIN PF_cvar (pubprogfuncs_t *prinst, struct globalvars_s *pr_g else { var = Cvar_Get(str, "", 0, "csqc cvars"); - if (var) + if (var && !(var->flags & CVAR_NOUNSAFEEXPAND)) G_FLOAT(OFS_RETURN) = var->value; else G_FLOAT(OFS_RETURN) = 0; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index f99ab9dae..008c7a222 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -988,8 +988,9 @@ static void QCBUILTIN PF_menu_cvar (pubprogfuncs_t *prinst, struct globalvars_s { str = RemapCvarNameFromDPToFTE(str); var = Cvar_Get(str, "", 0, "menu cvars"); - if (var) + if (var && !(var->flags & CVAR_NOUNSAFEEXPAND)) { + //menuqc sees desired settings, not latched settings. if (var->latched_string) G_FLOAT(OFS_RETURN) = atof(var->latched_string); else @@ -1009,6 +1010,11 @@ static void QCBUILTIN PF_menu_cvar_set (pubprogfuncs_t *prinst, struct globalvar val = PR_GetStringOfs(prinst, OFS_PARM1); var = Cvar_Get(var_name, val, 0, "QC variables"); + if (var->flags & CVAR_NOTFROMSERVER) + { + //fixme: menuqc needs some way to display a prompt to allow it anyway. + return; + } Cvar_Set (var, val); } static void QCBUILTIN PF_menu_cvar_string (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1017,10 +1023,12 @@ static void QCBUILTIN PF_menu_cvar_string (pubprogfuncs_t *prinst, struct global cvar_t *cv = Cvar_Get(RemapCvarNameFromDPToFTE(str), "", 0, "QC variables"); if (!cv) G_INT(OFS_RETURN) = 0; + else if (cv->flags & CVAR_NOUNSAFEEXPAND) + G_INT(OFS_RETURN) = 0; else if (cv->latched_string) - G_INT(OFS_RETURN) = (int)PR_SetString(prinst, cv->latched_string); + G_INT(OFS_RETURN) = (int)PR_TempString(prinst, cv->latched_string); else - G_INT(OFS_RETURN) = (int)PR_SetString(prinst, cv->string); + G_INT(OFS_RETURN) = (int)PR_TempString(prinst, cv->string); } diff --git a/engine/common/common.h b/engine/common/common.h index 69a8b9dd9..69b304f50 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -466,7 +466,7 @@ qbyte *COM_LoadTempMoreFile (const char *path); //allocates a little bit more wi //qbyte *COM_LoadHunkFile (const char *path); qbyte *COM_LoadMallocFile (const char *path); -searchpathfuncs_t *COM_IteratePaths (void **iterator, char *buffer, int buffersize); +searchpathfuncs_t *COM_IteratePaths (void **iterator, char *pathbuffer, int pathbuffersize, char *dirname, int dirnamesize); void COM_FlushFSCache(void); //a file was written using fopen void COM_RefreshFSCache_f(void); qboolean FS_Restarted(unsigned int *since); diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 99979e179..bcb269324 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -125,14 +125,14 @@ typedef struct cvar_group_s //freestyle #define CVAR_POINTER (1<<5) // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly. #define CVAR_UNUSED (1<<6) //the default string was malloced/needs to be malloced, free on unregister -#define CVAR_NOTFROMSERVER (1<<7) // the console will ignore changes to cvars if set at from the server or any gamecode. This is to protect against security flaws - like qterm +#define CVAR_NOTFROMSERVER (1<<7) //cvar cannot be set by gamecode. the console will ignore changes to cvars if set at from the server or any gamecode. This is to protect against security flaws - like qterm #define CVAR_USERCREATED (1<<8) //write a 'set' or 'seta' in front of the var name. #define CVAR_CHEAT (1<<9) //latch to the default, unless cheats are enabled. #define CVAR_SEMICHEAT (1<<10) //if strict ruleset, force to 0/blank. #define CVAR_RENDERERLATCH (1<<11) //requires a vid_restart to reapply. #define CVAR_SERVEROVERRIDE (1<<12) //the server has overridden out local value - should probably be called SERVERLATCH #define CVAR_RENDERERCALLBACK (1<<13) //force callback for cvars on renderer change -#define CVAR_NOUNSAFEEXPAND (1<<14) // do not expand cvar value when command is from gamecode +#define CVAR_NOUNSAFEEXPAND (1<<14) //cvar cannot be read by gamecode. do not expand cvar value when command is from gamecode. #define CVAR_RULESETLATCH (1<<15) //latched by the ruleset #define CVAR_SHADERSYSTEM (1<<16) //change flushes shaders. #define CVAR_TELLGAMECODE (1<<17) //tells the gamecode when it has changed, does not prevent changing, added as an optimisation diff --git a/engine/common/fs.c b/engine/common/fs.c index e6a46ff4b..e9de7a482 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -2098,7 +2098,9 @@ void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, const ch FS_AddPathHandle(oldpaths, puredir, dir, handle, flags|keptflags, loadstuff); } -searchpathfuncs_t *COM_IteratePaths (void **iterator, char *buffer, int buffersize) +//if syspath, something like c:\quake\baseq2 +//otherwise just baseq2. beware of dupes. +searchpathfuncs_t *COM_IteratePaths (void **iterator, char *pathbuffer, int pathbuffersize, char *dirname, int dirnamesize) { searchpath_t *s; void *prev; @@ -2112,15 +2114,28 @@ searchpathfuncs_t *COM_IteratePaths (void **iterator, char *buffer, int buffersi if (*iterator == prev) { *iterator = s->handle; - Q_strncpyz(buffer, s->logicalpath, buffersize-1); - FS_CleanDir(buffer, buffersize); - return s->handle; + if (!strchr(s->purepath, '/')) + { + if (pathbuffer) + { + Q_strncpyz(pathbuffer, s->logicalpath, pathbuffersize-1); + FS_CleanDir(pathbuffer, pathbuffersize); + } + if (dirname) + { + Q_strncpyz(dirname, s->purepath, dirnamesize-1); + } + return s->handle; + } } prev = s->handle; } *iterator = NULL; - *buffer = 0; + if (pathbuffer) + *pathbuffer = 0; + if (dirname) + *dirname = 0; return NULL; } diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c index aa80e3a91..35d46a8c4 100644 --- a/engine/common/fs_pak.c +++ b/engine/common/fs_pak.c @@ -209,7 +209,7 @@ static int QDECL VFSPAK_WriteBytes (struct vfsfile_s *vfs, const void *buffer, i static qboolean QDECL VFSPAK_Seek (struct vfsfile_s *vfs, qofs_t pos) { vfspack_t *vfsp = (vfspack_t*)vfs; - if (pos < 0 || pos > vfsp->length) + if (pos > vfsp->length) return false; vfsp->currentpos = pos + vfsp->startpos; diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 808f0feff..35df35dca 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1036,7 +1036,7 @@ void QCBUILTIN PF_cvar_string (pubprogfuncs_t *prinst, struct globalvars_s *pr_g { const char *str = PR_GetStringOfs(prinst, OFS_PARM0); cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); - if (cv) + if (cv && !(cv->flags & CVAR_NOUNSAFEEXPAND)) { if(cv->latched_string) RETURN_CSTRING(cv->latched_string); @@ -1052,7 +1052,7 @@ void QCBUILTIN PF_cvar_defstring (pubprogfuncs_t *prinst, struct globalvars_s *p { const char *str = PR_GetStringOfs(prinst, OFS_PARM0); cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); - if (cv) + if (cv && !(cv->flags & CVAR_NOUNSAFEEXPAND)) RETURN_CSTRING(cv->defaultstr); else G_INT(OFS_RETURN) = 0; @@ -1063,7 +1063,7 @@ void QCBUILTIN PF_cvar_description (pubprogfuncs_t *prinst, struct globalvars_s { const char *str = PR_GetStringOfs(prinst, OFS_PARM0); cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); - if (cv) + if (cv && !(cv->flags & CVAR_NOUNSAFEEXPAND)) RETURN_CSTRING(cv->description); else G_INT(OFS_RETURN) = 0; @@ -1077,7 +1077,7 @@ void QCBUILTIN PF_cvar_type (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo cvar_t *v; v = Cvar_FindVar(str); - if (v) + if (v && !(v->flags & CVAR_NOUNSAFEEXPAND)) { ret |= 1; // CVAR_EXISTS if(v->flags & CVAR_ARCHIVE) @@ -1102,7 +1102,7 @@ void QCBUILTIN PF_cvar_set (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob val = PR_GetStringOfs(prinst, OFS_PARM1); var = Cvar_Get(var_name, val, 0, "QC variables"); - if (!var) + if (!var || (var->flags & CVAR_NOTFROMSERVER)) return; Cvar_Set (var, val); } @@ -1116,7 +1116,7 @@ void QCBUILTIN PF_cvar_setlatch (pubprogfuncs_t *prinst, struct globalvars_s *pr val = PR_GetStringOfs(prinst, OFS_PARM1); var = Cvar_Get(var_name, val, 0, "QC variables"); - if (!var) + if (!var || (var->flags & CVAR_NOTFROMSERVER)) return; Cvar_LockFromServer(var, val); } @@ -1131,10 +1131,9 @@ void QCBUILTIN PF_cvar_setf (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo val = G_FLOAT(OFS_PARM1); var = Cvar_FindVar(var_name); - if (!var) - Con_Printf("PF_cvar_set: variable %s not found\n", var_name); - else - Cvar_SetValue (var, val); + if (!var || (var->flags & CVAR_NOTFROMSERVER)) + return; + Cvar_SetValue (var, val); } //float(string name, string value) registercvar @@ -5120,6 +5119,10 @@ void PR_AutoCvar(pubprogfuncs_t *prinst, cvar_t *var) eval_t *val; etype_t type; int n, p; + + if (var->flags & CVAR_NOUNSAFEEXPAND) + return; + for (n = 0; n < 2; n++) { gname = n?var->name2:var->name; @@ -5167,7 +5170,7 @@ void PDECL PR_FoundAutoCvarGlobal(pubprogfuncs_t *progfuncs, char *name, eval_t return; } var = Cvar_Get(name, vals, 0, "autocvars"); - if (!var) + if (!var || (var->flags & CVAR_NOUNSAFEEXPAND)) return; var->flags |= CVAR_TELLGAMECODE; diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 9236edc61..82364aa44 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -103,7 +103,7 @@ dllhandle_t *QVM_LoadDLL(const char *name, qboolean binroot, void **vmMain, sys_ { // run through the search paths iterator = NULL; - while (!hVM && COM_IteratePaths(&iterator, gpath, sizeof(gpath))) + while (!hVM && COM_IteratePaths(&iterator, gpath, sizeof(gpath), NULL, false)) { if (!hVM) { diff --git a/engine/dotnet2005/emscripten.vcproj b/engine/dotnet2005/emscripten.vcproj new file mode 100644 index 000000000..62b9d1dd7 --- /dev/null +++ b/engine/dotnet2005/emscripten.vcproj @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 47fffdc89..47f609827 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -49,6 +49,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "irc", "..\..\plugins\irc\ir EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private", "..\..\plugins\private\private.vcproj", "{74542CA7-48C1-4664-9007-66F751131EA3}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "targets", "targets", "{EB5DFF7C-C0A8-426C-BC66-524162350F1B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emscripten", "emscripten.vcproj", "{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution D3DDebug|Win32 = D3DDebug|Win32 @@ -627,6 +631,42 @@ Global {74542CA7-48C1-4664-9007-66F751131EA3}.Release|Win32.ActiveCfg = Release|Win32 {74542CA7-48C1-4664-9007-66F751131EA3}.Release|Win32.Build.0 = Release|Win32 {74542CA7-48C1-4664-9007-66F751131EA3}.Release|x64.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DDebug|Win32.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DDebug|Win32.Build.0 = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DDebug|x64.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DRelease|Win32.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DRelease|Win32.Build.0 = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DRelease|x64.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Debug|Win32.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Debug|Win32.Build.0 = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Debug|x64.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.GLDebug|Win32.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.GLDebug|Win32.Build.0 = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.GLDebug|x64.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.GLRelease|Win32.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.GLRelease|Win32.Build.0 = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.GLRelease|x64.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MDebug|Win32.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MDebug|Win32.Build.0 = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MDebug|x64.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MinGLDebug|Win32.Build.0 = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MinGLDebug|x64.ActiveCfg = Debug|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MinGLRelease|Win32.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MinGLRelease|Win32.Build.0 = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MinGLRelease|x64.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MRelease|Win32.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MRelease|Win32.Build.0 = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.MRelease|x64.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Release Dedicated Server|Win32.Build.0 = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Release Dedicated Server|x64.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Release|Win32.ActiveCfg = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Release|Win32.Build.0 = Release|Win32 + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -639,6 +679,11 @@ Global {72269FEE-293D-40BC-A7AE-E429F4496869} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {6ABD62A3-C5A0-43E8-BA4F-84606057774F} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {74542CA7-48C1-4664-9007-66F751131EA3} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} + {4735677B-6D5A-4BE6-A945-CB32DEADBEEF} = {EB5DFF7C-C0A8-426C-BC66-524162350F1B} + {4735677B-6D5A-4BE6-A945-CB32A7282F56} = {EB5DFF7C-C0A8-426C-BC66-524162350F1B} + {482A886A-5755-4DAE-AD5F-D7CD4A990F9E} = {EB5DFF7C-C0A8-426C-BC66-524162350F1B} + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365} = {EB5DFF7C-C0A8-426C-BC66-524162350F1B} + {75D91BDE-CC30-4C53-BF33-5F69EF13A61B} = {EB5DFF7C-C0A8-426C-BC66-524162350F1B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index e43ac5e88..8eee100bb 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1391,7 +1391,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) model_t *clmodel; shader_t *shader, *regshader; batch_t *b; - int surfnum; + int surfnum, j; shadersort_t sort; texnums_t *skin; @@ -1462,10 +1462,8 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) b->skin = skin; b->texture = NULL; b->shader = shader; - b->lightmap[0] = -1; - b->lightmap[1] = -1; - b->lightmap[2] = -1; - b->lightmap[3] = -1; + for (j = 0; j < MAXRLIGHTMAPS; j++) + b->lightmap[0] = -1; b->surf_first = surfnum; b->flags = 0; sort = shader->sort; @@ -2248,6 +2246,7 @@ static void R_Sprite_GenerateBatch(entity_t *e, batch_t **batches, void (*drawfu shader_t *shader = NULL; batch_t *b; shadersort_t sort; + int j; if (!e->model || e->model->type != mod_sprite || e->forcedshader) { @@ -2310,10 +2309,8 @@ static void R_Sprite_GenerateBatch(entity_t *e, batch_t **batches, void (*drawfu b->skin = &shader->defaulttextures; b->texture = NULL; b->shader = shader; - b->lightmap[0] = -1; - b->lightmap[1] = -1; - b->lightmap[2] = -1; - b->lightmap[3] = -1; + for (j = 0; j < MAXRLIGHTMAPS; j++) + b->lightmap[j] = -1; b->surf_first = 0; b->flags |= BEF_NODLIGHT|BEF_NOSHADOWS; b->vbo = NULL; @@ -2340,7 +2337,7 @@ void BE_GenPolyBatches(batch_t **batches) { shader_t *shader = NULL; batch_t *b; - unsigned int i = cl_numstris; + unsigned int i = cl_numstris, j; while (i-- > 0) { @@ -2363,10 +2360,8 @@ void BE_GenPolyBatches(batch_t **batches) b->skin = &shader->defaulttextures; b->texture = NULL; b->shader = shader; - b->lightmap[0] = -1; - b->lightmap[1] = -1; - b->lightmap[2] = -1; - b->lightmap[3] = -1; + for (j = 0; j < MAXRLIGHTMAPS; j++) + b->lightmap[j] = -1; b->surf_first = i; b->flags = BEF_NODLIGHT|BEF_NOSHADOWS | cl_stris[i].flags; b->vbo = 0; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 615044b42..1d9507aea 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -648,7 +648,7 @@ static void Terr_AddMesh(heightmap_t *hm, int loadflags, model_t *mod, vec3_t ep continue; if (e->ent.model != mod || e->ent.scale != scale) continue; - if (memcmp(axis, e->ent.axis, sizeof(axis))) + if (memcmp(axis, e->ent.axis, sizeof(e->ent.axis))) continue; break; //looks like a match. } @@ -2672,7 +2672,7 @@ void Terr_DrawInBounds(struct tdibctx *ctx, int x, int y, int w, int h) vec3_t mins, maxs; hmsection_t *s; struct hmwater_s *wa; - int i; + int i, j; batch_t *b; heightmap_t *hm = ctx->hm; @@ -2804,9 +2804,8 @@ void Terr_DrawInBounds(struct tdibctx *ctx, int x, int y, int w, int h) b->texture = NULL; b->vbo = &s->vbo; b->lightmap[0] = s->lightmap; - b->lightmap[1] = -1; - b->lightmap[2] = -1; - b->lightmap[3] = -1; + for (j = 1; j < MAXRLIGHTMAPS; j++) + b->lightmap[j] = -1; b->next = ctx->batches[b->shader->sort]; ctx->batches[b->shader->sort] = b; @@ -2853,7 +2852,7 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e) model_t *m = e->model; heightmap_t *hm = m->terrain; batch_t *b; - int bounds[4]; + int bounds[4], j; struct tdibctx tdibctx; if (!r_refdef.recurse) @@ -2876,10 +2875,8 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e) b = BE_GetTempBatch(); if (b) { - b->lightmap[0] = -1; - b->lightmap[1] = -1; - b->lightmap[2] = -1; - b->lightmap[3] = -1; + for (j = 0; j < MAXRLIGHTMAPS; j++) + b->lightmap[j] = -1; b->ent = e; b->shader = hm->skyshader; b->flags = 0; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 430ead4bf..f3ca89a8c 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1654,7 +1654,7 @@ void GLR_RenderView (void) if (mrt) { //colour (with or without depth) - if (*r_refdef.rt_depth.texname && (dw != cw || dh != dh)) + if (*r_refdef.rt_depth.texname && (dw != cw || dh != ch)) { Con_Printf("RT: destcolour and depth render targets are of different sizes\n"); //should check rgb/depth modes too I guess. depth = r_nulltex; diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 254fb05dd..efae8bf48 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -573,7 +573,7 @@ void GLR_TimeRefresh_f (void) { int i; float start, stop, time; - qboolean finish; + int finish; int frames = 128; finish = atoi(Cmd_Argv(1)); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 2c4d4c322..7b8e38848 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -3569,7 +3569,10 @@ static void QCBUILTIN PF_cvar (pubprogfuncs_t *prinst, struct globalvars_s *pr_g cv = Cvar_Get(str, def, 0, "QC variables"); Con_Printf("^3Creating cvar %s\n", str); } - G_FLOAT(OFS_RETURN) = cv->value; + if (cv->flags & CVAR_NOUNSAFEEXPAND) + G_FLOAT(OFS_RETURN) = 0; + else + G_FLOAT(OFS_RETURN) = cv->value; } } @@ -5111,9 +5114,11 @@ logfrag (killer, killee) */ void QCBUILTIN PF_logfrag (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { + extern cvar_t fraglog_details; edict_t *ent1, *ent2; int e1, e2; - char *s; + char s[2048]; + int slen; sizebuf_t *sz; ent1 = G_EDICT(prinst, OFS_PARM0); @@ -5132,11 +5137,51 @@ void QCBUILTIN PF_logfrag (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa svs.clients[e2].deaths += 1; #endif - s = va("\\%s\\%s\\\n",svs.clients[e1].name, svs.clients[e2].name); + if (!fraglog_details.ival) + return; //not logging any details + else if (fraglog_details.ival == 7) + { //compat with mvdsv. + time_t t = time (NULL); + struct tm *tm = gmtime(&t); + Q_snprintfz(s, sizeof(s)-2, "\\frag\\"); + } + else if (fraglog_details.ival == 1) + strcpy(s, "\\");//vanilla compat + else //specify what info is actually in there + Q_snprintfz(s, sizeof(s)-2, "\\\\%u\\", fraglog_details.ival); + slen = strlen(s); + if (fraglog_details.ival & 1) + { + Q_snprintfz(s+slen, sizeof(s)-2-slen, "%s\\%s\\", svs.clients[e1].name, svs.clients[e2].name); + slen += strlen(s+slen); + } + if (fraglog_details.ival & 2) + { + Q_snprintfz(s+slen, sizeof(s)-2-slen, "%s\\%s\\", svs.clients[e1].team, svs.clients[e2].team); + slen += strlen(s+slen); + } + if (fraglog_details.ival & 4) + { + time_t t = time (NULL); + struct tm *tm = gmtime(&t); + Q_snprintfz(s+slen, sizeof(s)-2-slen, "%d-%d-%d %d:%d:%d\\", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + slen += strlen(s+slen); + } + if (fraglog_details.ival & 8) + { + Q_snprintfz(s+slen, sizeof(s)-2-slen, "%g\\", ent1->v->weapon); + slen += strlen(s+slen); + } + if (fraglog_details.ival & 16) + { + Q_snprintfz(s+slen, sizeof(s)-2-slen, "%s\\%s\\", svs.clients[e1].guid, svs.clients[e2].guid); + slen += strlen(s+slen); + } + s[slen++] = '\n'; //print it to the fraglog buffer for masters/etc to query sz = &svs.log[svs.logsequence&(FRAGLOG_BUFFERS-1)]; - if (sz->cursize && sz->cursize+strlen(s)+1 >= sz->maxsize) + if (sz->cursize && sz->cursize+slen+1 >= sz->maxsize) { // swap buffers and bump sequence svs.logtime = realtime; @@ -5145,7 +5190,7 @@ void QCBUILTIN PF_logfrag (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa sz->cursize = 0; Con_TPrintf ("beginning fraglog sequence %i\n", svs.logsequence); } - SZ_Print (sz, s); + SZ_Write(sz, s, slen); //print it to our local fraglog file. if (sv_fraglogfile) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index b9d87f056..e06f61b92 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -93,6 +93,7 @@ cvar_t sv_limittics = CVARD("sv_limittics","3", "The maximum number of ticks tha cvar_t sv_nailhack = CVARD("sv_nailhack","0", "If set to 1, disables the nail entity networking optimisation. This hack was popularised by qizmo which recommends it for better compression. Also allows clients to interplate nail positions and add trails."); cvar_t sv_nopvs = CVARD("sv_nopvs", "0", "Set to 1 to ignore pvs on the server. This can make wallhacks more dangerous, so should only be used for debugging."); cvar_t fraglog_public = CVARD("fraglog_public", "1", "Enables support for connectionless fraglog requests"); +cvar_t fraglog_details = CVARD("fraglog_details", "1", "Bitmask\n1: killer+killee names.\n2: killer+killee teams\n4:timestamp.\n8:killer weapon\n16:killer+killee guid.\nFor compatibility, use 1(vanilla) or 7(mvdsv)."); cvar_t timeout = SCVAR("timeout","65"); // seconds without any message cvar_t zombietime = SCVAR("zombietime", "2"); // seconds to sink messages @@ -1307,10 +1308,12 @@ void SVC_Log (void) unsigned int seq; char data[MAX_DATAGRAM+64]; char adr[MAX_ADR_SIZE]; + char *av; - if (Cmd_Argc() == 2) + av = Cmd_Argv(1); + if (*av) { - seq = strtoul(Cmd_Argv(1), NULL, 0); + seq = strtoul(av, NULL, 0); //seq is the last one that the client already has if (seq < svs.logsequence-(FRAGLOG_BUFFERS-1)) @@ -1338,7 +1341,12 @@ void SVC_Log (void) Con_DPrintf ("sending log %i to %s\n", seq, NET_AdrToString(adr, sizeof(adr), &net_from)); - Q_snprintfz(data, sizeof(data), "stdlog %i\n%s", seq, (char *)svs.log_buf[seq&(FRAGLOG_BUFFERS-1)]); + //cookie support, to avoid spoofing + av = Cmd_Argv(2); + if (*av) + Q_snprintfz(data, sizeof(data), "stdlog %i %s\n%s", seq, av, (char *)svs.log_buf[seq&(FRAGLOG_BUFFERS-1)]); + else + Q_snprintfz(data, sizeof(data), "stdlog %i\n%s", seq, (char *)svs.log_buf[seq&(FRAGLOG_BUFFERS-1)]); NET_SendPacket (NS_SERVER, strlen(data)+1, data, &net_from); } @@ -5098,11 +5106,6 @@ void SV_InitNet (void) // NET_StringToAdr ("192.246.40.70:27000", &idmaster_adr); } -void SV_IgnoreCommand_f(void) -{ -} - - /* ==================== SV_Init @@ -5239,8 +5242,10 @@ void SV_Init (quakeparms_t *parms) } if (sv.state == ss_dead && COM_FCheckExists("maps/start.bsp")) Cmd_ExecuteString ("map start", RESTRICT_LOCAL); //regular q1 + #ifdef HEXEN2 if (sv.state == ss_dead && COM_FCheckExists("maps/demo1.bsp")) Cmd_ExecuteString ("map demo1", RESTRICT_LOCAL); //regular h2 sp + #endif #ifdef Q2SERVER if (sv.state == ss_dead && COM_FCheckExists("maps/base1.bsp")) Cmd_ExecuteString ("map base1", RESTRICT_LOCAL); //regular q2 sp diff --git a/engine/server/svq2_game.c b/engine/server/svq2_game.c index 6b6dba870..ad80f4b51 100644 --- a/engine/server/svq2_game.c +++ b/engine/server/svq2_game.c @@ -28,10 +28,13 @@ void *SVQ2_GetGameAPI (void *parms) }; char name[MAX_OSPATH]; - char searchpath[MAX_OSPATH]; + char syspath[MAX_OSPATH]; + char gamepath[MAX_OSPATH]; void *iterator; int o; const char *gamename[] = { + "", + "", #ifdef _DEBUG "debug/game" ARCH_CPU_POSTFIX ARCH_DL_POSTFIX, #endif @@ -42,21 +45,37 @@ void *SVQ2_GetGameAPI (void *parms) "game" ARCH_DL_POSTFIX, NULL }; - void *ret; #ifdef _DEBUG - Con_DPrintf("Searching for %s\n", gamename[1]); + Con_DPrintf("Searching for %s\n", gamename[3]); #else - Con_DPrintf("Searching for %s\n", gamename[0]); + Con_DPrintf("Searching for %s\n", gamename[2]); #endif iterator = NULL; - while(COM_IteratePaths(&iterator, searchpath, sizeof(searchpath))) + while(COM_IteratePaths(&iterator, syspath, sizeof(syspath), gamepath, sizeof(gamepath))) { for (o = 0; gamename[o]; o++) { - snprintf(name, sizeof(name), "%s%s", searchpath, gamename[o]); + if (o == 0) + { //nice and specific + if (!host_parms.binarydir) + continue; + Q_snprintfz(name, sizeof(name), "%sq2game"ARCH_CPU_POSTFIX"_%s"ARCH_DL_POSTFIX, host_parms.binarydir, gamepath); + } + else if (o == 1) + { //because some people don't like knowing what cpu arch they're compiling for + if (!host_parms.binarydir) + continue; + Q_snprintfz(name, sizeof(name), "%slibgame_%s"ARCH_DL_POSTFIX, host_parms.binarydir, gamepath); + } + else + { + if (com_nogamedirnativecode.ival) + continue; + Q_snprintfz(name, sizeof(name), "%s%s", syspath, gamename[o]); + } q2gamedll = Sys_LoadLibrary(name, funcs); if (q2gamedll) diff --git a/engine/server/world.c b/engine/server/world.c index 945d3de77..3370f3f53 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -123,14 +123,74 @@ hull_t *World_HullForBox (vec3_t mins, vec3_t maxs) model_t mod_capsule; qboolean World_BoxTrace(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace) { - //bbox vs bbox (NYI) + hull_t *hull = &box_hull; + + //bbox vs bbox //capsule vs bbox (NYI) - return false; + + memset (trace, 0, sizeof(trace_t)); + trace->fraction = 1; + trace->allsolid = true; + + VectorCopy (p2, trace->endpos); + return Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, p1, p2, trace); } qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace) { //bbox vs capsule (NYI) //capsule vs capsule (NYI) + + memset (trace, 0, sizeof(trace_t)); + trace->fraction = 1; + trace->allsolid = false; + VectorCopy(p2, trace->endpos); + + if (capsule) + { //capsule vs capsule. + //no orientation support on either (ignore axis) + float sr = ((model->maxs[0]-model->mins[0]) + (model->maxs[1]-model->mins[1]))/4.0; + float sh = (model->maxs[2]-model->mins[2]) - sr*2; + float mr = ((maxs[0]-mins[0]) + (maxs[1]-mins[1]))/4.0; + float mh = (maxs[2]-mins[2]) - mr*2; + vec3_t sup = {0, 0, 1}; + vec3_t dir, sright; + vec4_t nearestplane; + float d1, d2; + vec3_t nearestpoint; + float neardist; + + //expand the static capsule's height+radius by the mover's height+radius, so that its point+capsule instead + sr += mr; + sh += mh; + + VectorSubtract(p1, p2, dir); + d2=VectorNormalize(dir); + CrossProduct(sup, dir, sright); + VectorNormalize(sright); + CrossProduct(sup, sright, nearestplane); + VectorNormalize(nearestplane); + nearestplane[3] = DotProduct(vec3_origin, nearestplane); //capsule is at 0 0 0 + d1 = DotProduct(nearestplane, p1) - nearestplane[3]; + d2 = DotProduct(nearestplane, p2) - nearestplane[3]; + d2 = -d1 /(d1+d2); + VectorInterpolate(p1, d2, p2, nearestpoint); + + neardist = VectorLength(nearestpoint); + if (neardist < sr) + { + float x, y, oz, nz; + //sqrt(h*h-(x*x+y*y))=z + //change the hypotenuse from the messed up value to the actual radius + //and update z to match the changed h + x = DotProduct(sup, nearestpoint) - 0; + y = DotProduct(sright, nearestpoint) - 0; + oz = DotProduct(nearestplane, nearestpoint) - nearestplane[3]; + nz = sqrt(sr*sr - (x*x+y*y)); + + VectorMA(nearestpoint, nz-oz, dir, trace->endpos); + trace->fraction = 0; + } + } return false; } model_t *World_CapsuleForBox(vec3_t mins, vec3_t maxs) @@ -1020,9 +1080,9 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v model = NULL; VectorSubtract (ent->v->mins, maxs, boxmins); VectorSubtract (ent->v->maxs, mins, boxmaxs); - if (ent->xv->geomtype == GEOMTYPE_CAPSULE && !hitmodel) - model = World_CapsuleForBox(boxmins, boxmaxs); - else +// if (ent->xv->geomtype == GEOMTYPE_CAPSULE && !hitmodel) +// model = World_CapsuleForBox(boxmins, boxmaxs); +// else World_HullForBox(boxmins, boxmaxs); }