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