mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
Compare commits
160 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de21d845ec | ||
|
|
320f8466e6 | ||
|
|
f3208e95b2 | ||
|
|
ea34bc8652 | ||
|
|
3daf014af8 | ||
|
|
ca9d3d262a | ||
|
|
a08f5e439d | ||
|
|
8f6771dff4 | ||
|
|
cd47c6b5b3 | ||
|
|
1f4f3d7fda | ||
|
|
e81b5144b3 | ||
|
|
9ec1caed53 | ||
|
|
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
@@ -1,17 +1,15 @@
|
|||||||
# Bug-compatibility in Xash3D FWGS
|
# Bug-compatibility in Xash3D FWGS
|
||||||
|
|
||||||
Xash3D FWGS has special mode for games that rely on original engine bugs.
|
Xash3D FWGS has special mode for games that rely on original engine bugs. In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
||||||
|
|
||||||
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
|
||||||
|
|
||||||
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
|
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
|
||||||
|
|
||||||
|
When `-bugcomp` is specified without argument, it enables everything. This behavior might be changed or removed in future versions.
|
||||||
|
|
||||||
|
When `-bugcomp` is specified with argument, it interpreted as flags separated with `+`. This way it's possible to combine multiple levels of bug-compatibility.
|
||||||
|
|
||||||
## GoldSrc bug-compatibility
|
## GoldSrc bug-compatibility
|
||||||
|
|
||||||
### Emulated bugs
|
| Flag | Description | Games that require this flag |
|
||||||
|
| ------- | ----------- | ---------------------------- |
|
||||||
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
|
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
||||||
|
|
||||||
### Games and mods that require this
|
|
||||||
|
|
||||||
* Counter-Strike: Condition Zero - Deleted Scenes
|
|
||||||
|
|||||||
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
|
||||||
|
|||||||
@@ -28,11 +28,7 @@ typedef byte rgb_t[3]; // unsigned byte colorpack
|
|||||||
typedef vec_t matrix3x4[3][4];
|
typedef vec_t matrix3x4[3][4];
|
||||||
typedef vec_t matrix4x4[4][4];
|
typedef vec_t matrix4x4[4][4];
|
||||||
|
|
||||||
#if XASH_64BIT
|
|
||||||
typedef uint32_t poolhandle_t;
|
typedef uint32_t poolhandle_t;
|
||||||
#else
|
|
||||||
typedef void* poolhandle_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef true
|
#undef true
|
||||||
#undef false
|
#undef false
|
||||||
@@ -86,8 +82,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 +89,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 +96,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,6 +1098,7 @@ 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 )
|
||||||
@@ -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;
|
||||||
@@ -503,7 +521,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -273,12 +273,8 @@ typedef struct
|
|||||||
|
|
||||||
typedef enum bugcomp_e
|
typedef enum bugcomp_e
|
||||||
{
|
{
|
||||||
// default mode, we assume that user dlls are not relying on engine bugs
|
// reverts fix for pfnPEntityOfEntIndex for bug compatibility with GoldSrc
|
||||||
BUGCOMP_OFF,
|
BUGCOMP_PENTITYOFENTINDEX_FLAG = BIT( 0 ),
|
||||||
|
|
||||||
// GoldSrc mode, user dlls are relying on GoldSrc specific bugs
|
|
||||||
// but fixing them may break regular Xash games
|
|
||||||
BUGCOMP_GOLDSRC,
|
|
||||||
} bugcomp_t;
|
} bugcomp_t;
|
||||||
|
|
||||||
typedef struct host_parm_s
|
typedef struct host_parm_s
|
||||||
@@ -356,7 +352,7 @@ typedef struct host_parm_s
|
|||||||
int numdecals;
|
int numdecals;
|
||||||
|
|
||||||
// bug compatibility level, for very "special" games
|
// bug compatibility level, for very "special" games
|
||||||
bugcomp_t bugcomp;
|
uint32_t bugcomp;
|
||||||
|
|
||||||
// measure time to first frame
|
// measure time to first frame
|
||||||
double starttime;
|
double starttime;
|
||||||
@@ -795,6 +791,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 +812,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 )
|
||||||
|
|||||||
@@ -65,6 +65,32 @@ static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTER
|
|||||||
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
||||||
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
|
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
|
||||||
|
|
||||||
|
typedef struct feature_message_s
|
||||||
|
{
|
||||||
|
uint32_t mask;
|
||||||
|
const char *msg;
|
||||||
|
const char *arg;
|
||||||
|
} feature_message_t;
|
||||||
|
|
||||||
|
static feature_message_t bugcomp_features[] =
|
||||||
|
{
|
||||||
|
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static feature_message_t engine_features[] =
|
||||||
|
{
|
||||||
|
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
|
||||||
|
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
|
||||||
|
{ ENGINE_LOAD_DELUXEDATA, "Deluxemap Support" },
|
||||||
|
{ ENGINE_PHYSICS_PUSHER_EXT, "Improved MOVETYPE_PUSH" },
|
||||||
|
{ ENGINE_LARGE_LIGHTMAPS, "Large Lightmaps" },
|
||||||
|
{ ENGINE_COMPENSATE_QUAKE_BUG, "Stupid Quake Bug Compensation" },
|
||||||
|
{ ENGINE_IMPROVED_LINETRACE, "Improved Trace Line" },
|
||||||
|
{ ENGINE_COMPUTE_STUDIO_LERP, "Studio MOVETYPE_STEP Lerping" },
|
||||||
|
{ ENGINE_LINEAR_GAMMA_SPACE, "Linear Gamma Space" },
|
||||||
|
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
|
||||||
|
};
|
||||||
|
|
||||||
static void Sys_PrintUsage( void )
|
static void Sys_PrintUsage( void )
|
||||||
{
|
{
|
||||||
string version_str;
|
string version_str;
|
||||||
@@ -92,8 +118,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 [opts] ", "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 +133,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")
|
||||||
@@ -190,31 +219,14 @@ void Host_ShutdownServer( void )
|
|||||||
Host_PrintEngineFeatures
|
Host_PrintEngineFeatures
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
static void Host_PrintEngineFeatures( int features )
|
static void Host_PrintFeatures( uint32_t flags, const char *s, feature_message_t *features, size_t size )
|
||||||
{
|
{
|
||||||
struct
|
size_t i;
|
||||||
{
|
|
||||||
uint32_t mask;
|
|
||||||
const char *msg;
|
|
||||||
} features_str[] =
|
|
||||||
{
|
|
||||||
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
|
|
||||||
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
|
|
||||||
{ ENGINE_LOAD_DELUXEDATA, "Deluxemap Support" },
|
|
||||||
{ ENGINE_PHYSICS_PUSHER_EXT, "Improved MOVETYPE_PUSH" },
|
|
||||||
{ ENGINE_LARGE_LIGHTMAPS, "Large Lightmaps" },
|
|
||||||
{ ENGINE_COMPENSATE_QUAKE_BUG, "Stupid Quake Bug Compensation" },
|
|
||||||
{ ENGINE_IMPROVED_LINETRACE, "Improved Trace Line" },
|
|
||||||
{ ENGINE_COMPUTE_STUDIO_LERP, "Studio MOVETYPE_STEP Lerping" },
|
|
||||||
{ ENGINE_LINEAR_GAMMA_SPACE, "Linear Gamma Space" },
|
|
||||||
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 0; i < ARRAYSIZE( features_str ); i++ )
|
for( i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
if( FBitSet( features, features_str[i].mask ))
|
if( FBitSet( flags, features[i].mask ))
|
||||||
Con_Reportf( "^3EXT:^7 %s is enabled\n", features_str[i].msg );
|
Con_Printf( "^3%s:^7 %s is enabled\n", s, features[i].msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +254,7 @@ void Host_ValidateEngineFeatures( uint32_t features )
|
|||||||
SetBits( features, ENGINE_STEP_POSHISTORY_LERP );
|
SetBits( features, ENGINE_STEP_POSHISTORY_LERP );
|
||||||
|
|
||||||
// print requested first
|
// print requested first
|
||||||
Host_PrintEngineFeatures( features );
|
Host_PrintFeatures( features, "EXT", engine_features, ARRAYSIZE( engine_features ));
|
||||||
|
|
||||||
// now warn about incompatible bits
|
// now warn about incompatible bits
|
||||||
if( FBitSet( features, ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ) == ( ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ))
|
if( FBitSet( features, ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ) == ( ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ))
|
||||||
@@ -938,11 +950,59 @@ 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint32_t Host_CheckBugcomp( void )
|
||||||
|
{
|
||||||
|
uint32_t flags = 0;
|
||||||
|
string args, arg;
|
||||||
|
char *prev, *next;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if( !Sys_CheckParm( "-bugcomp" ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && args[0] != '-' )
|
||||||
|
{
|
||||||
|
for( prev = args, next = Q_strchrnul( prev, '+' ); ; prev = next + 1, next = Q_strchrnul( prev, '+' ))
|
||||||
|
{
|
||||||
|
Q_strncpy( arg, prev, next - prev + 1 );
|
||||||
|
for( i = 0; i < ARRAYSIZE( bugcomp_features ); i++ )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( bugcomp_features[i].arg, arg ))
|
||||||
|
{
|
||||||
|
SetBits( flags, bugcomp_features[i].mask );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i == ARRAYSIZE( bugcomp_features ))
|
||||||
|
{
|
||||||
|
Con_Printf( S_ERROR "Unknown bugcomp flag %s\n", arg );
|
||||||
|
Con_Printf( "Valid flags are:\n" );
|
||||||
|
for( i = 0; i < ARRAYSIZE( bugcomp_features ); i++ )
|
||||||
|
Con_Printf( "\t%s: %s\n", bugcomp_features[i].arg, bugcomp_features[i].msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !*next )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no argument specified -bugcomp just enables everything
|
||||||
|
flags = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Host_PrintFeatures( flags, "BUGCOMP", bugcomp_features, ARRAYSIZE( bugcomp_features ));
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Host_InitCommon
|
Host_InitCommon
|
||||||
@@ -1047,13 +1107,6 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
|||||||
// member console allowing
|
// member console allowing
|
||||||
host.allow_console_init = host.allow_console;
|
host.allow_console_init = host.allow_console;
|
||||||
|
|
||||||
if( Sys_CheckParm( "-bugcomp" ))
|
|
||||||
{
|
|
||||||
// add argument check here when we add other levels
|
|
||||||
// of bugcompatibility
|
|
||||||
host.bugcomp = BUGCOMP_GOLDSRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
// timeBeginPeriod( 1 ); // a1ba: Do we need this?
|
// timeBeginPeriod( 1 ); // a1ba: Do we need this?
|
||||||
|
|
||||||
// NOTE: this message couldn't be passed into game console but it doesn't matter
|
// NOTE: this message couldn't be passed into game console but it doesn't matter
|
||||||
@@ -1180,11 +1233,11 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
|||||||
|
|
||||||
Sys_InitLog();
|
Sys_InitLog();
|
||||||
|
|
||||||
// print bugcompatibility level here, after log was initialized
|
// print current developer level to simplify processing users feedback
|
||||||
if( host.bugcomp == BUGCOMP_GOLDSRC )
|
if( developer > 0 )
|
||||||
{
|
Con_Printf( "Developer level: ^3%i\n", developer );
|
||||||
Con_Printf( "^3BUGCOMP^7: GoldSrc bug-compatibility enabled\n" );
|
|
||||||
}
|
host.bugcomp = Host_CheckBugcomp();
|
||||||
|
|
||||||
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" );
|
||||||
@@ -1310,6 +1363,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 +1421,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 +1470,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();
|
||||||
|
|||||||
@@ -400,7 +400,8 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
|||||||
f = FS_Open( pakname, "rb", true );
|
f = FS_Open( pakname, "rb", true );
|
||||||
if( !f )
|
if( !f )
|
||||||
{
|
{
|
||||||
Con_DPrintf( S_ERROR "Couldn't find %s.\n", pakname );
|
if( !quiet )
|
||||||
|
Con_DPrintf( S_ERROR "Couldn't find %s.\n", pakname );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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( val_a * 100.0 );
|
||||||
val_b -= Q_rint(timebase * 100.0);
|
toF = Q_rint( 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( val_a * pField->multiplier );
|
||||||
if( !Q_equal( pField->multiplier, 1.0f ))
|
toF = Q_rint( 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;
|
||||||
}
|
}
|
||||||
@@ -1359,22 +1394,14 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, void *from, vo
|
|||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_8 )
|
else if( pField->flags & DT_TIMEWINDOW_8 )
|
||||||
{
|
{
|
||||||
bSigned = true; // timewindow is always signed
|
iValue = MSG_ReadSBitLong( msg, pField->bits );
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
flTime = ( timebase * 100.0 - (int)iValue ) / 100.0;
|
||||||
flTime = (timebase * 100.0 - (int)iValue) / 100.0;
|
|
||||||
|
|
||||||
*(float *)((byte *)to + pField->offset ) = flTime;
|
*(float *)((byte *)to + pField->offset ) = flTime;
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
else if( pField->flags & DT_TIMEWINDOW_BIG )
|
||||||
{
|
{
|
||||||
bSigned = true; // timewindow is always signed
|
iValue = MSG_ReadSBitLong( msg, pField->bits );
|
||||||
iValue = MSG_ReadBitLong( msg, pField->bits, bSigned );
|
flTime = ( timebase * pField->multiplier - (int)iValue ) / pField->multiplier;
|
||||||
|
|
||||||
if( !Q_equal( pField->multiplier, 1.0 ) )
|
|
||||||
flTime = ( timebase * pField->multiplier - (int)iValue ) / pField->multiplier;
|
|
||||||
else
|
|
||||||
flTime = timebase - (int)iValue;
|
|
||||||
|
|
||||||
*(float *)((byte *)to + pField->offset ) = flTime;
|
*(float *)((byte *)to + pField->offset ) = flTime;
|
||||||
}
|
}
|
||||||
else if( pField->flags & DT_STRING )
|
else if( pField->flags & DT_STRING )
|
||||||
@@ -2069,3 +2096,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;
|
||||||
}
|
}
|
||||||
@@ -335,15 +341,18 @@ void GAME_EXPORT Con_Printf( const char *szFmt, ... )
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_PRINT_MSG];
|
static char buffer[MAX_PRINT_MSG];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
qboolean add_newline;
|
||||||
|
|
||||||
if( !host.allow_console )
|
if( !host.allow_console )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start( args, szFmt );
|
va_start( args, szFmt );
|
||||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
Sys_Print( buffer );
|
Sys_Print( buffer );
|
||||||
|
if( add_newline )
|
||||||
|
Sys_Print( "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -356,18 +365,21 @@ void GAME_EXPORT Con_DPrintf( const char *szFmt, ... )
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_PRINT_MSG];
|
static char buffer[MAX_PRINT_MSG];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
qboolean add_newline;
|
||||||
|
|
||||||
if( host_developer.value < DEV_NORMAL )
|
if( host_developer.value < DEV_NORMAL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start( args, szFmt );
|
va_start( args, szFmt );
|
||||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
if( buffer[0] == '0' && buffer[1] == '\n' && buffer[2] == '\0' )
|
||||||
return; // hlrally spam
|
return; // hlrally spam
|
||||||
|
|
||||||
Sys_Print( buffer );
|
Sys_Print( buffer );
|
||||||
|
if( add_newline )
|
||||||
|
Sys_Print( "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -380,15 +392,18 @@ void Con_Reportf( const char *szFmt, ... )
|
|||||||
{
|
{
|
||||||
static char buffer[MAX_PRINT_MSG];
|
static char buffer[MAX_PRINT_MSG];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
qboolean add_newline;
|
||||||
|
|
||||||
if( host_developer.value < DEV_EXTENDED )
|
if( host_developer.value < DEV_EXTENDED )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start( args, szFmt );
|
va_start( args, szFmt );
|
||||||
Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args );
|
add_newline = Q_vsnprintf( buffer, sizeof( buffer ), szFmt, args ) < 0;
|
||||||
va_end( args );
|
va_end( args );
|
||||||
|
|
||||||
Sys_Print( buffer );
|
Sys_Print( buffer );
|
||||||
|
if( add_newline )
|
||||||
|
Sys_Print( "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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(); \
|
||||||
|
|||||||
@@ -25,18 +25,39 @@ GNU General Public License for more details.
|
|||||||
#include "platform/swap/swap.h"
|
#include "platform/swap/swap.h"
|
||||||
#define Q_malloc SWAP_Malloc
|
#define Q_malloc SWAP_Malloc
|
||||||
#define Q_free SWAP_Free
|
#define Q_free SWAP_Free
|
||||||
|
|
||||||
|
static void *Q_realloc( void *mem, size_t size )
|
||||||
|
{
|
||||||
|
void *newmem;
|
||||||
|
|
||||||
|
if( mem && size == 0 )
|
||||||
|
{
|
||||||
|
Q_free( mem );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
newmem = Q_malloc( size );
|
||||||
|
if( mem && newmem )
|
||||||
|
{
|
||||||
|
memcpy( newmem, mem, size );
|
||||||
|
Q_free( mem );
|
||||||
|
}
|
||||||
|
|
||||||
|
return newmem;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#define Q_malloc malloc
|
#define Q_malloc malloc
|
||||||
#define Q_free free
|
#define Q_free free
|
||||||
|
#define Q_realloc realloc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct memheader_s
|
typedef struct memheader_s
|
||||||
{
|
{
|
||||||
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
|
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
|
||||||
struct memheader_s *prev;
|
struct memheader_s *prev;
|
||||||
struct mempool_s *pool; // pool this memheader belongs to
|
|
||||||
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
|
||||||
const char *filename; // file name and line where Mem_Alloc was called
|
const char *filename; // file name and line where Mem_Alloc was called
|
||||||
|
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
||||||
|
poolhandle_t poolptr; // pool this memheader belongs to
|
||||||
int fileline;
|
int fileline;
|
||||||
#if !XASH_64BIT
|
#if !XASH_64BIT
|
||||||
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
|
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
|
||||||
@@ -48,232 +69,321 @@ typedef struct memheader_s
|
|||||||
|
|
||||||
typedef struct mempool_s
|
typedef struct mempool_s
|
||||||
{
|
{
|
||||||
uint32_t sentinel1; // should always be MEMHEADER_SENTINEL1
|
|
||||||
struct memheader_s *chain; // chain of individual memory allocations
|
struct memheader_s *chain; // chain of individual memory allocations
|
||||||
size_t totalsize; // total memory allocated in this pool (inside memheaders)
|
size_t totalsize; // total memory allocated in this pool (inside memheaders)
|
||||||
size_t realsize; // total memory allocated in this pool (actual malloc total)
|
size_t realsize; // total memory allocated in this pool (actual malloc total)
|
||||||
size_t lastchecksize; // updated each time the pool is displayed by memlist
|
size_t lastchecksize; // updated each time the pool is displayed by memlist
|
||||||
struct mempool_s *next; // linked into global mempool list
|
|
||||||
const char *filename; // file name and line where Mem_AllocPool was called
|
const char *filename; // file name and line where Mem_AllocPool was called
|
||||||
int fileline;
|
int fileline;
|
||||||
#if XASH_64BIT
|
|
||||||
poolhandle_t idx;
|
|
||||||
#endif
|
|
||||||
char name[64]; // name of the pool
|
char name[64]; // name of the pool
|
||||||
uint32_t sentinel2; // should always be MEMHEADER_SENTINEL1
|
|
||||||
} mempool_t;
|
} mempool_t;
|
||||||
|
|
||||||
static mempool_t *poolchain = NULL; // critical stuff
|
static mempool_t *poolchain = NULL; // critical stuff
|
||||||
|
static size_t poolcount = 0;
|
||||||
|
|
||||||
#if XASH_64BIT
|
|
||||||
// a1ba: due to mempool being passed with the model through reused 32-bit field
|
// a1ba: due to mempool being passed with the model through reused 32-bit field
|
||||||
// which makes engine incompatible with 64-bit pointers I changed mempool type
|
// which makes engine incompatible with 64-bit pointers I changed mempool type
|
||||||
// from pointer to 32-bit handle, thankfully mempool structure is private
|
// from pointer to 32-bit handle, thankfully mempool structure is private
|
||||||
// But! Mempools are handled through linked list so we can't index them safely
|
|
||||||
static poolhandle_t lastidx = 0;
|
|
||||||
|
|
||||||
static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
if( likely( poolptr > 0 && poolptr <= poolcount ))
|
||||||
|
return &poolchain[poolptr - 1];
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
|
||||||
{
|
|
||||||
if( pool->idx == poolptr )
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sys_Error( "%s: not allocated or double freed pool %d", __FUNCTION__, poolptr );
|
Sys_Error( "%s: not allocated or double freed pool %d", __FUNCTION__, poolptr );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static mempool_t *Mem_FindPool( poolhandle_t poolptr )
|
static poolhandle_t Mem_PoolIndex( mempool_t *mempool )
|
||||||
{
|
{
|
||||||
return (mempool_t *)poolptr;
|
return (poolhandle_t)(mempool - poolchain) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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->poolptr = Mem_PoolIndex( 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->poolptr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
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( unlikely( !poolptr ))
|
||||||
|
{
|
||||||
|
Sys_Error( "%s: pool == NULL (alloc at %s:%i)\n", __func__, filename, fileline );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
pool = Mem_FindPool( poolptr );
|
pool = Mem_FindPool( poolptr );
|
||||||
|
if( !pool )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
pool->totalsize += size;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// big allocations are not clumped
|
Mem_InitAlloc( mem, size, filename, fileline );
|
||||||
pool->realsize += sizeof( memheader_t ) + size + sizeof( size_t );
|
|
||||||
mem = (memheader_t *)Q_malloc( sizeof( memheader_t ) + size + sizeof( size_t ));
|
Mem_PoolAdd( pool, size );
|
||||||
if( mem == NULL ) Sys_Error( "Mem_Alloc: out of memory (alloc at %s:%i)\n", filename, fileline );
|
Mem_PoolLinkAlloc( pool, mem );
|
||||||
|
|
||||||
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 )
|
pool = Mem_FindPool( mem->poolptr );
|
||||||
{
|
if( !pool )
|
||||||
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
|
return;
|
||||||
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;
|
|
||||||
// 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( unlikely( !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;
|
||||||
|
|
||||||
|
if( unlikely( mem->poolptr != poolptr ))
|
||||||
{
|
{
|
||||||
size_t newsize = memhdr->size < size ? memhdr->size : size; // upper data can be trucnated!
|
Sys_Error( "Mem_Realloc: pool migration is not allowed (alloc at %s:%i, realloc at %s:%i)\n",
|
||||||
memcpy( nb, memptr, newsize );
|
Mem_CheckFilename( mem->filename ), mem->fileline, filename, fileline );
|
||||||
_Mem_Free( memptr, filename, fileline ); // free unused old block
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)nb;
|
oldsize = mem->size;
|
||||||
|
if( size == oldsize )
|
||||||
|
return data;
|
||||||
|
|
||||||
|
pool = Mem_FindPool( poolptr );
|
||||||
|
|
||||||
|
oldmem = (uintptr_t)mem;
|
||||||
|
mem = Q_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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( 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 ));
|
||||||
|
}
|
||||||
|
|
||||||
|
static poolhandle_t Mem_InitPool( mempool_t *pool, const char *name, const char *filename, int fileline )
|
||||||
|
{
|
||||||
|
memset( pool, 0, sizeof( *pool ));
|
||||||
|
|
||||||
|
// fill header
|
||||||
|
pool->filename = filename;
|
||||||
|
pool->fileline = fileline;
|
||||||
|
pool->realsize = sizeof( mempool_t );
|
||||||
|
Q_strncpy( pool->name, name, sizeof( pool->name ));
|
||||||
|
|
||||||
|
return Mem_PoolIndex( pool );
|
||||||
}
|
}
|
||||||
|
|
||||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
pool = (mempool_t *)Q_malloc( sizeof( mempool_t ));
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
|
{
|
||||||
|
if( pool->filename == NULL )
|
||||||
|
return Mem_InitPool( pool, name, filename, fileline );
|
||||||
|
}
|
||||||
|
|
||||||
|
pool = (mempool_t *)Q_realloc( poolchain, sizeof( *poolchain ) * ( poolcount + 1 ));
|
||||||
if( pool == NULL )
|
if( pool == NULL )
|
||||||
{
|
{
|
||||||
Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline );
|
Sys_Error( "Mem_AllocPool: out of memory (allocpool at %s:%i)\n", filename, fileline );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset( pool, 0, sizeof( mempool_t ));
|
|
||||||
|
|
||||||
// fill header
|
|
||||||
pool->sentinel1 = MEMHEADER_SENTINEL1;
|
|
||||||
pool->sentinel2 = MEMHEADER_SENTINEL1;
|
|
||||||
pool->filename = filename;
|
|
||||||
pool->fileline = fileline;
|
|
||||||
pool->chain = NULL;
|
|
||||||
pool->totalsize = 0;
|
|
||||||
pool->realsize = sizeof( mempool_t );
|
|
||||||
Q_strncpy( pool->name, name, sizeof( pool->name ));
|
|
||||||
pool->next = poolchain;
|
|
||||||
poolchain = pool;
|
poolchain = pool;
|
||||||
|
pool = &poolchain[poolcount++];
|
||||||
#if XASH_64BIT
|
return Mem_InitPool( pool, name, filename, fileline );
|
||||||
pool->idx = ++lastidx;
|
|
||||||
return pool->idx;
|
|
||||||
#else
|
|
||||||
return (poolhandle_t)pool;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline )
|
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
mempool_t **chainaddress;
|
|
||||||
|
|
||||||
if( *poolptr && ( pool = Mem_FindPool( *poolptr )))
|
if( *poolptr && ( pool = Mem_FindPool( *poolptr )))
|
||||||
{
|
{
|
||||||
// unlink pool from chain
|
if( !pool->filename )
|
||||||
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 );
|
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 );
|
*poolptr = 0;
|
||||||
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 );
|
return;
|
||||||
*chainaddress = pool->next;
|
}
|
||||||
|
|
||||||
// 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 );
|
||||||
|
|
||||||
// free the pool itself
|
// free the pool itself
|
||||||
memset( pool, 0xBF, sizeof( mempool_t ));
|
memset( pool, 0xBF, sizeof( mempool_t ));
|
||||||
Q_free( pool );
|
pool->chain = NULL;
|
||||||
|
pool->filename = NULL; // mark as reusable
|
||||||
*poolptr = 0;
|
*poolptr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline )
|
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline )
|
||||||
{
|
{
|
||||||
mempool_t *pool = Mem_FindPool( poolptr );
|
mempool_t *pool;
|
||||||
if( !poolptr ) Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
|
if( unlikely( !poolptr ))
|
||||||
|
{
|
||||||
|
Sys_Error( "Mem_EmptyPool: pool == NULL (emptypool at %s:%i)\n", filename, fileline );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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 );
|
pool = Mem_FindPool( poolptr );
|
||||||
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 );
|
if( !pool )
|
||||||
|
return;
|
||||||
|
|
||||||
// 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 +398,20 @@ 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 )
|
size_t i;
|
||||||
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
|
{
|
||||||
if( Mem_CheckAlloc( pool, data ))
|
if( Mem_CheckAlloc( pool, data ))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -308,59 +424,35 @@ 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;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
{
|
|
||||||
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( 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 )
|
||||||
{
|
{
|
||||||
size_t count = 0, size = 0, realsize = 0;
|
size_t count = 0, size = 0, realsize = 0, i;
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
|
|
||||||
Mem_Check();
|
Mem_Check();
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
{
|
{
|
||||||
|
if( !pool->filename )
|
||||||
|
continue;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
size += pool->totalsize;
|
size += pool->totalsize;
|
||||||
realsize += pool->realsize;
|
realsize += pool->realsize;
|
||||||
@@ -374,31 +466,38 @@ void Mem_PrintList( size_t minallocationsize )
|
|||||||
{
|
{
|
||||||
mempool_t *pool;
|
mempool_t *pool;
|
||||||
memheader_t *mem;
|
memheader_t *mem;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
Mem_Check();
|
Mem_Check();
|
||||||
|
|
||||||
Con_Printf( "memory pool list:\n"" ^3size name\n");
|
Con_Printf( "memory pool list:\n" );
|
||||||
for( pool = poolchain; pool; pool = pool->next )
|
Con_Printf( "\t^3size\t\t\t\tname\n");
|
||||||
|
for( i = 0, pool = poolchain; i < poolcount; i++, pool++ )
|
||||||
{
|
{
|
||||||
long changed_size = (long)pool->totalsize - (long)pool->lastchecksize;
|
long changed_size = (long)pool->totalsize - (long)pool->lastchecksize;
|
||||||
|
|
||||||
|
if( !pool->filename )
|
||||||
|
continue;
|
||||||
|
|
||||||
// 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
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
@@ -3391,12 +3344,10 @@ pfnPEntityOfEntIndex
|
|||||||
|
|
||||||
=============
|
=============
|
||||||
*/
|
*/
|
||||||
static edict_t *pfnPEntityOfEntIndex( int iEntIndex )
|
static edict_t *pfnPEntityOfEntIndexBroken( int iEntIndex )
|
||||||
{
|
{
|
||||||
// have to be bug-compatible with GoldSrc in this function
|
// have to be bug-compatible with GoldSrc in this function
|
||||||
if( host.bugcomp == BUGCOMP_GOLDSRC )
|
return SV_PEntityOfEntIndex( iEntIndex, false );
|
||||||
return SV_PEntityOfEntIndex( iEntIndex, false );
|
|
||||||
return SV_PEntityOfEntIndex( iEntIndex, true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3737,9 +3688,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 +3824,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 )
|
||||||
@@ -4731,7 +4682,7 @@ static enginefuncs_t gEngfuncs =
|
|||||||
pfnPEntityOfEntOffset,
|
pfnPEntityOfEntOffset,
|
||||||
pfnEntOffsetOfPEntity,
|
pfnEntOffsetOfPEntity,
|
||||||
pfnIndexOfEdict,
|
pfnIndexOfEdict,
|
||||||
pfnPEntityOfEntIndex,
|
pfnPEntityOfEntIndexAllEntities,
|
||||||
pfnFindEntityByVars,
|
pfnFindEntityByVars,
|
||||||
pfnGetModelPtr,
|
pfnGetModelPtr,
|
||||||
pfnRegUserMsg,
|
pfnRegUserMsg,
|
||||||
@@ -4820,6 +4771,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 +4791,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 +4826,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 +4916,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 +4934,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 +4944,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 +4955,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 +5085,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 +5105,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 );
|
||||||
@@ -5170,6 +5153,11 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
// make sure what physic functions is cleared
|
// make sure what physic functions is cleared
|
||||||
memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs ));
|
memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs ));
|
||||||
|
|
||||||
|
// revert fix for pfnPEntityOfEntIndex to be compatible with GoldSrc
|
||||||
|
// games that rely on this bug
|
||||||
|
if( FBitSet( host.bugcomp, BUGCOMP_PENTITYOFENTINDEX_FLAG ))
|
||||||
|
gEngfuncs.pfnPEntityOfEntIndex = pfnPEntityOfEntIndexBroken;
|
||||||
|
|
||||||
// make local copy of engfuncs to prevent overwrite it with bots.dll
|
// make local copy of engfuncs to prevent overwrite it with bots.dll
|
||||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||||
|
|
||||||
@@ -5182,7 +5170,7 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GetEntityAPI proc\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GetEntityAPI proc\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5193,7 +5181,7 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GiveFnptrsToDll proc\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: failed to get address of GiveFnptrsToDll proc\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5218,7 +5206,8 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
{
|
{
|
||||||
if( !GetEntityAPI2( &svgame.dllFuncs, &version ))
|
if( !GetEntityAPI2( &svgame.dllFuncs, &version ))
|
||||||
{
|
{
|
||||||
Con_Printf( S_WARN "SV_LoadProgs: interface version %i should be %i\n", INTERFACE_VERSION, version );
|
if( INTERFACE_VERSION != version )
|
||||||
|
Con_Printf( S_WARN "SV_LoadProgs: interface version %i should be %i\n", INTERFACE_VERSION, version );
|
||||||
|
|
||||||
// fallback to old API
|
// fallback to old API
|
||||||
if( !GetEntityAPI( &svgame.dllFuncs, version ))
|
if( !GetEntityAPI( &svgame.dllFuncs, version ))
|
||||||
@@ -5226,9 +5215,10 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else Con_Reportf( "SV_LoadProgs: ^2initailized legacy EntityAPI ^7ver. %i\n", version );
|
||||||
}
|
}
|
||||||
else Con_Reportf( "SV_LoadProgs: ^2initailized extended EntityAPI ^7ver. %i\n", version );
|
else Con_Reportf( "SV_LoadProgs: ^2initailized extended EntityAPI ^7ver. %i\n", version );
|
||||||
}
|
}
|
||||||
@@ -5237,9 +5227,10 @@ qboolean SV_LoadProgs( const char *name )
|
|||||||
COM_FreeLibrary( svgame.hInstance );
|
COM_FreeLibrary( svgame.hInstance );
|
||||||
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
Con_Printf( S_ERROR "SV_LoadProgs: couldn't get entity API\n" );
|
||||||
svgame.hInstance = NULL;
|
svgame.hInstance = NULL;
|
||||||
Mem_FreePool(&svgame.mempool);
|
Mem_FreePool( &svgame.mempool );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else Con_Reportf( "SV_LoadProgs: ^2initailized legacy EntityAPI ^7ver. %i\n", version );
|
||||||
|
|
||||||
SV_InitOperatorCommands();
|
SV_InitOperatorCommands();
|
||||||
Mod_InitStudioAPI();
|
Mod_InitStudioAPI();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user