diff --git a/.gitignore b/.gitignore index c0f5d266..72a641d9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ # Other *.save + # Qt Creator for some reason creates *.user.$version files, so exclude it too *.user* *~ @@ -47,7 +48,6 @@ Network Trash Folder Temporary Items .apdisk - ### CMake ### CMakeCache.txt CMakeFiles @@ -307,7 +307,18 @@ build-* # Android *.apk +*.config +*.creator +*.includes +*.files # Waf +build_current .waf-* +waf-*/ +waf3-*/ .lock-waf* +*.lastbuildstate +*.unsuccessfulbuild +__pycache__ +*.pyc diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..80f6b447 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "mainui"] + path = mainui + url = https://github.com/FWGS/mainui_cpp +[submodule "vgui_support/miniutl"] + path = vgui_support/miniutl + url = https://github.com/FWGS/miniutl diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..126873ad --- /dev/null +++ b/.travis.yml @@ -0,0 +1,48 @@ +language: c +cache: ccache +compiler: gcc +sudo: false +addons: + apt: + packages: + - mingw-w64-i686-dev + - binutils-mingw-w64-i686 + - gcc-mingw-w64-i686 + - g++-mingw-w64-i686 + - p7zip-full + - gcc-multilib + - g++-multilib + - libx11-dev:i386 + - libxext-dev:i386 + - x11-utils + - libgl1-mesa-dev + - libasound-dev + - zlib1g:i386 + - libstdc++6:i386 + - libfuse2:i386 +env: + global: + - SDL_VERSION=2.0.8 +git: + depth: 50 + submodules: true +jdk: + - oraclejdk8 +matrix: + include: + - os: linux + dist: xenial + - os: osx +before_script: + - sh scripts/travis_common_deps.sh + - sh scripts/travis_${TRAVIS_OS_NAME}_deps.sh + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export ANDROID_HOME=$PWD/android-sdk-linux; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:$PWD/android-ndk; fi +script: + - sh scripts/build_${TRAVIS_OS_NAME}_engine.sh +# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh scripts/build_android_engine.sh; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh scripts/build_mingw_engine.sh; fi +after_script: + - cd ${TRAVIS_BUILD_DIR} + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ccache --show-stats > ccache_stats.log; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh scripts/travis-deploy.sh newengine Xash3DFWGS-i386.AppImage xash3d-mingw.7z ccache_stats.log; fi diff --git a/common/boneinfo.h b/common/boneinfo.h new file mode 100644 index 00000000..bd58845e --- /dev/null +++ b/common/boneinfo.h @@ -0,0 +1,25 @@ +/* +boneinfo.h - structure that send delta-compressed bones across network +Copyright (C) 2018 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#ifndef BONEINFO_H +#define BONEINFO_H + +typedef struct +{ + vec3_t angles; + vec3_t origin; +} boneinfo_t; + +#endif//BONEINFO_H \ No newline at end of file diff --git a/common/bspfile.h b/common/bspfile.h index ec1575b5..d5ecb458 100644 --- a/common/bspfile.h +++ b/common/bspfile.h @@ -74,7 +74,7 @@ BRUSH MODELS #define MAX_MAP_MARKSURFACES 524288 // can be increased without problems #else #define MAX_MAP_MODELS 768 // embedded models -#define MAX_MAP_ENTSTRING 0x80000 // 512 kB should be enough +#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough #define MAX_MAP_PLANES 65536 // can be increased without problems #define MAX_MAP_NODES 32767 // because negative shorts are leafs #define MAX_MAP_CLIPNODES 32767 // because negative shorts are contents @@ -117,14 +117,14 @@ BRUSH MODELS #define LUMP_FACEINFO 1 // landscape and lightmap resolution info #define LUMP_CUBEMAPS 2 // cubemap description #define LUMP_VERTNORMALS 3 // phong shaded vertex normals -#define LUMP_VERTEX_LIGHT 4 // contain compressed light cubes per empty leafs +#define LUMP_LEAF_LIGHTING 4 // store vertex lighting for statics #define LUMP_WORLDLIGHTS 5 // list of all the virtual and real lights (used to relight models in-game) -#define LUMP_COLLISION 6 // physics engine collision hull dump -#define LUMP_AINODEGRAPH 7 // node graph that stored into the bsp +#define LUMP_COLLISION 6 // physics engine collision hull dump (userdata) +#define LUMP_AINODEGRAPH 7 // node graph that stored into the bsp (userdata) #define LUMP_SHADOWMAP 8 // contains shadow map for direct light -#define LUMP_UNUSED1 9 // one lump reserved for me -#define LUMP_UNUSED2 10 // one lump reserved for me -#define LUMP_UNUSED3 11 // one lump reserved for me +#define LUMP_VERTEX_LIGHT 9 // store vertex lighting for statics +#define LUMP_UNUSED0 10 // one lump reserved for me +#define LUMP_UNUSED1 11 // one lump reserved for me #define EXTRA_LUMPS 12 // count of the extra lumps // texture flags @@ -132,6 +132,7 @@ BRUSH MODELS #define TEX_WORLD_LUXELS BIT( 1 ) // alternative lightmap matrix will be used (luxels per world units instead of luxels per texels) #define TEX_AXIAL_LUXELS BIT( 2 ) // force world luxels to axial positive scales #define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel +#define TEX_SCROLL BIT( 6 ) // Doom special FX // ambient sound types enum diff --git a/common/com_model.h b/common/com_model.h index d71e98fa..6642722c 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -166,6 +166,7 @@ struct decal_s // Xash3D specific vec3_t position; // location of the decal center in world space. glpoly_t *polys; // precomputed decal vertices + int reserved[4]; // just for future expansions or mod-makers }; typedef struct mleaf_s @@ -366,7 +367,7 @@ typedef struct player_info_s int userid; // User id on server char userinfo[MAX_INFO_STRING]; // User info string char name[MAX_SCOREBOARDNAME]; // Name (extracted from userinfo) - int spectator; // Spectator or not, unused + int spectator; // Spectator or not, unused (frags for quake demo playback) int ping; int packet_loss; diff --git a/common/defaults.h b/common/defaults.h index 8498eca1..7eb68476 100644 --- a/common/defaults.h +++ b/common/defaults.h @@ -21,7 +21,7 @@ GNU General Public License for more details. /* =================================================================== -SETUP BACKENDS DEFINATIONS +SETUP BACKENDS DEFINITIONS =================================================================== */ diff --git a/common/event_api.h b/common/event_api.h index 20e50705..699310d0 100644 --- a/common/event_api.h +++ b/common/event_api.h @@ -51,6 +51,8 @@ typedef struct event_api_s struct pmtrace_s *( *EV_VisTraceLine )( float *start, float *end, int flags ); struct physent_s *( *EV_GetVisent )( int idx ); int ( *EV_TestLine)( const vec3_t start, const vec3_t end, int flags ); + void ( *EV_PushTraceBounds)( int hullnum, const float *mins, const float *maxs ); + void ( *EV_PopTraceBounds)( void ); } event_api_t; #endif//EVENT_API_H \ No newline at end of file diff --git a/common/gameinfo.h b/common/gameinfo.h index 511b3718..aacc74d3 100644 --- a/common/gameinfo.h +++ b/common/gameinfo.h @@ -17,6 +17,7 @@ GNU General Public License for more details. #define GAMEINFO_H #define GFL_NOMODELS (1<<0) +#define GFL_NOSKILLS (1<<1) /* ======================================================================== diff --git a/common/net_api.h b/common/net_api.h index 86d90ba1..956b16ef 100644 --- a/common/net_api.h +++ b/common/net_api.h @@ -28,6 +28,9 @@ // kill the request hook after receiving the first response #define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 ) +struct net_response_s; +typedef void (*net_api_response_func_t) ( struct net_response_s *response ); + #define NET_SUCCESS ( 0 ) #define NET_ERROR_TIMEOUT ( 1<<0 ) #define NET_ERROR_PROTO_UNSUPPORTED ( 1<<1 ) @@ -58,8 +61,6 @@ typedef struct net_response_s void *response; } net_response_t; -typedef void (*net_api_response_func_t) ( net_response_t *response ); - typedef struct net_status_s { // Connected to remote server? 1 == yes, 0 otherwise @@ -83,12 +84,12 @@ typedef struct net_api_s // APIs void (*InitNetworking)( void ); void (*Status )( struct net_status_s *status ); - void (*SendRequest)( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response ); + void (*SendRequest)( int context, int request, int flags, double timeout, struct netadr_s *remote_address, net_api_response_func_t response ); void (*CancelRequest)( int context ); void (*CancelAllRequests)( void ); - char *(*AdrToString)( netadr_t *a ); - int ( *CompareAdr)( netadr_t *a, netadr_t *b ); - int ( *StringToAdr)( char *s, netadr_t *a ); + char *(*AdrToString)( struct netadr_s *a ); + int ( *CompareAdr)( struct netadr_s *a, struct netadr_s *b ); + int ( *StringToAdr)( char *s, struct netadr_s *a ); const char *(*ValueForKey)( const char *s, const char *key ); void (*RemoveKey)( char *s, const char *key ); void (*SetValueForKey)( char *s, const char *key, const char *value, int maxsize ); diff --git a/common/port.h b/common/port.h index a0de7c40..79ef55eb 100644 --- a/common/port.h +++ b/common/port.h @@ -67,15 +67,16 @@ GNU General Public License for more details. #define SERVERDLL "libserver" POSTFIX "." OS_LIB_EXT #define GAMEPATH "/sdcard/xash" #else - #define MENUDLL "libxashmenu" ARCH_SUFFIX "." OS_LIB_EXT - #define CLIENTDLL "client" ARCH_SUFFIX "." OS_LIB_EXT + #define MENUDLL "libmenu" ARCH_SUFFIX "." OS_LIB_EXT + #define CLIENTDLL "client" ARCH_SUFFIX "." OS_LIB_EXT #endif #define VGUI_SUPPORT_DLL "libvgui_support." OS_LIB_EXT // Windows-specific #define __cdecl - #define __stdcall + #define __stdcall + #define _inline static inline #define O_BINARY 0 // O_BINARY is Windows extension #define O_TEXT 0 // O_TEXT is Windows extension @@ -118,6 +119,7 @@ GNU General Public License for more details. #define strncasecmp _strnicmp #define open _open #define read _read + #define alloca _alloca // shut-up compiler warnings #pragma warning(disable : 4244) // MIPS diff --git a/common/render_api.h b/common/render_api.h index 2e0776ca..f8c9ecf5 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -40,7 +40,7 @@ GNU General Public License for more details. #define PARM_TEX_MIPCOUNT 15 // count of mipmaps (0 - autogenerated, 1 - disabled of mipmapping) #define PARM_BSP2_SUPPORTED 16 // tell custom renderer what engine is support BSP2 in this build #define PARM_SKY_SPHERE 17 // sky is quake sphere ? -//reserved +#define PARAM_GAMEPAUSED 18 // game is paused #define PARM_MAP_HAS_DELUXE 19 // map has deluxedata #define PARM_MAX_ENTITIES 20 #define PARM_WIDESCREEN 21 @@ -74,12 +74,13 @@ enum typedef enum { + TF_COLORMAP = 0, // just for tabulate source TF_NEAREST = (1<<0), // disable texfilter TF_KEEP_SOURCE = (1<<1), // some images keep source TF_NOFLIP_TGA = (1<<2), // Steam background completely ignore tga attribute 0x20 TF_EXPAND_SOURCE = (1<<3), // Don't keep source as 8-bit expand to RGBA - TF_TEXTURE_2D_ARRAY = (1<<4), // this is 2D texture array (multi-layers) - TF_TEXTURE_RECTANGLE= (1<<5), // this is GL_TEXTURE_RECTANGLE + TF_ALLOW_EMBOSS = (1<<4), // Allow emboss-mapping for this image + TF_RECTANGLE = (1<<5), // this is GL_TEXTURE_RECTANGLE TF_CUBEMAP = (1<<6), // it's cubemap texture TF_DEPTHMAP = (1<<7), // custom texture filter used TF_QUAKEPAL = (1<<8), // image has an quake1 palette @@ -92,11 +93,11 @@ typedef enum TF_NORMALMAP = (1<<15), // is a normalmap TF_HAS_ALPHA = (1<<16), // image has alpha (used only for GL_CreateTexture) TF_FORCE_COLOR = (1<<17), // force upload monochrome textures as RGB (detail textures) - TF_TEXTURE_1D = (1<<18), // this is GL_TEXTURE_1D +// reserved TF_BORDER = (1<<19), // zero clamp for projected textures TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page -// reserved + TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C // reserved // reserved TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage @@ -185,16 +186,16 @@ typedef struct render_api_s void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only) // AVIkit support - void *(*AVI_LoadVideo)( const char *filename ); + void *(*AVI_LoadVideo)( const char *filename, qboolean load_audio ); int (*AVI_GetVideoInfo)( void *Avi, long *xres, long *yres, float *duration ); long (*AVI_GetVideoFrameNumber)( void *Avi, float time ); byte *(*AVI_GetVideoFrame)( void *Avi, long frame ); void (*AVI_UploadRawFrame)( int texture, int cols, int rows, int width, int height, const byte *data ); void (*AVI_FreeVideo)( void *Avi ); int (*AVI_IsActive)( void *Avi ); + void (*AVI_StreamSound)( void *Avi, int entnum, float fvol, float attn, float synctime ); void (*AVI_Reserved0)( void ); // for potential interface expansion without broken compatibility void (*AVI_Reserved1)( void ); - void (*AVI_Reserved2)( void ); // glState related calls (must use this instead of normal gl-calls to prevent de-synchornize local states between engine and the client) void (*GL_Bind)( int tmu, unsigned int texnum ); @@ -206,20 +207,20 @@ typedef struct render_api_s void (*GL_TextureTarget)( unsigned int target ); // change texture unit mode without bind texture void (*GL_TexCoordArrayMode)( unsigned int texmode ); void* (*GL_GetProcAddress)( const char *name ); + void (*GL_UpdateTexSize)( int texnum, int width, int height, int depth ); // recalc statistics void (*GL_Reserved0)( void ); // for potential interface expansion without broken compatibility void (*GL_Reserved1)( void ); - void (*GL_Reserved2)( void ); // Misc renderer functions void (*GL_DrawParticles)( const struct ref_viewpass_s *rvp, qboolean trans_pass, float frametime ); void (*EnvShot)( const float *vieworg, const char *name, qboolean skyshot, int shotsize ); // store skybox into gfx\env folder int (*SPR_LoadExt)( const char *szPicName, unsigned int texFlags ); // extended version of SPR_Load - colorVec (*LightVec)( const float *start, const float *end, float *lightspot ); + colorVec (*LightVec)( const float *start, const float *end, float *lightspot, float *lightvec ); struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e ); const struct ref_overview_s *( *GetOverviewParms )( void ); const char *( *GetFileByIndex )( int fileindex ); - void (*R_Reserved1)( void ); // for potential interface expansion without broken compatibility - void (*R_Reserved2)( void ); + void (*R_Reserved0)( void ); // for potential interface expansion without broken compatibility + void (*R_Reserved1)( void ); // static allocations void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ); diff --git a/common/wadfile.h b/common/wadfile.h index b96b3658..646153b9 100644 --- a/common/wadfile.h +++ b/common/wadfile.h @@ -55,17 +55,6 @@ infotable dlumpinfo_t[dwadinfo_t->numlumps] #define TYP_COLORMAP2 69 // old stuff. build palette from LBM file (not used) #define TYP_QFONT 70 // half-life font (qfont_t) -// dlumpinfo_t->img_type -#define IMG_DIFFUSE 0 // same as default pad1 always equal 0 -#define IMG_ALPHAMASK 1 // alpha-channel that stored separate as luminance texture -#define IMG_NORMALMAP 2 // indexed normalmap -#define IMG_GLOSSMAP 3 // luminance or color specularity map -#define IMG_GLOSSPOWER 4 // gloss power map (each value is a specular pow) -#define IMG_HEIGHTMAP 5 // heightmap (for parallax occlusion mapping or source of normalmap) -#define IMG_LUMA 6 // luma or glow texture with self-illuminated parts -#define IMG_DECAL_ALPHA 7 // it's a decal texture (last color in palette is base color, and other colors his graduations) -#define IMG_DECAL_COLOR 8 // decal without alpha-channel uses base, like 127 127 127 as transparent color - /* ======================================================================== diff --git a/contrib/a1batross/xash3d.config b/contrib/a1batross/xash3d.config new file mode 100644 index 00000000..c69ac0ac --- /dev/null +++ b/contrib/a1batross/xash3d.config @@ -0,0 +1,3 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define XASH_SDL diff --git a/contrib/a1batross/xash3d.creator b/contrib/a1batross/xash3d.creator new file mode 100644 index 00000000..e94cbbd3 --- /dev/null +++ b/contrib/a1batross/xash3d.creator @@ -0,0 +1 @@ +[General] diff --git a/contrib/a1batross/xash3d.creator.user b/contrib/a1batross/xash3d.creator.user new file mode 100644 index 00000000..d4368eae --- /dev/null +++ b/contrib/a1batross/xash3d.creator.user @@ -0,0 +1,218 @@ + + + + + + EnvironmentId + {e98eea9b-9ef7-4df9-8f97-1e67893b8b3b} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {cc7c1b7f-457b-4e71-9eeb-5e67c737c51a} + 0 + 0 + 0 + + /home/a1ba/projects/xash/xash3d-fwgs + + + true + configure --vgui=vgui-dev --win-style-install --prefix=/home/a1ba/projects/builtXash + ./waf + %{buildDir} + Особый + + ProjectExplorer.ProcessStep + + + + false + build -j5 -v + ./waf + true + Сборка + + GenericProjectManager.GenericMakeStep + + 2 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + + ./waf + true + Сборка + + GenericProjectManager.GenericMakeStep + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig + + По умолчанию + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + + true + install + ./waf + %{buildDir} + Особый + + ProjectExplorer.ProcessStep + + 1 + Установка + + ProjectExplorer.BuildSteps.Deploy + + 1 + Локальная установка + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + LD_LIBRARY_PATH=/home/a1ba/projects/builtXash + + -dev 5 + /home/a1ba/projects/builtXash/xash3d + /home/a1ba/projects/builtXash + Запуск /home/a1ba/projects/builtXash/xash3d + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/contrib/a1batross/xash3d.files b/contrib/a1batross/xash3d.files new file mode 100644 index 00000000..03ccce6d --- /dev/null +++ b/contrib/a1batross/xash3d.files @@ -0,0 +1,397 @@ +common/backends.h +common/beamdef.h +common/boneinfo.h +common/bspfile.h +common/cl_entity.h +common/com_model.h +common/con_nprint.h +common/const.h +common/cvardef.h +common/defaults.h +common/demo_api.h +common/dlight.h +common/enginefeatures.h +common/entity_state.h +common/entity_types.h +common/event_api.h +common/event_args.h +common/event_flags.h +common/gameinfo.h +common/hltv.h +common/ivoicetweak.h +common/kbutton.h +common/lightstyle.h +common/mathlib.h +common/net_api.h +common/netadr.h +common/particledef.h +common/pmtrace.h +common/port.h +common/qfont.h +common/r_efx.h +common/r_studioint.h +common/ref_params.h +common/render_api.h +common/screenfade.h +common/studio_event.h +common/triangleapi.h +common/usercmd.h +common/wadfile.h +common/weaponinfo.h +common/wrect.h +common/xash3d_types.h +engine/alias.h +engine/anorms.h +engine/cdll_exp.h +engine/cdll_int.h +engine/client/avi/avi.h +engine/client/avi/avi_stub.c +engine/client/avi/avi_win.c +engine/client/cl_cmds.c +engine/client/cl_custom.c +engine/client/cl_debug.c +engine/client/cl_demo.c +engine/client/cl_events.c +engine/client/cl_frame.c +engine/client/cl_game.c +engine/client/cl_gameui.c +engine/client/cl_main.c +engine/client/cl_mobile.c +engine/client/cl_netgraph.c +engine/client/cl_parse.c +engine/client/cl_pmove.c +engine/client/cl_qparse.c +engine/client/cl_remap.c +engine/client/cl_scrn.c +engine/client/cl_tent.c +engine/client/cl_tent.h +engine/client/cl_video.c +engine/client/cl_view.c +engine/client/client.h +engine/client/console.c +engine/client/gl_alias.c +engine/client/gl_backend.c +engine/client/gl_beams.c +engine/client/gl_cull.c +engine/client/gl_decals.c +engine/client/gl_draw.c +engine/client/gl_export.h +engine/client/gl_frustum.c +engine/client/gl_frustum.h +engine/client/gl_image.c +engine/client/gl_local.h +engine/client/gl_refrag.c +engine/client/gl_rlight.c +engine/client/gl_rmain.c +engine/client/gl_rmath.c +engine/client/gl_rmisc.c +engine/client/gl_rpart.c +engine/client/gl_rsurf.c +engine/client/gl_sprite.c +engine/client/gl_studio.c +engine/client/gl_warp.c +engine/client/in_evdev.c +engine/client/in_joy.c +engine/client/in_touch.c +engine/client/input.c +engine/client/input.h +engine/client/keys.c +engine/client/mod_dbghulls.c +engine/client/s_dsp.c +engine/client/s_load.c +engine/client/s_main.c +engine/client/s_mix.c +engine/client/s_mouth.c +engine/client/s_stream.c +engine/client/s_utils.c +engine/client/s_vox.c +engine/client/sound.h +engine/client/titles.c +engine/client/vgui/vgui_draw.c +engine/client/vgui/vgui_draw.h +engine/client/vgui/vgui_main.h +engine/client/vid_common.c +engine/client/vid_common.h +engine/client/vox.h +engine/common/base_cmd.c +engine/common/base_cmd.h +engine/common/build.c +engine/common/cfgscript.c +engine/common/cmd.c +engine/common/com_strings.h +engine/common/common.c +engine/common/common.h +engine/common/con_utils.c +engine/common/crashhandler.c +engine/common/crclib.c +engine/common/crtlib.c +engine/common/crtlib.h +engine/common/custom.c +engine/common/cvar.c +engine/common/cvar.h +engine/common/dedicated.c +engine/common/filesystem.c +engine/common/filesystem.h +engine/common/gamma.c +engine/common/host.c +engine/common/host_state.c +engine/common/hpak.c +engine/common/identification.c +engine/common/imagelib/imagelib.h +engine/common/imagelib/img_bmp.c +engine/common/imagelib/img_dds.c +engine/common/imagelib/img_main.c +engine/common/imagelib/img_quant.c +engine/common/imagelib/img_tga.c +engine/common/imagelib/img_utils.c +engine/common/imagelib/img_wad.c +engine/common/infostring.c +engine/common/launcher.c +engine/common/lib_common.c +engine/common/library.h +engine/common/masterlist.c +engine/common/mathlib.c +engine/common/mathlib.h +engine/common/matrixlib.c +engine/common/mod_bmodel.c +engine/common/mod_local.h +engine/common/mod_studio.c +engine/common/model.c +engine/common/net_buffer.c +engine/common/net_buffer.h +engine/common/net_chan.c +engine/common/net_encode.c +engine/common/net_encode.h +engine/common/net_ws.c +engine/common/net_ws.h +engine/common/netchan.h +engine/common/pm_debug.c +engine/common/pm_local.h +engine/common/pm_surface.c +engine/common/pm_trace.c +engine/common/protocol.h +engine/common/sequence.c +engine/common/soundlib/libmpg/dct36.c +engine/common/soundlib/libmpg/dct64.c +engine/common/soundlib/libmpg/fmt123.h +engine/common/soundlib/libmpg/format.c +engine/common/soundlib/libmpg/frame.c +engine/common/soundlib/libmpg/frame.h +engine/common/soundlib/libmpg/getbits.h +engine/common/soundlib/libmpg/huffman.h +engine/common/soundlib/libmpg/index.c +engine/common/soundlib/libmpg/index.h +engine/common/soundlib/libmpg/layer3.c +engine/common/soundlib/libmpg/libmpg.c +engine/common/soundlib/libmpg/libmpg.h +engine/common/soundlib/libmpg/mpeghead.h +engine/common/soundlib/libmpg/mpg123.c +engine/common/soundlib/libmpg/mpg123.h +engine/common/soundlib/libmpg/parse.c +engine/common/soundlib/libmpg/reader.c +engine/common/soundlib/libmpg/reader.h +engine/common/soundlib/libmpg/sample.h +engine/common/soundlib/libmpg/synth.c +engine/common/soundlib/libmpg/synth.h +engine/common/soundlib/libmpg/tabinit.c +engine/common/soundlib/snd_main.c +engine/common/soundlib/snd_mp3.c +engine/common/soundlib/snd_utils.c +engine/common/soundlib/snd_wav.c +engine/common/soundlib/soundlib.h +engine/common/sys_con.c +engine/common/system.c +engine/common/system.h +engine/common/world.c +engine/common/world.h +engine/common/zone.c +engine/custom.h +engine/customentity.h +engine/edict.h +engine/eiface.h +engine/keydefs.h +engine/menu_int.h +engine/mobility_int.h +engine/physint.h +engine/platform/android/lib_android.c +engine/platform/android/lib_android.h +engine/platform/apple/lib_ios.c +engine/platform/apple/lib_ios.h +engine/platform/emscripten/lib_em.c +engine/platform/emscripten/lib_em.h +engine/platform/platform.h +engine/platform/posix/lib_posix.c +engine/platform/sdl/events.c +engine/platform/sdl/events.h +engine/platform/sdl/in_sdl.c +engine/platform/sdl/s_sdl.c +engine/platform/sdl/vid_sdl.c +engine/platform/win32/con_win.c +engine/platform/win32/lib_win.c +engine/progdefs.h +engine/sequence.h +engine/server/server.h +engine/server/sv_client.c +engine/server/sv_cmds.c +engine/server/sv_custom.c +engine/server/sv_frame.c +engine/server/sv_game.c +engine/server/sv_init.c +engine/server/sv_log.c +engine/server/sv_main.c +engine/server/sv_move.c +engine/server/sv_phys.c +engine/server/sv_pmove.c +engine/server/sv_save.c +engine/server/sv_world.c +engine/shake.h +engine/sprite.h +engine/studio.h +engine/vgui_api.h +engine/warpsin.h +engine/wscript +game_launch/game.cpp +game_launch/game.rc +game_launch/wscript +mainui/Android.mk +mainui/BMPUtils.h +mainui/BaseMenu.cpp +mainui/BaseMenu.h +mainui/Btns.cpp +mainui/BtnsBMPTable.h +mainui/CFGScript.cpp +mainui/CFGScript.h +mainui/Color.cpp +mainui/Color.h +mainui/Coord.h +mainui/EngineCallback.cpp +mainui/EventSystem.cpp +mainui/EventSystem.h +mainui/MenuStrings.cpp +mainui/MenuStrings.h +mainui/Primitive.h +mainui/Scissor.cpp +mainui/Scissor.h +mainui/Utils.cpp +mainui/Utils.h +mainui/controls/Action.cpp +mainui/controls/Action.h +mainui/controls/BackgroundBitmap.cpp +mainui/controls/BackgroundBitmap.h +mainui/controls/BaseClientWindow.cpp +mainui/controls/BaseClientWindow.h +mainui/controls/BaseItem.cpp +mainui/controls/BaseItem.h +mainui/controls/BaseWindow.cpp +mainui/controls/BaseWindow.h +mainui/controls/Bitmap.cpp +mainui/controls/Bitmap.h +mainui/controls/CheckBox.cpp +mainui/controls/CheckBox.h +mainui/controls/Editable.cpp +mainui/controls/Editable.h +mainui/controls/Field.cpp +mainui/controls/Field.h +mainui/controls/Framework.cpp +mainui/controls/Framework.h +mainui/controls/ItemsHolder.cpp +mainui/controls/ItemsHolder.h +mainui/controls/MessageBox.cpp +mainui/controls/MessageBox.h +mainui/controls/PicButton.cpp +mainui/controls/PicButton.h +mainui/controls/PlayerModelView.cpp +mainui/controls/PlayerModelView.h +mainui/controls/ProgressBar.cpp +mainui/controls/ProgressBar.h +mainui/controls/ScrollView.cpp +mainui/controls/ScrollView.h +mainui/controls/Slider.cpp +mainui/controls/Slider.h +mainui/controls/SpinControl.cpp +mainui/controls/SpinControl.h +mainui/controls/Switch.cpp +mainui/controls/Switch.h +mainui/controls/TabView.cpp +mainui/controls/TabView.h +mainui/controls/Table.cpp +mainui/controls/Table.h +mainui/controls/YesNoMessageBox.cpp +mainui/controls/YesNoMessageBox.h +mainui/enginecallback_menu.h +mainui/extdll_menu.h +mainui/font/BaseFontBackend.cpp +mainui/font/BaseFontBackend.h +mainui/font/BitmapFont.cpp +mainui/font/BitmapFont.h +mainui/font/FontManager.cpp +mainui/font/FontManager.h +mainui/font/FontRenderer.h +mainui/font/FreeTypeFont.cpp +mainui/font/FreeTypeFont.h +mainui/font/StbFont.cpp +mainui/font/StbFont.h +mainui/font/WinAPIFont.cpp +mainui/font/WinAPIFont.h +mainui/font/stb_truetype.h +mainui/legacy/menu_playdemo.cpp +mainui/legacy/menu_playrec.cpp +mainui/legacy/menu_recdemo.cpp +mainui/menufont.h +mainui/menus/AdvancedControls.cpp +mainui/menus/Audio.cpp +mainui/menus/Configuration.cpp +mainui/menus/ConnectionProgress.cpp +mainui/menus/ConnectionProgress.h +mainui/menus/ConnectionWarning.cpp +mainui/menus/ConnectionWarning.h +mainui/menus/Controls.cpp +mainui/menus/CreateGame.cpp +mainui/menus/Credits.cpp +mainui/menus/CustomGame.cpp +mainui/menus/FileDialog.cpp +mainui/menus/GameOptions.cpp +mainui/menus/Gamepad.cpp +mainui/menus/InputDevices.cpp +mainui/menus/LoadGame.cpp +mainui/menus/Main.cpp +mainui/menus/Multiplayer.cpp +mainui/menus/NewGame.cpp +mainui/menus/PlayerIntroduceDialog.cpp +mainui/menus/PlayerIntroduceDialog.h +mainui/menus/PlayerSetup.cpp +mainui/menus/SaveLoad.cpp +mainui/menus/ServerBrowser.cpp +mainui/menus/Touch.cpp +mainui/menus/TouchButtons.cpp +mainui/menus/TouchEdit.cpp +mainui/menus/TouchOptions.cpp +mainui/menus/Video.cpp +mainui/menus/VideoModes.cpp +mainui/menus/VideoOptions.cpp +mainui/menus/Zoo.cpp +mainui/menus/dynamic/ScriptMenu.cpp +mainui/model/BaseArrayModel.h +mainui/model/BaseModel.h +mainui/model/StringArrayModel.h +mainui/udll_int.cpp +mainui/utl/unicode_strtools.cpp +mainui/utl/unicode_strtools.h +mainui/utl/utlmemory.h +mainui/utl/utlrbtree.h +mainui/utl/utlvector.h +mainui/wscript +pm_shared/pm_defs.h +pm_shared/pm_info.h +pm_shared/pm_movevars.h +vgui_support/utlmemory.h +vgui_support/utlrbtree.h +vgui_support/utlvector.h +vgui_support/vgui_clip.cpp +vgui_support/vgui_font.cpp +vgui_support/vgui_input.cpp +vgui_support/vgui_int.cpp +vgui_support/vgui_main.h +vgui_support/vgui_surf.cpp +vgui_support/wscript +wscript diff --git a/contrib/a1batross/xash3d.includes b/contrib/a1batross/xash3d.includes new file mode 100644 index 00000000..347c1e9b --- /dev/null +++ b/contrib/a1batross/xash3d.includes @@ -0,0 +1,19 @@ +engine +engine/client +engine/client/avi +engine/client/vgui +engine/common +engine/common/imagelib +engine/common/soundlib +engine/common/soundlib/libmpg +engine/server +mainui +mainui/controls +mainui/font +mainui/menus +mainui/model +mainui/utl +pm_shared +vgui_support +common +/usr/include/SDL2 diff --git a/contib/mittorn/Makefile.linux b/contrib/mittorn/Makefile.linux similarity index 100% rename from contib/mittorn/Makefile.linux rename to contrib/mittorn/Makefile.linux diff --git a/contib/mittorn/README.md b/contrib/mittorn/README.md similarity index 100% rename from contib/mittorn/README.md rename to contrib/mittorn/README.md diff --git a/contib/mittorn/setup.sh b/contrib/mittorn/setup.sh similarity index 100% rename from contib/mittorn/setup.sh rename to contrib/mittorn/setup.sh diff --git a/contib/mittorn/wscript b/contrib/mittorn/wscript similarity index 100% rename from contib/mittorn/wscript rename to contrib/mittorn/wscript diff --git a/engine/cdll_exp.h b/engine/cdll_exp.h index a6d200d0..240d9c25 100644 --- a/engine/cdll_exp.h +++ b/engine/cdll_exp.h @@ -15,17 +15,13 @@ GNU General Public License for more details. #ifndef CDLL_EXP_H #define CDLL_EXP_H -typedef struct r_studio_interface_s r_studio_interface_t; -typedef struct engine_studio_api_s engine_studio_api_t; -typedef struct mstudioevent_s mstudioevent_t; -typedef struct local_state_s local_state_t; -typedef struct playermove_s playermove_t; -typedef struct tempent_s tempent_t; -typedef struct physent_s physent_t; -typedef struct pmtrace_s pmtrace_t; -typedef struct usercmd_s usercmd_t; -typedef struct netadr_s netadr_t; - +struct tempent_s; +struct usercmd_s; +struct physent_s; +struct playermove_s; +struct mstudioevent_s; +struct engine_studio_api_s; +struct r_studio_interface_s; // NOTE: ordering is important! typedef struct cldll_func_s @@ -36,15 +32,15 @@ typedef struct cldll_func_s int (*pfnRedraw)( float flTime, int intermission ); int (*pfnUpdateClientData)( client_data_t *cdata, float flTime ); void (*pfnReset)( void ); - void (*pfnPlayerMove)( playermove_t *ppmove, int server ); - void (*pfnPlayerMoveInit)( playermove_t *ppmove ); + void (*pfnPlayerMove)( struct playermove_s *ppmove, int server ); + void (*pfnPlayerMoveInit)( struct playermove_s *ppmove ); char (*pfnPlayerMoveTexture)( char *name ); void (*IN_ActivateMouse)( void ); void (*IN_DeactivateMouse)( void ); void (*IN_MouseEvent)( int mstate ); void (*IN_ClearStates)( void ); void (*IN_Accumulate)( void ); - void (*CL_CreateMove)( float frametime, usercmd_t *cmd, int active ); + void (*CL_CreateMove)( float frametime, struct usercmd_s *cmd, int active ); int (*CL_IsThirdPerson)( void ); void (*CL_CameraOffset)( float *ofs ); // unused void *(*KB_Find)( const char *name ); @@ -54,26 +50,26 @@ typedef struct cldll_func_s void (*pfnCreateEntities)( void ); void (*pfnDrawNormalTriangles)( void ); void (*pfnDrawTransparentTriangles)( void ); - void (*pfnStudioEvent)( const mstudioevent_t *event, const cl_entity_t *entity ); - void (*pfnPostRunCmd)( local_state_t *from, local_state_t *to, usercmd_t *cmd, int runfuncs, double time, unsigned int random_seed ); + void (*pfnStudioEvent)( const struct mstudioevent_s *event, const cl_entity_t *entity ); + void (*pfnPostRunCmd)( struct local_state_s *from, struct local_state_s *to, usercmd_t *cmd, int runfuncs, double time, unsigned int random_seed ); void (*pfnShutdown)( void ); void (*pfnTxferLocalOverrides)( entity_state_t *state, const clientdata_t *client ); void (*pfnProcessPlayerState)( entity_state_t *dst, const entity_state_t *src ); void (*pfnTxferPredictionData)( entity_state_t *ps, const entity_state_t *pps, clientdata_t *pcd, const clientdata_t *ppcd, weapon_data_t *wd, const weapon_data_t *pwd ); void (*pfnDemo_ReadBuffer)( int size, byte *buffer ); - int (*pfnConnectionlessPacket)( const netadr_t *net_from, const char *args, char *buffer, int *size ); + int (*pfnConnectionlessPacket)( const struct netadr_s *net_from, const char *args, char *buffer, int *size ); int (*pfnGetHullBounds)( int hullnumber, float *mins, float *maxs ); void (*pfnFrame)( double time ); int (*pfnKey_Event)( int eventcode, int keynum, const char *pszCurrentBinding ); - void (*pfnTempEntUpdate)( double frametime, double client_time, double cl_gravity, tempent_t **ppTempEntFree, tempent_t **ppTempEntActive, int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( *Callback_TempEntPlaySound )( tempent_t *pTemp, float damp )); + void (*pfnTempEntUpdate)( double frametime, double client_time, double cl_gravity, struct tempent_s **ppTempEntFree, struct tempent_s **ppTempEntActive, int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( *Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp )); cl_entity_t *(*pfnGetUserEntity)( int index ); void (*pfnVoiceStatus)( int entindex, qboolean bTalking ); void (*pfnDirectorMessage)( int iSize, void *pbuf ); - int (*pfnGetStudioModelInterface)( int version, r_studio_interface_t **ppinterface, engine_studio_api_t *pstudio ); + int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio ); void (*pfnChatInputPosition)( int *x, int *y ); // Xash3D extension int (*pfnGetRenderInterface)( int version, render_api_t *renderfuncs, render_interface_t *callback ); - void (*pfnClipMoveToEntity)( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr ); + void (*pfnClipMoveToEntity)( struct physent_s *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, struct pmtrace_s *tr ); // Xash3D FWGS extension int (*pfnTouchEvent)( int type, int fingerID, float x, float y, float dx, float dy ); void (*pfnMoveEvent)( float forwardmove, float sidemove ); diff --git a/engine/cdll_int.h b/engine/cdll_int.h index 3589c9e6..db6d9eb9 100644 --- a/engine/cdll_int.h +++ b/engine/cdll_int.h @@ -212,6 +212,7 @@ typedef struct cl_enginefuncs_s float (*pfnRandomFloat)( float flLow, float flHigh ); int (*pfnRandomLong)( int lLow, int lHigh ); void (*pfnHookEvent)( const char *name, void ( *pfnEvent )( struct event_args_s *args )); + int (*Con_IsVisible) (); const char *(*pfnGetGameDirectory)( void ); struct cvar_s *(*pfnGetCvarPointer)( const char *szName ); diff --git a/engine/client/avi/avi.h b/engine/client/avi/avi.h index 5b386976..6cf49dff 100644 --- a/engine/client/avi/avi.h +++ b/engine/client/avi/avi.h @@ -18,7 +18,7 @@ GNU General Public License for more details. // // avikit.c // -typedef struct movie_state_s movie_state_t; +typedef struct movie_state_s movie_state_t; long AVI_GetVideoFrameNumber( movie_state_t *Avi, float time ); byte *AVI_GetVideoFrame( movie_state_t *Avi, long frame ); qboolean AVI_GetVideoInfo( movie_state_t *Avi, long *xres, long *yres, float *duration ); @@ -26,7 +26,8 @@ qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info ); long AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, long offset, long length ); void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet ); movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ); -movie_state_t *AVI_LoadVideoNoSound( const char *filename ); +long AVI_TimeToSoundPosition( movie_state_t *Avi, long time ); +long AVI_GetVideoFrameCount( movie_state_t *Avi ); void AVI_CloseVideo( movie_state_t *Avi ); qboolean AVI_IsActive( movie_state_t *Avi ); void AVI_FreeVideo( movie_state_t *Avi ); diff --git a/engine/client/avi/avi_stub.c b/engine/client/avi/avi_stub.c index 92a7cc21..0ea1db8c 100644 --- a/engine/client/avi/avi_stub.c +++ b/engine/client/avi/avi_stub.c @@ -51,9 +51,14 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) return NULL; } -movie_state_t *AVI_LoadVideoNoSound( const char *filename ) +long AVI_TimeToSoundPosition( movie_state_t *Avi, long time ) { - return NULL; + return 0; +} + +long AVI_GetVideoFrameCount( movie_state_t *Avi ) +{ + return 0; } void AVI_CloseVideo( movie_state_t *Avi ) diff --git a/engine/client/avi/avi_win.c b/engine/client/avi/avi_win.c index 36ee99ba..616e2ca2 100644 --- a/engine/client/avi/avi_win.c +++ b/engine/client/avi/avi_win.c @@ -59,6 +59,7 @@ dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, false }; static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize ); static int (_stdcall *pAVIStreamRead)( PAVISTREAM pavi, LONG lStart, LONG lSamples, void *lpBuffer, LONG cbBuffer, LONG *plBytes, LONG *plSamples ); static PGETFRAME (_stdcall *pAVIStreamGetFrameOpen)( PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted ); +static long (_stdcall *pAVIStreamTimeToSample)( PAVISTREAM pavi, LONG lTime ); static void* (_stdcall *pAVIStreamGetFrame)( PGETFRAME pg, LONG lPos ); static int (_stdcall *pAVIStreamGetFrameClose)( PGETFRAME pg ); static dword (_stdcall *pAVIStreamRelease)( PAVISTREAM pavi ); @@ -85,6 +86,7 @@ static dllfunc_t avifile_funcs[] = { "AVIStreamReadFormat", (void **) &pAVIStreamReadFormat }, { "AVIStreamRelease", (void **) &pAVIStreamRelease }, { "AVIStreamStart", (void **) &pAVIStreamStart }, +{ "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample }, { NULL, NULL } }; @@ -142,7 +144,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) // WMA codecs, both versions - they simply don't work. if( Avi->audio_header->wFormatTag == 0x160 || Avi->audio_header->wFormatTag == 0x161 ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "ACM does not support this audio codec.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "ACM does not support this audio codec.\n" ); return false; } @@ -151,7 +154,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) if( Avi->audio_header_size < sizeof( WAVEFORMATEX )) { - if( !Avi->quiet ) MsgDev( D_ERROR, "ACM failed to open conversion stream.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" ); return false; } @@ -181,7 +185,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "ACM failed to open conversion stream.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" ); return false; } } @@ -201,13 +206,14 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) // get the size of the output buffer for streaming the compressed audio if( pacmStreamSize( Avi->cpa_conversion_stream, Avi->cpa_blockalign, &dest_length, ACM_STREAMSIZEF_SOURCE ) != MMSYSERR_NOERROR ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "Couldn't get ACM conversion stream size.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "Couldn't get ACM conversion stream size.\n" ); pacmStreamClose( Avi->cpa_conversion_stream, 0 ); return false; } - Avi->cpa_srcbuffer = (byte *)Mem_Alloc( cls.mempool, Avi->cpa_blockalign ); - Avi->cpa_dstbuffer = (byte *)Mem_Alloc( cls.mempool, dest_length ); // maintained buffer for raw data + Avi->cpa_srcbuffer = (byte *)Mem_Malloc( cls.mempool, Avi->cpa_blockalign ); + Avi->cpa_dstbuffer = (byte *)Mem_Malloc( cls.mempool, dest_length ); // maintained buffer for raw data // prep the headers! Avi->cpa_conversion_header.cbStruct = sizeof( ACMSTREAMHEADER ); @@ -224,7 +230,8 @@ qboolean AVI_ACMConvertAudio( movie_state_t *Avi ) if( pacmStreamPrepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 ) != MMSYSERR_NOERROR ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "couldn't prep headers.\n" ); + if( !Avi->quiet ) + Con_Reportf( S_ERROR "couldn't prepare stream headers.\n" ); pacmStreamClose( Avi->cpa_conversion_stream, 0 ); return false; } @@ -271,6 +278,23 @@ long AVI_GetVideoFrameNumber( movie_state_t *Avi, float time ) return (time * Avi->video_fps); } +long AVI_GetVideoFrameCount( movie_state_t *Avi ) +{ + if( !Avi->active ) + return 0; + + return Avi->video_frames; +} + +long AVI_TimeToSoundPosition( movie_state_t *Avi, long time ) +{ + if( !Avi->active || !Avi->audio_stream ) + return 0; + + // UNDONE: what about compressed audio? + return pAVIStreamTimeToSample( Avi->audio_stream, time ) * Avi->audio_bytes_per_sample; +} + // gets the raw frame data byte *AVI_GetVideoFrame( movie_state_t *Avi, long frame ) { @@ -378,8 +402,11 @@ long AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, long offset, long l } else { + // we out of soundtrack, just zeroing buffer for( i = 0; i < length; i++ ) audiodata[i] = 0; + + return length; } } @@ -482,20 +509,25 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi switch( hr ) { case AVIERR_BADFORMAT: - if( !Avi->quiet ) MsgDev( D_ERROR, "corrupt file or unknown format.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "corrupt file or unknown format.\n" ); break; case AVIERR_MEMORY: - if( !Avi->quiet ) MsgDev( D_ERROR, "insufficient memory to open file.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "insufficient memory to open file.\n" ); break; case AVIERR_FILEREAD: - if( !Avi->quiet ) MsgDev( D_ERROR, "disk error reading file.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "disk error reading file.\n" ); break; case AVIERR_FILEOPEN: - if( !Avi->quiet ) MsgDev( D_ERROR, "disk error opening file.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "disk error opening file.\n" ); break; case REGDB_E_CLASSNOTREG: default: - if( !Avi->quiet ) MsgDev( D_ERROR, "no handler found (or file not found).\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "no handler found (or file not found).\n" ); break; } return; @@ -533,7 +565,7 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi // read the audio header pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), 0, &size ); - Avi->audio_header = (WAVEFORMAT *)Mem_Alloc( cls.mempool, size ); + Avi->audio_header = (WAVEFORMAT *)Mem_Malloc( cls.mempool, size ); pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), Avi->audio_header, &size ); Avi->audio_header_size = size; Avi->audio_codec = Avi->audio_header->wFormatTag; @@ -565,7 +597,8 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi { if( Avi->pfile ) // if file is open, close it pAVIFileRelease( Avi->pfile ); - if( !Avi->quiet ) MsgDev( D_ERROR, "couldn't find a valid video stream.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "couldn't find a valid video stream.\n" ); return; } @@ -574,7 +607,8 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi if( Avi->video_getframe == NULL ) { - if( !Avi->quiet ) MsgDev( D_ERROR, "error attempting to read video frames.\n" ); + if( !Avi->quiet ) + Con_DPrintf( S_ERROR "error attempting to read video frames.\n" ); return; // couldn't open frame getter. } @@ -619,10 +653,7 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) // fast reject if( !avi_initialized ) - { - MsgDev( D_ERROR, "AVI_LoadVideo: movie support is disabled\n" ); return NULL; - } // open cinematic Q_snprintf( path, sizeof( path ), "media/%s", filename ); @@ -631,11 +662,11 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) if( FS_FileExists( path, false ) && !fullpath ) { - MsgDev( D_ERROR, "AVI_LoadVideo: Couldn't load %s from packfile. Please extract it\n", path ); + Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path ); return NULL; } - Avi = Mem_Alloc( cls.mempool, sizeof( movie_state_t )); + Avi = Mem_Malloc( cls.mempool, sizeof( movie_state_t )); AVI_OpenVideo( Avi, fullpath, load_audio, false ); if( !AVI_IsActive( Avi )) @@ -648,11 +679,6 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ) return Avi; } -movie_state_t *AVI_LoadVideoNoSound( const char *filename ) -{ - return AVI_LoadVideo( filename, false ); -} - void AVI_FreeVideo( movie_state_t *state ) { if( !state ) return; @@ -668,35 +694,29 @@ qboolean AVI_Initailize( void ) { if( Sys_CheckParm( "-noavi" )) { - MsgDev( D_INFO, "AVI: Disabled\n" ); + Con_Printf( "AVI: Disabled\n" ); return false; } if( !Sys_LoadLibrary( &avifile_dll )) - { - MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); return false; - } if( !Sys_LoadLibrary( &msvfw_dll )) { - MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); Sys_FreeLibrary( &avifile_dll ); return false; } if( !Sys_LoadLibrary( &msacm_dll )) { - MsgDev( D_ERROR, "AVI_Initailize: failed\n" ); Sys_FreeLibrary( &avifile_dll ); Sys_FreeLibrary( &msvfw_dll ); return false; } - pAVIFileInit(); avi_initialized = true; - MsgDev( D_NOTE, "AVI_Initailize: done\n" ); - + pAVIFileInit(); + return true; } diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index 4e62420b..a5d711d6 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -152,7 +152,7 @@ qboolean CL_ScreenshotGetName( int lastnum, char *filename ) if( lastnum < 0 || lastnum > 9999 ) { - MsgDev( D_ERROR, "unable to write screenshot\n" ); + Con_Printf( S_ERROR "unable to write screenshot\n" ); return false; } @@ -180,7 +180,7 @@ qboolean CL_SnapshotGetName( int lastnum, char *filename ) if( lastnum < 0 || lastnum > 9999 ) { - MsgDev( D_ERROR, "unable to write snapshot\n" ); + Con_Printf( S_ERROR "unable to write snapshot\n" ); FS_AllowDirectPaths( false ); return false; } @@ -345,7 +345,7 @@ void CL_LevelShot_f( void ) if( cls.demoplayback && ( cls.demonum != -1 )) { Q_sprintf( cls.shotname, "levelshots/%s_%s.bmp", cls.demoname, glState.wideScreen ? "16x9" : "4x3" ); - Q_snprintf( filename, sizeof( filename ), "demos/%s.dem", cls.demoname ); + Q_snprintf( filename, sizeof( filename ), "%s.dem", cls.demoname ); // make sure what levelshot is newer than demo ft1 = FS_FileTime( filename, false ); @@ -385,25 +385,6 @@ void CL_SaveShot_f( void ) cls.scrshot_action = scrshot_savegame; // build new frame for saveshot } -/* -================== -CL_DemoShot_f - -mini-pic in playdemo menu -================== -*/ -void CL_DemoShot_f( void ) -{ - if( Cmd_Argc() < 2 ) - { - Con_Printf( S_USAGE "demoshot \n" ); - return; - } - - Q_sprintf( cls.shotname, "demos/%s.bmp", Cmd_Argv( 1 )); - cls.scrshot_action = scrshot_demoshot; // build new frame for demoshot -} - /* ============== CL_DeleteDemo_f @@ -424,9 +405,8 @@ void CL_DeleteDemo_f( void ) return; } - // delete save and saveshot - FS_Delete( va( "demos/%s.dem", Cmd_Argv( 1 ))); - FS_Delete( va( "demos/%s.bmp", Cmd_Argv( 1 ))); + // delete demo + FS_Delete( va( "%s.dem", Cmd_Argv( 1 ))); } /* diff --git a/engine/client/cl_custom.c b/engine/client/cl_custom.c index 6ea718aa..a152fc25 100644 --- a/engine/client/cl_custom.c +++ b/engine/client/cl_custom.c @@ -44,19 +44,19 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource ) if( !COM_IsSafeFileToDownload( filepath )) { - MsgDev( D_REPORT, "refusing to download %s\n", filepath ); + Con_Reportf( "refusing to download %s\n", filepath ); return true; } if( !cl_allow_download.value ) { - MsgDev( D_REPORT, "Download refused, cl_allow_download is 0\n" ); + Con_Reportf( "Download refused, cl_allow_download is 0\n" ); return true; } if( cls.state == ca_active && !cl_download_ingame.value ) { - MsgDev( D_REPORT, "In-game download refused...\n" ); + Con_Reportf( "In-game download refused...\n" ); return true; } @@ -66,7 +66,7 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource ) if( cls.demoplayback ) { - MsgDev( D_WARN, "file %s missing during demo playback.\n", filepath ); + Con_Reportf( S_WARN "file %s missing during demo playback.\n", filepath ); return true; } @@ -81,7 +81,7 @@ void CL_AddToResourceList( resource_t *pResource, resource_t *pList ) { if( pResource->pPrev != NULL || pResource->pNext != NULL ) { - MsgDev( D_ERROR, "Resource already linked\n" ); + Con_Reportf( S_ERROR "Resource already linked\n" ); return; } @@ -112,7 +112,7 @@ void CL_MoveToOnHandList( resource_t *pResource ) { if( !pResource ) { - MsgDev( D_REPORT, "Null resource passed to CL_MoveToOnHandList\n" ); + Con_Reportf( "Null resource passed to CL_MoveToOnHandList\n" ); return; } diff --git a/engine/client/cl_debug.c b/engine/client/cl_debug.c new file mode 100644 index 00000000..4704b800 --- /dev/null +++ b/engine/client/cl_debug.c @@ -0,0 +1,242 @@ +/* +cl_debug.c - server message debugging +Copyright (C) 2018 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#include "common.h" +#include "client.h" +#include "net_encode.h" +#include "particledef.h" +#include "gl_local.h" +#include "cl_tent.h" +#include "shake.h" +#include "hltv.h" +#include "input.h" + +#define MSG_COUNT 32 // last 32 messages parsed +#define MSG_MASK (MSG_COUNT - 1) + +const char *svc_strings[svc_lastmsg+1] = +{ + "svc_bad", + "svc_nop", + "svc_disconnect", + "svc_event", + "svc_changing", + "svc_setview", + "svc_sound", + "svc_time", + "svc_print", + "svc_stufftext", + "svc_setangle", + "svc_serverdata", + "svc_lightstyle", + "svc_updateuserinfo", + "svc_deltatable", + "svc_clientdata", + "svc_resource", + "svc_pings", + "svc_particle", + "svc_restoresound", + "svc_spawnstatic", + "svc_event_reliable", + "svc_spawnbaseline", + "svc_temp_entity", + "svc_setpause", + "svc_signonnum", + "svc_centerprint", + "svc_unused27", + "svc_unused28", + "svc_unused29", + "svc_intermission", + "svc_finale", + "svc_cdtrack", + "svc_restore", + "svc_cutscene", + "svc_weaponanim", + "svc_bspdecal", + "svc_roomtype", + "svc_addangle", + "svc_usermessage", + "svc_packetentities", + "svc_deltapacketentities", + "svc_choke", + "svc_resourcelist", + "svc_deltamovevars", + "svc_resourcerequest", + "svc_customization", + "svc_crosshairangle", + "svc_soundfade", + "svc_filetxferfailed", + "svc_hltv", + "svc_director", + "svc_voiceinit", + "svc_voicedata", + "svc_deltapacketbones", + "svc_unused55", + "svc_resourcelocation", + "svc_querycvarvalue", + "svc_querycvarvalue2", +}; + +typedef struct +{ + int command; + int starting_offset; + int frame_number; +} oldcmd_t; + +typedef struct +{ + oldcmd_t oldcmd[MSG_COUNT]; + int currentcmd; + qboolean parsing; +} msg_debug_t; + +static msg_debug_t cls_message_debug; + +const char *CL_MsgInfo( int cmd ) +{ + static string sz; + + Q_strcpy( sz, "???" ); + + if( cmd >= 0 && cmd <= svc_lastmsg ) + { + // get engine message name + Q_strncpy( sz, svc_strings[cmd], sizeof( sz )); + } + else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES )) + { + int i; + + for( i = 0; i < MAX_USER_MESSAGES; i++ ) + { + if( clgame.msg[i].number == cmd ) + { + Q_strncpy( sz, clgame.msg[i].name, sizeof( sz )); + break; + } + } + } + return sz; +} + +/* +===================== +CL_Parse_Debug + +enable message debugging +===================== +*/ +void CL_Parse_Debug( qboolean enable ) +{ + cls_message_debug.parsing = enable; +} + +/* +===================== +CL_Parse_RecordCommand + +record new message params into debug buffer +===================== +*/ +void CL_Parse_RecordCommand( int cmd, int startoffset ) +{ + int slot; + + if( cmd == svc_nop ) return; + + slot = ( cls_message_debug.currentcmd++ & MSG_MASK ); + cls_message_debug.oldcmd[slot].command = cmd; + cls_message_debug.oldcmd[slot].starting_offset = startoffset; + cls_message_debug.oldcmd[slot].frame_number = host.framecount; +} + +/* +===================== +CL_ResetFrame +===================== +*/ +void CL_ResetFrame( frame_t *frame ) +{ + memset( &frame->graphdata, 0, sizeof( netbandwidthgraph_t )); + frame->receivedtime = host.realtime; + frame->valid = true; + frame->choked = false; + frame->latency = 0.0; + frame->time = cl.mtime[0]; +} + +/* +===================== +CL_WriteErrorMessage + +write net_message into buffer.dat for debugging +===================== +*/ +static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg ) +{ + const char *buffer_file = "buffer.dat"; + file_t *fp; + + fp = FS_Open( buffer_file, "wb", false ); + if( !fp ) return; + + FS_Write( fp, &cls.starting_count, sizeof( int )); + FS_Write( fp, ¤t_count, sizeof( int )); + FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg )); + FS_Close( fp ); + + Con_Printf( "Wrote erroneous message to %s\n", buffer_file ); +} + +/* +===================== +CL_WriteMessageHistory + +list last 32 messages for debugging net troubleshooting +===================== +*/ +void CL_WriteMessageHistory( void ) +{ + oldcmd_t *old, *failcommand; + sizebuf_t *msg = &net_message; + int i, thecmd; + + if( !cls.initialized || cls.state == ca_disconnected ) + return; + + if( !cls_message_debug.parsing ) + return; + + Con_Printf( "Last %i messages parsed.\n", MSG_COUNT ); + + // finish here + thecmd = cls_message_debug.currentcmd - 1; + thecmd -= ( MSG_COUNT - 1 ); // back up to here + + for( i = 0; i < MSG_COUNT - 1; i++ ) + { + thecmd &= MSG_MASK; + old = &cls_message_debug.oldcmd[thecmd]; + Con_Printf( "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command )); + thecmd++; + } + + failcommand = &cls_message_debug.oldcmd[thecmd]; + Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command )); + if( host_developer.value >= DEV_EXTENDED ) + CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg ); + cls_message_debug.parsing = false; +} \ No newline at end of file diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 98b5e7cd..f3e9e69a 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -126,7 +126,7 @@ void CL_StartupDemoHeader( void ) if( !cls.demoheader ) { - MsgDev( D_ERROR, "couldn't open temporary header file.\n" ); + Con_DPrintf( S_ERROR "couldn't open temporary header file.\n" ); return; } @@ -349,9 +349,9 @@ Write demo header */ void CL_WriteDemoHeader( const char *name ) { - long copysize; - long savepos; - long curpos; + int copysize; + int savepos; + int curpos; Con_Printf( "recording to %s.\n", name ); cls.demofile = FS_Open( name, "wb", false ); @@ -359,7 +359,7 @@ void CL_WriteDemoHeader( const char *name ) if( !cls.demofile ) { - MsgDev( D_ERROR, "couldn't open %s.\n", name ); + Con_Printf( S_ERROR "couldn't open %s.\n", name ); return; } @@ -380,7 +380,7 @@ void CL_WriteDemoHeader( const char *name ) FS_Write( cls.demofile, &demo.header, sizeof( demo.header )); demo.directory.numentries = 2; - demo.directory.entries = Mem_Alloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries ); + demo.directory.entries = Mem_Calloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries ); // DIRECTORY ENTRY # 0 demo.entry = &demo.directory.entries[0]; // only one here. @@ -489,7 +489,7 @@ void CL_DrawDemoRecording( void ) { char string[64]; rgba_t color = { 255, 255, 255, 255 }; - long pos; + int pos; int len; if(!( host_developer.value && cls.demorecording )) @@ -497,10 +497,10 @@ void CL_DrawDemoRecording( void ) pos = FS_Tell( cls.demofile ); Q_snprintf( string, sizeof( string ), "^1RECORDING:^7 %s: %s time: %02d:%02d", cls.demoname, - Q_memprint( pos ), (int)(cls.demotime / 60.0f ), (int)fmod( cls.demotime, 60.0f )); + Q_memprint( pos ), (int)(cls.demotime / 60.0f ), (int)fmod( cls.demotime, 60.0f )); Con_DrawStringLen( string, &len, NULL ); - Con_DrawString(( glState.width - len ) >> 1, glState.height >> 2, string, color ); + Con_DrawString(( glState.width - len ) >> 1, glState.height >> 4, string, color ); } /* @@ -626,6 +626,49 @@ void CL_ReadDemoSequence( qboolean discard ) cls.netchan.last_reliable_sequence = last_reliable_sequence; } +/* +================= +CL_DemoStartPlayback +================= +*/ +void CL_DemoStartPlayback( int mode ) +{ + if( cls.changedemo ) + { + S_StopAllSounds( true ); + SCR_BeginLoadingPlaque( false ); + + CL_ClearState (); + CL_InitEdicts (); // re-arrange edicts + } + else + { + // NOTE: at this point demo is still valid + CL_Disconnect(); + Host_ShutdownServer(); + + Con_FastClose(); + UI_SetActiveMenu( false ); + } + + cls.demoplayback = mode; + cls.state = ca_connected; + cl.background = (cls.demonum != -1) ? true : false; + cls.spectator = false; + cls.signon = 0; + + demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message + + Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize ); + + memset( demo.cmds, 0, sizeof( demo.cmds )); + demo.angle_position = 1; + demo.framecount = 0; + cls.lastoutgoingcommand = -1; + cls.nextcmdtime = host.realtime; + cl.last_command_ack = -1; +} + /* ================= CL_DemoAborted @@ -657,7 +700,7 @@ void CL_DemoCompleted( void ) CL_StopPlayback(); - if( !CL_NextDemo() && host_developer.value <= DEV_NONE ) + if( !CL_NextDemo() && !cls.changedemo ) UI_SetActiveMenu( true ); Cvar_SetValue( "v_dark", 0.0f ); @@ -705,14 +748,14 @@ qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length ) if( msglen < 0 ) { - MsgDev( D_ERROR, "Demo message length < 0\n" ); + Con_Reportf( S_ERROR "Demo message length < 0\n" ); CL_DemoCompleted(); return false; } if( msglen > MAX_INIT_MSG ) { - MsgDev( D_ERROR, "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); + Con_Reportf( S_ERROR "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); CL_DemoCompleted(); return false; } @@ -721,12 +764,14 @@ qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length ) { if( FS_Read( cls.demofile, buffer, msglen ) != msglen ) { - MsgDev( D_ERROR, "Error reading demo message data\n" ); + Con_Reportf( S_ERROR "Error reading demo message data\n" ); CL_DemoCompleted(); return false; } } + cls.netchan.last_received = host.realtime; + cls.netchan.total_received += msglen; *length = msglen; if( cls.state != ca_active ) @@ -735,6 +780,99 @@ qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length ) return true; } +/* +================= +CL_DemoReadMessageQuake + +reads demo data and write it to client +================= +*/ +qboolean CL_DemoReadMessageQuake( byte *buffer, size_t *length ) +{ + vec3_t viewangles; + int msglen = 0; + demoangle_t *a; + + *length = 0; // assume we fail + + // decide if it is time to grab the next message + if( cls.signon == SIGNONS ) // allways grab until fully connected + { + if( cls.timedemo ) + { + if( host.framecount == cls.td_lastframe ) + return false; // already read this frame's message + + cls.td_lastframe = host.framecount; + + // if this is the second frame, grab the real td_starttime + // so the bogus time on the first frame doesn't count + if( host.framecount == cls.td_startframe + 1 ) + cls.td_starttime = host.realtime; + } + else if( cl.time <= cl.mtime[0] ) + { + // don't need another message yet + return false; + } + } + + // get the next message + FS_Read( cls.demofile, &msglen, sizeof( int )); + FS_Read( cls.demofile, &viewangles[0], sizeof( float )); + FS_Read( cls.demofile, &viewangles[1], sizeof( float )); + FS_Read( cls.demofile, &viewangles[2], sizeof( float )); + cls.netchan.incoming_sequence++; + demo.timestamp = cl.mtime[0]; + cl.skip_interp = false; + + // make sure what interp info contain angles from different frames + // or lerping will stop working + if( demo.lasttime != demo.timestamp ) + { + // select entry into circular buffer + demo.angle_position = (demo.angle_position + 1) & ANGLE_MASK; + a = &demo.cmds[demo.angle_position]; + + // record update + a->starttime = demo.timestamp; + VectorCopy( viewangles, a->viewangles ); + demo.lasttime = demo.timestamp; + } + + if( msglen < 0 ) + { + Con_Reportf( S_ERROR "Demo message length < 0\n" ); + CL_DemoCompleted(); + return false; + } + + if( msglen > MAX_INIT_MSG ) + { + Con_Reportf( S_ERROR "Demo message %i > %i\n", msglen, MAX_INIT_MSG ); + CL_DemoCompleted(); + return false; + } + + if( msglen > 0 ) + { + if( FS_Read( cls.demofile, buffer, msglen ) != msglen ) + { + Con_Reportf( S_ERROR "Error reading demo message data\n" ); + CL_DemoCompleted(); + return false; + } + } + + cls.netchan.last_received = host.realtime; + cls.netchan.total_received += msglen; + *length = msglen; + + if( cls.state != ca_active ) + Cbuf_Execute(); + return true; +} + /* ================= CL_DemoReadMessage @@ -754,7 +892,6 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length ) if( !cls.demofile ) { - MsgDev( D_ERROR, "tried to read a demo message with no demo file\n" ); CL_DemoCompleted(); return false; } @@ -765,6 +902,9 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length ) return false; // paused } + if( cls.demoplayback == DEMO_QUAKE1 ) + return CL_DemoReadMessageQuake( buffer, length ); + do { qboolean bSkipMessage = false; @@ -812,7 +952,7 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length ) return false; // header is ended, skip frame case dem_userdata: FS_Read( cls.demofile, &size, sizeof( int )); - userbuf = Mem_Alloc( cls.mempool, size ); + userbuf = Mem_Malloc( cls.mempool, size ); FS_Read( cls.demofile, userbuf, size ); if( clgame.hInstance ) @@ -915,14 +1055,26 @@ but viewangles interpolate here */ void CL_DemoInterpolateAngles( void ) { - float curtime = (CL_GetDemoPlaybackClock() - demo.starttime) - host.frametime; demoangle_t *prev = NULL, *next = NULL; float frac = 0.0f; + float curtime; - if( curtime > demo.timestamp ) - curtime = demo.timestamp; // don't run too far + if( cls.demoplayback == DEMO_QUAKE1 ) + { + // manually select next & prev states + next = &demo.cmds[(demo.angle_position - 0) & ANGLE_MASK]; + prev = &demo.cmds[(demo.angle_position - 1) & ANGLE_MASK]; + if( cl.skip_interp ) *prev = *next; // camera was teleported + frac = cl.lerpFrac; + } + else + { + curtime = (CL_GetDemoPlaybackClock() - demo.starttime) - host.frametime; + if( curtime > demo.timestamp ) + curtime = demo.timestamp; // don't run too far - CL_DemoFindInterpolatedViewAngles( curtime, &frac, &prev, &next ); + CL_DemoFindInterpolatedViewAngles( curtime, &frac, &prev, &next ); + } if( prev && next ) { @@ -933,7 +1085,8 @@ void CL_DemoInterpolateAngles( void ) QuaternionSlerp( q2, q1, frac, q ); QuaternionAngle( q, cl.viewangles ); } - else VectorCopy( cl.cmd->viewangles, cl.viewangles ); + else if( cl.cmd != NULL ) + VectorCopy( cl.cmd->viewangles, cl.viewangles ); } /* @@ -976,7 +1129,8 @@ void CL_StopPlayback( void ) cls.demofile = NULL; cls.olddemonum = Q_max( -1, cls.demonum - 1 ); - Mem_Free( demo.directory.entries ); + if( demo.directory.entries != NULL ) + Mem_Free( demo.directory.entries ); cls.td_lastframe = host.framecount; demo.directory.numentries = 0; demo.directory.entries = NULL; @@ -999,6 +1153,7 @@ void CL_StopPlayback( void ) // let game known about demo state Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY ); cls.state = ca_disconnected; + cls.set_lastdemo = false; S_StopBackgroundTrack(); cls.connect_time = 0; cls.demonum = -1; @@ -1110,16 +1265,45 @@ qboolean CL_NextDemo( void ) return true; } +/* +================== +CL_CheckStartupDemos + +queue demos loop after movie playing +================== +*/ +void CL_CheckStartupDemos( void ) +{ + if( !cls.demos_pending ) + return; // no demos in loop + + if( cls.movienum != -1 ) + return; // wait until movies finished + + if( GameState->nextstate != STATE_RUNFRAME || cls.demoplayback ) + { + // commandline override + cls.demos_pending = false; + cls.demonum = -1; + return; + } + + // run demos loop in background mode + Cvar_SetValue( "v_dark", 1.0f ); + cls.demos_pending = false; + cls.demonum = 0; + CL_NextDemo (); +} + /* ================== CL_DemoGetName ================== */ -void CL_DemoGetName( int lastnum, char *filename ) +static void CL_DemoGetName( int lastnum, char *filename ) { int a, b, c, d; - if( !filename ) return; if( lastnum < 0 || lastnum > 9999 ) { // bound @@ -1148,8 +1332,8 @@ Begins recording a demo from the current position */ void CL_Record_f( void ) { + string demoname, demopath; const char *name; - string demoname, demopath, demoshot; int n; if( Cmd_Argc() == 1 ) @@ -1190,7 +1374,7 @@ void CL_Record_f( void ) for( n = 0; n < 10000; n++ ) { CL_DemoGetName( n, demoname ); - if( !FS_FileExists( va( "demos/%s.dem", demoname ), true )) + if( !FS_FileExists( va( "%s.dem", demoname ), true )) break; } @@ -1203,18 +1387,12 @@ void CL_Record_f( void ) else Q_strncpy( demoname, name, sizeof( demoname )); // open the demo file - Q_sprintf( demopath, "demos/%s.dem", demoname ); - Q_sprintf( demoshot, "demos/%s.bmp", demoname ); - - // unload previous image from memory (it's will be overwritten) - GL_FreeImage( demoshot ); + Q_sprintf( demopath, "%s.dem", demoname ); // make sure what old demo is removed - if( FS_FileExists( demopath, false )) FS_Delete( demopath ); - if( FS_FileExists( demoshot, false )) FS_Delete( demoshot ); + if( FS_FileExists( demopath, false )) + FS_Delete( demopath ); - // write demoshot for preview - Cbuf_AddText( va( "demoshot \"%s\"\n", demoname )); Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname )); Q_strncpy( gameui.globals->demoname, demoname, sizeof( gameui.globals->demoname )); @@ -1230,11 +1408,11 @@ playdemo */ void CL_PlayDemo_f( void ) { - string filename; - string demoname; - int i; + char filename[MAX_QPATH]; + char demoname[MAX_QPATH]; + int i, ident; - if( Cmd_Argc() != 2 ) + if( Cmd_Argc() < 2 ) { Con_Printf( S_USAGE "playdemo \n" ); return; @@ -1251,12 +1429,21 @@ void CL_PlayDemo_f( void ) return; } - Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ) - 1 ); - Q_snprintf( filename, sizeof( filename ), "demos/%s.dem", demoname ); + Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname )); + COM_StripExtension( demoname ); + Q_snprintf( filename, sizeof( filename ), "%s.dem", demoname ); + + // hidden parameter + if( Cmd_Argc() > 2 ) + cls.set_lastdemo = Q_atoi( Cmd_Argv( 2 )); + + // member last demo + if( cls.set_lastdemo ) + Cvar_Set( "lastdemo", demoname ); if( !FS_FileExists( filename, true )) { - MsgDev( D_ERROR, "couldn't open %s\n", filename ); + Con_Printf( S_ERROR "couldn't open %s\n", filename ); CL_DemoAborted(); return; } @@ -1265,12 +1452,34 @@ void CL_PlayDemo_f( void ) Q_strncpy( cls.demoname, demoname, sizeof( cls.demoname )); Q_strncpy( gameui.globals->demoname, demoname, sizeof( gameui.globals->demoname )); - // read in the m_DemoHeader + FS_Read( cls.demofile, &ident, sizeof( int )); + FS_Seek( cls.demofile, 0, SEEK_SET ); // rewind back to start + cls.forcetrack = 0; + + // check for quake demos + if( ident != IDEMOHEADER ) + { + int c, neg = false; + + demo.header.host_fps = host_maxfps->value; + + while(( c = FS_Getc( cls.demofile )) != '\n' ) + { + if( c == '-' ) neg = true; + else cls.forcetrack = cls.forcetrack * 10 + (c - '0'); + } + + if( neg ) cls.forcetrack = -cls.forcetrack; + CL_DemoStartPlayback( DEMO_QUAKE1 ); + return; // quake demo is started + } + + // read in the demo header FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t )); if( demo.header.id != IDEMOHEADER ) { - MsgDev( D_ERROR, "%s is not a demo file\n", filename ); + Con_Printf( S_ERROR "%s is not a demo file\n", demoname ); CL_DemoAborted(); return; } @@ -1278,10 +1487,10 @@ void CL_PlayDemo_f( void ) if( demo.header.net_protocol != PROTOCOL_VERSION || demo.header.dem_protocol != DEMO_PROTOCOL ) { if( demo.header.dem_protocol != DEMO_PROTOCOL ) - MsgDev( D_ERROR, "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL ); + Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL ); if( demo.header.net_protocol != PROTOCOL_VERSION ) - MsgDev( D_ERROR, "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION ); + Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION ); CL_DemoAborted(); return; } @@ -1292,31 +1501,13 @@ void CL_PlayDemo_f( void ) if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 ) { - MsgDev( D_ERROR, "demo had bogus # of directory entries: %i\n", demo.directory.numentries ); + Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries ); CL_DemoAborted(); return; } - if( cls.changedemo ) - { - S_StopAllSounds( true ); - SCR_BeginLoadingPlaque( false ); - - CL_ClearState (); - CL_InitEdicts (); // re-arrange edicts - } - else - { - // NOTE: at this point demo is still valid - CL_Disconnect(); - Host_ShutdownServer(); - - Con_FastClose(); - UI_SetActiveMenu( false ); - } - // allocate demo entries - demo.directory.entries = Mem_Alloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries ); + demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries ); for( i = 0; i < demo.directory.numentries; i++ ) { @@ -1328,22 +1519,7 @@ void CL_PlayDemo_f( void ) FS_Seek( cls.demofile, demo.entry->offset, SEEK_SET ); - cls.demoplayback = true; - cls.state = ca_connected; - cl.background = (cls.demonum != -1) ? true : false; - cls.spectator = false; - cls.signon = 0; - - demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message - - Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize ); - - memset( demo.cmds, 0, sizeof( demo.cmds )); - demo.angle_position = 1; - demo.framecount = 0; - cls.lastoutgoingcommand = -1; - cls.nextcmdtime = host.realtime; - cl.last_command_ack = -1; + CL_DemoStartPlayback( DEMO_XASH3D ); // g-cont. is this need? Q_strncpy( cls.servername, demoname, sizeof( cls.servername )); @@ -1394,7 +1570,7 @@ void CL_StartDemos_f( void ) c = Cmd_Argc() - 1; if( c > MAX_DEMOS ) { - MsgDev( D_WARN, "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS ); + Con_DPrintf( S_WARN "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS ); c = MAX_DEMOS; } @@ -1402,15 +1578,7 @@ void CL_StartDemos_f( void ) for( i = 1; i < c + 1; i++ ) Q_strncpy( cls.demos[i-1], Cmd_Argv( i ), sizeof( cls.demos[0] )); - - if( !SV_Active() && !cls.demoplayback ) - { - // run demos loop in background mode - Cvar_SetValue( "v_dark", 1.0f ); - cls.demonum = 0; - CL_NextDemo (); - } - else cls.demonum = -1; + cls.demos_pending = true; } /* @@ -1428,17 +1596,15 @@ void CL_Demos_f( void ) return; } + // demos loop are not running + if( cls.olddemonum == -1 ) + return; + cls.demonum = cls.olddemonum; - if( cls.demonum == -1 ) - cls.demonum = 0; - + // run demos loop in background mode if( !SV_Active() && !cls.demoplayback ) - { - // run demos loop in background mode - cls.changedemo = true; CL_NextDemo (); - } } diff --git a/engine/client/cl_events.c b/engine/client/cl_events.c index cbcb3519..3dff5921 100644 --- a/engine/client/cl_events.c +++ b/engine/client/cl_events.c @@ -157,14 +157,11 @@ void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func ) cl_user_event_t *ev; if( lastnum == MAX_EVENTS ) - { - MsgDev( D_ERROR, "CL_RegisterEvent: MAX_EVENTS hit!\n" ); return; - } // clear existing or allocate new one if( !clgame.events[lastnum] ) - clgame.events[lastnum] = Mem_Alloc( cls.mempool, sizeof( cl_user_event_t )); + clgame.events[lastnum] = Mem_Calloc( cls.mempool, sizeof( cl_user_event_t )); else memset( clgame.events[lastnum], 0, sizeof( cl_user_event_t )); ev = clgame.events[lastnum]; @@ -197,7 +194,7 @@ qboolean CL_FireEvent( event_info_t *ei, int slot ) if( !ev ) { idx = bound( 1, ei->index, ( MAX_EVENTS - 1 )); - MsgDev( D_ERROR, "CL_FireEvent: %s not precached\n", cl.event_precache[idx] ); + Con_Reportf( S_ERROR "CL_FireEvent: %s not precached\n", cl.event_precache[idx] ); break; } @@ -211,7 +208,7 @@ qboolean CL_FireEvent( event_info_t *ei, int slot ) } name = cl.event_precache[ei->index]; - MsgDev( D_ERROR, "CL_FireEvent: %s not hooked\n", name ); + Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name ); break; } } @@ -396,7 +393,7 @@ void CL_ParseEvent( sizebuf_t *msg ) event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS ); if( MSG_ReadOneBit( msg )) - packet_index = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); + packet_index = MSG_ReadUBitLong( msg, cls.legacymode ? MAX_LEGACY_ENTITY_BITS : MAX_ENTITY_BITS ); else packet_index = -1; if( MSG_ReadOneBit( msg )) @@ -439,10 +436,6 @@ void CL_ParseEvent( sizebuf_t *msg ) if( args.entindex > 0 && args.entindex <= cl.maxclients ) args.angles[PITCH] /= -3.0f; } - else - { - MsgDev( D_WARN, "CL_ParseEvent: Received non-packet entity index 0 for event\n" ); - } } // Place event on queue @@ -462,28 +455,25 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa { event_args_t args; - if( flags & FEV_SERVER ) - { - MsgDev( D_WARN, "CL_PlaybackEvent: event with FEV_SERVER flag!\n" ); + if( FBitSet( flags, FEV_SERVER )) return; - } // first check event for out of bounds if( eventindex < 1 || eventindex > MAX_EVENTS ) { - MsgDev( D_ERROR, "CL_PlaybackEvent: invalid eventindex %i\n", eventindex ); + Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex ); return; } // check event for precached if( !CL_EventIndex( cl.event_precache[eventindex] )) { - MsgDev( D_ERROR, "CL_PlaybackEvent: event %i was not precached\n", eventindex ); + Con_DPrintf( S_ERROR "CL_PlaybackEvent: event %i was not precached\n", eventindex ); return; } - flags |= FEV_CLIENT; // it's a client event - flags &= ~(FEV_NOTHOST|FEV_HOSTONLY|FEV_GLOBAL); + SetBits( flags, FEV_CLIENT ); // it's a client event + ClearBits( flags, FEV_NOTHOST|FEV_HOSTONLY|FEV_GLOBAL ); if( delay < 0.0f ) delay = 0.0f; // fixup negative delays memset( &args, 0, sizeof( args )); @@ -502,4 +492,4 @@ void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, floa args.bparam2 = bparam2; CL_QueueEvent( flags, eventindex, delay, &args ); -} \ No newline at end of file +} diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index fa88f05a..bf964fc6 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -96,7 +96,7 @@ we don't want interpolate this */ qboolean CL_EntityTeleported( cl_entity_t *ent ) { - int len, maxlen; + float len, maxlen; vec3_t delta; VectorSubtract( ent->curstate.origin, ent->prevstate.origin, delta ); @@ -270,8 +270,8 @@ void CL_ProcessEntityUpdate( cl_entity_t *ent ) ent->model = CL_ModelHandle( ent->curstate.modelindex ); ent->index = ent->curstate.number; - // g-cont. make sure what it's no broke XashXT physics - COM_NormalizeAngles( ent->curstate.angles ); + if( FBitSet( ent->curstate.entityType, ENTITY_NORMAL )) + COM_NormalizeAngles( ent->curstate.angles ); parametric = CL_ParametricMove( ent ); @@ -410,8 +410,19 @@ int CL_InterpolateModel( cl_entity_t *e ) if( cls.timedemo || !e->model ) return 1; - if( fabs( cl_serverframetime() - cl_clientframetime()) < 0.0001f ) - return 1; // interpolation disabled + if( cls.demoplayback == DEMO_QUAKE1 ) + { + // quake lerping is easy + VectorLerp( e->prevstate.origin, cl.lerpFrac, e->curstate.origin, e->origin ); + AngleQuaternion( e->prevstate.angles, q1, false ); + AngleQuaternion( e->curstate.angles, q2, false ); + QuaternionSlerp( q1, q2, cl.lerpFrac, q ); + QuaternionAngle( q, e->angles ); + return 1; + } + + if( cl.maxclients <= 1 ) + return 1; if( e->model->type == mod_brush && !cl_bmodelinterp->value ) return 1; @@ -419,7 +430,6 @@ int CL_InterpolateModel( cl_entity_t *e ) if( cl.local.moving && cl.local.onground == e->index ) return 1; -// t = cl.time - cl_serverframetime(); t = cl.time - cl_interp->value; CL_FindInterpolationUpdates( e, t, &ph0, &ph1 ); @@ -478,12 +488,24 @@ interpolate non-local clients void CL_ComputePlayerOrigin( cl_entity_t *ent ) { float targettime; + vec4_t q, q1, q2; vec3_t origin; vec3_t angles; if( !ent->player || ent->index == ( cl.playernum + 1 )) return; + if( cls.demoplayback == DEMO_QUAKE1 ) + { + // quake lerping is easy + VectorLerp( ent->prevstate.origin, cl.lerpFrac, ent->curstate.origin, ent->origin ); + AngleQuaternion( ent->prevstate.angles, q1, false ); + AngleQuaternion( ent->curstate.angles, q2, false ); + QuaternionSlerp( q1, q2, cl.lerpFrac, q ); + QuaternionAngle( q, ent->angles ); + return; + } + targettime = cl.time - cl_interp->value; CL_PureOrigin( ent, targettime, origin, angles ); @@ -603,13 +625,13 @@ void CL_FlushEntityPacket( sizebuf_t *msg ) // read it all, but ignore it while( 1 ) { - newnum = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ); + newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); if( newnum == LAST_EDICT ) break; // done if( MSG_CheckOverflow( msg )) Host_Error( "CL_FlushEntityPacket: overflow\n" ); - MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ), cl.mtime[0] ); + MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ) ? DELTA_PLAYER : DELTA_ENTITY, cl.mtime[0] ); } } @@ -626,17 +648,18 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t entity_state_t *state; qboolean newent = (old) ? false : true; int pack = frame->num_entities; - qboolean player = CL_IsPlayerIndex( newnum ); + int delta_type = DELTA_ENTITY; qboolean alive = true; // alloc next slot to store update state = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities]; + if( CL_IsPlayerIndex( newnum )) delta_type = DELTA_PLAYER; if(( newnum < 0 ) || ( newnum >= clgame.maxEntities )) { - MsgDev( D_ERROR, "CL_DeltaEntity: invalid newnum: %d\n", newnum ); + Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum ); if( has_update ) - MSG_ReadDeltaEntity( msg, old, state, newnum, player, cl.mtime[0] ); + MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] ); return; } @@ -645,7 +668,7 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t if( newent ) old = &ent->baseline; if( has_update ) - alive = MSG_ReadDeltaEntity( msg, old, state, newnum, player, cl.mtime[0] ); + alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] ); else memcpy( state, old, sizeof( entity_state_t )); if( !alive ) @@ -698,7 +721,10 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) CL_WriteDemoJumpTime(); // sentinel count. save it for debug checking - count = ( MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1 ); + if( cls.legacymode ) + count = MSG_ReadWord( msg ); + else count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1; + newframe = &cl.frames[cl.parsecountmod]; // allocate parse entities @@ -733,7 +759,6 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES )) { - MsgDev( D_NOTE, "CL_ParsePacketEntities: delta frame is too old (flush)\n"); Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" ); CL_FlushEntityPacket( msg ); return playerbytes; @@ -773,9 +798,19 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) while( 1 ) { - newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); - if( newnum == LAST_EDICT ) break; // end of packet entities + int lastedict; + if( cls.legacymode ) + { + newnum = MSG_ReadWord( msg ); + lastedict = 0; + } + else + { + newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); + lastedict = LAST_EDICT; + } + if( newnum == lastedict ) break; // end of packet entities if( MSG_CheckOverflow( msg )) Host_Error( "CL_ParsePacketEntities: overflow\n" ); player = CL_IsPlayerIndex( newnum ); @@ -846,7 +881,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta ) } if( newframe->num_entities != count && newframe->num_entities != 0 ) - MsgDev( D_WARN, "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count ); + Con_Reportf( S_WARN "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count ); if( !newframe->valid ) return playerbytes; // frame is not valid but message was parsed @@ -942,7 +977,7 @@ void CL_LinkCustomEntity( cl_entity_t *ent, entity_state_t *state ) ent->curstate.movetype = state->modelindex; // !!! if( ent->model->type != mod_sprite ) - MsgDev( D_WARN, "bad model on beam ( %s )\n", ent->model->name ); + Con_Reportf( S_WARN "bad model on beam ( %s )\n", ent->model->name ); ent->latched.prevsequence = ent->curstate.sequence; VectorCopy( ent->origin, ent->latched.prevorigin ); @@ -989,9 +1024,12 @@ void CL_LinkPlayers( frame_t *frame ) if( i == cl.playernum ) { - VectorCopy( state->origin, ent->origin ); - VectorCopy( state->origin, ent->prevstate.origin ); - VectorCopy( state->origin, ent->curstate.origin ); + if( cls.demoplayback != DEMO_QUAKE1 ) + { + VectorCopy( state->origin, ent->origin ); + VectorCopy( state->origin, ent->prevstate.origin ); + VectorCopy( state->origin, ent->curstate.origin ); + } VectorCopy( ent->curstate.angles, ent->angles ); } @@ -1007,6 +1045,8 @@ void CL_LinkPlayers( frame_t *frame ) if ( i == cl.playernum ) { + if( cls.demoplayback == DEMO_QUAKE1 ) + VectorLerp( ent->prevstate.origin, cl.lerpFrac, ent->curstate.origin, cl.simorg ); VectorCopy( cl.simorg, ent->origin ); } else @@ -1041,6 +1081,7 @@ void CL_LinkPacketEntities( frame_t *frame ) cl_entity_t *ent; entity_state_t *state; qboolean parametric; + qboolean interpolate; int i; for( i = 0; i < frame->num_entities; i++ ) @@ -1059,22 +1100,21 @@ void CL_LinkPacketEntities( frame_t *frame ) if( !ent ) { - MsgDev( D_ERROR, "CL_LinkPacketEntity: bad entity %i\n", state->number ); + Con_Reportf( S_ERROR "CL_LinkPacketEntity: bad entity %i\n", state->number ); continue; } - ent->curstate = *state; - - // XASH SPECIFIC - if( ent->curstate.rendermode == kRenderNormal && ent->curstate.renderfx == kRenderFxNone ) - ent->curstate.renderamt = 255.0f; + // animtime must keep an actual + ent->curstate.animtime = state->animtime; + ent->curstate.frame = state->frame; + interpolate = false; if( !ent->model ) continue; if( ent->curstate.rendermode == kRenderNormal ) { // auto 'solid' faces - if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) + if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && Host_IsQuakeCompatible( )) { ent->curstate.rendermode = kRenderTransAlpha; ent->curstate.renderamt = 255; @@ -1095,7 +1135,9 @@ void CL_LinkPacketEntities( frame_t *frame ) #ifdef STUDIO_INTERPOLATION_FIX if( ent->lastmove >= cl.time ) VectorCopy( ent->curstate.origin, ent->latched.prevorigin ); - ent->curstate.movetype = MOVETYPE_STEP; + if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) + interpolate = true; + else ent->curstate.movetype = MOVETYPE_STEP; #else if( ent->lastmove >= cl.time ) { @@ -1148,7 +1190,7 @@ void CL_LinkPacketEntities( frame_t *frame ) if( ent->model->type == mod_studio ) { - if( ent->curstate.movetype == MOVETYPE_STEP && FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) + if( interpolate && FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP )) R_StudioLerpMovement( ent, cl.time, ent->origin, ent->angles ); } } @@ -1166,6 +1208,10 @@ void CL_LinkPacketEntities( frame_t *frame ) ent->curstate.rendercolor.r = ent->curstate.rendercolor.g = ent->curstate.rendercolor.b = 255; } + // XASH SPECIFIC + if( ent->curstate.rendermode == kRenderNormal && ent->curstate.renderfx == kRenderFxNone ) + ent->curstate.renderamt = 255.0f; + if( ent->curstate.aiment != 0 && ent->curstate.movetype != MOVETYPE_COMPOUND ) ent->curstate.movetype = MOVETYPE_FOLLOW; @@ -1226,6 +1272,12 @@ void CL_EmitEntities( void ) if( !cl.frames[cl.parsecountmod].valid ) return; + // animate lightestyles + CL_RunLightStyles (); + + // decay dynamic lights + CL_DecayLights (); + // compute last interpolation amount CL_UpdateFrameLerp (); @@ -1313,12 +1365,29 @@ qboolean CL_GetEntitySpatialization( channel_t *ch ) qboolean CL_GetMovieSpatialization( rawchan_t *ch ) { - // UNDONE - return false; + cl_entity_t *ent; + qboolean valid_origin; + + valid_origin = VectorIsNull( ch->origin ) ? false : true; + ent = CL_GetEntityByIndex( ch->entnum ); + + // entity is not present on the client but has valid origin + if( !ent || !ent->index || ent->curstate.messagenum == 0 ) + return valid_origin; + + // setup origin + VectorAverage( ent->curstate.mins, ent->curstate.maxs, ch->origin ); + VectorAdd( ch->origin, ent->curstate.origin, ch->origin ); + + // setup radius + if( ent->model != NULL && ent->model->radius ) ch->radius = ent->model->radius; + else ch->radius = RadiusFromBounds( ent->curstate.mins, ent->curstate.maxs ); + + return true; } void CL_ExtraUpdate( void ) { clgame.dllFuncs.IN_Accumulate(); S_ExtraUpdate(); -} \ No newline at end of file +} diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index fff6d7cb..a1041a43 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -29,9 +29,7 @@ GNU General Public License for more details. #include "library.h" #include "vgui_draw.h" #include "sound.h" // SND_STOP_LOOPING -#ifdef XASH_SDL -#include -#endif +#include "platform/platform.h" #define MAX_LINELENGTH 80 #define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels) @@ -243,7 +241,7 @@ void CL_InitCDAudio( const char *filename ) if( ++c > MAX_CDTRACKS - 1 ) { - MsgDev( D_WARN, "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename ); + Con_Reportf( S_WARN "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename ); break; } } @@ -832,14 +830,14 @@ const char *CL_SoundFromIndex( int index ) if( !hSound ) { - MsgDev( D_ERROR, "CL_SoundFromIndex: invalid sound index %i\n", index ); + Con_DPrintf( S_ERROR "CL_SoundFromIndex: invalid sound index %i\n", index ); return NULL; } sfx = S_GetSfxByHandle( hSound ); if( !sfx ) { - MsgDev( D_ERROR, "CL_SoundFromIndex: bad sfx for index %i\n", index ); + Con_DPrintf( S_ERROR "CL_SoundFromIndex: bad sfx for index %i\n", index ); return NULL; } @@ -1065,7 +1063,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) { // NOTE: no check for DispatchFunc, check only name - if( !Q_strcmp( clgame.msg[i].name, pszName )) + if( !Q_stricmp( clgame.msg[i].name, pszName )) { clgame.msg[i].number = svc_num; clgame.msg[i].size = iSize; @@ -1115,16 +1113,16 @@ void CL_InitEdicts( void ) CL_UPDATE_BACKUP = ( cl.maxclients == 1 ) ? SINGLEPLAYER_BACKUP : MULTIPLAYER_BACKUP; cls.num_client_entities = CL_UPDATE_BACKUP * NUM_PACKET_ENTITIES; - cls.packet_entities = Z_Realloc( cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities ); - clgame.entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities ); - clgame.static_entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES ); + cls.packet_entities = Mem_Realloc( clgame.mempool, cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities ); + clgame.entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities ); + clgame.static_entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES ); clgame.numStatics = 0; if(( clgame.maxRemapInfos - 1 ) != clgame.maxEntities ) { CL_ClearAllRemaps (); // purge old remap info clgame.maxRemapInfos = clgame.maxEntities + 1; - clgame.remap_info = (remap_info_t **)Mem_Alloc( clgame.mempool, sizeof( remap_info_t* ) * clgame.maxRemapInfos ); + clgame.remap_info = (remap_info_t **)Mem_Calloc( clgame.mempool, sizeof( remap_info_t* ) * clgame.maxRemapInfos ); } if( clgame.drawFuncs.R_ProcessEntData != NULL ) @@ -1217,6 +1215,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite, } else { + Con_Reportf( S_ERROR "%s couldn't load\n", szSpriteName ); Mod_UnloadSpriteModel( m_pSprite ); return false; } @@ -1258,7 +1257,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla if( !COM_CheckString( filename )) { - MsgDev( D_ERROR, "CL_LoadSpriteModel: bad name!\n" ); + Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" ); return NULL; } @@ -1535,7 +1534,7 @@ static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount ) Q_strncpy( pEntry->szListName, psz, sizeof( pEntry->szListName )); // name, res, pic, x, y, w, h - pEntry->pList = Mem_Alloc( cls.mempool, sizeof( client_sprite_t ) * numSprites ); + pEntry->pList = Mem_Calloc( cls.mempool, sizeof( client_sprite_t ) * numSprites ); for( index = 0; index < numSprites; index++ ) { @@ -1584,12 +1583,14 @@ CL_FillRGBA */ void CL_FillRGBA( int x, int y, int w, int h, int r, int g, int b, int a ) { + float _x = x, _y = y, _w = w, _h = h; + r = bound( 0, r, 255 ); g = bound( 0, g, 255 ); b = bound( 0, b, 255 ); a = bound( 0, a, 255 ); - SPR_AdjustSize( (float *)&x, (float *)&y, (float *)&w, (float *)&h ); + SPR_AdjustSize( &_x, &_y, &_w, &_h ); pglDisable( GL_TEXTURE_2D ); pglEnable( GL_BLEND ); @@ -1598,10 +1599,10 @@ void CL_FillRGBA( int x, int y, int w, int h, int r, int g, int b, int a ) pglColor4f( r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f ); pglBegin( GL_QUADS ); - pglVertex2f( x, y ); - pglVertex2f( x + w, y ); - pglVertex2f( x + w, y + h ); - pglVertex2f( x, y + h ); + pglVertex2f( _x, _y ); + pglVertex2f( _x + _w, _y ); + pglVertex2f( _x + _w, _y + _h ); + pglVertex2f( _x, _y + _h ); pglEnd (); pglColor3f( 1.0f, 1.0f, 1.0f ); @@ -1682,7 +1683,7 @@ static int pfnHookUserMsg( const char *pszName, pfnUserMsgHook pfn ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) { // see if already hooked - if( !Q_strcmp( clgame.msg[i].name, pszName )) + if( !Q_stricmp( clgame.msg[i].name, pszName )) return 1; } @@ -1709,7 +1710,7 @@ static int pfnServerCmd( const char *szCmdString ) { string buf; - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; // just like the client typed "cmd xxxxx" at the console @@ -1727,11 +1728,20 @@ pfnClientCmd */ static int pfnClientCmd( const char *szCmdString ) { - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; - Cbuf_AddText( szCmdString ); - Cbuf_AddText( "\n" ); + if( cls.initialized ) + { + Cbuf_AddText( szCmdString ); + Cbuf_AddText( "\n" ); + } + else + { + // will exec later + Q_strncat( host.deferred_cmd, va( "%s\n", szCmdString ), sizeof( host.deferred_cmd )); + } + return 1; } @@ -1790,12 +1800,8 @@ static void pfnPlaySoundByIndex( int iSound, float volume ) // make sure what we in-bounds iSound = bound( 0, iSound, MAX_SOUNDS ); hSound = cl.sound_index[iSound]; + if( !hSound ) return; - if( !hSound ) - { - MsgDev( D_ERROR, "CL_PlaySoundByIndex: invalid sound handle %i\n", iSound ); - return; - } S_StartSound( NULL, cl.viewentity, CHAN_ITEM, hSound, volume, ATTN_NORM, PITCH_NORM, SND_STOP_LOOPING ); } @@ -1866,7 +1872,8 @@ int pfnDrawConsoleString( int x, int y, char *string ) { int drawLen; - if( !string || !*string ) return 0; // silent ignore + if( !COM_CheckString( string )) + return 0; // silent ignore Con_SetFont( con_fontsize->value ); clgame.ds.adjust_size = true; @@ -1942,7 +1949,21 @@ GetWindowCenterX */ static int pfnGetWindowCenterX( void ) { - return host.window_center_x; + int x = 0; +#ifdef _WIN32 + if( m_ignore->value ) + { + POINT pos; + GetCursorPos( &pos ); + return pos.x; + } +#endif + +#ifdef XASH_SDL + SDL_GetWindowPosition( host.hWnd, &x, NULL ); +#endif + + return host.window_center_x + x; } /* @@ -1953,7 +1974,21 @@ GetWindowCenterY */ static int pfnGetWindowCenterY( void ) { - return host.window_center_y; + int y = 0; +#ifdef _WIN32 + if( m_ignore->value ) + { + POINT pos; + GetCursorPos( &pos ); + return pos.y; + } +#endif + +#ifdef XASH_SDL + SDL_GetWindowPosition( host.hWnd, NULL, &y ); +#endif + + return host.window_center_y + y; } /* @@ -2014,22 +2049,6 @@ static float pfnGetClientMaxspeed( void ) return cl.local.maxspeed; } -/* -============= -CL_GetMousePosition - -============= -*/ -void CL_GetMousePosition( int *mx, int *my ) -{ -#ifdef XASH_SDL - SDL_GetMouseState( mx, my ); -#else - if( mx ) *mx = 0; - if( my ) *my = 0; -#endif -} - /* ============= pfnIsNoClipping @@ -2239,7 +2258,7 @@ static void pfnHookEvent( const char *filename, pfnEventHook pfn ) if( !Q_stricmp( name, ev->name ) && ev->func != NULL ) { - MsgDev( D_WARN, "CL_HookEvent: %s already hooked!\n", name ); + Con_Reportf( S_WARN "CL_HookEvent: %s already hooked!\n", name ); return; } } @@ -2720,7 +2739,7 @@ pfnServerCmdUnreliable */ int pfnServerCmdUnreliable( char *szCmdString ) { - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; MSG_BeginClientCmd( &cls.datagram, clc_stringcmd ); @@ -2740,20 +2759,7 @@ void pfnGetMousePos( struct tagPOINT *ppt ) if( !ppt ) return; - CL_GetMousePosition( &ppt->x, &ppt->y ); -} - -/* -============= -pfnSetMousePos - -============= -*/ -void pfnSetMousePos( int mx, int my ) -{ -#ifdef XASH_SDL - SDL_WarpMouseInWindow( host.hWnd, mx, my ); -#endif + Platform_GetMousePos( &ppt->x, &ppt->y ); } /* @@ -2992,12 +2998,14 @@ pfnFillRGBABlend */ void GAME_EXPORT CL_FillRGBABlend( int x, int y, int w, int h, int r, int g, int b, int a ) { + float _x = x, _y = y, _w = w, _h = h; + r = bound( 0, r, 255 ); g = bound( 0, g, 255 ); b = bound( 0, b, 255 ); a = bound( 0, a, 255 ); - SPR_AdjustSize( (float *)&x, (float *)&y, (float *)&w, (float *)&h ); + SPR_AdjustSize( &_x, &_y, &_w, &_h ); pglDisable( GL_TEXTURE_2D ); pglEnable( GL_BLEND ); @@ -3006,10 +3014,10 @@ void GAME_EXPORT CL_FillRGBABlend( int x, int y, int w, int h, int r, int g, int pglColor4f( r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f ); pglBegin( GL_QUADS ); - pglVertex2f( x, y ); - pglVertex2f( x + w, y ); - pglVertex2f( x + w, y + h ); - pglVertex2f( x, y + h ); + pglVertex2f( _x, _y ); + pglVertex2f( _x + _w, _y ); + pglVertex2f( _x + _w, _y + _h ); + pglVertex2f( _x, _y + _h ); pglEnd (); pglColor3f( 1.0f, 1.0f, 1.0f ); @@ -3525,7 +3533,7 @@ void NetAPI_SendRequest( int context, int request, int flags, double timeout, ne if( !response ) { - MsgDev( D_ERROR, "Net_SendRequest: no callbcak specified for request with context %i!\n", context ); + Con_DPrintf( S_ERROR "Net_SendRequest: no callbcak specified for request with context %i!\n", context ); return; } @@ -3908,6 +3916,8 @@ static event_api_t gEventApi = CL_VisTraceLine, pfnGetVisent, CL_TestLine, + CL_PushTraceBounds, + CL_PopTraceBounds, }; static demo_api_t gDemoApi = @@ -3993,7 +4003,7 @@ static cl_enginefunc_t gEngfuncs = pfnGetClientMaxspeed, COM_CheckParm, Key_Event, - CL_GetMousePosition, + Platform_GetMousePos, pfnIsNoClipping, CL_GetLocalPlayer, pfnGetViewModel, @@ -4043,7 +4053,7 @@ static cl_enginefunc_t gEngfuncs = pfnGetPlayerForTrackerID, pfnServerCmdUnreliable, pfnGetMousePos, - pfnSetMousePos, + Platform_SetMousePos, pfnSetMouseEnable, Cvar_GetList, (void*)Cmd_GetFirstFunctionHandle, @@ -4139,7 +4149,7 @@ qboolean CL_LoadProgs( const char *name ) // trying to get single export if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL ) { - MsgDev( D_NOTE, "CL_LoadProgs: found single callback export\n" ); + Con_Reportf( "CL_LoadProgs: found single callback export\n" ); // trying to fill interface now GetClientAPI( &clgame.dllFuncs ); @@ -4164,7 +4174,7 @@ qboolean CL_LoadProgs( const char *name ) // functions are cleared before all the extensions are evaluated if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL ) { - MsgDev( D_NOTE, "CL_LoadProgs: failed to get address of %s proc\n", func->name ); + Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name ); if( critical_exports ) { @@ -4191,13 +4201,13 @@ qboolean CL_LoadProgs( const char *name ) // functions are cleared before all the extensions are evaluated // NOTE: new exports can be missed without stop the engine if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL ) - MsgDev( D_NOTE, "CL_LoadProgs: failed to get address of %s proc\n", func->name ); + Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name ); } if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION )) { COM_FreeLibrary( clgame.hInstance ); - MsgDev( D_NOTE, "CL_LoadProgs: can't init client API\n" ); + Con_Reportf( "CL_LoadProgs: can't init client API\n" ); clgame.hInstance = NULL; return false; } diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index 2c62b894..eaf9a890 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -31,6 +31,19 @@ void UI_UpdateMenu( float realtime ) { if( !gameui.hInstance ) return; + // if some deferred cmds is waiting + if( UI_IsVisible() && COM_CheckString( host.deferred_cmd )) + { + Cbuf_AddText( host.deferred_cmd ); + host.deferred_cmd[0] = '\0'; + Cbuf_Execute(); + return; + } + + // don't show menu while level is loaded + if( GameState->nextstate != STATE_RUNFRAME && !GameState->loadGame ) + return; + // menu time (not paused, not clamped) gameui.globals->time = host.realtime; gameui.globals->frametime = host.realframetime; @@ -148,7 +161,7 @@ static void UI_DrawLogo( const char *filename, float x, float y, float width, fl if( FS_FileExists( path, false ) && !fullpath ) { - MsgDev( D_ERROR, "Couldn't load %s from packfile. Please extract it\n", path ); + Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", path ); gameui.drawLogo = false; return; } @@ -249,6 +262,8 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in ) if( in->nomodels ) out->flags |= GFL_NOMODELS; + if( in->noskills ) + out->flags |= GFL_NOSKILLS; } static qboolean PIC_Scissor( float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 ) @@ -361,13 +376,13 @@ pfnPIC_Load ========= */ -static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long image_size, long flags ) +static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, int image_size, int flags ) { HIMAGE tx; if( !szPicName || !*szPicName ) { - MsgDev( D_ERROR, "CL_LoadImage: bad name!\n" ); + Con_Reportf( S_ERROR "CL_LoadImage: bad name!\n" ); return 0; } @@ -375,7 +390,7 @@ static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, long im SetBits( flags, TF_IMAGE ); Image_SetForceFlags( IL_LOAD_DECAL ); // allow decal images for menu - tx = GL_LoadTexture( szPicName, image_buf, image_size, flags, NULL ); + tx = GL_LoadTexture( szPicName, image_buf, image_size, flags ); Image_ClearForceFlags(); return tx; @@ -700,15 +715,19 @@ for drawing playermodel previews */ static void pfnRenderScene( const ref_viewpass_t *rvp ) { + ref_viewpass_t copy; + // to avoid division by zero if( !rvp || rvp->fov_x <= 0.0f || rvp->fov_y <= 0.0f ) return; + copy = *rvp; + // don't allow special modes from menu - ((ref_viewpass_t *)&rvp)->flags = 0; + copy.flags = 0; R_Set2DMode( false ); - R_RenderFrame( rvp ); + R_RenderFrame( © ); R_Set2DMode( true ); R_PopScene(); } @@ -785,7 +804,7 @@ pfnMemAlloc */ static void *pfnMemAlloc( size_t cb, const char *filename, const int fileline ) { - return _Mem_Alloc( gameui.mempool, cb, filename, fileline ); + return _Mem_Alloc( gameui.mempool, cb, true, filename, fileline ); } /* @@ -886,7 +905,7 @@ int pfnCheckGameDll( void ) COM_FreeLibrary( hInst ); // don't increase linker's reference counter return true; } - MsgDev( D_WARN, "Could not load server library:\n%s", COM_GetLibraryError() ); + Con_Reportf( S_WARN "Could not load server library:\n%s", COM_GetLibraryError() ); return false; } @@ -1080,7 +1099,7 @@ qboolean UI_LoadProgs( void ) if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL ) { COM_FreeLibrary( gameui.hInstance ); - MsgDev( D_NOTE, "UI_LoadProgs: can't init menu API\n" ); + Con_Reportf( "UI_LoadProgs: can't init menu API\n" ); gameui.hInstance = NULL; return false; } @@ -1088,21 +1107,6 @@ qboolean UI_LoadProgs( void ) gameui.use_text_api = false; - if( ( GiveTextApi = (UITEXTAPI)COM_GetProcAddress( gameui.hInstance, "GiveTextAPI" ) ) ) - { - MsgDev( D_NOTE, "UI_LoadProgs: extended Text API initialized\n" ); - // make local copy of engfuncs to prevent overwrite it with user dll - memcpy( &gpTextfuncs, &gTextfuncs, sizeof( gpTextfuncs )); - if( GiveTextApi( &gpTextfuncs ) ) - gameui.use_text_api = true; - } - - pfnAddTouchButtonToList = (ADDTOUCHBUTTONTOLIST)COM_GetProcAddress( gameui.hInstance, "AddTouchButtonToList" ); - if( pfnAddTouchButtonToList ) - { - MsgDev( D_NOTE, "UI_LoadProgs: AddTouchButtonToList call found\n" ); - } - // make local copy of engfuncs to prevent overwrite it with user dll memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs )); @@ -1111,18 +1115,33 @@ qboolean UI_LoadProgs( void ) if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals )) { COM_FreeLibrary( gameui.hInstance ); - MsgDev( D_NOTE, "UI_LoadProgs: can't init menu API\n" ); + Con_Reportf( "UI_LoadProgs: can't init menu API\n" ); Mem_FreePool( &gameui.mempool ); gameui.hInstance = NULL; return false; } + if( ( GiveTextApi = (UITEXTAPI)COM_GetProcAddress( gameui.hInstance, "GiveTextAPI" ) ) ) + { + Con_Reportf( "UI_LoadProgs: extended Text API initialized\n" ); + // make local copy of engfuncs to prevent overwrite it with user dll + memcpy( &gpTextfuncs, &gTextfuncs, sizeof( gpTextfuncs )); + if( GiveTextApi( &gpTextfuncs ) ) + gameui.use_text_api = true; + } + + pfnAddTouchButtonToList = (ADDTOUCHBUTTONTOLIST)COM_GetProcAddress( gameui.hInstance, "AddTouchButtonToList" ); + if( pfnAddTouchButtonToList ) + { + Con_Reportf( "UI_LoadProgs: AddTouchButtonToList call found\n" ); + } + Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY ); // setup gameinfo for( i = 0; i < SI.numgames; i++ ) { - gameui.modsInfo[i] = Mem_Alloc( gameui.mempool, sizeof( GAMEINFO )); + gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO )); UI_ConvertGameInfo( gameui.modsInfo[i], SI.games[i] ); } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 93bd18b1..e1d86ee8 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -83,6 +83,8 @@ client_t cl; client_static_t cls; clgame_static_t clgame; +void CL_InternetServers_f( void ); + //====================================================================== int CL_Active( void ) { @@ -213,7 +215,7 @@ An svc_signonnum has been received, perform a client side setup void CL_SignonReply( void ) { // g-cont. my favorite message :-) - Con_DPrintf( "CL_SignonReply: %i\n", cls.signon ); + Con_Reportf( "CL_SignonReply: %i\n", cls.signon ); switch( cls.signon ) { @@ -247,14 +249,31 @@ static float CL_LerpPoint( void ) if( f == 0.0f || cls.timedemo ) { cl.time = cl.mtime[0]; - - // g-cont. probably this is redundant - if( cls.demoplayback ) - cl.oldtime = cl.mtime[0] - cl_clientframetime(); - return 1.0f; } + if( f > 0.1f ) + { + // dropped packet, or start of demo + cl.mtime[1] = cl.mtime[0] - 0.1f; + f = 0.1f; + } +#if 1 + frac = (cl.time - cl.mtime[1]) / f; + + if( frac < 0.0f ) + { + if( frac < -0.01 ) + cl.time = cl.mtime[1]; + frac = 0.0f; + } + else if( frac > 1.0f ) + { + if( frac > 1.01 ) + cl.time = cl.mtime[0]; + frac = 1.0f; + } +#else if( cl_interp->value > 0.001f ) { // manual lerp value (goldsrc mode) @@ -265,7 +284,7 @@ static float CL_LerpPoint( void ) // automatic lerp (classic mode) frac = ( cl.time - cl.mtime[1] ) / f; } - +#endif return frac; } @@ -888,16 +907,10 @@ void CL_BeginUpload_f( void ) name = Cmd_Argv( 1 ); if( !COM_CheckString( name )) - { - MsgDev( D_ERROR, "upload without filename\n" ); return; - } if( !cl_allow_upload.value ) - { - MsgDev( D_WARN, "ingoring decal upload ( cl_allow_upload is 0 )\n" ); return; - } if( Q_strlen( name ) != 36 || Q_strnicmp( name, "!MD5", 4 )) { @@ -912,7 +925,7 @@ void CL_BeginUpload_f( void ) { if( memcmp( md5, custResource.rgucMD5_hash, 16 )) { - MsgDev( D_REPORT, "Bogus data retrieved from %s, attempting to delete entry\n", CUSTOM_RES_PATH ); + Con_Reportf( "Bogus data retrieved from %s, attempting to delete entry\n", CUSTOM_RES_PATH ); HPAK_RemoveLump( CUSTOM_RES_PATH, &custResource ); return; } @@ -929,26 +942,22 @@ void CL_BeginUpload_f( void ) if( memcmp( custResource.rgucMD5_hash, md5, 16 )) { - MsgDev( D_REPORT, "HPAK_AddLump called with bogus lump, md5 mismatch\n" ); - MsgDev( D_REPORT, "Purported: %s\n", MD5_Print( custResource.rgucMD5_hash ) ); - MsgDev( D_REPORT, "Actual : %s\n", MD5_Print( md5 ) ); - MsgDev( D_REPORT, "Removing conflicting lump\n" ); + Con_Reportf( "HPAK_AddLump called with bogus lump, md5 mismatch\n" ); + Con_Reportf( "Purported: %s\n", MD5_Print( custResource.rgucMD5_hash ) ); + Con_Reportf( "Actual : %s\n", MD5_Print( md5 ) ); + Con_Reportf( "Removing conflicting lump\n" ); HPAK_RemoveLump( CUSTOM_RES_PATH, &custResource ); return; } } } - if( buf && size ) + if( buf && size > 0 ) { Netchan_CreateFileFragmentsFromBuffer( &cls.netchan, name, buf, size ); Netchan_FragSend( &cls.netchan ); Mem_Free( buf ); } - else - { - MsgDev( D_REPORT, "ingoring customization upload, couldn't find decal locally\n" ); - } } /* @@ -1003,10 +1012,40 @@ void CL_SendConnectPacket( void ) key = ID_GetMD5(); memset( protinfo, 0, sizeof( protinfo )); - Info_SetValueForKey( protinfo, "uuid", key, sizeof( protinfo )); - Info_SetValueForKey( protinfo, "qport", qport, sizeof( protinfo )); - Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, cls.challenge, protinfo, cls.userinfo ); + if( cls.legacymode ) + { + // set related userinfo keys + if( cl_dlmax->value >= 40000 || cl_dlmax->value < 100 ) + Cvar_FullSet( "cl_maxpacket", "1400", FCVAR_USERINFO ); + else + Cvar_FullSet( "cl_maxpacket", cl_dlmax->string, FCVAR_USERINFO ); + Cvar_FullSet( "cl_maxpayload", "1000", FCVAR_USERINFO ); + + /// TODO: add input devices list + //Info_SetValueForKey( protinfo, "d", va( "%d", input_devices ), sizeof( protinfo ) ); + Info_SetValueForKey( protinfo, "v", XASH_VERSION, sizeof( protinfo ) ); + Info_SetValueForKey( protinfo, "b", va( "%d", Q_buildnum() ), sizeof( protinfo ) ); + Info_SetValueForKey( protinfo, "o", Q_buildos(), sizeof( protinfo ) ); + Info_SetValueForKey( protinfo, "a", Q_buildarch(), sizeof( protinfo ) ); + Info_SetValueForKey( protinfo, "i", ID_GetMD5(), sizeof( protinfo ) ); + + Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i %i \"%s\" 2 \"%s\"\n", + PROTOCOL_LEGACY_VERSION, Q_atoi( qport ), cls.challenge, cls.userinfo, protinfo ); + Con_Printf( "Trying to connect by legacy protocol\n" ); + } + else + { + // remove useless userinfo keys + Cvar_FullSet( "cl_maxpacket", "0", 0 ); + Cvar_FullSet( "cl_maxpayload", "1000", 0 ); + Info_SetValueForKey( protinfo, "uuid", key, sizeof( protinfo )); + Info_SetValueForKey( protinfo, "qport", qport, sizeof( protinfo )); + Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, cls.challenge, protinfo, cls.userinfo ); + Con_Printf( "Trying to connect by modern protocol\n" ); + } + + cls.timestart = Sys_DoubleTime(); } @@ -1020,6 +1059,10 @@ Resend a connect message if the last one has timed out void CL_CheckForResend( void ) { netadr_t adr; + int res; + + if( cls.internetservers_wait ) + CL_InternetServers_f(); // if the local server is running and we aren't then connect if( cls.state == ca_disconnected && SV_Active( )) @@ -1044,17 +1087,24 @@ void CL_CheckForResend( void ) if(( host.realtime - cls.connect_time ) < cl_resend.value ) return; - if( !NET_StringToAdr( cls.servername, &adr )) + res = NET_StringToAdrNB( cls.servername, &adr ); + + if( !res ) { - MsgDev( D_ERROR, "CL_CheckForResend: bad server address\n" ); CL_Disconnect(); return; } + if( res == 2 ) + { + cls.connect_time = MAX_HEARTBEAT; + return; + } + // only retry so many times before failure. if( cls.connect_retry >= CL_CONNECTION_RETRIES ) { - MsgDev( D_ERROR, "CL_CheckForResend: couldn't connected\n" ); + Con_DPrintf( S_ERROR "CL_CheckForResend: couldn't connected\n" ); CL_Disconnect(); return; } @@ -1078,9 +1128,10 @@ void CL_CheckForResend( void ) Con_Printf( "Connecting to %s... [retry #%i]\n", cls.servername, cls.connect_retry ); - if( cl_test_bandwidth.value ) + if( !cls.legacymode && cl_test_bandwidth.value ) Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size ); - else Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" ); + else + Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" ); } resource_t *CL_AddResource( resourcetype_t type, const char *name, int size, qboolean bFatalIfMissing, int index ) @@ -1145,8 +1196,14 @@ CL_Connect_f void CL_Connect_f( void ) { string server; + qboolean legacyconnect = false; - if( Cmd_Argc() != 2 ) + // hidden hint to connect by using legacy protocol + if( Cmd_Argc() == 3 ) + { + legacyconnect = !Q_strcmp( Cmd_Argv( 2 ), "legacy" ); + } + else if( Cmd_Argc() != 2 ) { Con_Printf( S_USAGE "connect \n" ); return; @@ -1166,6 +1223,7 @@ void CL_Connect_f( void ) Key_SetKeyDest( key_console ); cls.state = ca_connecting; + cls.legacymode = legacyconnect; Q_strncpy( cls.servername, server, sizeof( cls.servername )); cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately cls.max_fragment_size = FRAGMENT_MAX_SIZE; // guess a we can establish connection with maximum fragment size @@ -1317,6 +1375,19 @@ void CL_Reconnect( qboolean setup_netchan ) if( setup_netchan ) { Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize ); + + if( cls.legacymode ) + { + unsigned int extensions = Q_atoi( Cmd_Argv( 1 ) ); + + if( extensions & NET_EXT_SPLIT ) + { + // only enable incoming split for legacy mode + cls.netchan.split = true; + Con_Reportf( "^2NET_EXT_SPLIT enabled^7 (packet sizes is %d/%d)\n", (int)cl_dlmax->value, 65536 ); + } + } + } else { @@ -1351,6 +1422,8 @@ This is also called on Host_Error, so it shouldn't cause any errors */ void CL_Disconnect( void ) { + cls.legacymode = false; + if( cls.state == ca_disconnected ) return; @@ -1370,6 +1443,7 @@ void CL_Disconnect( void ) Netchan_Clear( &cls.netchan ); cls.state = ca_disconnected; + cls.set_lastdemo = false; cls.connect_retry = 0; cls.signon = 0; @@ -1416,7 +1490,7 @@ void CL_LocalServers_f( void ) Con_Printf( "Scanning for servers on the local network area...\n" ); NET_Config( true ); // allow remote - + // send a broadcast packet adr.type = NA_BROADCAST; adr.port = MSG_BigShort( PORT_SERVER ); @@ -1424,6 +1498,8 @@ void CL_LocalServers_f( void ) Netchan_OutOfBandPrint( NS_CLIENT, adr, "info %i", PROTOCOL_VERSION ); } +#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" + /* ================= CL_InternetServers_f @@ -1431,23 +1507,27 @@ CL_InternetServers_f */ void CL_InternetServers_f( void ) { - netadr_t adr; - char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\"; + char fullquery[512] = MS_SCAN_REQUEST; + char *info = fullquery + sizeof( MS_SCAN_REQUEST ) - 1; + const size_t remaining = sizeof( fullquery ) - sizeof( MS_SCAN_REQUEST ); - Con_Printf( "Scanning for servers on the internet area...\n" ); NET_Config( true ); // allow remote - if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) ) - MsgDev( D_ERROR, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); + Con_Printf( "Scanning for servers on the internet area...\n" ); + Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); + Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version + // Info_SetValueForKey( info, "nat", cl_nat->string, remaining ); - Q_strcpy( &fullquery[22], GI->gamefolder ); + cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ), fullquery ); + cls.internetservers_pending = true; - NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamefolder ) + 23, fullquery, adr ); - - // now we clearing the vgui request - if( clgame.master_request != NULL ) - memset( clgame.master_request, 0, sizeof( net_request_t )); - clgame.request_type = NET_REQUEST_GAMEUI; + if( !cls.internetservers_wait ) + { + // now we clearing the vgui request + if( clgame.master_request != NULL ) + memset( clgame.master_request, 0, sizeof( net_request_t )); + clgame.request_type = NET_REQUEST_GAMEUI; + } } /* @@ -1562,11 +1642,21 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg ) CL_FixupColorStringsForInfoString( s, infostring ); + if( Q_strstr( infostring, "wrong version" ) ) + { + Netchan_OutOfBandPrint( NS_CLIENT, from, "info %i", PROTOCOL_LEGACY_VERSION ); + Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring ); + return; + } + if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" ))) - return; // unsupported proto + { + Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring ); + return; // unsupported proto + } // more info about servers - Con_Printf( "Server: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" )); + Con_Printf( "^2Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" )); UI_AddServerToList( from, infostring ); } @@ -1719,14 +1809,14 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) Cmd_TokenizeString( args ); c = Cmd_Argv( 0 ); - MsgDev( D_NOTE, "CL_ConnectionlessPacket: %s : %s\n", NET_AdrToString( from ), c ); + Con_Reportf( "CL_ConnectionlessPacket: %s : %s\n", NET_AdrToString( from ), c ); // server connection if( !Q_strcmp( c, "client_connect" )) { if( cls.state == ca_connected ) { - MsgDev( D_ERROR, "dup connect received. ignored\n"); + Con_DPrintf( S_ERROR "dup connect received. ignored\n"); return; } @@ -1764,6 +1854,14 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) // print command from somewhere Con_Printf( "%s", MSG_ReadString( msg )); } + else if( !Q_strcmp( c, "errormsg" )) + { + args = MSG_ReadString( msg ); + if( !Q_strcmp( args, "Server uses protocol version 48.\n" )) + { + cls.legacyserver = from; + } + } else if( !Q_strcmp( c, "testpacket" )) { byte recv_buf[NET_MAX_FRAGMENT]; @@ -1784,7 +1882,6 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) } // if we waiting more than cl_timeout or packet was trashed - Msg( "got testpacket, size mismatched %d should be %d\n", MSG_GetMaxBytes( msg ), cls.max_fragment_size ); cls.connect_time = MAX_HEARTBEAT; return; // just wait for a next responce } @@ -1798,7 +1895,8 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) if( crcValue == crcValue2 ) { // packet was sucessfully delivered, adjust the fragment size and get challenge - Msg( "CRC 0x%08x is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size ); + + Con_DPrintf( "CRC %x is matched, get challenge, fragment size %d\n", crcValue, cls.max_fragment_size ); Netchan_OutOfBandPrint( NS_CLIENT, from, "getchallenge\n" ); Cvar_SetValue( "cl_dlmax", cls.max_fragment_size ); cls.connect_time = host.realtime; @@ -1816,6 +1914,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) } Msg( "got testpacket, CRC mismatched 0x%08x should be 0x%08x, trying next fragment size %d\n", crcValue2, crcValue, cls.max_fragment_size >> 1 ); + // trying the next size of packet cls.connect_time = MAX_HEARTBEAT; } @@ -1842,6 +1941,12 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) // a disconnect message from the server, which will happen if the server // dropped the connection but it is still getting packets from us CL_Disconnect_f(); + + if( NET_CompareAdr( from, cls.legacyserver )) + { + Cbuf_AddText( va( "connect %s legacy\n", NET_AdrToString( from ))); + memset( &cls.legacyserver, 0, sizeof( cls.legacyserver )); + } } else if( !Q_strcmp( c, "f" )) { @@ -1907,13 +2012,19 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION ); } } + + if( cls.internetservers_pending ) + { + Cbuf_AddText( "menu_resetping\n" ); // TODO: New Menu API + cls.internetservers_pending = false; + } } else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len )) { // user out of band message (must be handled in CL_ConnectionlessPacket) if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, buf ); } - else MsgDev( D_ERROR, "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); + else Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); } /* @@ -1948,6 +2059,11 @@ void CL_ReadNetMessage( void ) while( CL_GetMessage( net_message_buffer, &curSize )) { + if( cls.legacymode && *((int *)&net_message_buffer) == 0xFFFFFFFE ) + // Will rewrite existing packet by merged + if( !NetSplit_GetLong( &cls.netchan.netsplit, &net_from, net_message_buffer, &curSize ) ) + continue; + MSG_Init( &net_message, "ServerData", net_message_buffer, curSize ); // check for connectionless packet (0xffffffff) first @@ -1962,21 +2078,25 @@ void CL_ReadNetMessage( void ) if( !cls.demoplayback && MSG_GetMaxBytes( &net_message ) < 8 ) { - MsgDev( D_WARN, "%s: runt packet\n", NET_AdrToString( net_from )); + Con_Printf( S_WARN "CL_ReadPackets: %s:runt packet\n", NET_AdrToString( net_from )); continue; } // packet from server if( !cls.demoplayback && !NET_CompareAdr( net_from, cls.netchan.remote_address )) { - MsgDev( D_ERROR, "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( net_from )); + Con_DPrintf( S_ERROR "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( net_from )); continue; } if( !cls.demoplayback && !Netchan_Process( &cls.netchan, &net_message )) continue; // wasn't accepted for some reason - CL_ParseServerMessage( &net_message, true ); + // run special handler for quake demos + if( cls.demoplayback == DEMO_QUAKE1 ) + CL_ParseQuakeMessage( &net_message, true ); + else if( cls.legacymode ) CL_ParseLegacyServerMessage( &net_message, true ); + else CL_ParseServerMessage( &net_message, true ); cl.send_reply = true; } @@ -2019,7 +2139,7 @@ void CL_ReadPackets( void ) // decide the simulation time cl.oldtime = cl.time; - if( !cls.demoplayback && !cl.paused ) + if( cls.demoplayback != DEMO_XASH3D && !cl.paused ) cl.time += host.frametime; // demo time @@ -2034,13 +2154,11 @@ void CL_ReadPackets( void ) if( cl.maxclients > 1 && cls.state == ca_active && !host_developer.value ) Cvar_SetCheatState(); #endif - // singleplayer never has connection timeout - if( NET_IsLocalAddress( cls.netchan.remote_address )) - return; - // hot precache and downloading resources if( cls.signon == SIGNONS && cl.lastresourcecheck < host.realtime ) { + double checktime = Host_IsLocalGame() ? 0.1 : 1.0; + if( !cls.dl.custom && cl.resourcesneeded.pNext != &cl.resourcesneeded ) { // check resource for downloading and precache @@ -2048,9 +2166,14 @@ void CL_ReadPackets( void ) CL_BatchResourceRequest( false ); cls.dl.custom = true; } - cl.lastresourcecheck = host.realtime + 5.0f; // don't checking too often + + cl.lastresourcecheck = host.realtime + checktime; } + // singleplayer never has connection timeout + if( NET_IsLocalAddress( cls.netchan.remote_address )) + return; + // if in the debugger last frame, don't timeout if( host.frametime > 5.0f ) cls.netchan.last_received = Sys_DoubleTime(); @@ -2359,7 +2482,7 @@ qboolean CL_PrecacheResources( void ) if( cl.models[pRes->nIndex] == NULL ) { - MsgDev( D_ERROR, "submodel %s not found\n", pRes->szFileName ); + Con_Printf( S_ERROR "submodel %s not found\n", pRes->szFileName ); if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING )) { @@ -2386,6 +2509,7 @@ qboolean CL_PrecacheResources( void ) { if( FBitSet( pRes->ucFlags, RES_WASMISSING )) { + Con_Printf( S_ERROR "%s%s couldn't load\n", DEFAULT_SOUNDPATH, pRes->szFileName ); cl.sound_precache[pRes->nIndex][0] = 0; cl.sound_index[pRes->nIndex] = 0; } @@ -2450,7 +2574,6 @@ qboolean CL_PrecacheResources( void ) CL_SetEventIndex( cl.event_precache[pRes->nIndex], pRes->nIndex ); break; default: - MsgDev( D_REPORT, "unknown resource type\n" ); break; } @@ -2558,9 +2681,13 @@ void CL_InitLocal( void ) Cvar_Get( "team", "", FCVAR_USERINFO, "player team" ); Cvar_Get( "skin", "", FCVAR_USERINFO, "player skin" ); + // legacy mode cvars (need this to add it to userinfo) + Cvar_Get( "cl_maxpacket", "0", 0, "legacy server compatibility" ); + Cvar_Get( "cl_maxpayload", "1000", 0, "legacy server compatibility" ); + cl_showfps = Cvar_Get( "cl_showfps", "1", FCVAR_ARCHIVE, "show client fps" ); cl_nosmooth = Cvar_Get( "cl_nosmooth", "0", FCVAR_ARCHIVE, "disable smooth up stair climbing and interpolate position in multiplayer" ); - cl_smoothtime = Cvar_Get( "cl_smoothtime", "0.1", FCVAR_ARCHIVE, "time to smooth up" ); + cl_smoothtime = Cvar_Get( "cl_smoothtime", "0", FCVAR_ARCHIVE, "time to smooth up" ); cl_cmdbackup = Cvar_Get( "cl_cmdbackup", "10", FCVAR_ARCHIVE, "how many additional history commands are sent" ); cl_cmdrate = Cvar_Get( "cl_cmdrate", "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" ); cl_draw_particles = Cvar_Get( "r_drawparticles", "1", FCVAR_CHEAT, "render particles" ); @@ -2574,6 +2701,7 @@ void CL_InitLocal( void ) hud_scale = Cvar_Get( "hud_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" ); Cvar_Get( "cl_background", "0", FCVAR_READ_ONLY, "indicate what background map is running" ); cl_showevents = Cvar_Get( "cl_showevents", "0", FCVAR_ARCHIVE, "show events playback" ); + Cvar_Get( "lastdemo", "", FCVAR_ARCHIVE, "last played demo" ); // these two added to shut up CS 1.5 about 'unknown' commands Cvar_Get( "lightgamma", "1", FCVAR_ARCHIVE, "ambient lighting level (legacy, unused)" ); @@ -2605,7 +2733,7 @@ void CL_InitLocal( void ) Cmd_AddCommand ("record", CL_Record_f, "record a demo" ); Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "play a demo" ); Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "demo benchmark" ); - Cmd_AddCommand ("killdemo", CL_DeleteDemo_f, "delete a specified demo file and demoshot" ); + Cmd_AddCommand ("killdemo", CL_DeleteDemo_f, "delete a specified demo file" ); Cmd_AddCommand ("startdemos", CL_StartDemos_f, "start playing back the selected demos sequentially" ); Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" ); Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" ); @@ -2627,12 +2755,13 @@ void CL_InitLocal( void ) Cmd_AddCommand ("skyshot", CL_SkyShot_f, "takes a six-sides envmap (skybox) shot with specified name" ); Cmd_AddCommand ("levelshot", CL_LevelShot_f, "same as \"screenshot\", used for create plaque images" ); Cmd_AddCommand ("saveshot", CL_SaveShot_f, "used for create save previews with LoadGame menu" ); - Cmd_AddCommand ("demoshot", CL_DemoShot_f, "used for create demo previews with PlayDemo menu" ); Cmd_AddCommand ("connect", CL_Connect_f, "connect to a server by hostname" ); Cmd_AddCommand ("reconnect", CL_Reconnect_f, "reconnect to current level" ); Cmd_AddCommand ("rcon", CL_Rcon_f, "sends a command to the server console (rcon_password and rcon_address required)" ); + Cmd_AddCommand ("precache", CL_LegacyPrecache_f, "legacy server compatibility" ); + } //============================================================================ @@ -2753,12 +2882,6 @@ void Host_ClientFrame( void ) // update audio SND_UpdateSound (); - // animate lightestyles - CL_RunLightStyles (); - - // decay dynamic lights - CL_DecayLights (); - // play avi-files SCR_RunCinematic (); @@ -2787,6 +2910,7 @@ void CL_Init( void ) MSG_Init( &cls.datagram, "cls.datagram", cls.datagram_buf, sizeof( cls.datagram_buf )); IN_TouchInit(); + Con_LoadHistory(); if( !CL_LoadProgs( va( "%s/%s", GI->dll_path, SI.clientlib))) Host_Error( "can't initialize %s: %s\n", SI.clientlib, COM_GetLibraryError() ); diff --git a/engine/client/cl_mobile.c b/engine/client/cl_mobile.c index d3dd0286..af11a7aa 100644 --- a/engine/client/cl_mobile.c +++ b/engine/client/cl_mobile.c @@ -21,10 +21,7 @@ GNU General Public License for more details. #include "library.h" #include "gl_local.h" #include "input.h" - -#if defined(__ANDROID__) -#include "platform/android/android-main.h" -#endif +#include "platform/platform.h" mobile_engfuncs_t *gMobileEngfuncs; @@ -38,23 +35,21 @@ static void pfnVibrate( float life, char flags ) if( life < 0.0f ) { - MsgDev( D_WARN, "Negative vibrate time: %f\n", life ); + Con_Reportf( S_WARN "Negative vibrate time: %f\n", life ); return; } - //MsgDev( D_NOTE, "Vibrate: %f %d\n", life, flags ); + //Con_Reportf( "Vibrate: %f %d\n", life, flags ); // here goes platform-specific backends -#ifdef __ANDROID__ - Android_Vibrate( life * vibration_length->value, flags ); -#endif + Platform_Vibrate( life * vibration_length->value, flags ); } static void Vibrate_f() { if( Cmd_Argc() != 2 ) { - Msg( "Usage: vibrate