mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
Compare commits
148 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca3b4a9d7f | ||
|
|
87ac217887 | ||
|
|
213650db8f | ||
|
|
ac46164a6e | ||
|
|
6d12d84e94 | ||
|
|
2a18cde60c | ||
|
|
35783bcec2 | ||
|
|
1677835b45 | ||
|
|
2f2780cb1b | ||
|
|
95b134b5a6 | ||
|
|
f60e856f35 | ||
|
|
2ec0d25d85 | ||
|
|
fcd0982524 | ||
|
|
6881ee742d | ||
|
|
f070bbef3c | ||
|
|
dd8c66d90e | ||
|
|
f995d055b5 | ||
|
|
fed65dd497 | ||
|
|
c896425ad9 | ||
|
|
4107bd4e0f | ||
|
|
156b2b2b10 | ||
|
|
13a063bf7d | ||
|
|
ef786b7d79 | ||
|
|
5c0c1b1226 | ||
|
|
d041b2aa27 | ||
|
|
f6d489e038 | ||
|
|
d34fedea69 | ||
|
|
80b3f90091 | ||
|
|
2a4fafc3f9 | ||
|
|
9b3ccf5f04 | ||
|
|
f59ac2360a | ||
|
|
ff21fb42e6 | ||
|
|
288cac69de | ||
|
|
2640b6d869 | ||
|
|
d8910b0e38 | ||
|
|
049bed555e | ||
|
|
fe5944720b | ||
|
|
665c46b281 | ||
|
|
975ab6785e | ||
|
|
6fa4dbfba2 | ||
|
|
0506a1dfce | ||
|
|
908a9930e6 | ||
|
|
7d7e72196b | ||
|
|
7cc67157e5 | ||
|
|
b7ff9c7a24 | ||
|
|
aab1fa1ba2 | ||
|
|
effeba2f44 | ||
|
|
e039ef35c0 | ||
|
|
599a1f026e | ||
|
|
39cba17f01 | ||
|
|
17e106f96d | ||
|
|
081cf9132b | ||
|
|
6a7e027248 | ||
|
|
27100e7751 | ||
|
|
75d9ed341a | ||
|
|
1a0867523d | ||
|
|
7584bbe47e | ||
|
|
505b6cc264 | ||
|
|
24f23908be | ||
|
|
43bd73f37b | ||
|
|
bb2753cbfc | ||
|
|
5568eccc8a | ||
|
|
c3b2cc4423 | ||
|
|
d84130219f | ||
|
|
d97d4d6c42 | ||
|
|
15798aaf52 | ||
|
|
e53892e827 | ||
|
|
cb12af69ed | ||
|
|
e82050a4bc | ||
|
|
e4edd2da45 | ||
|
|
4f80922358 | ||
|
|
ae7ed03376 | ||
|
|
c082e46662 | ||
|
|
b0bbcab6b4 | ||
|
|
0fc83080ec | ||
|
|
73883b504f | ||
|
|
8efc9d74e8 | ||
|
|
373321ff00 | ||
|
|
a508467aac | ||
|
|
abbe993e80 | ||
|
|
c644e4d569 | ||
|
|
c200e008f1 | ||
|
|
e95a2da6d0 | ||
|
|
8afca1a79c | ||
|
|
827c9ca857 | ||
|
|
2416635ba3 | ||
|
|
39eec89580 | ||
|
|
98d88266a6 | ||
|
|
0f3359fc05 | ||
|
|
6c77608c34 | ||
|
|
abdff6eff6 | ||
|
|
95a75465c9 | ||
|
|
119926805f | ||
|
|
f749b5cb4b | ||
|
|
c29ad6b598 | ||
|
|
4c5dfb963e | ||
|
|
e11f9e05d4 | ||
|
|
5c8b5b3511 | ||
|
|
2ea7162287 | ||
|
|
e62ab51842 | ||
|
|
f1bc9b87b1 | ||
|
|
a9bddaac64 | ||
|
|
6cef6f6a75 | ||
|
|
25ea6ed500 | ||
|
|
3d5173f257 | ||
|
|
05ff0d6020 | ||
|
|
3cea12627e | ||
|
|
b59b7c1a8d | ||
|
|
dd2c369df3 | ||
|
|
8b79e49a0f | ||
|
|
4ea6eba8f2 | ||
|
|
f649076bc3 | ||
|
|
8ecffa4663 | ||
|
|
e90b83849a | ||
|
|
d517b9717a | ||
|
|
2c0d6e06be | ||
|
|
dec71850a1 | ||
|
|
b1860972c6 | ||
|
|
1f4c9b67da | ||
|
|
c2da125358 | ||
|
|
31fa990d44 | ||
|
|
d3e60c7d84 | ||
|
|
e2424b4303 | ||
|
|
240563cd1b | ||
|
|
d708cd58fb | ||
|
|
491b503f96 | ||
|
|
636a2228f6 | ||
|
|
bb03e2597c | ||
|
|
21c828ee40 | ||
|
|
132c9de142 | ||
|
|
9d9507d77f | ||
|
|
7daa6c3451 | ||
|
|
c8e1ffe0dd | ||
|
|
b5f02324a6 | ||
|
|
47f5dfdcfd | ||
|
|
33da68b013 | ||
|
|
618ec83c9d | ||
|
|
85de61ebc8 | ||
|
|
2feaae59f7 | ||
|
|
2550d7fbd3 | ||
|
|
565f717804 | ||
|
|
b56c83a2f9 | ||
|
|
bf17996f72 | ||
|
|
a3acb1c85b | ||
|
|
d4d63301e0 | ||
|
|
e9af0c9810 | ||
|
|
131ad9c790 | ||
|
|
bfcaba54dc |
15
.cirrus.yml
15
.cirrus.yml
@@ -1,16 +1,3 @@
|
|||||||
task:
|
|
||||||
# Seems packages for it were removed from the mirrors
|
|
||||||
# name: freebsd-12-amd64
|
|
||||||
# freebsd_instance:
|
|
||||||
# image_family: freebsd-12-4
|
|
||||||
# setup_script:
|
|
||||||
# - pkg update
|
|
||||||
# - pkg install -y pkgconf git sdl2 python fontconfig opus
|
|
||||||
# - git submodule update --init --recursive
|
|
||||||
# test_script:
|
|
||||||
# - ./scripts/cirrus/build_freebsd.sh dedicated
|
|
||||||
# - ./scripts/cirrus/build_freebsd.sh full
|
|
||||||
|
|
||||||
task:
|
task:
|
||||||
name: freebsd-13-amd64
|
name: freebsd-13-amd64
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
@@ -26,7 +13,7 @@ task:
|
|||||||
task:
|
task:
|
||||||
name: freebsd-14-amd64
|
name: freebsd-14-amd64
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-14-0-snap
|
image_family: freebsd-14-0
|
||||||
setup_script:
|
setup_script:
|
||||||
- pkg update
|
- pkg update
|
||||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||||
|
|||||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
custom: https://github.com/FWGS/xash3d-fwgs/blob/master/Documentation/donate.md
|
||||||
12
.github/workflows/c-cpp.yml
vendored
12
.github/workflows/c-cpp.yml
vendored
@@ -24,14 +24,9 @@ jobs:
|
|||||||
# - os: ubuntu-aarch64-20.04
|
# - os: ubuntu-aarch64-20.04
|
||||||
# targetos: linux
|
# targetos: linux
|
||||||
# targetarch: aarch64
|
# targetarch: aarch64
|
||||||
|
- os: ubuntu-20.04
|
||||||
# - os: ubuntu-20.04
|
targetos: android
|
||||||
# targetos: android
|
targetarch: multiarch
|
||||||
# targetarch: 32
|
|
||||||
# - os: ubuntu-20.04
|
|
||||||
# targetos: android
|
|
||||||
# targetarch: 64
|
|
||||||
|
|
||||||
# - os: ubuntu-20.04
|
# - os: ubuntu-20.04
|
||||||
# targetos: motomagx
|
# targetos: motomagx
|
||||||
# targetarch: armv6
|
# targetarch: armv6
|
||||||
@@ -51,7 +46,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
SDL_VERSION: 2.28.5
|
SDL_VERSION: 2.28.5
|
||||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||||
ANDROID_SDK_TOOLS_VER: 4333796
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -54,6 +54,11 @@ CMakeFiles
|
|||||||
Makefile
|
Makefile
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
|
CMakeLists.txt*
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
compile_commands.json
|
||||||
|
_deps
|
||||||
# makedepend
|
# makedepend
|
||||||
Makefile.dep
|
Makefile.dep
|
||||||
*.bak
|
*.bak
|
||||||
|
|||||||
2
3rdparty/gl-wes-v2
vendored
2
3rdparty/gl-wes-v2
vendored
Submodule 3rdparty/gl-wes-v2 updated: f2a28de15d...2d9b5afe10
2
3rdparty/gl4es/gl4es
vendored
2
3rdparty/gl4es/gl4es
vendored
Submodule 3rdparty/gl4es/gl4es updated: 5226f5f937...e39434a2b1
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: 7223589d60...f5497ceb04
2
3rdparty/nanogl
vendored
2
3rdparty/nanogl
vendored
Submodule 3rdparty/nanogl updated: 6b6a947ee0...e75792de03
2
3rdparty/vgui_support
vendored
2
3rdparty/vgui_support
vendored
Submodule 3rdparty/vgui_support updated: f85d64c149...a2a7b9073f
21
Documentation/environment-variables.md
Normal file
21
Documentation/environment-variables.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
## Environment variables
|
||||||
|
|
||||||
|
#### Xash3D FWGS
|
||||||
|
|
||||||
|
The engine respects these environment variables:
|
||||||
|
|
||||||
|
| Variable | Type | Description |
|
||||||
|
| --------------------- | ---------- | ----------- |
|
||||||
|
| `XASH3D_GAME` | _string_ | Overrides default game directory. Ignored if `-game` command line argument is set |
|
||||||
|
| `XASH3D_BASEDIR` | _string_ | Sets path to base (root) directory, instead of current working directory |
|
||||||
|
| `XASH3D_RODIR` | _string_ | Sets path to read-only base (root) directory. Ignored if `-rodir` command line argument is set |
|
||||||
|
| `XASH3D_EXTRAS_PAK1` | _string_ | Archive file from specified path will be added to virtual filesystem search path in the lowest possible priority |
|
||||||
|
| `XASH3D_EXTRAS_PAK2` | _string_ | Similar to `XASH3D_EXTRAS_PAK1` but next to it in priority list |
|
||||||
|
|
||||||
|
Environment variables NOT listed in the table above are used internally, and aren't considered as stable interface.
|
||||||
|
|
||||||
|
#### mdldec
|
||||||
|
|
||||||
|
| Variable | Type | Description |
|
||||||
|
| --------------------- | ---------- | ----------- |
|
||||||
|
| `MDLDEC_ACT_PATH` | _string_ | If set, will read activities list from this path |
|
||||||
25
Documentation/extensions/native-object.md
Normal file
25
Documentation/extensions/native-object.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# GetNativeObject API
|
||||||
|
|
||||||
|
To be able to use platform-specific features or get optional engine interfaces, we've added a simple call to MobilityAPI on client DLL and PhysicsAPI for server DLL and extended MenuAPI for menu DLL.
|
||||||
|
|
||||||
|
It's defined like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
void *pfnGetNativeObject( const char *name );
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Cross-platform objects
|
||||||
|
|
||||||
|
Only these objects are guaranteed to be available on all targets.
|
||||||
|
|
||||||
|
| Object name | Interface |
|
||||||
|
|-------------|-----------|
|
||||||
|
| `VFileSystem009` | Provides C++ interface to filesystem, binary-compatible with Valve's VFileSystem009. |
|
||||||
|
| `XashFileSystemXXX` | Provides C interface to filesystem. This interface is unstable and not recommended for generic use, outside of engine internals. For more info about current version look into `filesystem.h`. |
|
||||||
|
|
||||||
|
#### Android-specific objects
|
||||||
|
|
||||||
|
| Object name | Interface |
|
||||||
|
|-------------|-----------|
|
||||||
|
| `JNIEnv` | Allows interfacing with Java Native Interface. |
|
||||||
|
| `ActivityClass` | Returns JNI object for engine Android activity class. |
|
||||||
65
Documentation/extensions/sounds.lst.md
Normal file
65
Documentation/extensions/sounds.lst.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# sounds.lst.md
|
||||||
|
|
||||||
|
Using sounds.lst located in scripts folder, modder can override some of the hardcoded sounds in temp entities and server physics.
|
||||||
|
|
||||||
|
File format:
|
||||||
|
```
|
||||||
|
<group name>
|
||||||
|
{
|
||||||
|
<path1>
|
||||||
|
<path2>
|
||||||
|
<path3>
|
||||||
|
}
|
||||||
|
|
||||||
|
<group2 name> <path with %d> <min number> <max number>
|
||||||
|
```
|
||||||
|
|
||||||
|
* Sounds can use any supported sound format (WAV or MP3).
|
||||||
|
* The path must be relative to the sounds/ folder in the game or base directory root, addon folder, or archive root.
|
||||||
|
* Groups can be empty or omitted from the file to load no sound.
|
||||||
|
* Groups can either list a set of files or specify a format string and a range.
|
||||||
|
* Anything after // will be considered a comment and ignored.
|
||||||
|
* Behavior is undefined if the group was listed multiple times.
|
||||||
|
|
||||||
|
Currently supported groups are:
|
||||||
|
|Group name|Usage|
|
||||||
|
|----------|-----|
|
||||||
|
|`BouncePlayerShell`|Used for BOUNCE_SHELL tempentity hitsound|
|
||||||
|
|`BounceWeaponShell`|Used for BOUCNE_SHOTSHELL tempentity hitsound|
|
||||||
|
|`BounceConcrete`|Used for BOUNCE_CONCRETE tempentity hitsound|
|
||||||
|
|`BounceGlass`|Used for BOUCNE_GLASS|
|
||||||
|
|`BounceMetal`|Used for BOUNCE_METAL|
|
||||||
|
|`BounceFlesh`|Used for BOUNCE_FLESH|
|
||||||
|
|`BounceWood`|Used for BOUNCE_WOOD|
|
||||||
|
|`Ricochet`|Used for BOUNCE_SHRAP and ricochet tempentities|
|
||||||
|
|`Explode`|Used for tempentity explosions|
|
||||||
|
|`EntityWaterEnter`|Used for entity entering water|
|
||||||
|
|`EntityWaterExit`|Used for entity exiting water|
|
||||||
|
|`PlayerWaterEnter`|Used for player entering water|
|
||||||
|
|`PlayerWaterExit`|Used for player exiting water|
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
This example is based on defaults sounds used in Half-Life:
|
||||||
|
|
||||||
|
```
|
||||||
|
BouncePlayerShell "player/pl_shell%d.wav" 1 3
|
||||||
|
BounceWeaponShell "weapons/sshell%d.wav" 1 3
|
||||||
|
BounceConcrete "debris/concrete%d.wav" 1 3
|
||||||
|
BounceGlass "debris/glass%d.wav" 1 4
|
||||||
|
BounceMetal "debris/metal%d.wav" 1 6
|
||||||
|
BounceFlesh "debris/flesh%d.wav" 1 7
|
||||||
|
BounceWood "debris/wood%d.wav" 1 4
|
||||||
|
Ricochet "weapons/ric%d.wav" 1 5
|
||||||
|
Explode "weapons/explode%d.wav" 3 5
|
||||||
|
EntityWaterEnter "player/pl_wade%d.wav" 1 4
|
||||||
|
EntityWaterExit "player/pl_wade%d.wav" 1 4
|
||||||
|
PlayerWaterEnter
|
||||||
|
{
|
||||||
|
"player/pl_wade1.wav"
|
||||||
|
}
|
||||||
|
PlayerWaterExit
|
||||||
|
{
|
||||||
|
"player/pl_wade2.wav"
|
||||||
|
}
|
||||||
|
```
|
||||||
15
Documentation/musl.md
Normal file
15
Documentation/musl.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Xash3D FWGS on `musl`
|
||||||
|
|
||||||
|
Xash3D FWGS works on `musl` out of the box. However, the engine doesn't try to differentiate glibc and musl anymore. If you see error similar to:
|
||||||
|
|
||||||
|
```
|
||||||
|
Host_InitError: can't initialize cl_dlls/client.so: Error relocating valve/cl_dlls/client.so: __sprintf_chk: symbol not found
|
||||||
|
```
|
||||||
|
|
||||||
|
... or you know that the game you're running is linked against glibc, you can try using `libgcompat`, like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ LD_PRELOAD=/lib/libgcompat.so.0 ./xash3d ...
|
||||||
|
```
|
||||||
|
|
||||||
|
It will automatically add the missing symbols that glibc binaries usually need. In the future we might automatically link engine against `libgcompat` for better compatibility with prebuilt or closed-source games, if there will be any use for this.
|
||||||
@@ -534,5 +534,14 @@ typedef struct
|
|||||||
#define MAX_EFRAGS 8192 // Arcane Dimensions required
|
#define MAX_EFRAGS 8192 // Arcane Dimensions required
|
||||||
#define MAX_REQUESTS 64
|
#define MAX_REQUESTS 64
|
||||||
|
|
||||||
|
#if ! XASH_64BIT
|
||||||
|
STATIC_ASSERT( sizeof( mextrasurf_t ) == 324, "mextrasurf_t unexpected size" );
|
||||||
|
STATIC_ASSERT( sizeof( decal_t ) == 60, "decal_t unexpected size");
|
||||||
|
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 176, "mfaceinfo_t unexpected size");
|
||||||
|
#else
|
||||||
|
STATIC_ASSERT( sizeof( mextrasurf_t) == 496, "mextrasurf_t unexpected size");
|
||||||
|
STATIC_ASSERT( sizeof( decal_t ) == 88, "decal_t unexpected size");
|
||||||
|
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 304, "mfaceinfo_t unexpected size");
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif//COM_MODEL_H
|
#endif//COM_MODEL_H
|
||||||
|
|||||||
@@ -86,8 +86,6 @@ typedef uint64_t longtime_t;
|
|||||||
#define NORETURN __attribute__((noreturn))
|
#define NORETURN __attribute__((noreturn))
|
||||||
#define NONNULL __attribute__((nonnull))
|
#define NONNULL __attribute__((nonnull))
|
||||||
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
|
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
|
||||||
#define FORCEINLINE inline __attribute__((always_inline))
|
|
||||||
#define NOINLINE __attribute__((noinline))
|
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define EXPORT __declspec( dllexport )
|
#define EXPORT __declspec( dllexport )
|
||||||
#define GAME_EXPORT
|
#define GAME_EXPORT
|
||||||
@@ -95,8 +93,6 @@ typedef uint64_t longtime_t;
|
|||||||
#define NORETURN
|
#define NORETURN
|
||||||
#define NONNULL
|
#define NONNULL
|
||||||
#define ALLOC_CHECK(x)
|
#define ALLOC_CHECK(x)
|
||||||
#define FORCEINLINE __forceinline
|
|
||||||
#define NOINLINE __declspec( noinline )
|
|
||||||
#else
|
#else
|
||||||
#define EXPORT
|
#define EXPORT
|
||||||
#define GAME_EXPORT
|
#define GAME_EXPORT
|
||||||
@@ -104,8 +100,6 @@ typedef uint64_t longtime_t;
|
|||||||
#define NORETURN
|
#define NORETURN
|
||||||
#define NONNULL
|
#define NONNULL
|
||||||
#define ALLOC_CHECK(x)
|
#define ALLOC_CHECK(x)
|
||||||
#define FORCEINLINE
|
|
||||||
#define NOINLINE
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ( __GNUC__ >= 3 )
|
#if ( __GNUC__ >= 3 )
|
||||||
|
|||||||
@@ -46,10 +46,35 @@ static int CL_LoadFontTexture( const char *fontname, uint texFlags, int *width )
|
|||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
|
static int CL_FontRenderMode( convar_t *fontrender )
|
||||||
|
{
|
||||||
|
switch((int)fontrender->value )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return kRenderTransAdd;
|
||||||
|
case 1:
|
||||||
|
return kRenderTransAlpha;
|
||||||
|
case 2:
|
||||||
|
return kRenderTransTexture;
|
||||||
|
default:
|
||||||
|
Cvar_DirectSet( fontrender, fontrender->def_string );
|
||||||
|
}
|
||||||
|
|
||||||
|
return kRenderTransTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CL_SetFontRendermode( cl_font_t *font )
|
||||||
|
{
|
||||||
|
ref.dllFuncs.GL_SetRenderMode( CL_FontRenderMode( font->rendermode ));
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags )
|
||||||
{
|
{
|
||||||
int font_width, i;
|
int font_width, i;
|
||||||
|
|
||||||
|
if( !rendermode )
|
||||||
|
return false;
|
||||||
|
|
||||||
if( font->valid )
|
if( font->valid )
|
||||||
return true; // already loaded
|
return true; // already loaded
|
||||||
|
|
||||||
@@ -76,13 +101,16 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
|
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags )
|
||||||
{
|
{
|
||||||
fs_offset_t length;
|
fs_offset_t length;
|
||||||
qfont_t src;
|
qfont_t src;
|
||||||
byte *pfile;
|
byte *pfile;
|
||||||
int font_width, i;
|
int font_width, i;
|
||||||
|
|
||||||
|
if( !rendermode )
|
||||||
|
return false;
|
||||||
|
|
||||||
if( font->valid )
|
if( font->valid )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -105,7 +133,7 @@ qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float
|
|||||||
|
|
||||||
font->type = FONT_VARIABLE;
|
font->type = FONT_VARIABLE;
|
||||||
font->valid = true;
|
font->valid = true;
|
||||||
font->scale = scale;
|
font->scale = scale ? scale : 1.0f;
|
||||||
font->rendermode = rendermode;
|
font->rendermode = rendermode;
|
||||||
font->charHeight = Q_rint( src.rowheight * scale );
|
font->charHeight = Q_rint( src.rowheight * scale );
|
||||||
|
|
||||||
@@ -177,7 +205,8 @@ int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *fon
|
|||||||
return font->charWidths[number];
|
return font->charWidths[number];
|
||||||
|
|
||||||
rc = &font->fontRc[number];
|
rc = &font->fontRc[number];
|
||||||
if( font->scale <= 1.0f || REF_GET_PARM( PARM_TEX_FILTERING, font->hFontTexture ))
|
|
||||||
|
if( font->scale <= 1.f || !REF_GET_PARM( PARM_TEX_FILTERING, font->hFontTexture ))
|
||||||
half = 0;
|
half = 0;
|
||||||
|
|
||||||
s1 = ((float)rc->left + half ) / texw;
|
s1 = ((float)rc->left + half ) / texw;
|
||||||
@@ -191,7 +220,7 @@ int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *fon
|
|||||||
SPR_AdjustSize( &x, &y, &w, &h );
|
SPR_AdjustSize( &x, &y, &w, &h );
|
||||||
|
|
||||||
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
||||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
CL_SetFontRendermode( font );
|
||||||
|
|
||||||
// don't apply color to fixed fonts it's already colored
|
// don't apply color to fixed fonts it's already colored
|
||||||
if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
|
if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
|
||||||
@@ -214,7 +243,7 @@ int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *fon
|
|||||||
Con_UtfProcessChar( 0 ); // clear utf state
|
Con_UtfProcessChar( 0 ); // clear utf state
|
||||||
|
|
||||||
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
||||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
CL_SetFontRendermode( font );
|
||||||
|
|
||||||
Vector4Copy( color, current_color );
|
Vector4Copy( color, current_color );
|
||||||
|
|
||||||
|
|||||||
@@ -474,8 +474,7 @@ void CL_DrawCenterPrint( void )
|
|||||||
pText = clgame.centerPrint.message;
|
pText = clgame.centerPrint.message;
|
||||||
|
|
||||||
CL_DrawCharacterLen( font, 0, NULL, &charHeight );
|
CL_DrawCharacterLen( font, 0, NULL, &charHeight );
|
||||||
|
CL_SetFontRendermode( font );
|
||||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
|
||||||
for( i = 0; i < clgame.centerPrint.lines; i++ )
|
for( i = 0; i < clgame.centerPrint.lines; i++ )
|
||||||
{
|
{
|
||||||
lineLength = 0;
|
lineLength = 0;
|
||||||
@@ -1449,7 +1448,7 @@ pfnSPR_Draw
|
|||||||
*/
|
*/
|
||||||
static void GAME_EXPORT pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc )
|
static void GAME_EXPORT pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc )
|
||||||
{
|
{
|
||||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
ref.dllFuncs.GL_SetRenderMode( kRenderTransAlpha );
|
||||||
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1714,7 +1713,8 @@ pfnCvar_RegisterVariable
|
|||||||
static cvar_t *GAME_EXPORT pfnCvar_RegisterClientVariable( const char *szName, const char *szValue, int flags )
|
static cvar_t *GAME_EXPORT pfnCvar_RegisterClientVariable( const char *szName, const char *szValue, int flags )
|
||||||
{
|
{
|
||||||
// a1ba: try to mitigate outdated client.dll vulnerabilities
|
// a1ba: try to mitigate outdated client.dll vulnerabilities
|
||||||
if( !Q_stricmp( szName, "motdfile" ))
|
if( !Q_stricmp( szName, "motdfile" )
|
||||||
|
|| !Q_stricmp( szName, "sensitivity" ))
|
||||||
flags |= FCVAR_PRIVILEGED;
|
flags |= FCVAR_PRIVILEGED;
|
||||||
|
|
||||||
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL ));
|
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL ));
|
||||||
|
|||||||
@@ -1220,6 +1220,7 @@ static ui_extendedfuncs_t gExtendedfuncs =
|
|||||||
pfnParseFileSafe,
|
pfnParseFileSafe,
|
||||||
NET_AdrToString,
|
NET_AdrToString,
|
||||||
NET_CompareAdrSort,
|
NET_CompareAdrSort,
|
||||||
|
Sys_GetNativeObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
void UI_UnloadProgs( void )
|
void UI_UnloadProgs( void )
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ GNU General Public License for more details.
|
|||||||
#define MAX_CMD_BUFFER 8000
|
#define MAX_CMD_BUFFER 8000
|
||||||
#define CONNECTION_PROBLEM_TIME 15.0 // 15 seconds
|
#define CONNECTION_PROBLEM_TIME 15.0 // 15 seconds
|
||||||
#define CL_CONNECTION_RETRIES 10
|
#define CL_CONNECTION_RETRIES 10
|
||||||
#define CL_TEST_RETRIES_NORESPONCE 3
|
|
||||||
#define CL_TEST_RETRIES 5
|
#define CL_TEST_RETRIES 5
|
||||||
|
|
||||||
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
|
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
|
||||||
@@ -61,6 +60,7 @@ CVAR_DEFINE_AUTO( cl_smoothtime, "0.1", FCVAR_ARCHIVE, "time to smooth up" );
|
|||||||
CVAR_DEFINE_AUTO( cl_clockreset, "0.1", FCVAR_ARCHIVE, "frametime delta maximum value before reset" );
|
CVAR_DEFINE_AUTO( cl_clockreset, "0.1", FCVAR_ARCHIVE, "frametime delta maximum value before reset" );
|
||||||
CVAR_DEFINE_AUTO( cl_fixtimerate, "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" );
|
CVAR_DEFINE_AUTO( cl_fixtimerate, "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" );
|
||||||
CVAR_DEFINE_AUTO( hud_fontscale, "1.0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud font texture" );
|
CVAR_DEFINE_AUTO( hud_fontscale, "1.0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud font texture" );
|
||||||
|
CVAR_DEFINE_AUTO( hud_fontrender, "0", FCVAR_ARCHIVE, "hud font render mode (0: additive, 1: holes, 2: trans)" );
|
||||||
CVAR_DEFINE_AUTO( hud_scale, "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" );
|
CVAR_DEFINE_AUTO( hud_scale, "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" );
|
||||||
CVAR_DEFINE_AUTO( hud_scale_minimal_width, "640", FCVAR_ARCHIVE|FCVAR_LATCH, "if hud_scale results in a HUD virtual screen smaller than this value, it won't be applied" );
|
CVAR_DEFINE_AUTO( hud_scale_minimal_width, "640", FCVAR_ARCHIVE|FCVAR_LATCH, "if hud_scale results in a HUD virtual screen smaller than this value, it won't be applied" );
|
||||||
CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" );
|
CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" );
|
||||||
@@ -74,8 +74,9 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
|
|||||||
|
|
||||||
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
|
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
|
||||||
CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
|
CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
|
||||||
CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)");
|
CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable stufftext (server-to-client console commands) tracing (good for developers)" );
|
||||||
CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)");
|
CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" );
|
||||||
|
CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" );
|
||||||
static CVAR_DEFINE_AUTO( cl_nat, "0", 0, "show servers running under NAT" );
|
static CVAR_DEFINE_AUTO( cl_nat, "0", 0, "show servers running under NAT" );
|
||||||
CVAR_DEFINE_AUTO( hud_utf8, "0", FCVAR_ARCHIVE, "Use utf-8 encoding for hud text" );
|
CVAR_DEFINE_AUTO( hud_utf8, "0", FCVAR_ARCHIVE, "Use utf-8 encoding for hud text" );
|
||||||
CVAR_DEFINE_AUTO( ui_renderworld, "0", FCVAR_ARCHIVE, "render world when UI is visible" );
|
CVAR_DEFINE_AUTO( ui_renderworld, "0", FCVAR_ARCHIVE, "render world when UI is visible" );
|
||||||
@@ -1070,6 +1071,22 @@ static void CL_SendConnectPacket( void )
|
|||||||
cls.timestart = Sys_DoubleTime();
|
cls.timestart = Sys_DoubleTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CL_GetTestFragmentSize
|
||||||
|
|
||||||
|
Returns bandwidth test fragment size
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static int CL_GetTestFragmentSize( void )
|
||||||
|
{
|
||||||
|
const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
|
||||||
|
if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES )
|
||||||
|
return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE );
|
||||||
|
else
|
||||||
|
return FRAGMENT_MIN_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CL_CheckForResend
|
CL_CheckForResend
|
||||||
@@ -1081,8 +1098,9 @@ static void CL_CheckForResend( void )
|
|||||||
{
|
{
|
||||||
netadr_t adr;
|
netadr_t adr;
|
||||||
net_gai_state_t res;
|
net_gai_state_t res;
|
||||||
|
float resendTime;
|
||||||
qboolean bandwidthTest;
|
qboolean bandwidthTest;
|
||||||
|
|
||||||
if( cls.internetservers_wait )
|
if( cls.internetservers_wait )
|
||||||
CL_SendMasterServerScanRequest();
|
CL_SendMasterServerScanRequest();
|
||||||
|
|
||||||
@@ -1108,7 +1126,10 @@ static void CL_CheckForResend( void )
|
|||||||
else if( cl_resend.value > CL_MAX_RESEND_TIME )
|
else if( cl_resend.value > CL_MAX_RESEND_TIME )
|
||||||
Cvar_SetValue( "cl_resend", CL_MAX_RESEND_TIME );
|
Cvar_SetValue( "cl_resend", CL_MAX_RESEND_TIME );
|
||||||
|
|
||||||
if(( host.realtime - cls.connect_time ) < cl_resend.value )
|
bandwidthTest = !cls.legacymode && cl_test_bandwidth.value && cls.connect_retry <= CL_TEST_RETRIES;
|
||||||
|
resendTime = bandwidthTest ? 1.0f : cl_resend.value;
|
||||||
|
|
||||||
|
if(( host.realtime - cls.connect_time ) < resendTime )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
res = NET_StringToAdrNB( cls.servername, &adr );
|
res = NET_StringToAdrNB( cls.servername, &adr );
|
||||||
@@ -1135,10 +1156,11 @@ static void CL_CheckForResend( void )
|
|||||||
|
|
||||||
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
|
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
|
||||||
|
|
||||||
if( cls.connect_retry == CL_TEST_RETRIES_NORESPONCE )
|
if( cls.connect_retry == CL_TEST_RETRIES )
|
||||||
{
|
{
|
||||||
// too many fails use default connection method
|
// too many fails use default connection method
|
||||||
Con_Printf( "hi-speed connection is failed, use default method\n" );
|
Con_Printf( "Bandwidth test failed, fallback to default connecting method\n" );
|
||||||
|
Con_Printf( "Connecting to %s... (retry #%i)\n", cls.servername, cls.connect_retry + 1 );
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
|
||||||
Cvar_SetValue( "cl_dlmax", FRAGMENT_MIN_SIZE );
|
Cvar_SetValue( "cl_dlmax", FRAGMENT_MIN_SIZE );
|
||||||
cls.connect_time = host.realtime;
|
cls.connect_time = host.realtime;
|
||||||
@@ -1146,16 +1168,15 @@ static void CL_CheckForResend( void )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bandwidthTest = !cls.legacymode && cl_test_bandwidth.value;
|
|
||||||
cls.serveradr = adr;
|
cls.serveradr = adr;
|
||||||
cls.max_fragment_size = Q_min( FRAGMENT_MAX_SIZE, cls.max_fragment_size / (cls.connect_retry + 1));
|
cls.max_fragment_size = CL_GetTestFragmentSize();
|
||||||
cls.connect_time = host.realtime; // for retransmit requests
|
cls.connect_time = host.realtime; // for retransmit requests
|
||||||
cls.connect_retry++;
|
cls.connect_retry++;
|
||||||
|
|
||||||
if( bandwidthTest )
|
if( bandwidthTest )
|
||||||
Con_Printf( "Connecting to %s... [retry #%i, max fragment size %i]\n", cls.servername, cls.connect_retry, cls.max_fragment_size );
|
Con_Printf( "Connecting to %s... (retry #%i, fragment size %i)\n", cls.servername, cls.connect_retry, cls.max_fragment_size );
|
||||||
else
|
else
|
||||||
Con_Printf( "Connecting to %s... [retry #%i]\n", cls.servername, cls.connect_retry );
|
Con_Printf( "Connecting to %s... (retry #%i)\n", cls.servername, cls.connect_retry );
|
||||||
|
|
||||||
if( bandwidthTest )
|
if( bandwidthTest )
|
||||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
|
Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
|
||||||
@@ -2891,6 +2912,7 @@ static void CL_InitLocal( void )
|
|||||||
|
|
||||||
Cvar_RegisterVariable( &rcon_address );
|
Cvar_RegisterVariable( &rcon_address );
|
||||||
|
|
||||||
|
Cvar_RegisterVariable( &cl_trace_stufftext );
|
||||||
Cvar_RegisterVariable( &cl_trace_messages );
|
Cvar_RegisterVariable( &cl_trace_messages );
|
||||||
Cvar_RegisterVariable( &cl_trace_events );
|
Cvar_RegisterVariable( &cl_trace_events );
|
||||||
|
|
||||||
@@ -2926,6 +2948,7 @@ static void CL_InitLocal( void )
|
|||||||
Cvar_RegisterVariable( &cl_clockreset );
|
Cvar_RegisterVariable( &cl_clockreset );
|
||||||
Cvar_RegisterVariable( &cl_fixtimerate );
|
Cvar_RegisterVariable( &cl_fixtimerate );
|
||||||
Cvar_RegisterVariable( &hud_fontscale );
|
Cvar_RegisterVariable( &hud_fontscale );
|
||||||
|
Cvar_RegisterVariable( &hud_fontrender );
|
||||||
Cvar_RegisterVariable( &hud_scale );
|
Cvar_RegisterVariable( &hud_scale );
|
||||||
Cvar_RegisterVariable( &hud_scale_minimal_width );
|
Cvar_RegisterVariable( &hud_scale_minimal_width );
|
||||||
Cvar_Get( "cl_background", "0", FCVAR_READ_ONLY, "indicate what background map is running" );
|
Cvar_Get( "cl_background", "0", FCVAR_READ_ONLY, "indicate what background map is running" );
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
|
|||||||
// move rolling average
|
// move rolling average
|
||||||
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate;
|
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate;
|
||||||
|
|
||||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
CL_SetFontRendermode( font );
|
||||||
|
|
||||||
if( framerate > 0.0f )
|
if( framerate > 0.0f )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1382,9 +1382,13 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
|||||||
if( slot >= MAX_CLIENTS )
|
if( slot >= MAX_CLIENTS )
|
||||||
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" );
|
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" );
|
||||||
|
|
||||||
|
player = &cl.players[slot];
|
||||||
|
|
||||||
if( !legacy )
|
if( !legacy )
|
||||||
id = MSG_ReadLong( msg ); // unique user ID
|
id = MSG_ReadLong( msg ); // unique user ID
|
||||||
player = &cl.players[slot];
|
else
|
||||||
|
id = 0; // bogus
|
||||||
|
|
||||||
active = MSG_ReadOneBit( msg ) ? true : false;
|
active = MSG_ReadOneBit( msg ) ? true : false;
|
||||||
|
|
||||||
if( active )
|
if( active )
|
||||||
@@ -1406,6 +1410,10 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
|||||||
|
|
||||||
memset( player, 0, sizeof( *player ));
|
memset( player, 0, sizeof( *player ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in GoldSrc userinfo might be empty but userid is always sent as separate value
|
||||||
|
// thus avoids clean up even after client disconnect
|
||||||
|
player->userid = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2321,11 +2329,18 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
|||||||
break;
|
break;
|
||||||
case svc_stufftext:
|
case svc_stufftext:
|
||||||
s = MSG_ReadString( msg );
|
s = MSG_ReadString( msg );
|
||||||
|
if( cl_trace_stufftext.value )
|
||||||
|
{
|
||||||
|
size_t len = Q_strlen( s );
|
||||||
|
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HACKS_RELATED_HLMODS
|
#ifdef HACKS_RELATED_HLMODS
|
||||||
// disable Cry Of Fear antisave protection
|
// disable Cry Of Fear antisave protection
|
||||||
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
|
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
|
||||||
break; // too early
|
break; // too early
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Cbuf_AddFilteredText( s );
|
Cbuf_AddFilteredText( s );
|
||||||
break;
|
break;
|
||||||
case svc_setangle:
|
case svc_setangle:
|
||||||
|
|||||||
@@ -443,13 +443,17 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
|
|||||||
break;
|
break;
|
||||||
case svc_stufftext:
|
case svc_stufftext:
|
||||||
s = MSG_ReadString( msg );
|
s = MSG_ReadString( msg );
|
||||||
|
if( cl_trace_stufftext.value )
|
||||||
|
{
|
||||||
|
size_t len = Q_strlen( s );
|
||||||
|
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HACKS_RELATED_HLMODS
|
#ifdef HACKS_RELATED_HLMODS
|
||||||
// disable Cry Of Fear antisave protection
|
// disable Cry Of Fear antisave protection
|
||||||
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
|
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
|
||||||
break; // too early
|
break; // too early
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Con_Reportf( "Stufftext: %s", s );
|
|
||||||
Cbuf_AddFilteredText( s );
|
Cbuf_AddFilteredText( s );
|
||||||
break;
|
break;
|
||||||
case svc_setangle:
|
case svc_setangle:
|
||||||
|
|||||||
@@ -795,25 +795,14 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
|
|||||||
|
|
||||||
pmove->player_index = ps->number - 1;
|
pmove->player_index = ps->number - 1;
|
||||||
|
|
||||||
// a1ba: workaround bug on old protocol where the server refuse to send
|
// a1ba: workaround bug where the server refuse to send our local player in delta
|
||||||
// our local player in delta. cl.playernum, in theory, must be equal
|
// cl.playernum, in theory, must be equal to our local player index anyway
|
||||||
// to our local player index anyway
|
//
|
||||||
// this might not be a real solution, since everything else will be bogus
|
// this might not be a real solution, since everything else will be bogus
|
||||||
// but we need to properly run prediction and avoid potential memory
|
// but we need to properly run prediction and avoid potential memory
|
||||||
// corruption
|
// corruption
|
||||||
// either debug this, or remove when old protocol will be dropped!!!
|
|
||||||
if( pmove->player_index < 0 )
|
if( pmove->player_index < 0 )
|
||||||
{
|
pmove->player_index = bound( 0, cl.playernum, cl.maxclients - 1 );
|
||||||
if( cls.legacymode )
|
|
||||||
{
|
|
||||||
pmove->player_index = bound( 0, cl.playernum, cl.maxclients - 1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if this happens, record a demo and send it to a1ba
|
|
||||||
Host_Error( "%s: ps->number == %d\n", __func__, ps->number );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pmove->multiplayer = (cl.maxclients > 1);
|
pmove->multiplayer = (cl.maxclients > 1);
|
||||||
pmove->runfuncs = runfuncs;
|
pmove->runfuncs = runfuncs;
|
||||||
|
|||||||
@@ -288,6 +288,9 @@ void SCR_MakeScreenShot( void )
|
|||||||
qboolean iRet = false;
|
qboolean iRet = false;
|
||||||
int viewsize;
|
int viewsize;
|
||||||
|
|
||||||
|
if( cls.scrshot_action == scrshot_inactive )
|
||||||
|
return;
|
||||||
|
|
||||||
if( cls.envshot_viewsize > 0 )
|
if( cls.envshot_viewsize > 0 )
|
||||||
viewsize = cls.envshot_viewsize;
|
viewsize = cls.envshot_viewsize;
|
||||||
else viewsize = cl_envshot_size.value;
|
else viewsize = cl_envshot_size.value;
|
||||||
@@ -319,8 +322,6 @@ void SCR_MakeScreenShot( void )
|
|||||||
if( iRet )
|
if( iRet )
|
||||||
VID_WriteOverviewScript(); // store overview script too
|
VID_WriteOverviewScript(); // store overview script too
|
||||||
break;
|
break;
|
||||||
case scrshot_inactive:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// report
|
// report
|
||||||
@@ -572,15 +573,15 @@ void SCR_LoadCreditsFont( void )
|
|||||||
"creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 )
|
"creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 )
|
||||||
{
|
{
|
||||||
if( FS_FileExists( charsetFnt, false ))
|
if( FS_FileExists( charsetFnt, false ))
|
||||||
success = Con_LoadVariableWidthFont( charsetFnt, font, scale, kRenderTransAdd, TF_FONT );
|
success = Con_LoadVariableWidthFont( charsetFnt, font, scale, &hud_fontrender, TF_FONT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !success )
|
if( !success )
|
||||||
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, kRenderTransAdd, TF_FONT );
|
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, &hud_fontrender, TF_FONT );
|
||||||
|
|
||||||
if( !success )
|
if( !success )
|
||||||
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransAdd, TF_FONT );
|
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, &hud_fontrender, TF_FONT );
|
||||||
|
|
||||||
// copy font size for client.dll
|
// copy font size for client.dll
|
||||||
if( success )
|
if( success )
|
||||||
|
|||||||
@@ -57,36 +57,6 @@ const char *cl_default_sprites[] =
|
|||||||
"sprites/shellchrome.spr",
|
"sprites/shellchrome.spr",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *cl_player_shell_sounds[] =
|
|
||||||
{
|
|
||||||
"player/pl_shell1.wav",
|
|
||||||
"player/pl_shell2.wav",
|
|
||||||
"player/pl_shell3.wav",
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *cl_weapon_shell_sounds[] =
|
|
||||||
{
|
|
||||||
"weapons/sshell1.wav",
|
|
||||||
"weapons/sshell2.wav",
|
|
||||||
"weapons/sshell3.wav",
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *cl_ricochet_sounds[] =
|
|
||||||
{
|
|
||||||
"weapons/ric1.wav",
|
|
||||||
"weapons/ric2.wav",
|
|
||||||
"weapons/ric3.wav",
|
|
||||||
"weapons/ric4.wav",
|
|
||||||
"weapons/ric5.wav",
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *cl_explode_sounds[] =
|
|
||||||
{
|
|
||||||
"weapons/explode3.wav",
|
|
||||||
"weapons/explode4.wav",
|
|
||||||
"weapons/explode5.wav",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void CL_PlayerDecal( int playerIndex, int textureIndex, int entityIndex, float *pos );
|
static void CL_PlayerDecal( int playerIndex, int textureIndex, int entityIndex, float *pos );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -148,6 +118,7 @@ client resources not precached by server
|
|||||||
*/
|
*/
|
||||||
void CL_AddClientResources( void )
|
void CL_AddClientResources( void )
|
||||||
{
|
{
|
||||||
|
const char *snd;
|
||||||
char filepath[MAX_QPATH];
|
char filepath[MAX_QPATH];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -163,37 +134,37 @@ void CL_AddClientResources( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then check sounds
|
// then check sounds
|
||||||
for( i = 0; i < ARRAYSIZE( cl_player_shell_sounds ); i++ )
|
for( i = 0; ( snd = SoundList_Get( BouncePlayerShell, i )); i++ )
|
||||||
{
|
{
|
||||||
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_player_shell_sounds[i] );
|
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
|
||||||
|
|
||||||
if( !FS_FileExists( filepath, false ))
|
if( !FS_FileExists( filepath, false ))
|
||||||
CL_AddClientResource( cl_player_shell_sounds[i], t_sound );
|
CL_AddClientResource( snd, t_sound );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < ARRAYSIZE( cl_weapon_shell_sounds ); i++ )
|
for( i = 0; ( snd = SoundList_Get( BounceWeaponShell, i )); i++ )
|
||||||
{
|
{
|
||||||
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_weapon_shell_sounds[i] );
|
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
|
||||||
|
|
||||||
if( !FS_FileExists( filepath, false ))
|
if( !FS_FileExists( filepath, false ))
|
||||||
CL_AddClientResource( cl_weapon_shell_sounds[i], t_sound );
|
CL_AddClientResource( snd, t_sound );
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i = 0; i < ARRAYSIZE( cl_explode_sounds ); i++ )
|
for( i = 0; ( snd = SoundList_Get( Explode, i )); i++ )
|
||||||
{
|
{
|
||||||
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_explode_sounds[i] );
|
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
|
||||||
|
|
||||||
if( !FS_FileExists( filepath, false ))
|
if( !FS_FileExists( filepath, false ))
|
||||||
CL_AddClientResource( cl_explode_sounds[i], t_sound );
|
CL_AddClientResource( snd, t_sound );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // ric sounds was precached by server-side
|
#if 0 // ric sounds was precached by server-side
|
||||||
for( i = 0; i < ARRAYSIZE( cl_ricochet_sounds ); i++ )
|
for( i = 0; ( snd = SoundList_Get( Ricochet, i )); i++ )
|
||||||
{
|
{
|
||||||
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_ricochet_sounds[i] );
|
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
|
||||||
|
|
||||||
if( !FS_FileExists( filepath, false ))
|
if( !FS_FileExists( filepath, false ))
|
||||||
CL_AddClientResource( cl_ricochet_sounds[i], t_sound );
|
CL_AddClientResource( snd, t_sound );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -301,7 +272,7 @@ play collide sound
|
|||||||
static void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
|
static void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
|
||||||
{
|
{
|
||||||
float fvol;
|
float fvol;
|
||||||
char soundname[32];
|
const char *soundname = NULL;
|
||||||
qboolean isshellcasing = false;
|
qboolean isshellcasing = false;
|
||||||
int zvel;
|
int zvel;
|
||||||
|
|
||||||
@@ -312,36 +283,39 @@ static void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
|
|||||||
switch( pTemp->hitSound )
|
switch( pTemp->hitSound )
|
||||||
{
|
{
|
||||||
case BOUNCE_GLASS:
|
case BOUNCE_GLASS:
|
||||||
Q_snprintf( soundname, sizeof( soundname ), "debris/glass%i.wav", COM_RandomLong( 1, 4 ));
|
soundname = SoundList_GetRandom( BounceGlass );
|
||||||
break;
|
break;
|
||||||
case BOUNCE_METAL:
|
case BOUNCE_METAL:
|
||||||
Q_snprintf( soundname, sizeof( soundname ), "debris/metal%i.wav", COM_RandomLong( 1, 6 ));
|
soundname = SoundList_GetRandom( BounceMetal );
|
||||||
break;
|
break;
|
||||||
case BOUNCE_FLESH:
|
case BOUNCE_FLESH:
|
||||||
Q_snprintf( soundname, sizeof( soundname ), "debris/flesh%i.wav", COM_RandomLong( 1, 7 ));
|
soundname = SoundList_GetRandom( BounceFlesh );
|
||||||
break;
|
break;
|
||||||
case BOUNCE_WOOD:
|
case BOUNCE_WOOD:
|
||||||
Q_snprintf( soundname, sizeof( soundname ), "debris/wood%i.wav", COM_RandomLong( 1, 4 ));
|
soundname = SoundList_GetRandom( BounceWood );
|
||||||
break;
|
break;
|
||||||
case BOUNCE_SHRAP:
|
case BOUNCE_SHRAP:
|
||||||
Q_strncpy( soundname, cl_ricochet_sounds[COM_RandomLong( 0, 4 )], sizeof( soundname ) );
|
soundname = SoundList_GetRandom( Ricochet );
|
||||||
break;
|
break;
|
||||||
case BOUNCE_SHOTSHELL:
|
case BOUNCE_SHOTSHELL:
|
||||||
Q_strncpy( soundname, cl_weapon_shell_sounds[COM_RandomLong( 0, 2 )], sizeof( soundname ) );
|
soundname = SoundList_GetRandom( BounceWeaponShell );
|
||||||
isshellcasing = true; // shell casings have different playback parameters
|
isshellcasing = true; // shell casings have different playback parameters
|
||||||
fvol = 0.5f;
|
fvol = 0.5f;
|
||||||
break;
|
break;
|
||||||
case BOUNCE_SHELL:
|
case BOUNCE_SHELL:
|
||||||
Q_strncpy( soundname, cl_player_shell_sounds[COM_RandomLong( 0, 2 )], sizeof( soundname ) );
|
soundname = SoundList_GetRandom( BouncePlayerShell );
|
||||||
isshellcasing = true; // shell casings have different playback parameters
|
isshellcasing = true; // shell casings have different playback parameters
|
||||||
break;
|
break;
|
||||||
case BOUNCE_CONCRETE:
|
case BOUNCE_CONCRETE:
|
||||||
Q_snprintf( soundname, sizeof( soundname ), "debris/concrete%i.wav", COM_RandomLong( 1, 3 ));
|
soundname = SoundList_GetRandom( BounceConcrete );
|
||||||
break;
|
break;
|
||||||
default: // null sound
|
default: // null sound
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !soundname )
|
||||||
|
return;
|
||||||
|
|
||||||
zvel = abs( pTemp->entity.baseline.origin[2] );
|
zvel = abs( pTemp->entity.baseline.origin[2] );
|
||||||
|
|
||||||
// only play one out of every n
|
// only play one out of every n
|
||||||
@@ -1491,7 +1465,7 @@ void GAME_EXPORT R_FunnelSprite( const vec3_t org, int modelIndex, int reverse )
|
|||||||
===============
|
===============
|
||||||
R_SparkEffect
|
R_SparkEffect
|
||||||
|
|
||||||
Create a streaks + richochet sprite
|
Create a streaks + ricochet sprite
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
void GAME_EXPORT R_SparkEffect( const vec3_t pos, int count, int velocityMin, int velocityMax )
|
void GAME_EXPORT R_SparkEffect( const vec3_t pos, int count, int velocityMin, int velocityMax )
|
||||||
@@ -1507,18 +1481,25 @@ R_RicochetSound
|
|||||||
Make a random ricochet sound
|
Make a random ricochet sound
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
static void R_RicochetSound_( const vec3_t pos, int sound )
|
static void R_RicochetSoundByName( const vec3_t pos, const char *name )
|
||||||
{
|
{
|
||||||
sound_t handle;
|
sound_t handle;
|
||||||
|
handle = S_RegisterSound( name );
|
||||||
handle = S_RegisterSound( cl_ricochet_sounds[sound] );
|
|
||||||
|
|
||||||
S_StartSound( pos, 0, CHAN_AUTO, handle, VOL_NORM, 1.0, 100, 0 );
|
S_StartSound( pos, 0, CHAN_AUTO, handle, VOL_NORM, 1.0, 100, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void R_RicochetSoundByIndex( const vec3_t pos, int idx )
|
||||||
|
{
|
||||||
|
const char *name = SoundList_Get( Ricochet, idx );
|
||||||
|
if( name )
|
||||||
|
R_RicochetSoundByName( pos, name );
|
||||||
|
}
|
||||||
|
|
||||||
void GAME_EXPORT R_RicochetSound( const vec3_t pos )
|
void GAME_EXPORT R_RicochetSound( const vec3_t pos )
|
||||||
{
|
{
|
||||||
R_RicochetSound_( pos, COM_RandomLong( 0, 4 ));
|
const char *name = SoundList_GetRandom( Ricochet );
|
||||||
|
if( name )
|
||||||
|
R_RicochetSoundByName( pos, name );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1665,8 +1646,12 @@ void GAME_EXPORT R_Explosion( vec3_t pos, int model, float scale, float framerat
|
|||||||
|
|
||||||
if( !FBitSet( flags, TE_EXPLFLAG_NOSOUND ))
|
if( !FBitSet( flags, TE_EXPLFLAG_NOSOUND ))
|
||||||
{
|
{
|
||||||
hSound = S_RegisterSound( cl_explode_sounds[COM_RandomLong( 0, 2 )] );
|
const char *name = SoundList_GetRandom( Explode );
|
||||||
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.3f, PITCH_NORM, 0 );
|
if( name )
|
||||||
|
{
|
||||||
|
hSound = S_RegisterSound( name );
|
||||||
|
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.3f, PITCH_NORM, 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1909,6 +1894,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
|||||||
cl_entity_t *pEnt;
|
cl_entity_t *pEnt;
|
||||||
dlight_t *dl;
|
dlight_t *dl;
|
||||||
sound_t hSound;
|
sound_t hSound;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
if( cls.legacymode )
|
if( cls.legacymode )
|
||||||
iSize = MSG_ReadByte( msg );
|
iSize = MSG_ReadByte( msg );
|
||||||
@@ -1968,8 +1954,11 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
|||||||
pos[2] = MSG_ReadCoord( &buf );
|
pos[2] = MSG_ReadCoord( &buf );
|
||||||
R_BlobExplosion( pos );
|
R_BlobExplosion( pos );
|
||||||
|
|
||||||
hSound = S_RegisterSound( cl_explode_sounds[0] );
|
if(( name = SoundList_Get( Explode, 0 )))
|
||||||
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
|
{
|
||||||
|
hSound = S_RegisterSound( name );
|
||||||
|
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TE_SMOKE:
|
case TE_SMOKE:
|
||||||
pos[0] = MSG_ReadCoord( &buf );
|
pos[0] = MSG_ReadCoord( &buf );
|
||||||
@@ -2022,8 +2011,11 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
|||||||
dl->die = cl.time + 0.5;
|
dl->die = cl.time + 0.5;
|
||||||
dl->decay = 300;
|
dl->decay = 300;
|
||||||
|
|
||||||
hSound = S_RegisterSound( cl_explode_sounds[0] );
|
if(( name = SoundList_Get( Explode, 0 )))
|
||||||
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
|
{
|
||||||
|
hSound = S_RegisterSound( name );
|
||||||
|
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TE_BSPDECAL:
|
case TE_BSPDECAL:
|
||||||
case TE_DECAL:
|
case TE_DECAL:
|
||||||
@@ -2251,8 +2243,8 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
|||||||
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
|
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
|
||||||
R_BulletImpactParticles( pos );
|
R_BulletImpactParticles( pos );
|
||||||
flags = COM_RandomLong( 0, 0x7fff );
|
flags = COM_RandomLong( 0, 0x7fff );
|
||||||
if( flags < 0x3fff )
|
if( flags < 0x3fff && ( count = SoundList_Count( Ricochet )))
|
||||||
R_RicochetSound_( pos, flags % 5 );
|
R_RicochetSoundByIndex( pos, flags % count );
|
||||||
break;
|
break;
|
||||||
case TE_SPRAY:
|
case TE_SPRAY:
|
||||||
case TE_SPRITE_SPRAY:
|
case TE_SPRITE_SPRAY:
|
||||||
|
|||||||
@@ -553,4 +553,6 @@ void V_PostRender( void )
|
|||||||
ref.dllFuncs.R_AllowFog( true );
|
ref.dllFuncs.R_AllowFog( true );
|
||||||
Platform_SetTimer( 0.0f );
|
Platform_SetTimer( 0.0f );
|
||||||
ref.dllFuncs.R_EndFrame();
|
ref.dllFuncs.R_EndFrame();
|
||||||
|
|
||||||
|
V_CheckGammaEnd();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ typedef struct
|
|||||||
byte charWidths[256]; // scaled widths
|
byte charWidths[256]; // scaled widths
|
||||||
int charHeight; // scaled height
|
int charHeight; // scaled height
|
||||||
int type; // fixed width font or variable
|
int type; // fixed width font or variable
|
||||||
int rendermode; // default rendermode
|
convar_t *rendermode; // user-defined default rendermode
|
||||||
qboolean valid; // all rectangles are valid
|
qboolean valid; // all rectangles are valid
|
||||||
} cl_font_t;
|
} cl_font_t;
|
||||||
|
|
||||||
@@ -681,12 +681,14 @@ extern convar_t cl_draw_beams;
|
|||||||
extern convar_t cl_clockreset;
|
extern convar_t cl_clockreset;
|
||||||
extern convar_t cl_fixtimerate;
|
extern convar_t cl_fixtimerate;
|
||||||
extern convar_t hud_fontscale;
|
extern convar_t hud_fontscale;
|
||||||
|
extern convar_t hud_fontrender;
|
||||||
extern convar_t hud_scale;
|
extern convar_t hud_scale;
|
||||||
extern convar_t hud_scale_minimal_width;
|
extern convar_t hud_scale_minimal_width;
|
||||||
extern convar_t r_showtextures;
|
extern convar_t r_showtextures;
|
||||||
extern convar_t cl_bmodelinterp;
|
extern convar_t cl_bmodelinterp;
|
||||||
extern convar_t cl_lw; // local weapons
|
extern convar_t cl_lw; // local weapons
|
||||||
extern convar_t cl_charset;
|
extern convar_t cl_charset;
|
||||||
|
extern convar_t cl_trace_stufftext;
|
||||||
extern convar_t cl_trace_messages;
|
extern convar_t cl_trace_messages;
|
||||||
extern convar_t cl_trace_events;
|
extern convar_t cl_trace_events;
|
||||||
extern convar_t hud_utf8;
|
extern convar_t hud_utf8;
|
||||||
@@ -798,9 +800,10 @@ void CL_FireEvents( void );
|
|||||||
// cl_font.c
|
// cl_font.c
|
||||||
//
|
//
|
||||||
qboolean CL_FixedFont( cl_font_t *font );
|
qboolean CL_FixedFont( cl_font_t *font );
|
||||||
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
|
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
|
||||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
|
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
|
||||||
void CL_FreeFont( cl_font_t *font );
|
void CL_FreeFont( cl_font_t *font );
|
||||||
|
void CL_SetFontRendermode( cl_font_t *font );
|
||||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
|
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
|
||||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
|
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
|
||||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
|
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ GNU General Public License for more details.
|
|||||||
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
|
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
|
||||||
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
|
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
|
||||||
CVAR_DEFINE_AUTO( con_fontsize, "1", FCVAR_ARCHIVE, "console font number (0, 1 or 2)" );
|
CVAR_DEFINE_AUTO( con_fontsize, "1", FCVAR_ARCHIVE, "console font number (0, 1 or 2)" );
|
||||||
|
static CVAR_DEFINE_AUTO( con_fontrender, "2", FCVAR_ARCHIVE, "console font render mode (0: additive, 1: holes, 2: trans)" );
|
||||||
static CVAR_DEFINE_AUTO( con_charset, "cp1251", FCVAR_ARCHIVE, "console font charset (only cp1251 supported now)" );
|
static CVAR_DEFINE_AUTO( con_charset, "cp1251", FCVAR_ARCHIVE, "console font charset (only cp1251 supported now)" );
|
||||||
static CVAR_DEFINE_AUTO( con_fontscale, "1.0", FCVAR_ARCHIVE, "scale font texture" );
|
static CVAR_DEFINE_AUTO( con_fontscale, "1.0", FCVAR_ARCHIVE, "scale font texture" );
|
||||||
static CVAR_DEFINE_AUTO( con_fontnum, "-1", FCVAR_ARCHIVE, "console font number (0, 1 or 2), -1 for autoselect" );
|
static CVAR_DEFINE_AUTO( con_fontnum, "-1", FCVAR_ARCHIVE, "console font number (0, 1 or 2), -1 for autoselect" );
|
||||||
@@ -547,7 +548,7 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
|
|||||||
|
|
||||||
if( con_oldfont.value )
|
if( con_oldfont.value )
|
||||||
{
|
{
|
||||||
success = Con_LoadVariableWidthFont( "gfx/conchars.fnt", font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
|
success = Con_LoadVariableWidthFont( "gfx/conchars.fnt", font, scale, &con_fontrender, TF_FONT|TF_NEAREST );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -560,14 +561,14 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
|
|||||||
if( Q_snprintf( path, sizeof( path ),
|
if( Q_snprintf( path, sizeof( path ),
|
||||||
"font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" )) > 0 )
|
"font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" )) > 0 )
|
||||||
{
|
{
|
||||||
success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
|
success = Con_LoadVariableWidthFont( path, font, scale, &con_fontrender, TF_FONT|TF_NEAREST );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !success )
|
if( !success )
|
||||||
{
|
{
|
||||||
Q_snprintf( path, sizeof( path ), "fonts/font%i", fontNumber );
|
Q_snprintf( path, sizeof( path ), "fonts/font%i", fontNumber );
|
||||||
success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
|
success = Con_LoadVariableWidthFont( path, font, scale, &con_fontrender, TF_FONT|TF_NEAREST );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,7 +576,7 @@ static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
|
|||||||
{
|
{
|
||||||
// quake fixed font as fallback
|
// quake fixed font as fallback
|
||||||
// keep source to print directly into conback image
|
// keep source to print directly into conback image
|
||||||
if( !Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST|TF_KEEP_SOURCE ))
|
if( !Con_LoadFixedWidthFont( "gfx/conchars", font, scale, &con_fontrender, TF_FONT|TF_NEAREST|TF_KEEP_SOURCE ))
|
||||||
Con_DPrintf( S_ERROR "failed to load console font\n" );
|
Con_DPrintf( S_ERROR "failed to load console font\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -840,6 +841,7 @@ void Con_Init( void )
|
|||||||
Cvar_RegisterVariable( &con_fontsize );
|
Cvar_RegisterVariable( &con_fontsize );
|
||||||
Cvar_RegisterVariable( &con_charset );
|
Cvar_RegisterVariable( &con_charset );
|
||||||
Cvar_RegisterVariable( &con_fontscale );
|
Cvar_RegisterVariable( &con_fontscale );
|
||||||
|
Cvar_RegisterVariable( &con_fontrender );
|
||||||
Cvar_RegisterVariable( &con_fontnum );
|
Cvar_RegisterVariable( &con_fontnum );
|
||||||
Cvar_RegisterVariable( &con_color );
|
Cvar_RegisterVariable( &con_color );
|
||||||
Cvar_RegisterVariable( &scr_drawversion );
|
Cvar_RegisterVariable( &scr_drawversion );
|
||||||
@@ -1123,7 +1125,7 @@ Con_ClearField
|
|||||||
*/
|
*/
|
||||||
static void Con_ClearField( field_t *edit )
|
static void Con_ClearField( field_t *edit )
|
||||||
{
|
{
|
||||||
memset( edit->buffer, 0, MAX_STRING );
|
memset( edit->buffer, 0, sizeof( edit->buffer ));
|
||||||
edit->cursor = 0;
|
edit->cursor = 0;
|
||||||
edit->scroll = 0;
|
edit->scroll = 0;
|
||||||
}
|
}
|
||||||
@@ -1442,36 +1444,49 @@ static void Con_HistoryAppend( con_history_t *self, field_t *from )
|
|||||||
|
|
||||||
static void Con_LoadHistory( con_history_t *self )
|
static void Con_LoadHistory( con_history_t *self )
|
||||||
{
|
{
|
||||||
const byte *aFile = FS_LoadFile( "console_history.txt", NULL, true );
|
|
||||||
const char *pLine, *pFile;
|
|
||||||
int i, len;
|
|
||||||
field_t *f;
|
field_t *f;
|
||||||
|
file_t *fd;
|
||||||
|
int i;
|
||||||
|
|
||||||
if( !aFile )
|
fd = FS_Open( "console_history.txt", "rb", true );
|
||||||
|
|
||||||
|
if( !fd )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for( pFile = pLine = (char *)aFile; *pFile; pFile++ )
|
while( !FS_Eof( fd ))
|
||||||
{
|
{
|
||||||
if( *pFile != '\n' )
|
f = &self->lines[self->next % CON_HISTORY];
|
||||||
|
|
||||||
|
Con_ClearField( f );
|
||||||
|
f->widthInChars = con.linewidth;
|
||||||
|
|
||||||
|
FS_Gets( fd, f->buffer, sizeof( f->buffer ));
|
||||||
|
f->cursor = Q_strlen( f->buffer );
|
||||||
|
|
||||||
|
// skip empty lines
|
||||||
|
if( f->cursor == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Con_ClearField( &self->lines[self->next] );
|
// skip repeating lines
|
||||||
|
if( self->next > 0 )
|
||||||
len = Q_min( pFile - pLine + 1, sizeof( f->buffer ));
|
{
|
||||||
f = &self->lines[self->next % CON_HISTORY];
|
field_t *prev;
|
||||||
f->widthInChars = con.linewidth;
|
prev = &self->lines[(self->next - 1) % CON_HISTORY];
|
||||||
f->cursor = len - 1;
|
if( !Q_stricmp( prev->buffer, f->buffer ))
|
||||||
Q_strncpy( f->buffer, pLine, len);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
self->next++;
|
self->next++;
|
||||||
|
|
||||||
pLine = pFile + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FS_Close( fd );
|
||||||
|
|
||||||
for( i = self->next; i < CON_HISTORY; i++ )
|
for( i = self->next; i < CON_HISTORY; i++ )
|
||||||
{
|
{
|
||||||
Con_ClearField( &self->lines[i] );
|
f = &self->lines[i];
|
||||||
self->lines[i].widthInChars = con.linewidth;
|
|
||||||
|
Con_ClearField( f );
|
||||||
|
f->widthInChars = con.linewidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->line = self->next;
|
self->line = self->next;
|
||||||
@@ -1489,7 +1504,7 @@ static void Con_SaveHistory( con_history_t *self )
|
|||||||
if( historyStart < 0 )
|
if( historyStart < 0 )
|
||||||
historyStart = 0;
|
historyStart = 0;
|
||||||
|
|
||||||
f = FS_Open( "console_history.txt", "w", true );
|
f = FS_Open( "console_history.txt", "wb", true );
|
||||||
|
|
||||||
for( i = historyStart; i < self->next; i++ )
|
for( i = historyStart; i < self->next; i++ )
|
||||||
FS_Printf( f, "%s\n", self->lines[i % CON_HISTORY].buffer );
|
FS_Printf( f, "%s\n", self->lines[i % CON_HISTORY].buffer );
|
||||||
@@ -2098,9 +2113,13 @@ void Con_RunConsole( void )
|
|||||||
// decide on the destination height of the console
|
// decide on the destination height of the console
|
||||||
if( host.allow_console && cls.key_dest == key_console )
|
if( host.allow_console && cls.key_dest == key_console )
|
||||||
{
|
{
|
||||||
|
#if XASH_MOBILE_PLATFORM
|
||||||
|
con.showlines = refState.height; // always full screen on mobile devices
|
||||||
|
#else
|
||||||
if( cls.state < ca_active || cl.first_frame )
|
if( cls.state < ca_active || cl.first_frame )
|
||||||
con.showlines = refState.height; // full screen
|
con.showlines = refState.height; // full screen
|
||||||
else con.showlines = (refState.height >> 1); // half screen
|
else con.showlines = (refState.height >> 1); // half screen
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else con.showlines = 0; // none visible
|
else con.showlines = 0; // none visible
|
||||||
|
|
||||||
@@ -2185,6 +2204,8 @@ INTERNAL RESOURCE
|
|||||||
*/
|
*/
|
||||||
void Con_VidInit( void )
|
void Con_VidInit( void )
|
||||||
{
|
{
|
||||||
|
const uint flags = TF_IMAGE|TF_ALLOW_NEAREST;
|
||||||
|
|
||||||
if( !con.historyLoaded )
|
if( !con.historyLoaded )
|
||||||
{
|
{
|
||||||
Con_LoadHistory( &con.history );
|
Con_LoadHistory( &con.history );
|
||||||
@@ -2204,28 +2225,28 @@ void Con_VidInit( void )
|
|||||||
{
|
{
|
||||||
// trying to load truecolor image first
|
// trying to load truecolor image first
|
||||||
if( FS_FileExists( "gfx/shell/conback.bmp", false ) || FS_FileExists( "gfx/shell/conback.tga", false ))
|
if( FS_FileExists( "gfx/shell/conback.bmp", false ) || FS_FileExists( "gfx/shell/conback.tga", false ))
|
||||||
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/conback", NULL, 0, TF_IMAGE );
|
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/conback", NULL, 0, flags );
|
||||||
|
|
||||||
if( !con.background )
|
if( !con.background )
|
||||||
{
|
{
|
||||||
if( FS_FileExists( "cached/conback640", false ))
|
if( FS_FileExists( "cached/conback640", false ))
|
||||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback640", NULL, 0, TF_IMAGE );
|
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback640", NULL, 0, flags );
|
||||||
else if( FS_FileExists( "cached/conback", false ))
|
else if( FS_FileExists( "cached/conback", false ))
|
||||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback", NULL, 0, TF_IMAGE );
|
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback", NULL, 0, flags );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// trying to load truecolor image first
|
// trying to load truecolor image first
|
||||||
if( FS_FileExists( "gfx/shell/loading.bmp", false ) || FS_FileExists( "gfx/shell/loading.tga", false ))
|
if( FS_FileExists( "gfx/shell/loading.bmp", false ) || FS_FileExists( "gfx/shell/loading.tga", false ))
|
||||||
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/loading", NULL, 0, TF_IMAGE );
|
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/loading", NULL, 0, flags );
|
||||||
|
|
||||||
if( !con.background )
|
if( !con.background )
|
||||||
{
|
{
|
||||||
if( FS_FileExists( "cached/loading640", false ))
|
if( FS_FileExists( "cached/loading640", false ))
|
||||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading640", NULL, 0, TF_IMAGE );
|
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading640", NULL, 0, flags );
|
||||||
else if( FS_FileExists( "cached/loading", false ))
|
else if( FS_FileExists( "cached/loading", false ))
|
||||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading", NULL, 0, TF_IMAGE );
|
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading", NULL, 0, flags );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ GNU General Public License for more details.
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Gamma conversion support
|
// Gamma conversion support
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
static qboolean gamma_rebuilt;
|
||||||
static byte texgammatable[256];
|
static byte texgammatable[256];
|
||||||
static uint lightgammatable[1024];
|
static uint lightgammatable[1024];
|
||||||
static uint lineargammatable[1024];
|
static uint lineargammatable[1024];
|
||||||
@@ -82,9 +83,6 @@ static void BuildGammaTable( const float gamma, const float brightness, const fl
|
|||||||
|
|
||||||
static void V_ValidateGammaCvars( void )
|
static void V_ValidateGammaCvars( void )
|
||||||
{
|
{
|
||||||
if( Host_IsLocalGame( ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if( v_gamma.value < 1.8f )
|
if( v_gamma.value < 1.8f )
|
||||||
Cvar_DirectSet( &v_gamma, "1.8" );
|
Cvar_DirectSet( &v_gamma, "1.8" );
|
||||||
else if( v_gamma.value > 3.0f )
|
else if( v_gamma.value > 3.0f )
|
||||||
@@ -102,14 +100,13 @@ static void V_ValidateGammaCvars( void )
|
|||||||
|
|
||||||
if( v_brightness.value < 0.0f )
|
if( v_brightness.value < 0.0f )
|
||||||
Cvar_DirectSet( &v_brightness, "0" );
|
Cvar_DirectSet( &v_brightness, "0" );
|
||||||
else if( v_brightness.value > 2.0f )
|
else if( v_brightness.value > 3.0f )
|
||||||
Cvar_DirectSet( &v_brightness, "2" );
|
Cvar_DirectSet( &v_brightness, "3" );
|
||||||
}
|
}
|
||||||
|
|
||||||
void V_CheckGamma( void )
|
void V_CheckGamma( void )
|
||||||
{
|
{
|
||||||
static qboolean dirty = false;
|
static qboolean dirty = false;
|
||||||
qboolean notify_refdll = false;
|
|
||||||
|
|
||||||
// because these cvars were defined as archive
|
// because these cvars were defined as archive
|
||||||
// but wasn't doing anything useful
|
// but wasn't doing anything useful
|
||||||
@@ -135,20 +132,33 @@ void V_CheckGamma( void )
|
|||||||
V_ValidateGammaCvars();
|
V_ValidateGammaCvars();
|
||||||
|
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
gamma_rebuilt = true;
|
||||||
|
|
||||||
BuildGammaTable( v_gamma.value, v_brightness.value, v_texgamma.value, v_lightgamma.value );
|
BuildGammaTable( v_gamma.value, v_brightness.value, v_texgamma.value, v_lightgamma.value );
|
||||||
|
|
||||||
// force refdll to recalculate lightmaps
|
// force refdll to recalculate lightmaps
|
||||||
notify_refdll = true;
|
if( ref.initialized )
|
||||||
|
ref.dllFuncs.R_GammaChanged( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// unfortunately, recalculating textures isn't possible yet
|
void V_CheckGammaEnd( void )
|
||||||
|
{
|
||||||
|
// don't reset changed flag if it was set during frame
|
||||||
|
// keep it for next frame
|
||||||
|
if( !gamma_rebuilt )
|
||||||
|
return;
|
||||||
|
|
||||||
|
gamma_rebuilt = false;
|
||||||
|
|
||||||
|
// keep the flags until the end of frame so client.dll will catch these changes
|
||||||
|
if( FBitSet( v_texgamma.flags|v_lightgamma.flags|v_brightness.flags|v_gamma.flags, FCVAR_CHANGED ))
|
||||||
|
{
|
||||||
ClearBits( v_texgamma.flags, FCVAR_CHANGED );
|
ClearBits( v_texgamma.flags, FCVAR_CHANGED );
|
||||||
ClearBits( v_lightgamma.flags, FCVAR_CHANGED );
|
ClearBits( v_lightgamma.flags, FCVAR_CHANGED );
|
||||||
ClearBits( v_brightness.flags, FCVAR_CHANGED );
|
ClearBits( v_brightness.flags, FCVAR_CHANGED );
|
||||||
ClearBits( v_gamma.flags, FCVAR_CHANGED );
|
ClearBits( v_gamma.flags, FCVAR_CHANGED );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( notify_refdll && ref.initialized )
|
|
||||||
ref.dllFuncs.R_GammaChanged( false );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void V_Init( void )
|
void V_Init( void )
|
||||||
|
|||||||
@@ -2029,10 +2029,18 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
|
|||||||
{
|
{
|
||||||
touch.move_finger = touch.resize_finger = touch.look_finger = -1;
|
touch.move_finger = touch.resize_finger = touch.look_finger = -1;
|
||||||
// Hack for keyboard, hope it help
|
// Hack for keyboard, hope it help
|
||||||
|
// a1ba: this is absolutely horrible
|
||||||
if( cls.key_dest == key_console || cls.key_dest == key_message )
|
if( cls.key_dest == key_console || cls.key_dest == key_message )
|
||||||
{
|
{
|
||||||
if ( type == event_down ) // don't pop it again on event_up
|
static float x1 = 0.0f;
|
||||||
|
x1 += dx;
|
||||||
|
|
||||||
|
if( type == event_up ) // don't show keyboard on every tap
|
||||||
|
{
|
||||||
Key_EnableTextInput( true, true );
|
Key_EnableTextInput( true, true );
|
||||||
|
x1 = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if( cls.key_dest == key_console )
|
if( cls.key_dest == key_console )
|
||||||
{
|
{
|
||||||
static float y1 = 0;
|
static float y1 = 0;
|
||||||
@@ -2054,6 +2062,13 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
|
|||||||
// exit of console area
|
// exit of console area
|
||||||
if( type == event_down && x < 0.1f && y > 0.9f )
|
if( type == event_down && x < 0.1f && y > 0.9f )
|
||||||
Cbuf_AddText( "escape\n" );
|
Cbuf_AddText( "escape\n" );
|
||||||
|
|
||||||
|
// swipe from edge to exit console/chat
|
||||||
|
if(( x > 0.8f && x1 < -0.1f ) || ( x < 0.2f && x1 > 0.1f ))
|
||||||
|
{
|
||||||
|
Cbuf_AddText( "escape\n" );
|
||||||
|
x1 = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UI_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) );
|
UI_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) );
|
||||||
//MsgDev( D_NOTE, "touch %d %d\n", TO_SCRN_X(x), TO_SCRN_Y(y) );
|
//MsgDev( D_NOTE, "touch %d %d\n", TO_SCRN_X(x), TO_SCRN_Y(y) );
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ static void R_CollectRendererNames( void )
|
|||||||
"GL4ES",
|
"GL4ES",
|
||||||
#endif
|
#endif
|
||||||
#if XASH_REF_GLES3COMPAT_ENABLED
|
#if XASH_REF_GLES3COMPAT_ENABLED
|
||||||
"GLES3 (gl2_shim)"
|
"GLES3 (gl2_shim)",
|
||||||
#endif
|
#endif
|
||||||
#if XASH_REF_SOFT_ENABLED
|
#if XASH_REF_SOFT_ENABLED
|
||||||
"Software",
|
"Software",
|
||||||
@@ -611,6 +611,7 @@ qboolean R_Init( void )
|
|||||||
|
|
||||||
// cvars that are expected to exist by client.dll
|
// cvars that are expected to exist by client.dll
|
||||||
// refdll should just get pointer to them
|
// refdll should just get pointer to them
|
||||||
|
Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "compatibility cvar, does nothing" );
|
||||||
Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
|
Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
|
||||||
Cvar_Get( "cl_himodels", "1", FCVAR_ARCHIVE, "draw high-resolution player models in multiplayer" );
|
Cvar_Get( "cl_himodels", "1", FCVAR_ARCHIVE, "draw high-resolution player models in multiplayer" );
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "apply interpo
|
|||||||
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" );
|
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" );
|
||||||
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" );
|
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" );
|
||||||
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" );
|
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" );
|
||||||
CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
|
static CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
|
||||||
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
|
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
|
||||||
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" );
|
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" );
|
||||||
CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" );
|
CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" );
|
||||||
@@ -64,6 +64,12 @@ float S_GetMasterVolume( void )
|
|||||||
{
|
{
|
||||||
float scale = 1.0f;
|
float scale = 1.0f;
|
||||||
|
|
||||||
|
if( host.status == HOST_NOFOCUS && snd_mute_losefocus.value != 0.0f )
|
||||||
|
{
|
||||||
|
// we return zero volume to keep sounds running
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
if( !s_listener.inmenu && soundfade.percent != 0 )
|
if( !s_listener.inmenu && soundfade.percent != 0 )
|
||||||
{
|
{
|
||||||
scale = bound( 0.0f, soundfade.percent / 100.0f, 1.0f );
|
scale = bound( 0.0f, soundfade.percent / 100.0f, 1.0f );
|
||||||
|
|||||||
@@ -221,7 +221,6 @@ extern convar_t s_musicvolume;
|
|||||||
extern convar_t s_lerping;
|
extern convar_t s_lerping;
|
||||||
extern convar_t s_test; // cvar to testify new effects
|
extern convar_t s_test; // cvar to testify new effects
|
||||||
extern convar_t s_samplecount;
|
extern convar_t s_samplecount;
|
||||||
extern convar_t snd_mute_losefocus;
|
|
||||||
extern convar_t s_warn_late_precache;
|
extern convar_t s_warn_late_precache;
|
||||||
|
|
||||||
void S_InitScaletable( void );
|
void S_InitScaletable( void );
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ GNU General Public License for more details.
|
|||||||
#include "vid_common.h"
|
#include "vid_common.h"
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
|
||||||
static CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
|
|
||||||
static CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
|
|
||||||
static CVAR_DEFINE_AUTO( vid_mode, "0", FCVAR_RENDERINFO, "current video mode index (used only for storage)" );
|
static CVAR_DEFINE_AUTO( vid_mode, "0", FCVAR_RENDERINFO, "current video mode index (used only for storage)" );
|
||||||
static CVAR_DEFINE_AUTO( vid_rotate, "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
|
static CVAR_DEFINE_AUTO( vid_rotate, "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
|
||||||
static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
|
static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
|
||||||
@@ -29,6 +27,8 @@ static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "p
|
|||||||
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
|
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
|
||||||
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
|
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
|
||||||
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
||||||
|
CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
|
||||||
|
CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
|
||||||
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
|
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
|
||||||
CVAR_DEFINE( window_ypos, "_window_ypos", "-1", FCVAR_RENDERINFO, "window position by vertical" );
|
CVAR_DEFINE( window_ypos, "_window_ypos", "-1", FCVAR_RENDERINFO, "window position by vertical" );
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ extern glwstate_t glw_state;
|
|||||||
extern convar_t vid_fullscreen;
|
extern convar_t vid_fullscreen;
|
||||||
extern convar_t vid_maximized;
|
extern convar_t vid_maximized;
|
||||||
extern convar_t vid_highdpi;
|
extern convar_t vid_highdpi;
|
||||||
|
extern convar_t window_width;
|
||||||
|
extern convar_t window_height;
|
||||||
extern convar_t window_xpos;
|
extern convar_t window_xpos;
|
||||||
extern convar_t window_ypos;
|
extern convar_t window_ypos;
|
||||||
extern convar_t gl_msaa_samples;
|
extern convar_t gl_msaa_samples;
|
||||||
|
|||||||
@@ -25,11 +25,12 @@ voice_state_t voice = { 0 };
|
|||||||
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
|
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
|
||||||
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
|
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
|
||||||
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
|
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
|
||||||
|
CVAR_DEFINE_AUTO( voice_transmit_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "outcoming voice volume scale" );
|
||||||
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
|
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
|
||||||
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
|
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
|
||||||
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
|
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
|
||||||
|
|
||||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
|
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============================================================================
|
===============================================================================
|
||||||
@@ -39,6 +40,25 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count );
|
|||||||
===============================================================================
|
===============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static qboolean Voice_InitCustomMode( void )
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
voice.width = sizeof( opus_int16 );
|
||||||
|
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
|
||||||
|
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
|
||||||
|
|
||||||
|
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
|
||||||
|
|
||||||
|
if( !voice.custom_mode )
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=========================
|
=========================
|
||||||
Voice_InitOpusDecoder
|
Voice_InitOpusDecoder
|
||||||
@@ -47,24 +67,17 @@ Voice_InitOpusDecoder
|
|||||||
*/
|
*/
|
||||||
static qboolean Voice_InitOpusDecoder( void )
|
static qboolean Voice_InitOpusDecoder( void )
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
|
|
||||||
voice.width = sizeof( opus_int16 );
|
for( int i = 0; i < cl.maxclients; i++ )
|
||||||
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
|
|
||||||
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
|
|
||||||
|
|
||||||
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
|
|
||||||
if( !voice.custom_mode )
|
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
|
voice.decoders[i] = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
if( !voice.decoders[i] )
|
||||||
if( !voice.decoder )
|
{
|
||||||
{
|
Con_Printf( S_ERROR "Can't create Opus decoder for %i: %s\n", i, opus_strerror( err ));
|
||||||
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -78,7 +91,7 @@ Voice_InitOpusEncoder
|
|||||||
*/
|
*/
|
||||||
static qboolean Voice_InitOpusEncoder( int quality )
|
static qboolean Voice_InitOpusEncoder( int quality )
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
|
|
||||||
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||||
if( !voice.encoder )
|
if( !voice.encoder )
|
||||||
@@ -117,10 +130,13 @@ Voice_ShutdownOpusDecoder
|
|||||||
*/
|
*/
|
||||||
static void Voice_ShutdownOpusDecoder( void )
|
static void Voice_ShutdownOpusDecoder( void )
|
||||||
{
|
{
|
||||||
if( voice.decoder )
|
for( int i = 0; i < MAX_CLIENTS; i++ )
|
||||||
{
|
{
|
||||||
opus_custom_decoder_destroy( voice.decoder );
|
if( !voice.decoders[i] )
|
||||||
voice.decoder = NULL;
|
continue;
|
||||||
|
|
||||||
|
opus_custom_decoder_destroy( voice.decoders[i] );
|
||||||
|
voice.decoders[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +153,10 @@ static void Voice_ShutdownOpusEncoder( void )
|
|||||||
opus_custom_encoder_destroy( voice.encoder );
|
opus_custom_encoder_destroy( voice.encoder );
|
||||||
voice.encoder = NULL;
|
voice.encoder = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Voice_ShutdownCustomMode( void )
|
||||||
|
{
|
||||||
if( voice.custom_mode )
|
if( voice.custom_mode )
|
||||||
{
|
{
|
||||||
opus_custom_mode_destroy( voice.custom_mode );
|
opus_custom_mode_destroy( voice.custom_mode );
|
||||||
@@ -184,7 +203,7 @@ static uint Voice_GetOpusCompressedData( byte *out, uint maxsize, uint *frames )
|
|||||||
if( !voice.input_file )
|
if( !voice.input_file )
|
||||||
{
|
{
|
||||||
// adjust gain before encoding, but only for input from voice
|
// adjust gain before encoding, but only for input from voice
|
||||||
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size);
|
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size, voice_transmit_scale.value);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -238,10 +257,10 @@ Voice_ApplyGainAdjust
|
|||||||
|
|
||||||
=========================
|
=========================
|
||||||
*/
|
*/
|
||||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale )
|
||||||
{
|
{
|
||||||
float gain, modifiedMax;
|
float gain, modifiedMax;
|
||||||
int average, adjustedSample, blockOffset = 0;
|
int average, blockOffset = 0;
|
||||||
|
|
||||||
for( ;; )
|
for( ;; )
|
||||||
{
|
{
|
||||||
@@ -260,10 +279,8 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
|||||||
localMax = absSample;
|
localMax = absSample;
|
||||||
|
|
||||||
localSum += absSample;
|
localSum += absSample;
|
||||||
|
|
||||||
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
|
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
|
||||||
adjustedSample = Q_min( SHRT_MAX, Q_max(( int )( sample * gain ), SHRT_MIN ));
|
samples[blockOffset + i] = bound( SHRT_MIN, (int)( sample * gain ), SHRT_MAX );
|
||||||
samples[blockOffset + i] = adjustedSample;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( blockOffset % voice.autogain.block_size == 0 )
|
if( blockOffset % voice.autogain.block_size == 0 )
|
||||||
@@ -271,9 +288,9 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
|||||||
average = localSum / blockSize;
|
average = localSum / blockSize;
|
||||||
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
|
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
|
||||||
|
|
||||||
voice.autogain.current_gain = voice.autogain.next_gain * voice_scale.value;
|
voice.autogain.current_gain = voice.autogain.next_gain * scale;
|
||||||
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * voice_scale.value;
|
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * scale;
|
||||||
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( voice.autogain.block_size - 1 );
|
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( blockSize - 1 );
|
||||||
}
|
}
|
||||||
blockOffset += blockSize;
|
blockOffset += blockSize;
|
||||||
}
|
}
|
||||||
@@ -443,7 +460,7 @@ Feed the decoded data to engine sound subsystem
|
|||||||
static void Voice_StartChannel( uint samples, byte *data, int entnum )
|
static void Voice_StartChannel( uint samples, byte *data, int entnum )
|
||||||
{
|
{
|
||||||
SND_ForceInitMouth( entnum );
|
SND_ForceInitMouth( entnum );
|
||||||
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, 255 );
|
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, bound( 0, 255 * voice_scale.value, 255 ));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -455,10 +472,11 @@ Received encoded voice data, decode it
|
|||||||
*/
|
*/
|
||||||
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
|
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
|
||||||
{
|
{
|
||||||
|
const int playernum = ent - 1;
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
int ofs = 0;
|
int ofs = 0;
|
||||||
|
|
||||||
if( !voice.decoder )
|
if( playernum < 0 || playernum >= cl.maxclients || !voice.decoders[playernum] )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// decode frame by frame
|
// decode frame by frame
|
||||||
@@ -478,7 +496,7 @@ void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
|
|||||||
if( ofs + compressed_size > size )
|
if( ofs + compressed_size > size )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size,
|
frame_samples = opus_custom_decode( voice.decoders[playernum], data + ofs, compressed_size,
|
||||||
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
|
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
|
||||||
|
|
||||||
ofs += compressed_size;
|
ofs += compressed_size;
|
||||||
@@ -502,8 +520,8 @@ void CL_AddVoiceToDatagram( void )
|
|||||||
|
|
||||||
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
|
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size = Voice_GetOpusCompressedData( voice.output_buffer, sizeof( voice.output_buffer ), &frames );
|
size = Voice_GetOpusCompressedData( voice.compress_buffer, sizeof( voice.compress_buffer ), &frames );
|
||||||
|
|
||||||
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
|
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
|
||||||
{
|
{
|
||||||
@@ -511,7 +529,7 @@ void CL_AddVoiceToDatagram( void )
|
|||||||
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
|
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
|
||||||
MSG_WriteByte( &cls.datagram, frames );
|
MSG_WriteByte( &cls.datagram, frames );
|
||||||
MSG_WriteShort( &cls.datagram, size );
|
MSG_WriteShort( &cls.datagram, size );
|
||||||
MSG_WriteBytes( &cls.datagram, voice.output_buffer, size );
|
MSG_WriteBytes( &cls.datagram, voice.compress_buffer, size );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +545,7 @@ void Voice_RegisterCvars( void )
|
|||||||
Cvar_RegisterVariable( &voice_enable );
|
Cvar_RegisterVariable( &voice_enable );
|
||||||
Cvar_RegisterVariable( &voice_loopback );
|
Cvar_RegisterVariable( &voice_loopback );
|
||||||
Cvar_RegisterVariable( &voice_scale );
|
Cvar_RegisterVariable( &voice_scale );
|
||||||
|
Cvar_RegisterVariable( &voice_transmit_scale );
|
||||||
Cvar_RegisterVariable( &voice_avggain );
|
Cvar_RegisterVariable( &voice_avggain );
|
||||||
Cvar_RegisterVariable( &voice_maxgain );
|
Cvar_RegisterVariable( &voice_maxgain );
|
||||||
Cvar_RegisterVariable( &voice_inputfromfile );
|
Cvar_RegisterVariable( &voice_inputfromfile );
|
||||||
@@ -544,8 +563,9 @@ static void Voice_Shutdown( void )
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
Voice_RecordStop();
|
Voice_RecordStop();
|
||||||
Voice_ShutdownOpusEncoder();
|
|
||||||
Voice_ShutdownOpusDecoder();
|
Voice_ShutdownOpusDecoder();
|
||||||
|
Voice_ShutdownOpusEncoder();
|
||||||
|
Voice_ShutdownCustomMode();
|
||||||
VoiceCapture_Shutdown();
|
VoiceCapture_Shutdown();
|
||||||
|
|
||||||
if( voice.local.talking_ack )
|
if( voice.local.talking_ack )
|
||||||
@@ -609,11 +629,10 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
|||||||
|
|
||||||
voice.autogain.block_size = 128;
|
voice.autogain.block_size = 128;
|
||||||
|
|
||||||
if( !Voice_InitOpusDecoder( ))
|
if( !Voice_InitCustomMode( ))
|
||||||
{
|
{
|
||||||
// no reason to init encoder and open audio device
|
// no reason to init encoder and open audio device
|
||||||
// if we can't hear other players
|
// if we can't hear other players
|
||||||
Con_Printf( S_ERROR "Voice chat disabled.\n" );
|
|
||||||
Voice_Shutdown();
|
Voice_Shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -633,6 +652,16 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
|||||||
|
|
||||||
if( !preinit )
|
if( !preinit )
|
||||||
{
|
{
|
||||||
|
Voice_ShutdownOpusDecoder();
|
||||||
|
if( !Voice_InitOpusDecoder())
|
||||||
|
{
|
||||||
|
// no reason to init encoder and open audio device
|
||||||
|
// if we can't hear other players
|
||||||
|
Con_Printf( S_ERROR "Can't create decoders, voice chat is disabled.\n" );
|
||||||
|
Voice_Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
voice.device_opened = VoiceCapture_Init();
|
voice.device_opened = VoiceCapture_Init();
|
||||||
|
|
||||||
if( !voice.device_opened )
|
if( !voice.device_opened )
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ typedef struct voice_state_s
|
|||||||
// opus stuff
|
// opus stuff
|
||||||
OpusCustomMode *custom_mode;
|
OpusCustomMode *custom_mode;
|
||||||
OpusCustomEncoder *encoder;
|
OpusCustomEncoder *encoder;
|
||||||
OpusCustomDecoder *decoder;
|
OpusCustomDecoder *decoders[MAX_CLIENTS];
|
||||||
|
|
||||||
// audio info
|
// audio info
|
||||||
uint width;
|
uint width;
|
||||||
@@ -71,7 +71,7 @@ typedef struct voice_state_s
|
|||||||
|
|
||||||
// buffers
|
// buffers
|
||||||
byte input_buffer[MAX_RAW_SAMPLES];
|
byte input_buffer[MAX_RAW_SAMPLES];
|
||||||
byte output_buffer[MAX_RAW_SAMPLES];
|
byte compress_buffer[MAX_RAW_SAMPLES];
|
||||||
byte decompress_buffer[MAX_RAW_SAMPLES];
|
byte decompress_buffer[MAX_RAW_SAMPLES];
|
||||||
fs_offset_t input_buffer_pos; // in bytes
|
fs_offset_t input_buffer_pos; // in bytes
|
||||||
|
|
||||||
|
|||||||
@@ -529,7 +529,6 @@ typedef struct cmd_s
|
|||||||
static int cmd_argc;
|
static int cmd_argc;
|
||||||
static const char *cmd_args = NULL;
|
static const char *cmd_args = NULL;
|
||||||
static char *cmd_argv[MAX_CMD_TOKENS];
|
static char *cmd_argv[MAX_CMD_TOKENS];
|
||||||
static char cmd_tokenized[MAX_CMD_BUFFER]; // will have 0 bytes inserted
|
|
||||||
static cmd_t *cmd_functions; // possible commands to execute
|
static cmd_t *cmd_functions; // possible commands to execute
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -950,7 +949,7 @@ static void Cmd_Else_f( void )
|
|||||||
|
|
||||||
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
|
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
|
||||||
{
|
{
|
||||||
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_" };
|
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_" };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// always allow local commands
|
// always allow local commands
|
||||||
|
|||||||
@@ -17,15 +17,24 @@ GNU General Public License for more details.
|
|||||||
#define COM_STRINGS_H
|
#define COM_STRINGS_H
|
||||||
|
|
||||||
// default colored message headers
|
// default colored message headers
|
||||||
#define S_NOTE "^2Note:^7 "
|
#define S_BLACK "^0"
|
||||||
#define S_WARN "^3Warning:^7 "
|
#define S_RED "^1"
|
||||||
#define S_ERROR "^1Error:^7 "
|
#define S_GREEN "^2"
|
||||||
#define S_USAGE "Usage: "
|
#define S_YELLOW "^3"
|
||||||
#define S_USAGE_INDENT " "
|
#define S_BLUE "^4"
|
||||||
|
#define S_CYAN "^5"
|
||||||
|
#define S_MAGENTA "^6"
|
||||||
|
#define S_DEFAULT "^7"
|
||||||
|
|
||||||
#define S_OPENGL_NOTE "^2OpenGL Note:^7 "
|
#define S_NOTE S_GREEN "Note: " S_DEFAULT
|
||||||
#define S_OPENGL_WARN "^3OpenGL Warning:^7 "
|
#define S_WARN S_YELLOW "Warning: " S_DEFAULT
|
||||||
#define S_OPENGL_ERROR "^3OpenGL Error:^7 "
|
#define S_ERROR S_RED "Error: " S_DEFAULT
|
||||||
|
#define S_USAGE "Usage: "
|
||||||
|
#define S_USAGE_INDENT "\t"
|
||||||
|
|
||||||
|
#define S_OPENGL_NOTE S_GREEN "OpenGL Note: " S_DEFAULT
|
||||||
|
#define S_OPENGL_WARN S_YELLOW "OpenGL Warning: " S_DEFAULT
|
||||||
|
#define S_OPENGL_ERROR S_RED "OpenGL Error: " S_DEFAULT
|
||||||
|
|
||||||
// end game final default message
|
// end game final default message
|
||||||
#define DEFAULT_ENDGAME_MESSAGE "The End"
|
#define DEFAULT_ENDGAME_MESSAGE "The End"
|
||||||
@@ -65,6 +74,7 @@ GNU General Public License for more details.
|
|||||||
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
|
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
|
||||||
|
|
||||||
#define XASH_ENGINE_NAME "Xash3D FWGS"
|
#define XASH_ENGINE_NAME "Xash3D FWGS"
|
||||||
|
#define XASH_DEDICATED_SERVER_NAME "XashDS"
|
||||||
#define XASH_VERSION "0.20" // engine current version
|
#define XASH_VERSION "0.20" // engine current version
|
||||||
#define XASH_COMPAT_VERSION "0.99" // version we are based on
|
#define XASH_COMPAT_VERSION "0.99" // version we are based on
|
||||||
|
|
||||||
|
|||||||
@@ -390,6 +390,9 @@ byte *LZSS_Compress( byte *pInput, int inputLength, uint *pOutputSize )
|
|||||||
byte *pFinal = NULL;
|
byte *pFinal = NULL;
|
||||||
lzss_state_t state;
|
lzss_state_t state;
|
||||||
|
|
||||||
|
if( !pStart )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
memset( &state, 0, sizeof( state ));
|
memset( &state, 0, sizeof( state ));
|
||||||
state.window_size = LZSS_WINDOW_SIZE;
|
state.window_size = LZSS_WINDOW_SIZE;
|
||||||
|
|
||||||
@@ -693,7 +696,7 @@ COM_LoadFileForMe
|
|||||||
byte *GAME_EXPORT COM_LoadFileForMe( const char *filename, int *pLength )
|
byte *GAME_EXPORT COM_LoadFileForMe( const char *filename, int *pLength )
|
||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
byte *file, *pfile;
|
byte *pfile;
|
||||||
fs_offset_t iLength;
|
fs_offset_t iLength;
|
||||||
|
|
||||||
if( !COM_CheckString( filename ))
|
if( !COM_CheckString( filename ))
|
||||||
@@ -706,21 +709,9 @@ byte *GAME_EXPORT COM_LoadFileForMe( const char *filename, int *pLength )
|
|||||||
Q_strncpy( name, filename, sizeof( name ));
|
Q_strncpy( name, filename, sizeof( name ));
|
||||||
COM_FixSlashes( name );
|
COM_FixSlashes( name );
|
||||||
|
|
||||||
pfile = FS_LoadFile( name, &iLength, false );
|
pfile = g_fsapi.LoadFileMalloc( name, &iLength, false );
|
||||||
if( pLength ) *pLength = (int)iLength;
|
if( pLength ) *pLength = (int)iLength;
|
||||||
|
|
||||||
if( pfile )
|
|
||||||
{
|
|
||||||
file = malloc( iLength + 1 );
|
|
||||||
if( file != NULL )
|
|
||||||
{
|
|
||||||
memcpy( file, pfile, iLength );
|
|
||||||
file[iLength] = '\0';
|
|
||||||
}
|
|
||||||
Mem_Free( pfile );
|
|
||||||
pfile = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pfile;
|
return pfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -795,6 +795,7 @@ uint ScreenGammaTable( uint );
|
|||||||
uint LinearGammaTable( uint );
|
uint LinearGammaTable( uint );
|
||||||
void V_Init( void );
|
void V_Init( void );
|
||||||
void V_CheckGamma( void );
|
void V_CheckGamma( void );
|
||||||
|
void V_CheckGammaEnd( void );
|
||||||
|
|
||||||
//
|
//
|
||||||
// identification.c
|
// identification.c
|
||||||
@@ -815,6 +816,34 @@ void NET_MasterClear( void );
|
|||||||
void NET_MasterShutdown( void );
|
void NET_MasterShutdown( void );
|
||||||
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat );
|
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat );
|
||||||
|
|
||||||
|
//
|
||||||
|
// sounds.c
|
||||||
|
//
|
||||||
|
typedef enum soundlst_group_e
|
||||||
|
{
|
||||||
|
BouncePlayerShell = 0,
|
||||||
|
BounceWeaponShell,
|
||||||
|
BounceConcrete,
|
||||||
|
BounceGlass,
|
||||||
|
BounceMetal,
|
||||||
|
BounceFlesh,
|
||||||
|
BounceWood,
|
||||||
|
Ricochet,
|
||||||
|
Explode,
|
||||||
|
PlayerWaterEnter,
|
||||||
|
PlayerWaterExit,
|
||||||
|
EntityWaterEnter,
|
||||||
|
EntityWaterExit,
|
||||||
|
|
||||||
|
SoundList_Groups // must be last
|
||||||
|
} soundlst_group_t;
|
||||||
|
|
||||||
|
int SoundList_Count( soundlst_group_t group );
|
||||||
|
const char *SoundList_GetRandom( soundlst_group_t group );
|
||||||
|
const char *SoundList_Get( soundlst_group_t group, int idx );
|
||||||
|
void SoundList_Init( void );
|
||||||
|
void SoundList_Shutdown( void );
|
||||||
|
|
||||||
#ifdef REF_DLL
|
#ifdef REF_DLL
|
||||||
#error "common.h in ref_dll"
|
#error "common.h in ref_dll"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -866,7 +866,7 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
|||||||
return true; // exist
|
return true; // exist
|
||||||
|
|
||||||
// setup mpfilter
|
// setup mpfilter
|
||||||
size = Q_snprintf( mpfilter, sizeof( mpfilter ), "maps/%s", GI->mp_filter );
|
Q_snprintf( mpfilter, sizeof( mpfilter ), "maps/%s", GI->mp_filter );
|
||||||
t = FS_Search( "maps/*.bsp", false, onlyingamedir );
|
t = FS_Search( "maps/*.bsp", false, onlyingamedir );
|
||||||
|
|
||||||
if( !t )
|
if( !t )
|
||||||
@@ -900,9 +900,9 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
|||||||
|
|
||||||
if( f )
|
if( f )
|
||||||
{
|
{
|
||||||
int num_spawnpoints = 0;
|
qboolean have_spawnpoints = false;
|
||||||
dheader_t *header;
|
dheader_t *header;
|
||||||
dlump_t entities;
|
dlump_t entities;
|
||||||
|
|
||||||
memset( buf, 0, MAX_SYSPATH );
|
memset( buf, 0, MAX_SYSPATH );
|
||||||
FS_Read( f, buf, MAX_SYSPATH );
|
FS_Read( f, buf, MAX_SYSPATH );
|
||||||
@@ -943,7 +943,18 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
|||||||
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
||||||
{
|
{
|
||||||
if( token[0] == '}' && worldspawn )
|
if( token[0] == '}' && worldspawn )
|
||||||
|
{
|
||||||
worldspawn = false;
|
worldspawn = false;
|
||||||
|
|
||||||
|
// if mod has mp_filter set up, then it's a mod that
|
||||||
|
// might not have valid mp_entity set in GI
|
||||||
|
// if mod is multiplayer only, assume all maps are valid
|
||||||
|
if( use_filter || GI->gamemode == GAME_MULTIPLAYER_ONLY )
|
||||||
|
{
|
||||||
|
have_spawnpoints = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if( !Q_strcmp( token, "message" ) && worldspawn )
|
else if( !Q_strcmp( token, "message" ) && worldspawn )
|
||||||
{
|
{
|
||||||
// get the message contents
|
// get the message contents
|
||||||
@@ -952,17 +963,23 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
|||||||
else if( !Q_strcmp( token, "classname" ))
|
else if( !Q_strcmp( token, "classname" ))
|
||||||
{
|
{
|
||||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||||
if( !Q_strcmp( token, GI->mp_entity ) || use_filter )
|
|
||||||
num_spawnpoints++;
|
if( !Q_strcmp( token, GI->mp_entity ))
|
||||||
|
{
|
||||||
|
have_spawnpoints = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( num_spawnpoints ) break; // valid map
|
|
||||||
|
if( have_spawnpoints )
|
||||||
|
break; // valid map
|
||||||
}
|
}
|
||||||
Mem_Free( ents );
|
Mem_Free( ents );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( f ) FS_Close( f );
|
if( f ) FS_Close( f );
|
||||||
|
|
||||||
if( num_spawnpoints )
|
if( have_spawnpoints )
|
||||||
{
|
{
|
||||||
// format: mapname "maptitle"\n
|
// format: mapname "maptitle"\n
|
||||||
Q_snprintf( result, sizeof( result ), "%s \"%s\"\n", mapname, message );
|
Q_snprintf( result, sizeof( result ), "%s \"%s\"\n", mapname, message );
|
||||||
|
|||||||
@@ -490,13 +490,14 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
|||||||
#ifdef XASH_SDL
|
#ifdef XASH_SDL
|
||||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||||
#endif
|
#endif
|
||||||
|
host.crashed = true;
|
||||||
Platform_MessageBox( "Xash Error", message, false );
|
Platform_MessageBox( "Xash Error", message, false );
|
||||||
|
|
||||||
// log saved, now we can try to save configs and close log correctly, it may crash
|
// log saved, now we can try to save configs and close log correctly, it may crash
|
||||||
if( host.type == HOST_NORMAL )
|
if( host.type == HOST_NORMAL )
|
||||||
CL_Crashed();
|
CL_Crashed();
|
||||||
host.status = HOST_CRASHED;
|
host.status = HOST_CRASHED;
|
||||||
host.crashed = true;
|
|
||||||
|
|
||||||
Sys_Quit();
|
Sys_Quit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,8 +152,10 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
|||||||
if ( Host_IsDedicated() )
|
if ( Host_IsDedicated() )
|
||||||
{
|
{
|
||||||
// g-cont. this is a very strange behavior...
|
// g-cont. this is a very strange behavior...
|
||||||
Info_SetValueForKey( SV_Serverinfo(), var->name, value, MAX_SERVERINFO_STRING ),
|
char *info = SV_Serverinfo();
|
||||||
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", SV_Serverinfo( ));
|
|
||||||
|
Info_SetValueForKey( info, var->name, value, MAX_SERVERINFO_STRING ),
|
||||||
|
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", info );
|
||||||
}
|
}
|
||||||
#if !XASH_DEDICATED
|
#if !XASH_DEDICATED
|
||||||
else
|
else
|
||||||
@@ -953,7 +955,7 @@ static void Cvar_SetGL( const char *name, const char *value )
|
|||||||
|
|
||||||
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
|
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
|
||||||
{
|
{
|
||||||
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_" };
|
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_" };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if( isPrivileged )
|
if( isPrivileged )
|
||||||
|
|||||||
@@ -92,8 +92,9 @@ static void Sys_PrintUsage( void )
|
|||||||
O("-minidumps ", "enable writing minidumps when game is crashed")
|
O("-minidumps ", "enable writing minidumps when game is crashed")
|
||||||
#endif
|
#endif
|
||||||
O("-rodir <path> ", "set read-only base directory")
|
O("-rodir <path> ", "set read-only base directory")
|
||||||
O("-bugcomp ", "enable precise bug compatibility. Will break games that don't require it")
|
O("-bugcomp ", "enable precise bug compatibility")
|
||||||
O(" ", "Refer to engine documentation for more info")
|
O(" ", "will break games that don't require it")
|
||||||
|
O(" ", "refer to engine documentation for more info")
|
||||||
O("-disablehelp ", "disable this message")
|
O("-disablehelp ", "disable this message")
|
||||||
#if !XASH_DEDICATED
|
#if !XASH_DEDICATED
|
||||||
O("-dedicated ", "run engine in dedicated mode")
|
O("-dedicated ", "run engine in dedicated mode")
|
||||||
@@ -106,9 +107,11 @@ static void Sys_PrintUsage( void )
|
|||||||
O("-noip6 ", "disable IPv6")
|
O("-noip6 ", "disable IPv6")
|
||||||
O("-ip6 <ip> ", "set IPv6 address")
|
O("-ip6 <ip> ", "set IPv6 address")
|
||||||
O("-port6 <port> ", "set IPv6 port")
|
O("-port6 <port> ", "set IPv6 port")
|
||||||
O("-clockwindow <cw>", "adjust clockwindow used to ignore client commands to prevent speed hacks")
|
O("-clockwindow <cw>", "adjust clockwindow used to ignore client commands")
|
||||||
|
O(" ", "to prevent speed hacks")
|
||||||
|
|
||||||
"\nGame options:\n"
|
"\nGame options:\n"
|
||||||
|
O("-game <directory>", "set game directory to start engine with")
|
||||||
O("-dll <path> ", "override server DLL path")
|
O("-dll <path> ", "override server DLL path")
|
||||||
#if !XASH_DEDICATED
|
#if !XASH_DEDICATED
|
||||||
O("-clientlib <path>", "override client DLL path")
|
O("-clientlib <path>", "override client DLL path")
|
||||||
@@ -938,6 +941,7 @@ static void Host_RunTests( int stage )
|
|||||||
TEST_LIST_1_CLIENT;
|
TEST_LIST_1_CLIENT;
|
||||||
#endif
|
#endif
|
||||||
Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed );
|
Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed );
|
||||||
|
error_on_exit = tests_stats.failed > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
Sys_Quit();
|
Sys_Quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1186,6 +1190,11 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
|||||||
Con_Printf( "^3BUGCOMP^7: GoldSrc bug-compatibility enabled\n" );
|
Con_Printf( "^3BUGCOMP^7: GoldSrc bug-compatibility enabled\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// print current developer level to simplify processing users feedback
|
||||||
|
if( developer > 0 ) {
|
||||||
|
Con_Printf( "Developer level: ^3%i\n", developer );
|
||||||
|
}
|
||||||
|
|
||||||
Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
|
Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
|
||||||
Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );
|
Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );
|
||||||
Cmd_AddRestrictedCommand( "userconfigd", Host_Userconfigd_f, "execute all scripts from userconfig.d" );
|
Cmd_AddRestrictedCommand( "userconfigd", Host_Userconfigd_f, "execute all scripts from userconfig.d" );
|
||||||
@@ -1310,6 +1319,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
|||||||
|
|
||||||
HTTP_Init();
|
HTTP_Init();
|
||||||
ID_Init();
|
ID_Init();
|
||||||
|
SoundList_Init();
|
||||||
|
|
||||||
if( Host_IsDedicated() )
|
if( Host_IsDedicated() )
|
||||||
{
|
{
|
||||||
@@ -1367,7 +1377,11 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
|||||||
host.status = HOST_FRAME;
|
host.status = HOST_FRAME;
|
||||||
|
|
||||||
if( GameState->nextstate == STATE_RUNFRAME )
|
if( GameState->nextstate == STATE_RUNFRAME )
|
||||||
|
#if XASH_WIN32 // FIXME: implement autocomplete on *nix
|
||||||
Con_Printf( "Type 'map <mapname>' to start game... (TAB-autocomplete is working too)\n" );
|
Con_Printf( "Type 'map <mapname>' to start game... (TAB-autocomplete is working too)\n" );
|
||||||
|
#else // !XASH_WIN32
|
||||||
|
Con_Printf( "Type 'map <mapname>' to start game...\n" );
|
||||||
|
#endif // !XASH_WIN32
|
||||||
|
|
||||||
// execute server.cfg after commandline
|
// execute server.cfg after commandline
|
||||||
// so we have a chance to set servercfgfile
|
// so we have a chance to set servercfgfile
|
||||||
@@ -1412,6 +1426,7 @@ void EXPORT Host_Shutdown( void )
|
|||||||
SV_ShutdownFilter();
|
SV_ShutdownFilter();
|
||||||
CL_Shutdown();
|
CL_Shutdown();
|
||||||
|
|
||||||
|
SoundList_Shutdown();
|
||||||
Mod_Shutdown();
|
Mod_Shutdown();
|
||||||
NET_Shutdown();
|
NET_Shutdown();
|
||||||
HTTP_Shutdown();
|
HTTP_Shutdown();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
rgba_t palette[256] = { 0 };
|
rgba_t palette[256] = { 0 };
|
||||||
int i, columns, column, rows, row, bpp = 1;
|
int i, columns, column, rows, row, bpp = 1;
|
||||||
int cbPalBytes = 0, padSize = 0, bps = 0;
|
int cbPalBytes = 0, padSize = 0, bps = 0;
|
||||||
int reflectivity[3] = { 0, 0, 0 };
|
uint reflectivity[3] = { 0, 0, 0 };
|
||||||
qboolean load_qfont = false;
|
qboolean load_qfont = false;
|
||||||
bmp_t bhdr;
|
bmp_t bhdr;
|
||||||
fs_offset_t estimatedSize;
|
fs_offset_t estimatedSize;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
|
|||||||
ktx2_index_t index;
|
ktx2_index_t index;
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
size_t max_offset = 0;
|
size_t max_offset = 0;
|
||||||
|
int mip, cursor;
|
||||||
const byte *const levels_begin = buffer + KTX2_LEVELS_OFFSET;
|
const byte *const levels_begin = buffer + KTX2_LEVELS_OFFSET;
|
||||||
|
|
||||||
// Sets image.type and image.flags
|
// Sets image.type and image.flags
|
||||||
@@ -125,7 +126,7 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
|
|||||||
|
|
||||||
memcpy( &index, buffer + KTX2_IDENTIFIER_SIZE + sizeof( ktx2_header_t ), sizeof( index ));
|
memcpy( &index, buffer + KTX2_IDENTIFIER_SIZE + sizeof( ktx2_header_t ), sizeof( index ));
|
||||||
|
|
||||||
for( int mip = 0; mip < header->levelCount; ++mip )
|
for( mip = 0; mip < header->levelCount; ++mip )
|
||||||
{
|
{
|
||||||
const uint32_t width = Q_max( 1, ( header->pixelWidth >> mip ));
|
const uint32_t width = Q_max( 1, ( header->pixelWidth >> mip ));
|
||||||
const uint32_t height = Q_max( 1, ( header->pixelHeight >> mip ));
|
const uint32_t height = Q_max( 1, ( header->pixelHeight >> mip ));
|
||||||
@@ -154,7 +155,7 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
|
|||||||
image.rgba = Mem_Malloc( host.imagepool, image.size );
|
image.rgba = Mem_Malloc( host.imagepool, image.size );
|
||||||
memcpy( image.rgba, buffer, image.size );
|
memcpy( image.rgba, buffer, image.size );
|
||||||
|
|
||||||
for( int mip = 0, cursor = 0; mip < header->levelCount; ++mip )
|
for( mip = 0, cursor = 0; mip < header->levelCount; ++mip )
|
||||||
{
|
{
|
||||||
ktx2_level_t level;
|
ktx2_level_t level;
|
||||||
memcpy( &level, levels_begin + mip * sizeof( level ), sizeof( level ));
|
memcpy( &level, levels_begin + mip * sizeof( level ), sizeof( level ));
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
rgba_t palette[256];
|
rgba_t palette[256];
|
||||||
byte red = 0, green = 0, blue = 0, alpha = 0;
|
byte red = 0, green = 0, blue = 0, alpha = 0;
|
||||||
int readpixelcount, pixelcount;
|
int readpixelcount, pixelcount;
|
||||||
int reflectivity[3] = { 0, 0, 0 };
|
uint reflectivity[3] = { 0, 0, 0 };
|
||||||
qboolean compressed;
|
qboolean compressed;
|
||||||
tga_t targa_header;
|
tga_t targa_header;
|
||||||
|
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
byte *fin, *pal;
|
byte *fin, *pal;
|
||||||
int ofs[4], rendermode;
|
int ofs[4], rendermode;
|
||||||
int i, pixels, numcolors;
|
int i, pixels, numcolors;
|
||||||
int reflectivity[3] = { 0, 0, 0 };
|
uint reflectivity[3] = { 0, 0, 0 };
|
||||||
|
|
||||||
if( filesize < sizeof( mip ))
|
if( filesize < sizeof( mip ))
|
||||||
return false;
|
return false;
|
||||||
@@ -390,7 +390,7 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
if( Q_strrchr( name, '{' ))
|
if( Q_strrchr( name, '{' ))
|
||||||
{
|
{
|
||||||
// NOTE: decals with 'blue base' can be interpret as colored decals
|
// NOTE: decals with 'blue base' can be interpret as colored decals
|
||||||
if( !Image_CheckFlag( IL_LOAD_DECAL ) || ( pal[765] == 0 && pal[766] == 0 && pal[767] == 255 ))
|
if( !Image_CheckFlag( IL_LOAD_DECAL ) || ( pal && pal[765] == 0 && pal[766] == 0 && pal[767] == 255 ))
|
||||||
{
|
{
|
||||||
SetBits( image.flags, IMAGE_ONEBIT_ALPHA );
|
SetBits( image.flags, IMAGE_ONEBIT_ALPHA );
|
||||||
rendermode = LUMP_MASKED;
|
rendermode = LUMP_MASKED;
|
||||||
@@ -488,37 +488,40 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for half-life water texture
|
// check for half-life water texture
|
||||||
if( hl_texture && ( mip.name[0] == '!' || !Q_strnicmp( mip.name, "water", 5 )))
|
if( pal != NULL )
|
||||||
{
|
{
|
||||||
// grab the fog color
|
if( hl_texture && ( mip.name[0] == '!' || !Q_strnicmp( mip.name, "water", 5 )))
|
||||||
image.fogParams[0] = pal[3*3+0];
|
|
||||||
image.fogParams[1] = pal[3*3+1];
|
|
||||||
image.fogParams[2] = pal[3*3+2];
|
|
||||||
|
|
||||||
// grab the fog density
|
|
||||||
image.fogParams[3] = pal[4*3+0];
|
|
||||||
}
|
|
||||||
else if( hl_texture && ( rendermode == LUMP_GRADIENT ))
|
|
||||||
{
|
|
||||||
// grab the decal color
|
|
||||||
image.fogParams[0] = pal[255*3+0];
|
|
||||||
image.fogParams[1] = pal[255*3+1];
|
|
||||||
image.fogParams[2] = pal[255*3+2];
|
|
||||||
|
|
||||||
// calc the decal reflectivity
|
|
||||||
image.fogParams[3] = VectorAvg( image.fogParams );
|
|
||||||
}
|
|
||||||
else if( pal != NULL )
|
|
||||||
{
|
|
||||||
// calc texture reflectivity
|
|
||||||
for( i = 0; i < 256; i++ )
|
|
||||||
{
|
{
|
||||||
reflectivity[0] += pal[i*3+0];
|
// grab the fog color
|
||||||
reflectivity[1] += pal[i*3+1];
|
image.fogParams[0] = pal[3*3+0];
|
||||||
reflectivity[2] += pal[i*3+2];
|
image.fogParams[1] = pal[3*3+1];
|
||||||
}
|
image.fogParams[2] = pal[3*3+2];
|
||||||
|
|
||||||
VectorDivide( reflectivity, 256, image.fogParams );
|
// grab the fog density
|
||||||
|
image.fogParams[3] = pal[4*3+0];
|
||||||
|
}
|
||||||
|
else if( hl_texture && ( rendermode == LUMP_GRADIENT ))
|
||||||
|
{
|
||||||
|
// grab the decal color
|
||||||
|
image.fogParams[0] = pal[255*3+0];
|
||||||
|
image.fogParams[1] = pal[255*3+1];
|
||||||
|
image.fogParams[2] = pal[255*3+2];
|
||||||
|
|
||||||
|
// calc the decal reflectivity
|
||||||
|
image.fogParams[3] = VectorAvg( image.fogParams );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// calc texture reflectivity
|
||||||
|
for( i = 0; i < 256; i++ )
|
||||||
|
{
|
||||||
|
reflectivity[0] += pal[i*3+0];
|
||||||
|
reflectivity[1] += pal[i*3+1];
|
||||||
|
reflectivity[2] += pal[i*3+2];
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorDivide( reflectivity, 256, image.fogParams );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image.type = PF_INDEXED_32; // 32-bit palete
|
image.type = PF_INDEXED_32; // 32-bit palete
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ static void NET_AnnounceToMaster( master_t *m )
|
|||||||
MSG_WriteBytes( &msg, "q\xFF", 2 );
|
MSG_WriteBytes( &msg, "q\xFF", 2 );
|
||||||
MSG_WriteDword( &msg, m->heartbeat_challenge );
|
MSG_WriteDword( &msg, m->heartbeat_challenge );
|
||||||
|
|
||||||
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &msg ), MSG_GetBuf( &msg ), m->adr );
|
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg ), m->adr );
|
||||||
|
|
||||||
if( sv_verbose_heartbeats.value )
|
if( sv_verbose_heartbeats.value )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -109,85 +109,6 @@ void MSG_InitMasks( void )
|
|||||||
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
|
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits )
|
|
||||||
{
|
|
||||||
MSG_StartWriting( sb, pData, nBytes, 0, nMaxBits );
|
|
||||||
|
|
||||||
sb->pDebugName = pDebugName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits )
|
|
||||||
{
|
|
||||||
// make sure it's dword aligned and padded.
|
|
||||||
Assert(((uint32_t)pData & 3 ) == 0 );
|
|
||||||
|
|
||||||
sb->pDebugName = "Unnamed";
|
|
||||||
sb->pData = (byte *)pData;
|
|
||||||
|
|
||||||
if( nBits == -1 )
|
|
||||||
{
|
|
||||||
sb->nDataBits = nBytes << 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Assert( nBits <= nBytes * 8 );
|
|
||||||
sb->nDataBits = nBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb->iCurBit = iStartBit;
|
|
||||||
sb->bOverflow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
=======================
|
|
||||||
MSG_Clear
|
|
||||||
|
|
||||||
for clearing overflowed buffer
|
|
||||||
=======================
|
|
||||||
*/
|
|
||||||
void MSG_Clear( sizebuf_t *sb )
|
|
||||||
{
|
|
||||||
sb->iCurBit = 0;
|
|
||||||
sb->bOverflow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
|
||||||
{
|
|
||||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
|
||||||
sb->bOverflow = true;
|
|
||||||
return sb->bOverflow;
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean MSG_CheckOverflow( sizebuf_t *sb )
|
|
||||||
{
|
|
||||||
return MSG_Overflow( sb, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
|
|
||||||
{
|
|
||||||
// compute the file offset
|
|
||||||
switch( whence )
|
|
||||||
{
|
|
||||||
case SEEK_CUR:
|
|
||||||
bitPos += sb->iCurBit;
|
|
||||||
break;
|
|
||||||
case SEEK_SET:
|
|
||||||
break;
|
|
||||||
case SEEK_END:
|
|
||||||
bitPos += sb->nDataBits;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( bitPos < 0 || bitPos > sb->nDataBits )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
sb->iCurBit = bitPos;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||||
{
|
{
|
||||||
if( !MSG_Overflow( sb, 1 ))
|
if( !MSG_Overflow( sb, 1 ))
|
||||||
@@ -669,7 +590,7 @@ qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
|
|||||||
return MSG_ReadBits( sb, pOut, nBytes << 3 );
|
return MSG_ReadBits( sb, pOut, nBytes << 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
|
static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
|
||||||
{
|
{
|
||||||
static char string[4096];
|
static char string[4096];
|
||||||
int l = 0, c;
|
int l = 0, c;
|
||||||
@@ -695,6 +616,16 @@ char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *MSG_ReadString( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return MSG_ReadStringExt( sb, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
char *MSG_ReadStringLine( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return MSG_ReadStringExt( sb, true );
|
||||||
|
}
|
||||||
|
|
||||||
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
|
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
|
||||||
{
|
{
|
||||||
int i, endbit = startbit + bitstoremove;
|
int i, endbit = startbit + bitstoremove;
|
||||||
|
|||||||
@@ -30,39 +30,128 @@ GNU General Public License for more details.
|
|||||||
// So PAD_NUMBER(0,4) is 0 and PAD_NUMBER(1,4) is 4
|
// So PAD_NUMBER(0,4) is 0 and PAD_NUMBER(1,4) is 4
|
||||||
#define PAD_NUMBER( num, boundary ) ((( num ) + (( boundary ) - 1 )) / ( boundary )) * ( boundary )
|
#define PAD_NUMBER( num, boundary ) ((( num ) + (( boundary ) - 1 )) / ( boundary )) * ( boundary )
|
||||||
|
|
||||||
_inline int BitByte( int bits )
|
static inline int BitByte( int bits )
|
||||||
{
|
{
|
||||||
return PAD_NUMBER( bits, 8 ) >> 3;
|
return PAD_NUMBER( bits, 8 ) >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sizebuf_s
|
struct sizebuf_s
|
||||||
{
|
{
|
||||||
qboolean bOverflow; // overflow reading or writing
|
byte *pData;
|
||||||
const char *pDebugName; // buffer name (pointer to const name)
|
qboolean bOverflow; // overflow reading or writing
|
||||||
|
int iCurBit;
|
||||||
byte *pData;
|
int nDataBits;
|
||||||
int iCurBit;
|
const char *pDebugName; // buffer name (pointer to const name)
|
||||||
int nDataBits;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MSG_StartReading MSG_StartWriting
|
#define MSG_StartReading MSG_StartWriting
|
||||||
#define MSG_GetNumBytesRead MSG_GetNumBytesWritten
|
#define MSG_GetNumBytesRead MSG_GetNumBytesWritten
|
||||||
#define MSG_GetRealBytesRead MSG_GetRealBytesWritten
|
#define MSG_GetRealBytesRead MSG_GetRealBytesWritten
|
||||||
#define MSG_GetNumBitsRead MSG_GetNumBitsWritten
|
#define MSG_GetNumBitsRead MSG_GetNumBitsWritten
|
||||||
#define MSG_ReadBitAngles MSG_ReadBitVec3Coord
|
#define MSG_ReadBitAngles MSG_ReadBitVec3Coord
|
||||||
#define MSG_ReadString( sb ) MSG_ReadStringExt( sb, false )
|
#define MSG_ReadAngle( sb ) (float)( MSG_ReadChar( sb ) * ( 360.0f / 256.0f ))
|
||||||
#define MSG_ReadStringLine( sb ) MSG_ReadStringExt( sb, true )
|
#define MSG_Init( sb, name, data, bytes ) MSG_InitExt( sb, name, data, bytes, -1 )
|
||||||
#define MSG_ReadAngle( sb ) (float)(MSG_ReadChar( sb ) * ( 360.0f / 256.0f ))
|
#define MSG_CheckOverflow( sb ) MSG_Overflow( sb, 0 )
|
||||||
#define MSG_Init( sb, name, data, bytes ) MSG_InitExt( sb, name, data, bytes, -1 )
|
|
||||||
|
|
||||||
// common functions
|
// common functions
|
||||||
void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits );
|
static inline void MSG_Clear( sizebuf_t *sb )
|
||||||
void MSG_InitMasks( void ); // called once at startup engine
|
{
|
||||||
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence );
|
sb->bOverflow = false;
|
||||||
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
|
sb->iCurBit = 0;
|
||||||
_inline int MSG_TellBit( sizebuf_t *sb ) { return sb->iCurBit; }
|
}
|
||||||
_inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; }
|
|
||||||
qboolean MSG_CheckOverflow( sizebuf_t *sb );
|
static inline void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nBits )
|
||||||
|
{
|
||||||
|
sb->pData = pData;
|
||||||
|
MSG_Clear( sb );
|
||||||
|
|
||||||
|
if( nBits < 0 )
|
||||||
|
sb->nDataBits = nBytes << 3;
|
||||||
|
else
|
||||||
|
sb->nDataBits = nBits;
|
||||||
|
|
||||||
|
sb->pDebugName = pDebugName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits )
|
||||||
|
{
|
||||||
|
MSG_InitExt( sb, "Unnamed", pData, nBytes, nBits );
|
||||||
|
sb->iCurBit = iStartBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
|
||||||
|
{
|
||||||
|
// compute the file offset
|
||||||
|
switch( whence )
|
||||||
|
{
|
||||||
|
case SEEK_CUR:
|
||||||
|
bitPos += sb->iCurBit;
|
||||||
|
break;
|
||||||
|
case SEEK_SET:
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
bitPos += sb->nDataBits;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( unlikely( bitPos < 0 || bitPos > sb->nDataBits ))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sb->iCurBit = bitPos;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_TellBit( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->iCurBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *MSG_GetName( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->pDebugName;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_GetNumBytesWritten( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return BitByte( sb->iCurBit );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_GetRealBytesWritten( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->iCurBit >> 3; // unpadded
|
||||||
|
}
|
||||||
|
static inline int MSG_GetNumBitsWritten( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->iCurBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_GetMaxBits( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->nDataBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_GetMaxBytes( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->nDataBits >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_GetNumBitsLeft( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->nDataBits - sb->iCurBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int MSG_GetNumBytesLeft( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return MSG_GetNumBitsLeft( sb ) >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline byte *MSG_GetData( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return sb->pData;
|
||||||
|
}
|
||||||
|
|
||||||
#if XASH_BIG_ENDIAN
|
#if XASH_BIG_ENDIAN
|
||||||
#define MSG_BigShort( x ) ( x )
|
#define MSG_BigShort( x ) ( x )
|
||||||
@@ -73,9 +162,15 @@ static inline uint16_t MSG_BigShort( const uint16_t x )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// init writing
|
static inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||||
void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits );
|
{
|
||||||
void MSG_Clear( sizebuf_t *sb );
|
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||||
|
sb->bOverflow = true;
|
||||||
|
return sb->bOverflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MSG_InitMasks( void ); // called once at startup engine
|
||||||
|
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
|
||||||
|
|
||||||
// Bit-write functions
|
// Bit-write functions
|
||||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
|
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
|
||||||
@@ -99,20 +194,11 @@ void MSG_WriteCoord( sizebuf_t *sb, float val );
|
|||||||
void MSG_WriteFloat( sizebuf_t *sb, float val );
|
void MSG_WriteFloat( sizebuf_t *sb, float val );
|
||||||
void MSG_WriteVec3Coord( sizebuf_t *sb, const float *fa );
|
void MSG_WriteVec3Coord( sizebuf_t *sb, const float *fa );
|
||||||
void MSG_WriteVec3Angles( sizebuf_t *sb, const float *fa );
|
void MSG_WriteVec3Angles( sizebuf_t *sb, const float *fa );
|
||||||
qboolean MSG_WriteBytes( sizebuf_t *sb, const void *pBuf, int nBytes ); // same as MSG_WriteData
|
|
||||||
qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr ); // returns false if it overflows the buffer.
|
qboolean MSG_WriteString( sizebuf_t *sb, const char *pStr ); // returns false if it overflows the buffer.
|
||||||
qboolean MSG_WriteStringf( sizebuf_t *sb, const char *format, ... ) _format( 2 );
|
qboolean MSG_WriteStringf( sizebuf_t *sb, const char *format, ... ) _format( 2 );
|
||||||
|
qboolean MSG_WriteBytes( sizebuf_t *sb, const void *pBuf, int nBytes );
|
||||||
|
|
||||||
// helper functions
|
// helper functions
|
||||||
_inline int MSG_GetNumBytesWritten( sizebuf_t *sb ) { return BitByte( sb->iCurBit ); }
|
|
||||||
_inline int MSG_GetRealBytesWritten( sizebuf_t *sb ) { return sb->iCurBit >> 3; } // unpadded
|
|
||||||
_inline int MSG_GetNumBitsWritten( sizebuf_t *sb ) { return sb->iCurBit; }
|
|
||||||
_inline int MSG_GetMaxBits( sizebuf_t *sb ) { return sb->nDataBits; }
|
|
||||||
_inline int MSG_GetMaxBytes( sizebuf_t *sb ) { return sb->nDataBits >> 3; }
|
|
||||||
_inline int MSG_GetNumBitsLeft( sizebuf_t *sb ) { return sb->nDataBits - sb->iCurBit; }
|
|
||||||
_inline int MSG_GetNumBytesLeft( sizebuf_t *sb ) { return MSG_GetNumBitsLeft( sb ) >> 3; }
|
|
||||||
_inline byte *MSG_GetData( sizebuf_t *sb ) { return sb->pData; }
|
|
||||||
_inline byte *MSG_GetBuf( sizebuf_t *sb ) { return sb->pData; } // just an alias
|
|
||||||
|
|
||||||
// Bit-read functions
|
// Bit-read functions
|
||||||
int MSG_ReadOneBit( sizebuf_t *sb );
|
int MSG_ReadOneBit( sizebuf_t *sb );
|
||||||
@@ -136,7 +222,8 @@ float MSG_ReadCoord( sizebuf_t *sb );
|
|||||||
float MSG_ReadFloat( sizebuf_t *sb );
|
float MSG_ReadFloat( sizebuf_t *sb );
|
||||||
void MSG_ReadVec3Coord( sizebuf_t *sb, vec3_t fa );
|
void MSG_ReadVec3Coord( sizebuf_t *sb, vec3_t fa );
|
||||||
void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa );
|
void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa );
|
||||||
|
char *MSG_ReadString( sizebuf_t *sb );
|
||||||
|
char *MSG_ReadStringLine( sizebuf_t *sb );
|
||||||
qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes );
|
qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes );
|
||||||
char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine );
|
|
||||||
|
|
||||||
#endif//NET_BUFFER_H
|
#endif//NET_BUFFER_H
|
||||||
|
|||||||
@@ -315,6 +315,43 @@ static const delta_field_t ent_fields[] =
|
|||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if XASH_ENGINE_TESTS
|
||||||
|
typedef struct delta_test_struct_t
|
||||||
|
{
|
||||||
|
char dt_string[128]; // always signed
|
||||||
|
float dt_timewindow_big; // always signed
|
||||||
|
float dt_timewindow_8; // always signed
|
||||||
|
float dt_angle; // always_signed
|
||||||
|
float dt_float_signed;
|
||||||
|
float dt_float_unsigned;
|
||||||
|
int32_t dt_integer_signed;
|
||||||
|
uint32_t dt_integer_unsigned;
|
||||||
|
int16_t dt_short_signed;
|
||||||
|
uint16_t dt_short_unsigned;
|
||||||
|
int8_t dt_byte_signed;
|
||||||
|
uint8_t dt_byte_unsigned;
|
||||||
|
} delta_test_struct_t;
|
||||||
|
|
||||||
|
#define TEST_DEF( x ) #x, offsetof( delta_test_struct_t, x ), sizeof( ((delta_test_struct_t *)0)->x )
|
||||||
|
|
||||||
|
static const delta_field_t test_fields[] =
|
||||||
|
{
|
||||||
|
{ TEST_DEF( dt_string ) },
|
||||||
|
{ TEST_DEF( dt_timewindow_big )},
|
||||||
|
{ TEST_DEF( dt_timewindow_8 )},
|
||||||
|
{ TEST_DEF( dt_angle ) },
|
||||||
|
{ TEST_DEF( dt_float_signed ) },
|
||||||
|
{ TEST_DEF( dt_float_unsigned ) },
|
||||||
|
{ TEST_DEF( dt_integer_signed ) },
|
||||||
|
{ TEST_DEF( dt_integer_unsigned ) },
|
||||||
|
{ TEST_DEF( dt_short_signed ) },
|
||||||
|
{ TEST_DEF( dt_short_unsigned ) },
|
||||||
|
{ TEST_DEF( dt_byte_signed ) },
|
||||||
|
{ TEST_DEF( dt_byte_unsigned ) },
|
||||||
|
{ NULL },
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
DT_EVENT_T = 0,
|
DT_EVENT_T = 0,
|
||||||
@@ -325,6 +362,10 @@ enum
|
|||||||
DT_ENTITY_STATE_T,
|
DT_ENTITY_STATE_T,
|
||||||
DT_ENTITY_STATE_PLAYER_T,
|
DT_ENTITY_STATE_PLAYER_T,
|
||||||
DT_CUSTOM_ENTITY_STATE_T,
|
DT_CUSTOM_ENTITY_STATE_T,
|
||||||
|
#if XASH_ENGINE_TESTS
|
||||||
|
DT_DELTA_TEST_STRUCT_T,
|
||||||
|
#endif
|
||||||
|
DT_STRUCT_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
static delta_info_t dt_info[] =
|
static delta_info_t dt_info[] =
|
||||||
@@ -337,7 +378,10 @@ static delta_info_t dt_info[] =
|
|||||||
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||||
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||||
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
|
||||||
{ NULL },
|
#if XASH_ENGINE_TESTS
|
||||||
|
[DT_DELTA_TEST_STRUCT_T] = { "delta_test_struct_t", test_fields, NUM_FIELDS( test_fields ) },
|
||||||
|
#endif
|
||||||
|
[DT_STRUCT_COUNT] = { NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static delta_info_t *Delta_FindStruct( const char *name )
|
static delta_info_t *Delta_FindStruct( const char *name )
|
||||||
@@ -411,9 +455,7 @@ static void Delta_CustomEncode( delta_info_t *dt, const void *from, const void *
|
|||||||
dt->pFields[i].bInactive = false;
|
dt->pFields[i].bInactive = false;
|
||||||
|
|
||||||
if( dt->userCallback )
|
if( dt->userCallback )
|
||||||
{
|
|
||||||
dt->userCallback( dt->pFields, from, to );
|
dt->userCallback( dt->pFields, from, to );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName )
|
static delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName )
|
||||||
@@ -974,14 +1016,14 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
toF = *(uint8_t *)((int8_t *)to + pField->offset );
|
toF = *(uint8_t *)((int8_t *)to + pField->offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !Q_equal(pField->multiplier, 1.0f ))
|
||||||
|
{
|
||||||
|
fromF *= pField->multiplier;
|
||||||
|
toF *= pField->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
||||||
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
||||||
|
|
||||||
if( !Q_equal(pField->multiplier, 1.0f ))
|
|
||||||
fromF *= pField->multiplier;
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
|
||||||
toF *= pField->multiplier;
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_SHORT )
|
else if( pField->flags & DT_SHORT )
|
||||||
{
|
{
|
||||||
@@ -996,14 +1038,14 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
toF = *(uint16_t *)((int8_t *)to + pField->offset );
|
toF = *(uint16_t *)((int8_t *)to + pField->offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !Q_equal(pField->multiplier, 1.0f ))
|
||||||
|
{
|
||||||
|
fromF *= pField->multiplier;
|
||||||
|
toF *= pField->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
||||||
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
||||||
|
|
||||||
if( !Q_equal(pField->multiplier, 1.0f ))
|
|
||||||
fromF *= pField->multiplier;
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
|
||||||
toF *= pField->multiplier;
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_INTEGER )
|
else if( pField->flags & DT_INTEGER )
|
||||||
{
|
{
|
||||||
@@ -1017,14 +1059,15 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
fromF = *(uint32_t *)((int8_t *)from + pField->offset );
|
fromF = *(uint32_t *)((int8_t *)from + pField->offset );
|
||||||
toF = *(uint32_t *)((int8_t *)to + pField->offset );
|
toF = *(uint32_t *)((int8_t *)to + pField->offset );
|
||||||
}
|
}
|
||||||
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
|
||||||
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal(pField->multiplier, 1.0f ))
|
if( !Q_equal(pField->multiplier, 1.0f ))
|
||||||
|
{
|
||||||
fromF *= pField->multiplier;
|
fromF *= pField->multiplier;
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
|
||||||
toF *= pField->multiplier;
|
toF *= pField->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
fromF = Delta_ClampIntegerField( pField, fromF, signbit, pField->bits );
|
||||||
|
toF = Delta_ClampIntegerField( pField, toF, signbit, pField->bits );
|
||||||
}
|
}
|
||||||
else if( pField->flags & ( DT_ANGLE|DT_FLOAT ))
|
else if( pField->flags & ( DT_ANGLE|DT_FLOAT ))
|
||||||
{
|
{
|
||||||
@@ -1034,33 +1077,17 @@ static qboolean Delta_CompareField( delta_t *pField, void *from, void *to, doubl
|
|||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_8 )
|
else if( pField->flags & DT_TIMEWINDOW_8 )
|
||||||
{
|
{
|
||||||
val_a = Q_rint((*(float *)((byte *)from + pField->offset )) * 100.0f );
|
val_a = *(float *)((byte *)from + pField->offset );
|
||||||
val_b = Q_rint((*(float *)((byte *)to + pField->offset )) * 100.0f );
|
val_b = *(float *)((byte *)to + pField->offset );
|
||||||
val_a -= Q_rint(timebase * 100.0);
|
fromF = Q_rint(( timebase - val_a ) * 100.0 );
|
||||||
val_b -= Q_rint(timebase * 100.0);
|
toF = Q_rint(( timebase - val_b ) * 100.0 );
|
||||||
fromF = FloatAsInt( val_a );
|
|
||||||
toF = FloatAsInt( val_b );
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
||||||
{
|
{
|
||||||
val_a = (*(float *)((byte *)from + pField->offset ));
|
val_a = *(float *)((byte *)from + pField->offset );
|
||||||
val_b = (*(float *)((byte *)to + pField->offset ));
|
val_b = *(float *)((byte *)to + pField->offset );
|
||||||
|
fromF = Q_rint(( timebase - val_a ) * pField->multiplier );
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
toF = Q_rint(( timebase - val_b ) * pField->multiplier );
|
||||||
{
|
|
||||||
val_a *= pField->multiplier;
|
|
||||||
val_b *= pField->multiplier;
|
|
||||||
val_a = (timebase * pField->multiplier) - val_a;
|
|
||||||
val_b = (timebase * pField->multiplier) - val_b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val_a = timebase - val_a;
|
|
||||||
val_b = timebase - val_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
fromF = FloatAsInt( val_a );
|
|
||||||
toF = FloatAsInt( val_b );
|
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_STRING )
|
else if( pField->flags & DT_STRING )
|
||||||
{
|
{
|
||||||
@@ -1144,6 +1171,7 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
int signbit = FBitSet( pField->flags, DT_SIGNED ) ? 1 : 0;
|
int signbit = FBitSet( pField->flags, DT_SIGNED ) ? 1 : 0;
|
||||||
float flValue, flAngle;
|
float flValue, flAngle;
|
||||||
uint iValue;
|
uint iValue;
|
||||||
|
int dt;
|
||||||
const char *pStr;
|
const char *pStr;
|
||||||
|
|
||||||
if( Delta_CompareField( pField, from, to, timebase ))
|
if( Delta_CompareField( pField, from, to, timebase ))
|
||||||
@@ -1160,11 +1188,11 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
iValue = *(int8_t *)((int8_t *)to + pField->offset );
|
iValue = *(int8_t *)((int8_t *)to + pField->offset );
|
||||||
else
|
else
|
||||||
iValue = *(uint8_t *)((int8_t *)to + pField->offset );
|
iValue = *(uint8_t *)((int8_t *)to + pField->offset );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue *= pField->multiplier;
|
iValue *= pField->multiplier;
|
||||||
|
|
||||||
|
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_SHORT )
|
else if( pField->flags & DT_SHORT )
|
||||||
@@ -1173,11 +1201,11 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
iValue = *(int16_t *)((int8_t *)to + pField->offset );
|
iValue = *(int16_t *)((int8_t *)to + pField->offset );
|
||||||
else
|
else
|
||||||
iValue = *(uint16_t *)((int8_t *)to + pField->offset );
|
iValue = *(uint16_t *)((int8_t *)to + pField->offset );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue *= pField->multiplier;
|
iValue *= pField->multiplier;
|
||||||
|
|
||||||
|
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_INTEGER )
|
else if( pField->flags & DT_INTEGER )
|
||||||
@@ -1186,11 +1214,11 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
iValue = *(int32_t *)((int8_t *)to + pField->offset );
|
iValue = *(int32_t *)((int8_t *)to + pField->offset );
|
||||||
else
|
else
|
||||||
iValue = *(uint32_t *)((int8_t *)to + pField->offset );
|
iValue = *(uint32_t *)((int8_t *)to + pField->offset );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue *= pField->multiplier;
|
iValue *= pField->multiplier;
|
||||||
|
|
||||||
|
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_FLOAT )
|
else if( pField->flags & DT_FLOAT )
|
||||||
@@ -1210,19 +1238,17 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, v
|
|||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_8 )
|
else if( pField->flags & DT_TIMEWINDOW_8 )
|
||||||
{
|
{
|
||||||
signbit = 1; // timewindow is always signed
|
|
||||||
flValue = *(float *)((byte *)to + pField->offset );
|
flValue = *(float *)((byte *)to + pField->offset );
|
||||||
iValue = (int)Q_rint( timebase * 100.0 ) - (int)Q_rint( flValue * 100.0 );
|
dt = Q_rint(( timebase - flValue ) * 100.0 );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
dt = Delta_ClampIntegerField( pField, dt, 1, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteSBitLong( msg, dt, pField->bits );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
||||||
{
|
{
|
||||||
signbit = 1; // timewindow is always signed
|
|
||||||
flValue = *(float *)((byte *)to + pField->offset );
|
flValue = *(float *)((byte *)to + pField->offset );
|
||||||
iValue = (int)Q_rint( timebase * pField->multiplier ) - (int)Q_rint( flValue * pField->multiplier );
|
dt = Q_rint(( timebase - flValue ) * pField->multiplier );
|
||||||
iValue = Delta_ClampIntegerField( pField, iValue, signbit, pField->bits );
|
dt = Delta_ClampIntegerField( pField, dt, 1, pField->bits );
|
||||||
MSG_WriteBitLong( msg, iValue, pField->bits, signbit );
|
MSG_WriteSBitLong( msg, dt, pField->bits );
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_STRING )
|
else if( pField->flags & DT_STRING )
|
||||||
{
|
{
|
||||||
@@ -1306,9 +1332,12 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
if( pField->flags & DT_BYTE )
|
if( pField->flags & DT_BYTE )
|
||||||
{
|
{
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue /= pField->multiplier;
|
iValue /= pField->multiplier;
|
||||||
|
|
||||||
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
|
iValue *= pField->post_multiplier;
|
||||||
|
|
||||||
if( bSigned )
|
if( bSigned )
|
||||||
*(int8_t *)((uint8_t *)to + pField->offset ) = iValue;
|
*(int8_t *)((uint8_t *)to + pField->offset ) = iValue;
|
||||||
else
|
else
|
||||||
@@ -1317,9 +1346,12 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
else if( pField->flags & DT_SHORT )
|
else if( pField->flags & DT_SHORT )
|
||||||
{
|
{
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue /= pField->multiplier;
|
iValue /= pField->multiplier;
|
||||||
|
|
||||||
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
|
iValue *= pField->post_multiplier;
|
||||||
|
|
||||||
if( bSigned )
|
if( bSigned )
|
||||||
*(int16_t *)((uint8_t *)to + pField->offset ) = iValue;
|
*(int16_t *)((uint8_t *)to + pField->offset ) = iValue;
|
||||||
else
|
else
|
||||||
@@ -1328,9 +1360,12 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
else if( pField->flags & DT_INTEGER )
|
else if( pField->flags & DT_INTEGER )
|
||||||
{
|
{
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
iValue /= pField->multiplier;
|
iValue /= pField->multiplier;
|
||||||
|
|
||||||
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
|
iValue *= pField->post_multiplier;
|
||||||
|
|
||||||
if( bSigned )
|
if( bSigned )
|
||||||
*(int32_t *)((uint8_t *)to + pField->offset ) = iValue;
|
*(int32_t *)((uint8_t *)to + pField->offset ) = iValue;
|
||||||
else
|
else
|
||||||
@@ -1344,11 +1379,11 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
else
|
else
|
||||||
flValue = iValue;
|
flValue = iValue;
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
flValue = flValue / pField->multiplier;
|
flValue /= pField->multiplier;
|
||||||
|
|
||||||
if( !Q_equal( pField->post_multiplier, 1.0 ) )
|
if( !Q_equal( pField->post_multiplier, 1.0 ))
|
||||||
flValue = flValue * pField->post_multiplier;
|
flValue *= pField->post_multiplier;
|
||||||
|
|
||||||
*(float *)((byte *)to + pField->offset ) = flValue;
|
*(float *)((byte *)to + pField->offset ) = flValue;
|
||||||
}
|
}
|
||||||
@@ -1370,7 +1405,7 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
bSigned = true; // timewindow is always signed
|
bSigned = true; // timewindow is always signed
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
if( !Q_equal( pField->multiplier, 1.0 ))
|
||||||
flTime = ( timebase * pField->multiplier - (int)iValue ) / pField->multiplier;
|
flTime = ( timebase * pField->multiplier - (int)iValue ) / pField->multiplier;
|
||||||
else
|
else
|
||||||
flTime = timebase - (int)iValue;
|
flTime = timebase - (int)iValue;
|
||||||
@@ -2069,3 +2104,103 @@ void GAME_EXPORT Delta_UnsetFieldByIndex( delta_t *pFields, int fieldNumber )
|
|||||||
|
|
||||||
dt->pFields[fieldNumber].bInactive = true;
|
dt->pFields[fieldNumber].bInactive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_ENGINE_TESTS
|
||||||
|
#include "tests.h"
|
||||||
|
|
||||||
|
void Test_RunDelta( void )
|
||||||
|
{
|
||||||
|
delta_info_t *dt = &dt_info[DT_DELTA_TEST_STRUCT_T];
|
||||||
|
delta_test_struct_t from, to = { 0 };
|
||||||
|
delta_test_struct_t null = { 0 };
|
||||||
|
sizebuf_t msg;
|
||||||
|
int i;
|
||||||
|
char buffer[4096] = { 0 };
|
||||||
|
const double timebase = 123.123;
|
||||||
|
|
||||||
|
// a1ba: netbuffer bitmasks are initialized in netchan for some reason
|
||||||
|
// initialize it ourselves just in case
|
||||||
|
MSG_InitMasks(); // initialize bit-masks
|
||||||
|
|
||||||
|
Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_angle", DT_ANGLE, 16, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_float_signed", DT_FLOAT | DT_SIGNED, 22, 100.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_float_unsigned", DT_FLOAT, 24, 10000.0f, 0.1f );
|
||||||
|
Delta_AddField( dt, "dt_integer_signed", DT_INTEGER | DT_SIGNED, 24, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_integer_unsigned", DT_INTEGER, 24, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_short_signed", DT_SHORT | DT_SIGNED, 16, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_short_unsigned", DT_SHORT, 15, 0.125f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_byte_signed", DT_BYTE | DT_SIGNED, 6, 1.0f, 1.0f );
|
||||||
|
Delta_AddField( dt, "dt_byte_unsigned", DT_BYTE, 8, 1.0f, 1.0f );
|
||||||
|
|
||||||
|
Q_strncpy( from.dt_string, "test data check it's the same", sizeof( from.dt_string ));
|
||||||
|
from.dt_timewindow_big = timebase + 2.3456;
|
||||||
|
from.dt_timewindow_8 = timebase + 0.0234;
|
||||||
|
from.dt_angle = 160.245f;
|
||||||
|
from.dt_float_signed = -15.123f;
|
||||||
|
from.dt_float_unsigned = 1235.321f;
|
||||||
|
from.dt_integer_signed = -412784;
|
||||||
|
from.dt_integer_unsigned = 123453;
|
||||||
|
from.dt_short_signed = -12343;
|
||||||
|
from.dt_short_unsigned = 32131;
|
||||||
|
from.dt_byte_signed = 16;
|
||||||
|
from.dt_byte_unsigned = 218;
|
||||||
|
|
||||||
|
MSG_Init( &msg, "test message", buffer, sizeof( buffer ));
|
||||||
|
|
||||||
|
for( i = 0; i < dt->numFields; i++ )
|
||||||
|
Delta_WriteField( &msg, &dt->pFields[i], &null, &from, timebase );
|
||||||
|
|
||||||
|
MSG_SeekToBit( &msg, 0, SEEK_SET );
|
||||||
|
|
||||||
|
for( i = 0; i < dt->numFields; i++ )
|
||||||
|
Delta_ReadField( &msg, &dt->pFields[i], &null, &to, timebase );
|
||||||
|
|
||||||
|
Con_Printf( "struct as encoded to delta:\n" );
|
||||||
|
TASSERT_STR( from.dt_string, to.dt_string );
|
||||||
|
|
||||||
|
// the epsilon value is derived from multiplier value
|
||||||
|
TASSERT( Q_equal_e( from.dt_timewindow_big, to.dt_timewindow_big, 0.001f ));
|
||||||
|
|
||||||
|
// dt_timewindow_8 type has multiplier locked at 100.0f
|
||||||
|
TASSERT( Q_equal_e( from.dt_timewindow_8, to.dt_timewindow_8, 0.01f ));
|
||||||
|
TASSERT( Q_equal_e( from.dt_angle, to.dt_angle, 0.1f ));
|
||||||
|
TASSERT( Q_equal_e( from.dt_float_signed, to.dt_float_signed, 0.01f ));
|
||||||
|
|
||||||
|
// dt_float_unsigned has post-multiplier that doesn't affect network data
|
||||||
|
// and therefore should be reverted back when comparing
|
||||||
|
TASSERT( Q_equal_e( from.dt_float_unsigned, to.dt_float_unsigned * 10.f , 0.01f ));
|
||||||
|
|
||||||
|
TASSERT_EQi( from.dt_integer_signed, to.dt_integer_signed );
|
||||||
|
TASSERT_EQi( from.dt_integer_unsigned, to.dt_integer_unsigned );
|
||||||
|
TASSERT_EQi( from.dt_short_signed, to.dt_short_signed );
|
||||||
|
TASSERT(( from.dt_short_unsigned & ( 0xffff << 3 )) == to.dt_short_unsigned );
|
||||||
|
TASSERT_EQi( from.dt_byte_signed, to.dt_byte_signed );
|
||||||
|
TASSERT_EQi( from.dt_byte_unsigned, to.dt_byte_unsigned );
|
||||||
|
|
||||||
|
Con_Printf( "from.dt_timewindow_big = %f\n", from.dt_timewindow_big );
|
||||||
|
Con_Printf( "to.dt_timewindow_big = %f\n", to.dt_timewindow_big );
|
||||||
|
Con_Printf( "from.dt_timewindow_8 = %f\n", from.dt_timewindow_8 );
|
||||||
|
Con_Printf( "to.dt_timewindow_8 = %f\n", to.dt_timewindow_8 );
|
||||||
|
Con_Printf( "from.dt_angle = %f\n", from.dt_angle );
|
||||||
|
Con_Printf( "to.dt_angle = %f\n", to.dt_angle );
|
||||||
|
Con_Printf( "from.dt_float_signed = %f\n", from.dt_float_signed );
|
||||||
|
Con_Printf( "to.dt_float_signed = %f\n", to.dt_float_signed );
|
||||||
|
Con_Printf( "from.dt_float_unsigned = %f\n", from.dt_float_unsigned );
|
||||||
|
Con_Printf( "to.dt_float_unsigned = %f\n", to.dt_float_unsigned );
|
||||||
|
Con_Printf( "from.dt_integer_signed = %i\n", from.dt_integer_signed );
|
||||||
|
Con_Printf( "to.dt_integer_signed = %i\n", to.dt_integer_signed );
|
||||||
|
Con_Printf( "from.dt_integer_unsigned = %i\n", from.dt_integer_unsigned );
|
||||||
|
Con_Printf( "to.dt_integer_unsigned = %i\n", to.dt_integer_unsigned );
|
||||||
|
Con_Printf( "from.dt_short_signed = %i\n", from.dt_short_signed );
|
||||||
|
Con_Printf( "to.dt_short_signed = %i\n", to.dt_short_signed );
|
||||||
|
Con_Printf( "from.dt_short_unsigned = %i\n", from.dt_short_unsigned );
|
||||||
|
Con_Printf( "to.dt_short_unsigned = %i\n", to.dt_short_unsigned );
|
||||||
|
Con_Printf( "from.dt_byte_signed = %i\n", from.dt_byte_signed );
|
||||||
|
Con_Printf( "to.dt_byte_signed = %i\n", to.dt_byte_signed );
|
||||||
|
Con_Printf( "from.dt_byte_unsigned = %i\n", from.dt_byte_unsigned );
|
||||||
|
Con_Printf( "to.dt_byte_unsigned = %i\n", to.dt_byte_unsigned );
|
||||||
|
}
|
||||||
|
#endif // XASH_ENGINE_TESTS
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ GNU General Public License for more details.
|
|||||||
#define MAX_CUSTOM (1<<MAX_CUSTOM_BITS)// 10 bits == 1024 generic file
|
#define MAX_CUSTOM (1<<MAX_CUSTOM_BITS)// 10 bits == 1024 generic file
|
||||||
#define MAX_USER_MESSAGES 197 // another 58 messages reserved for engine routines
|
#define MAX_USER_MESSAGES 197 // another 58 messages reserved for engine routines
|
||||||
#define MAX_DLIGHTS 32 // dynamic lights (rendered per one frame)
|
#define MAX_DLIGHTS 32 // dynamic lights (rendered per one frame)
|
||||||
#define MAX_ELIGHTS 64 // entity only point lights
|
#define MAX_ELIGHTS 128 // a1ba: increased from 64 to 128, entity only point lights
|
||||||
#define MAX_LIGHTSTYLES 256 // a1ba: increased from 64 to 256, protocol limit
|
#define MAX_LIGHTSTYLES 256 // a1ba: increased from 64 to 256, protocol limit
|
||||||
#define MAX_RENDER_DECALS 4096 // max rendering decals per a level
|
#define MAX_RENDER_DECALS 4096 // max rendering decals per a level
|
||||||
|
|
||||||
|
|||||||
362
engine/common/sounds.c
Normal file
362
engine/common/sounds.c
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
sounds.c - sounds.lst parser
|
||||||
|
Copyright (C) 2024 Alibek Omarov
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
enum soundlst_type_e
|
||||||
|
{
|
||||||
|
SoundList_None,
|
||||||
|
SoundList_Range,
|
||||||
|
SoundList_List
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *soundlst_groups[SoundList_Groups] =
|
||||||
|
{
|
||||||
|
"BouncePlayerShell",
|
||||||
|
"BounceWeaponShell",
|
||||||
|
"BounceConcrete",
|
||||||
|
"BounceGlass",
|
||||||
|
"BounceMetal",
|
||||||
|
"BounceFlesh",
|
||||||
|
"BounceWood",
|
||||||
|
"Ricochet",
|
||||||
|
"Explode",
|
||||||
|
"PlayerWaterEnter",
|
||||||
|
"PlayerWaterExit",
|
||||||
|
"EntityWaterEnter",
|
||||||
|
"EntityWaterExit",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct soundlst_s
|
||||||
|
{
|
||||||
|
enum soundlst_type_e type;
|
||||||
|
char *snd;
|
||||||
|
int min; // the string length if type is group
|
||||||
|
int max; // the string count if type is group
|
||||||
|
} soundlst_t;
|
||||||
|
|
||||||
|
soundlst_t soundlst[SoundList_Groups];
|
||||||
|
|
||||||
|
static void SoundList_Print_f( void );
|
||||||
|
static void SoundList_Free( soundlst_t *lst )
|
||||||
|
{
|
||||||
|
if( lst->snd )
|
||||||
|
Mem_Free( lst->snd );
|
||||||
|
|
||||||
|
memset( lst, 0, sizeof( *lst ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundList_Shutdown( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < SoundList_Groups; i++ )
|
||||||
|
SoundList_Free( &soundlst[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
int SoundList_Count( enum soundlst_group_e group )
|
||||||
|
{
|
||||||
|
soundlst_t *lst = &soundlst[group];
|
||||||
|
|
||||||
|
switch( lst->type )
|
||||||
|
{
|
||||||
|
case SoundList_Range:
|
||||||
|
return lst->max - lst->min + 1;
|
||||||
|
case SoundList_List:
|
||||||
|
return lst->max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SoundList_Get( enum soundlst_group_e group, int i )
|
||||||
|
{
|
||||||
|
static string temp;
|
||||||
|
soundlst_t *lst = &soundlst[group];
|
||||||
|
|
||||||
|
if( i < 0 || i >= SoundList_Count( group ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch( lst->type )
|
||||||
|
{
|
||||||
|
case SoundList_Range:
|
||||||
|
Q_snprintf( temp, sizeof( temp ), lst->snd, lst->min + i );
|
||||||
|
return temp;
|
||||||
|
case SoundList_List:
|
||||||
|
return &lst->snd[i * lst->min];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *SoundList_GetRandom( enum soundlst_group_e group )
|
||||||
|
{
|
||||||
|
int count = SoundList_Count( group );
|
||||||
|
int idx = COM_RandomLong( 0, count - 1 );
|
||||||
|
|
||||||
|
// Con_Printf( "%s: %s %d %d\n", __func__, soundlst_groups[group], count, idx );
|
||||||
|
|
||||||
|
return SoundList_Get( group, idx );
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean SoundList_ParseGroup( soundlst_t *lst, char **file )
|
||||||
|
{
|
||||||
|
string token;
|
||||||
|
int count = 0, slen = 0, i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
p = *file;
|
||||||
|
|
||||||
|
while(( p = COM_ParseFile( p, token, sizeof( token ))))
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if( !Q_strcmp( token, "}" ))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( !Q_strcmp( token, "{" ))
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: expected '}' but got '{' during group list parse\n", __func__ );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if( !COM_CheckStringEmpty( token ))
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: expected '}' but got EOF during group list parse\n", __func__ );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = Q_strlen( token ) + 1;
|
||||||
|
if( slen < len )
|
||||||
|
slen = len;
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( count == 0 ) // deactivate group
|
||||||
|
{
|
||||||
|
lst->type = SoundList_None;
|
||||||
|
lst->snd = NULL;
|
||||||
|
lst->min = lst->max = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lst->type = SoundList_List;
|
||||||
|
lst->min = slen;
|
||||||
|
lst->max = count;
|
||||||
|
lst->snd = Mem_Malloc( host.mempool, count * slen ); // allocate single buffer for the whole group
|
||||||
|
|
||||||
|
for( i = 0; i < count; i++ )
|
||||||
|
{
|
||||||
|
*file = COM_ParseFile( *file, token, sizeof( token ));
|
||||||
|
|
||||||
|
Q_strncpy( &lst->snd[i * slen], token, slen );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean SoundList_ParseRange( soundlst_t *lst, char **file )
|
||||||
|
{
|
||||||
|
string token, snd;
|
||||||
|
char *p;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
lst->type = SoundList_Range;
|
||||||
|
*file = COM_ParseFile( *file, snd, sizeof( snd ));
|
||||||
|
|
||||||
|
// validate format string, count all % characters
|
||||||
|
p = snd;
|
||||||
|
i = 0;
|
||||||
|
while(( p = Q_strchr( p, '%' )))
|
||||||
|
{
|
||||||
|
// only decimal
|
||||||
|
if( p[1] != 'd' && p[1] != 'i' && p[1] != 'u' )
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: invalid range string %s, only decimal numbers are allowed", __func__, snd );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if more than one %, then it's an invalid format string
|
||||||
|
if( i != 1 )
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: invalid range string %s, only single specifier is allowed\n", __func__, snd );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*file = COM_ParseFile( *file, token, sizeof( token ));
|
||||||
|
if( !Q_isdigit( token ))
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: %s must be a digit\n", __func__, token );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lst->min = Q_atoi( token );
|
||||||
|
|
||||||
|
*file = COM_ParseFile( *file, token, sizeof( token ));
|
||||||
|
if( !Q_isdigit( token ))
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: %s must be a digit\n", __func__, token );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lst->max = Q_atoi( token );
|
||||||
|
lst->snd = copystring( snd );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean SoundList_Parse( char *file )
|
||||||
|
{
|
||||||
|
string token;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while(( file = COM_ParseFile( file, token, sizeof( token ))))
|
||||||
|
{
|
||||||
|
soundlst_t *lst = NULL;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for( i = 0; i < SoundList_Groups; i++ )
|
||||||
|
{
|
||||||
|
if( !Q_strcmp( token, soundlst_groups[i] ))
|
||||||
|
{
|
||||||
|
lst = &soundlst[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !lst )
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: unexpected token %s, must be group name\n", __func__, token );
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = COM_ParseFile( file, token, sizeof( token ));
|
||||||
|
|
||||||
|
// group is a range
|
||||||
|
if( !Q_strcmp( token, "{" ))
|
||||||
|
{
|
||||||
|
file = p; // advance pointer
|
||||||
|
|
||||||
|
if( !SoundList_ParseGroup( lst, &file ))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
file = COM_ParseFile( file, token, sizeof( token ));
|
||||||
|
if( Q_strcmp( token, "}" ))
|
||||||
|
{
|
||||||
|
Con_Printf( "%s: unexpected token %s, must be }\n", __func__, token );
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ranges are more simple, but need to rewind pointer for them
|
||||||
|
if( !SoundList_ParseRange( lst, &file ))
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( host_developer.value >= 2 )
|
||||||
|
SoundList_Print_f();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
SoundList_Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SoundList_Print_f( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < SoundList_Groups; i++ )
|
||||||
|
{
|
||||||
|
soundlst_t *lst = &soundlst[i];
|
||||||
|
|
||||||
|
switch( lst->type )
|
||||||
|
{
|
||||||
|
case SoundList_Range:
|
||||||
|
Con_Reportf( "%-16s\t" S_CYAN "Range" S_DEFAULT " %s [%d; %d]\n",
|
||||||
|
soundlst_groups[i], lst->snd, lst->min, lst->max );
|
||||||
|
break;
|
||||||
|
case SoundList_List:
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
Con_Reportf( "%-16s\t" S_MAGENTA "List" S_DEFAULT " [", soundlst_groups[i] );
|
||||||
|
for( j = 0; j < lst->max; j++ )
|
||||||
|
Con_Reportf( "%s%s", &lst->snd[j * lst->min], j + 1 == lst->max ? "" : ", " );
|
||||||
|
Con_Reportf( "]\n" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Con_Reportf( "%-16s\t" S_RED "inactive" S_DEFAULT "\n", soundlst_groups[i] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// I wish we had #embed already
|
||||||
|
static const char default_sounds_lst[] =
|
||||||
|
"BouncePlayerShell \"player/pl_shell%d.wav\" 1 3\n"
|
||||||
|
"BounceWeaponShell \"weapons/sshell%d.wav\" 1 3\n"
|
||||||
|
"BounceConcrete \"debris/concrete%d.wav\" 1 3\n"
|
||||||
|
"BounceGlass \"debris/glass%d.wav\" 1 4\n"
|
||||||
|
"BounceMetal \"debris/metal%d.wav\" 1 6\n"
|
||||||
|
"BounceFlesh \"debris/flesh%d.wav\" 1 7\n"
|
||||||
|
"BounceWood \"debris/wood%d.wav\" 1 4\n"
|
||||||
|
"Ricochet \"weapons/ric%d.wav\" 1 5\n"
|
||||||
|
"Explode \"weapons/explode%d.wav\" 3 5\n"
|
||||||
|
"EntityWaterEnter \"player/pl_wade%d.wav\" 1 4\n"
|
||||||
|
"EntityWaterExit \"player/pl_wade%d.wav\" 1 4\n"
|
||||||
|
"PlayerWaterEnter\n"
|
||||||
|
"{\n"
|
||||||
|
" \"player/pl_wade1.wav\"\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"PlayerWaterExit\n"
|
||||||
|
"{\n"
|
||||||
|
" \"player/pl_wade2.wav\"\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static void SoundList_Reload_f( void )
|
||||||
|
{
|
||||||
|
qboolean load_internal = false;
|
||||||
|
char *pfile = FS_LoadFile( "scripts/sounds.lst", NULL, false );
|
||||||
|
|
||||||
|
if( pfile )
|
||||||
|
{
|
||||||
|
if( !SoundList_Parse( pfile ))
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "can't parse sounds.lst file, loading internal...\n" );
|
||||||
|
load_internal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem_Free( pfile );
|
||||||
|
}
|
||||||
|
else load_internal = true;
|
||||||
|
|
||||||
|
if( load_internal )
|
||||||
|
SoundList_Parse( (char *)default_sounds_lst );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundList_Init( void )
|
||||||
|
{
|
||||||
|
Cmd_AddRestrictedCommand( "host_soundlist_print", SoundList_Print_f, "print current sound list" );
|
||||||
|
Cmd_AddRestrictedCommand( "host_soundlist_reload", SoundList_Reload_f, "reload sound list" );
|
||||||
|
|
||||||
|
SoundList_Reload_f ();
|
||||||
|
}
|
||||||
@@ -135,6 +135,10 @@ void Sys_InitLog( void )
|
|||||||
mode = "a";
|
mode = "a";
|
||||||
else mode = "w";
|
else mode = "w";
|
||||||
|
|
||||||
|
if( Host_IsDedicated( ))
|
||||||
|
Q_strncpy( s_ld.title, XASH_DEDICATED_SERVER_NAME " " XASH_VERSION, sizeof( s_ld.title ));
|
||||||
|
else Q_strncpy( s_ld.title, XASH_ENGINE_NAME " " XASH_VERSION, sizeof( s_ld.title ));
|
||||||
|
|
||||||
// create log if needed
|
// create log if needed
|
||||||
if( s_ld.log_active )
|
if( s_ld.log_active )
|
||||||
{
|
{
|
||||||
@@ -142,15 +146,18 @@ void Sys_InitLog( void )
|
|||||||
|
|
||||||
if ( !s_ld.logfile )
|
if ( !s_ld.logfile )
|
||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno ) );
|
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno ));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_ld.logfileno = fileno( s_ld.logfile );
|
s_ld.logfileno = fileno( s_ld.logfile );
|
||||||
|
|
||||||
fprintf( s_ld.logfile, "=================================================================================\n" );
|
// fit to 80 columns for easier read on standard terminal
|
||||||
fprintf( s_ld.logfile, "\t%s (build %i commit %s (%s-%s)) started at %s\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch(), Q_timestamp( TIME_FULL ) );
|
fputs( "================================================================================\n", s_ld.logfile );
|
||||||
fprintf( s_ld.logfile, "=================================================================================\n" );
|
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||||
|
fprintf( s_ld.logfile, "Game started at %s\n", Q_timestamp( TIME_FULL ));
|
||||||
|
fputs( "================================================================================\n", s_ld.logfile );
|
||||||
|
fflush( s_ld.logfile );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,12 +184,11 @@ void Sys_CloseLog( void )
|
|||||||
|
|
||||||
if( s_ld.logfile )
|
if( s_ld.logfile )
|
||||||
{
|
{
|
||||||
fprintf( s_ld.logfile, "\n");
|
fputc( '\n', s_ld.logfile );
|
||||||
fprintf( s_ld.logfile, "=================================================================================");
|
fputs( "================================================================================\n", s_ld.logfile );
|
||||||
if( host.change_game ) fprintf( s_ld.logfile, "\n\t%s (build %i) %s\n", s_ld.title, Q_buildnum(), event_name );
|
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||||
else fprintf( s_ld.logfile, "\n\t%s (build %i) %s at %s\n", s_ld.title, Q_buildnum(), event_name, Q_timestamp( TIME_FULL ));
|
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", event_name, Q_timestamp( TIME_FULL ));
|
||||||
fprintf( s_ld.logfile, "=================================================================================\n");
|
fputs( "================================================================================\n", s_ld.logfile );
|
||||||
|
|
||||||
fclose( s_ld.logfile );
|
fclose( s_ld.logfile );
|
||||||
s_ld.logfile = NULL;
|
s_ld.logfile = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ GNU General Public License for more details.
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if _MSC_VER
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef XASH_SDL
|
#ifdef XASH_SDL
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -49,7 +53,7 @@ GNU General Public License for more details.
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "whereami.h"
|
#include "whereami.h"
|
||||||
|
|
||||||
qboolean error_on_exit = false; // arg for exit();
|
int error_on_exit = 0; // arg for exit();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
@@ -68,17 +72,15 @@ Sys_DebugBreak
|
|||||||
*/
|
*/
|
||||||
void Sys_DebugBreak( void )
|
void Sys_DebugBreak( void )
|
||||||
{
|
{
|
||||||
#if XASH_LINUX || ( XASH_WIN32 && !XASH_64BIT )
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
if( Sys_DebuggerPresent() )
|
if( Sys_DebuggerPresent( ))
|
||||||
_asm { int 3 }
|
__debugbreak();
|
||||||
#elif XASH_X86
|
#else // !_MSC_VER
|
||||||
if( Sys_DebuggerPresent() )
|
if( Sys_DebuggerPresent( ))
|
||||||
asm volatile( "int $3;" );
|
{
|
||||||
#else
|
INLINE_RAISE( SIGINT );
|
||||||
if( Sys_DebuggerPresent() )
|
INLINE_NANOSLEEP1(); // sometimes signal comes with delay, let it interrupt nanosleep
|
||||||
raise( SIGINT );
|
}
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +404,7 @@ void Sys_Warn( const char *format, ... )
|
|||||||
Msg( "Sys_Warn: %s\n", text );
|
Msg( "Sys_Warn: %s\n", text );
|
||||||
|
|
||||||
if( !Host_IsDedicated() ) // dedicated server should not hang on messagebox
|
if( !Host_IsDedicated() ) // dedicated server should not hang on messagebox
|
||||||
Platform_MessageBox( "Xash Warning", text, false );
|
Platform_MessageBox( "Xash Warning", text, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -428,7 +430,7 @@ void Sys_Error( const char *error, ... )
|
|||||||
// make sure that console received last message
|
// make sure that console received last message
|
||||||
if( host.change_game ) Sys_Sleep( 200 );
|
if( host.change_game ) Sys_Sleep( 200 );
|
||||||
|
|
||||||
error_on_exit = true;
|
error_on_exit = 1;
|
||||||
host.status = HOST_ERR_FATAL;
|
host.status = HOST_ERR_FATAL;
|
||||||
va_start( argptr, error );
|
va_start( argptr, error );
|
||||||
Q_vsnprintf( text, MAX_PRINT_MSG, error, argptr );
|
Q_vsnprintf( text, MAX_PRINT_MSG, error, argptr );
|
||||||
@@ -447,7 +449,7 @@ void Sys_Error( const char *error, ... )
|
|||||||
Wcon_ShowConsole( false );
|
Wcon_ShowConsole( false );
|
||||||
#endif
|
#endif
|
||||||
Sys_Print( text );
|
Sys_Print( text );
|
||||||
Platform_MessageBox( "Xash Error", text, false );
|
Platform_MessageBox( "Xash Error", text, true );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ NOTE: never change this structure because all dll descriptions in xash code
|
|||||||
writes into struct by offsets not names
|
writes into struct by offsets not names
|
||||||
========================================================================
|
========================================================================
|
||||||
*/
|
*/
|
||||||
|
extern int error_on_exit;
|
||||||
void Sys_Sleep( int msec );
|
void Sys_Sleep( int msec );
|
||||||
double Sys_DoubleTime( void );
|
double Sys_DoubleTime( void );
|
||||||
char *Sys_GetClipboardData( void );
|
char *Sys_GetClipboardData( void );
|
||||||
|
|||||||
@@ -39,13 +39,15 @@ void Test_RunCon( void );
|
|||||||
void Test_RunVOX( void );
|
void Test_RunVOX( void );
|
||||||
void Test_RunIPFilter( void );
|
void Test_RunIPFilter( void );
|
||||||
void Test_RunGamma( void );
|
void Test_RunGamma( void );
|
||||||
|
void Test_RunDelta( void );
|
||||||
|
|
||||||
#define TEST_LIST_0 \
|
#define TEST_LIST_0 \
|
||||||
Test_RunLibCommon(); \
|
Test_RunLibCommon(); \
|
||||||
Test_RunCommon(); \
|
Test_RunCommon(); \
|
||||||
Test_RunCmd(); \
|
Test_RunCmd(); \
|
||||||
Test_RunCvar(); \
|
Test_RunCvar(); \
|
||||||
Test_RunIPFilter();
|
Test_RunIPFilter(); \
|
||||||
|
Test_RunDelta();
|
||||||
|
|
||||||
#define TEST_LIST_0_CLIENT \
|
#define TEST_LIST_0_CLIENT \
|
||||||
Test_RunCon(); \
|
Test_RunCon(); \
|
||||||
|
|||||||
@@ -93,123 +93,241 @@ static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline void Mem_PoolAdd( mempool_t *pool, size_t size )
|
||||||
|
{
|
||||||
|
pool->totalsize += size;
|
||||||
|
pool->realsize += sizeof( memheader_t ) + size + sizeof( byte );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Mem_PoolSubtract( mempool_t *pool, size_t size )
|
||||||
|
{
|
||||||
|
pool->totalsize -= size;
|
||||||
|
pool->realsize -= sizeof( memheader_t ) + size + sizeof( byte );
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Mem_PoolLinkAlloc( mempool_t *pool, memheader_t *mem )
|
||||||
|
{
|
||||||
|
mem->next = pool->chain;
|
||||||
|
if( mem->next ) mem->next->prev = mem;
|
||||||
|
pool->chain = mem;
|
||||||
|
mem->prev = NULL;
|
||||||
|
mem->pool = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Mem_PoolUnlinkAlloc( mempool_t *pool, memheader_t *mem )
|
||||||
|
{
|
||||||
|
if( mem->next ) mem->next->prev = mem->prev;
|
||||||
|
if( mem->prev ) mem->prev->next = mem->next;
|
||||||
|
else pool->chain = mem->next;
|
||||||
|
mem->pool = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Mem_InitAlloc( memheader_t *mem, size_t size, const char *filename, int fileline )
|
||||||
|
{
|
||||||
|
mem->size = size;
|
||||||
|
mem->filename = filename;
|
||||||
|
mem->fileline = fileline;
|
||||||
|
mem->sentinel1 = MEMHEADER_SENTINEL1;
|
||||||
|
*((byte *)mem + sizeof( memheader_t ) + mem->size ) = MEMHEADER_SENTINEL2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *Mem_CheckFilename( const char *filename )
|
||||||
|
{
|
||||||
|
static const char *dummy = "<corrupted>\0";
|
||||||
|
|
||||||
|
if( !COM_CheckString( filename ))
|
||||||
|
return dummy;
|
||||||
|
|
||||||
|
if( memchr( filename, '\0', MAX_OSPATH ) != NULL )
|
||||||
|
return filename;
|
||||||
|
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean Mem_CheckAllocHeader( const char *func, const memheader_t *mem, const char *filename, int fileline )
|
||||||
|
{
|
||||||
|
const char *memfilename;
|
||||||
|
|
||||||
|
if( mem->sentinel1 != MEMHEADER_SENTINEL1 )
|
||||||
|
{
|
||||||
|
memfilename = Mem_CheckFilename( mem->filename );
|
||||||
|
Sys_Error( "%s: trashed header sentinel 1 (alloc at %s:%i, check at %s:%i)\n", func, memfilename, mem->fileline, filename, fileline );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *((byte *)mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 )
|
||||||
|
{
|
||||||
|
memfilename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
|
||||||
|
Sys_Error( "%s: trashed header sentinel 2 (alloc at %s:%i, check at %s:%i)\n", func, memfilename, mem->fileline, filename, fileline );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean Mem_CheckPool( const char *func, const mempool_t *pool, const char *filename, int fileline )
|
||||||
|
{
|
||||||
|
if( pool->sentinel1 != MEMHEADER_SENTINEL1 )
|
||||||
|
{
|
||||||
|
Sys_Error( "%s: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)\n", func, pool->filename, pool->fileline, filename, fileline );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pool->sentinel2 != MEMHEADER_SENTINEL1 )
|
||||||
|
{
|
||||||
|
Sys_Error( "%s: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)\n", func, pool->filename, pool->fileline, filename, fileline );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
memheader_t *mem;
|
memheader_t *mem;
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
|
||||||
if( size <= 0 ) return NULL;
|
if( size <= 0 )
|
||||||
if( !poolptr ) Sys_Error( "Mem_Alloc: pool == NULL (alloc at %s:%i)\n", filename, fileline );
|
return NULL;
|
||||||
|
|
||||||
|
if( !poolptr )
|
||||||
|
{
|
||||||
|
Sys_Error( "%s: pool == NULL (alloc at %s:%i)\n", __func__, filename, fileline );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem = (memheader_t *)Q_malloc( sizeof( memheader_t ) + size + sizeof( byte ));
|
||||||
|
if( mem == NULL )
|
||||||
|
{
|
||||||
|
Sys_Error( "%s: out of memory (alloc size %s at %s:%i)\n", __func__, Q_memprint( size ), filename, fileline );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem_InitAlloc( mem, size, filename, fileline );
|
||||||
|
|
||||||
pool = Mem_FindPool( poolptr );
|
pool = Mem_FindPool( poolptr );
|
||||||
|
Mem_PoolAdd( pool, size );
|
||||||
|
Mem_PoolLinkAlloc( pool, mem );
|
||||||
|
|
||||||
pool->totalsize += size;
|
|
||||||
|
|
||||||
// big allocations are not clumped
|
|
||||||
pool->realsize += sizeof( memheader_t ) + size + sizeof( size_t );
|
|
||||||
mem = (memheader_t *)Q_malloc( sizeof( memheader_t ) + size + sizeof( size_t ));
|
|
||||||
if( mem == NULL ) Sys_Error( "Mem_Alloc: out of memory (alloc at %s:%i)\n", filename, fileline );
|
|
||||||
|
|
||||||
mem->filename = filename;
|
|
||||||
mem->fileline = fileline;
|
|
||||||
mem->size = size;
|
|
||||||
mem->pool = pool;
|
|
||||||
mem->sentinel1 = MEMHEADER_SENTINEL1;
|
|
||||||
// we have to use only a single byte for this sentinel, because it may not be aligned
|
|
||||||
// and some platforms can't use unaligned accesses
|
|
||||||
*((byte *)mem + sizeof( memheader_t ) + mem->size ) = MEMHEADER_SENTINEL2;
|
|
||||||
// append to head of list
|
|
||||||
mem->next = pool->chain;
|
|
||||||
mem->prev = NULL;
|
|
||||||
pool->chain = mem;
|
|
||||||
if( mem->next ) mem->next->prev = mem;
|
|
||||||
if( clear )
|
if( clear )
|
||||||
memset((void *)((byte *)mem + sizeof( memheader_t )), 0, mem->size );
|
memset((void *)((byte *)mem + sizeof( memheader_t )), 0, mem->size );
|
||||||
|
|
||||||
return (void *)((byte *)mem + sizeof( memheader_t ));
|
return (void *)((byte *)mem + sizeof( memheader_t ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *Mem_CheckFilename( const char *filename )
|
|
||||||
{
|
|
||||||
static const char *dummy = "<corrupted>\0";
|
|
||||||
const char *out = filename;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if( !COM_CheckString( out ))
|
|
||||||
return dummy;
|
|
||||||
|
|
||||||
for( i = 0; i < MAX_OSPATH; i++, out++ )
|
|
||||||
{
|
|
||||||
if( *out == '\0' )
|
|
||||||
return filename; // valid name
|
|
||||||
}
|
|
||||||
|
|
||||||
return dummy;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline )
|
static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
|
||||||
if( mem->sentinel1 != MEMHEADER_SENTINEL1 )
|
if( !Mem_CheckAllocHeader( __func__, mem, filename, fileline ))
|
||||||
{
|
return;
|
||||||
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
|
|
||||||
Sys_Error( "Mem_Free: trashed header sentinel 1 (alloc at %s:%i, free at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( *((byte *)mem + sizeof( memheader_t ) + mem->size ) != MEMHEADER_SENTINEL2 )
|
|
||||||
{
|
|
||||||
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
|
|
||||||
Sys_Error( "Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );
|
|
||||||
}
|
|
||||||
|
|
||||||
pool = mem->pool;
|
pool = mem->pool;
|
||||||
|
|
||||||
// unlink memheader from doubly linked list
|
// unlink memheader from doubly linked list
|
||||||
if(( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem ))
|
if(( mem->prev ? mem->prev->next != mem : pool->chain != mem ) || ( mem->next && mem->next->prev != mem ))
|
||||||
Sys_Error( "Mem_Free: not allocated or double freed (free at %s:%i)\n", filename, fileline );
|
{
|
||||||
|
Sys_Error( "%s: not allocated or double freed (free at %s:%i)\n", __func__, filename, fileline );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( mem->prev ) mem->prev->next = mem->next;
|
Mem_PoolSubtract( pool, mem->size );
|
||||||
else pool->chain = mem->next;
|
Mem_PoolUnlinkAlloc( pool, mem );
|
||||||
|
|
||||||
if( mem->next )
|
|
||||||
mem->next->prev = mem->prev;
|
|
||||||
|
|
||||||
// memheader has been unlinked, do the actual free now
|
|
||||||
pool->totalsize -= mem->size;
|
|
||||||
|
|
||||||
pool->realsize -= sizeof( memheader_t ) + mem->size + sizeof( size_t );
|
|
||||||
Q_free( mem );
|
Q_free( mem );
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
if( data == NULL ) Sys_Error( "Mem_Free: data == NULL (called at %s:%i)\n", filename, fileline );
|
if( data == NULL )
|
||||||
|
{
|
||||||
|
Sys_Error( "Mem_Free: data == NULL (called at %s:%i)\n", filename, fileline );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
|
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
void *_Mem_Realloc( poolhandle_t poolptr, void *data, size_t size, qboolean clear, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
memheader_t *memhdr = NULL;
|
memheader_t *mem;
|
||||||
char *nb;
|
uintptr_t oldmem;
|
||||||
|
mempool_t *pool;
|
||||||
|
size_t oldsize;
|
||||||
|
|
||||||
if( size <= 0 ) return memptr; // no need to reallocate
|
if( size <= 0 )
|
||||||
|
return data; // no need to reallocate
|
||||||
|
|
||||||
if( memptr )
|
if( !poolptr )
|
||||||
{
|
{
|
||||||
memhdr = (memheader_t *)((byte *)memptr - sizeof( memheader_t ));
|
Sys_Error( "Mem_Realloc: pool == NULL (alloc at %s:%i)\n", filename, fileline );
|
||||||
if( size == memhdr->size ) return memptr;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nb = _Mem_Alloc( poolptr, size, clear, filename, fileline );
|
if( !data )
|
||||||
|
return _Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||||
|
|
||||||
if( memptr ) // first allocate?
|
mem = (memheader_t *)((byte *)data - sizeof( memheader_t ));
|
||||||
|
|
||||||
|
if( !Mem_CheckAllocHeader( "Mem_Realloc", mem, filename, fileline ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
oldsize = mem->size;
|
||||||
|
if( size == oldsize )
|
||||||
|
return data;
|
||||||
|
|
||||||
|
#if XASH_CUSTOM_SWAP
|
||||||
{
|
{
|
||||||
size_t newsize = memhdr->size < size ? memhdr->size : size; // upper data can be trucnated!
|
char *nb = _Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||||
memcpy( nb, memptr, newsize );
|
|
||||||
_Mem_Free( memptr, filename, fileline ); // free unused old block
|
size_t newsize = mem->size < size ? mem->size : size; // upper data can be trucnated!
|
||||||
|
memcpy( nb, data, newsize );
|
||||||
|
_Mem_Free( data, filename, fileline ); // free unused old block
|
||||||
|
|
||||||
|
return nb;
|
||||||
|
}
|
||||||
|
#else // XASH_CUSTOM_SWAP
|
||||||
|
pool = Mem_FindPool( poolptr );
|
||||||
|
|
||||||
|
oldmem = (uintptr_t)mem;
|
||||||
|
mem = realloc( mem, sizeof( memheader_t ) + size + sizeof( byte ));
|
||||||
|
|
||||||
|
if( mem == NULL )
|
||||||
|
{
|
||||||
|
Sys_Error( "Mem_Realloc: out of memory (alloc size %s at %s:%i)\n", Q_memprint( size ), filename, fileline );
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)nb;
|
// Con_Printf( S_NOTE "%s: mem %s oldmem, size before %zu now %zu (alloc at %s:%i)\n",
|
||||||
|
// __func__, (uintptr_t)mem != oldmem ? "!=" : "==", oldsize, size, filename, fileline );
|
||||||
|
|
||||||
|
Mem_InitAlloc( mem, size, filename, fileline );
|
||||||
|
|
||||||
|
if( size > oldsize )
|
||||||
|
{
|
||||||
|
Mem_PoolAdd( pool, size - oldsize );
|
||||||
|
|
||||||
|
if( clear )
|
||||||
|
memset((byte *)mem + sizeof( memheader_t ) + oldsize, 0, size - oldsize );
|
||||||
|
}
|
||||||
|
else Mem_PoolSubtract( pool, oldsize - size );
|
||||||
|
|
||||||
|
// if allocation was migrated from one pool to another
|
||||||
|
// (this is possible with original Mem_Realloc func)
|
||||||
|
if( unlikely( mem->pool != pool ))
|
||||||
|
{
|
||||||
|
Mem_PoolUnlinkAlloc( mem->pool, mem );
|
||||||
|
Mem_PoolLinkAlloc( pool, mem );
|
||||||
|
}
|
||||||
|
else if( oldmem != (uintptr_t)mem ) // just relink pointers
|
||||||
|
{
|
||||||
|
if( mem->next ) mem->next->prev = mem;
|
||||||
|
if( mem->prev ) mem->prev->next = mem;
|
||||||
|
else pool->chain = mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)((byte *)mem + sizeof( memheader_t ));
|
||||||
|
#endif // XASH_CUSTOM_SWAP
|
||||||
}
|
}
|
||||||
|
|
||||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
||||||
@@ -254,8 +372,7 @@ void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline )
|
|||||||
// unlink pool from chain
|
// unlink pool from chain
|
||||||
for( chainaddress = &poolchain; *chainaddress && *chainaddress != pool; chainaddress = &((*chainaddress)->next));
|
for( chainaddress = &poolchain; *chainaddress && *chainaddress != pool; chainaddress = &((*chainaddress)->next));
|
||||||
if( *chainaddress != pool ) Sys_Error( "Mem_FreePool: pool already free (freepool at %s:%i)\n", filename, fileline );
|
if( *chainaddress != pool ) Sys_Error( "Mem_FreePool: pool already free (freepool at %s:%i)\n", filename, fileline );
|
||||||
if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_FreePool: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
|
Mem_CheckPool( "Mem_FreePool", pool, filename, fileline );
|
||||||
if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
|
|
||||||
*chainaddress = pool->next;
|
*chainaddress = pool->next;
|
||||||
|
|
||||||
// free memory owned by the pool
|
// free memory owned by the pool
|
||||||
@@ -272,8 +389,7 @@ void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline )
|
|||||||
mempool_t *pool = Mem_FindPool( poolptr );
|
mempool_t *pool = Mem_FindPool( poolptr );
|
||||||
if( !poolptr ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
|
if( !poolptr ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
|
||||||
|
|
||||||
if( pool->sentinel1 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
|
Mem_CheckPool( "Mem_FreePool", pool, filename, fileline );
|
||||||
if( pool->sentinel2 != MEMHEADER_SENTINEL1 ) Sys_Error( "Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
|
|
||||||
|
|
||||||
// free memory owned by the pool
|
// free memory owned by the pool
|
||||||
while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline );
|
while( pool->chain ) Mem_FreeBlock( pool->chain, filename, fileline );
|
||||||
@@ -288,14 +404,19 @@ static qboolean Mem_CheckAlloc( mempool_t *pool, void *data )
|
|||||||
// search only one pool
|
// search only one pool
|
||||||
target = (memheader_t *)((byte *)data - sizeof( memheader_t ));
|
target = (memheader_t *)((byte *)data - sizeof( memheader_t ));
|
||||||
for( header = pool->chain; header; header = header->next )
|
for( header = pool->chain; header; header = header->next )
|
||||||
if( header == target ) return true;
|
{
|
||||||
|
if( header == target )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// search all pools
|
// search all pools
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( pool = poolchain; pool; pool = pool->next )
|
||||||
|
{
|
||||||
if( Mem_CheckAlloc( pool, data ))
|
if( Mem_CheckAlloc( pool, data ))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -308,49 +429,24 @@ Check pointer for memory
|
|||||||
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data )
|
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data )
|
||||||
{
|
{
|
||||||
mempool_t *pool = NULL;
|
mempool_t *pool = NULL;
|
||||||
if( poolptr ) pool = Mem_FindPool( poolptr );
|
|
||||||
|
if( poolptr )
|
||||||
|
pool = Mem_FindPool( poolptr );
|
||||||
|
|
||||||
return Mem_CheckAlloc( pool, data );
|
return Mem_CheckAlloc( pool, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline )
|
|
||||||
{
|
|
||||||
memheader_t *mem;
|
|
||||||
|
|
||||||
if( data == NULL )
|
|
||||||
Sys_Error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)\n", filename, fileline );
|
|
||||||
|
|
||||||
mem = (memheader_t *)((byte *) data - sizeof(memheader_t));
|
|
||||||
|
|
||||||
if( mem->sentinel1 != MEMHEADER_SENTINEL1 )
|
|
||||||
{
|
|
||||||
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
|
|
||||||
Sys_Error( "Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( *((byte *)mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 )
|
|
||||||
{
|
|
||||||
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
|
|
||||||
Sys_Error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _Mem_Check( const char *filename, int fileline )
|
void _Mem_Check( const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
memheader_t *mem;
|
memheader_t *mem;
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( pool = poolchain; pool; pool = pool->next )
|
||||||
{
|
Mem_CheckPool( "Mem_CheckSentinels", pool, filename, fileline );
|
||||||
if( pool->sentinel1 != MEMHEADER_SENTINEL1 )
|
|
||||||
Sys_Error( "Mem_CheckSentinelsGlobal: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
|
|
||||||
if( pool->sentinel2 != MEMHEADER_SENTINEL1 )
|
|
||||||
Sys_Error( "Mem_CheckSentinelsGlobal: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)\n", pool->filename, pool->fileline, filename, fileline );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( pool = poolchain; pool; pool = pool->next )
|
||||||
for( mem = pool->chain; mem; mem = mem->next )
|
for( mem = pool->chain; mem; mem = mem->next )
|
||||||
Mem_CheckHeaderSentinels((void *)((byte *) mem + sizeof(memheader_t)), filename, fileline );
|
Mem_CheckAllocHeader( "Mem_CheckSentinels", mem, filename, fileline );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mem_PrintStats( void )
|
void Mem_PrintStats( void )
|
||||||
@@ -377,28 +473,31 @@ void Mem_PrintList( size_t minallocationsize )
|
|||||||
|
|
||||||
Mem_Check();
|
Mem_Check();
|
||||||
|
|
||||||
Con_Printf( "memory pool list:\n"" ^3size name\n");
|
Con_Printf( "memory pool list:\n" );
|
||||||
|
Con_Printf( "\t^3size\t\t\t\tname\n");
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( pool = poolchain; pool; pool = pool->next )
|
||||||
{
|
{
|
||||||
long changed_size = (long)pool->totalsize - (long)pool->lastchecksize;
|
long changed_size = (long)pool->totalsize - (long)pool->lastchecksize;
|
||||||
|
|
||||||
// poolnames can contain color symbols, make sure what color is reset
|
// poolnames can contain color symbols, make sure what color is reset
|
||||||
if( changed_size != 0 )
|
if( pool->lastchecksize != 0 && changed_size != 0 )
|
||||||
{
|
{
|
||||||
char sign = (changed_size < 0) ? '-' : '+';
|
char sign = (changed_size < 0) ? '-' : '+';
|
||||||
|
|
||||||
Con_Printf( "%10s (%10s actual) %s (^7%c%s change)\n", Q_memprint( pool->totalsize ), Q_memprint( pool->realsize ),
|
Con_Printf( "%10s (%10s real)\t%s (^7%c%s change)\n", Q_memprint( pool->totalsize ), Q_memprint( pool->realsize ),
|
||||||
pool->name, sign, Q_memprint( abs( changed_size )));
|
pool->name, sign, Q_memprint( abs( changed_size )));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Con_Printf( "%5s (%5s actual) %s\n", Q_memprint( pool->totalsize ), Q_memprint( pool->realsize ), pool->name );
|
Con_Printf( "%10s (%10s real)\t%s\n", Q_memprint( pool->totalsize ), Q_memprint( pool->realsize ), pool->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
pool->lastchecksize = pool->totalsize;
|
pool->lastchecksize = pool->totalsize;
|
||||||
for( mem = pool->chain; mem; mem = mem->next )
|
for( mem = pool->chain; mem; mem = mem->next )
|
||||||
|
{
|
||||||
if( mem->size >= minallocationsize )
|
if( mem->size >= minallocationsize )
|
||||||
Con_Printf( "%10s allocated at %s:%i\n", Q_memprint( mem->size ), mem->filename, mem->fileline );
|
Con_Printf( "%10s allocated at %s:%i\n", Q_memprint( mem->size ), mem->filename, mem->fileline );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ typedef struct ui_extendedfuncs_s {
|
|||||||
// network address funcs
|
// network address funcs
|
||||||
const char *(*pfnAdrToString)( const struct netadr_s a );
|
const char *(*pfnAdrToString)( const struct netadr_s a );
|
||||||
int (*pfnCompareAdr)( const void *a, const void *b ); // netadr_t
|
int (*pfnCompareAdr)( const void *a, const void *b ); // netadr_t
|
||||||
|
void *(*pfnGetNativeObject)( const char *name );
|
||||||
} ui_extendedfuncs_t;
|
} ui_extendedfuncs_t;
|
||||||
|
|
||||||
// deprecated export from old engine
|
// deprecated export from old engine
|
||||||
|
|||||||
@@ -2,15 +2,30 @@
|
|||||||
mobility_int.h - interface between engine and client for mobile platforms
|
mobility_int.h - interface between engine and client for mobile platforms
|
||||||
Copyright (C) 2015 a1batross
|
Copyright (C) 2015 a1batross
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This is free and unencumbered software released into the public domain.
|
||||||
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,
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
distribute this software, either in source code form or as a compiled
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
GNU General Public License for more details.
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -107,7 +107,10 @@ typedef struct server_physics_api_s
|
|||||||
int (*pfnSaveFile)( const char *filename, const void *data, int len );
|
int (*pfnSaveFile)( const char *filename, const void *data, int len );
|
||||||
const byte *(*pfnLoadImagePixels)( const char *filename, int *width, int *height );
|
const byte *(*pfnLoadImagePixels)( const char *filename, int *width, int *height );
|
||||||
|
|
||||||
const char* (*pfnGetModelName)( int modelindex );
|
const char *(*pfnGetModelName)( int modelindex );
|
||||||
|
|
||||||
|
// FWGS extension
|
||||||
|
void *(*pfnGetNativeObject)( const char *object );
|
||||||
} server_physics_api_t;
|
} server_physics_api_t;
|
||||||
|
|
||||||
// physic callbacks
|
// physic callbacks
|
||||||
|
|||||||
@@ -61,23 +61,16 @@ Android_GetNativeObject
|
|||||||
|
|
||||||
void *Android_GetNativeObject( const char *name )
|
void *Android_GetNativeObject( const char *name )
|
||||||
{
|
{
|
||||||
static const char *availObjects[] = { "JNIEnv", "ActivityClass", NULL };
|
if( !strcasecmp( name, "JNIEnv" ) )
|
||||||
void *object = NULL;
|
|
||||||
|
|
||||||
if( !name )
|
|
||||||
{
|
{
|
||||||
object = (void *)availObjects;
|
return (void *)jni.env;
|
||||||
}
|
|
||||||
else if( !strcasecmp( name, "JNIEnv" ) )
|
|
||||||
{
|
|
||||||
object = (void *)jni.env;
|
|
||||||
}
|
}
|
||||||
else if( !strcasecmp( name, "ActivityClass" ) )
|
else if( !strcasecmp( name, "ActivityClass" ) )
|
||||||
{
|
{
|
||||||
object = (void *)jni.actcls;
|
return (void *)jni.actcls;
|
||||||
}
|
}
|
||||||
|
|
||||||
return object;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static pid_t gettid( void )
|
|||||||
static void *g_hsystemd;
|
static void *g_hsystemd;
|
||||||
static int (*g_pfn_sd_notify)( int unset_environment, const char *state );
|
static int (*g_pfn_sd_notify)( int unset_environment, const char *state );
|
||||||
|
|
||||||
qboolean Sys_DebuggerPresent( void )
|
qboolean Platform_DebuggerPresent( void )
|
||||||
{
|
{
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
ssize_t num_read;
|
ssize_t num_read;
|
||||||
@@ -111,6 +111,11 @@ void Linux_Init( void )
|
|||||||
if( !Host_IsDedicated( ))
|
if( !Host_IsDedicated( ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// manpage says sd_notify will send messages to socket in NOTIFY_SOCKET
|
||||||
|
// environment variable. Check if it's available.
|
||||||
|
if( getenv( "NOTIFY_SOCKET" ) == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
if(( g_hsystemd = dlopen( "libsystemd.so.0", RTLD_LAZY )) == NULL )
|
if(( g_hsystemd = dlopen( "libsystemd.so.0", RTLD_LAZY )) == NULL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ double Platform_DoubleTime( void );
|
|||||||
void Platform_Sleep( int msec );
|
void Platform_Sleep( int msec );
|
||||||
void Platform_ShellExecute( const char *path, const char *parms );
|
void Platform_ShellExecute( const char *path, const char *parms );
|
||||||
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow );
|
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow );
|
||||||
qboolean Sys_DebuggerPresent( void ); // optional, see Sys_DebugBreak
|
|
||||||
void Platform_SetStatus( const char *status );
|
void Platform_SetStatus( const char *status );
|
||||||
|
qboolean Platform_DebuggerPresent( void );
|
||||||
|
|
||||||
// legacy iOS port functions
|
// legacy iOS port functions
|
||||||
#if TARGET_OS_IOS
|
#if TARGET_OS_IOS
|
||||||
@@ -64,6 +64,8 @@ const char *Android_LoadID( void );
|
|||||||
void Android_SaveID( const char *id );
|
void Android_SaveID( const char *id );
|
||||||
void Android_Init( void );
|
void Android_Init( void );
|
||||||
void *Android_GetNativeObject( const char *name );
|
void *Android_GetNativeObject( const char *name );
|
||||||
|
int Android_GetKeyboardHeight( void );
|
||||||
|
void Android_Shutdown( void );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
@@ -140,6 +142,15 @@ static inline void Platform_Shutdown( void )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline qboolean Sys_DebuggerPresent( void )
|
||||||
|
{
|
||||||
|
#if XASH_LINUX || XASH_WIN32
|
||||||
|
return Platform_DebuggerPresent();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
@@ -256,4 +267,89 @@ void VoiceCapture_Shutdown( void );
|
|||||||
qboolean VoiceCapture_Activate( qboolean activate );
|
qboolean VoiceCapture_Activate( qboolean activate );
|
||||||
qboolean VoiceCapture_Lock( qboolean lock );
|
qboolean VoiceCapture_Lock( qboolean lock );
|
||||||
|
|
||||||
|
// this allows to make break in current line, without entering libc code
|
||||||
|
// libc built with -fomit-frame-pointer may just eat stack frame (hello, glibc), making entering libc even more useless
|
||||||
|
// calling syscalls directly allows to make break like if it was asm("int $3") on x86
|
||||||
|
#if XASH_LINUX && XASH_X86
|
||||||
|
#define INLINE_RAISE(x) asm volatile( "int $3;" );
|
||||||
|
#define INLINE_NANOSLEEP1() // nothing!
|
||||||
|
#elif XASH_LINUX && XASH_ARM && !XASH_64BIT
|
||||||
|
#define INLINE_RAISE(x) do \
|
||||||
|
{ \
|
||||||
|
int raise_pid = getpid(); \
|
||||||
|
int raise_tid = gettid(); \
|
||||||
|
int raise_sig = (x); \
|
||||||
|
__asm__ volatile ( \
|
||||||
|
"mov r7,#268\n\t" \
|
||||||
|
"mov r0,%0\n\t" \
|
||||||
|
"mov r1,%1\n\t" \
|
||||||
|
"mov r2,%2\n\t" \
|
||||||
|
"svc 0\n\t" \
|
||||||
|
: \
|
||||||
|
: "r"(raise_pid), "r"(raise_tid), "r"(raise_sig) \
|
||||||
|
: "r0", "r1", "r2", "r7", "memory" \
|
||||||
|
); \
|
||||||
|
} while( 0 )
|
||||||
|
#define INLINE_NANOSLEEP1() do \
|
||||||
|
{ \
|
||||||
|
struct timespec ns_t1 = {1, 0}; \
|
||||||
|
struct timespec ns_t2 = {0, 0}; \
|
||||||
|
__asm__ volatile ( \
|
||||||
|
"mov r7,#162\n\t" \
|
||||||
|
"mov r0,%0\n\t" \
|
||||||
|
"mov r1,%1\n\t" \
|
||||||
|
"svc 0\n\t" \
|
||||||
|
: \
|
||||||
|
: "r"(&ns_t1), "r"(&ns_t2) \
|
||||||
|
: "r0", "r1", "r7", "memory" \
|
||||||
|
); \
|
||||||
|
} while( 0 )
|
||||||
|
#elif XASH_LINUX && XASH_ARM && XASH_64BIT
|
||||||
|
#define INLINE_RAISE(x) do \
|
||||||
|
{ \
|
||||||
|
int raise_pid = getpid(); \
|
||||||
|
int raise_tid = gettid(); \
|
||||||
|
int raise_sig = (x); \
|
||||||
|
__asm__ volatile ( \
|
||||||
|
"mov x8,#131\n\t" \
|
||||||
|
"mov x0,%0\n\t" \
|
||||||
|
"mov x1,%1\n\t" \
|
||||||
|
"mov x2,%2\n\t" \
|
||||||
|
"svc 0\n\t" \
|
||||||
|
: \
|
||||||
|
: "r"(raise_pid), "r"(raise_tid), "r"(raise_sig) \
|
||||||
|
: "x0", "x1", "x2", "x8", "memory", "cc" \
|
||||||
|
); \
|
||||||
|
} while( 0 )
|
||||||
|
#define INLINE_NANOSLEEP1() do \
|
||||||
|
{ \
|
||||||
|
struct timespec ns_t1 = {1, 0}; \
|
||||||
|
struct timespec ns_t2 = {0, 0}; \
|
||||||
|
__asm__ volatile ( \
|
||||||
|
"mov x8,#101\n\t" \
|
||||||
|
"mov x0,%0\n\t" \
|
||||||
|
"mov x1,%1\n\t" \
|
||||||
|
"svc 0\n\t" \
|
||||||
|
: \
|
||||||
|
: "r"(&ns_t1), "r"(&ns_t2) \
|
||||||
|
: "x0", "x1", "x8", "memory", "cc" \
|
||||||
|
); \
|
||||||
|
} while( 0 )
|
||||||
|
#elif XASH_LINUX
|
||||||
|
#ifdef __NR_tgkill
|
||||||
|
#define INLINE_RAISE(x) syscall( __NR_tgkill, getpid(), gettid(), x )
|
||||||
|
#else // __NR_tgkill
|
||||||
|
#define INLINE_RAISE(x) raise(x)
|
||||||
|
#endif // __NR_tgkill
|
||||||
|
#define INLINE_NANOSLEEP1() do \
|
||||||
|
{ \
|
||||||
|
struct timespec ns_t1 = {1, 0}; \
|
||||||
|
struct timespec ns_t2 = {0, 0}; \
|
||||||
|
nanosleep( &ns_t1, &ns_t2 ); \
|
||||||
|
} while( 0 )
|
||||||
|
#else // generic
|
||||||
|
#define INLINE_RAISE(x) raise(x)
|
||||||
|
#define INLINE_NANOSLEEP1() sleep(1)
|
||||||
|
#endif // generic
|
||||||
|
|
||||||
#endif // PLATFORM_H
|
#endif // PLATFORM_H
|
||||||
|
|||||||
@@ -212,8 +212,8 @@ const char *COM_NameForFunction( void *hInstance, void *function )
|
|||||||
// NOTE: dladdr() is a glibc extension
|
// NOTE: dladdr() is a glibc extension
|
||||||
{
|
{
|
||||||
Dl_info info = {0};
|
Dl_info info = {0};
|
||||||
dladdr( (void*)function, &info );
|
int ret = dladdr( (void*)function, &info );
|
||||||
if( info.dli_sname )
|
if( ret && info.dli_sname )
|
||||||
return COM_GetPlatformNeutralName( info.dli_sname );
|
return COM_GetPlatformNeutralName( info.dli_sname );
|
||||||
}
|
}
|
||||||
#ifdef XASH_ALLOW_SAVERESTORE_OFFSETS
|
#ifdef XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||||
|
|||||||
@@ -374,14 +374,8 @@ static void SDLash_ActiveEvent( int gain )
|
|||||||
{
|
{
|
||||||
host.status = HOST_FRAME;
|
host.status = HOST_FRAME;
|
||||||
if( cls.key_dest == key_game )
|
if( cls.key_dest == key_game )
|
||||||
{
|
|
||||||
IN_ActivateMouse( );
|
IN_ActivateMouse( );
|
||||||
}
|
|
||||||
|
|
||||||
if( dma.initialized && snd_mute_losefocus.value )
|
|
||||||
{
|
|
||||||
SNDDMA_Activate( true );
|
|
||||||
}
|
|
||||||
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
host.force_draw_version_time = host.realtime + FORCE_DRAW_VERSION_TIME;
|
||||||
if( vid_fullscreen.value == WINDOW_MODE_FULLSCREEN )
|
if( vid_fullscreen.value == WINDOW_MODE_FULLSCREEN )
|
||||||
VID_SetMode();
|
VID_SetMode();
|
||||||
@@ -397,14 +391,8 @@ static void SDLash_ActiveEvent( int gain )
|
|||||||
#endif
|
#endif
|
||||||
host.status = HOST_NOFOCUS;
|
host.status = HOST_NOFOCUS;
|
||||||
if( cls.key_dest == key_game )
|
if( cls.key_dest == key_game )
|
||||||
{
|
|
||||||
IN_DeactivateMouse();
|
IN_DeactivateMouse();
|
||||||
}
|
|
||||||
|
|
||||||
if( dma.initialized && snd_mute_losefocus.value )
|
|
||||||
{
|
|
||||||
SNDDMA_Activate( false );
|
|
||||||
}
|
|
||||||
host.force_draw_version_time = host.realtime + 2.0;
|
host.force_draw_version_time = host.realtime + 2.0;
|
||||||
VID_RestoreScreenResolution();
|
VID_RestoreScreenResolution();
|
||||||
}
|
}
|
||||||
@@ -654,7 +642,9 @@ static void SDLash_EventFilter( SDL_Event *event )
|
|||||||
SDLash_ActiveEvent( false );
|
SDLash_ActiveEvent( false );
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_RESIZED:
|
case SDL_WINDOWEVENT_RESIZED:
|
||||||
|
#if !XASH_MOBILE_PLATFORM
|
||||||
if( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
if( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
SDL_Window *wnd = SDL_GetWindowFromID( event->window.windowID );
|
SDL_Window *wnd = SDL_GetWindowFromID( event->window.windowID );
|
||||||
VID_SaveWindowSize( event->window.data1, event->window.data2,
|
VID_SaveWindowSize( event->window.data1, event->window.data2,
|
||||||
|
|||||||
@@ -44,6 +44,18 @@ Platform_GetMousePos
|
|||||||
void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
|
void GAME_EXPORT Platform_GetMousePos( int *x, int *y )
|
||||||
{
|
{
|
||||||
SDL_GetMouseState( x, y );
|
SDL_GetMouseState( x, y );
|
||||||
|
|
||||||
|
if( x && window_width.value && window_width.value != refState.width )
|
||||||
|
{
|
||||||
|
float factor = refState.width / window_width.value;
|
||||||
|
*x = *x * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( y && window_height.value && window_height.value != refState.height )
|
||||||
|
{
|
||||||
|
float factor = refState.height / window_height.value;
|
||||||
|
*y = *y * factor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -576,10 +576,8 @@ static qboolean VID_SetScreenResolution( int width, int height, window_mode_t wi
|
|||||||
SDL_DisplayMode got;
|
SDL_DisplayMode got;
|
||||||
Uint32 wndFlags = 0;
|
Uint32 wndFlags = 0;
|
||||||
|
|
||||||
#if !XASH_APPLE
|
|
||||||
if( vid_highdpi.value )
|
if( vid_highdpi.value )
|
||||||
SetBits( wndFlags, SDL_WINDOW_ALLOW_HIGHDPI );
|
SetBits( wndFlags, SDL_WINDOW_ALLOW_HIGHDPI );
|
||||||
#endif
|
|
||||||
|
|
||||||
SDL_SetWindowBordered( host.hWnd, SDL_FALSE );
|
SDL_SetWindowBordered( host.hWnd, SDL_FALSE );
|
||||||
|
|
||||||
@@ -744,7 +742,6 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
|||||||
if( !glw_state.software )
|
if( !glw_state.software )
|
||||||
SetBits( wndFlags, SDL_WINDOW_OPENGL );
|
SetBits( wndFlags, SDL_WINDOW_OPENGL );
|
||||||
|
|
||||||
#if !XASH_MOBILE_PLATFORM
|
|
||||||
if( window_mode == WINDOW_MODE_WINDOWED )
|
if( window_mode == WINDOW_MODE_WINDOWED )
|
||||||
{
|
{
|
||||||
SDL_Rect r;
|
SDL_Rect r;
|
||||||
@@ -787,10 +784,6 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
|||||||
SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
|
SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
|
||||||
xpos = ypos = 0;
|
xpos = ypos = 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
SetBits( wndFlags, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_INPUT_GRABBED );
|
|
||||||
xpos = ypos = SDL_WINDOWPOS_UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
|
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
|
||||||
return false;
|
return false;
|
||||||
@@ -799,14 +792,12 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
|||||||
if( FBitSet( SDL_GetWindowFlags( host.hWnd ), SDL_WINDOW_MAXIMIZED|SDL_WINDOW_FULLSCREEN_DESKTOP ) != 0 )
|
if( FBitSet( SDL_GetWindowFlags( host.hWnd ), SDL_WINDOW_MAXIMIZED|SDL_WINDOW_FULLSCREEN_DESKTOP ) != 0 )
|
||||||
SDL_GetWindowSize( host.hWnd, &width, &height );
|
SDL_GetWindowSize( host.hWnd, &width, &height );
|
||||||
|
|
||||||
#if !XASH_MOBILE_PLATFORM
|
|
||||||
if( window_mode != WINDOW_MODE_WINDOWED )
|
if( window_mode != WINDOW_MODE_WINDOWED )
|
||||||
{
|
{
|
||||||
if( !VID_SetScreenResolution( width, height, window_mode ))
|
if( !VID_SetScreenResolution( width, height, window_mode ))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else VID_RestoreScreenResolution();
|
else VID_RestoreScreenResolution();
|
||||||
#endif
|
|
||||||
|
|
||||||
VID_SetWindowIcon( host.hWnd );
|
VID_SetWindowIcon( host.hWnd );
|
||||||
SDL_ShowWindow( host.hWnd );
|
SDL_ShowWindow( host.hWnd );
|
||||||
@@ -1175,6 +1166,14 @@ qboolean VID_SetMode( void )
|
|||||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_MOBILE_PLATFORM
|
||||||
|
if( Q_strcmp( vid_fullscreen.string, DEFAULT_FULLSCREEN ))
|
||||||
|
{
|
||||||
|
Cvar_DirectSet( &vid_fullscreen, DEFAULT_FULLSCREEN );
|
||||||
|
Con_Reportf( S_ERROR "VID_SetMode: windowed unavailable on this platform\n" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if( !FBitSet( vid_fullscreen.flags, FCVAR_CHANGED ))
|
if( !FBitSet( vid_fullscreen.flags, FCVAR_CHANGED ))
|
||||||
Cvar_DirectSet( &vid_fullscreen, DEFAULT_FULLSCREEN );
|
Cvar_DirectSet( &vid_fullscreen, DEFAULT_FULLSCREEN );
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -504,12 +504,12 @@ void Wcon_CreateConsole( void )
|
|||||||
|
|
||||||
if( host.type == HOST_NORMAL )
|
if( host.type == HOST_NORMAL )
|
||||||
{
|
{
|
||||||
Q_strncpy( s_wcd.title, "Xash3D " XASH_VERSION, sizeof( s_wcd.title ));
|
Q_strncpy( s_wcd.title, XASH_ENGINE_NAME " " XASH_VERSION, sizeof( s_wcd.title ));
|
||||||
Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path ));
|
Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path ));
|
||||||
}
|
}
|
||||||
else // dedicated console
|
else // dedicated console
|
||||||
{
|
{
|
||||||
Q_strncpy( s_wcd.title, "XashDS " XASH_VERSION, sizeof( s_wcd.title ));
|
Q_strncpy( s_wcd.title, XASH_DEDICATED_SERVER_NAME " " XASH_VERSION, sizeof( s_wcd.title ));
|
||||||
Q_strncpy( s_wcd.log_path, "dedicated.log", sizeof( s_wcd.log_path ));
|
Q_strncpy( s_wcd.log_path, "dedicated.log", sizeof( s_wcd.log_path ));
|
||||||
s_wcd.log_active = true; // always make log
|
s_wcd.log_active = true; // always make log
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -356,13 +356,13 @@ static void ListMissingModules( dll_user_t *hInst )
|
|||||||
byte *data;
|
byte *data;
|
||||||
char buf[MAX_VA_STRING];
|
char buf[MAX_VA_STRING];
|
||||||
|
|
||||||
if ( !hInst ) return;
|
if( !hInst || !g_fsapi.LoadFile ) return;
|
||||||
|
|
||||||
data = FS_LoadFile( hInst->dllName, NULL, false );
|
data = g_fsapi.LoadFile( hInst->dllName, NULL, false );
|
||||||
if ( !data ) return;
|
if( !data ) return;
|
||||||
|
|
||||||
importDesc = GetImportDescriptor( hInst->dllName, data, &peHeader );
|
importDesc = GetImportDescriptor( hInst->dllName, data, &peHeader );
|
||||||
if ( !importDesc )
|
if( !importDesc )
|
||||||
{
|
{
|
||||||
Mem_Free( data );
|
Mem_Free( data );
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ void Platform_Sleep( int msec )
|
|||||||
}
|
}
|
||||||
#endif // XASH_TIMER == TIMER_WIN32
|
#endif // XASH_TIMER == TIMER_WIN32
|
||||||
|
|
||||||
qboolean Sys_DebuggerPresent( void )
|
qboolean Platform_DebuggerPresent( void )
|
||||||
{
|
{
|
||||||
return IsDebuggerPresent();
|
return IsDebuggerPresent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,10 +43,9 @@ extern int SV_UPDATE_BACKUP;
|
|||||||
#define SVF_MERGE_VISIBILITY BIT( 1 ) // we are do portal pass
|
#define SVF_MERGE_VISIBILITY BIT( 1 ) // we are do portal pass
|
||||||
|
|
||||||
// mapvalid flags
|
// mapvalid flags
|
||||||
#define MAP_IS_EXIST BIT( 0 )
|
#define MAP_IS_EXIST BIT( 0 )
|
||||||
#define MAP_HAS_SPAWNPOINT BIT( 1 )
|
#define MAP_HAS_LANDMARK BIT( 2 )
|
||||||
#define MAP_HAS_LANDMARK BIT( 2 )
|
#define MAP_INVALID_VERSION BIT( 3 )
|
||||||
#define MAP_INVALID_VERSION BIT( 3 )
|
|
||||||
|
|
||||||
#define SV_SPAWN_TIME 0.1
|
#define SV_SPAWN_TIME 0.1
|
||||||
|
|
||||||
@@ -613,11 +612,9 @@ string_t SV_MakeString( const char *szValue );
|
|||||||
const char *SV_GetString( string_t iString );
|
const char *SV_GetString( string_t iString );
|
||||||
void SV_SetStringArrayMode( qboolean dynamic );
|
void SV_SetStringArrayMode( qboolean dynamic );
|
||||||
void SV_EmptyStringPool( void );
|
void SV_EmptyStringPool( void );
|
||||||
#ifdef XASH_64BIT
|
|
||||||
void SV_PrintStr64Stats_f( void );
|
void SV_PrintStr64Stats_f( void );
|
||||||
#endif
|
|
||||||
sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, qboolean spawned_only );
|
sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, qboolean spawned_only );
|
||||||
uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name );
|
uint SV_MapIsValid( const char *filename, const char *landmark_name );
|
||||||
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
|
||||||
edict_t *SV_FindGlobalEntity( string_t classname, string_t globalname );
|
edict_t *SV_FindGlobalEntity( string_t classname, string_t globalname );
|
||||||
qboolean SV_CreateStaticEntity( struct sizebuf_s *msg, int index );
|
qboolean SV_CreateStaticEntity( struct sizebuf_s *msg, int index );
|
||||||
@@ -628,12 +625,18 @@ void SV_RestartAmbientSounds( void );
|
|||||||
void SV_RestartDecals( void );
|
void SV_RestartDecals( void );
|
||||||
void SV_RestartStaticEnts( void );
|
void SV_RestartStaticEnts( void );
|
||||||
int pfnDropToFloor( edict_t* e );
|
int pfnDropToFloor( edict_t* e );
|
||||||
edict_t *SV_EdictNum( int n );
|
|
||||||
void SV_SetModel( edict_t *ent, const char *name );
|
void SV_SetModel( edict_t *ent, const char *name );
|
||||||
int pfnDecalIndex( const char *m );
|
int pfnDecalIndex( const char *m );
|
||||||
void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
|
void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
|
||||||
qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
|
qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
|
||||||
|
|
||||||
|
static inline edict_t *SV_EdictNum( int n )
|
||||||
|
{
|
||||||
|
if( likely( n >= 0 && n < GI->max_edicts ))
|
||||||
|
return &svgame.edicts[n];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// sv_log.c
|
// sv_log.c
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -453,6 +453,11 @@ static void SV_ConnectClient( netadr_t from )
|
|||||||
|
|
||||||
// parse some info from the info strings (this can override cl_updaterate)
|
// parse some info from the info strings (this can override cl_updaterate)
|
||||||
Q_strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo ));
|
Q_strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo ));
|
||||||
|
newcl->fullupdate_next_calltime = 0;
|
||||||
|
newcl->userinfo_next_changetime = 0;
|
||||||
|
newcl->userinfo_penalty = 0;
|
||||||
|
newcl->userinfo_change_attempts = 0;
|
||||||
|
|
||||||
SV_UserinfoChanged( newcl );
|
SV_UserinfoChanged( newcl );
|
||||||
SV_ClearResourceLists( newcl );
|
SV_ClearResourceLists( newcl );
|
||||||
#if 0
|
#if 0
|
||||||
@@ -794,7 +799,7 @@ sv_client_t *SV_ClientById( int id )
|
|||||||
|
|
||||||
ASSERT( id >= 0 );
|
ASSERT( id >= 0 );
|
||||||
|
|
||||||
for( i = 0, cl = svs.clients; i < svgame.globals->maxClients; i++, cl++ )
|
for( i = 0, cl = svs.clients; cl && i < svgame.globals->maxClients; i++, cl++ )
|
||||||
{
|
{
|
||||||
if( !cl->state )
|
if( !cl->state )
|
||||||
continue;
|
continue;
|
||||||
@@ -814,7 +819,7 @@ sv_client_t *SV_ClientByName( const char *name )
|
|||||||
if( !COM_CheckString( name ))
|
if( !COM_CheckString( name ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for( i = 0, cl = svs.clients; i < svgame.globals->maxClients; i++, cl++ )
|
for( i = 0, cl = svs.clients; cl && i < svgame.globals->maxClients; i++, cl++ )
|
||||||
{
|
{
|
||||||
if( !cl->state )
|
if( !cl->state )
|
||||||
continue;
|
continue;
|
||||||
@@ -1685,7 +1690,7 @@ static qboolean SV_New_f( sv_client_t *cl )
|
|||||||
|
|
||||||
// server info string
|
// server info string
|
||||||
MSG_BeginServerCmd( &msg, svc_stufftext );
|
MSG_BeginServerCmd( &msg, svc_stufftext );
|
||||||
MSG_WriteStringf( &msg, "fullserverinfo \"%s\"\n", SV_Serverinfo( ));
|
MSG_WriteStringf( &msg, "fullserverinfo \"%s\"\n", svs.serverinfo );
|
||||||
|
|
||||||
// collect the info about all the players and send to me
|
// collect the info about all the players and send to me
|
||||||
for( i = 0, cur = svs.clients; i < svs.maxclients; i++, cur++ )
|
for( i = 0, cur = svs.clients; i < svs.maxclients; i++, cur++ )
|
||||||
@@ -3453,7 +3458,7 @@ static void SV_ParseVoiceData( sv_client_t *cl, sizebuf_t *msg )
|
|||||||
|
|
||||||
MSG_ReadBytes( msg, received, size );
|
MSG_ReadBytes( msg, received, size );
|
||||||
|
|
||||||
if( !sv_voiceenable.value )
|
if( !sv_voiceenable.value || svs.maxclients <= 1 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for( i = 0, cur = svs.clients; i < svs.maxclients; i++, cur++ )
|
for( i = 0, cur = svs.clients; i < svs.maxclients; i++, cur++ )
|
||||||
|
|||||||
@@ -169,17 +169,11 @@ SV_ValidateMap
|
|||||||
check map for typically errors
|
check map for typically errors
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
static qboolean SV_ValidateMap( const char *pMapName, qboolean check_spawn )
|
static qboolean SV_ValidateMap( const char *pMapName )
|
||||||
{
|
{
|
||||||
char *spawn_entity;
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
// determine spawn entity classname
|
flags = SV_MapIsValid( pMapName, NULL );
|
||||||
if( !check_spawn || (int)sv_maxclients.value <= 1 )
|
|
||||||
spawn_entity = GI->sp_entity;
|
|
||||||
else spawn_entity = GI->mp_entity;
|
|
||||||
|
|
||||||
flags = SV_MapIsValid( pMapName, spawn_entity, NULL );
|
|
||||||
|
|
||||||
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
||||||
{
|
{
|
||||||
@@ -193,12 +187,6 @@ static qboolean SV_ValidateMap( const char *pMapName, qboolean check_spawn )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( check_spawn && !FBitSet( flags, MAP_HAS_SPAWNPOINT ))
|
|
||||||
{
|
|
||||||
Con_Printf( S_ERROR "map %s doesn't have a valid spawnpoint\n", pMapName );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,7 +212,7 @@ static void SV_Map_f( void )
|
|||||||
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
|
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
|
||||||
COM_StripExtension( mapname );
|
COM_StripExtension( mapname );
|
||||||
|
|
||||||
if( !SV_ValidateMap( mapname, true ))
|
if( !SV_ValidateMap( mapname ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Cvar_DirectSet( &sv_hostmap, mapname );
|
Cvar_DirectSet( &sv_hostmap, mapname );
|
||||||
@@ -296,7 +284,7 @@ static void SV_MapBackground_f( void )
|
|||||||
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
|
Q_strncpy( mapname, Cmd_Argv( 1 ), sizeof( mapname ));
|
||||||
COM_StripExtension( mapname );
|
COM_StripExtension( mapname );
|
||||||
|
|
||||||
if( !SV_ValidateMap( mapname, false ))
|
if( !SV_ValidateMap( mapname ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// background map is always run as singleplayer
|
// background map is always run as singleplayer
|
||||||
@@ -346,7 +334,7 @@ static void SV_NextMap_f( void )
|
|||||||
Cvar_DirectSet( &sv_hostmap, nextmap );
|
Cvar_DirectSet( &sv_hostmap, nextmap );
|
||||||
|
|
||||||
// found current point, check for valid
|
// found current point, check for valid
|
||||||
if( SV_ValidateMap( nextmap, true ))
|
if( SV_ValidateMap( nextmap ))
|
||||||
{
|
{
|
||||||
// found and valid
|
// found and valid
|
||||||
COM_LoadLevel( nextmap, false );
|
COM_LoadLevel( nextmap, false );
|
||||||
@@ -368,13 +356,12 @@ SV_NewGame_f
|
|||||||
*/
|
*/
|
||||||
static void SV_NewGame_f( void )
|
static void SV_NewGame_f( void )
|
||||||
{
|
{
|
||||||
if( Cmd_Argc() != 1 )
|
if( Cmd_Argc() == 1 )
|
||||||
{
|
COM_NewGame( GI->startmap );
|
||||||
|
else if( Cmd_Argc() == 2 )
|
||||||
|
COM_NewGame( Cmd_Argv( 1 ));
|
||||||
|
else
|
||||||
Con_Printf( S_USAGE "newgame\n" );
|
Con_Printf( S_USAGE "newgame\n" );
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
COM_NewGame( GI->startmap );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -547,7 +534,7 @@ classic change level
|
|||||||
*/
|
*/
|
||||||
static void SV_ChangeLevel_f( void )
|
static void SV_ChangeLevel_f( void )
|
||||||
{
|
{
|
||||||
if( Cmd_Argc() != 2 )
|
if( Cmd_Argc() < 2 ) // allow extra arguments, for compatibility
|
||||||
{
|
{
|
||||||
Con_Printf( S_USAGE "changelevel <mapname>\n" );
|
Con_Printf( S_USAGE "changelevel <mapname>\n" );
|
||||||
return;
|
return;
|
||||||
@@ -565,13 +552,15 @@ smooth change level
|
|||||||
*/
|
*/
|
||||||
static void SV_ChangeLevel2_f( void )
|
static void SV_ChangeLevel2_f( void )
|
||||||
{
|
{
|
||||||
if( Cmd_Argc() != 3 )
|
if( Cmd_Argc() < 2 ) // allow extra arguments, for compatibility
|
||||||
{
|
{
|
||||||
Con_Printf( S_USAGE "changelevel2 <mapname> <landmark>\n" );
|
Con_Printf( S_USAGE "changelevel2 <mapname> [landmark]\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SV_QueueChangeLevel( Cmd_Argv( 1 ), Cmd_Argv( 2 ));
|
if( Cmd_Argc() == 2 ) // with single argument, behaves like usual changelevel
|
||||||
|
SV_QueueChangeLevel( Cmd_Argv( 1 ), NULL );
|
||||||
|
else SV_QueueChangeLevel( Cmd_Argv( 1 ), Cmd_Argv( 2 ));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -764,7 +753,7 @@ static void SV_ServerInfo_f( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Info_SetValueForStarKey( svs.serverinfo, Cmd_Argv( 1 ), Cmd_Argv( 2 ), MAX_SERVERINFO_STRING );
|
Info_SetValueForStarKey( svs.serverinfo, Cmd_Argv( 1 ), Cmd_Argv( 2 ), MAX_SERVERINFO_STRING );
|
||||||
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", SV_Serverinfo( ));
|
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", svs.serverinfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1018,6 +1007,7 @@ void SV_InitOperatorCommands( void )
|
|||||||
Cmd_AddCommand( "redirect", Rcon_Redirect_f, "force enable rcon redirection" );
|
Cmd_AddCommand( "redirect", Rcon_Redirect_f, "force enable rcon redirection" );
|
||||||
Cmd_AddCommand( "logaddress", SV_SetLogAddress_f, "sets address and port for remote logging host" );
|
Cmd_AddCommand( "logaddress", SV_SetLogAddress_f, "sets address and port for remote logging host" );
|
||||||
Cmd_AddCommand( "log", SV_ServerLog_f, "enables logging to file" );
|
Cmd_AddCommand( "log", SV_ServerLog_f, "enables logging to file" );
|
||||||
|
Cmd_AddCommand( "str64stats", SV_PrintStr64Stats_f, "print engine pool string statistics" );
|
||||||
|
|
||||||
if( host.type == HOST_NORMAL )
|
if( host.type == HOST_NORMAL )
|
||||||
{
|
{
|
||||||
@@ -1056,6 +1046,7 @@ void SV_KillOperatorCommands( void )
|
|||||||
Cmd_RemoveCommand( "redirect" );
|
Cmd_RemoveCommand( "redirect" );
|
||||||
Cmd_RemoveCommand( "logaddress" );
|
Cmd_RemoveCommand( "logaddress" );
|
||||||
Cmd_RemoveCommand( "log" );
|
Cmd_RemoveCommand( "log" );
|
||||||
|
Cmd_RemoveCommand( "str64stats" );
|
||||||
|
|
||||||
if( host.type == HOST_NORMAL )
|
if( host.type == HOST_NORMAL )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -811,17 +811,17 @@ static void SV_UpdateToReliableMessages( void )
|
|||||||
continue; // reliables go to all connected or spawned
|
continue; // reliables go to all connected or spawned
|
||||||
|
|
||||||
if( MSG_GetNumBytesWritten( &sv.reliable_datagram ) < MSG_GetNumBytesLeft( &cl->netchan.message ))
|
if( MSG_GetNumBytesWritten( &sv.reliable_datagram ) < MSG_GetNumBytesLeft( &cl->netchan.message ))
|
||||||
MSG_WriteBits( &cl->netchan.message, MSG_GetBuf( &sv.reliable_datagram ), MSG_GetNumBitsWritten( &sv.reliable_datagram ));
|
MSG_WriteBits( &cl->netchan.message, MSG_GetData( &sv.reliable_datagram ), MSG_GetNumBitsWritten( &sv.reliable_datagram ));
|
||||||
else Netchan_CreateFragments( &cl->netchan, &sv.reliable_datagram );
|
else Netchan_CreateFragments( &cl->netchan, &sv.reliable_datagram );
|
||||||
|
|
||||||
if( MSG_GetNumBytesWritten( &sv.datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
|
if( MSG_GetNumBytesWritten( &sv.datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
|
||||||
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.datagram ), MSG_GetNumBitsWritten( &sv.datagram ));
|
MSG_WriteBits( &cl->datagram, MSG_GetData( &sv.datagram ), MSG_GetNumBitsWritten( &sv.datagram ));
|
||||||
else Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name );
|
else Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name );
|
||||||
|
|
||||||
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
|
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
|
||||||
{
|
{
|
||||||
if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
|
if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
|
||||||
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.spec_datagram ), MSG_GetNumBitsWritten( &sv.spec_datagram ));
|
MSG_WriteBits( &cl->datagram, MSG_GetData( &sv.spec_datagram ), MSG_GetNumBitsWritten( &sv.spec_datagram ));
|
||||||
else Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name );
|
else Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,13 +39,6 @@ static vec3_t viewPoint[MAX_CLIENTS];
|
|||||||
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
||||||
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
||||||
|
|
||||||
edict_t *SV_EdictNum( int n )
|
|
||||||
{
|
|
||||||
if(( n >= 0 ) && ( n < GI->max_edicts ))
|
|
||||||
return svgame.edicts + n;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
||||||
{
|
{
|
||||||
@@ -150,18 +143,6 @@ char *SV_Serverinfo( void )
|
|||||||
return svs.serverinfo;
|
return svs.serverinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
SV_LocalInfo
|
|
||||||
|
|
||||||
get local infostring
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
static char *SV_Localinfo( void )
|
|
||||||
{
|
|
||||||
return svs.localinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
SV_AngleMod
|
SV_AngleMod
|
||||||
@@ -268,7 +249,6 @@ SV_SetModel
|
|||||||
void GAME_EXPORT SV_SetModel( edict_t *ent, const char *modelname )
|
void GAME_EXPORT SV_SetModel( edict_t *ent, const char *modelname )
|
||||||
{
|
{
|
||||||
char name[MAX_QPATH];
|
char name[MAX_QPATH];
|
||||||
qboolean found = false;
|
|
||||||
model_t *mod;
|
model_t *mod;
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
@@ -778,7 +758,6 @@ void SV_QueueChangeLevel( const char *level, const char *landname )
|
|||||||
{
|
{
|
||||||
uint flags, smooth = false;
|
uint flags, smooth = false;
|
||||||
char mapname[MAX_QPATH];
|
char mapname[MAX_QPATH];
|
||||||
char *spawn_entity;
|
|
||||||
|
|
||||||
// hold mapname to other place
|
// hold mapname to other place
|
||||||
Q_strncpy( mapname, level, sizeof( mapname ));
|
Q_strncpy( mapname, level, sizeof( mapname ));
|
||||||
@@ -787,12 +766,7 @@ void SV_QueueChangeLevel( const char *level, const char *landname )
|
|||||||
if( COM_CheckString( landname ))
|
if( COM_CheckString( landname ))
|
||||||
smooth = true;
|
smooth = true;
|
||||||
|
|
||||||
// determine spawn entity classname
|
flags = SV_MapIsValid( mapname, landname );
|
||||||
if( svs.maxclients == 1 )
|
|
||||||
spawn_entity = GI->sp_entity;
|
|
||||||
else spawn_entity = GI->mp_entity;
|
|
||||||
|
|
||||||
flags = SV_MapIsValid( mapname, spawn_entity, landname );
|
|
||||||
|
|
||||||
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
||||||
{
|
{
|
||||||
@@ -826,15 +800,6 @@ void SV_QueueChangeLevel( const char *level, const char *landname )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !smooth && !FBitSet( flags, MAP_HAS_SPAWNPOINT ))
|
|
||||||
{
|
|
||||||
if( sv_validate_changelevel.value )
|
|
||||||
{
|
|
||||||
Con_Printf( S_ERROR "changelevel: %s doesn't have a valid spawnpoint. Ignored.\n", mapname );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bad changelevel position invoke enables in one-way transition
|
// bad changelevel position invoke enables in one-way transition
|
||||||
if( sv.framecount < 15 )
|
if( sv.framecount < 15 )
|
||||||
{
|
{
|
||||||
@@ -864,7 +829,6 @@ void SV_WriteEntityPatch( const char *filename )
|
|||||||
int lumpofs = 0, lumplen = 0;
|
int lumpofs = 0, lumplen = 0;
|
||||||
byte buf[MAX_TOKEN]; // 1 kb
|
byte buf[MAX_TOKEN]; // 1 kb
|
||||||
string bspfilename;
|
string bspfilename;
|
||||||
dheader_t *header;
|
|
||||||
dlump_t entities;
|
dlump_t entities;
|
||||||
file_t *f;
|
file_t *f;
|
||||||
|
|
||||||
@@ -875,7 +839,6 @@ void SV_WriteEntityPatch( const char *filename )
|
|||||||
|
|
||||||
memset( buf, 0, MAX_TOKEN );
|
memset( buf, 0, MAX_TOKEN );
|
||||||
FS_Read( f, buf, MAX_TOKEN );
|
FS_Read( f, buf, MAX_TOKEN );
|
||||||
header = (dheader_t *)buf;
|
|
||||||
|
|
||||||
// check all the lumps and some other errors
|
// check all the lumps and some other errors
|
||||||
if( !Mod_TestBmodelLumps( f, bspfilename, buf, true, &entities ))
|
if( !Mod_TestBmodelLumps( f, bspfilename, buf, true, &entities ))
|
||||||
@@ -915,7 +878,6 @@ static char *SV_ReadEntityScript( const char *filename, int *flags )
|
|||||||
int lumpofs = 0, lumplen = 0;
|
int lumpofs = 0, lumplen = 0;
|
||||||
byte buf[MAX_TOKEN];
|
byte buf[MAX_TOKEN];
|
||||||
char *ents = NULL;
|
char *ents = NULL;
|
||||||
dheader_t *header;
|
|
||||||
dlump_t entities;
|
dlump_t entities;
|
||||||
size_t ft1, ft2;
|
size_t ft1, ft2;
|
||||||
file_t *f;
|
file_t *f;
|
||||||
@@ -930,7 +892,6 @@ static char *SV_ReadEntityScript( const char *filename, int *flags )
|
|||||||
SetBits( *flags, MAP_IS_EXIST );
|
SetBits( *flags, MAP_IS_EXIST );
|
||||||
memset( buf, 0, MAX_TOKEN );
|
memset( buf, 0, MAX_TOKEN );
|
||||||
FS_Read( f, buf, MAX_TOKEN );
|
FS_Read( f, buf, MAX_TOKEN );
|
||||||
header = (dheader_t *)buf;
|
|
||||||
|
|
||||||
// check all the lumps and some other errors
|
// check all the lumps and some other errors
|
||||||
if( !Mod_TestBmodelLumps( f, bspfilename, buf, (host_developer.value) ? false : true, &entities ))
|
if( !Mod_TestBmodelLumps( f, bspfilename, buf, (host_developer.value) ? false : true, &entities ))
|
||||||
@@ -977,7 +938,7 @@ SV_MapIsValid
|
|||||||
Validate map
|
Validate map
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char *landmark_name )
|
uint SV_MapIsValid( const char *filename, const char *landmark_name )
|
||||||
{
|
{
|
||||||
uint flags = 0;
|
uint flags = 0;
|
||||||
char *pfile;
|
char *pfile;
|
||||||
@@ -993,45 +954,27 @@ uint SV_MapIsValid( const char *filename, const char *spawn_entity, const char *
|
|||||||
|
|
||||||
need_landmark = COM_CheckString( landmark_name );
|
need_landmark = COM_CheckString( landmark_name );
|
||||||
|
|
||||||
// g-cont. in-dev mode we can entering on map even without "info_player_start"
|
if( !need_landmark )
|
||||||
if( !need_landmark && host_developer.value )
|
|
||||||
{
|
{
|
||||||
// not transition
|
|
||||||
Mem_Free( ents );
|
Mem_Free( ents );
|
||||||
|
|
||||||
// skip spawnpoint checks in devmode
|
return flags;
|
||||||
return (flags|MAP_HAS_SPAWNPOINT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pfile = ents;
|
pfile = ents;
|
||||||
|
|
||||||
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
||||||
{
|
{
|
||||||
if( !Q_strcmp( token, "classname" ))
|
if( !Q_strcmp( token, "targetname" ))
|
||||||
{
|
|
||||||
// check classname for spawn entity
|
|
||||||
pfile = COM_ParseFile( pfile, check_name, sizeof( check_name ));
|
|
||||||
if( !Q_strcmp( spawn_entity, check_name ))
|
|
||||||
{
|
|
||||||
SetBits( flags, MAP_HAS_SPAWNPOINT );
|
|
||||||
|
|
||||||
// we already find landmark, stop the parsing
|
|
||||||
if( need_landmark && FBitSet( flags, MAP_HAS_LANDMARK ))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( need_landmark && !Q_strcmp( token, "targetname" ))
|
|
||||||
{
|
{
|
||||||
// check targetname for landmark entity
|
// check targetname for landmark entity
|
||||||
pfile = COM_ParseFile( pfile, check_name, sizeof( check_name ));
|
pfile = COM_ParseFile( pfile, check_name, sizeof( check_name ));
|
||||||
|
|
||||||
if( !Q_strcmp( landmark_name, check_name ))
|
if( !Q_strcmp( landmark_name, check_name ))
|
||||||
{
|
{
|
||||||
|
// we found landmark, stop the parsing
|
||||||
SetBits( flags, MAP_HAS_LANDMARK );
|
SetBits( flags, MAP_HAS_LANDMARK );
|
||||||
|
break;
|
||||||
// we already find spawnpoint, stop the parsing
|
|
||||||
if( FBitSet( flags, MAP_HAS_SPAWNPOINT ))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1174,15 +1117,22 @@ static LINK_ENTITY_FUNC SV_GetEntityClass( const char *pszClassName )
|
|||||||
SV_AllocPrivateData
|
SV_AllocPrivateData
|
||||||
|
|
||||||
allocate private data for a given edict
|
allocate private data for a given edict
|
||||||
|
|
||||||
|
if customentity is NULL, no "custom" entity EXPORT is being done
|
||||||
|
if customentity is not NULL, will be set to true if "custom" export
|
||||||
|
was used to create this entity
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
static edict_t* SV_AllocPrivateData( edict_t *ent, string_t className )
|
static edict_t* SV_AllocPrivateData( edict_t *ent, string_t className, qboolean *customentity )
|
||||||
{
|
{
|
||||||
const char *pszClassName;
|
const char *pszClassName;
|
||||||
LINK_ENTITY_FUNC SpawnEdict;
|
LINK_ENTITY_FUNC SpawnEdict;
|
||||||
|
|
||||||
pszClassName = STRING( className );
|
pszClassName = STRING( className );
|
||||||
|
|
||||||
|
if( customentity )
|
||||||
|
*customentity = false;
|
||||||
|
|
||||||
if( !ent )
|
if( !ent )
|
||||||
{
|
{
|
||||||
// allocate a new one
|
// allocate a new one
|
||||||
@@ -1205,19 +1155,21 @@ static edict_t* SV_AllocPrivateData( edict_t *ent, string_t className )
|
|||||||
if( svgame.physFuncs.SV_CreateEntity && svgame.physFuncs.SV_CreateEntity( ent, pszClassName ) != -1 )
|
if( svgame.physFuncs.SV_CreateEntity && svgame.physFuncs.SV_CreateEntity( ent, pszClassName ) != -1 )
|
||||||
return ent;
|
return ent;
|
||||||
|
|
||||||
SpawnEdict = SV_GetEntityClass( "custom" );
|
if( customentity )
|
||||||
|
{
|
||||||
|
SpawnEdict = SV_GetEntityClass( "custom" );
|
||||||
|
*customentity = SpawnEdict != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if( !SpawnEdict )
|
if( !SpawnEdict )
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "No spawn function for %s\n", STRING( className ));
|
Con_Printf( S_ERROR "No spawn function for \"%s\"\n", pszClassName );
|
||||||
|
|
||||||
// free entity immediately
|
// free entity immediately
|
||||||
SV_FreeEdict( ent );
|
SV_FreeEdict( ent );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetBits( ent->v.flags, FL_CUSTOMENTITY ); // it's a custom entity but not a beam!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpawnEdict( &ent->v );
|
SpawnEdict( &ent->v );
|
||||||
@@ -1234,12 +1186,7 @@ create specified entity, alloc private data
|
|||||||
*/
|
*/
|
||||||
edict_t* SV_CreateNamedEntity( edict_t *ent, string_t className )
|
edict_t* SV_CreateNamedEntity( edict_t *ent, string_t className )
|
||||||
{
|
{
|
||||||
edict_t *ed = SV_AllocPrivateData( ent, className );
|
return SV_AllocPrivateData( ent, className, NULL );
|
||||||
|
|
||||||
// for some reasons this flag should be immediately cleared
|
|
||||||
if( ed ) ClearBits( ed->v.flags, FL_CUSTOMENTITY );
|
|
||||||
|
|
||||||
return ed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2851,8 +2798,10 @@ standard path to register game variable
|
|||||||
static void GAME_EXPORT pfnCvar_RegisterServerVariable( cvar_t *variable )
|
static void GAME_EXPORT pfnCvar_RegisterServerVariable( cvar_t *variable )
|
||||||
{
|
{
|
||||||
if( variable != NULL )
|
if( variable != NULL )
|
||||||
|
{
|
||||||
SetBits( variable->flags, FCVAR_EXTDLL );
|
SetBits( variable->flags, FCVAR_EXTDLL );
|
||||||
Cvar_RegisterVariable( (convar_t *)variable );
|
Cvar_RegisterVariable( (convar_t *)variable );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3218,7 +3167,9 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
|
|||||||
{
|
{
|
||||||
char *newString = NULL;
|
char *newString = NULL;
|
||||||
uint len;
|
uint len;
|
||||||
|
#ifdef XASH_64BIT
|
||||||
int cmp;
|
int cmp;
|
||||||
|
#endif
|
||||||
|
|
||||||
if( svgame.physFuncs.pfnAllocString != NULL )
|
if( svgame.physFuncs.pfnAllocString != NULL )
|
||||||
{
|
{
|
||||||
@@ -3281,19 +3232,21 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XASH_64BIT
|
|
||||||
void SV_PrintStr64Stats_f( void )
|
void SV_PrintStr64Stats_f( void )
|
||||||
{
|
{
|
||||||
Msg( "====================\n" );
|
#ifdef XASH_64BIT
|
||||||
Msg( "64 bit string pool statistics\n" );
|
Con_Printf( "====================\n" );
|
||||||
Msg( "====================\n" );
|
Con_Printf( "64 bit string pool statistics\n" );
|
||||||
Msg( "string array size: %lu\n", str64.maxstringarray );
|
Con_Printf( "====================\n" );
|
||||||
Msg( "total alloc %lu\n", str64.totalalloc );
|
Con_Printf( "string array size: %lu\n", str64.maxstringarray );
|
||||||
Msg( "maximum array usage: %lu\n", str64.maxalloc );
|
Con_Printf( "total alloc %lu\n", str64.totalalloc );
|
||||||
Msg( "overflow counter: %lu\n", str64.numoverflows );
|
Con_Printf( "maximum array usage: %lu\n", str64.maxalloc );
|
||||||
Msg( "dup string counter: %lu\n", str64.numdups );
|
Con_Printf( "overflow counter: %lu\n", str64.numoverflows );
|
||||||
}
|
Con_Printf( "dup string counter: %lu\n", str64.numdups );
|
||||||
|
#else
|
||||||
|
Con_Printf( "Not implemented\n" );
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
@@ -3737,9 +3690,9 @@ vaild map must contain one info_player_deatchmatch
|
|||||||
*/
|
*/
|
||||||
int GAME_EXPORT pfnIsMapValid( char *filename )
|
int GAME_EXPORT pfnIsMapValid( char *filename )
|
||||||
{
|
{
|
||||||
uint flags = SV_MapIsValid( filename, GI->mp_entity, NULL );
|
uint flags = SV_MapIsValid( filename, NULL );
|
||||||
|
|
||||||
if( FBitSet( flags, MAP_IS_EXIST ) && FBitSet( flags, MAP_HAS_SPAWNPOINT ))
|
if( FBitSet( flags, MAP_IS_EXIST ))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3873,11 +3826,11 @@ static char *GAME_EXPORT pfnGetInfoKeyBuffer( edict_t *e )
|
|||||||
|
|
||||||
// NULL passes localinfo
|
// NULL passes localinfo
|
||||||
if( !SV_IsValidEdict( e ))
|
if( !SV_IsValidEdict( e ))
|
||||||
return SV_Localinfo();
|
return svs.localinfo;
|
||||||
|
|
||||||
// world passes serverinfo
|
// world passes serverinfo
|
||||||
if( e == svgame.edicts )
|
if( e == svgame.edicts )
|
||||||
return SV_Serverinfo();
|
return svs.serverinfo;
|
||||||
|
|
||||||
// userinfo for specified edict
|
// userinfo for specified edict
|
||||||
if(( cl = SV_ClientFromEdict( e, false )) != NULL )
|
if(( cl = SV_ClientFromEdict( e, false )) != NULL )
|
||||||
@@ -4820,6 +4773,15 @@ static enginefuncs_t gEngfuncs =
|
|||||||
pfnPEntityOfEntIndexAllEntities,
|
pfnPEntityOfEntIndexAllEntities,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void SV_FreeKeyValueStrings( KeyValueData *kvd, int numpairs )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < numpairs; i++ )
|
||||||
|
{
|
||||||
|
Mem_Free( kvd[i].szKeyName );
|
||||||
|
Mem_Free( kvd[i].szValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
SV_ParseEdict
|
SV_ParseEdict
|
||||||
@@ -4831,36 +4793,34 @@ ed should be a properly initialized empty edict.
|
|||||||
static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
||||||
{
|
{
|
||||||
KeyValueData pkvd[256]; // per one entity
|
KeyValueData pkvd[256]; // per one entity
|
||||||
qboolean adjust_origin = false;
|
qboolean adjust_origin = false, customentity;
|
||||||
int i, numpairs = 0;
|
int i, numpairs = 0;
|
||||||
char *classname = NULL;
|
const char *classname = NULL;
|
||||||
char token[2048];
|
|
||||||
vec3_t origin;
|
|
||||||
|
|
||||||
// go through all the dictionary pairs
|
// go through all the dictionary pairs
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
string keyname;
|
string keyname;
|
||||||
|
char value[2048];
|
||||||
|
int len;
|
||||||
|
|
||||||
// parse key
|
// parse key
|
||||||
if(( *pfile = COM_ParseFile( *pfile, token, sizeof( token ))) == NULL )
|
if(( *pfile = COM_ParseFile( *pfile, keyname, sizeof( keyname ))) == NULL )
|
||||||
Host_Error( "ED_ParseEdict: EOF without closing brace\n" );
|
Host_Error( "ED_ParseEdict: EOF without closing brace\n" );
|
||||||
if( token[0] == '}' ) break; // end of desc
|
|
||||||
|
|
||||||
Q_strncpy( keyname, token, sizeof( keyname ));
|
if( keyname[0] == '}' )
|
||||||
|
break; // end of desc
|
||||||
|
|
||||||
// parse value
|
// parse value
|
||||||
if(( *pfile = COM_ParseFile( *pfile, token, sizeof( token ))) == NULL )
|
if(( *pfile = COM_ParseFile( *pfile, value, sizeof( value ))) == NULL )
|
||||||
Host_Error( "ED_ParseEdict: EOF without closing brace\n" );
|
Host_Error( "ED_ParseEdict: EOF without closing brace\n" );
|
||||||
|
|
||||||
if( token[0] == '}' )
|
if( value[0] == '}' )
|
||||||
Host_Error( "ED_ParseEdict: closing brace without data\n" );
|
Host_Error( "ED_ParseEdict: closing brace without data\n" );
|
||||||
|
|
||||||
// ignore attempts to set key ""
|
// ignore attempts to set empty key or value
|
||||||
if( !keyname[0] ) continue;
|
|
||||||
|
|
||||||
// "wad" field is already handled
|
// "wad" field is already handled
|
||||||
if( !Q_strcmp( keyname, "wad" ))
|
if( !keyname[0] || !value[0] || !Q_strcmp( keyname, "wad" ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// keynames with a leading underscore are used for
|
// keynames with a leading underscore are used for
|
||||||
@@ -4868,57 +4828,83 @@ static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
|||||||
if( FBitSet( world.flags, FWORLD_SKYSPHERE ) && keyname[0] == '_' )
|
if( FBitSet( world.flags, FWORLD_SKYSPHERE ) && keyname[0] == '_' )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// ignore attempts to set value ""
|
// classname must be first
|
||||||
if( !token[0] ) continue;
|
if( !Q_strcmp( keyname, "classname" ))
|
||||||
|
{
|
||||||
|
KeyValueData kvd = {
|
||||||
|
.szClassName = NULL,
|
||||||
|
.szKeyName = keyname,
|
||||||
|
.szValue = value,
|
||||||
|
.fHandled = false
|
||||||
|
};
|
||||||
|
|
||||||
|
// don't allow double classnames
|
||||||
|
if( classname != NULL )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
svgame.dllFuncs.pfnKeyValue( ent, &kvd );
|
||||||
|
|
||||||
|
// ideally, all game dlls should handle classname.
|
||||||
|
// throw an error for now, improve the logic if it causes
|
||||||
|
// compatibility issues with Xash-based games
|
||||||
|
if( !kvd.fHandled )
|
||||||
|
Host_Error( "%s: game didn't handled \"%s\" classname\n", __func__, value );
|
||||||
|
|
||||||
|
// this lets game dll override custom entity classname
|
||||||
|
// to something bogus that's exported in game dll
|
||||||
|
classname = STRING( ent->v.classname );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoldSrc removes trailing spaces
|
||||||
|
// but does this after sucking out classname
|
||||||
|
// which doesn't have similar check
|
||||||
|
for( len = Q_strlen( keyname ); len > 0 && keyname[len - 1] == ' '; len-- )
|
||||||
|
keyname[len - 1] = '\0';
|
||||||
|
|
||||||
// create keyvalue strings
|
// create keyvalue strings
|
||||||
pkvd[numpairs].szClassName = (char*)""; // unknown at this moment
|
pkvd[numpairs].szClassName = (char*)""; // unknown at this moment
|
||||||
pkvd[numpairs].szKeyName = copystring( keyname );
|
pkvd[numpairs].szKeyName = copystring( keyname );
|
||||||
pkvd[numpairs].szValue = copystring( token );
|
pkvd[numpairs].szValue = copystring( value );
|
||||||
pkvd[numpairs].fHandled = false;
|
pkvd[numpairs].fHandled = false;
|
||||||
|
numpairs++;
|
||||||
|
|
||||||
if( !Q_strcmp( keyname, "classname" ) && classname == NULL )
|
if( numpairs > ARRAYSIZE( pkvd ))
|
||||||
classname = copystring( pkvd[numpairs].szValue );
|
{
|
||||||
if( ++numpairs >= 256 ) break;
|
if( classname )
|
||||||
|
Con_Printf( S_ERROR "%s: too many keyvalue pairs for %s!\n", __func__, classname );
|
||||||
|
else Con_Printf( S_ERROR "%s: too many keyvalue pairs!\n", __func__ );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( classname == NULL )
|
if( classname == NULL )
|
||||||
{
|
{
|
||||||
// release allocated strings
|
// release allocated strings
|
||||||
for( i = 0; i < numpairs; i++ )
|
SV_FreeKeyValueStrings( pkvd, numpairs );
|
||||||
{
|
|
||||||
Mem_Free( pkvd[i].szKeyName );
|
|
||||||
Mem_Free( pkvd[i].szValue );
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ent = SV_AllocPrivateData( ent, ALLOC_STRING( classname ));
|
ent = SV_AllocPrivateData( ent, ent->v.classname, &customentity );
|
||||||
|
|
||||||
if( !SV_IsValidEdict( ent ) || FBitSet( ent->v.flags, FL_KILLME ))
|
if( !SV_IsValidEdict( ent ) || FBitSet( ent->v.flags, FL_KILLME ))
|
||||||
{
|
{
|
||||||
// release allocated strings
|
// release allocated strings
|
||||||
for( i = 0; i < numpairs; i++ )
|
SV_FreeKeyValueStrings( pkvd, numpairs );
|
||||||
{
|
|
||||||
Mem_Free( pkvd[i].szKeyName );
|
|
||||||
Mem_Free( pkvd[i].szValue );
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( FBitSet( ent->v.flags, FL_CUSTOMENTITY ))
|
if( customentity )
|
||||||
{
|
{
|
||||||
if( numpairs < 256 )
|
KeyValueData kvd = {
|
||||||
{
|
.szClassName = (char *)"custom",
|
||||||
pkvd[numpairs].szClassName = (char*)"custom";
|
.szKeyName = (char *)"customclass",
|
||||||
pkvd[numpairs].szKeyName = (char*)"customclass";
|
.szValue = (char *)classname,
|
||||||
pkvd[numpairs].szValue = classname;
|
.fHandled = false
|
||||||
pkvd[numpairs].fHandled = false;
|
};
|
||||||
numpairs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear it now - no longer used
|
svgame.dllFuncs.pfnKeyValue( ent, &kvd );
|
||||||
ClearBits( ent->v.flags, FL_CUSTOMENTITY );
|
// no fHandled check, GoldSrc behavior
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HACKS_RELATED_HLMODS
|
#ifdef HACKS_RELATED_HLMODS
|
||||||
@@ -4932,6 +4918,14 @@ static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
|||||||
|
|
||||||
for( i = 0; i < numpairs; i++ )
|
for( i = 0; i < numpairs; i++ )
|
||||||
{
|
{
|
||||||
|
char *keyname, *value;
|
||||||
|
char temp[MAX_VA_STRING];
|
||||||
|
|
||||||
|
#if 0 // this is stupid bug in GoldSrc, disable
|
||||||
|
if( !Q_strcmp( pkvd[i].szValue, classname ))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
if( !Q_strcmp( pkvd[i].szKeyName, "angle" ))
|
if( !Q_strcmp( pkvd[i].szKeyName, "angle" ))
|
||||||
{
|
{
|
||||||
float flYawAngle = Q_atof( pkvd[i].szValue );
|
float flYawAngle = Q_atof( pkvd[i].szValue );
|
||||||
@@ -4942,8 +4936,6 @@ static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
|||||||
|
|
||||||
if( flYawAngle >= 0.0f )
|
if( flYawAngle >= 0.0f )
|
||||||
{
|
{
|
||||||
char temp[MAX_VA_STRING];
|
|
||||||
|
|
||||||
Q_snprintf( temp, sizeof( temp ), "%g %g %g", ent->v.angles[0], flYawAngle, ent->v.angles[2] );
|
Q_snprintf( temp, sizeof( temp ), "%g %g %g", ent->v.angles[0], flYawAngle, ent->v.angles[2] );
|
||||||
pkvd[i].szValue = copystring( temp );
|
pkvd[i].szValue = copystring( temp );
|
||||||
}
|
}
|
||||||
@@ -4954,11 +4946,10 @@ static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
|||||||
else pkvd[i].szValue = copystring( "0 0 0" ); // technically an error
|
else pkvd[i].szValue = copystring( "0 0 0" ); // technically an error
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HACKS_RELATED_HLMODS
|
|
||||||
if( adjust_origin && !Q_strcmp( pkvd[i].szKeyName, "origin" ))
|
if( adjust_origin && !Q_strcmp( pkvd[i].szKeyName, "origin" ))
|
||||||
{
|
{
|
||||||
char temp[MAX_VA_STRING];
|
char *pstart = pkvd[i].szValue;
|
||||||
char *pstart = pkvd[i].szValue;
|
vec3_t origin;
|
||||||
|
|
||||||
COM_ParseVector( &pstart, origin, 3 );
|
COM_ParseVector( &pstart, origin, 3 );
|
||||||
Mem_Free( pkvd[i].szValue ); // release old value, so we don't need these
|
Mem_Free( pkvd[i].szValue ); // release old value, so we don't need these
|
||||||
@@ -4966,24 +4957,18 @@ static qboolean SV_ParseEdict( char **pfile, edict_t *ent )
|
|||||||
Q_snprintf( temp, sizeof( temp ), "%g %g %g", origin[0], origin[1], origin[2] - 16.0f );
|
Q_snprintf( temp, sizeof( temp ), "%g %g %g", origin[0], origin[1], origin[2] - 16.0f );
|
||||||
pkvd[i].szValue = copystring( temp );
|
pkvd[i].szValue = copystring( temp );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if( !pkvd[i].fHandled )
|
|
||||||
{
|
|
||||||
pkvd[i].szClassName = classname;
|
|
||||||
svgame.dllFuncs.pfnKeyValue( ent, &pkvd[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// no reason to keep this data
|
// do not leak memory if game overwritten these pointers
|
||||||
if( Mem_IsAllocatedExt( host.mempool, pkvd[i].szKeyName ))
|
keyname = pkvd[i].szKeyName;
|
||||||
Mem_Free( pkvd[i].szKeyName );
|
value = pkvd[i].szValue;
|
||||||
|
|
||||||
if( Mem_IsAllocatedExt( host.mempool, pkvd[i].szValue ))
|
pkvd[i].szClassName = (char *)classname;
|
||||||
Mem_Free( pkvd[i].szValue );
|
svgame.dllFuncs.pfnKeyValue( ent, &pkvd[i] );
|
||||||
|
|
||||||
|
Mem_Free( keyname );
|
||||||
|
Mem_Free( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Mem_IsAllocatedExt( host.mempool, classname ))
|
|
||||||
Mem_Free( classname );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5102,8 +5087,6 @@ void SV_UnloadProgs( void )
|
|||||||
/// SV_UnloadProgs will be disabled
|
/// SV_UnloadProgs will be disabled
|
||||||
//Mod_ClearUserData ();
|
//Mod_ClearUserData ();
|
||||||
|
|
||||||
SV_FreeStringPool();
|
|
||||||
|
|
||||||
if( svgame.dllFuncs2.pfnGameShutdown != NULL )
|
if( svgame.dllFuncs2.pfnGameShutdown != NULL )
|
||||||
svgame.dllFuncs2.pfnGameShutdown ();
|
svgame.dllFuncs2.pfnGameShutdown ();
|
||||||
|
|
||||||
@@ -5124,6 +5107,8 @@ void SV_UnloadProgs( void )
|
|||||||
Cvar_Unlink( FCVAR_EXTDLL );
|
Cvar_Unlink( FCVAR_EXTDLL );
|
||||||
Cmd_Unlink( CMD_SERVERDLL );
|
Cmd_Unlink( CMD_SERVERDLL );
|
||||||
|
|
||||||
|
SV_FreeStringPool();
|
||||||
|
|
||||||
Mod_ResetStudioAPI ();
|
Mod_ResetStudioAPI ();
|
||||||
|
|
||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
|
|||||||
@@ -469,7 +469,8 @@ static void SV_CreateBaseline( void )
|
|||||||
int delta_type;
|
int delta_type;
|
||||||
int entnum;
|
int entnum;
|
||||||
|
|
||||||
SV_WriteVoiceCodec( &sv.signon );
|
if( svs.maxclients > 1 )
|
||||||
|
SV_WriteVoiceCodec( &sv.signon );
|
||||||
|
|
||||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||||
playermodel = SV_ModelIndex( DEFAULT_PLAYER_PATH_QUAKE );
|
playermodel = SV_ModelIndex( DEFAULT_PLAYER_PATH_QUAKE );
|
||||||
@@ -672,14 +673,6 @@ void SV_ActivateServer( int runPhysics )
|
|||||||
|
|
||||||
if( sv.ignored_world_decals )
|
if( sv.ignored_world_decals )
|
||||||
Con_Printf( S_WARN "%i static decals was rejected due buffer overflow\n", sv.ignored_world_decals );
|
Con_Printf( S_WARN "%i static decals was rejected due buffer overflow\n", sv.ignored_world_decals );
|
||||||
|
|
||||||
if( svs.maxclients > 1 )
|
|
||||||
{
|
|
||||||
const char *cycle = Cvar_VariableString( "mapchangecfgfile" );
|
|
||||||
|
|
||||||
if( COM_CheckString( cycle ))
|
|
||||||
Cbuf_AddTextf( "exec %s\n", cycle );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -692,6 +685,13 @@ deactivate server, free edicts, strings etc
|
|||||||
void SV_DeactivateServer( void )
|
void SV_DeactivateServer( void )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
const char *cycle = Cvar_VariableString( "disconcfgfile" );
|
||||||
|
|
||||||
|
if( COM_CheckString( cycle ))
|
||||||
|
Cbuf_AddTextf( "exec %s\n", cycle );
|
||||||
|
|
||||||
|
if( COM_CheckStringEmpty( sv.name ))
|
||||||
|
Cbuf_AddTextf( "exec maps/%s_unload.cfg\n", sv.name );
|
||||||
|
|
||||||
if( !svs.initialized || sv.state == ss_dead )
|
if( !svs.initialized || sv.state == ss_dead )
|
||||||
return;
|
return;
|
||||||
@@ -922,11 +922,11 @@ static void SV_GenerateTestPacket( void )
|
|||||||
// testpacket already generated once, exit
|
// testpacket already generated once, exit
|
||||||
// testpacket and lookup table takes ~300k of memory
|
// testpacket and lookup table takes ~300k of memory
|
||||||
// disable for low memory mode
|
// disable for low memory mode
|
||||||
if( svs.testpacket_buf || XASH_LOW_MEMORY >= 0 )
|
if( svs.testpacket_buf || XASH_LOW_MEMORY > 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// don't need in singleplayer with full client
|
// don't need in singleplayer with full client
|
||||||
if( svs.maxclients <= 1 && !Host_IsDedicated( ))
|
if( svs.maxclients <= 1 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
file = FS_Open( "gfx.wad", "rb", false );
|
file = FS_Open( "gfx.wad", "rb", false );
|
||||||
@@ -987,8 +987,9 @@ clients along with it.
|
|||||||
*/
|
*/
|
||||||
qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean background )
|
qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean background )
|
||||||
{
|
{
|
||||||
int i, current_skill;
|
int i, current_skill;
|
||||||
edict_t *ent;
|
edict_t *ent;
|
||||||
|
const char *cycle;
|
||||||
|
|
||||||
SV_SetupClients();
|
SV_SetupClients();
|
||||||
|
|
||||||
@@ -1006,6 +1007,13 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
|||||||
svs.timestart = Sys_DoubleTime();
|
svs.timestart = Sys_DoubleTime();
|
||||||
svs.spawncount++; // any partially connected client will be restarted
|
svs.spawncount++; // any partially connected client will be restarted
|
||||||
|
|
||||||
|
cycle = Cvar_VariableString( "mapchangecfgfile" );
|
||||||
|
|
||||||
|
if( COM_CheckString( cycle ))
|
||||||
|
Cbuf_AddTextf( "exec %s\n", cycle );
|
||||||
|
|
||||||
|
Cbuf_AddTextf( "exec maps/%s_load.cfg\n", mapname );
|
||||||
|
|
||||||
// let's not have any servers with no name
|
// let's not have any servers with no name
|
||||||
if( !COM_CheckString( hostname.string ))
|
if( !COM_CheckString( hostname.string ))
|
||||||
Cvar_Set( "hostname", svgame.dllFuncs.pfnGetGameDescription ? svgame.dllFuncs.pfnGetGameDescription() : FS_Title( ));
|
Cvar_Set( "hostname", svgame.dllFuncs.pfnGetGameDescription ? svgame.dllFuncs.pfnGetGameDescription() : FS_Title( ));
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ void Log_Open( void )
|
|||||||
|
|
||||||
if( fp ) svs.log.file = fp;
|
if( fp ) svs.log.file = fp;
|
||||||
Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/" XASH_VERSION "/%d\")\n",
|
Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/" XASH_VERSION "/%d\")\n",
|
||||||
szTestFile, Info_ValueForKey( SV_Serverinfo(), "*gamedir" ), PROTOCOL_VERSION, Q_buildnum() );
|
szTestFile, Info_ValueForKey( svs.serverinfo, "*gamedir" ), PROTOCOL_VERSION, Q_buildnum() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log_Close( void )
|
void Log_Close( void )
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ CVAR_DEFINE_AUTO( skill, "1", 0, "skill level in singleplayer game" );
|
|||||||
CVAR_DEFINE_AUTO( temp1, "0", 0, "temporary cvar that used by some mods" );
|
CVAR_DEFINE_AUTO( temp1, "0", 0, "temporary cvar that used by some mods" );
|
||||||
CVAR_DEFINE_AUTO( listipcfgfile, "listip.cfg", 0, "name of listip.cfg file" );
|
CVAR_DEFINE_AUTO( listipcfgfile, "listip.cfg", 0, "name of listip.cfg file" );
|
||||||
CVAR_DEFINE_AUTO( mapchangecfgfile, "", 0, "name of map change configuration file" );
|
CVAR_DEFINE_AUTO( mapchangecfgfile, "", 0, "name of map change configuration file" );
|
||||||
|
CVAR_DEFINE_AUTO( disconcfgfile, "", 0, "name of disconnect configuration file" );
|
||||||
|
CVAR_DEFINE_AUTO( _sv_override_scientist_mdl, "", 0, "override default scientist model name (specially for HL25 Uplink maps)" );
|
||||||
|
|
||||||
// physic-related variables
|
// physic-related variables
|
||||||
CVAR_DEFINE_AUTO( sv_gravity, "800", FCVAR_MOVEVARS, "world gravity value" );
|
CVAR_DEFINE_AUTO( sv_gravity, "800", FCVAR_MOVEVARS, "world gravity value" );
|
||||||
@@ -948,6 +950,8 @@ void SV_Init( void )
|
|||||||
Cvar_RegisterVariable( &bannedcfgfile );
|
Cvar_RegisterVariable( &bannedcfgfile );
|
||||||
Cvar_RegisterVariable( &listipcfgfile );
|
Cvar_RegisterVariable( &listipcfgfile );
|
||||||
Cvar_RegisterVariable( &mapchangecfgfile );
|
Cvar_RegisterVariable( &mapchangecfgfile );
|
||||||
|
Cvar_RegisterVariable( &disconcfgfile );
|
||||||
|
Cvar_RegisterVariable( &_sv_override_scientist_mdl );
|
||||||
|
|
||||||
Cvar_RegisterVariable( &sv_voiceenable );
|
Cvar_RegisterVariable( &sv_voiceenable );
|
||||||
Cvar_RegisterVariable( &sv_voicequality );
|
Cvar_RegisterVariable( &sv_voicequality );
|
||||||
|
|||||||
@@ -150,21 +150,9 @@ void SV_WaterMove( edict_t *ent )
|
|||||||
if( flags & FL_INWATER )
|
if( flags & FL_INWATER )
|
||||||
{
|
{
|
||||||
// leave the water.
|
// leave the water.
|
||||||
switch( COM_RandomLong( 0, 3 ))
|
const char *snd = SoundList_GetRandom( EntityWaterExit );
|
||||||
{
|
if( snd )
|
||||||
case 0:
|
SV_StartSound( ent, CHAN_BODY, snd, 1.0f, ATTN_NORM, 0, 100 );
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade1.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade2.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade3.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade4.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent->v.flags = flags & ~FL_INWATER;
|
ent->v.flags = flags & ~FL_INWATER;
|
||||||
}
|
}
|
||||||
@@ -197,21 +185,9 @@ void SV_WaterMove( edict_t *ent )
|
|||||||
if( watertype == CONTENTS_WATER )
|
if( watertype == CONTENTS_WATER )
|
||||||
{
|
{
|
||||||
// entering the water
|
// entering the water
|
||||||
switch( COM_RandomLong( 0, 3 ))
|
const char *snd = SoundList_GetRandom( EntityWaterEnter );
|
||||||
{
|
if( snd )
|
||||||
case 0:
|
SV_StartSound( ent, CHAN_BODY, snd, 1.0f, ATTN_NORM, 0, 100 );
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade1.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade2.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade3.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
SV_StartSound( ent, CHAN_BODY, "player/pl_wade4.wav", 1.0f, ATTN_NORM, 0, 100 );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ent->v.flags = flags | FL_INWATER;
|
ent->v.flags = flags | FL_INWATER;
|
||||||
|
|||||||
@@ -1384,7 +1384,9 @@ static void SV_CheckWaterTransition( edict_t *ent )
|
|||||||
if( ent->v.watertype == CONTENTS_EMPTY )
|
if( ent->v.watertype == CONTENTS_EMPTY )
|
||||||
{
|
{
|
||||||
// just crossed into water
|
// just crossed into water
|
||||||
SV_StartSound( ent, CHAN_AUTO, "player/pl_wade1.wav", 1.0f, ATTN_NORM, 0, 100 );
|
const char *snd = SoundList_GetRandom( PlayerWaterEnter );
|
||||||
|
if( snd )
|
||||||
|
SV_StartSound( ent, CHAN_AUTO, snd, 1.0f, ATTN_NORM, 0, 100 );
|
||||||
ent->v.velocity[2] *= 0.5f;
|
ent->v.velocity[2] *= 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1418,7 +1420,9 @@ static void SV_CheckWaterTransition( edict_t *ent )
|
|||||||
if( ent->v.watertype != CONTENTS_EMPTY )
|
if( ent->v.watertype != CONTENTS_EMPTY )
|
||||||
{
|
{
|
||||||
// just crossed into water
|
// just crossed into water
|
||||||
SV_StartSound( ent, CHAN_AUTO, "player/pl_wade2.wav", 1.0f, ATTN_NORM, 0, 100 );
|
const char *snd = SoundList_GetRandom( PlayerWaterExit );
|
||||||
|
if( snd )
|
||||||
|
SV_StartSound( ent, CHAN_AUTO, snd, 1.0f, ATTN_NORM, 0, 100 );
|
||||||
}
|
}
|
||||||
ent->v.watertype = CONTENTS_EMPTY;
|
ent->v.watertype = CONTENTS_EMPTY;
|
||||||
ent->v.waterlevel = 0;
|
ent->v.waterlevel = 0;
|
||||||
@@ -2118,6 +2122,7 @@ static server_physics_api_t gPhysicsAPI =
|
|||||||
COM_SaveFile,
|
COM_SaveFile,
|
||||||
pfnLoadImagePixels,
|
pfnLoadImagePixels,
|
||||||
pfnGetModelName,
|
pfnGetModelName,
|
||||||
|
Sys_GetNativeObject
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -2110,7 +2110,7 @@ qboolean SV_LoadGame( const char *pPath )
|
|||||||
if( validload )
|
if( validload )
|
||||||
{
|
{
|
||||||
// now check for map problems
|
// now check for map problems
|
||||||
flags = SV_MapIsValid( gameHeader.mapName, GI->sp_entity, NULL );
|
flags = SV_MapIsValid( gameHeader.mapName, NULL );
|
||||||
|
|
||||||
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
||||||
{
|
{
|
||||||
@@ -2386,7 +2386,7 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
|||||||
uint flags;
|
uint flags;
|
||||||
|
|
||||||
// now check for map problems
|
// now check for map problems
|
||||||
flags = SV_MapIsValid( mapName, GI->sp_entity, NULL );
|
flags = SV_MapIsValid( mapName, NULL );
|
||||||
|
|
||||||
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ def build(bld):
|
|||||||
bld(name = 'engine_includes', export_includes = '. common common/imagelib', use = 'filesystem_includes')
|
bld(name = 'engine_includes', export_includes = '. common common/imagelib', use = 'filesystem_includes')
|
||||||
|
|
||||||
is_cxx_link = False
|
is_cxx_link = False
|
||||||
libs = [ 'engine_includes', 'public', 'dllemu' ]
|
libs = [ 'engine_includes', 'public', 'dllemu', 'werror' ]
|
||||||
|
|
||||||
# basic build: dedicated only
|
# basic build: dedicated only
|
||||||
source = bld.path.ant_glob([
|
source = bld.path.ant_glob([
|
||||||
@@ -237,7 +237,8 @@ def build(bld):
|
|||||||
app_name = 'xash3d-fwgs'
|
app_name = 'xash3d-fwgs'
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if bld.env.DISABLE_LAUNCHER:
|
# always build as shared library on Android
|
||||||
|
if bld.env.DISABLE_LAUNCHER and bld.env.DEST_OS != "android":
|
||||||
install_path = bld.env.BINDIR
|
install_path = bld.env.BINDIR
|
||||||
program = 'cxxprogram' if is_cxx_link else 'cprogram'
|
program = 'cxxprogram' if is_cxx_link else 'cprogram'
|
||||||
if bld.env.STATIC:
|
if bld.env.STATIC:
|
||||||
|
|||||||
@@ -320,6 +320,12 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
state = new CSearchState( &searchHead, search );
|
state = new CSearchState( &searchHead, search );
|
||||||
|
if( !state )
|
||||||
|
{
|
||||||
|
Mem_Free( search );
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
*handle = state->handle;
|
*handle = state->handle;
|
||||||
return state->search->filenames[0];
|
return state->search->filenames[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ static file_t *FS_OpenFile_AndroidAssets( searchpath_t *search, const char *file
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte *FS_LoadAndroidAssetsFile( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *filesize )
|
static byte *FS_LoadAndroidAssetsFile( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *filesize, void *( *pfnAlloc )( size_t ), void ( *pfnFree )( void * ))
|
||||||
{
|
{
|
||||||
byte *buf;
|
byte *buf;
|
||||||
off_t size;
|
off_t size;
|
||||||
@@ -247,18 +247,24 @@ static byte *FS_LoadAndroidAssetsFile( searchpath_t *search, const char *path, i
|
|||||||
|
|
||||||
size = AAsset_getLength( asset );
|
size = AAsset_getLength( asset );
|
||||||
|
|
||||||
buf = (byte *)Mem_Malloc( fs_mempool, size + 1 );
|
buf = (byte *)pfnAlloc( size + 1 );
|
||||||
|
if( unlikely( !buf ))
|
||||||
|
{
|
||||||
|
Con_Reportf( "%s: can't alloc %d bytes, no free memory\n", __func__, size + 1 );
|
||||||
|
AAsset_close( asset );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
buf[size] = '\0';
|
buf[size] = '\0';
|
||||||
|
|
||||||
if( AAsset_read( asset, buf, size ) < 0 )
|
if( AAsset_read( asset, buf, size ) < 0 )
|
||||||
{
|
{
|
||||||
Mem_Free( buf );
|
pfnFree( buf );
|
||||||
AAsset_close( asset );
|
AAsset_close( asset );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
AAsset_close( asset );
|
AAsset_close( asset );
|
||||||
|
|
||||||
if( filesize ) *filesize = size;
|
if( filesize ) *filesize = size;
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
@@ -270,6 +276,9 @@ searchpath_t *FS_AddAndroidAssets_Fullpath( const char *path, int flags )
|
|||||||
android_assets_t *assets = NULL;
|
android_assets_t *assets = NULL;
|
||||||
qboolean engine = true;
|
qboolean engine = true;
|
||||||
|
|
||||||
|
if( !jni.getPackageName || !jni.getCallingPackage || !jni.getAssetsList || !jni.getAssets )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if( FBitSet( flags, FS_STATIC_PATH | FS_CUSTOM_PATH ))
|
if( FBitSet( flags, FS_STATIC_PATH | FS_CUSTOM_PATH ))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -280,7 +289,7 @@ searchpath_t *FS_AddAndroidAssets_Fullpath( const char *path, int flags )
|
|||||||
|
|
||||||
if( !assets )
|
if( !assets )
|
||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "%s: unable to load Android assets \"%s\"\n", __FUNCTION__, Android_GetPackageName( engine ));
|
Con_Reportf( S_ERROR "%s: unable to load Android assets \"%s\"\n", __func__, Android_GetPackageName( engine ));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +329,9 @@ void FS_InitAndroid( void )
|
|||||||
jni.getCallingPackage = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getCallingPackage", "()Ljava/lang/String;" );
|
jni.getCallingPackage = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getCallingPackage", "()Ljava/lang/String;" );
|
||||||
jni.getAssetsList = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getAssetsList", "(ZLjava/lang/String;)[Ljava/lang/String;" );
|
jni.getAssetsList = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getAssetsList", "(ZLjava/lang/String;)[Ljava/lang/String;" );
|
||||||
jni.getAssets = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getAssets", "(Z)Landroid/content/res/AssetManager;" );
|
jni.getAssets = (*jni.env)->GetMethodID( jni.env, jni.activity_class, "getAssets", "(Z)Landroid/content/res/AssetManager;" );
|
||||||
|
|
||||||
|
if( !jni.getPackageName || !jni.getCallingPackage || !jni.getAssetsList || !jni.getAssets )
|
||||||
|
Con_Reportf( S_WARN "%s: unable to find required JNI interface to load Android assets\n", __func__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // XASH_ANDROID
|
#endif // XASH_ANDROID
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const fs_archive_t g_archives[] =
|
|||||||
static const fs_archive_t g_directory_archive =
|
static const fs_archive_t g_directory_archive =
|
||||||
{ NULL, SEARCHPATH_PLAIN, FS_AddDir_Fullpath, false };
|
{ NULL, SEARCHPATH_PLAIN, FS_AddDir_Fullpath, false };
|
||||||
|
|
||||||
#ifdef XASH_ANDROID
|
#if XASH_ANDROID
|
||||||
static const fs_archive_t g_android_archive =
|
static const fs_archive_t g_android_archive =
|
||||||
{ NULL, SEARCHPATH_ANDROID_ASSETS, FS_AddAndroidAssets_Fullpath, false };
|
{ NULL, SEARCHPATH_ANDROID_ASSETS, FS_AddAndroidAssets_Fullpath, false };
|
||||||
#endif
|
#endif
|
||||||
@@ -406,7 +406,7 @@ void FS_AddGameDirectory( const char *dir, uint flags )
|
|||||||
|
|
||||||
stringlistfreecontents( &list );
|
stringlistfreecontents( &list );
|
||||||
|
|
||||||
#ifdef XASH_ANDROID
|
#if XASH_ANDROID
|
||||||
FS_AddArchive_Fullpath( &g_android_archive, dir, flags );
|
FS_AddArchive_Fullpath( &g_android_archive, dir, flags );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -632,30 +632,23 @@ static void FS_InitGameInfo( gameinfo_t *GameInfo, const char *gamedir )
|
|||||||
memset( GameInfo, 0, sizeof( *GameInfo ));
|
memset( GameInfo, 0, sizeof( *GameInfo ));
|
||||||
|
|
||||||
// filesystem info
|
// filesystem info
|
||||||
Q_strncpy( GameInfo->gamefolder, gamedir, sizeof( GameInfo->gamefolder ));
|
|
||||||
Q_strncpy( GameInfo->basedir, "valve", sizeof( GameInfo->basedir ));
|
|
||||||
GameInfo->falldir[0] = 0;
|
|
||||||
Q_strncpy( GameInfo->startmap, "c0a0", sizeof( GameInfo->startmap ));
|
|
||||||
Q_strncpy( GameInfo->trainmap, "t0a0", sizeof( GameInfo->trainmap ));
|
|
||||||
Q_strncpy( GameInfo->title, "New Game", sizeof( GameInfo->title ));
|
Q_strncpy( GameInfo->title, "New Game", sizeof( GameInfo->title ));
|
||||||
GameInfo->version = 1.0f;
|
Q_strncpy( GameInfo->gamefolder, gamedir, sizeof( GameInfo->gamefolder ));
|
||||||
|
Q_strncpy( GameInfo->basedir, fs_basedir, sizeof( GameInfo->basedir ));
|
||||||
// .dll pathes
|
Q_strncpy( GameInfo->sp_entity, "info_player_start", sizeof( GameInfo->sp_entity ));
|
||||||
|
Q_strncpy( GameInfo->mp_entity, "info_player_deathmatch", sizeof( GameInfo->mp_entity ));
|
||||||
|
Q_strncpy( GameInfo->startmap, "newmap", sizeof( GameInfo->startmap ));
|
||||||
Q_strncpy( GameInfo->dll_path, "cl_dlls", sizeof( GameInfo->dll_path ));
|
Q_strncpy( GameInfo->dll_path, "cl_dlls", sizeof( GameInfo->dll_path ));
|
||||||
Q_strncpy( GameInfo->game_dll, "dlls/hl.dll", sizeof( GameInfo->game_dll ));
|
Q_strncpy( GameInfo->game_dll, "dlls/hl.dll", sizeof( GameInfo->game_dll ));
|
||||||
Q_strncpy( GameInfo->game_dll_linux, "dlls/hl.so", sizeof( GameInfo->game_dll_linux ));
|
Q_strncpy( GameInfo->game_dll_linux, "dlls/hl.so", sizeof( GameInfo->game_dll_linux ));
|
||||||
Q_strncpy( GameInfo->game_dll_osx, "dlls/hl.dylib", sizeof( GameInfo->game_dll_osx ));
|
Q_strncpy( GameInfo->game_dll_osx, "dlls/hl.dylib", sizeof( GameInfo->game_dll_osx ));
|
||||||
|
|
||||||
// .ico path
|
|
||||||
Q_strncpy( GameInfo->iconpath, "game.ico", sizeof( GameInfo->iconpath ));
|
Q_strncpy( GameInfo->iconpath, "game.ico", sizeof( GameInfo->iconpath ));
|
||||||
|
|
||||||
Q_strncpy( GameInfo->sp_entity, "info_player_start", sizeof( GameInfo->sp_entity ));
|
|
||||||
Q_strncpy( GameInfo->mp_entity, "info_player_deathmatch", sizeof( GameInfo->mp_entity ));
|
|
||||||
|
|
||||||
GameInfo->max_edicts = DEFAULT_MAX_EDICTS; // default value if not specified
|
GameInfo->max_edicts = DEFAULT_MAX_EDICTS; // default value if not specified
|
||||||
GameInfo->max_tents = 500;
|
GameInfo->max_tents = 500;
|
||||||
GameInfo->max_beams = 128;
|
GameInfo->max_beams = 128;
|
||||||
GameInfo->max_particles = 4096;
|
GameInfo->max_particles = 4096;
|
||||||
|
GameInfo->version = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qboolean isGameInfo )
|
static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qboolean isGameInfo )
|
||||||
@@ -1468,7 +1461,7 @@ qboolean FS_InitStdio( qboolean unused_set_to_true, const char *rootdir, const c
|
|||||||
|
|
||||||
FS_InitMemory();
|
FS_InitMemory();
|
||||||
|
|
||||||
#ifdef XASH_ANDROID
|
#if XASH_ANDROID
|
||||||
FS_InitAndroid();
|
FS_InitAndroid();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2419,6 +2412,16 @@ static void FS_Purge( file_t *file )
|
|||||||
file->ungetc = EOF;
|
file->ungetc = EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *FS_CustomAlloc( size_t size )
|
||||||
|
{
|
||||||
|
return Mem_Malloc( fs_mempool, size );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FS_CustomFree( void *data )
|
||||||
|
{
|
||||||
|
return Mem_Free( data );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
============
|
============
|
||||||
FS_LoadFile
|
FS_LoadFile
|
||||||
@@ -2427,12 +2430,16 @@ Filename are relative to the xash directory.
|
|||||||
Always appends a 0 byte.
|
Always appends a 0 byte.
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
static byte *FS_LoadFile_( const char *path, fs_offset_t *filesizeptr, const qboolean gamedironly, const qboolean custom_alloc )
|
||||||
{
|
{
|
||||||
searchpath_t *search;
|
searchpath_t *search;
|
||||||
|
fs_offset_t filesize;
|
||||||
file_t *file;
|
file_t *file;
|
||||||
|
byte *buf;
|
||||||
char netpath[MAX_SYSPATH];
|
char netpath[MAX_SYSPATH];
|
||||||
int pack_ind;
|
int pack_ind;
|
||||||
|
void *( *pfnAlloc )( size_t ) = custom_alloc ? FS_CustomAlloc : malloc;
|
||||||
|
void ( *pfnFree )( void * ) = custom_alloc ? FS_CustomFree : free;
|
||||||
|
|
||||||
// some mappers used leading '/' or '\' in path to models or sounds
|
// some mappers used leading '/' or '\' in path to models or sounds
|
||||||
if( path[0] == '/' || path[0] == '\\' )
|
if( path[0] == '/' || path[0] == '\\' )
|
||||||
@@ -2451,27 +2458,39 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
|
|||||||
|
|
||||||
// custom load file function for compressed files
|
// custom load file function for compressed files
|
||||||
if( search->pfnLoadFile )
|
if( search->pfnLoadFile )
|
||||||
return search->pfnLoadFile( search, netpath, pack_ind, filesizeptr );
|
return search->pfnLoadFile( search, netpath, pack_ind, filesizeptr, pfnAlloc, pfnFree );
|
||||||
|
|
||||||
file = search->pfnOpenFile( search, netpath, "rb", pack_ind );
|
file = search->pfnOpenFile( search, netpath, "rb", pack_ind );
|
||||||
|
|
||||||
if( file )
|
if( !file ) // TODO: indicate errors
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
filesize = file->real_length;
|
||||||
|
buf = (byte *)pfnAlloc( filesize + 1 );
|
||||||
|
|
||||||
|
if( unlikely( !buf )) // TODO: indicate errors
|
||||||
{
|
{
|
||||||
fs_offset_t filesize = file->real_length;
|
Con_Reportf( "%s: can't alloc %d bytes, no free memory\n", __func__, filesize + 1 );
|
||||||
byte *buf;
|
|
||||||
|
|
||||||
buf = (byte *)Mem_Malloc( fs_mempool, filesize + 1 );
|
|
||||||
buf[filesize] = '\0';
|
|
||||||
FS_Read( file, buf, filesize );
|
|
||||||
FS_Close( file );
|
FS_Close( file );
|
||||||
|
return NULL;
|
||||||
if( filesizeptr )
|
|
||||||
*filesizeptr = filesize;
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
buf[filesize] = '\0';
|
||||||
|
FS_Read( file, buf, filesize );
|
||||||
|
FS_Close( file );
|
||||||
|
if( filesizeptr ) *filesizeptr = filesize;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *FS_LoadFileMalloc( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||||
|
{
|
||||||
|
return FS_LoadFile_( path, filesizeptr, gamedironly, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||||
|
{
|
||||||
|
return FS_LoadFile_( path, filesizeptr, gamedironly, g_engfuncs._Mem_Alloc != _Mem_Alloc );
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean CRC32_File( dword *crcvalue, const char *filename )
|
qboolean CRC32_File( dword *crcvalue, const char *filename )
|
||||||
@@ -3020,6 +3039,7 @@ fs_api_t g_api =
|
|||||||
(void *)FS_MountArchive_Fullpath,
|
(void *)FS_MountArchive_Fullpath,
|
||||||
|
|
||||||
FS_GetFullDiskPath,
|
FS_GetFullDiskPath,
|
||||||
|
FS_LoadFileMalloc,
|
||||||
};
|
};
|
||||||
|
|
||||||
int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *engfuncs );
|
int EXPORT GetFSAPI( int version, fs_api_t *api, fs_globals_t **globals, fs_interface_t *engfuncs );
|
||||||
|
|||||||
@@ -196,6 +196,9 @@ typedef struct fs_api_t
|
|||||||
void *(*MountArchive_Fullpath)( const char *path, int flags );
|
void *(*MountArchive_Fullpath)( const char *path, int flags );
|
||||||
|
|
||||||
qboolean (*GetFullDiskPath)( char *buffer, size_t size, const char *name, qboolean gamedironly );
|
qboolean (*GetFullDiskPath)( char *buffer, size_t size, const char *name, qboolean gamedironly );
|
||||||
|
|
||||||
|
// like LoadFile but returns pointer that can be free'd using standard library function
|
||||||
|
byte *(*LoadFileMalloc)( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
||||||
} fs_api_t;
|
} fs_api_t;
|
||||||
|
|
||||||
typedef struct fs_interface_t
|
typedef struct fs_interface_t
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ typedef struct searchpath_s
|
|||||||
int (*pfnFileTime)( struct searchpath_s *search, const char *filename );
|
int (*pfnFileTime)( struct searchpath_s *search, const char *filename );
|
||||||
int (*pfnFindFile)( struct searchpath_s *search, const char *path, char *fixedname, size_t len );
|
int (*pfnFindFile)( struct searchpath_s *search, const char *path, char *fixedname, size_t len );
|
||||||
void (*pfnSearch)( struct searchpath_s *search, stringlist_t *list, const char *pattern, int caseinsensitive );
|
void (*pfnSearch)( struct searchpath_s *search, stringlist_t *list, const char *pattern, int caseinsensitive );
|
||||||
byte *(*pfnLoadFile)( struct searchpath_s *search, const char *path, int pack_ind, fs_offset_t *filesize );
|
byte *(*pfnLoadFile)( struct searchpath_s *search, const char *path, int pack_ind, fs_offset_t *filesize, void *( *pfnAlloc )( size_t ), void ( *pfnFree )( void * ));
|
||||||
} searchpath_t;
|
} searchpath_t;
|
||||||
|
|
||||||
typedef searchpath_t *(*FS_ADDARCHIVE_FULLPATH)( const char *path, int flags );
|
typedef searchpath_t *(*FS_ADDARCHIVE_FULLPATH)( const char *path, int flags );
|
||||||
@@ -181,6 +181,7 @@ qboolean FS_FileCopy( file_t *pOutput, file_t *pInput, int fileSize );
|
|||||||
|
|
||||||
// file buffer ops
|
// file buffer ops
|
||||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
||||||
|
byte *FS_LoadFileMalloc( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
|
||||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr );
|
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr );
|
||||||
qboolean FS_WriteFile( const char *filename, const void *data, fs_offset_t len );
|
qboolean FS_WriteFile( const char *filename, const void *data, fs_offset_t len );
|
||||||
|
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ searchpath_t *FS_AddPak_Fullpath( const char *pakfile, int flags )
|
|||||||
search->pfnFindFile = FS_FindFile_PAK;
|
search->pfnFindFile = FS_FindFile_PAK;
|
||||||
search->pfnSearch = FS_Search_PAK;
|
search->pfnSearch = FS_Search_PAK;
|
||||||
|
|
||||||
Con_Reportf( "Adding pakfile: %s (%i files)\n", pakfile, pak->numfiles );
|
Con_Reportf( "Adding PAK: %s (%i files)\n", pakfile, pak->numfiles );
|
||||||
|
|
||||||
return search;
|
return search;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -591,7 +591,7 @@ W_ReadLump
|
|||||||
reading lump into temp buffer
|
reading lump into temp buffer
|
||||||
===========
|
===========
|
||||||
*/
|
*/
|
||||||
static byte *W_ReadLump( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *lumpsizeptr )
|
static byte *W_ReadLump( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *lumpsizeptr, void *( *pfnAlloc )( size_t ), void ( *pfnFree )( void * ))
|
||||||
{
|
{
|
||||||
const wfile_t *wad = search->wad;
|
const wfile_t *wad = search->wad;
|
||||||
const dlumpinfo_t *lump = &wad->lumps[pack_ind];
|
const dlumpinfo_t *lump = &wad->lumps[pack_ind];
|
||||||
@@ -613,19 +613,25 @@ static byte *W_ReadLump( searchpath_t *search, const char *path, int pack_ind, f
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = (byte *)Mem_Malloc( wad->mempool, lump->disksize );
|
buf = (byte *)pfnAlloc( lump->disksize );
|
||||||
|
if( unlikely( !buf ))
|
||||||
|
{
|
||||||
|
Con_Reportf( S_ERROR "%s: can't alloc %d bytes, no free memory\n", __func__, lump->disksize );
|
||||||
|
FS_Seek( wad->handle, oldpos, SEEK_SET );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
size = FS_Read( wad->handle, buf, lump->disksize );
|
size = FS_Read( wad->handle, buf, lump->disksize );
|
||||||
|
FS_Seek( wad->handle, oldpos, SEEK_SET );
|
||||||
|
|
||||||
if( size < lump->disksize )
|
if( size < lump->disksize )
|
||||||
{
|
{
|
||||||
Con_Reportf( S_WARN "W_ReadLump: %s is probably corrupted\n", lump->name );
|
Con_Reportf( S_WARN "W_ReadLump: %s is probably corrupted\n", lump->name );
|
||||||
FS_Seek( wad->handle, oldpos, SEEK_SET );
|
pfnFree( buf );
|
||||||
Mem_Free( buf );
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( lumpsizeptr ) *lumpsizeptr = lump->disksize;
|
if( lumpsizeptr ) *lumpsizeptr = lump->disksize;
|
||||||
FS_Seek( wad->handle, oldpos, SEEK_SET );
|
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@@ -664,6 +670,6 @@ searchpath_t *FS_AddWad_Fullpath( const char *wadfile, int flags )
|
|||||||
search->pfnSearch = FS_Search_WAD;
|
search->pfnSearch = FS_Search_WAD;
|
||||||
search->pfnLoadFile = W_ReadLump;
|
search->pfnLoadFile = W_ReadLump;
|
||||||
|
|
||||||
Con_Reportf( "Adding wadfile: %s (%i files)\n", wadfile, wad->numlumps );
|
Con_Reportf( "Adding WAD: %s (%i files)\n", wadfile, wad->numlumps );
|
||||||
return search;
|
return search;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ def configure(conf):
|
|||||||
def build(bld):
|
def build(bld):
|
||||||
bld(name = 'filesystem_includes', export_includes = '.')
|
bld(name = 'filesystem_includes', export_includes = '.')
|
||||||
|
|
||||||
libs = [ 'filesystem_includes', 'sdk_includes' ]
|
libs = [ 'filesystem_includes', 'sdk_includes', 'werror' ]
|
||||||
|
|
||||||
# on PSVita do not link any libraries that are already in the main executable, but add the includes target
|
# on PSVita do not link any libraries that are already in the main executable, but add the includes target
|
||||||
if bld.env.DEST_OS != 'psvita':
|
if bld.env.DEST_OS != 'psvita':
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ FS_LoadZIPFile
|
|||||||
|
|
||||||
===========
|
===========
|
||||||
*/
|
*/
|
||||||
static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *sizeptr )
|
static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_ind, fs_offset_t *sizeptr, void *( *pfnAlloc )( size_t ), void ( *pfnFree )( void * ))
|
||||||
{
|
{
|
||||||
zipfile_t *file;
|
zipfile_t *file;
|
||||||
byte *compressed_buffer = NULL, *decompressed_buffer = NULL;
|
byte *compressed_buffer = NULL, *decompressed_buffer = NULL;
|
||||||
@@ -451,11 +451,16 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
|||||||
return NULL;
|
return NULL;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
decompressed_buffer = pfnAlloc( file->size + 1 );
|
||||||
|
if( unlikely( !decompressed_buffer ))
|
||||||
|
{
|
||||||
|
Con_Reportf( S_ERROR "%s: can't alloc %d bytes, no free memory\n", __func__, file->size + 1 );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
decompressed_buffer[file->size] = '\0';
|
||||||
|
|
||||||
if( file->flags == ZIP_COMPRESSION_NO_COMPRESSION )
|
if( file->flags == ZIP_COMPRESSION_NO_COMPRESSION )
|
||||||
{
|
{
|
||||||
decompressed_buffer = Mem_Malloc( fs_mempool, file->size + 1 );
|
|
||||||
decompressed_buffer[file->size] = '\0';
|
|
||||||
|
|
||||||
c = read( search->zip->handle, decompressed_buffer, file->size );
|
c = read( search->zip->handle, decompressed_buffer, file->size );
|
||||||
if( c != file->size )
|
if( c != file->size )
|
||||||
{
|
{
|
||||||
@@ -472,7 +477,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
|||||||
if( final_crc != file->crc32 )
|
if( final_crc != file->crc32 )
|
||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name );
|
Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name );
|
||||||
Mem_Free( decompressed_buffer );
|
pfnFree( decompressed_buffer );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif // ENABLE_CRC_CHECK
|
#endif // ENABLE_CRC_CHECK
|
||||||
@@ -485,8 +490,6 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
|||||||
else if( file->flags == ZIP_COMPRESSION_DEFLATED )
|
else if( file->flags == ZIP_COMPRESSION_DEFLATED )
|
||||||
{
|
{
|
||||||
compressed_buffer = Mem_Malloc( fs_mempool, file->compressed_size + 1 );
|
compressed_buffer = Mem_Malloc( fs_mempool, file->compressed_size + 1 );
|
||||||
decompressed_buffer = Mem_Malloc( fs_mempool, file->size + 1 );
|
|
||||||
decompressed_buffer[file->size] = '\0';
|
|
||||||
|
|
||||||
c = read( search->zip->handle, compressed_buffer, file->compressed_size );
|
c = read( search->zip->handle, compressed_buffer, file->compressed_size );
|
||||||
if( c != file->compressed_size )
|
if( c != file->compressed_size )
|
||||||
@@ -529,7 +532,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
|||||||
if( final_crc != file->crc32 )
|
if( final_crc != file->crc32 )
|
||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name );
|
Con_Reportf( S_ERROR "Zip_LoadFile: %s file crc32 mismatch\n", file->name );
|
||||||
Mem_Free( decompressed_buffer );
|
pfnFree( decompressed_buffer );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -542,7 +545,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
|||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "Zip_LoadFile: %s : error while file decompressing. Zlib return code %d.\n", file->name, zlib_result );
|
Con_Reportf( S_ERROR "Zip_LoadFile: %s : error while file decompressing. Zlib return code %d.\n", file->name, zlib_result );
|
||||||
Mem_Free( compressed_buffer );
|
Mem_Free( compressed_buffer );
|
||||||
Mem_Free( decompressed_buffer );
|
pfnFree( decompressed_buffer );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,6 +553,7 @@ static byte *FS_LoadZIPFile( searchpath_t *search, const char *path, int pack_in
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "Zip_LoadFile: %s : file compressed with unknown algorithm.\n", file->name );
|
Con_Reportf( S_ERROR "Zip_LoadFile: %s : file compressed with unknown algorithm.\n", file->name );
|
||||||
|
pfnFree( decompressed_buffer );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,7 +701,7 @@ searchpath_t *FS_AddZip_Fullpath( const char *zipfile, int flags )
|
|||||||
search->pfnSearch = FS_Search_ZIP;
|
search->pfnSearch = FS_Search_ZIP;
|
||||||
search->pfnLoadFile = FS_LoadZIPFile;
|
search->pfnLoadFile = FS_LoadZIPFile;
|
||||||
|
|
||||||
Con_Reportf( "Adding zipfile: %s (%i files)\n", zipfile, zip->numfiles );
|
Con_Reportf( "Adding ZIP: %s (%i files)\n", zipfile, zip->numfiles );
|
||||||
return search;
|
return search;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ def build(bld):
|
|||||||
bld(source = source,
|
bld(source = source,
|
||||||
target = 'xash3d', # hl.exe
|
target = 'xash3d', # hl.exe
|
||||||
features = 'c cxx cxxprogram',
|
features = 'c cxx cxxprogram',
|
||||||
use = 'sdk_includes DL USER32 SHELL32',
|
use = 'sdk_includes DL USER32 SHELL32 werror',
|
||||||
rpath = bld.env.DEFAULT_RPATH,
|
rpath = bld.env.DEFAULT_RPATH,
|
||||||
install_path = bld.env.BINDIR,
|
install_path = bld.env.BINDIR,
|
||||||
subsystem = bld.env.MSVC_SUBSYSTEM
|
subsystem = bld.env.MSVC_SUBSYSTEM
|
||||||
|
|||||||
@@ -95,8 +95,6 @@ const char *Q_PlatformStringByID( const int platform )
|
|||||||
return "win32";
|
return "win32";
|
||||||
case PLATFORM_ANDROID:
|
case PLATFORM_ANDROID:
|
||||||
return "android";
|
return "android";
|
||||||
case PLATFORM_LINUX_UNKNOWN:
|
|
||||||
return "linuxunkabi";
|
|
||||||
case PLATFORM_LINUX:
|
case PLATFORM_LINUX:
|
||||||
return "linux";
|
return "linux";
|
||||||
case PLATFORM_APPLE:
|
case PLATFORM_APPLE:
|
||||||
@@ -239,19 +237,25 @@ const char *Q_buildarch( void )
|
|||||||
=============
|
=============
|
||||||
Q_buildcommit
|
Q_buildcommit
|
||||||
|
|
||||||
Returns a short hash of current commit in VCS as string.
|
Returns a short hash of current commit in VCS as string
|
||||||
XASH_BUILD_COMMIT must be passed in quotes
|
XASH_BUILD_COMMIT must be passed in quotes
|
||||||
|
|
||||||
if XASH_BUILD_COMMIT is not defined,
|
|
||||||
Q_buildcommit will identify this build as "notset"
|
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
const char *Q_buildcommit( void )
|
const char *Q_buildcommit( void )
|
||||||
{
|
{
|
||||||
#ifdef XASH_BUILD_COMMIT
|
|
||||||
return XASH_BUILD_COMMIT;
|
return XASH_BUILD_COMMIT;
|
||||||
#else
|
}
|
||||||
return "notset";
|
|
||||||
#endif
|
/*
|
||||||
|
=============
|
||||||
|
Q_buildbranch
|
||||||
|
|
||||||
|
Returns current branch name in VCS as string
|
||||||
|
XASH_BUILD_BRANCH must be passed in quotes
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
const char *Q_buildbranch( void )
|
||||||
|
{
|
||||||
|
return XASH_BUILD_BRANCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ Then you can use another oneliner to query all variables:
|
|||||||
#undef XASH_IRIX
|
#undef XASH_IRIX
|
||||||
#undef XASH_JS
|
#undef XASH_JS
|
||||||
#undef XASH_LINUX
|
#undef XASH_LINUX
|
||||||
#undef XASH_LINUX_UNKNOWN
|
|
||||||
#undef XASH_LITTLE_ENDIAN
|
#undef XASH_LITTLE_ENDIAN
|
||||||
#undef XASH_MIPS
|
#undef XASH_MIPS
|
||||||
#undef XASH_MOBILE_PLATFORM
|
#undef XASH_MOBILE_PLATFORM
|
||||||
@@ -103,13 +102,6 @@ Then you can use another oneliner to query all variables:
|
|||||||
#if defined __linux__
|
#if defined __linux__
|
||||||
#if defined __ANDROID__
|
#if defined __ANDROID__
|
||||||
#define XASH_ANDROID 1
|
#define XASH_ANDROID 1
|
||||||
#else
|
|
||||||
#include <features.h>
|
|
||||||
// if our system libc has features.h header
|
|
||||||
// try to detect it to not confuse other libcs with built with glibc game libraries
|
|
||||||
#if !defined __GLIBC__
|
|
||||||
#define XASH_LINUX_UNKNOWN 1
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#define XASH_LINUX 1
|
#define XASH_LINUX 1
|
||||||
#elif defined __FreeBSD__
|
#elif defined __FreeBSD__
|
||||||
|
|||||||
@@ -41,14 +41,11 @@ GNU General Public License for more details.
|
|||||||
#define PLATFORM_IRIX 12
|
#define PLATFORM_IRIX 12
|
||||||
#define PLATFORM_NSWITCH 13
|
#define PLATFORM_NSWITCH 13
|
||||||
#define PLATFORM_PSVITA 14
|
#define PLATFORM_PSVITA 14
|
||||||
#define PLATFORM_LINUX_UNKNOWN 15
|
|
||||||
|
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
#define XASH_PLATFORM PLATFORM_WIN32
|
#define XASH_PLATFORM PLATFORM_WIN32
|
||||||
#elif XASH_ANDROID
|
#elif XASH_ANDROID
|
||||||
#define XASH_PLATFORM PLATFORM_ANDROID
|
#define XASH_PLATFORM PLATFORM_ANDROID
|
||||||
#elif XASH_LINUX_UNKNOWN
|
|
||||||
#define XASH_PLATFORM PLATFORM_LINUX_UNKNOWN
|
|
||||||
#elif XASH_LINUX
|
#elif XASH_LINUX
|
||||||
#define XASH_PLATFORM PLATFORM_LINUX
|
#define XASH_PLATFORM PLATFORM_LINUX
|
||||||
#elif XASH_APPLE
|
#elif XASH_APPLE
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ const char *Q_buildos( void );
|
|||||||
const char *Q_ArchitectureStringByID( const int arch, const uint abi, const int endianness, const qboolean is64 );
|
const char *Q_ArchitectureStringByID( const int arch, const uint abi, const int endianness, const qboolean is64 );
|
||||||
const char *Q_buildarch( void );
|
const char *Q_buildarch( void );
|
||||||
const char *Q_buildcommit( void );
|
const char *Q_buildcommit( void );
|
||||||
|
const char *Q_buildbranch( void );
|
||||||
|
|
||||||
//
|
//
|
||||||
// crtlib.c
|
// crtlib.c
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ static struct
|
|||||||
{
|
{
|
||||||
{ PLATFORM_WIN32, "win32" },
|
{ PLATFORM_WIN32, "win32" },
|
||||||
{ PLATFORM_ANDROID, "android" },
|
{ PLATFORM_ANDROID, "android" },
|
||||||
{ PLATFORM_LINUX_UNKNOWN, "linuxunkabi" },
|
|
||||||
{ PLATFORM_LINUX, "linux" },
|
{ PLATFORM_LINUX, "linux" },
|
||||||
{ PLATFORM_APPLE, "apple" },
|
{ PLATFORM_APPLE, "apple" },
|
||||||
{ PLATFORM_FREEBSD, "freebsd" },
|
{ PLATFORM_FREEBSD, "freebsd" },
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user