From 4d9ee2395a6b2ea9e889ce2c8013ac3603f66745 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 2 Dec 2014 02:00:41 +0000 Subject: [PATCH] warn clients when stuff will be invisible due to protocol limits. this does not include extra features, only limits. try to handle mvd prespawning a little more generically, to enable support for vweps (when protocol extensions are active). also fix issues with mid-demo map changes, which can potentially affect qtv streams. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4795 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 68 +++++++++++++++++++++++++++++--------- engine/client/cl_cg.c | 2 +- engine/client/cl_ents.c | 18 +++------- engine/client/cl_main.c | 4 +-- engine/client/net_master.c | 2 +- engine/client/p_script.c | 3 +- engine/common/protocol.h | 19 +++++++++++ engine/common/q1bsp.c | 33 +++++++++++------- engine/d3d/d3d_shader.c | 14 ++++++-- engine/gl/gl_model.h | 2 +- engine/gl/gl_rmain.c | 1 + engine/gl/gl_vidcommon.c | 1 + engine/qclib/pr_edict.c | 13 ++++++-- engine/server/server.h | 10 ++++++ engine/server/sv_ents.c | 15 ++++++--- engine/server/sv_mvd.c | 67 +++++++++++++++++++++++++++---------- engine/server/sv_user.c | 18 +++++++++- 17 files changed, 213 insertions(+), 77 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index 46191d668..40133dcd4 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -38,12 +38,14 @@ RELEASE_DIR=$(BASE_DIR)/release DEBUG_DIR=$(BASE_DIR)/debug PROFILE_DIR=$(BASE_DIR)/profile COMPILE_SYS:=$(shell uname -o 2>&1) +NATIVE_ABSBASE_DIR:=$(realpath $(BASE_DIR)) ifeq ($(COMPILE_SYS),Cygwin) OUT_DIR?=. NATIVE_OUT_DIR:=$(shell cygpath -m $(OUT_DIR)) NATIVE_BASE_DIR:=$(shell cygpath -m $(BASE_DIR)) NATIVE_RELEASE_DIR:=$(shell cygpath -m $(RELEASE_DIR)) NATIVE_DEBUG_DIR:=$(shell cygpath -m $(DEBUG_DIR)) + NATIVE_ABSBASE_DIR:=$(shell cygpath -m $(NATIVE_ABSBASE_DIR)) endif NATIVE_OUT_DIR?=$(OUT_DIR) NATIVE_BASE_DIR?=$(BASE_DIR) @@ -122,19 +124,34 @@ ifeq ($(FTE_TARGET),droid) #if we're running under windows, then we want to run some other binary ifeq ($(shell uname -o 2>&1 | grep Cygwin),) #set up for linux - TOOLCHAIN:=$(ANDROID_NDK_ROOT)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/bin/arm-linux-androideabi- + ifeq ($(DROID_ARCH),x86) + TOOLCHAINPATH:=$(ANDROID_NDK_ROOT)/toolchains/x86-4.7/prebuilt/linux-x86/bin/ + TOOLCHAIN:=$(TOOLCHAINPATH)i686-linux-androideabi- + else + TOOLCHAINPATH:=$(ANDROID_NDK_ROOT)/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86/bin/ + TOOLCHAIN:=$(TOOLCHAINPATH)arm-linux-androideabi- + endif + + TOOLOVERRIDES=PATH="/usr/bin:$(realpath $(TOOLCHAINPATH))" CFLAGS=--sysroot="$(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC))" CPPFLAGS=--sysroot="$(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC))" + CONFIGARGS= --with-sysroot="$(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC))" else #FIXME: support mingw too... #we're running upon windows ifeq ($(DROID_ARCH),x86) - TOOLCHAIN:=$(ANDROID_NDK_ROOT)/toolchains/x86-4.7/prebuilt/windows-x86_64/bin/i686-linux-android- + TOOLCHAINPATH:=$(ANDROID_NDK_ROOT)/toolchains/x86-4.7/prebuilt/windows-x86_64/bin/ + TOOLCHAIN:=$(TOOLCHAINPATH)i686-linux-android- else - TOOLCHAIN:=$(ANDROID_NDK_ROOT)/toolchains/arm-linux-androideabi-4.7/prebuilt/windows-x86_64/bin/arm-linux-androideabi- + TOOLCHAINPATH:=$(ANDROID_NDK_ROOT)/toolchains/arm-linux-androideabi-4.7/prebuilt/windows-x86_64/bin/ + TOOLCHAIN:=$(TOOLCHAINPATH)arm-linux-androideabi- endif ANDROID_SCRIPT=android.bat #make can't cope with absolute win32 paths in dependancy files DEPCC= + + #configure hates android, with its broken default sysroot and lack of path etc + TOOLOVERRIDES=PATH="/usr/bin:$(shell cygpath -u $(realpath $(TOOLCHAINPATH)))" CFLAGS=--sysroot="$(shell cygpath -m $(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)))" CPPFLAGS=--sysroot="$(shell cygpath -m $(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)))" + CONFIGARGS= --with-sysroot="$(shell cygpath -u $(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)))" endif DROID_API_LEVEL=4 @@ -152,10 +169,11 @@ ifeq ($(FTE_TARGET),droid) #armv7+neon DROID_ABI?=-mfloat-abi=softfp endif - + CC:=$(TOOLCHAIN)gcc --sysroot="$(shell cygpath -m $(realpath $(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)))" -DANDROID $(DROID_ABI) -fno-strict-aliasing + DO_LD:=$(DO_ECHO) $(CC) -Wl,-soname,libftedroid.so -shared -Wl,--no-undefined -Wl,-z,noexecstack -o $@ $(LTO_LD) $(WCFLAGS) $(BRANDFLAGS) $(CFLAGS) -llog -lc -lz -lm + LD:=$(TOOLCHAIN)ld + AR:=$(TOOLCHAIN)ar STRIP=$(TOOLCHAIN)strip - CC=$(TOOLCHAIN)gcc -I$(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/include/ -DANDROID $(DROID_ABI) -fno-strict-aliasing - DO_LD=$(DO_ECHO) $(CC) -Wl,-soname,libftedroid.so -shared -Wl,--no-undefined -Wl,-z,noexecstack --sysroot=$(ANDROID_NDK_ROOT)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC) -L$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/lib -o $@ $(LTO_LD) $(WCFLAGS) $(BRANDFLAGS) $(CFLAGS) -llog -lc -lz -lm endif @@ -1751,23 +1769,41 @@ $(BASE_DIR)/libs/SDL2-2.0.1/i686-w64-mingw32/bin/sdl2-config: rm $(BASE_DIR)/sdl2.tar.gz $(BASE_DIR)/libs/SDL2-2.0.1/x86_64-w64-mingw32/bin/sdl2-config: $(BASE_DIR)/libs/SDL2-2.0.1/i686-w64-mingw32/bin/sdl2-config + + +#update these to download+build a different version. this assumes that the url+subdirs etc contain a consistant version everywhere. +JPEGVER=9a +ZLIBVER=1.2.8 +PNGVER=1.6.14 +OGGVER=1.3.2 +VORBISVER=1.3.4 +#makes sure the configure scripts get the right idea. +AR?=$(ARCH)-ar + + +CONFIGARGS+= -host=$(ARCH) --enable-shared=no +#--disable-silent-rules + makelibs: + #lock these down, to avoid expanding them too often + #TOOLOVERRIDES:=$(TOOLOVERRIDES) + #CONFIGARGS:=$(CONFIGARGS) ifndef ARCH $(MAKE) makelibs ARCH=$(shell $(CC) -dumpmachine) else mkdir -p libs-$(ARCH) - test -f jpegsrc.v9.tar.gz || wget http://www.ijg.org/files/jpegsrc.v9.tar.gz - -test -f libs-$(ARCH)/libjpeg.a || (cd libs-$(ARCH) && tar -xvzf ../jpegsrc.v9.tar.gz && cd jpeg-9 && ./configure -host=$(ARCH) && $(MAKE) && cp .libs/libjpeg.a ../ && $(ARCH)-ar -s ../libjpeg.a ) + test -f jpegsrc.v$(JPEGVER).tar.gz || wget http://www.ijg.org/files/jpegsrc.v$(JPEGVER).tar.gz + -test -f libs-$(ARCH)/libjpeg.a || (cd libs-$(ARCH) && tar -xvzf ../jpegsrc.v$(JPEGVER).tar.gz && cd jpeg-$(JPEGVER) && $(TOOLOVERRIDES) ./configure $(CONFIGARGS) && $(TOOLOVERRIDES) $(MAKE) && cp .libs/libjpeg.a ../ && $(TOOLOVERRIDES) $(AR) -s ../libjpeg.a && cp jconfig.h jerror.h jmorecfg.h jpeglib.h jversion.h ../ ) - test -f zlib-1.2.8.tar.gz || wget http://zlib.net/zlib-1.2.8.tar.gz - -test -f libs-$(ARCH)/libz.a || (cd libs-$(ARCH) && tar -xvzf ../zlib-1.2.8.tar.gz && cd zlib-1.2.8 && CC="$(CC) $(W32_CFLAGS)" ./configure --static && $(MAKE) libz.a CC="$(CC) $(W32_CFLAGS)" && cp libz.a ../ && $(ARCH)-ar -s ../libz.a ) + test -f zlib-$(ZLIBVER).tar.gz || wget http://zlib.net/zlib-$(ZLIBVER).tar.gz + -test -f libs-$(ARCH)/libz.a || (cd libs-$(ARCH) && tar -xvzf ../zlib-$(ZLIBVER).tar.gz && cd zlib-$(ZLIBVER) && $(TOOLOVERRIDES) ./configure --static && $(TOOLOVERRIDES) $(MAKE) libz.a CC="$(CC) $(W32_CFLAGS)" && cp libz.a ../ && $(TOOLOVERRIDES) $(AR) -s ../libz.a && cp zlib.h zconf.h zutil.h ../ ) - test -f libpng-1.6.2.tar.gz || wget http://prdownloads.sourceforge.net/libpng/libpng-1.6.2.tar.gz?download -O libpng-1.6.2.tar.gz - -test -f libs-$(ARCH)/libpng.a || (cd libs-$(ARCH) && tar -xvzf ../libpng-1.6.2.tar.gz && cd libpng-1.6.2 && ./configure -host=$(ARCH) CFLAGS=-I$(realpath libs-$(ARCH)/zlib-1.2.8/) LDFLAGS=-L$(realpath libs-$(ARCH)) && $(MAKE) && cp .libs/libpng16.a ../libpng.a ) + test -f libpng-$(PNGVER).tar.gz || wget http://prdownloads.sourceforge.net/libpng/libpng-$(PNGVER).tar.gz?download -O libpng-$(PNGVER).tar.gz + -test -f libs-$(ARCH)/libpng.a || (cd libs-$(ARCH) && tar -xvzf ../libpng-$(PNGVER).tar.gz && cd libpng-$(PNGVER) && $(TOOLOVERRIDES) ./configure $(CONFIGARGS) --with-zlib-prefix=$(NATIVE_ABSBASE_DIR)/libs-$(ARCH)/zlib-$(ZLIBVER)/ && $(TOOLOVERRIDES) $(MAKE) && cp .libs/libpng16.a ../libpng.a && cp png*.h ../ ) - test -f libogg-1.3.0.tar.gz || wget http://downloads.xiph.org/releases/ogg/libogg-1.3.0.tar.gz - -test -f libs-$(ARCH)/libogg.a || (cd libs-$(ARCH) && tar -xvzf ../libogg-1.3.0.tar.gz && cd libogg-1.3.0 && ./configure -host=$(ARCH) && $(MAKE) && cp src/.libs/libogg.a ../ && $(ARCH)-ar -s ../libogg.a) + test -f libogg-$(OGGVER).tar.gz || wget http://downloads.xiph.org/releases/ogg/libogg-$(OGGVER).tar.gz + -test -f libs-$(ARCH)/libogg.a || (cd libs-$(ARCH) && tar -xvzf ../libogg-$(OGGVER).tar.gz && cd libogg-$(OGGVER) && $(TOOLOVERRIDES) ./configure $(CONFIGARGS) && $(TOOLOVERRIDES) $(MAKE) && cp src/.libs/libogg.a ../ && $(TOOLOVERRIDES) $(AR) -s ../libogg.a) - test -f libvorbis-1.3.3.tar.gz || wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.3.tar.gz - -test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-1.3.3.tar.gz && cd libvorbis-1.3.3 && ./configure PKG_CONFIG= -host=$(ARCH) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(realpath libs-$(ARCH)/libogg-1.3.0/include) && $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ ) + test -f libvorbis-$(VORBISVER).tar.gz || wget http://downloads.xiph.org/releases/vorbis/libvorbis-$(VORBISVER).tar.gz + -test -f libs-$(ARCH)/libvorbisfile.a || (cd libs-$(ARCH) && tar -xvzf ../libvorbis-$(VORBISVER).tar.gz && cd libvorbis-$(VORBISVER) && $(TOOLOVERRIDES) ./configure PKG_CONFIG= $(CONFIGARGS) --disable-oggtest --with-ogg-libraries=.. --with-ogg-includes=$(NATIVE_ABSBASE_DIR)/libs-$(ARCH)/libogg-$(OGGVER)/include && $(TOOLOVERRIDES) $(MAKE) && cp lib/.libs/libvorbis.a ../ && cp lib/.libs/libvorbisfile.a ../ ) endif diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 4eba9e1ad..975445b9e 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -438,7 +438,7 @@ int CG_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projecti VectorNormalize(axis[2]); VectorNormalize2(projection, axis[0]); - numtris = Q1BSP_ClipDecal(center, axis[0], axis[1], axis[2], radius, &clippedpoints); + numtris = Q1BSP_ClipDecal(cl.worldmodel, center, axis[0], axis[1], axis[2], radius, &clippedpoints); if (numtris > maxFragments) numtris = maxFragments; if (numtris > maxPoints/3) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 5b940607a..8960b5333 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -2520,7 +2520,7 @@ void CL_AddDecal(shader_t *shader, vec3_t origin, vec3_t up, vec3_t side, vec3_t VectorScale(tang, s/l, tang); - num = Q1BSP_ClipDecal(origin, up, side, tang, 2, &verts); + num = Q1BSP_ClipDecal(cl.worldmodel, origin, up, side, tang, 2, &verts); if (!num) return; @@ -2637,7 +2637,7 @@ void CLQ1_AddShadow(entity_t *ent) AngleVectors(eang, axis[0], axis[1], axis[2]); VectorNegate(axis[2], axis[2]); - num = Q1BSP_ClipDecal(shadoworg, axis[2], axis[1], axis[0], radius, &verts); + num = Q1BSP_ClipDecal(cl.worldmodel, shadoworg, axis[2], axis[1], axis[0], radius, &verts); if (!num) return; @@ -3748,16 +3748,6 @@ extern int cl_spikeindex, cl_playerindex, cl_flagindex, cl_rocketindex, cl_gren entity_t *CL_NewTempEntity (void); - - -#define DF_ORIGIN 1 -#define DF_ANGLES (1<<3) -#define DF_EFFECTS (1<<6) -#define DF_SKINNUM (1<<7) -#define DF_DEAD (1<<8) -#define DF_GIB (1<<9) -#define DF_WEAPONFRAME (1<<10) -#define DF_MODEL (1<<11) static int MVD_TranslateFlags(int src) { int dst = 0; @@ -3849,7 +3839,7 @@ void CL_ParsePlayerinfo (void) for (i = 0; i < 3; i++) { - if (flags & (DF_ORIGIN << i)) + if (flags & (DF_ORIGINX << i)) state->origin[i] = MSG_ReadCoord (); } @@ -3859,7 +3849,7 @@ void CL_ParsePlayerinfo (void) for (i = 0; i < 3; i++) { - if (flags & (DF_ANGLES << i)) + if (flags & (DF_ANGLEX << i)) { state->command.angles[i] = MSG_ReadShort(); } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d79ccdd2b..62d8fd9e5 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3616,7 +3616,7 @@ void CL_Init (void) Cmd_AddCommand ("qtvplay", CL_QTVPlay_f); Cmd_AddCommand ("qtvlist", CL_QTVList_f); Cmd_AddCommand ("qtvdemos", CL_QTVDemos_f); - Cmd_AddCommand ("demo_jump", CL_DemoJump_f); + Cmd_AddCommandD ("demo_jump", CL_DemoJump_f, "Jump to a specified time in a demo. Prefix with a + or - for a relative offset. Seeking backwards will restart the demo and the fast forward, which can take some time in long demos."); Cmd_AddCommand ("timedemo", CL_TimeDemo_f); Cmd_AddCommand ("crashme_endgame", CL_CrashMeEndgame_f); @@ -3630,7 +3630,7 @@ void CL_Init (void) Cmd_AddCommand ("allskins", Skin_AllSkins_f); Cmd_AddCommand ("cl_status", CL_Status_f); - Cmd_AddCommand ("quit", CL_Quit_f); + Cmd_AddCommandD ("quit", CL_Quit_f, "Use this command when you get angry. Does not save any cvars. Use cfg_save to save settings, or use the menu for a prompt."); Cmd_AddCommandD ("connect", CL_Connect_f, "connect scheme://address:port\nConnect to a server. Use a scheme of tcp:// or tls:// to connect via non-udp protocols." #if defined(NQPROT) || defined(Q2CLIENT) || defined(Q3CLIENT) diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 2f4df1776..ae3070ae0 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -816,7 +816,7 @@ qboolean Master_LoadMasterList (char *filename, qboolean withcomment, int defaul favourite = true; } - if (!*name) + if (!*name && next) { sep = name; while(*next == ' ' || *next == '\t') diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 21f18451f..76b7ad62f 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -3667,7 +3667,6 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t axis[3] Surf_AddStain(org, ptype->stain_rgb[0], ptype->stain_rgb[1], ptype->stain_rgb[2], ptype->stain_radius); } -int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent, vec3_t tangent2, float size, float **out); static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk) { part_type_t *ptype = &part_type[typenum]; @@ -3823,7 +3822,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, sw /= m; tw /= m; - decalcount = Q1BSP_ClipDecal(bestorg, dir, tangent, t2, m, &decverts); + decalcount = Q1BSP_ClipDecal(cl.worldmodel, bestorg, dir, tangent, t2, m, &decverts); while(decalcount) { if (!free_decals) diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 69beb37cc..717e0ab2d 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -776,6 +776,25 @@ enum clcq2_ops_e #define Q2U_SOUND (1<<26) #define Q2U_SOLID (1<<27) + +//============================================== +//obsolete demo players info +#define DF_ORIGINX (1u<<0) +#define DF_ORIGINY (1u<<1) +#define DF_ORIGINZ (1u<<2) +#define DF_ORIGINALL (DF_ORIGINX|DF_ORIGINY|DF_ORIGINZ) +#define DF_ANGLEX (1u<<3) +#define DF_ANGLEY (1u<<4) +#define DF_ANGLEZ (1u<<5) +#define DF_ANGLESALL (DF_ANGLEX|DF_ANGLEY|DF_ANGLEZ) +#define DF_EFFECTS (1u<<6) +#define DF_SKINNUM (1u<<7) +#define DF_DEAD (1u<<8) +#define DF_GIB (1u<<9) +#define DF_WEAPONFRAME (1u<<10) +#define DF_MODEL (1u<<11) +#define DF_RESET (DF_ORIGINALL|DF_ANGLESALL|DF_EFFECTS|DF_SKINNUM|DF_WEAPONFRAME|DF_MODEL) + //============================================== // a sound with no channel is a local only sound diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 7580c008f..fecbcaeb7 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -1291,12 +1291,20 @@ void Fragment_ClipPoly(fragmentdecal_t *dec, int numverts, float *inverts) float verts2[MAXFRAGMENTVERTS*C]; float *cverts; int flip; + vec3_t d1, d2, n; if (numverts > MAXFRAGMENTTRIS) return; if (dec->numtris == MAXFRAGMENTTRIS) return; //don't bother + VectorSubtract(inverts+C*1, inverts+C*0, d1); + VectorSubtract(inverts+C*2, inverts+C*0, d2); + CrossProduct(d1, d2, n); + VectorNormalizeFast(n); + if (DotProduct(n, dec->normal) > 0.1) + return; //faces too far way from the normal + //clip to the first plane specially, so we don't have extra copys numverts = Fragment_ClipPolyToPlane(inverts, verts, numverts, dec->planenorm[0], dec->planedist[0]); @@ -1366,7 +1374,7 @@ static void Fragment_Mesh (fragmentdecal_t *dec, mesh_t *mesh) } } -static void Q1BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) +static void Q1BSP_ClipDecalToNodes (model_t *mod, fragmentdecal_t *dec, mnode_t *node) { mplane_t *splitplane; float dist; @@ -1381,17 +1389,17 @@ static void Q1BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) if (dist > dec->radius) { - Q1BSP_ClipDecalToNodes (dec, node->children[0]); + Q1BSP_ClipDecalToNodes (mod, dec, node->children[0]); return; } if (dist < -dec->radius) { - Q1BSP_ClipDecalToNodes (dec, node->children[1]); + Q1BSP_ClipDecalToNodes (mod, dec, node->children[1]); return; } // mark the polygons - surf = cl.worldmodel->surfaces + node->firstsurface; + surf = mod->surfaces + node->firstsurface; for (i=0 ; inumsurfaces ; i++, surf++) { if (surf->flags & SURF_PLANEBACK) @@ -1407,8 +1415,8 @@ static void Q1BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) Fragment_Mesh(dec, surf->mesh); } - Q1BSP_ClipDecalToNodes (dec, node->children[0]); - Q1BSP_ClipDecalToNodes (dec, node->children[1]); + Q1BSP_ClipDecalToNodes (mod, dec, node->children[0]); + Q1BSP_ClipDecalToNodes (mod, dec, node->children[1]); } #ifdef RTLIGHTS @@ -1463,7 +1471,8 @@ static void Q3BSP_ClipDecalToNodes (fragmentdecal_t *dec, mnode_t *node) } #endif -int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, float **out) +//returns trisoup within a 3d volume. +int Q1BSP_ClipDecal(model_t *mod, vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, float **out) { //quad marks a full, independant quad int p; float r; @@ -1493,19 +1502,19 @@ int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangen sh_shadowframe++; - if (!cl.worldmodel || cl.worldmodel->type != mod_brush) + if (!mod || mod->type != mod_brush) { } - else if (cl.worldmodel->fromgame == fg_quake) - Q1BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes); + else if (mod->fromgame == fg_quake) + Q1BSP_ClipDecalToNodes(mod, &dec, mod->nodes); #ifdef Q3BSPS else if (cl.worldmodel->fromgame == fg_quake3) - Q3BSP_ClipDecalToNodes(&dec, cl.worldmodel->nodes); + Q3BSP_ClipDecalToNodes(&dec, mod->nodes); #endif #ifdef TERRAIN if (cl.worldmodel && cl.worldmodel->terrain) - Terrain_ClipDecal(&dec, center, dec.radius, cl.worldmodel); + Terrain_ClipDecal(&dec, center, dec.radius, mod); #endif *out = (float *)decalfragmentverts; diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index d6fdbce75..443833e12 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -379,8 +379,6 @@ void D3D9Shader_Init(void) sh_config.pCreateProgram = D3D9Shader_CreateProgram; sh_config.pProgAutoFields = D3D9Shader_ProgAutoFields; - sh_config.texture_non_power_of_two = 0; - sh_config.texture_non_power_of_two_pic = 0; sh_config.tex_env_combine = 1; sh_config.nv_tex_env_combine4 = 1; sh_config.env_add = 1; @@ -395,6 +393,18 @@ void D3D9Shader_Init(void) sh_config.texfmt[PTI_ARGB4444] = true; IDirect3DDevice9_GetDeviceCaps(pD3DDev9, &caps); + + if (caps.TextureCaps & D3DPTEXTURECAPS_POW2) + { //this flag is a LIMITATION, not a capability. + sh_config.texture_non_power_of_two = false; + sh_config.texture_non_power_of_two_pic = !!(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL); //pic npot is supported if both flags are set. + } + else + { //modern cards support npot + sh_config.texture_non_power_of_two_pic = true; + sh_config.texture_non_power_of_two = true; + } + sh_config.texture_maxsize = min(caps.MaxTextureWidth, caps.MaxTextureHeight); } #endif diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 5622a4d32..d55efdf7a 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -497,7 +497,7 @@ void Q1BSP_Init(void); void *Q1BSPX_FindLump(char *lumpname, int *lumpsize); void Q1BSPX_Setup(struct model_s *mod, char *filebase, unsigned int filelen, lump_t *lumps, int numlumps); -int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, float **out); +int Q1BSP_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, float **out); void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 17b331315..870ec5ff1 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1234,6 +1234,7 @@ void R_Clear (void) /*tbh, this entire function should be in the backend*/ GL_ForceDepthWritable(); { + qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (r_clear.ival && R_GameRectIsFullscreen() && !(r_refdef.flags & RDF_NOWORLDMODEL)) { qglClearColor(1, 0, 0, 0); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 8b368d091..20ebafe36 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -320,6 +320,7 @@ void (APIENTRY myGLDEBUGPROCAMD)(GLenum source, break; default: case GL_DEBUG_TYPE_OTHER_ARB: + return; OutputDebugStringA("Other: "); break; } diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 9525e06b8..3ecec2253 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -1078,10 +1078,17 @@ char *PDECL ED_NewString (pubprogfuncs_t *ppf, const char *string, int minlength if (demarkup && string[i] == '\\' && i < l-1 && string[i+1] != 0) { i++; - if (string[i] == 'n') - *new_p++ = '\n'; - else + switch(string[i]) + { + case 'n': *new_p++ = '\n'; break; + case '\'': *new_p++ = '\''; break; + case '\"': *new_p++ = '\"'; break; + case 'r': *new_p++ = '\r'; break; + default: *new_p++ = '\\'; + i--; + break; + } } else *new_p++ = string[i]; diff --git a/engine/server/server.h b/engine/server/server.h index 786fa89d3..ff69bf18b 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -357,6 +357,13 @@ enum PRESPAWN_DONE }; +enum +{ //'soft' limits that result in warnings if the client's protocol is too limited. + PLIMIT_ENTITIES = 1u<<0, + PLIMIT_MODELS = 1u<<1, + PLIMIT_SOUNDS = 1u<<2 +}; + typedef struct client_s { client_conn_state_t state; @@ -601,6 +608,8 @@ typedef struct client_s int realip_num; int realip_ping; + unsigned int plimitwarned; + float delay; laggedpacket_t *laggedpacket; laggedpacket_t *laggedpacket_last; @@ -693,6 +702,7 @@ typedef struct float statsf[MAX_CLIENTS][MAX_CL_STATS]; // ouch! char *statss[MAX_CLIENTS][MAX_CL_STATS]; // ouch! client_t recorder; + qboolean playerreset[MAX_CLIENTS]; //will ensure that the model etc is written when this player is next written. qboolean fixangle[MAX_CLIENTS]; float fixangletime[MAX_CLIENTS]; vec3_t angles[MAX_CLIENTS]; diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 87cf7eb3b..c6c1e8ce1 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1202,7 +1202,7 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t client->pendingentbits[j] = (client->pendingentbits[j] & ~UF_REMOVE) | UF_RESET2; client->pendingentbits[j] |= SVFTE_DeltaCalcBits(o, n); //even if prediction is disabled, we want to force velocity info to be sent for the local player. This is used by view bob and things. - if (j == client->edict->entnum && (n->u.q1.velocity[0] || n->u.q1.velocity[1] || n->u.q1.velocity[2])) + if (client->edict && j == client->edict->entnum && (n->u.q1.velocity[0] || n->u.q1.velocity[1] || n->u.q1.velocity[2])) client->pendingentbits[j] |= UF_PREDINFO; } *o = *n; @@ -2058,8 +2058,6 @@ void SV_WritePlayersToMVD (client_t *client, client_frame_t *frame, sizebuf_t *m demo_frame_t *demo_frame; demo_client_t *dcl; -#define DF_DEAD (1<<8) -#define DF_GIB (1<<9) demo_frame = &demo.frames[demo.parsecount&DEMO_FRAMES_MASK]; for (j=0,cl=svs.clients, dcl = demo_frame->clients; j < svs.allocated_client_slots ; j++,cl++, dcl++) @@ -3171,7 +3169,16 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t else e = 1; - limit = min(client->max_net_ents, sv.world.num_edicts); + limit = sv.world.num_edicts; + if (client->max_net_ents < limit) + { + limit = client->max_net_ents; + if (!(client->plimitwarned & PLIMIT_ENTITIES)) + { + client->plimitwarned |= PLIMIT_ENTITIES; + SV_ClientPrintf(client, PRINT_HIGH, "WARNING: Your client's network protocol only supports %i entities. Please upgrade or enable extensions.\n", client->max_net_ents); + } + } if (client->penalties & BAN_BLIND) { diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 93ccd30f6..24f75177f 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -756,7 +756,7 @@ void SV_MVDPings (void) client_t *client; int j; - for (j = 0, client = svs.clients; j < demo.recorder.max_net_clients; j++, client++) + for (j = 0, client = svs.clients; j < demo.recorder.max_net_clients && j < svs.allocated_client_slots; j++, client++) { if (client->state != cs_spawned) continue; @@ -1060,15 +1060,6 @@ float adjustangle(float current, float ideal, float fraction) return (current + move); } -#define DF_ORIGIN 1 -#define DF_ANGLES (1<<3) -#define DF_EFFECTS (1<<6) -#define DF_SKINNUM (1<<7) -#define DF_DEAD (1<<8) -#define DF_GIB (1<<9) -#define DF_WEAPONFRAME (1<<10) -#define DF_MODEL (1<<11) - qboolean SV_MVDWritePackets (int num) { demo_frame_t *frame, *nextframe; @@ -1145,7 +1136,13 @@ qboolean SV_MVDWritePackets (int num) } // now write it to buf - flags = cl->flags; + flags = cl->flags; //df_dead/df_gib + + if (demo.playerreset[i]) + { + demo.playerreset[i] = false; + flags |= DF_RESET; + } if (cl->fixangle) { @@ -1154,13 +1151,13 @@ qboolean SV_MVDWritePackets (int num) for (j=0; j < 3; j++) if (origin[j] != demoinfo->origin[i]) - flags |= DF_ORIGIN << j; + flags |= DF_ORIGINX << j; if (cl->fixangle || demo.fixangletime[i] != cl->cmdtime) { for (j=0; j < 3; j++) if (angles[j] != demoinfo->angles[j]) - flags |= DF_ANGLES << j; + flags |= DF_ANGLEX << j; } if (cl->info.model != demoinfo->model) @@ -1179,11 +1176,11 @@ qboolean SV_MVDWritePackets (int num) MSG_WriteByte (&msg, cl->frame); for (j=0 ; j<3 ; j++) - if (flags & (DF_ORIGIN << j)) + if (flags & (DF_ORIGINX << j)) MSG_WriteCoord (&msg, origin[j]); for (j=0 ; j<3 ; j++) - if (flags & (DF_ANGLES << j)) + if (flags & (DF_ANGLEX << j)) MSG_WriteAngle16 (&msg, angles[j]); @@ -1686,7 +1683,7 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) { sizebuf_t buf; char buf_data[MAX_QWMSGLEN]; - int n, i; + int n, i, j; const char *s; client_t *player; @@ -1764,6 +1761,29 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) MSG_WriteFloat(&buf, movevars.waterfriction); MSG_WriteFloat(&buf, movevars.entgravity); + SV_WriteRecordMVDMessage (&buf); + SZ_Clear (&buf); + +#if 1 + demo.recorder.prespawn_stage = PRESPAWN_SERVERINFO; + demo.recorder.prespawn_idx = 0; + demo.recorder.netchan.message = buf; + while (demo.recorder.prespawn_stage != PRESPAWN_DONE) + { + if (demo.recorder.prespawn_stage == PRESPAWN_MAPCHECK) + { + demo.recorder.prespawn_stage++;//client won't reply, so don't wait. + demo.recorder.prespawn_idx = 0; + } + if (demo.recorder.prespawn_stage == PRESPAWN_SOUNDLIST || demo.recorder.prespawn_stage == PRESPAWN_MODELLIST) + demo.recorder.prespawn_idx &= ~0x80000000; //normally set for the server to wait for ack. we don't want to wait. + + SV_SendClientPrespawnInfo(&demo.recorder); + SV_WriteRecordMVDMessage (&demo.recorder.netchan.message); + SZ_Clear (&demo.recorder.netchan.message); + } + memset(&demo.recorder.netchan.message, 0, sizeof(demo.recorder.netchan.message)); +#else // send music MSG_WriteByte (&buf, svc_cdtrack); MSG_WriteByte (&buf, 0); // none in demos @@ -1933,10 +1953,10 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) SV_WriteRecordMVDMessage (&buf); SZ_Clear (&buf); } - +#endif // send current status of all other players - for (i = 0; i < demo.recorder.max_net_clients; i++) + for (i = 0; i < demo.recorder.max_net_clients && i < svs.allocated_client_slots; i++) { player = &svs.clients[i]; @@ -1975,6 +1995,17 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) } } + //invalidate stats+players somehow + for (i = 0; i < MAX_CLIENTS; i++) + { + for (j = 0; j < MAX_CL_STATS; j++) + { + demo.statsi[i][j] ^= -1; + demo.statsf[i][j] *= -0.41426712; //randomish value + } + demo.playerreset[i] = true; + } + // get the client to check and download skins // when that is completed, a begin command will be issued MSG_WriteByte (&buf, svc_stufftext); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index ff8b503c6..7337989cf 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -597,10 +597,13 @@ void SVNQ_New_f (void) MSG_WriteString (&host_client->netchan.message,message); + + //fixme: don't send too many models. for (i = 1; sv.strings.model_precache[i] ; i++) MSG_WriteString (&host_client->netchan.message, sv.strings.model_precache[i]); MSG_WriteByte (&host_client->netchan.message, 0); + //fixme: don't send too many sounds. for (i = 1; *sv.strings.sound_precache[i] ; i++) MSG_WriteString (&host_client->netchan.message, sv.strings.sound_precache[i]); MSG_WriteByte (&host_client->netchan.message, 0); @@ -979,7 +982,7 @@ void SV_SendClientPrespawnInfo(client_t *client) if (client->prespawn_stage == PRESPAWN_SOUNDLIST) { if (!ISQWCLIENT(client)) - client->prespawn_stage++; + client->prespawn_stage++; //nq sends sound lists as part of the svc_serverdata else { int maxclientsupportedsounds = 256; @@ -1015,6 +1018,11 @@ void SV_SendClientPrespawnInfo(client_t *client) if (client->prespawn_idx >= maxclientsupportedsounds || !*sv.strings.sound_precache[client->prespawn_idx]) { + if (*sv.strings.sound_precache[client->prespawn_idx] && !(client->plimitwarned & PLIMIT_SOUNDS)) + { + client->plimitwarned |= PLIMIT_SOUNDS; + SV_ClientPrintf(client, PRINT_HIGH, "WARNING: Your client's network protocol only supports %i sounds. Please upgrade or enable extensions.\n", client->prespawn_idx); + } //write final-end-of-list MSG_WriteByte (&client->netchan.message, 0); MSG_WriteByte (&client->netchan.message, 0); @@ -1112,6 +1120,11 @@ void SV_SendClientPrespawnInfo(client_t *client) if (client->prespawn_idx >= client->maxmodels || !sv.strings.model_precache[client->prespawn_idx]) { + if (*sv.strings.model_precache[client->prespawn_idx] && !(client->plimitwarned & PLIMIT_MODELS)) + { + client->plimitwarned |= PLIMIT_MODELS; + SV_ClientPrintf(client, PRINT_HIGH, "WARNING: Your client's network protocol only supports %i models. Please upgrade or enable extensions.\n", client->prespawn_idx); + } //write final-end-of-list MSG_WriteByte (&client->netchan.message, 0); MSG_WriteByte (&client->netchan.message, 0); @@ -4972,6 +4985,9 @@ void SVNQ_PreSpawn_f (void) host_client->checksum = ~0u; host_client->prespawn_stage = PRESPAWN_MAPCHECK+1; host_client->prespawn_idx = 0; + + if (sv_mapcheck.value) + Con_Printf("Warning: %s does cannot be applied to NQ clients.\n", sv_mapcheck.name); //as you can fake it in a client anyway, this is hardly a significant issue. } host_client->send_message = true;