Compare commits

..

1 Commits

402 changed files with 20440 additions and 19591 deletions

View File

@@ -1,10 +1,10 @@
task:
name: freebsd-14-amd64
freebsd_instance:
image_family: freebsd-14-3
image_family: freebsd-14-2
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python freetype2 libvorbis opusfile bzip2 libbacktrace libogg libvorbis
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh
@@ -12,21 +12,10 @@ task:
task:
name: freebsd-15-amd64
freebsd_instance:
image_family: freebsd-15-0-amd64-zfs
image_family: freebsd-15-0-snap
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python freetype2 libvorbis opusfile bzip2 libbacktrace libogg libvorbis
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh
#task:
# name: freebsd-16-amd64
# freebsd_instance:
# image_family: freebsd-16-0-snap
# setup_script:
# - pkg update
# - pkg install -y pkgconf git sdl2 python freetype2 libvorbis opusfile bzip2 libbacktrace libogg libvorbis
# - git submodule update --init --recursive
# test_script:
# - ./scripts/cirrus/build_freebsd.sh

View File

@@ -21,12 +21,14 @@ jobs:
- os: ubuntu-22.04
targetos: linux
targetarch: i386
- os: ubuntu-22.04-arm
- os: ubuntu-22.04
targetos: linux
targetarch: arm64
- os: ubuntu-22.04-arm
cross: true
- os: ubuntu-22.04
targetos: linux
targetarch: armhf
cross: true
- os: ubuntu-24.04 # riscv64 would benefit from having latest compilers
targetos: linux
targetarch: riscv64
@@ -35,6 +37,9 @@ jobs:
targetos: linux
targetarch: ppc64el
cross: true
# - os: ubuntu-aarch64-22.04
# targetos: linux
# targetarch: aarch64
# - os: ubuntu-latest
# targetos: linux
# targetarch: e2k-8c
@@ -61,21 +66,18 @@ jobs:
- os: macos-14 # arm64 as per github documentation
targetos: apple
targetarch: arm64
- os: macos-latest
targetos: ios
targetarch: arm64
- os: macos-15-intel
- os: macos-13 # x86 as per github documentation (will they fix it before they deprecate this version?..)
targetos: apple
targetarch: amd64
env:
SDL_VERSION: 2.32.10
FFMPEG_VERSION: 8.1
SDL_VERSION: 2.32.8
FFMPEG_VERSION: 7.1
GH_CPU_ARCH: ${{ matrix.targetarch }}
GH_CPU_OS: ${{ matrix.targetos }}
GH_CROSSCOMPILING: ${{ matrix.cross }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
@@ -85,7 +87,7 @@ jobs:
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
@@ -97,11 +99,11 @@ jobs:
include:
- app: su.xash.Engine.Compat.i386
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-24.08
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build flatpak (Compat.i386)
@@ -115,10 +117,31 @@ jobs:
needs: [build, flatpak]
if: ${{ github.event_name == 'push' }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Remove old release, fetch artifacts, repackage binaries and upload new release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE_BUILDNUM_DATE: "2015-04-01"
run: bash scripts/gha/make_release.sh "Xash3D FWGS" "${{ github.ref_name }}"
RELEASE_TAG: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
run: |
gh release delete "$RELEASE_TAG" \
--yes \
--cleanup-tag \
--repo "$GITHUB_REPOSITORY" || true
gh run download "$GITHUB_RUN_ID" \
--dir artifacts/ \
--repo "$GITHUB_REPOSITORY"
pushd artifacts/
echo "Found artifacts:"
ls
for i in $(find -mindepth 1 -maxdepth 1 -type d); do
mv "$i"/* .
rm -rf "$i"
done
echo "Repackaged artifacts:"
ls -R
popd
sleep 20s
gh release create "$RELEASE_TAG" artifacts/* \
--title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
--target $GITHUB_SHA \
--repo "$GITHUB_REPOSITORY" \
--prerelease

7
.gitignore vendored
View File

@@ -318,12 +318,6 @@ build-*
*.includes
*.files
# ios
ios/cl_dlls/*
ios/dlls/*
ios/*.framework
scripts/ios/mod-build
# Waf
build_current
*waf-*/
@@ -345,7 +339,6 @@ __pycache__
.history/*
.cache/*
enc_temp_folder/
Taskfile.yml
# KDevelop4
*.kdev4

5
.gitmodules vendored
View File

@@ -39,7 +39,4 @@
url = https://github.com/ianlancetaylor/libbacktrace
[submodule "3rdparty/maintui"]
path = 3rdparty/maintui
url = https://github.com/FWGS/xash3d-maintui.git
[submodule "3rdparty/library_suffix"]
path = 3rdparty/library_suffix
url = https://github.com/FWGS/library-suffix.git
url = https://github.com/numas13/xash3d-maintui.git

View File

@@ -20,10 +20,10 @@ int main (void) {
}'''
FRAGMENT_GETPAGESIZE='''#include <unistd.h>
int main(void) { return getpagesize(); }'''
int main(void) { return getpagesize() }'''
FRAGMENT_GETEXECNAME='''#include <stdlib.h>
int main(void) { return getexecname() != 0; }'''
int main(void) { return getexecname() != 0 }'''
FRAGMENT_STRNLEN='''#include <string.h>
int main(int argc, char **argv) { return (int)strnlen(argv[0], 10); }'''
@@ -62,7 +62,7 @@ def options(opt):
def configure(conf):
# add unsupported platforms here
if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos', 'irix']:
if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos']:
conf.env.DISABLE_LIBBACKTRACE = True
return
@@ -95,7 +95,7 @@ def configure(conf):
return {'header_name':hdr, 'msg':'... %s header' % hdr, 'mandatory':False, 'id':hdr, 'compiler': 'c'}
def check_frag(frag, msg, define, **kw):
return dict({'fragment': frag, 'msg':'... %s' % msg, 'mandatory': False, 'define_name': define, 'compiler': 'c'}, **kw)
return dict({'fragment': frag, 'msg':'... %s' % msg, 'mandatory': False, 'compiler': 'c'}, **kw)
conf.multicheck(
check_header('dlfcn.h'),
@@ -120,8 +120,8 @@ def configure(conf):
check_frag(FRAGMENT_SYNC, ' __sync extensions', 'HAVE_SYNC_FUNCTIONS'),
check_frag(FRAGMENT_GETPAGESIZE, ' getpagesize function', 'HAVE_DECL_GETPAGESIZE'),
check_frag(FRAGMENT_STRNLEN, ' strnlen function', 'HAVE_DECL_STRNLEN'),
check_frag(FRAGMENT_DL_ITERATE_PHDR % 'link.h', ' dl_iterate_phdr function in link.h', 'HAVE_DL_ITERATE_PHDR_LINK_H', after_tests=['link.h']),
check_frag(FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', ' dl_iterate_phdr function in sys/link.h', 'HAVE_DL_ITERATE_PHDR_SYS_LINK_H', after_tests=['sys/link.h']),
check_frag(FRAGMENT_DL_ITERATE_PHDR % 'link.h', ' dl_iterate_phdr function in link.h', 'HAVE_DL_ITERATE_PHDR', after_tests=['link.h']),
check_frag(FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', ' dl_iterate_phdr function in sys/link.h', 'HAVE_DL_ITERATE_PHDR', after_tests=['sys/link.h']),
check_frag(FRAGMENT_FCNTL, 'fnctl function', 'HAVE_FCNTL'),
check_frag(FRAGMENT_GETEXECNAME, 'getexecname function','HAVE_GETEXECNAME'),
check_frag(FRAGMENT_GETIPINFO, '_Unwind_GetIPInfo function', 'HAVE_GETIPINFO'),
@@ -137,9 +137,6 @@ def configure(conf):
msg='Checking for in parallel'
)
if conf.is_defined('HAVE_DL_ITERATE_PHDR_LINK_H') or conf.is_defined('HAVE_DL_ITERATE_PHDR_SYS_LINK_H'):
conf.define('HAVE_DL_ITERATE_PHDR', 1)
conf.env[DEFKEYS].sort()
conf.write_config_header()
@@ -165,13 +162,8 @@ def build(bld):
if bld.env.DISABLE_LIBBACKTRACE:
return
sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c']
if bld.env.DEST_OS == 'win32':
sources += ['read.c', 'alloc.c']
else:
# we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers
sources += ['mmap.c', 'mmapio.c']
# we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers
sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c', 'mmap.c', 'mmapio.c']
if bld.env.DEST_BINFMT == 'pe':
sources += ['pecoff.c']
@@ -184,8 +176,7 @@ def build(bld):
task = bld.stlib(
source = ['libbacktrace/' + i for i in sources],
# while we're using upstream libbacktrace, sometimes compiler picks up it's own version that isn't built with required options
target = 'backtrace_custom',
target = 'backtrace',
features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '',
use = 'EXTRAFLAGS lzma z zstd',
includes = '. libbacktrace/',

Submodule 3rdparty/library_suffix deleted from 2cb2a0e120

View File

@@ -29,11 +29,10 @@
* This project uses mixed Quake's and HLSDK's C/C++ code style convention.
* In short:
* Use spaces in parenthesis, but not when two parentheses are consecutive.
* Use spaces in parenthesis.
* Only tabs for indentation.
* Any brace must have it's own line.
* Short blocks, if statements and loops on single line are allowed.
* Prefer generic utilities from libpublic over rolling your own.
* Avoid magic numbers.
* While macros are powerful, it's better to avoid overusing them.
* If you unsure, try to mimic code style from anywhere else of engine source code.

View File

@@ -1,103 +0,0 @@
## Setting up Xash3D FWGS in Qt Creator
### Intro
Most versions of Qt Creator support using `compile_commands.json` as a project
file and Waf supports generating this file in a compliant format. In this
tutorial we will leverage that features.
The tutorial is written using Qt Creator 18.0, but I urge you to use whatever
latest Qt Creator version is available, as it's often has important bug fixes.
### Step 1. Configure the build.
`compile_commands.json` file, as it can be guessed from it's name, contains
every command used to invoke compiler during build. As the build process
depends on the build configuration, we have to configure it first. I'm not
going to get into details here, as basics of compiling Xash3D FWGS already
explained in `README.md`, located in repository root.
Save the configure step command somewhere, as it's going to be used later.
### Step 2. Generate `compile_commands.json` file.
Usually, this file is located in `build` directory after a successful build.
However, it's also possible to generate it manually by running follow command:
On *nix systems:
```
$ ./waf clangdb
```
Or on Windows:
```
> waf.bat clangdb
```
### Step 3. Load the project in Qt Creator.
To do this, you need to be sure that `Compilation Databases` plugin is enabled.
As it's considered experimental, it probably needs to be enabled manually. It
can be done in `Help` -> `About Plugins...`. Locate it in `Build Systems`
category, put the checkbox and press `OK`. The IDE will ask for restart, so do
this.
After IDE has been restarted, you can use `File` -> `Open File or Project...`.
Navigate to Xash3D FWGS directory, then to `build` directory and select
`compile_commands.json` file. If everything is done correctly, IDE will ask to
set up the project. Press `Configure Project` button, as most options there are
usually unapplicable to us.
Next IDE will show project tree, however you might not see any files. This is
happens as Qt Creator "thinks" our project root located in `build` directory.
Thankfully it provides a way to override this. To fix it, click with right
mouse button on the root of project tree (it's usually called something like
`build [master]`) and select `Change Root Directory`. In opened window choose
Xash3D FWGS repository root and press `OK`.
### Step 4. Tell IDE how to build this project.
Open `Projects` on the left menu and choose `Build Settings` tab. You should
see an empty configuration for build and clean steps. Press on `Add Build Step`
button and choose `Custom Process Step`.
In created step you should see `Command`, `Arguments` and `Working Directory`.
For the command, choose the Python executable. For arguments, use configure
command for Waf from the first step. Working directory is usually set by IDE
to `%{buildDir}`. You need to select the upper directory, where the `waf` is
located. To save some time, it can be specified as `%{buildDir}/../`.
Add another custom step, fill it with the same command and working directory.
For arguments use `waf build`.
Below you should see `Clean steps`. Create a clean step the same way, fill the
arguments and working directory as usual, for arguments use `waf clean`.
### Step 5. Tell IDE how to copy built binaries.
Now select `Deploy Settings` tab. Press `Add Deploy Step` -> `Custom Process
Step`. Again, same command and working directory. In arguments field type:
`waf install --destdir="<here put where Xash binaries should be copied to>"`.
### Step 6. Finally, set up Qt Creator to run the engine.
Select the `Run Settings` tab. Below you might see familiar text fields:
`Executable`, `Command line arguments` and `Working directory`.
For working directory click on `Browse...` button and select the folder where
Xash3D executable will be copied to, from previous step.
For executable type `./xash3d` if you're on *nix or `xash3d.exe` if you're on
Windows. The command line arguments are the same you use to run the engine. Can
be empty as well, but I personally use `-dev 2 -log` for extra verbosity.
### Outro
At this moment, you should be able to press `Run` button, wait until build
finishes and see running Xash3D FWGS. On Windows to use the debugger you might
need the `CDB` debugger and appropriate `qtcreatorcdbext` binary for debugging
32-bit applications and a separate for 64-bit, but that's left as an exercise
for the reader and a potential improvement for this document.

View File

@@ -26,12 +26,3 @@ Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of
* [Boosty page](https://boosty.to/snmetamorph)
* [Other donation methods](https://snmetamorph.github.io/donate)
## [$_Vladislav](https://github.com/Vladislav4KZ)
[YaPB Project](https://github.com/yapb) member, [Xash3D FWGS](https://github.com/FWGS/xash3d-fwgs) tester,
editor of the [Official YaPB Documentation](https://github.com/yapb/docs) (in English and Russian), curator of the [YaPB Graph Database](https://github.com/yapb/graph) and author of [YaPB Waypoint/Graph Pack](https://gamebanana.com/mods/40087).
Also does the Russian localization of text, images (gfx/shell), as well as additional menu buttons in English used in Xash3D FWGS for various mods.
* [Boosty page](https://boosty.to/rasstaman1337)

View File

@@ -1,16 +0,0 @@
# Addon folders in Xash3D FWGS
Xash3D FWGS supports both GoldSource-style addon folders and has few own. Each directory can have it's own archives that will be mounted with lower priority than directory itself.
Below is the mounts map, in order of precedence from least important to most important.
|--------------------|------|
| Directory | Note |
|--------------------|------|
| `$game/downloaded` | Always added. Used to store server downloads.|
| `$game` | This is the game directory. |
| `$game/custom` | Always added. Used for user modifications content. |
| `$game_hd` | Added with `fs_mount_hd` set to non-zero value. Used for high definition content, similar to GoldSrc.. |
| `$game_addon` | Added with `fs_mount_addon` set to non-zero value. Used for user modifications content, similar to GoldSrc. |
| `$game_lv` | Added with `fs_mount_lv` set to non-zero value. Used for low-violence content, similar to GoldSrc. |
| `$game_$language` | Added with `fs_mount_l10n` set to non-zero value. Language is controlled with `ui_language` cvar or `-language` command line switch. Used for localization content, similar to GoldSrc. |

View File

@@ -1,19 +0,0 @@
## Lightmapped water
Xash3D FWGS supports lightmapped water, as an extension. It adds three new cvars and new worldspawn key values.
### For level designers:
If you're a level designer and intend to make your level to have lightmapped water, you can put these keyvalues to worldspawn entity description (always first entity in entities list):
| Key | Value | Description |
| ---------------------- | ------- | ----------- |
| `_litwater` | integer | Set to any non-zero value to enable lightmapped water. Overrides `gl_litwater_force` cvar value. |
| `_litwater_minlight` | integer | Minimal lightmap value water surface will receive. Helps to avoid too dark areas when water isn't properly lit. If not set, defaults to zero. |
| `_litwater_scale` | float | Scales up lightmap value for water surfaces. If not set, defaults to 1.0. |
### For players:
Some of the maps already have computed lightmap for water surfaces and sometimes water has been properly lit but the support hasn't been declared by the level designer.
As a player, you can enable it in `Video options` menu or through console with `gl_litwater_force` cvar. There are also `gl_litwater_minlight` and `gl_litwater_scale` cvars that function similar to keys above. The default values has been set to `192` and `1.25` respectively to slightly avoid issues with maps that wasn't intended to have lightmapped water.

View File

@@ -1,8 +0,0 @@
# Steam broker protocol
`sb_connect <ip:port> <server's steam id> <secure> <challenge>` - used for obtaining auth ticket during connection to GoldSrc server
`sb_disconnect <ip:port> <challenge>` - used for signaling broker about disconnecting from GoldSrc server
`sb_gamedir <gamedir>` - used for signaling broker about game startup and for announcing started mod, so broker could choose proper AppID for Steam API initialization
`sb_terminate` - used for signaling broker about game shutdown, ideally broker should be terminated too (and later restarted automatically and waiting for sb_gamedir message)

View File

@@ -1,18 +1,15 @@
# Support for GoldSrc network protocol
This feature is still work-in-progress, but for now it's available for all users, and we appreciate any bug-reports and contributions around it.
For connecting to GoldSrc-based servers, use this command:
```
connect ip:port gs
```
You need to use [Steam API broker](https://github.com/FWGS/steam-broker) and have purchased Half-Life 1 on your Steam account to be able to join GoldSrc servers.
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
Without this requirement, you will just get "Steam validation rejected" error on connecting.
Broker will run on your PC and will be responsible for communicating with Steam client and obtaining auth tickets.
Also, make sure to set that broker as current ticket generator using console or edit `config.cfg` file manually:
```
cl_ticket_generator steam
```
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
If you want to join GoldSrc servers from other device (Android/iOS or console), make sure to set proper broker IP address with `cl_steam_broker_addr` console variable. Default value assumed that broker is running on the same device as game client.
By the way, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be
Also, we encountered that some GoldSrc-based servers are recognizing Xash3D clients as "fake clients" and banning/kicking them. Maybe this problem will be
solved along with better compatibility with GoldSrc behavior, but may be not - we don't know logic behind this fake client checks.

View File

@@ -16,9 +16,6 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth
## Battle Grounds
Mirrored on github - https://github.com/nekonomicon/BattleGrounds
## Brain Bread
Official github repository - https://github.com/IronOak-Studios/BrainBread
## Bubblemod
Download page on official site(WM snapshot) - [http://www.bubblemod.org/dl_default.php](https://web.archive.org/web/20130717133158/http://www.bubblemod.org/dl_default.php)
@@ -53,9 +50,6 @@ Alpha 2.0 - https://www.gamers-desire.de/details/2830
## ESHQ
Official github repository - https://github.com/adslbarxatov/xash3d-for-ESHQ
## Feline
Available on ModDB - https://www.moddb.com/mods/feline-10/downloads/feline-sdk
## Flat-Life
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Half-Life_2D_(Flat-Life)
@@ -70,9 +64,6 @@ Version 3.0, mirrored on github - https://github.com/nekonomicon/Go-mod30
## GT mod
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki)
## Half-Force
Available on ModDB - https://www.moddb.com/mods/half-force/downloads/half-force-v20-sdk
## Half-Life: Advanced Deathmatch
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/hla
@@ -85,9 +76,6 @@ Available on ModDB - https://www.moddb.com/mods/half-life-echoes
## Half-Life: Expanded Arsenal
Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal
## Half-Life: Field Intensity
Branch **field_intensity_1.7** in halflife-featureful - https://github.com/FreeSlave/halflife-featureful/tree/field_intensity_1.7
## Half-Life: Gravgun mod
Branch **gravgun** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/gravgun
@@ -109,9 +97,6 @@ Official github repository - https://github.com/Fograin/hl-subsmod-ex
## Half-Life: Rally
Official gitlab repository - https://gitlab.com/hlrally/src
## Half-Life: RXT
Available on ModDB - https://www.moddb.com/mods/half-life-rxt/downloads/rxt-source-code-v57
## Half-Life: Weapon Edition
Available on ModDB - https://www.moddb.com/mods/half-life-weapon-edition/downloads/half-life-weapon-edition-1508-alpha-open-src
@@ -133,17 +118,12 @@ Official github repository - https://github.com/HeathGames/half_rats_parasomnia_
## Half-Screwed
Official github repository - https://github.com/desukuran/half-screwed
## Halo: GoldSource
Available on ModDB - https://www.moddb.com/mods/halo-goldsrc/downloads/halo-gold-source-summer-2025-release-v10-sdk
## Headcrab Frenzy
Version 1.3 on ModDB - https://www.moddb.com/mods/headcrab-frenzy/downloads/headcrab-frenzy-13-beta-source-code
## Heart of Evil
Mirrored on github - https://github.com/nekonomicon/HeartOfEvil
Mirrored on github (Includes maps and models source files) - https://github.com/malortie/heart-of-evil-source-files
## Ingram Chillin' Mod
Official SourceForge repository - https://sourceforge.net/projects/icm-hl/
@@ -175,9 +155,6 @@ Prealpha, mirrored on github - https://github.com/a1batross/Paranoia2_ancient
Version 1.51, mirrored on github - https://github.com/a1batross/Paranoia2_original
## Public Enemy
Official github repository - https://github.com/IronOak-Studios/Public-Enemy
## Raven City
*Unfinished mod*
@@ -209,9 +186,6 @@ Mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-wastelan
## Wizard Wars
Download page on official site - http://www.thothie.com/ww/
## Wrong Door
Available on ModDB - https://www.moddb.com/mods/wrong-door/downloads/wrong-door-sdk
## XashXT
Mirrored on github - https://github.com/a1batross/XashXT_original
@@ -277,9 +251,6 @@ Reverse-engineered code of server part by s1lentq - https://github.com/s1lentq/R
## Counter Strike Online
CSO-like Xash3D-based mod, CSMoE - https://github.com/MoeMod/CSMoE
## Crack-Life
Reverse-engineered code: branch **cracklife** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/cracklife
## Crack-Life: Campaign Mode
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_life
@@ -382,9 +353,6 @@ Deathmatch Quaked - https://www.moddb.com/games/deathmatch-classic/downloads/dmq
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc
## Delta Particles
Branch **delta_particles** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/delta_particles
## Half-Life: Echoes
Branch **echoes** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/echoes

View File

@@ -22,7 +22,6 @@ Table is sorted by status and platform.
| PSVita | Supported | @fgsfdsfgs |
| Switch | Supported | @fgsfdsfgs |
| Windows | Supported | @a1batross, @SNMetamorph |
| iOS | Supported | @ksagameng2 |
| DOS4GW | Orphaned | N/A | Haven't been confirmed to work for a very long time
| Haiku | Orphaned | N/A | Was added by #478 and #483
| IRIX | Orphaned | N/A | Undone, compiles but requires big endian port
@@ -36,3 +35,4 @@ Table is sorted by status and platform.
| Emscripten | Old Engine | N/A |
| 3DS | Old Engine fork | N/A | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
| Oculus Quest | Old Engine fork | N/A | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
| iOS | Deprecated | N/A | See GitHub issue #61

View File

@@ -1,11 +0,0 @@
# Xash3D FWGS protocol support
Xash3D FWGS currently supports four network protocols:
* Version 49, introduced in Xash3D in around 2018.
* Version 48, used in Xash3D FWGS 0.19 and earlier. Deprecated and to be removed in the future.
* GoldSrc version 48, used in current GoldSource version.
* Quake version 15, only used for demo playback for Quake Wrapper mod.
On the server side, we only support Xash3D 49 protocol, but bugcomp `gsmrf` mode can convert GoldSrc 48 messages into Xash3D 49 on the fly, for some mods that directly write engine internal messages.
In the following documents we will only cover version 49, as everything else is either not Xash3D specific or deprecated.

View File

@@ -1,305 +0,0 @@
# Xash3D 49 connectionless protocol
Connectionless protocol defines four common message sources and destinations, they can be:
* `S` for Server
* `C` for Client
* `M` for Master
* `A` for Anything else
All connectionless packets have `\xff\xff\xff\xff` (32-bit integer set to all ones) in it's header. Let's go through each of possible direction in this document.
<!--TOC-->
- [Any](#any)
- [Any to Any](#any-to-any)
- [`A2A_NETINFO`](#a2a_netinfo)
- [`A2A_INFO`](#a2a_info)
- [`A2A_PING` and `A2A_GOLDSRC_PING`](#a2a_ping-and-a2a_goldsrc_ping)
- [`A2A_ACK` and `A2A_GOLDSRC_ACK`](#a2a_ack-and-a2a_goldsrc_ack)
- [Any to Client](#any-to-client)
- [`A2C_PRINT` and `A2C_GOLDSRC_PRINT`](#a2c_print-and-a2c_goldsrc_print)
- [Any to Server and Server to Any](#any-to-server-and-server-to-any)
- [`A2S_GOLDSRC_INFO`, `A2S_GOLDSRC_RULES` and `A2S_GOLDSRC_PLAYERS` and their responses](#a2s_goldsrc_info-a2s_goldsrc_rules-and-a2s_goldsrc_players-and-their-responses)
- [Any to Master](#any-to-master)
- [`S2M_SCAN_REQUEST`](#s2m_scan_request)
- [Master to Any](#master-to-any)
- [`M2A_SERVERSLIST`](#m2a_serverslist)
- [Master and game server](#master-and-game-server)
- [Server to Master](#server-to-master)
- [`S2M_HEARTBEAT`](#s2m_heartbeat)
- [`S2M_SHUTDOWN`](#s2m_shutdown)
- [`S2M_INFO`](#s2m_info)
- [Master to Server](#master-to-server)
- [`M2S_CHALLENGE`](#m2s_challenge)
- [`M2S_NAT_CONNECT`](#m2s_nat_connect)
- [Client and game server](#client-and-game-server)
- [Client to Server](#client-to-server)
- [`C2S_BANDWIDTHTEST`](#c2s_bandwidthtest)
- [`C2S_GETCHALLENGE`](#c2s_getchallenge)
- [`C2S_CONNECT`](#c2s_connect)
- [Server to Client](#server-to-client)
- [`S2C_BANDWIDTHTEST`](#s2c_bandwidthtest)
- [`S2C_CHALLENGE`](#s2c_challenge)
- [`S2C_CONNECTION`](#s2c_connection)
- [`S2C_ERRORMSG`](#s2c_errormsg)
- [`S2C_REJECT`](#s2c_reject)
<!--TOC-->
## Any
### Any to Any
#### `A2A_NETINFO`
Used to implement Half-Life's NetAPI.
* Request message, in ASCII: `netinfo <version> <context> <request_id>`
- `version` must be 49, as text.
- `context` can be any 32-bit signed integer value, encoded as text.
- `request_id` see `common/net_api.h`
* Response message, in ASCII: `netinfo <context> <request_id> <response>`
- `context` same as in request.
- `request_id` same as in request.
- `response` is server's response, depending on request type. Always encoded as Quake info string.
Possible requests and response formats:
* Request ID `1` will make server respond with empty response string.
* Request ID `2` makes server respond with all server game rule cvars where the key is cvar name and the value is cvar value. One additional key `rules` with total amount of cvars is added.
* Request ID `3` makes server respond with players list, where:
- `p<id>name` is set to player's name
- `p<id>frags` is set to player's kill count
- `p<id>time` is set to player's total play time
- `players` is total player's list.
- Alternatively, it can respond with `neterror` set to `forbidden` if server does not wish to expose it's player list.
* Request ID `4` makes server to respond with common game details:
- `hostname` is server's name
- `gamedir` is game directory name
- `current` is total player count
- `max` is max players limit
- `map` is server's current level
* On any other server will respond with `neterror` set to `undefined`
* If protocol version doesn't match, server responds with `neterror` set to `protocol`
#### `A2A_INFO`
Used to request server's details.
* Request message, in ASCII: `info <version>`
- `version` must be 49, as text
* Response message, in ASCII: `info\n<response>`
- `response` is Quake info string, otherwise it's an error message.
* Response info string format:
- `p` is set to protocol version (FWGS extension)
- `map` is server's current level
- `dm` set to 1 if current game mode is deathmatch otherwise 0
- `team` set to 1 if current game mode includes teamplay otherwise 0
- `coop` set to 1 if current game mode is cooperative otherwise 0
- `numcl` is total player count
- `maxcl` is max players limit
- `gamedir` is game directory name
- `password` set to 1 if server is protected with password otherwise 0
- `host` is server's name
#### `A2A_PING` and `A2A_GOLDSRC_PING`
Simple ping message.
* Request, in ASCII: `ping` or `i` in GoldSrc format
* Response is always `A2A_ACK` or `A2A_GOLDSRC_ACK`
#### `A2A_ACK` and `A2A_GOLDSRC_ACK`
Simple ack message.
* Request, in ASCII: `ack` or `j` in GoldSrc format
* Response: none
### Any to Client
#### `A2C_PRINT` and `A2C_GOLDSRC_PRINT`
Simple print message.
* Header: `\xff\xff\xff\xff`
* Request, in ASCII: `print <message>` or `l<message>` in GoldSrc format.
* Response: none
### Any to Server and Server to Any
#### `A2S_GOLDSRC_INFO`, `A2S_GOLDSRC_RULES` and `A2S_GOLDSRC_PLAYERS` and their responses
These match Source Engine Query messages used in GoldSrc and Source engine and implemented for compatibility with existing tools. Read documentation for them on VDC: https://developer.valvesoftware.com/wiki/Server_queries
### Any to Master
#### `S2M_SCAN_REQUEST`
* Request: `1<region><IP:Port>\0<info>`
- Format of this message is loosely based on https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol
- `info` however adds few additional fields:
- `clver` set to engine's version
- `nat` set to 1 to filter only servers behind NAT and tell master to notify servers about scan
- `commit` set to engine's build commit hash
- `branch` set to engine's build branch
- `os` set to which operating system engine has been built
- `arch` set to which CPU architecture engine has been built
- `buildnum` set to engine's build number
- `key` set to random 32-bit value formatted as hex, used to validate master responses
* Response: `M2A_SERVERSLIST`
### Master to Any
#### `M2A_SERVERSLIST`
* Request: `f\xff<key><reserved><IP:Port>...`
- `key` is random 32-bit value set in `S2M_SCAN_REQUEST`
- `reserved` is single reserved 8-bit byte
- Following is list of IP addresses in binary form: 6-bytes for IPv4 address + port and 18-bytes for IPv6 address + port
- If port is 0, it means the end of list, otherwise it's the last IP used for pagination (not implemented in Xash3D)
* Response: client doesn't make response to master server but might request `A2S_INFO` from servers
## Master and game server
### Server to Master
#### `S2M_HEARTBEAT`
Used to update game server information on the master server.
* Request: `q\xff<heartbeat challenge>`
- `heartbeat challenge` is random 32-bit value, used to prevent faked/forged source IP addresses.
* Response: `M2S_CHALLENGE`
#### `S2M_SHUTDOWN`
Used to notify master server about server shutdown, but due to security reasons must be ignored by any master implementation.
* Request: `\x62\x0a`
* Response: none
#### `S2M_INFO`
Game server info response on `M2S_CHALLENGE`.
* Request: `0\n<info>`
- `info` is Quake info string containing server information passed to master server. It contains following fields:
- `protocol` is always 49
- `challenge` is master challenge
- `players` is total player count, without bots
- `max` is max players limits
- `bots` is total bot count
- `gamedir` is set to game directory
- `map` is server's current level
- `type` set to `d` for dedicated or `l` for listen server
- `password` set to `1` if server protected with password set otherwise `0`
- `os` always `w`
- `secure` always `0`
- `lan` always `0`
- `version` engine version
- `region` always `255`
- `product` same as `gamedir`
- `nat` set to `1` if server is behind NAT
* Response: none
### Master to Server
#### `M2S_CHALLENGE`
Master's respoonse on game server's heartbeat message.
* Request: `s<master challenge><heartbeat challenge>`
- `master challenge` contains 32-bit value, used in server response to prevent faked/forged source IP addresses.
- `heartbat challenge` cotnains 32-bit value, used in heartbeat request to prevent faked/forged source IP addresses.
* Response: `S2M_INFO`.
#### `M2S_NAT_CONNECT`
Master server's message with client IP address and port, used in NAT punching.
* Request: `c <IP:Port>`
* Response: `S2C_INFO` to a specified client address.
## Client and game server
### Client to Server
#### `C2S_BANDWIDTHTEST`
Used to figure out network MTU. The message is optional and server might choose to not implement it or respond with challenge.
* Request, in ASCII: `bandwidth <version> <max_size>`
- `version` must be 49, as text.
- `max_size` is requested maximum packet size.
* Possible responses:
- `S2C_BANDWIDTHTEST`
- `S2C_CHALLENGE`
- `A2A_PRINT` followed by `S2C_REJECT`
- `S2C_ERRORMSG` (as FWGS extension) followed by `A2A_PRINT` and `S2C_REJECT`.
#### `C2S_GETCHALLENGE`
Used to validate client's address to prevent faked/forged source IP addresses.
* Header: `\xff\xff\xff\xff`
* Request, in ASCII: `getchallenge steam`
- `steam` argument is optional and can be ignored by the server, as it's only kept for compatibility with similar GoldSrc 48 message.
* Possible responses:
- `S2C_CHALLENGE`
#### `C2S_CONNECT`
Used to build a connection with the server.
* Header: `\xff\xff\xff\xff`
* Request, in ASCII: `connect <version> <challenge> "<protinfo>" "<userinfo>"`
- `version` must be 49, as text.
- `challenge` must be challenge value, as text.
- `protinfo` is a Quake info string, containing protocol extensions and other connection information.
- `uuid` is this client's unique ID (FWGS extension) hasheed with MD5.
- `qport` is random integer value from 1 to 65535, unique for this engine run.
- `ext` is an integer value OR'ed with requested protocol extensions. Currently only extension is `NET_EXT_SPLITSIZE` with the value of `1`, which tells server to split messages based on `cl_dlmax` value from `userinfo`.
- `userinfo` contains initial user info, encoded as Quake info string.
* Possible responses:
- `A2A_PRINT` followed by `S2C_REJECT`
- `S2C_ERRORMSG` (as FWGS extension) followed by `A2A_PRINT` and `S2C_REJECT`.
- `S2C_CONNECTION`
### Server to Client
#### `S2C_BANDWIDTHTEST`
* Request: `testpacket<crc><blob>`
- `crc` is 32-bit CRC of `blob`
- `blob` random data
* There is no required response to this message
Total message size doesn't exceed request max size.
#### `S2C_CHALLENGE`
* Request, in ASCII: `challenge <value>`
- `value` is challenge value that client must include in it's response
* Response: `C2S_CONNECT`
#### `S2C_CONNECTION`
* Request, in ASCII: `client_connect <protinfo>`
- `protinfo` is an optional Quake info string, contains following optional fields:
- `ext` is an integer value OR'ed with allowed protocol extension. Bit fields match requested in `ext` field in `C2S_CONNECT`
- `cheats` set to 1 if server allows cheats otherwise 0
* Response: there is no out of band from the client but client will proceed to building netchan and switch client-server interaction to it.
#### `S2C_ERRORMSG`
Show client error message. Doesn't mean connection reject, only used for UI.
* Request, in ASCII: `errormsg <message>`
- `message` contains error message
* Response: none
#### `S2C_REJECT`
Client has been rejected in connection.
* Request, in ASCII: `disconnect`
* Response: client can cope, get depressed or mentally tell server to fuck off.

View File

@@ -1,3 +0,0 @@
# Xash3D 49 netchan protocol
TBD...

View File

@@ -962,57 +962,53 @@ Client: https://github.com/Velaron/cs16-client/
Server: https://github.com/rehlds/ReGameDLL_CS
15. **[Crack-Life](https://www.moddb.com/mods/crack-life/downloads/crack-life)**
To run this mod on specific platforms you may be need to compile libraries from **cracklife** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
16. **[Crack-Life: Campaign Mode](https://www.moddb.com/mods/crack-life/downloads/crack-life-campaign-mode)**
15. **[Crack-Life: Campaign Mode](https://www.moddb.com/mods/crack-life)**
To run this mod on specific platforms you may be need to compile libraries from **clcampaign** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
17. **[Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)**
16. **[Deathmatch Classic](https://store.steampowered.com/app/40/Deathmatch_Classic/)**
Steam version already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
18. **[Delta Particles](https://www.moddb.com/mods/half-life-delta)**
17. **[Delta Particles](https://www.moddb.com/mods/half-life-delta)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
19. **[Escape from the Darkness](https://www.moddb.com/mods/escape-from-the-darkness)**
18. **[Escape from the Darkness](https://www.moddb.com/mods/escape-from-the-darkness)**
To run this mod on specific platforms you may be need to compile libraries from **eftd** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
20. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
19. **[Gang Wars](https://www.moddb.com/mods/gangwars)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
21. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
20. **[Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)**
To run this mod on specific platforms you may be need to compile libraries from **bshift** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
22. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
21. **[Half-Life: Decay](https://www.moddb.com/mods/half-life-decay)**
Currently, you can compile mod libraries for x86 Linux from **decay-pc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Support for other platforms may be available later.
23. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
22. **[Half-Life: Echoes](https://www.moddb.com/mods/half-life-echoes)**
To run this mod on specific platforms you may be need to compile libraries from **echoes** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
24. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
23. **[Half-Life: Field Intensity](https://www.moddb.com/mods/field-intensity)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
25. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
24. **Half-Life: Gravgun** (unfinished) by *mittorn*, *a1batross* and *Solexid*
*Support temporary abandoned*
@@ -1022,163 +1018,163 @@ Currently, MSVC is not supported, use MinGW if you need build for Windows.
Mod files: [1](http://mittorn.fwgs.ru/coop-entpatches/), [2](http://mittorn.fwgs.ru/ggm/), [3](https://github.com/nillerusr/gravgun-extras).
26. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
25. **[Half-Life: Induction 1.2](https://www.moddb.com/mods/half-life-induction)**
To run this mod on specific platforms you may be need to compile libraries from **induction_1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
27. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
26. **[Half-Life: Invasion](https://www.moddb.com/mods/half-life-invasion)**
This mod supports x86 Linux.
Support for other platforms may be available later.
28. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
27. **[Half-Life: Intense Force](https://www.moddb.com/downloads/intense-force)**
This mod already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **intense_force** branch of [halflife-featureful](https://github.com/FreeSlave/halflife-featureful).
29. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
28. **[Half-Life: Opposing Force](https://store.steampowered.com/app/50/HalfLife_Opposing_Force/)**
Steam version already supports x86 Linux.
To run this mod on specific platforms you may be need to compile libraries from **opfor** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
30. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
29. **[Half-Life: Quest mod](https://csm.dev/threads/half-life-the-quest-mod-isxodniki.38030/)**
To run this mod on specific platforms you may be need to compile libraries from **sci** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
31. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
30. **[Half-Life: TopDown](https://www.moddb.com/mods/half-life-top-downs)**
To run this mod on specific platforms you may be need to compile libraries from **topdown** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
32. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
31. **[Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)**
To run this mod on specific platforms you may be need to compile libraries from **hl_urbicide** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
33. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
32. **[Half-Life: Visitors](https://www.moddb.com/mods/half-life-visitors)**
To run this mod on specific platforms you may be need to compile libraries from **visitors** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
34. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
33. **[Half-Rats: Parasomnia](https://www.moddb.com/mods/half-rats-parasomnia/downloads/half-rats-parasomnia-v10b-steamlinux)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
35. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
34. **[Half-Screwed: Death and Rebirth](https://www.moddb.com/mods/half-screwed)**
To run this mod on specific platforms you may be need to compile libraries from **half-screwed** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
36. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
35. **[Half-Secret](https://www.moddb.com/mods/half-secret)**
To run this mod on specific platforms you may be need to compile libraries from **half-secret** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
37. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
36. **[Natural Selection](https://www.moddb.com/mods/natural-selection)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
38. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
37. **[Night at the Office](https://www.moddb.com/mods/night-at-the-office)**
To run this mod on specific platforms you may be need to compile libraries from **noffice** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
39. **[Paranoia](https://www.moddb.com/mods/paranoia)**
38. **[Paranoia](https://www.moddb.com/mods/paranoia)**
*Support temporary abandoned*
[Source code](https://github.com/FWGS/paranoia_toolkit).
40. **[Poke646](https://poke646.com/)**
39. **[Poke646](https://poke646.com/)**
To run this mod on specific platforms you may be need to compile libraries from **poke646** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
41. **[Poke646: Vendetta](https://poke646.com/)**
40. **[Poke646: Vendetta](https://poke646.com/)**
To run this mod on specific platforms you may be need to compile libraries from **poke646_vendetta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
42. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
41. [PrimeXT](https://snmetamorph.github.io/PrimeXT/)
[Source code](https://github.com/SNMetamorph/PrimeXT)
43. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
42. **[Quake Remake](https://www.moddb.com/games/quake-remake)**
*Support was fully abandoned due Quake Wrapper release.*
[Actual source code](https://github.com/FWGS/quakeremake)
44. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
43. **[Rebellion](https://www.moddb.com/mods/rebellion1)**
To run this mod on specific platforms you may be need to compile libraries from **rebellion** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
45. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
44. **[Residual Life](https://www.moddb.com/mods/hl-residual-life)**
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
46. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
45. **[Residual Point](https://www.moddb.com/mods/hl-residual-point)**
To run this mod on specific platforms you may be need to compile libraries from **residual_point** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
47. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
46. **[Ricochet](https://store.steampowered.com/app/60/Ricochet/)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
48. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
47. [Sewer](https://www.moddb.com/games/half-life/addons/sewer-beta)
To run this mod on specific platforms you may be need to compile libraries from **sewer_beta** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
49. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
48. [Spirit of Half-Life 1.2](https://www.moddb.com/mods/spirit-of-half-life)
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
50. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
49. **[Swiss Cheese Halloween](https://www.moddb.com/mods/half-life-halloween-mod)**
To run this mod on specific platforms you may be need to compile libraries from **halloween** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
51. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
50. **[Team Fortress Classic](https://store.steampowered.com/app/20/Team_Fortress_Classic/)**
This mod already supports x86 Linux.
Currently, only source code of [client part](https://github.com/Velaron/tf15-client) is available.
52. **[The Gate](https://www.moddb.com/mods/the-gate)**
51. **[The Gate](https://www.moddb.com/mods/the-gate)**
To run this mod on specific platforms you may be need to compile libraries from **thegate** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
53. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
52. **[They Hunger: Trilogy](https://www.moddb.com/mods/they-hunger)**
To run this mod on specific platforms you may be need to compile libraries from **theyhunger** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
54. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
53. **[ThreeWave CTF](https://www.moddb.com/games/deathmatch-classic/downloads/threewave-ctf)**
To run this mod on specific platforms you may be need to compile libraries from **dmc** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
55. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
54. **[Times of Troubles](https://www.moddb.com/mods/times-of-troubles)**
To run this mod on specific platforms you may be need to compile libraries from **tot** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
56. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
55. [XashXT](https://csm.dev/threads/xashxt-0-65-rev-4-release-stable.38319/)
*Support was fully abandoned due PrimeXT development*
[Source code](https://github.com/FWGS/XashXT-FWGS/)
57. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
56. **[X-Half-Life DeathMatch](https://www.moddb.com/mods/xdm)**
This mod already supports x86 Linux.
Support for other platforms may be available later.
58. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
57. **[Xen-Warrior](https://www.moddb.com/mods/xen-warrior)**
To run this mod on specific platforms you may be need to compile libraries from **sohl1.2** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).
Don't forget to enable XENWARRIOR build option!!!
59. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
58. [Zombie-X](https://www.moddb.com/mods/zombie-x-10-final)
To run this mod on specific platforms you may be need to compile libraries from **zombie-x** branch of [hlsdk-portable](https://github.com/FWGS/hlsdk-portable).

View File

@@ -1,6 +1,6 @@
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
[![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) \
[![Discord Server](https://img.shields.io/discord/355697768582610945?logo=Discord&label=International%20Discord%20chat)](http://xash.su/discord/) [![Russian speakers Telegram Chat](https://img.shields.io/badge/Russian_speakers_Telegram_chat-gray?logo=Telegram)](https://t.me/flyingwithgauss) \
[![Discord Server](https://img.shields.io/discord/355697768582610945?logo=Discord&label=International%20Discord%20chat)](http://fwgsdiscord.mentality.rip/) [![Russian speakers Telegram Chat](https://img.shields.io/badge/Russian_speakers_Telegram_chat-gray?logo=Telegram)](https://t.me/flyingwithgauss) \
[![Download Daily Build](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
@@ -41,12 +41,10 @@ For additional info, run Xash3D with `-help` command line key.
1) Copy `valve` directory to a folder named `xash` in the Internal storage.
2) Run games from within the app.
## Reporting issues
## Contributing
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html.
* Issues are accepted in both English and Russian.
* They are only accepted if you run legally acquired product (e.g. Half-Life in Steam).
## Contributing code
* Check the CONTRIBUTING.md file.
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
@@ -83,11 +81,11 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
##### RedHat/Fedora
* Only for 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL3-devel.i686 sdl2-compat-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686 libvorbis-devel.i686 opusfile-devel.i686 libogg-devel.i686`.
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686 libvorbis-devel.i686 opusfile-devel.i686 libogg-devel.i686`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL3-devel sdl2-compat-devel opus-devel freetype-devel bzip2-devel libvorbis-devel opusfile-devel libogg-devel`.
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel libvorbis-devel opusfile-devel libogg-devel`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
@@ -100,16 +98,6 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
#### iOS/iPadOS
* Install Xcode from the appstore.
* Install [Homebrew package manager](https://brew.sh).
* Install build dependencies by running: `brew install python`.
* Clone the SDL2 repo `$ git clone --recursive https://github.com/libsdl-org/SDL.git -b SDL2` and compile the iOS framework by navigating to SDL/Xcode/SDL and opening the Xcode project.
* Clone this repository: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
### Building
#### Windows (Visual Studio)
0) Open command line.
@@ -128,17 +116,4 @@ If compiling 32-bit on amd64, make sure `PKG_CONFIG_PATH` from the previous step
3) Install: `./waf install --destdir=/path/to/any/output/directory`.
#### Android (Windows/Linux/macOS)
To build you should clone [SDL](https://github.com/libsdl-org/SDL) from `SDL2` branch and [HLSDK-portable](https://github.com/FWGS/hlsdk-portable) `mobile-hacks` branch repositories to 3rdparty folder, after that you should be able to open the project in Android Studio from `android` directory or manually call Gradle to build the APK.
#### iOS/iPadOS (MacOS only)
0) (optional) Examine which build options are available: `./waf --help`.
1) Configure build: `./waf configure --ios --enable-bundled-deps --sdl2 (path/to/SDL2.framework)`, set `--ios-simulator` instead of `--ios` if you want to build for simulator.
2) Compile `./waf build`.
3) Navigate to `build` and copy your compiled SDL2.framework there, then add your game dylibs to `build/ios/libs/(gamedir)/(dlls/cl_dlls)`(You can also run `scripts/ios/buildhlsdk.sh` instead to automatically create an ipa with hlsdk dylibs)
4) Run `scripts/ios/createipa.sh` to create an installable ipa
### Running tests
Tests are enabled with `--enable-tests` passed to `./waf configure` and can be run with `./waf --alltests`.
This builds both standalone unit tests and a separate engine test binary (`xash3d_tests`) that embeds engine-level tests. The engine test binary requires no game assets.
You can just open the `android` folder in Android Studio and build from here, or use `gradlew` to build from command line.

View File

@@ -1,18 +0,0 @@
# Xash3D FWGS Security Policy
## Supported versions
Because we don't have clear release cycle yet, support is only provided to the
latest engine versions from `master` branch. You can use `host_ver` command in
console to fetch detailed info about the engine build.
## Reporting a Vulnerability
If you discover a security vulnerability in this project, it can be reported
privately though `Security` tab on GitHub:
https://github.com/FWGS/xash3d-fwgs/security
Alternatively, you can report them publicly on the `Issues` tab:
https://github.com/FWGS/xash3d-fwgs/issues
In both cases, expect a reply within approximately a week.

View File

@@ -1,4 +1,3 @@
import com.android.build.api.dsl.ApplicationExtension
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import java.time.LocalDateTime
import java.time.Month
@@ -6,11 +5,12 @@ import java.time.temporal.ChronoUnit
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
extensions.configure<ApplicationExtension> {
android {
namespace = "su.xash.engine"
ndkVersion = "29.0.14206865"
ndkVersion = "28.2.13676358"
compileSdk = 35
defaultConfig {
@@ -34,7 +34,7 @@ extensions.configure<ApplicationExtension> {
"--configuration-dir=\${ndk.buildRoot}",
"--ndk-version=\${ndk.moduleNdkVersion}",
"--min-sdk-version=\${ndk.minPlatform}",
"--ndk-root=${androidComponents.sdkComponents.ndkDirectory.get()}",
"--ndk-root=${android.ndkDirectory}",
// shut up, fake options
"-p:Configuration=\${ndk.variantName}",
"-p:Platform=\${ndk.abi}"
@@ -77,8 +77,8 @@ extensions.configure<ApplicationExtension> {
sourceSets {
getByName("main") {
assets.directories.add("../../3rdparty/extras/xash-extras")
java.directories.add("../../3rdparty/SDL/android-project/app/src/main/java")
assets.srcDirs("../../3rdparty/extras/xash-extras")
java.srcDir("../../3rdparty/SDL/android-project/app/src/main/java")
}
}

View File

@@ -29,10 +29,10 @@
<!-- Allow downloading to the external storage on Android 5.1 and older -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
android:maxSdkVersion="22" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- Allow access to Bluetooth devices -->
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->

View File

@@ -15,9 +15,6 @@ import org.libsdl.app.SDLActivity;
import su.xash.engine.util.AndroidBug5497Workaround;
import java.util.Arrays;
import java.util.List;
public class XashActivity extends SDLActivity {
private boolean mUseVolumeKeys;
private String mPackageName;
@@ -152,7 +149,6 @@ public class XashActivity extends SDLActivity {
String argv = getIntent().getStringExtra("argv");
if (argv == null) argv = "-console -log";
return argv.split(" ");
}
}

View File

@@ -6,36 +6,28 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.core.net.toUri
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import su.xash.engine.R
import android.net.Uri
import su.xash.engine.XashActivity
import java.io.File
import java.io.FileInputStream
import java.util.Arrays
import android.util.Log
class Game(val ctx: Context, val basedir: File, val gameInfoFile: File) {
class Game(val ctx: Context, val basedir: File) {
private var iconName = "game.ico"
var title = "Unknown Game"
var icon: Bitmap? = null
var cover: Bitmap? = null
val mobileHacksGames = arrayOf("aom", "bdlands", "biglolly", "bshift", "caseclosed",
"hl_urbicide", "induction", "redempt", "secret",
"sewer_beta", "tot", "valve", "vendetta")
// a1ba: follow the behavior of Xash3D's game_launch.
// for hl mods we put `valve` as game directory
// for any other game that's not hl this string must be replaced with your
// main game directory
// mods always use -game command line parameter
var defaultGameDir = "valve"
private val pref = ctx.getSharedPreferences(basedir.name, Context.MODE_PRIVATE)
init {
parseGameInfo(gameInfoFile)
val gameInfo = File(basedir, "gameinfo.txt")
if (gameInfo.exists()) {
parseGameInfo(gameInfo)
} else {
val libListGam = File(basedir, "liblist.gam")
if (libListGam.exists()) parseGameInfo(libListGam)
}
val iconFile = File(basedir, iconName)
if (iconFile.exists()) {
@@ -50,76 +42,14 @@ class Game(val ctx: Context, val basedir: File, val gameInfoFile: File) {
}
fun startEngine(ctx: Context) {
val packageNames = getPackageNamesForGameDir(basedir.name)
var externalGame = false
var commandLineArgs = "";
if (basedir.name != defaultGameDir)
commandLineArgs += "-game ${basedir.name} "
if (packageNames != null) {
if (packageNames.contains("su.xash.engine")) {
commandLineArgs += "-dll @hl "
} else if (packageNames.contains("su.xash.cs16client")) {
if (pref.getBoolean("enable_yapb_bots", true)) {
commandLineArgs += "-dll @yapb "
}
externalGame = true
}
}
commandLineArgs += pref.getString("arguments", "-console -log")
var packageName: String? = null
var gameLibDir: String? = null
if (externalGame && packageNames != null) {
for (pn in packageNames) {
gameLibDir = try {
getGameLibDir(ctx, pn)
} catch(e: PackageManager.NameNotFoundException) {
null
} catch(e: Exception) {
e.printStackTrace()
null
}
if (gameLibDir != null) {
packageName = pn
break
}
}
if (gameLibDir == null) {
MaterialAlertDialogBuilder(ctx).apply {
setTitle(R.string.game_apk_required)
setMessage(R.string.game_apk_message)
setPositiveButton(R.string.game_apk_install) { _, _ ->
val intent = Intent(Intent.ACTION_VIEW,
getDownloadPageForGameDir(basedir.name).toUri())
ctx.startActivity(intent)
}
show()
return
}
}
}
ctx.startActivity(Intent(ctx, XashActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra("gamedir", defaultGameDir)
putExtra("argv", commandLineArgs)
putExtra("gamedir", basedir.name)
putExtra("argv", pref.getString("arguments", "-console -log"))
putExtra("usevolume", pref.getBoolean("use_volume_buttons", false))
putExtra("basedir", basedir.parent)
if (gameLibDir != null) {
putExtra("gamelibdir", gameLibDir)
}
if (packageName != null) {
putExtra("package", packageName)
}
//.putExtra("gamelibdir", getGameLibDir(context))
//.putExtra("package", getPackageName()) }
})
}
@@ -140,50 +70,44 @@ class Game(val ctx: Context, val basedir: File, val gameInfoFile: File) {
}
}
private fun getPackageNamesForGameDir(gamedir: String): Array<String>? {
if (gamedir.equals("cstrike", ignoreCase = true)
|| gamedir.equals("czero", ignoreCase = true))
return arrayOf("su.xash.cs16client.test", "su.xash.cs16client")
if (gamedir.equals("tfc", ignoreCase = true))
return arrayOf("su.xash.tf15client.test", "su.xash.tf15client")
// mobile_hacks hlsdk-portable branch allows us to have few more mods out of the box
if (mobileHacksGames.any { it.equals(gamedir, ignoreCase = true) })
return arrayOf("su.xash.engine")
// return if (mDbEntry != null) {
// mDbEntry.getPackageName()
// } else null
private fun getPackageName(): String? {
// return if (mDbEntry != null) {
// mDbEntry.getPackageName()
// } else null
return null
}
private fun getDownloadPageForGameDir(gamedir: String): String {
if (gamedir.equals("cstrike", ignoreCase = true)
|| gamedir.equals("czero", ignoreCase = true))
return "https://github.com/Velaron/cs16-client/releases/download/continuous/CS16Client-Android.apk"
if (gamedir.equals("tfc", ignoreCase = true))
return "https://github.com/Velaron/tf15-client/releases/download/continuous/TF15Client-Android.apk"
// just so we don't return null
return "https://github.com/FWGS/xash3d-fwgs/releases/download/continuous/xash3d-fwgs-android.apk"
}
private fun getGameLibDir(ctx: Context, packageName: String): String? {
val packageInfo: PackageInfo = ctx.packageManager.getPackageInfo(packageName, 0)
return packageInfo.applicationInfo?.nativeLibraryDir
private fun getGameLibDir(ctx: Context): String? {
val pkgName = getPackageName()
if (pkgName != null) {
val pkgInfo: PackageInfo = try {
ctx.packageManager.getPackageInfo(pkgName, 0)
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
ctx.startActivity(
Intent(
Intent.ACTION_VIEW, Uri.parse("market://details?id=$pkgName")
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
)
return null
}
return pkgInfo.applicationInfo?.nativeLibraryDir
}
return ctx.applicationInfo.nativeLibraryDir
}
companion object {
fun getGames(ctx: Context, root: File): List<Game> {
fun getGames(ctx: Context, file: File): List<Game> {
val games = mutableListOf<Game>()
root.listFiles()?.forEach {
if (it.isDirectory) {
val subDirGameInfoFile = checkIfGamedir(it)
if (subDirGameInfoFile != null) {
games.add(Game(ctx, it, subDirGameInfoFile))
if (checkIfGamedir(file)) {
games.add(Game(ctx, file))
} else {
file.listFiles()?.forEach {
if (it.isDirectory) {
if (checkIfGamedir(it)) {
games.add(Game(ctx, it))
}
}
}
}
@@ -191,18 +115,24 @@ class Game(val ctx: Context, val basedir: File, val gameInfoFile: File) {
return games
}
fun checkIfGamedir(gamedir: File): File? {
gamedir.listFiles()?.forEach {
if (it.isFile) {
if (it.name.equals("liblist.gam", ignoreCase = true))
return it
fun checkIfGamedir(file: File): Boolean {
if (File(file, "liblist.gam").exists()) return true
if (File(file, "gameinfo.txt").exists()) return true
if (it.name.equals("gameinfo.txt", ignoreCase = true))
return it
}
}
return null
return false
}
}
}
// Intent intent = new Intent("su.xash.engine.MOD");
// for (ResolveInfo info : context.getPackageManager()
// .queryIntentActivities(intent, PackageManager.GET_META_DATA)) {
// String packageName = info.activityInfo.applicationInfo.packageName;
// String gameDir = info.activityInfo.applicationInfo.metaData.getString(
// "su.xash.engine.gamedir");
// Log.d(TAG, "package = " + packageName + " gamedir = " + gameDir);
// }
//public void startEngine(Context context) {
// context.startActivity(new Intent(context, XashActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).putExtra("gamedir", getGameDir()).putExtra("argv", getArguments()).putExtra("usevolume", getVolumeState()).putExtra("gamelibdir", getGameLibDir(context)).putExtra("package", getPackageName()));
//}

View File

@@ -1,8 +1,6 @@
package su.xash.engine.ui.library
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -15,8 +13,7 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AlertDialog
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@@ -28,7 +25,6 @@ import su.xash.engine.R
import su.xash.engine.adapters.GameAdapter
import su.xash.engine.databinding.FragmentLibraryBinding
class LibraryFragment : Fragment(), MenuProvider {
private var _binding: FragmentLibraryBinding? = null
private val binding get() = _binding!!
@@ -42,85 +38,23 @@ class LibraryFragment : Fragment(), MenuProvider {
}
}
private val requiredPermissions = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
val granted = permissions.entries.all { it.value }
if (granted) {
libraryViewModel.reloadGames(requireContext())
} else {
checkStoragePermissions()
}
}
private fun checkStoragePermissions(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (!Environment.isExternalStorageManager()) {
MaterialAlertDialogBuilder(requireContext()).apply {
setTitle(R.string.file_access_required)
setMessage(R.string.file_access_message)
setPositiveButton(R.string.open_settings) { _, _ ->
startActivityForResult.launch(
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).setData(
Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
MaterialAlertDialogBuilder(requireContext()).apply {
setTitle(R.string.file_access_required)
setMessage(R.string.file_access_message)
setPositiveButton(android.R.string.ok) { _, _ ->
startActivityForResult.launch(
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).setData(
Uri.fromParts("package", BuildConfig.APPLICATION_ID, null)
)
}
setNeutralButton(R.string.done_check_permissions) { dialog, _ ->
checkStoragePermissions()
}
setCancelable(false)
show()
return false
)
}
} else {
return true
setCancelable(false)
show()
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val permissionsNeeded = requiredPermissions.filter {
ContextCompat.checkSelfPermission(
requireContext(),
it
) != PackageManager.PERMISSION_GRANTED
}.toTypedArray()
if (!permissionsNeeded.isEmpty()) {
val showRationale = permissionsNeeded.any {
ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(), it)
}
MaterialAlertDialogBuilder(requireContext()).apply {
setTitle(R.string.external_storage_required)
setMessage(R.string.external_storage_message)
setPositiveButton(R.string.open_settings) { _, _ ->
if (showRationale) {
requestPermissionLauncher.launch(permissionsNeeded)
} else {
val intent =
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data =
Uri.fromParts("package", requireContext().packageName, null)
}
startActivity(intent)
}
}
setNeutralButton(R.string.done_check_permissions) { _, _ ->
checkStoragePermissions()
}
setCancelable(false)
show()
}
return false
} else {
return true
}
return false
} else {
return true
}
@@ -173,12 +107,4 @@ class LibraryFragment : Fragment(), MenuProvider {
return false
}
override fun onResume() {
super.onResume()
if (checkStoragePermissions()) {
libraryViewModel.reloadGames(requireContext())
}
}
}

View File

@@ -12,7 +12,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import su.xash.engine.model.Game
import su.xash.engine.util.Nomedia
import java.io.File
class LibraryViewModel(application: Application) : AndroidViewModel(application) {
@@ -40,8 +39,6 @@ class LibraryViewModel(application: Application) : AndroidViewModel(application)
?: (Environment.getExternalStorageDirectory().absolutePath + "/xash")
val root = File(rootPath)
Nomedia.ensureNomedia(root)
_installedGames.postValue(Game.getGames(ctx, root))
_isReloading.postValue(false)
}

View File

@@ -20,12 +20,6 @@ class GameSettingsPreferenceFragment(val game: Game) : PreferenceFragmentCompat(
packageList.setValueIndex(0);
}
if (game.basedir.name.equals("cstrike", ignoreCase = true)
|| game.basedir.name.equals("czero", ignoreCase = true)) {
val enableYaPBBots = findPreference<SwitchPreferenceCompat>("enable_yapb_bots")!!
enableYaPBBots.isVisible = true
}
val separatePackages = findPreference<SwitchPreferenceCompat>("separate_libraries")!!
val clientPackage = findPreference<ListPreference>("client_package")!!
val serverPackage = findPreference<ListPreference>("server_package")!!

View File

@@ -1,52 +0,0 @@
/*
Nomedia.kt - ensure that .nomedia file exists in directory
Copyright (C) 2025 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.
*/
package su.xash.engine.util
import java.io.File
object Nomedia {
fun ensureNomedia(directory: File): Boolean {
try {
// ensure paths exists
if (!directory.exists() && !directory.mkdirs()) {
return false
}
// check if it's a directory
if (!directory.isDirectory) {
return false
}
val nomediaFile = File(directory, ".nomedia")
// if the .nomedia is directory, remove it
if (nomediaFile.isDirectory) {
// it should be empty to be deleted, but that's good
// because this way we're not deleting something important
// (who would stash important files in .nomedia directory though...)
if (!nomediaFile.delete()) {
return false
}
}
// it returns false if file already exists, which is fine for us
nomediaFile.createNewFile()
return true
} catch (e: Exception) {
e.printStackTrace()
return false
}
}
}

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">Xash3D FWGS</string>
<string name="library">Librería</string>
<string name="dedicated_server">Dedicado</string>
<string name="app_settings">Ajustes</string>
<string name="game_settings">Ajustes del juego</string>
<string name="game_settings_command_line">Argumentos de la línea de comandos</string>
<string name="game_settings_volume_buttons">Usar botones de volumen en el juego</string>
<string name="preferences_package_name">Paquete de librerías</string>
<string name="preferences_separate_libraries">Librerías de paquetes separados</string>
<string name="preferences_client_package">Paquete de cliente</string>
<string name="preferences_server_package">Paquete de servidor</string>
<string name="preferences_use_icons">Usar iconos en lugar de fondos</string>
<string name="game_data_location">Ubicación de los datos del juego</string>
<string name="file_access_required">Se requiere acceso a todos los archivos</string>
<string name="file_access_message">Se requiere acceso a todos los archivos para que la aplicación funcione correctamente.</string>
<string name="select_current_directory">Seleccionar directorio actual</string>
<string name="external_storage_required">Se requiere acceso al almacenamiento externo</string>
<string name="external_storage_message">Se requiere acceso al almacenamiento externo para que la aplicación funcione correctamente.</string>
</resources>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">Xash3D FWGS</string>
<string name="library">Bibliothèque</string>
<string name="dedicated_server">Dédié</string>
<string name="app_settings">Paramètres</string>
<string name="game_settings">Paramètres du jeu</string>
<string name="game_settings_command_line">Arguments de ligne de commande</string>
<string name="game_settings_volume_buttons">Utiliser les boutons de volume dans le jeu</string>
<string name="game_settings_yapb_bots">Activer les bots YaPB (Uniquement pour CS)</string>
<string name="preferences_package_name">Paquet de bibliothèques</string>
<string name="preferences_separate_libraries">Bibliothèques de paquets séparés</string>
<string name="preferences_client_package">Paquet client</string>
<string name="preferences_server_package">Paquet serveur</string>
<string name="preferences_use_icons">Utiliser des icônes au lieu d\'arrière-plans</string>
<string name="game_data_location">Emplacement des données du jeu</string>
<string name="file_access_required">L\'accès à tous les fichiers est requis</string>
<string name="file_access_message">L\'accès à tous les fichiers est requis pour que l\'application fonctionne correctement.</string>
<string name="select_current_directory">Sélectionner le répertoire actuel</string>
<string name="external_storage_required">L\'accès au stockage externe est requis</string>
<string name="external_storage_message">L\'accès au stockage externe est requis pour que l\'application fonctionne correctement.</string>
<string name="open_settings">Ouvrir les paramètres</string>
<string name="done_check_permissions">Terminé ! Vérifier les permissions</string>
<string name="game_apk_required">Nécessite un APK de bibliothèques de jeu</string>
<string name="game_apk_message">Pour lancer ce jeu, vous devez installer un APK additionnel</string>
<string name="game_apk_install">Télécharger</string>
</resources>

View File

@@ -6,15 +6,9 @@
<string name="game_settings">Configurações do jogo</string>
<string name="game_settings_command_line">Argumentos de linha de comando</string>
<string name="game_settings_volume_buttons">Usar botões de volume no jogo</string>
<string name="preferences_package_name">Pacote de bibliotecas</string>
<string name="preferences_package_name">Bibliotecas de pacotes</string>
<string name="preferences_separate_libraries">Bibliotecas de pacotes separados</string>
<string name="preferences_client_package">Pacote do cliente</string>
<string name="preferences_server_package">Pacote do servidor</string>
<string name="preferences_use_icons">Usar ícones em vez de fundos</string>
<string name="game_data_location">Local dos dados do jogo</string>
<string name="file_access_required">Acesso a todos os arquivos necessário</string>
<string name="file_access_message">É necessário acesso a todos os arquivos para que o aplicativo funcione corretamente.</string>
<string name="select_current_directory">Selecionar diretório atual</string>
<string name="external_storage_required">Acesso ao armazenamento externo necessário</string>
<string name="external_storage_message">É necessário acesso ao armazenamento externo para que o aplicativo funcione corretamente.</string>
<string name="preferences_client_package">Pacotes de Cliente</string>
<string name="preferences_server_package">Pacotes de Servidor</string>
<string name="preferences_use_icons">Usar ícones ao inves de imagens de fundo</string>
</resources>

View File

@@ -6,21 +6,9 @@
<string name="game_settings">Настройки игры</string>
<string name="game_settings_command_line">Аргументы командной строки</string>
<string name="game_settings_volume_buttons">Использовать кнопки громкости</string>
<string name="game_settings_yapb_bots">Включить YaPB ботов (только CS)</string>
<string name="preferences_package_name">Пакет библиотек</string>
<string name="preferences_separate_libraries">Библиотеки из отдельных пакетов</string>
<string name="preferences_client_package">Пакет клиента</string>
<string name="preferences_server_package">Пакет сервера</string>
<string name="preferences_use_icons">Использовать иконки вместо фона</string>
<string name="game_data_location">Расположение игровых данных</string>
<string name="file_access_required">Требуется доступ ко всем файлам</string>
<string name="file_access_message">Для правильной работы приложения требуется доступ ко всем файлам.</string>
<string name="select_current_directory">Выбрать текущую директорию</string>
<string name="external_storage_required">Требуется доступ к внешнему хранилищу</string>
<string name="external_storage_message">Для правильной работы приложения требуется доступ к внешнему хранилищу.</string>
<string name="open_settings">Открыть настройки</string>
<string name="done_check_permissions">Готово! Проверить разрешения</string>
<string name="game_apk_required">Требуется APK с игровыми библиотеками</string>
<string name="game_apk_message">Чтобы запустить эту игру, нужно установить дополнительный APK</string>
<string name="game_apk_install">Скачать</string>
</resources>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="library"></string>
<string name="dedicated_server">专用服务器</string>
<string name="app_settings">设置</string>
<string name="game_settings">游戏设置</string>
<string name="game_settings_command_line">命令行参数</string>
<string name="game_settings_volume_buttons">在游戏中使用音量按钮</string>
<string name="game_settings_yapb_bots">启用yapb机器人(仅限CS)</string>
<string name="preferences_package_name">数据包</string>
<string name="preferences_separate_libraries">来自独立包的库</string>
<string name="preferences_client_package">客户端包</string>
<string name="preferences_server_package">服务器包</string>
<string name="preferences_use_icons">使用图标代替背景</string>
<string name="game_data_location">游戏数据包路径位置</string>
<string name="file_access_required">需要所有文件访问权限</string>
<string name="file_access_message">应用程序需要所有文件访问权限才能正常运行</string>
<string name="select_current_directory">选择当前目录</string>
<string name="external_storage_required">需要外部存储访问权限</string>
<string name="external_storage_message">应用程序需要外部存储访问权限才能正常运行</string>
<string name="open_settings">打开设置</string>
<string name="done_check_permissions">准备好了!检查权限</string>
<string name="game_apk_required">需要带有游戏库的APK</string>
<string name="game_apk_message">要运行此游戏您需要安装额外的APK</string>
<string name="game_apk_install">下载</string>
</resources>

View File

@@ -7,7 +7,6 @@
<string name="game_settings">Game Settings</string>
<string name="game_settings_command_line">Command-line arguments</string>
<string name="game_settings_volume_buttons">Use volume buttons in-game</string>
<string name="game_settings_yapb_bots">Enable YaPB bots (CS only)</string>
<string name="preferences_package_name">Libraries package</string>
<string name="preferences_separate_libraries">Libraries from separate packages</string>
<string name="preferences_client_package">Client package</string>
@@ -17,11 +16,4 @@
<string name="file_access_required">All-files access required</string>
<string name="file_access_message">All-files access is required for the app to function properly.</string>
<string name="select_current_directory">Select current directory</string>
<string name="external_storage_required">External storage access required</string>
<string name="external_storage_message">External storage access is required for the app to function properly.</string>
<string name="open_settings">Open settings</string>
<string name="done_check_permissions">Done! Check permissions</string>
<string name="game_apk_required">Game code APK required</string>
<string name="game_apk_message">To launch this game, you need additional APK installed</string>
<string name="game_apk_install">Download</string>
</resources>

View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<EditTextPreference
app:defaultValue="-console -log"
app:key="arguments"
@@ -13,13 +12,6 @@
app:layout="@layout/switch_preference"
app:title="@string/game_settings_volume_buttons" />
<SwitchPreferenceCompat
app:key="enable_yapb_bots"
app:layout="@layout/switch_preference"
app:title="@string/game_settings_yapb_bots"
app:defaultValue="true"
app:isPreferenceVisible="false" />
<SwitchPreferenceCompat
app:key="separate_libraries"
app:layout="@layout/switch_preference"

View File

@@ -1,4 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}

View File

@@ -25,6 +25,3 @@ android.nonTransitiveRClass=true
# Enable verbose output for CMake
android.native.buildOutput=verbose
android.uniquePackageNames=false
android.dependency.useConstraints=true
android.r8.strictFullModeForKeepRules=false

View File

@@ -1,13 +0,0 @@
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/10fc3bf1ee0001078a473afe6e43cfdb/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/658299a896470fbb3103ba3a430ee227/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/67a0fee3c4236b6397dcbe8575ca2011/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/39846e8427e64a3824c13e399d7d813c/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/932015f6361ccaead0c6d9b8717ed96e/redirect
toolchainVendor=JETBRAINS
toolchainVersion=21

View File

@@ -1,7 +1,8 @@
[versions]
acraHttp = "5.12.0"
agp = "9.0.1"
agp = "8.11.1"
appcompat = "1.7.1"
kotlin = "2.2.0"
material = "1.12.0"
navigationRuntimeKtx = "2.9.1"
preferenceKtx = "1.2.1"
@@ -19,3 +20,4 @@ swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout"
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

View File

@@ -1,6 +1,6 @@
#Tue Jul 01 19:51:06 EEST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -11,9 +11,6 @@ pluginManagement {
gradlePluginPortal()
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {

View File

@@ -18,20 +18,17 @@ GNU General Public License for more details.
// video backends (XASH_VIDEO)
#define VIDEO_NULL 0
#define VIDEO_SDL 1
#define VIDEO_PSP 2
#define VIDEO_FBDEV 3
#define VIDEO_DOS 4
// audio backends (XASH_SOUND)
#define SOUND_NULL 0
#define SOUND_SDL 1
#define SOUND_PSP 2
#define SOUND_ALSA 3
// input (XASH_INPUT)
#define INPUT_NULL 0
#define INPUT_SDL 1
#define INPUT_PSP 2
#define INPUT_EVDEV 3
// timer (XASH_TIMER)
@@ -40,21 +37,18 @@ GNU General Public License for more details.
#define TIMER_POSIX 2
#define TIMER_WIN32 3
#define TIMER_DOS 4
#define TIMER_PSP 5
// messageboxes (XASH_MESSAGEBOX)
#define MSGBOX_STDERR 0
#define MSGBOX_SDL 1
#define MSGBOX_PSP 2
#define MSGBOX_WIN32 3
#define MSGBOX_NSWITCH 4
// library loading (XASH_LIB)
#define LIB_NULL 0
#define LIB_POSIX 1
#define LIB_WIN32 2
#define LIB_NULL 0
#define LIB_POSIX 1
#define LIB_WIN32 2
#define LIB_STATIC 3
#define LIB_PSP 4
// movies (XASH_AVI)
#define AVI_NULL 0

View File

@@ -16,8 +16,6 @@
#ifndef BEAMDEF_H
#define BEAMDEF_H
#include "xash3d_types.h"
#define FBEAM_STARTENTITY 0x00000001
#define FBEAM_ENDENTITY 0x00000002
#define FBEAM_FADEIN 0x00000004

View File

@@ -12,12 +12,10 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef BSPFILE_H
#define BSPFILE_H
#include <stdint.h>
#include "xash3d_types.h"
/*
==============================================================================
@@ -28,310 +26,288 @@ BRUSH MODELS
*/
// header
#define Q1BSP_VERSION 29 // quake1 regular version (beta is 28)
#define HLBSP_VERSION 30 // half-life regular version
#define QBSP2_VERSION (( 'B' << 0 ) | ( 'S' << 8 ) | ( 'P' << 16 ) | ( '2' << 24 ))
#define Q1BSP_VERSION 29 // quake1 regular version (beta is 28)
#define HLBSP_VERSION 30 // half-life regular version
#define QBSP2_VERSION (('B' << 0) | ('S' << 8) | ('P' << 16) | ('2'<<24))
#define IDEXTRAHEADER (( 'X' << 0 ) | ( 'A' << 8 ) | ( 'S' << 16 ) | ( 'H' << 24 ))
#define EXTRA_VERSION 4 // ver. 1 was occupied by old versions of XashXT
// ver. 2 was occupied by old vesrions of P2:savior
// ver. 3 was occupied by experimental versions of P2:savior change fmt
#define IDEXTRAHEADER (('H'<<24)+('S'<<16)+('A'<<8)+'X') // little-endian "XASH"
#define EXTRA_VERSION 4 // ver. 1 was occupied by old versions of XashXT, ver. 2 was occupied by old vesrions of P2:savior
// ver. 3 was occupied by experimental versions of P2:savior change fmt
#define IDBSPXHEADER (( 'B' << 0 ) | ( 'S' << 8 ) | ( 'P' << 16 ) | ( 'X' << 24 ))
#define DELUXEMAP_VERSION 1
#define IDDELUXEMAPHEADER (( 'Q' << 0 ) | ('L' << 8 ) | ( 'I' << 16 ) | ( 'T' << 24 ))
#define DELUXEMAP_VERSION 1
#define IDDELUXEMAPHEADER (('T'<<24)+('I'<<16)+('L'<<8)+'Q') // little-endian "QLIT"
// worldcraft predefined angles
#define ANGLE_UP -1
#define ANGLE_DOWN -2
#define ANGLE_UP -1
#define ANGLE_DOWN -2
// bmodel limits
#define MAX_MAP_HULLS 4 // MAX_HULLS
#define MAX_MAP_HULLS 4 // MAX_HULLS
#define SURF_PLANEBACK BIT( 1 ) // plane should be negated
#define SURF_DRAWSKY BIT( 2 ) // sky surface
#define SURF_DRAWTURB_QUADS BIT( 3 ) // all subidivided polygons are quads
#define SURF_DRAWTURB BIT( 4 ) // warp surface
#define SURF_DRAWTILED BIT( 5 ) // face without lighmap
#define SURF_CONVEYOR BIT( 6 ) // scrolled texture (was SURF_DRAWBACKGROUND)
#define SURF_UNDERWATER BIT( 7 ) // caustics
#define SURF_TRANSPARENT BIT( 8 ) // it's a transparent texture (was SURF_DONTWARP)
#define SURF_PLANEBACK BIT( 1 ) // plane should be negated
#define SURF_DRAWSKY BIT( 2 ) // sky surface
#define SURF_DRAWTURB_QUADS BIT( 3 ) // all subidivided polygons are quads
#define SURF_DRAWTURB BIT( 4 ) // warp surface
#define SURF_DRAWTILED BIT( 5 ) // face without lighmap
#define SURF_CONVEYOR BIT( 6 ) // scrolled texture (was SURF_DRAWBACKGROUND)
#define SURF_UNDERWATER BIT( 7 ) // caustics
#define SURF_TRANSPARENT BIT( 8 ) // it's a transparent texture (was SURF_DONTWARP)
// lightstyle management
#define LM_STYLES 4 // MAXLIGHTMAPS
#define LS_NORMAL 0x00
#define LS_UNUSED 0xFE
#define LS_NONE 0xFF
#define LM_STYLES 4 // MAXLIGHTMAPS
#define LS_NORMAL 0x00
#define LS_UNUSED 0xFE
#define LS_NONE 0xFF
#define MAX_MAP_CLIPNODES_HLBSP 32767
#define MAX_MAP_CLIPNODES_BSP2 524288
// these limis not using by modelloader but only for displaying 'mapstats' correctly
#define MAX_MAP_MODELS 2048 // embedded models
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
#define MAX_MAP_PLANES 131072 // can be increased without problems
#define MAX_MAP_NODES 262144 // can be increased without problems
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_BSP2 // can be increased without problems
#define MAX_MAP_LEAFS 131072 // CRITICAL STUFF to run ad_sepulcher!!!
#define MAX_MAP_VERTS 524288 // can be increased without problems
#define MAX_MAP_FACES 262144 // can be increased without problems
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
#define MAX_MAP_MODELS 2048 // embedded models
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
#define MAX_MAP_PLANES 131072 // can be increased without problems
#define MAX_MAP_NODES 262144 // can be increased without problems
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_BSP2 // can be increased without problems
#define MAX_MAP_LEAFS 131072 // CRITICAL STUFF to run ad_sepulcher!!!
#define MAX_MAP_VERTS 524288 // can be increased without problems
#define MAX_MAP_FACES 262144 // can be increased without problems
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
#define MAX_MAP_ENTITIES 8192 // network limit
#define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo
#define MAX_MAP_EDGES 0x100000 // can be increased but not needed
#define MAX_MAP_SURFEDGES 0x200000 // can be increased but not needed
#define MAX_MAP_TEXTURES 2048 // can be increased but not needed
#define MAX_MAP_MIPTEX 0x2000000 // 32 Mb internal textures data
#define MAX_MAP_LIGHTING 0x2000000 // 32 Mb lightmap raw data (can contain deluxemaps)
#define MAX_MAP_VISIBILITY 0x1000000 // 16 Mb visdata
#define MAX_MAP_FACEINFO 8192 // can be increased but not needed
#define MAX_MAP_ENTITIES 8192 // network limit
#define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo
#define MAX_MAP_EDGES 0x100000 // can be increased but not needs
#define MAX_MAP_SURFEDGES 0x200000 // can be increased but not needs
#define MAX_MAP_TEXTURES 2048 // can be increased but not needs
#define MAX_MAP_MIPTEX 0x2000000 // 32 Mb internal textures data
#define MAX_MAP_LIGHTING 0x2000000 // 32 Mb lightmap raw data (can contain deluxemaps)
#define MAX_MAP_VISIBILITY 0x1000000 // 16 Mb visdata
#define MAX_MAP_FACEINFO 8192 // can be increased but not needs
// quake lump ordering
enum
{
LUMP_ENTITIES = 0,
LUMP_PLANES = 1,
LUMP_TEXTURES = 2, // internal textures
LUMP_VERTEXES = 3,
LUMP_VISIBILITY = 4,
LUMP_NODES = 5,
LUMP_TEXINFO = 6,
LUMP_FACES = 7,
LUMP_LIGHTING = 8,
LUMP_CLIPNODES = 9,
LUMP_LEAFS = 10,
LUMP_MARKSURFACES = 11,
LUMP_EDGES = 12,
LUMP_SURFEDGES = 13,
LUMP_MODELS = 14, // internal submodels
HEADER_LUMPS = 15,
};
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_TEXTURES 2 // internal textures
#define LUMP_VERTEXES 3
#define LUMP_VISIBILITY 4
#define LUMP_NODES 5
#define LUMP_TEXINFO 6
#define LUMP_FACES 7
#define LUMP_LIGHTING 8
#define LUMP_CLIPNODES 9
#define LUMP_LEAFS 10
#define LUMP_MARKSURFACES 11
#define LUMP_EDGES 12
#define LUMP_SURFEDGES 13
#define LUMP_MODELS 14 // internal submodels
#define HEADER_LUMPS 15
// extra lump ordering
enum
{
LUMP_LIGHTVECS = 0, // deluxemap data
LUMP_FACEINFO = 1, // landscape and lightmap resolution info
LUMP_CUBEMAPS = 2, // cubemap description
LUMP_VERTNORMALS = 3, // phong shaded vertex normals
LUMP_LEAF_LIGHTING = 4, // store vertex lighting for statics
LUMP_WORLDLIGHTS = 5, // list of all the virtual and real lights (used to relight models in-game)
LUMP_COLLISION = 6, // physics engine collision hull dump (userdata)
LUMP_AINODEGRAPH = 7, // node graph that stored into the bsp (userdata)
LUMP_SHADOWMAP = 8, // contains shadow map for direct light
LUMP_VERTEX_LIGHT = 9, // store vertex lighting for statics
LUMP_UNUSED0 = 10, // one lump reserved for me
LUMP_UNUSED1 = 11, // one lump reserved for me
EXTRA_LUMPS = 12, // count of the extra lumps
};
#define LUMP_LIGHTVECS 0 // deluxemap data
#define LUMP_FACEINFO 1 // landscape and lightmap resolution info
#define LUMP_CUBEMAPS 2 // cubemap description
#define LUMP_VERTNORMALS 3 // phong shaded vertex normals
#define LUMP_LEAF_LIGHTING 4 // store vertex lighting for statics
#define LUMP_WORLDLIGHTS 5 // list of all the virtual and real lights (used to relight models in-game)
#define LUMP_COLLISION 6 // physics engine collision hull dump (userdata)
#define LUMP_AINODEGRAPH 7 // node graph that stored into the bsp (userdata)
#define LUMP_SHADOWMAP 8 // contains shadow map for direct light
#define LUMP_VERTEX_LIGHT 9 // store vertex lighting for statics
#define LUMP_UNUSED0 10 // one lump reserved for me
#define LUMP_UNUSED1 11 // one lump reserved for me
#define EXTRA_LUMPS 12 // count of the extra lumps
// texture flags
#define TEX_SPECIAL BIT( 0 ) // sky or slime, no lightmap or 256 subdivision
#define TEX_WORLD_LUXELS BIT( 1 ) // alternative lightmap matrix will be used (luxels per world units instead of luxels per texels)
#define TEX_AXIAL_LUXELS BIT( 2 ) // force world luxels to axial positive scales
#define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel
#define TEX_SCROLL BIT( 6 ) // Doom special FX
#define TEX_SPECIAL BIT( 0 ) // sky or slime, no lightmap or 256 subdivision
#define TEX_WORLD_LUXELS BIT( 1 ) // alternative lightmap matrix will be used (luxels per world units instead of luxels per texels)
#define TEX_AXIAL_LUXELS BIT( 2 ) // force world luxels to axial positive scales
#define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel
#define TEX_SCROLL BIT( 6 ) // Doom special FX
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
// ambient sound types
enum
{
AMBIENT_WATER = 0, // waterfall
AMBIENT_SKY, // wind
AMBIENT_SLIME, // never used in quake
AMBIENT_LAVA, // never used in quake
NUM_AMBIENTS, // automatic ambient sounds
AMBIENT_WATER = 0, // waterfall
AMBIENT_SKY, // wind
AMBIENT_SLIME, // never used in quake
AMBIENT_LAVA, // never used in quake
NUM_AMBIENTS, // automatic ambient sounds
};
//
// BSP File Structures
//
typedef struct
{
int32_t fileofs;
int32_t filelen;
int fileofs;
int filelen;
} dlump_t;
typedef struct
{
int32_t version;
dlump_t lumps[HEADER_LUMPS];
int version;
dlump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct
{
int32_t id; // must be little endian XASH
int32_t version;
dlump_t lumps[EXTRA_LUMPS];
int id; // must be little endian XASH
int version;
dlump_t lumps[EXTRA_LUMPS];
} dextrahdr_t;
typedef struct
{
char lumpname[24]; // up to 23 chars, zero-padded
int32_t fileofs;
int32_t filelen;
} dbspx_lump_t;
typedef struct
{
int32_t id; // must be little endian BSPX
int32_t numlumps;
dbspx_lump_t lumps[];
} dbspx_hdr_t;
typedef struct
{
vec3_t mins;
vec3_t maxs;
vec3_t origin; // for sounds or lights
int32_t headnode[MAX_MAP_HULLS];
int32_t visleafs; // not including the solid leaf 0
int32_t firstface;
int32_t numfaces;
vec3_t mins;
vec3_t maxs;
vec3_t origin; // for sounds or lights
int headnode[MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface;
int numfaces;
} dmodel_t;
typedef struct
{
int32_t nummiptex;
int32_t dataofs[4]; // [nummiptex]
int nummiptex;
int dataofs[4]; // [nummiptex]
} dmiptexlump_t;
typedef struct
{
vec3_t point;
vec3_t point;
} dvertex_t;
typedef struct
{
vec3_t normal;
float dist;
int32_t type; // PLANE_X - PLANE_ANYZ ?
vec3_t normal;
float dist;
int type; // PLANE_X - PLANE_ANYZ ?
} dplane_t;
typedef struct
{
int32_t planenum;
int16_t children[2]; // negative numbers are -(leafs + 1), not nodes
int16_t mins[3]; // for sphere culling
int16_t maxs[3];
uint16_t firstface;
uint16_t numfaces; // counting both sides
int planenum;
short children[2]; // negative numbers are -(leafs + 1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
word firstface;
word numfaces; // counting both sides
} dnode_t;
typedef struct
{
int32_t planenum;
int32_t children[2]; // negative numbers are -(leafs+1), not nodes
float mins[3]; // for sphere culling
float maxs[3];
int32_t firstface;
int32_t numfaces; // counting both sides
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
float mins[3]; // for sphere culling
float maxs[3];
int firstface;
int numfaces; // counting both sides
} dnode32_t;
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
typedef struct
{
int32_t contents;
int32_t visofs; // -1 = no visibility info
int contents;
int visofs; // -1 = no visibility info
int16_t mins[3]; // for frustum culling
int16_t maxs[3];
uint16_t firstmarksurface;
uint16_t nummarksurfaces;
short mins[3]; // for frustum culling
short maxs[3];
word firstmarksurface;
word nummarksurfaces;
// automatic ambient sounds
uint8_t ambient_level[NUM_AMBIENTS]; // ambient sound level (0 - 255)
byte ambient_level[NUM_AMBIENTS]; // ambient sound level (0 - 255)
} dleaf_t;
typedef struct
{
int32_t contents;
int32_t visofs; // -1 = no visibility info
int contents;
int visofs; // -1 = no visibility info
float mins[3]; // for frustum culling
float maxs[3];
float mins[3]; // for frustum culling
float maxs[3];
int32_t firstmarksurface;
int32_t nummarksurfaces;
int firstmarksurface;
int nummarksurfaces;
uint8_t ambient_level[NUM_AMBIENTS];
byte ambient_level[NUM_AMBIENTS];
} dleaf32_t;
typedef struct
{
int32_t planenum;
int16_t children[2]; // negative numbers are contents
int planenum;
short children[2]; // negative numbers are contents
} dclipnode_t;
typedef struct
{
int32_t planenum;
int32_t children[2]; // negative numbers are contents
int planenum;
int children[2]; // negative numbers are contents
} dclipnode32_t;
typedef struct
{
float vecs[2][4]; // texmatrix [s/t][xyz offset]
int32_t miptex;
int16_t flags;
int16_t faceinfo; // -1 no face info otherwise dfaceinfo_t
float vecs[2][4]; // texmatrix [s/t][xyz offset]
int miptex;
short flags;
short faceinfo; // -1 no face info otherwise dfaceinfo_t
} dtexinfo_t;
typedef struct
{
char landname[16]; // name of decsription in mapname_land.txt
uint16_t texture_step; // default is 16, pixels\luxels ratio
uint16_t max_extent; // default is 16, subdivision step ((texture_step * max_extent) - texture_step)
int16_t groupid; // to determine equal landscapes from various groups, -1 - no group
char landname[16]; // name of decsription in mapname_land.txt
unsigned short texture_step; // default is 16, pixels\luxels ratio
unsigned short max_extent; // default is 16, subdivision step ((texture_step * max_extent) - texture_step)
short groupid; // to determine equal landscapes from various groups, -1 - no group
} dfaceinfo_t;
typedef uint16_t dmarkface_t; // leaf marksurfaces indexes
typedef int32_t dmarkface32_t; // leaf marksurfaces indexes
typedef word dmarkface_t; // leaf marksurfaces indexes
typedef int dmarkface32_t; // leaf marksurfaces indexes
typedef int32_t dsurfedge_t; // map surfedges
typedef int dsurfedge_t; // map surfedges
// NOTE: that edge 0 is never used, because negative edge nums
// are used for counterclockwise use of the edge in a face
typedef struct
{
uint16_t v[2]; // vertex numbers
word v[2]; // vertex numbers
} dedge_t;
typedef struct
{
int32_t v[2]; // vertex numbers
int v[2]; // vertex numbers
} dedge32_t;
typedef struct
{
uint16_t planenum;
int16_t side;
word planenum;
short side;
int32_t firstedge; // we must support > 64k edges
int16_t numedges;
int16_t texinfo;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
uint8_t styles[LM_STYLES];
int32_t lightofs; // start of [numstyles*surfsize] samples
byte styles[LM_STYLES];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
typedef struct
{
int32_t planenum;
int32_t side;
int planenum;
int side;
int32_t firstedge; // we must support > 64k edges
int32_t numedges;
int32_t texinfo;
int firstedge; // we must support > 64k edges
int numedges;
int texinfo;
// lighting info
uint8_t styles[LM_STYLES];
int32_t lightofs; // start of [numstyles*surfsize] samples
byte styles[LM_STYLES];
int lightofs; // start of [numstyles*surfsize] samples
} dface32_t;
#endif // BSPFILE_H
#endif//BSPFILE_H

View File

@@ -16,8 +16,6 @@
#ifndef CL_ENTITY_H
#define CL_ENTITY_H
#include "const.h"
typedef struct efrag_s
{
struct mleaf_s *leaf;

View File

@@ -1,23 +1,4 @@
/*
com_image.h - image definitions common between client and server
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef COM_IMAGE_H
#define COM_IMAGE_H
#include "xash3d_types.h"
#pragma once
/*
========================================================================
@@ -27,9 +8,21 @@ typically expanded to rgba buffer
NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 == PF_RGB_888
========================================================================
*/
#define ImageRAW( type ) ( type >= PF_RGBA_32 && type <= PF_LUMINANCE )
#define ImageCompressed( type ) ( type >= PF_DXT1 && type <= PF_KTX2_RAW )
#define ImageBigEndian( type ) ( type == PF_BGRA_32 || type == PF_BGR_24 )
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
#define ImageCompressed( type ) \
( type == PF_DXT1 \
|| type == PF_DXT3 \
|| type == PF_DXT5 \
|| type == PF_ATI2 \
|| type == PF_BC4_SIGNED \
|| type == PF_BC4_UNSIGNED \
|| type == PF_BC5_SIGNED \
|| type == PF_BC5_UNSIGNED \
|| type == PF_BC6H_SIGNED \
|| type == PF_BC6H_UNSIGNED \
|| type == PF_BC7_UNORM \
|| type == PF_BC7_SRGB \
|| type == PF_KTX2_RAW )
typedef enum
{
@@ -57,20 +50,11 @@ typedef enum
PF_TOTALCOUNT, // must be last
} pixformat_t;
typedef enum
{
RF_COMPRESSED,
RF_RGBA,
RF_BGRA,
RF_BGR,
RF_LUMINANCE
} rawformat_t;
typedef struct bpc_desc_s
{
int format; // pixelformat
char name[16]; // used for debug
rawformat_t rawformat;
uint glFormat; // RGBA format
int bpp; // channels (e.g. rgb = 3, rgba = 4)
} bpc_desc_t;
@@ -86,8 +70,6 @@ typedef enum
IL_OVERVIEW = BIT(6), // overview required some unque operations
IL_LOAD_PLAYER_DECAL = BIT(7), // special mode for player decals
IL_KTX2_RAW = BIT(8), // renderer can consume raw KTX2 files (e.g. ref_vk)
IL_ALLOW_WAD3_LUMA = BIT(9), // allow usage of luma textures in wad3 (tilde textures)
IL_HOST_ENDIAN = BIT(10), // buffer is already in host endian, skip byte-swapping
} ilFlags_t;
// goes into rgbdata_t->encode
@@ -117,8 +99,6 @@ typedef enum
IMAGE_MULTILAYER = BIT(8), // to differentiate from 3D texture
IMAGE_ONEBIT_ALPHA = BIT(9), // binary alpha
IMAGE_QUAKEPAL = BIT(10), // image has quake1 palette
IMAGE_PREMULTIPLIED = BIT(11),
IMAGE_PLAYERDECAL = BIT(12), // loaded with IL_LOAD_PLAYER_DECAL (custom player spray)
// Image_Process manipulation flags
IMAGE_FLIP_X = BIT(16), // flip the image by width
@@ -152,4 +132,3 @@ typedef struct rgbdata_s
size_t size; // for bounds checking
} rgbdata_t;
#endif//COM_IMAGE_H

View File

@@ -16,11 +16,9 @@ GNU General Public License for more details.
#ifndef COM_MODEL_H
#define COM_MODEL_H
#include "const.h"
#include "xash3d_types.h"
#include "bspfile.h" // we need some declarations from it
#include "xash3d_mathlib.h" // mplane_t
/*
==============================================================================
@@ -48,6 +46,15 @@ typedef enum
mod_studio
} modtype_t;
typedef struct mplane_s
{
vec3_t normal;
float dist;
byte type; // for fast side tests
byte signbits; // signx + (signy<<1) + (signz<<1)
byte pad[2];
} mplane_t;
typedef struct
{
vec3_t position;
@@ -612,9 +619,9 @@ static inline mnode_t *node_child( const mnode_t *n, int side, const model_t *mo
}
}
return n->children_[side ? 1 : 0];
return n->children_[side];
#else
return n->children_[side ? 1 : 0];
return n->children_[side];
#endif
}

View File

@@ -723,6 +723,8 @@ enum
typedef int func_t;
typedef int string_t;
typedef unsigned short word;
#include "xash3d_types.h"
typedef struct
@@ -735,6 +737,11 @@ typedef struct
unsigned r, g, b, a;
} colorVec;
typedef struct link_s
{
struct link_s *prev, *next;
} link_t;
typedef struct edict_s edict_t;
typedef struct

View File

@@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef CVAR
#define CVAR
#include <stdint.h>
#include STDINT_H
#include "xash3d_types.h"
/*

View File

@@ -26,44 +26,68 @@ SETUP BACKENDS DEFINITIONS
===================================================================
*/
//
// when compiling client, we need to pick video, audio and input implementations
//
#if !XASH_DEDICATED // when compiling client, we need to pick video, audio and input implementations
#if XASH_SDL // we are building with SDL
#define XASH_VIDEO VIDEO_SDL
#define XASH_INPUT INPUT_SDL
#define XASH_SOUND SOUND_SDL
#elif XASH_LINUX // we are building for Linux without SDL, only framebuffer is supported for now
#define XASH_VIDEO VIDEO_FBDEV
#define XASH_INPUT INPUT_EVDEV
#define XASH_SOUND SOUND_ALSA
#if !XASH_DEDICATED
#if XASH_SDL
// we are building using libSDL
#ifndef XASH_VIDEO
#define XASH_VIDEO VIDEO_SDL
#endif // XASH_VIDEO
#ifndef XASH_INPUT
#define XASH_INPUT INPUT_SDL
#endif // XASH_INPUT
#ifndef XASH_SOUND
#define XASH_SOUND SOUND_SDL
#endif // XASH_SOUND
#if XASH_SDL == 2
#ifndef XASH_TIMER
#define XASH_TIMER TIMER_SDL
#endif // XASH_TIMER
#ifndef XASH_MESSAGEBOX
#if !XASH_NSWITCH // SDL2 messageboxes not available
#define XASH_MESSAGEBOX MSGBOX_SDL
#endif
#endif // XASH_MESSAGEBOX
#endif
#elif XASH_LINUX
// we are building for Linux without SDL2, can draw only to framebuffer yet
#ifndef XASH_VIDEO
#define XASH_VIDEO VIDEO_FBDEV
#endif // XASH_VIDEO
#ifndef XASH_INPUT
#define XASH_INPUT INPUT_EVDEV
#endif // XASH_INPUT
#ifndef XASH_SOUND
#define XASH_SOUND SOUND_ALSA
#endif // XASH_SOUND
#define XASH_USE_EVDEV 1
#elif XASH_DOS4GW
#define XASH_VIDEO VIDEO_DOS
#define XASH_REDUCE_FD 1 // usually only 10-20 fds available
#elif XASH_PSP
#define XASH_VIDEO VIDEO_PSP
#define XASH_INPUT INPUT_PSP
#define XASH_SOUND SOUND_PSP
#define XASH_REDUCE_FD 1
#define XASH_NO_TOUCH 1
#define XASH_NO_ZIP 1
#ifndef XASH_VIDEO
#define XASH_VIDEO VIDEO_DOS
#endif
#ifndef XASH_TIMER
#define XASH_TIMER TIMER_DOS
#endif
// usually only 10-20 fds availiable
#define XASH_REDUCE_FD
#endif
#endif // !XASH_DEDICATED
#endif // XASH_DEDICATED
//
// select messagebox implementation
//
#ifndef XASH_MESSAGEBOX
#if XASH_SDL >= 2 && !XASH_NSWITCH // SDL2 messageboxes are not available on NSW
#define XASH_MESSAGEBOX MSGBOX_SDL
#elif XASH_WIN32
#if XASH_WIN32
#define XASH_MESSAGEBOX MSGBOX_WIN32
#elif XASH_NSWITCH
#define XASH_MESSAGEBOX MSGBOX_NSWITCH
#elif XASH_PSP
#define XASH_MESSAGEBOX MSGBOX_PSP
#else // !XASH_WIN32
#define XASH_MESSAGEBOX MSGBOX_STDERR
#endif // !XASH_WIN32
@@ -73,14 +97,8 @@ SETUP BACKENDS DEFINITIONS
// no timer - no xash
//
#ifndef XASH_TIMER
#if XASH_SDL >= 2
#define XASH_TIMER TIMER_SDL
#elif XASH_WIN32
#if XASH_WIN32
#define XASH_TIMER TIMER_WIN32
#elif XASH_DOS4GW
#define XASH_TIMER TIMER_DOS
#elif XASH_PSP
#define XASH_TIMER TIMER_PSP
#else // !XASH_WIN32
#define XASH_TIMER TIMER_POSIX
#endif // !XASH_WIN32
@@ -97,16 +115,14 @@ SETUP BACKENDS DEFINITIONS
#endif
#endif
#if XASH_PSP
#define XASH_PSP LIB_PSP
#elif defined( XASH_STATIC_LIBS )
#define XASH_LIB LIB_STATIC
#define XASH_INTERNAL_GAMELIBS
#define XASH_ALLOW_SAVERESTORE_OFFSETS
#ifdef XASH_STATIC_LIBS
#define XASH_LIB LIB_STATIC
#define XASH_INTERNAL_GAMELIBS
#define XASH_ALLOW_SAVERESTORE_OFFSETS
#elif XASH_WIN32
#define XASH_LIB LIB_WIN32
#define XASH_LIB LIB_WIN32
#elif XASH_POSIX
#define XASH_LIB LIB_POSIX
#define XASH_LIB LIB_POSIX
#endif
//
@@ -133,11 +149,7 @@ Default build-depended cvar and constant values
*/
// Platform overrides
#if XASH_WIN32
// set up windowed by default on Windows to avoid problems with
// Xbox Game Bar
#define DEFAULT_FULLSCREEN "0"
#elif XASH_NSWITCH
#if XASH_NSWITCH
#define DEFAULT_TOUCH_ENABLE "1"
#define DEFAULT_M_IGNORE "1"
#define DEFAULT_MODE_WIDTH 1280
@@ -156,6 +168,12 @@ Default build-depended cvar and constant values
#define DEFAULT_M_IGNORE "1"
#endif // !XASH_MOBILE_PLATFORM && !XASH_NSWITCH
#if XASH_IOS
// this means that libraries are provided with engine, but not in game data
// You need add library loading code to library.c when adding new platform
#define XASH_INTERNAL_GAMELIBS
#endif // XASH_IOS
// Defaults
#ifndef DEFAULT_TOUCH_ENABLE
#define DEFAULT_TOUCH_ENABLE "0"
@@ -178,28 +196,11 @@ Default build-depended cvar and constant values
#endif // DEFAULT_ALLOWCONSOLE
#ifndef DEFAULT_FULLSCREEN
#define DEFAULT_FULLSCREEN "2" // must be a string
#define DEFAULT_FULLSCREEN "1" // must be a string
#endif // DEFAULT_FULLSCREEN
#ifndef DEFAULT_MAX_EDICTS
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
#endif // DEFAULT_MAX_EDICTS
#ifndef DEFAULT_ACCELERATED_RENDERER
#if XASH_PSP
#define DEFAULT_ACCELERATED_RENDERER "gu"
#elif XASH_MOBILE_PLATFORM
#define DEFAULT_ACCELERATED_RENDERER "gles1"
#elif XASH_IOS
#define DEFAULT_ACCELERATED_RENDERER "gles2"
#else // !XASH_MOBILE_PLATFORM
#define DEFAULT_ACCELERATED_RENDERER "gl"
#endif // !XASH_MOBILE_PLATFORM
#endif // DEFAULT_ACCELERATED_RENDERER
#ifndef DEFAULT_SOFTWARE_RENDERER
#define DEFAULT_SOFTWARE_RENDERER "soft" // mittorn's ref_soft
#endif // DEFAULT_SOFTWARE_RENDERER
#endif // DEFAULTS_H

31
common/dlight.h Normal file
View File

@@ -0,0 +1,31 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef DLIGHT_H
#define DLIGHT_H
typedef struct dlight_s
{
vec3_t origin;
float radius;
color24 color;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
int key;
qboolean dark; // subtracts light instead of adding
} dlight_t;
#endif//DLIGHT_H

59
common/hltv.h Normal file
View File

@@ -0,0 +1,59 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef HLTV_H
#define HLTV_H
#define TYPE_CLIENT 0 // client is a normal HL client (default)
#define TYPE_PROXY 1 // client is another proxy
#define TYPE_COMMENTATOR 3 // client is a commentator
#define TYPE_DEMO 4 // client is a demo file
// sub commands of svc_hltv:
#define HLTV_ACTIVE 0 // tells client that he's an spectator and will get director commands
#define HLTV_STATUS 1 // send status infos about proxy
#define HLTV_LISTEN 2 // tell client to listen to a multicast stream
// sub commands of svc_director:
#define DRC_CMD_NONE 0 // NULL director command
#define DRC_CMD_START 1 // start director mode
#define DRC_CMD_EVENT 2 // informs about director command
#define DRC_CMD_MODE 3 // switches camera modes
#define DRC_CMD_CAMERA 4 // sets camera registers
#define DRC_CMD_TIMESCALE 5 // sets time scale
#define DRC_CMD_MESSAGE 6 // send HUD centerprint
#define DRC_CMD_SOUND 7 // plays a particular sound
#define DRC_CMD_STATUS 8 // status info about broadcast
#define DRC_CMD_BANNER 9 // banner file name for HLTV gui
#define DRC_CMD_FADE 10 // send screen fade command
#define DRC_CMD_SHAKE 11 // send screen shake command
#define DRC_CMD_STUFFTEXT 12 // like the normal svc_stufftext but as director command
#define DRC_CMD_LAST 12
// HLTV_EVENT event flags
#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important)
#define DRC_FLAG_SIDE (1<<4) //
#define DRC_FLAG_DRAMATIC (1<<5) // is a dramatic scene
#define DRC_FLAG_SLOWMOTION (1<<6) // would look good in SloMo
#define DRC_FLAG_FACEPLAYER (1<<7) // player is doning something (reload/defuse bomb etc)
#define DRC_FLAG_INTRO (1<<8) // is a introduction scene
#define DRC_FLAG_FINAL (1<<9) // is a final scene
#define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data
#define MAX_DIRECTOR_CMD_PARAMETERS 4
#define MAX_DIRECTOR_CMD_STRING 128
#endif//HLTV_H

35
common/kbutton.h Normal file
View File

@@ -0,0 +1,35 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
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 2
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef KBUTTON_H
#define KBUTTON_H
// a1ba: copied from WinQuake/client.h
//
// cl_input
//
typedef struct
{
int down[2]; // key nums holding it down
int state; // low bit is down state
} kbutton_t;
STATIC_CHECK_SIZEOF( kbutton_t, 12, 12 );
#endif // KBUTTON_H

View File

@@ -16,8 +16,6 @@ GNU General Public License for more details.
#ifndef LIGHTSTYLE_H
#define LIGHTSTYLE_H
#include "xash3d_types.h"
typedef struct
{
char pattern[256];

95
common/mathlib.h Normal file
View File

@@ -0,0 +1,95 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
// mathlib.h
#include <math.h>
typedef float vec_t;
typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4]; // x,y,z,w
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
struct mplane_s;
extern vec3_t vec3_origin;
extern int nanmask;
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
#ifndef VECTOR_H
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
#endif
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
#define VectorClear(a) {(a)[0]=0.0;(a)[1]=0.0;(a)[2]=0.0;}
void VectorMA (const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc);
vec_t _DotProduct (vec3_t v1, vec3_t v2);
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out);
void _VectorCopy (vec3_t in, vec3_t out);
int VectorCompare (const vec3_t v1, const vec3_t v2);
float Length (const vec3_t v);
void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross);
float VectorNormalize (vec3_t v); // returns vector length
void VectorInverse (vec3_t v);
void VectorScale (const vec3_t in, vec_t scale, vec3_t out);
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
void AngleVectorsTranspose (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
#define AngleIVectors AngleVectorsTranspose
void AngleMatrix (const vec3_t angles, float (*matrix)[4] );
void AngleIMatrix (const vec3_t angles, float (*matrix)[4] );
void VectorTransform (const vec3_t in1, float in2[3][4], vec3_t out);
void NormalizeAngles( vec3_t angles );
void InterpolateAngles( vec3_t start, vec3_t end, vec3_t output, float frac );
float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 );
void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up);
void VectorAngles( const vec3_t forward, vec3_t angles );
int InvertMatrix( const float * m, float *out );
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane);
float anglemod(float a);
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
(((p)->type < 3)? \
( \
((p)->dist <= (emins)[(p)->type])? \
1 \
: \
( \
((p)->dist >= (emaxs)[(p)->type])?\
2 \
: \
3 \
) \
) \
: \
BoxOnPlaneSide( (emins), (emaxs), (p)))

View File

@@ -27,7 +27,7 @@
// Set this flag for things like broadcast requests, etc. where the engine should not
// kill the request hook after receiving the first response
#define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 )
// 1<<1 is reserved for deprecated xash3d-fwgs extension
#define FNETAPI_LEGACY_PROTOCOL ( 1<<1 ) // xash3d-fwgs extension
struct net_response_s;
typedef void (*net_api_response_func_t) ( struct net_response_s *response );

View File

@@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef NET_ADR_H
#define NET_ADR_H
#include <stdint.h>
#include STDINT_H
// net.h -- quake's interface to the networking layer
// a1ba: copied from Quake-2/qcommon/qcommon.h and modified to support IPv6

53
common/particledef.h Normal file
View File

@@ -0,0 +1,53 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef PARTICLEDEF_H
#define PARTICLEDEF_H
typedef enum
{
pt_static,
pt_grav,
pt_slowgrav,
pt_fire,
pt_explode,
pt_explode2,
pt_blob,
pt_blob2,
pt_vox_slowgrav,
pt_vox_grav,
pt_clientcustom // Must have callback function specified
} ptype_t;
typedef struct particle_s
{
vec3_t org;
short color;
short packedColor;
struct particle_s *next;
vec3_t vel;
float ramp;
float die;
ptype_t type;
void (*deathfunc)( struct particle_s *particle );
// for pt_clientcusttom, we'll call this function each frame
void (*callback)( struct particle_s *particle, float frametime );
// For deathfunc, etc.
unsigned char context;
} particle_t;
#endif//PARTICLEDEF_H

View File

@@ -1,86 +0,0 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
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 2
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef QW_PMOVE_H
#define QW_PMOVE_H
// a1ba: from QW's client/pmove.h
// and modified to keep binary compatibility with
// goldsrc base structs and xash extensions
typedef struct pmplane_s
{
vec3_t normal;
float dist;
} pmplane_t;
STATIC_CHECK_SIZEOF( pmplane_t, 16, 16 );
typedef struct pmtrace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
qboolean inopen, inwater;
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
pmplane_t plane; // surface normal at impact
int ent; // entity the surface is on
vec3_t deltavelocity;
int hitgroup;
} pmtrace_t;
STATIC_CHECK_SIZEOF( pmtrace_t, 68, 68 );
typedef struct movevars_s
{
float gravity;
float stopspeed;
float maxspeed;
float spectatormaxspeed;
float accelerate;
float airaccelerate;
float wateraccelerate;
float friction;
float edgefriction; // goldsrc binary compat
float waterfriction;
float entgravity;
// goldsrc additions
float bounce;
float stepsize;
float maxvelocity;
float zmax;
float waveHeight;
qboolean footsteps;
char skyName[32];
float rollangle;
float rollspeed;
vec3_t skycolor;
vec3_t skyvec;
// xash extensions
int features;
int fog_settings;
float wateralpha;
vec3_t skydir; // unused
float skyangle; // unused
} movevars_t;
STATIC_CHECK_SIZEOF( movevars_t, 160, 160 );
#endif // QW_PMOVE_H

41
common/pmtrace.h Normal file
View File

@@ -0,0 +1,41 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef PM_TRACE_H
#define PM_TRACE_H
typedef struct
{
vec3_t normal;
float dist;
} pmplane_t;
typedef struct pmtrace_s pmtrace_t;
struct pmtrace_s
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
qboolean inopen, inwater; // End point is in empty space or in water
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
pmplane_t plane; // surface normal at impact
int ent; // entity at impact
vec3_t deltavelocity; // Change in player's velocity caused by impact.
// Only run on server.
int hitgroup;
};
#endif//PM_TRACE_H

View File

@@ -17,54 +17,76 @@ GNU General Public License for more details.
#ifndef PORT_H
#define PORT_H
#include "build.h"
#if !XASH_WIN32
#if XASH_APPLE
#include <sys/syslimits.h>
#define OS_LIB_EXT "dylib"
#define OPEN_COMMAND "open"
#elif XASH_EMSCRIPTEN
#define OS_LIB_EXT "wasm"
#define OPEN_COMMAND "???"
#else
#define OS_LIB_EXT "so"
#define OPEN_COMMAND "xdg-open"
#endif
#define OS_LIB_PREFIX "lib"
#define VGUI_SUPPORT_DLL "libvgui_support." OS_LIB_EXT
// Windows-specific
#define __cdecl
#define __stdcall
#define _inline static inline
#if XASH_POSIX
#include <unistd.h>
#if XASH_NSWITCH
#define SOLDER_LIBDL_COMPAT
#include <solder.h>
#elif XASH_PSVITA
#define VRTLD_LIBDL_COMPAT
#include <vrtld.h>
#define O_BINARY 0
#else
#include <dlfcn.h>
#define HAVE_DUP
#define O_BINARY 0
#endif
#define O_TEXT 0
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
#endif
typedef void* HANDLE;
typedef void* HINSTANCE;
typedef struct tagPOINT
{
int x, y;
} POINT;
#else // WIN32
#define open _open
#define read _read
#define alloca _alloca
#define HSPRITE WINAPI_HSPRITE
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#undef HSPRITE
#define OS_LIB_PREFIX ""
#define OS_LIB_EXT "dll"
#define VGUI_SUPPORT_DLL "../vgui_support." OS_LIB_EXT
#define HAVE_DUP
#endif //WIN32
#ifndef XASH_LOW_MEMORY
#define XASH_LOW_MEMORY 0
#endif
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "build.h"
#if XASH_POSIX
#include <unistd.h>
#define OS_LIB_PREFIX "lib"
#endif
#if XASH_APPLE
#include <sys/syslimits.h>
#define OS_LIB_EXT "dylib"
#define OPEN_COMMAND "open"
#elif XASH_POSIX
#define OS_LIB_EXT "so"
#define OPEN_COMMAND "xdg-open"
#elif XASH_WIN32
#define HSPRITE WINAPI_HSPRITE
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX
#include <windows.h>
#undef HSPRITE
#define open _open
#define read _read
#ifndef alloca
#define alloca _alloca
#endif // alloca
#define OS_LIB_PREFIX ""
#define OS_LIB_EXT "dll"
#define OPEN_COMMAND "open"
#elif XASH_PSP
#define OS_LIB_EXT "prx"
#endif
#if !XASH_WIN32
typedef void *HINSTANCE;
typedef struct tagPOINT { int x, y; } POINT; // one nasty function in cdll_int.h needs it
#endif // !XASH_WIN32
#ifndef XASH_LOW_MEMORY
#define XASH_LOW_MEMORY 0
#endif
#endif // PORT_H

View File

@@ -1,118 +0,0 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
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 2
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// client.h -- primary header for client
#ifndef QUAKE_CLIENT_H
#define QUAKE_CLIENT_H
#include <stdint.h>
#include "xash3d_types.h"
// Definitions originally taken from Quake, modified for binary compatibility
typedef struct usercmd_s
{
int16_t lerp_msec; // added in HL
int8_t msec; // added in QW
uint8_t pad1;
vec3_t viewangles;
// intended velocities
float forwardmove;
float sidemove;
float upmove;
uint8_t lightlevel;
uint8_t pad2;
uint16_t buttons; // added in QW
uint8_t impulse;
// added in HL
uint8_t weaponselect;
uint8_t pad3[2];
// unused HL impact stuff, left for modders
// TODO: document how to use them in delta encoding
int32_t reserved[4];
} usercmd_t;
STATIC_CHECK_SIZEOF( usercmd_t, 52, 52 );
typedef struct dlight_s
{
vec3_t origin;
float radius;
struct
{
uint8_t r, g, b;
} color;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
int key; // so entities can reuse same entry
qboolean dark; // subtracts light instead of adding
} dlight_t;
STATIC_CHECK_SIZEOF( dlight_t, 40, 40 );
//
// cl_input
//
typedef struct
{
int down[2]; // key nums holding it down
int state; // low bit is down state
} kbutton_t;
STATIC_CHECK_SIZEOF( kbutton_t, 12, 12 );
typedef enum {
// Quake defined types
pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2,
// added in HL
pt_4x_slowgrav, // 4 times faster than pt_slowgrav
pt_8x_slowgrav, // 8 times faster than pt_slowgrav
pt_custom, // will call think function from particle
} ptype_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct particle_s
{
// driver-usable fields
vec3_t org;
short color; // in HL color is defnied by palette
short unused; // not used in hw
// drivers never touch the following fields
struct particle_s *next;
vec3_t vel;
float ramp;
float die;
ptype_t type;
// HL added fields
void (*on_die)( struct particle_s *p );
void (*think)( struct particle_s *p, float frametime );
unsigned char userdata;
} particle_t;
STATIC_CHECK_SIZEOF( particle_t, 56, 72 );
#endif // QUAKE_CLIENT_H

View File

@@ -16,13 +16,23 @@
#ifndef R_EFX_H
#define R_EFX_H
// particle_t
#if !defined( PARTICLEDEFH )
#include "particledef.h"
#endif
// BEAM
#if !defined( BEAMDEF_H )
#if !defined( BEAMDEFH )
#include "beamdef.h"
#endif
// dlight_t
#if !defined ( DLIGHTH )
#include "dlight.h"
#endif
// cl_entity_t
#if !defined( CL_ENTITY_H )
#if !defined( CL_ENTITYH )
#include "cl_entity.h"
#endif
@@ -104,9 +114,7 @@ typedef struct tempent_s
// baseline.angles - angle velocity
} TEMPENTITY;
typedef struct particle_s particle_t;
typedef struct efx_api_s efx_api_t;
struct dlight_s;
struct efx_api_s
{
@@ -174,8 +182,8 @@ struct efx_api_s
BEAM *(*R_BeamLightning)( float *start, float *end, int modelIndex, float life, float width, float amplitude, float brightness, float speed );
BEAM *(*R_BeamPoints)( float *start, float *end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b );
BEAM *(*R_BeamRing)( int startEnt, int endEnt, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b );
struct dlight_s *(*CL_AllocDlight)( int key );
struct dlight_s *(*CL_AllocElight)( int key );
dlight_t *(*CL_AllocDlight)( int key );
dlight_t *(*CL_AllocElight)( int key );
TEMPENTITY *(*CL_TempEntAlloc)( const float *org, struct model_s *model );
TEMPENTITY *(*CL_TempEntAllocNoModel)( const float *org );
TEMPENTITY *(*CL_TempEntAllocHigh)( const float *org, struct model_s *model );

View File

@@ -16,8 +16,6 @@
#ifndef REF_PARAMS_H
#define REF_PARAMS_H
#include "xash3d_types.h"
typedef struct ref_params_s
{
// output

View File

@@ -16,8 +16,8 @@ GNU General Public License for more details.
#ifndef RENDER_API_H
#define RENDER_API_H
#include <stdint.h>
#include "lightstyle.h"
#include "dlight.h"
#define CL_RENDER_INTERFACE_VERSION 37 // Xash3D 1.0
#define MAX_STUDIO_DECALS 4096 // + unused space of BSP decals
@@ -101,7 +101,7 @@ typedef enum
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
TF_PREMULTIPLIED = (1<<23), // RGBA was stored premultiplied (HL gradient / indexalpha)
// reserved
// reserved
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
TF_ARB_FLOAT = (1<<26), // float textures
@@ -175,7 +175,6 @@ enum movie_parms_e
struct movie_state_s;
struct ref_viewpass_s;
struct dlight_s;
typedef struct render_api_s
{
@@ -184,8 +183,8 @@ typedef struct render_api_s
void (*GetDetailScaleForTexture)( int texture, float *xScale, float *yScale );
void (*GetExtraParmsForTexture)( int texture, byte *red, byte *green, byte *blue, byte *alpha );
lightstyle_t* (*GetLightStyle)( int number );
struct dlight_s* (*GetDynamicLight)( int number );
struct dlight_s* (*GetEntityLight)( int number );
dlight_t* (*GetDynamicLight)( int number );
dlight_t* (*GetEntityLight)( int number );
byte (*LightToTexGamma)( byte color ); // software gamma support
float (*GetFrameTime)( void );

View File

@@ -1,196 +0,0 @@
/*
sound_api.h - Xash3D extension for client sound interface
Copyright (C) 2026 Xash3D FWGS Developers
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
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/>
*/
#ifndef SOUND_API_H
#define SOUND_API_H
#include "xash3d_types.h"
// Experimental implementation, backward compatibility is not guaranteed.
#define CL_SOUND_INTERFACE_VERSION 1
#define FL_VOXWORD_IN_CACHE BIT( 0 ) // if set, it was loaded prior and shouldn't be freed
#define FL_CHAN_USE_LOOP BIT( 0 ) // don't loop default and local sounds
#define FL_CHAN_STATIC_SOUND BIT( 1 ) // use origin instead of fetching entnum's origin
#define FL_CHAN_LOCAL_SOUND BIT( 2 ) // it's a local menu sound (not looped, not paused)
#define FL_CHAN_SENTENCE_FINISHED BIT( 4 ) // if set, finished playing sentence
#define FL_CHAN_FINISHED BIT( 5 ) // if set, finished playing single word
typedef int sound_t;
typedef struct portable_samplepair_s
{
int left;
int right;
} portable_samplepair_t;
typedef struct sfx_s
{
char name[MAX_QPATH];
wavdata_t *cache;
int servercount;
uint hashValue;
struct sfx_s *hashNext;
} sfx_t;
typedef struct voxword_s
{
sfx_t *sfx;
uint16_t volume; // volume percent
uint16_t pitch; // pitch shift percent (keep large for extra chipmunk fun)
uint8_t timecompress; // percent of skipped data (speeds up playback without pitch shift)
uint8_t start; // percent at which playback starts
uint8_t end; // percent at which playback ends
uint8_t flags;
} voxword_t;
typedef struct channel_s
{
char name[16]; // keep sentence name
sfx_t *sfx; // sfx number
vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK)
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
uint flags;
short entnum; // entity soundsource
short master_vol; // 0-255 master volume
short leftvol; // 0-255 left volume
short rightvol; // 0-255 right volume
short basePitch; // base pitch percent (100% is normal pitch playback)
byte word_index;
// HACKHACK: count when this channel became inaudible
// to not free it when it could be respatialized soon
#define MAX_CHANNEL_INAUDIBLE_TIME 0.1f
float inauduble_free_time;
double sample;
double forced_end;
wavdata_t *data;
voxword_t *words; // dynamically allocated, (num_words + 1) entries, null sfx terminates
uintptr_t engine_reserved[8]; // only for engine developers
uintptr_t game_reserved[8]; // free space for game developers
} channel_t;
typedef struct rawchan_s
{
short entnum;
short master_vol;
short leftvol; // 0-255 left volume
short rightvol; // 0-255 right volume
float dist_mult; // distance multiplier (attenuation/clipK)
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
float oldtime; // catch time jumps
uintptr_t engine_reserved[8]; // only for engine developers
uintptr_t game_reserved[8]; // free space for game developers
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t;
typedef struct snd_format_s
{
uint speed;
byte width;
byte channels;
} snd_format_t;
typedef struct snd_globals_s
{
// dma
const char *backend_name;
byte *buffer;
snd_format_t format;
qboolean initialized; // sound engine is active
int samples; // mono samples in buffer
int samplepos; // in mono samples
int paintedtime; // total samples that have been mixed at speed
int soundtime; // total samples that have been played out to hardware at dma speed
// listener (client, camera, etc)
vec3_t origin;
vec3_t forward, right, up;
int entnum;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
// SoundAPI shared pointers
channel_t *const channels;
int max_channels;
int total_channels;
rawchan_t **const raw_channels;
int max_raw_channels;
sound_t ambient_sfx[NUM_AMBIENTS];
qboolean have_ambient_sfx;
} snd_globals_t;
typedef struct voice_audio_info_s
{
uint width;
uint samplerate;
uint frame_size; // in samples
} voice_audio_info_t;
// API from engine to client (client calls these)
typedef struct sound_api_s
{
qboolean (*CL_GetEntitySpatialization)( channel_t *ch );
sfx_t* (*S_GetSfxByHandle)( sound_t handle );
// Voice extensions
void (*pfnS_RawEntSamples)( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol, float attn );
void (*pfnSND_ForceInitMouth)( int entnum );
voice_audio_info_t (*pfnVoice_GetAudioInfo)( void );
} sound_api_t;
// Callbacks from client to engine (engine calls these when custom sound is active)
typedef struct sound_interface_s
{
int version;
qboolean (*pfnS_Init)( snd_globals_t *globals );
void (*pfnS_Shutdown)( void );
void (*pfnS_UpdateSound)( void );
/* Full paint: endtime (sample pairs), dma buffer, paintedtime in/out. Client does mix + transfer to dma.buffer. */
void (*pfnS_PaintChannels)( int endtime );
void (*pfnS_UpdateChannel)( int ch_idx, const channel_t *ch, sound_t handle ); // ch=NULL -> channel freed
void (*pfnS_UpdateRawChannel)( int raw_idx, rawchan_t *ch ); // ch=NULL -> channel freed
void (*pfnS_Spatialize)( channel_t *ch );
void (*pfnS_FreeSound)( sfx_t *sfx, sound_t handle );
} sound_interface_t;
#endif // SOUND_API_H

39
common/usercmd.h Normal file
View File

@@ -0,0 +1,39 @@
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef USERCMD_H
#define USERCMD_H
typedef struct usercmd_s
{
short lerp_msec; // Interpolation time on client
byte msec; // Duration in ms of command
vec3_t viewangles; // Command view angles
// intended velocities
float forwardmove; // Forward velocity
float sidemove; // Sideways velocity
float upmove; // Upward velocity
byte lightlevel; // Light level at spot where we are standing.
unsigned short buttons; // Attack and move buttons
byte impulse; // Impulse command issued
byte weaponselect; // Current weapon id
// Experimental player impact stuff.
int impact_index;
vec3_t impact_position;
} usercmd_t;
#endif//USERCMD_H

View File

@@ -2,28 +2,23 @@
#ifndef XASH_TYPES_H
#define XASH_TYPES_H
#include <wchar.h> // off_t
#include <sys/types.h> // off_t
#include <stdint.h>
#include <assert.h>
#include "build.h"
#include "port.h"
#define MAX_STRING 256 // generic string
#define MAX_VA_STRING 1024 // compatibility macro
#define MAX_SYSPATH 1024 // system filepath
#define MAX_OSPATH 260 // max length of a filesystem pathname
#define CS_SIZE 64 // size of one config string
#define CS_TIME 16 // size of time string
// platform-specific alignment for types, to not break ABI
#if XASH_PSP
#define MAYBE_ALIGNED( x ) __attribute__(( aligned( 16 )))
#if XASH_IRIX
#include <port.h>
#endif
#if !defined( MAYBE_ALIGNED )
#define MAYBE_ALIGNED( x )
#endif // !defined( MAYBE_ALIGNED )
#if XASH_WIN32
#include <wchar.h> // off_t
#endif // _WIN32
#include <sys/types.h> // off_t
#ifdef STDINT_H
#include STDINT_H
#else // !STDINT_H
#include <stdint.h>
#endif // !STDINT_H
#include <assert.h>
typedef uint8_t byte;
typedef float vec_t;
@@ -31,30 +26,13 @@ typedef vec_t vec2_t[2];
#ifndef vec3_t // SDK renames it to Vector
typedef vec_t vec3_t[3];
#endif
typedef vec_t vec4_t[4] MAYBE_ALIGNED( 16 );
typedef vec_t quat_t[4] MAYBE_ALIGNED( 16 );
typedef byte rgba_t[4]; // unsigned byte colorpack
typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4] MAYBE_ALIGNED( 16 );
typedef vec_t matrix4x4[4][4] MAYBE_ALIGNED( 16 );
typedef vec_t vec4_t[4];
typedef vec_t quat_t[4];
typedef byte rgba_t[4]; // unsigned byte colorpack
typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4];
typedef vec_t matrix4x4[4][4];
typedef uint32_t poolhandle_t;
typedef uint16_t word;
typedef uint32_t dword;
typedef char string[MAX_STRING];
typedef off_t fs_offset_t;
#if XASH_WIN32
typedef int fs_size_t; // return type of _read, _write funcs
#else // !XASH_WIN32
typedef ssize_t fs_size_t;
#endif // !XASH_WIN32
typedef unsigned int uint;
typedef void *(*pfnCreateInterface_t)( const char *, int * );
// Quake definition
typedef struct link_s
{
struct link_s *prev, *next;
} link_t;
#undef true
#undef false
@@ -65,77 +43,95 @@ enum { false, true };
#endif
typedef int qboolean;
#if XASH_LOW_MEMORY == 1 || XASH_PSP
#define MAX_QPATH 48
#define MAX_MODS 16
#elif XASH_LOW_MEMORY == 2
#define MAX_QPATH 32 // should be enough for singleplayer
#define MAX_MODS 4
#else // !XASH_LOW_MEMORY
#define MAX_QPATH 64
#define MAX_MODS 512
#endif // !XASH_LOW_MEMORY
#define MAX_STRING 256 // generic string
#define MAX_VA_STRING 1024 // compatibility macro
#define MAX_SYSPATH 1024 // system filepath
#define MAX_MODS 512 // environment games that engine can keep visible
#define BIT( n ) ( 1U << ( n ))
#define BIT64( n ) ( 1ULL << ( n ))
#define BIT( n ) ( 1U << ( n ))
#define BIT64( n ) ( 1ULL << ( n ))
#define SetBits( bit_vector, bits ) (( bit_vector ) |= ( bits ))
#define ClearBits( bit_vector, bits ) (( bit_vector ) &= ~( bits ))
#define FBitSet( bit_vector, bits ) (( bit_vector ) & ( bits ))
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
#ifndef __cplusplus
#ifdef NULL
#undef NULL
#endif
#define NULL ((void *)0)
#endif
// color strings
#define IsColorString( p ) (( p ) && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#undef EXPORT
#if defined( __GNUC__ )
#if defined( __i386__ )
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
#define GAME_EXPORT __attribute__(( force_align_arg_pointer ))
#else // !defined( __i386__ )
#define EXPORT __attribute__(( visibility ( "default" )))
#endif // !defined( __i386__ )
#else
#define EXPORT __attribute__(( visibility ( "default" )))
#define GAME_EXPORT
#endif
#define MALLOC __attribute__(( malloc ))
// added in GCC 11
#if __GNUC__ >= 11
// might want to set noclone due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116893
// but it's easier to not force mismatched-dealloc to error yet
#define MALLOC_LIKE( x, y ) __attribute__(( malloc( x, y )))
#else
#define MALLOC_LIKE( x, y ) __attribute__(( malloc ))
#endif
#define RETURNS_NONNULL __attribute__(( returns_nonnull ))
#if !__clang__ && !__MCST__
// clang has bugged returns_nonnull for functions pointers, it's ignored and generates a warning about objective-c? O_o
// lcc doesn't support it at all
#define PFN_RETURNS_NONNULL RETURNS_NONNULL
#define MALLOC_LIKE( x, y ) MALLOC
#endif
#define NORETURN __attribute__(( noreturn ))
#define NONNULL __attribute__(( nonnull ))
#define RETURNS_NONNULL __attribute__(( returns_nonnull ))
#if __clang__ || __MCST__
// clang has bugged returns_nonnull for functions pointers, it's ignored and generates a warning about objective-c? O_o
// lcc doesn't support it at all
#define PFN_RETURNS_NONNULL
#else
#define PFN_RETURNS_NONNULL RETURNS_NONNULL
#endif
#define FORMAT_CHECK( x ) __attribute__(( format( printf, x, x + 1 )))
#define ALLOC_CHECK( x ) __attribute__(( alloc_size( x )))
#define NO_ASAN __attribute__(( no_sanitize( "address" )))
#define WARN_UNUSED_RESULT __attribute__(( warn_unused_result ))
#define RENAME_SYMBOL( x ) asm( x )
#if !defined( offsetof )
#define offsetof( s, m ) __builtin_offsetof( s, m )
#endif // !defined( offsetof )
#elif defined( _MSC_VER )
#define EXPORT __declspec( dllexport )
#else
#if defined( _MSC_VER )
#define EXPORT __declspec( dllexport )
#define NO_ASAN __declspec( no_sanitize_address )
#else
#define EXPORT
#define NO_ASAN
#endif
#define GAME_EXPORT
#define NORETURN
#define NONNULL
#define RETURNS_NONNULL
#define PFN_RETURNS_NONNULL
#define FORMAT_CHECK( x )
#define ALLOC_CHECK( x )
#define RENAME_SYMBOL( x )
#define MALLOC
#define MALLOC_LIKE( x, y )
#define WARN_UNUSED_RESULT
#endif
#ifdef ARRAYSIZE
#undef ARRAYSIZE
#endif // ARRAYSIZE
#if defined( __has_feature )
#if __has_feature( address_sanitizer )
#define USE_ASAN 1
#endif // __has_feature
#endif // defined( __has_feature )
#define ARRAYSIZE( p ) ( sizeof(( p ))/ sizeof(( p )[0] ))
#if defined( __SANITIZE_ADDRESS__ )
#define USE_ASAN 1
#if defined( __GNUC__ )
#define NO_ASAN __attribute__(( no_sanitize( "address" )))
#elif defined( _MSC_VER )
#define NO_ASAN __declspec( no_sanitize_address )
#endif
#if !defined( USE_ASAN ) && defined( __SANITIZE_ADDRESS__ )
#define USE_ASAN 1
#endif
#if __GNUC__ >= 3
@@ -148,73 +144,11 @@ typedef int qboolean;
#endif
#endif
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
#define XASH_RESTRICT restrict
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions
#define XASH_RESTRICT __restrict
#endif
#if !defined( EXPORT )
#define EXPORT
#endif // !defined( EXPORT )
#if !defined( GAME_EXPORT )
#define GAME_EXPORT
#endif // !defined( GAME_EXPORT )
#if !defined( MALLOC_LIKE )
#define MALLOC_LIKE( x, y )
#endif // !defined MALLOC_LIKE
#if !defined( NO_ASAN )
#define NO_ASAN
#endif // !defined( NO_ASAN )
#if !defined( RETURNS_NONNULL )
#define RETURNS_NONNULL
#endif // !defined( RETURNS_NONNULL )
#if !defined( PFN_RETURNS_NONNULL )
#define PFN_RETURNS_NONNULL
#endif // !defined( PFN_RETURNS_NONNULL )
#if !defined( NORETURN )
#define NORETURN
#endif // !defined( NORETURN )
#if !defined( NONNULL )
#define NONNULL
#endif // !defined( NONNULL )
#if !defined( FORMAT_CHECK )
#define FORMAT_CHECK( x )
#endif // !defined( FORMAT_CHECK )
#if !defined( ALLOC_CHECK )
#define ALLOC_CHECK( x )
#endif // !defined( ALLOC_CHECK )
#if !defined( WARN_UNUSED_RESULT )
#define WARN_UNUSED_RESULT
#endif // !defined( WARN_UNUSED_RESULT )
#if !defined( RENAME_SYMBOL )
#define RENAME_SYMBOL( x )
#endif // !defined( RENAME_SYMBOL )
#if !defined( unlikely ) || !defined( likely )
#define unlikely( x ) ( x )
#define likely( x ) ( x )
#endif // !defined( unlikely ) || !defined( likely )
#if !defined( XASH_RESTRICT )
#define XASH_RESTRICT
#endif
#if !defined( offsetof )
#define offsetof( s, m ) (size_t)&(((s *)0)->m )
#endif // !defined( offsetof )
#if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword
#define STATIC_ASSERT_( ignore, x, y ) static_assert( x, y )
#define STATIC_ASSERT static_assert
@@ -231,41 +165,75 @@ typedef int qboolean;
// at least, statically check size of some public structures
#if XASH_64BIT
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size64, #type " unexpected size" )
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size64, #type " unexpected size" )
#else
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size32, #type " unexpected size" )
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size32, #type " unexpected size" )
#endif
#define Swap32( x ) (((uint32_t)((( x ) & 255 ) << 24 )) + ((uint32_t)(((( x ) >> 8 ) & 255 ) << 16 )) + ((uint32_t)((( x ) >> 16 ) & 255 ) << 8 ) + ((( x ) >> 24 ) & 255 ))
#define Swap16( x ) ((uint16_t)((((uint16_t)( x ) >> 8 ) & 255 ) + (((uint16_t)( x ) & 255 ) << 8 )))
#define Swap32Store( x ) ( x = Swap32( x ))
#define Swap16Store( x ) ( x = Swap16( x ))
#define LittleFourCC( a, b, c, d ) (((uint32_t)( d ) << 24 ) | ((uint32_t)( c ) << 16 ) | ((uint32_t)( b ) << 8 ) | (uint32_t)( a ))
#define BigFourCC( a, b, c, d ) (((uint32_t)( a ) << 24 ) | ((uint32_t)( b ) << 16 ) | ((uint32_t)( c ) << 8 ) | (uint32_t)( d ))
#if XASH_BIG_ENDIAN
#define LittleLong( x ) Swap32( x )
#define LittleShort( x ) Swap16( x )
#define LittleLongSW( x ) Swap32Store( x )
#define LittleShortSW( x ) Swap16Store( x )
#define LittleFloat( x ) SwapFloat( x )
#define BigLong( x ) ( x )
#define BigShort( x ) ( x )
#define BigFloat( x ) ( x )
#define HostFourCC( a, b, c, d ) BigFourCC( a, b, c, d )
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
#define XASH_RESTRICT restrict
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions
#define XASH_RESTRICT __restrict
#else
#define LittleLong( x ) ( x )
#define LittleShort( x ) ( x )
#define LittleFloat( x ) ( x )
#define LittleLongSW( x )
#define LittleShortSW( x )
#define BigLong( x ) Swap32( x )
#define BigShort( x ) Swap16( x )
#define BigFloat( x ) SwapFloat( x )
#define HostFourCC( a, b, c, d ) LittleFourCC( a, b, c, d )
#define XASH_RESTRICT // nothing
#endif
#ifdef XASH_BIG_ENDIAN
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
#define LittleLongSW(x) (x = LittleLong(x) )
#define LittleShort(x) ((short)( (((short)(x) >> 8) & 255) + (((short)(x) & 255) << 8)))
#define LittleShortSW(x) (x = LittleShort(x) )
_inline float LittleFloat( float f )
{
union
{
float f;
unsigned char b[4];
} dat1, dat2;
dat1.f = f;
dat2.b[0] = dat1.b[3];
dat2.b[1] = dat1.b[2];
dat2.b[2] = dat1.b[1];
dat2.b[3] = dat1.b[0];
return dat2.f;
}
#else
#define LittleLong(x) (x)
#define LittleLongSW(x)
#define LittleShort(x) (x)
#define LittleShortSW(x)
#define LittleFloat(x) (x)
#endif
typedef unsigned int dword;
typedef unsigned int uint;
typedef char string[MAX_STRING];
typedef off_t fs_offset_t;
#if XASH_WIN32
typedef int fs_size_t; // return type of _read, _write funcs
#else /* !XASH_WIN32 */
typedef ssize_t fs_size_t;
#endif /* !XASH_WIN32 */
typedef void *(*pfnCreateInterface_t)( const char *, int * );
// config strings are a general means of communication from
// the server to all connected clients.
// each config string can be at most CS_SIZE characters.
#if XASH_LOW_MEMORY == 0
#define MAX_QPATH 64 // max length of a game pathname
#elif XASH_LOW_MEMORY == 2
#define MAX_QPATH 32 // should be enough for singleplayer
#elif XASH_LOW_MEMORY == 1
#define MAX_QPATH 48
#endif
#define MAX_OSPATH 260 // max length of a filesystem pathname
#define CS_SIZE 64 // size of one config string
#define CS_TIME 16 // size of time string
#endif // XASH_TYPES_H

View File

@@ -17,10 +17,8 @@
#define ALIAS_H
#include "build.h"
#include <stdint.h>
#include STDINT_H
#include "synctype.h"
#include "xash3d_types.h"
#include "com_model.h"
/*
==============================================================================

View File

@@ -23,12 +23,6 @@ struct mstudioevent_s;
struct engine_studio_api_s;
struct r_studio_interface_s;
struct sound_api_s;
struct sound_interface_s;
typedef struct sound_api_s sound_api_t;
typedef struct sound_interface_s sound_interface_t;
// NOTE: ordering is important!
typedef struct cldll_func_s
{
@@ -80,9 +74,6 @@ typedef struct cldll_func_s
int (*pfnTouchEvent)( int type, int fingerID, float x, float y, float dx, float dy );
void (*pfnMoveEvent)( float forwardmove, float sidemove );
void (*pfnLookEvent)( float relyaw, float relpitch );
// Sound API
int (*pfnGetSoundInterface)( int version, const sound_api_t *api, sound_interface_t *callback );
int (*pfnVoice_StartChannel)( int samples, byte *data, int entnum );
} cldll_func_t;
#endif//CDLL_EXP_H

View File

@@ -25,6 +25,7 @@ qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *dura
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi );
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet );
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio );
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time );
void AVI_CloseVideo( movie_state_t *Avi );
qboolean AVI_IsActive( movie_state_t *Avi );
void AVI_FreeVideo( movie_state_t *Avi );

View File

@@ -23,6 +23,7 @@ static qboolean avi_initialized;
static poolhandle_t avi_mempool;
#if XASH_AVI == AVI_FFMPEG
#define XASH_FFMPEG_DLOPEN 1
#include "avi_ffmpeg.h"
struct movie_state_s
@@ -221,6 +222,11 @@ int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
return 0;
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
return 0;
}
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
{
if( !Avi->active )
@@ -255,9 +261,9 @@ static void AVI_StreamAudio( movie_state_t *Avi )
rawchan_t *ch = NULL;
// keep the same semantics, when S_RAW_SOUND_SOUNDTRACK doesn't play if S_StartStreaming wasn't enabled
qboolean disable_stream = Avi->entnum == S_RAW_SOUND_SOUNDTRACK ? !snd.streaming : false;
qboolean disable_stream = Avi->entnum == S_RAW_SOUND_SOUNDTRACK ? !s_listener.streaming : false;
if( !snd.initialized || disable_stream || cl.paused || !Avi->cached_audio )
if( !dma.initialized || disable_stream || s_listener.paused || !Avi->cached_audio )
return;
ch = S_FindRawChannel( Avi->entnum, true );
@@ -268,14 +274,14 @@ static void AVI_StreamAudio( movie_state_t *Avi )
ch->master_vol = Avi->volume;
ch->dist_mult = (Avi->attn / SND_CLIP_DISTANCE);
if( ch->s_rawend < snd.soundtime )
ch->s_rawend = snd.soundtime;
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
while( ch->s_rawend < snd.soundtime + ch->max_samples )
while( ch->s_rawend < soundtime + ch->max_samples )
{
size_t copy;
buffer_samples = ch->max_samples - (ch->s_rawend - snd.soundtime);
buffer_samples = ch->max_samples - (ch->s_rawend - soundtime);
file_samples = buffer_samples * ((float)Avi->rate / SOUND_DMA_SPEED);
if( file_samples <= 1 ) return; // no more samples need
@@ -349,10 +355,6 @@ qboolean AVI_Think( movie_state_t *Avi )
qboolean decoded = false;
qboolean flushing = false;
qboolean redraw = false;
if( !Avi->video_ctx )
return false;
const double timebase = (double)Avi->video_ctx->pkt_timebase.den / Avi->video_ctx->pkt_timebase.num;
int64_t curtime = round( Platform_DoubleTime() * timebase );
@@ -382,7 +384,7 @@ qboolean AVI_Think( movie_state_t *Avi )
if(( res = pav_read_frame( Avi->fmt_ctx, Avi->pkt )) >= 0 )
{
if( Avi->pkt->stream_index == Avi->audio_stream && Avi->audio_ctx )
if( Avi->pkt->stream_index == Avi->audio_stream )
{
res = pavcodec_send_packet( Avi->audio_ctx, Avi->pkt );
if( res < 0 )
@@ -444,16 +446,13 @@ qboolean AVI_Think( movie_state_t *Avi )
if( Avi->texture == 0 )
{
int cinTexture = SCR_GetCinematicTexture();
int w = Avi->w >= 0 ? Avi->w : refState.width;
int h = Avi->h >= 0 ? Avi->h : refState.height;
if( redraw )
ref.dllFuncs.GL_UpdateTexture( cinTexture, Avi->xres, Avi->yres, Avi->xres, Avi->yres, Avi->dst, PF_BGRA_32 );
ref.dllFuncs.R_DrawStretchPic( Avi->x, Avi->y, w, h, 0, 0, 1, 1, cinTexture );
ref.dllFuncs.R_DrawStretchRaw( Avi->x, Avi->y, w, h, Avi->xres, Avi->yres, Avi->dst, redraw );
}
else if( redraw && Avi->texture > 0 )
ref.dllFuncs.GL_UpdateTexture( Avi->texture, Avi->xres, Avi->yres, Avi->w, Avi->h, Avi->dst, PF_BGRA_32 );
ref.dllFuncs.AVI_UploadRawFrame( Avi->texture, Avi->xres, Avi->yres, Avi->w, Avi->h, Avi->dst );
if( flushing && !decoded )
return false; // probably hit an EOF
@@ -843,6 +842,11 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi
;
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
return 0;
}
void AVI_CloseVideo( movie_state_t *Avi )
{
;

View File

@@ -26,101 +26,35 @@ GNU General Public License for more details.
#if XASH_FFMPEG_DLOPEN
// using typeof gives more resilience to function declaration changes
// but it's only available in GCC and standardized in C23
#if defined(__GNUC__) || __STDC_VERSION__ >= 202311L
#define SUPPORTED_AVU_VERSION_MAJOR LIBAVUTIL_VERSION_MAJOR
#define SUPPORTED_AVF_VERSION_MAJOR LIBAVFORMAT_VERSION_MAJOR
#define SUPPORTED_AVC_VERSION_MAJOR LIBAVCODEC_VERSION_MAJOR
#define SUPPORTED_SWR_VERSION_MAJOR LIBSWRESAMPLE_VERSION_MAJOR
#define SUPPORTED_SWS_VERSION_MAJOR LIBSWSCALE_VERSION_MAJOR
#define F( func ) \
typedef typeof( func ) func##_t; \
func##_t *p##func
// libavutil
F( avutil_version );
F( av_frame_alloc );
F( av_frame_free );
F( av_frame_ref );
F( av_frame_unref );
F( av_strerror );
F( av_free );
F( av_get_bytes_per_sample );
F( av_get_media_type_string );
F( av_image_alloc );
// libavformat
F( avformat_version );
F( av_find_best_stream );
F( av_read_frame );
F( av_seek_frame );
F( avformat_close_input );
F( avformat_find_stream_info );
F( avformat_open_input );
// libavcodec
F( avcodec_version );
F( av_packet_alloc );
F( av_packet_free );
F( av_packet_unref );
F( avcodec_alloc_context3 );
F( avcodec_find_decoder );
F( avcodec_flush_buffers );
F( avcodec_free_context );
F( avcodec_open2 );
F( avcodec_parameters_to_context );
F( avcodec_receive_frame );
F( avcodec_send_packet );
// libswresample
F( swresample_version );
F( swr_alloc_set_opts2 );
F( swr_convert );
F( swr_free );
F( swr_init );
// libswscale
F( swscale_version );
F( sws_freeContext );
F( sws_getContext );
F( sws_scale );
#undef F
#else // !defined(__GNUC__) && __STDC_VERSION__ < 202311L
// the following symbols were taken from ffmpeg public headers
// on each major ffmpeg uprgade, they must be validated
// ffmpeg guarantees API and ABI compatibility between major versions
// so complain if this gets compiled against unsupported yet version
// the same check will be done in runtime to ensure compatibility
#define SUPPORTED_AVU_VERSION_MAJOR 60
#define SUPPORTED_AVF_VERSION_MAJOR 62
#define SUPPORTED_AVC_VERSION_MAJOR 62
#define SUPPORTED_SWR_VERSION_MAJOR 6
#define SUPPORTED_SWS_VERSION_MAJOR 9
#define SUPPORTED_AVU_VERSION_MAJOR 59
#define SUPPORTED_AVF_VERSION_MAJOR 61
#define SUPPORTED_AVC_VERSION_MAJOR 61
#define SUPPORTED_SWR_VERSION_MAJOR 5
#define SUPPORTED_SWS_VERSION_MAJOR 8
#if SUPPORTED_AVU_VERSION_MAJOR != LIBAVUTIL_VERSION_MAJOR
#error "unsupported libavutil version"
#error
#endif
#if SUPPORTED_AVF_VERSION_MAJOR != LIBAVFORMAT_VERSION_MAJOR
#error "unsupported libavformat version"
#error
#endif
#if SUPPORTED_AVC_VERSION_MAJOR != LIBAVCODEC_VERSION_MAJOR
#error "unsupported libavcodec version"
#error
#endif
#if SUPPORTED_SWR_VERSION_MAJOR != LIBSWRESAMPLE_VERSION_MAJOR
#error "unsupported libswresample version"
#error
#endif
#if SUPPORTED_SWS_VERSION_MAJOR != LIBSWSCALE_VERSION_MAJOR
#error "unsupported libswscale version"
#error
#endif
// libavutil
@@ -171,8 +105,6 @@ void (*psws_freeContext)( struct SwsContext *swsContext );
struct SwsContext *(*psws_getContext)( int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param );
int (*psws_scale)( struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[] );
#endif // defined(__GNUC__) || __STDC_VERSION__ >= 202311L
#else // !XASH_FFMPEG_DLOPEN
#define SUPPORTED_AVU_VERSION_MAJOR LIBAVUTIL_VERSION_MAJOR
@@ -184,9 +116,8 @@ int (*psws_scale)( struct SwsContext *c, const uint8_t *const srcS
// libavutil
#define pavutil_version avutil_version
#define pav_frame_alloc av_frame_alloc
#define pav_frame_free av_frame_free
#define pav_frame_ref av_frame_ref
#define pav_frame_unref av_frame_unref
#define pav_frame_unref av_Frame_unref
#define pav_strerror av_strerror
#define pav_free av_free
#define pav_get_bytes_per_sample av_get_bytes_per_sample

View File

@@ -97,17 +97,7 @@ void CL_PlayCDTrack_f( void )
if( Q_isdigit( pszTrack ))
{
track = bound( 1, Q_atoi( Cmd_Argv( 2 )), MAX_CDTRACKS );
// a1ba: some maps contain cd track set in worldspawn
// forcibly stopping music on changelevel
//
// server notifies us about this in sv_client.c SV_PutClientInServer
// through "cd loop" command
//
// however, it could be set to a track that doesn't contain music data (in CD terms)
// so we catch it here and music will carry over changelevels
if( !COM_StringEmpty( clgame.cdtracks[track-1] ))
S_StartBackgroundTrack( clgame.cdtracks[track-1], clgame.cdtracks[track-1], 0, false );
S_StartBackgroundTrack( clgame.cdtracks[track-1], clgame.cdtracks[track-1], 0, false );
}
else S_StartBackgroundTrack( pszTrack, pszTrack, 0, true );
paused = false;
@@ -146,13 +136,10 @@ void CL_PlayCDTrack_f( void )
}
else if( !Q_stricmp( command, "info" ))
{
int maxTrack = 0;
int i, maxTrack;
for( int i = 0; i < MAX_CDTRACKS; i++ )
{
if( !COM_StringEmpty( clgame.cdtracks[i] ) )
maxTrack++;
}
for( maxTrack = i = 0; i < MAX_CDTRACKS; i++ )
if( COM_CheckStringEmpty( clgame.cdtracks[i] ) ) maxTrack++;
Con_Printf( "%u tracks\n", maxTrack );
if( track )

View File

@@ -16,8 +16,10 @@ GNU General Public License for more details.
#include "common.h"
#include "client.h"
#include "net_encode.h"
#include "particledef.h"
#include "cl_tent.h"
#include "shake.h"
#include "hltv.h"
#include "input.h"
#define MSG_COUNT 32 // last 32 messages parsed
@@ -55,6 +57,9 @@ const char *CL_MsgInfo( int cmd )
case PROTO_CURRENT:
svc_string = svc_strings[cmd];
break;
case PROTO_LEGACY:
svc_string = svc_legacy_strings[cmd];
break;
case PROTO_QUAKE:
svc_string = svc_quake_strings[cmd];
break;
@@ -144,11 +149,7 @@ static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
file_t *fp;
fp = FS_Open( buffer_file, "wb", false );
if( !fp )
{
Con_Printf( S_ERROR "%s: can't open %s for write\n", __func__, buffer_file );
return;
}
if( !fp ) return;
FS_Write( fp, &cls.starting_count, sizeof( int ));
FS_Write( fp, &current_count, sizeof( int ));

View File

@@ -117,6 +117,8 @@ static int CL_GetDemoNetProtocol( connprotocol_t proto )
{
case PROTO_CURRENT:
return PROTOCOL_VERSION;
case PROTO_LEGACY:
return PROTOCOL_LEGACY_VERSION;
case PROTO_QUAKE:
return PROTOCOL_VERSION_QUAKE;
case PROTO_GOLDSRC:
@@ -132,6 +134,8 @@ static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
{
case PROTOCOL_VERSION:
return PROTO_CURRENT;
case PROTOCOL_LEGACY_VERSION:
return PROTO_LEGACY;
case PROTOCOL_VERSION_QUAKE:
return PROTO_QUAKE;
case PROTOCOL_GOLDSRC_VERSION_DEMO:
@@ -1213,7 +1217,7 @@ void CL_StopPlayback( void )
else
{
// let game known about demo state
Cvar_DirectFullSet( &cl_background, "0", FCVAR_READ_ONLY );
Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
cls.state = ca_disconnected;
memset( &cls.serveradr, 0, sizeof( cls.serveradr ) );
cls.set_lastdemo = false;
@@ -1260,7 +1264,8 @@ int GAME_EXPORT CL_GetDemoComment( const char *demoname, char *comment )
return false;
}
if( demohdr.net_protocol != PROTOCOL_VERSION ||
if(( demohdr.net_protocol != PROTOCOL_VERSION &&
demohdr.net_protocol != PROTOCOL_LEGACY_VERSION ) ||
demohdr.dem_protocol != DEMO_PROTOCOL )
{
FS_Close( demfile );
@@ -1475,10 +1480,10 @@ static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, fi
return false;
}
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_GOLDSRC_VERSION_DEMO )
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION && hdr->net_protocol != PROTOCOL_GOLDSRC_VERSION_DEMO )
{
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_GOLDSRC_VERSION );
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );
return false;
}

View File

@@ -200,15 +200,15 @@ particle_t * GAME_EXPORT R_AllocParticle( void (*callback)( particle_t*, float )
p->type = pt_static;
VectorClear( p->vel );
VectorClear( p->org );
p->unused = 0;
p->packedColor = 0;
p->die = cl.time;
p->color = 0;
p->ramp = 0;
if( callback )
{
p->type = pt_custom;
p->think = callback;
p->type = pt_clientcustom;
p->callback = callback;
}
return p;
@@ -254,7 +254,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
p->die = cl.time + life;
p->ramp = tracerlength.value;
p->color = TRACER_COLORINDEX_DEFAULT; // select custom color
p->unused = 255; // alpha
p->packedColor = 255; // alpha
return p;
}
@@ -849,31 +849,6 @@ BEAM * GAME_EXPORT R_BeamEnts( int startEnt, int endEnt, int modelIndex, float l
return pbeam;
}
static qboolean R_BeamVisible( const vec3_t start, const vec3_t end )
{
vec3_t mins, maxs;
for( int i = 0; i < 3; i++ )
{
if( start[i] < end[i] )
{
mins[i] = start[i];
maxs[i] = end[i];
}
else
{
mins[i] = end[i];
maxs[i] = start[i];
}
// don't let it be zero sized
if( mins[i] == maxs[i] )
maxs[i] += 1.0f;
}
return Mod_BoxVisible( mins, maxs, ref.dllFuncs.Mod_GetCurrentVis( ));
}
/*
==============
R_BeamPoints
@@ -886,7 +861,7 @@ BEAM * GAME_EXPORT R_BeamPoints( vec3_t start, vec3_t end, int modelIndex, float
{
BEAM *pbeam;
if( life != 0 && !R_BeamVisible( start, end ))
if( life != 0 && ref.dllFuncs.R_BeamCull( start, end, true ))
return NULL;
pbeam = R_BeamAlloc();
@@ -1143,7 +1118,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
p->die = cl.time + 0.3f;
p->color = colorStart + ( colorMod % colorLength );
p->unused = packedColor;
p->packedColor = packedColor;
colorMod++;
p->type = pt_blob;
@@ -1175,7 +1150,7 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
if( !p ) return;
p->die = cl.time + COM_RandomFloat( 1.0f, 1.4f );
p->unused = packedColor;
p->packedColor = packedColor;
if( i & 1 )
{
@@ -1239,8 +1214,8 @@ particle spray
void GAME_EXPORT R_Blood( const vec3_t org, const vec3_t ndir, int pcolor, int speed )
{
vec3_t pos, dir, vec;
float pspeed = speed * 3.0f;
int i, j;
int pspeed = speed * 3;
particle_t *p;
VectorNormalize2( ndir, dir );
@@ -1250,20 +1225,18 @@ void GAME_EXPORT R_Blood( const vec3_t org, const vec3_t ndir, int pcolor, int s
VectorAddScalar( org, COM_RandomFloat( -3.0f, 3.0f ), pos );
VectorAddScalar( dir, COM_RandomFloat( -0.06f, 0.06f ), vec );
for( j = 0; j < 8; j++ )
for( j = 0; j < 7; j++ )
{
p = R_AllocParticle( NULL );
if( !p ) return;
p->die = cl.time + 1.5f;
p->color = pcolor + COM_RandomLong( 0, 9 );
p->type = pt_8x_slowgrav;
p->type = pt_vox_grav;
VectorAddScalar( pos, COM_RandomFloat( -1.0f, 1.0f ), p->org );
VectorScale( vec, pspeed, p->vel );
}
pspeed -= speed;
}
}
@@ -1290,7 +1263,7 @@ void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t ndir, int pcolor,
if( !p ) return;
p->die = cl.time + 2.0f;
p->type = pt_8x_slowgrav;
p->type = pt_vox_grav;
p->color = pcolor + COM_RandomLong( 0, 9 );
VectorCopy( org, p->org );
@@ -1311,7 +1284,7 @@ void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t ndir, int pcolor,
p->die = cl.time + 3.0f;
p->color = pcolor + COM_RandomLong( 0, 9 );
p->type = pt_4x_slowgrav;
p->type = pt_vox_slowgrav;
VectorCopy( org, p->org );
VectorCopy( dir, p->vel );
@@ -1333,9 +1306,12 @@ void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t ndir, int pcolor,
p->die = cl.time + 3.0f;
p->color = pcolor + COM_RandomLong( 0, 9 );
p->type = pt_4x_slowgrav;
p->type = pt_vox_slowgrav;
p->org[0] = org[0] + COM_RandomFloat( -1.0f, 1.0f );
p->org[1] = org[1] + COM_RandomFloat( -1.0f, 1.0f );
p->org[2] = org[2] + COM_RandomFloat( -1.0f, 1.0f );
VectorAddScalar( org, COM_RandomFloat( -1.0f, 1.0f ), p->org );
VectorCopy( dir, p->vel );
p->vel[2] -= arc;
@@ -1922,8 +1898,8 @@ void GAME_EXPORT R_UserTracerParticle( float *org, float *vel, float life, int c
if(( p = R_AllocTracer( org, vel, life )) != NULL )
{
p->userdata = deathcontext;
p->on_die = deathfunc;
p->context = deathcontext;
p->deathfunc = deathfunc;
p->color = colorIndex;
p->ramp = length;
}
@@ -2020,9 +1996,9 @@ void R_FreeDeadParticles( particle_t **ppparticles )
kill = *ppparticles;
if( kill && kill->die < cl.time )
{
if( kill->on_die )
kill->on_die( kill );
kill->on_die = NULL;
if( kill->deathfunc )
kill->deathfunc( kill );
kill->deathfunc = NULL;
*ppparticles = kill->next;
kill->next = cl_free_particles;
cl_free_particles = kill;
@@ -2039,9 +2015,9 @@ void R_FreeDeadParticles( particle_t **ppparticles )
kill = p->next;
if( kill && kill->die < cl.time )
{
if( kill->on_die )
kill->on_die( kill );
kill->on_die = NULL;
if( kill->deathfunc )
kill->deathfunc( kill );
kill->deathfunc = NULL;
p->next = kill->next;
kill->next = cl_free_particles;
cl_free_particles = kill;
@@ -2178,7 +2154,7 @@ void CL_ThinkParticle( double frametime, particle_t *p )
float grav = frametime * clgame.movevars.gravity * 0.05f;
if( p->type != pt_custom )
if( p->type != pt_clientcustom )
{
// update position.
VectorMA( p->org, frametime, p->vel, p->org );
@@ -2209,7 +2185,7 @@ void CL_ThinkParticle( double frametime, particle_t *p )
p->vel[2] -= grav;
break;
case pt_blob:
if( p->unused == 255 )
if( p->packedColor == 255 )
{
// normal blob explosion
VectorMA( p->vel, dvel, p->vel, p->vel );
@@ -2218,7 +2194,7 @@ void CL_ThinkParticle( double frametime, particle_t *p )
}
// intentionally fallthrough
case pt_blob2:
if( p->unused == 255 )
if( p->packedColor == 255 )
{
// normal blob explosion
p->vel[0] -= p->vel[0] * dvel;
@@ -2241,15 +2217,15 @@ void CL_ThinkParticle( double frametime, particle_t *p )
case pt_slowgrav:
p->vel[2] -= grav;
break;
case pt_8x_slowgrav:
case pt_vox_grav:
p->vel[2] -= grav * 8.0f;
break;
case pt_4x_slowgrav:
case pt_vox_slowgrav:
p->vel[2] -= grav * 4.0f;
break;
case pt_custom:
if( p->think )
p->think( p, frametime );
case pt_clientcustom:
if( p->callback )
p->callback( p, frametime );
break;
}
}

View File

@@ -160,7 +160,7 @@ word CL_EventIndex( const char *name )
{
word i;
if( COM_StringEmptyOrNULL( name ))
if( !COM_CheckString( name ))
return 0;
for( i = 1; i < MAX_EVENTS && cl.event_precache[i][0]; i++ )
@@ -436,8 +436,9 @@ void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
if( proto == PROTO_GOLDSRC )
entity_bits = MAX_GOLDSRC_ENTITY_BITS;
else
entity_bits = MAX_ENTITY_BITS;
else if( proto == PROTO_LEGACY )
entity_bits = MAX_LEGACY_ENTITY_BITS;
else entity_bits = MAX_ENTITY_BITS;
// parse events queue
for( i = 0 ; i < num_events; i++ )

View File

@@ -17,20 +17,6 @@ GNU General Public License for more details.
#include "filesystem.h"
#include "client.h"
#include "qfont.h"
#include "swaplib.h"
le_struct_begin( charinfo_swap )
le_struct_field( charinfo, startoffset )
le_struct_field( charinfo, charwidth )
le_struct_end();
le_struct_begin( qfont_swap )
le_struct_field( qfont_t, width )
le_struct_field( qfont_t, height )
le_struct_field( qfont_t, rowcount )
le_struct_field( qfont_t, rowheight )
le_struct_array_child( qfont_t, fontinfo, charinfo_swap, NUM_GLYPHS )
le_struct_end();
qboolean CL_FixedFont( cl_font_t *font )
{
@@ -82,11 +68,6 @@ void CL_SetFontRendermode( cl_font_t *font )
ref.dllFuncs.GL_SetRenderMode( CL_FontRenderMode( font->rendermode ));
}
void CL_SetFontColor( cl_font_t *font, const rgba_t color )
{
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
}
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags )
{
int font_width, i;
@@ -144,7 +125,6 @@ qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float
}
memcpy( &src, pfile, sizeof( src ));
le_struct_swap( qfont_swap, &src );
Mem_Free( pfile );
font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width );
@@ -183,7 +163,7 @@ void CL_FreeFont( cl_font_t *font )
static int CL_CalcTabStop( const cl_font_t *font, int x )
{
int space = font->charWidths['0'];
int space = font->charWidths[' '];
int tab = space * 6; // 6 spaces
int stop = tab - x % tab;
@@ -242,9 +222,10 @@ int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
CL_SetFontRendermode( font );
if( !FBitSet( flags, FONT_DRAW_NOCOLOR ))
CL_SetFontColor( font, color );
// 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
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] );
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, font->hFontTexture );
return font->charWidths[number];
@@ -252,6 +233,7 @@ int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags )
{
rgba_t current_color;
int draw_len = 0;
if( !font || !font->valid )
@@ -263,9 +245,7 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
CL_SetFontRendermode( font );
CL_SetFontColor( font, color );
SetBits( flags, FONT_DRAW_NOCOLOR | FONT_DRAW_NORENDERMODE );
Vector4Copy( color, current_color );
while( *s )
{
@@ -284,7 +264,7 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_
}
if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF ))
CL_SetFontColor( font, color );
Vector4Copy( color, current_color );
continue;
}
@@ -292,14 +272,14 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_
{
// don't copy alpha
if( !FBitSet( flags, FONT_DRAW_FORCECOL ))
CL_SetFontColor( font, g_color_table[ColorIndex(*( s + 1 ))] );
VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color );
s += 2;
continue;
}
// skip setting rendermode, it was changed for this string already
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, NULL, font, flags );
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, current_color, font, flags | FONT_DRAW_NORENDERMODE );
s++;
}
@@ -344,7 +324,7 @@ void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height,
if( width )
*width = 0;
if( COM_StringEmptyOrNULL( s ))
if( !COM_CheckString( s ))
return;
if( FBitSet( flags, FONT_DRAW_UTF8 ))

View File

@@ -20,6 +20,7 @@ GNU General Public License for more details.
#include "pm_local.h"
#include "cl_tent.h"
#include "studio.h"
#include "dlight.h"
#include "sound.h"
#include "input.h"
@@ -156,6 +157,13 @@ static qboolean CL_EntityCustomLerp( cl_entity_t *e )
case MOVETYPE_FLY:
case MOVETYPE_COMPOUND:
return false;
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
case MOVETYPE_TOSS:
if( cls.legacymode == PROTO_LEGACY && e->model && e->model->type == mod_studio )
return false;
}
return true;
@@ -310,21 +318,6 @@ static void CL_ProcessEntityUpdate( cl_entity_t *ent )
if( FBitSet( ent->curstate.entityType, ENTITY_NORMAL ))
COM_NormalizeAngles( ent->curstate.angles );
// a1ba: follow entities are sent with null origin, grab their aiment origin here
//
// null origin leads to triggered entity teleport check and subsequent reset of position history
// and empty position history doesn't allow entity to render correctly
//
// it's probably should be done somewhere else, as goldsrc doesn't do this here
// it has MoveAiments function but it's called after LinkPacketEntities :shrug:
if( ent->curstate.movetype == MOVETYPE_FOLLOW && VectorIsNull( ent->curstate.origin ) && ent->curstate.aiment )
{
cl_entity_t *aiment = CL_GetEntityByIndex( ent->curstate.aiment );
if( aiment )
VectorCopy( aiment->origin, ent->curstate.origin );
}
parametric = ent->curstate.starttime != 0.0f && ent->curstate.impacttime != 0.0f;
// allow interpolation on bmodels too
@@ -660,9 +653,18 @@ FRAME PARSING
*/
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum, connprotocol_t proto )
{
*newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
if( *newnum == LAST_EDICT )
return false;
if( proto == PROTO_LEGACY )
{
*newnum = MSG_ReadWord( msg );
if( *newnum == 0 )
return false;
}
else
{
*newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
if( *newnum == LAST_EDICT )
return false;
}
return true;
}
@@ -829,7 +831,9 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
CL_WriteDemoJumpTime();
// sentinel count. save it for debug checking
count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1;
if( proto == PROTO_LEGACY )
count = MSG_ReadWord( msg );
else count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1;
newframe = &cl.frames[cl.parsecountmod];
@@ -981,8 +985,15 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
if( !draw_player )
return false;
if( !ref.dllFuncs.R_AddEntity( ent, entityType ))
if( entityType == ET_BEAM )
{
ref.dllFuncs.CL_AddCustomBeam( ent );
return true;
}
else if( !ref.dllFuncs.R_AddEntity( ent, entityType ))
{
return false;
}
// because pTemp->entity.curstate.effects
// is already occupied by FTENT_FLICKER
@@ -1235,6 +1246,16 @@ static void CL_LinkPacketEntities( frame_t *frame )
if( !CL_InterpolateModel( ent ))
continue;
}
#if 0
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
else if( cls.legacymode == PROTO_LEGACY && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
{
if( !CL_InterpolateModel( ent ))
continue;
}
#endif
else
{
// no interpolation right now
@@ -1374,7 +1395,7 @@ qboolean CL_GetEntitySpatialization( channel_t *ch )
if( ch->entnum == 0 )
{
SetBits( ch->flags, FL_CHAN_STATIC_SOUND );
ch->staticsound = true;
return true; // static sound
}

View File

@@ -23,8 +23,6 @@ GNU General Public License for more details.
#include "client.h"
#include "const.h"
#include "triangleapi.h"
#include "r_studioint.h"
#include "mod_local.h"
#include "r_efx.h"
#include "demo_api.h"
#include "ivoicetweak.h"
@@ -39,20 +37,11 @@ GNU General Public License for more details.
#include "platform/platform.h"
#define MAX_LINELENGTH 80
#define TEXT_MSGNAME "TextMessage"
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
#define TEXT_MSGNAME "TextMessage%i"
static char cl_textbuffer[MAX_TEXTCHANNELS][2048];
client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS] =
{
{ .pName = "TextMessage0", .pMessage = cl_textbuffer[0] },
{ .pName = "TextMessage1", .pMessage = cl_textbuffer[1] },
{ .pName = "TextMessage2", .pMessage = cl_textbuffer[2] },
{ .pName = "TextMessage3", .pMessage = cl_textbuffer[3] },
{ .pName = "TextMessage4", .pMessage = cl_textbuffer[4] },
{ .pName = "TextMessage5", .pMessage = cl_textbuffer[5] },
{ .pName = "TextMessage6", .pMessage = cl_textbuffer[6] },
{ .pName = "TextMessage7", .pMessage = cl_textbuffer[7] },
};
static client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
static const dllfunc_t cdll_exports[] =
{
@@ -107,8 +96,6 @@ static const dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and high
{ "IN_ClientTouchEvent", (void **)&clgame.dllFuncs.pfnTouchEvent}, // Xash3D FWGS ext
{ "IN_ClientMoveEvent", (void **)&clgame.dllFuncs.pfnMoveEvent}, // Xash3D FWGS ext
{ "IN_ClientLookEvent", (void **)&clgame.dllFuncs.pfnLookEvent}, // Xash3D FWGS ext
{ "HUD_GetSoundInterface", (void **)&clgame.dllFuncs.pfnGetSoundInterface }, // Xash3D FWGS ext
{ "Voice_StartChannel", (void **)&clgame.dllFuncs.pfnVoice_StartChannel }, // Xash3D FWGS ext
};
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
@@ -125,11 +112,7 @@ static void CL_CreatePlaylist( const char *filename )
file_t *f;
f = FS_Open( filename, "w", false );
if( !f )
{
Con_Printf( S_ERROR "%s: can't open %s for write\n", __func__, filename );
return;
}
if( !f ) return;
// make standard cdaudio playlist
FS_Print( f, "blank\n" ); // #1
@@ -192,13 +175,7 @@ static void CL_InitCDAudio( const char *filename )
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
{
if( !Q_stricmp( token, "blank" ))
{
clgame.cdtracks[c][0] = '\0';
}
else if( token[0] == '/' ) // allow custom path
{
Q_strncpy( clgame.cdtracks[c], &token[1], sizeof( clgame.cdtracks[c] ));
}
else
{
Q_snprintf( clgame.cdtracks[c], sizeof( clgame.cdtracks[c] ),
@@ -289,7 +266,7 @@ void CL_CenterPrint( const char *text, float y )
{
cl_font_t *font = Con_GetCurFont();
if( COM_StringEmptyOrNULL( text ) || !font || !font->valid )
if( !COM_CheckString( text ) || !font || !font->valid )
return;
clgame.centerPrint.totalWidth = 0;
@@ -376,13 +353,13 @@ static void SPR_DrawGeneric( int frame, float x, float y, float width, float hei
int w, h;
// assume we get sizes from image
R_GetSpriteParms( &w, &h, NULL, frame, clgame.ds.pSprite );
ref.dllFuncs.R_GetSpriteParms( &w, &h, NULL, frame, clgame.ds.pSprite );
width = w;
height = h;
}
texnum = R_GetSpriteTexture( clgame.ds.pSprite, frame );
texnum = ref.dllFuncs.R_GetSpriteTexture( clgame.ds.pSprite, frame );
if( prc )
{
@@ -452,7 +429,6 @@ void CL_DrawCenterPrint( void )
CL_DrawCharacterLen( font, 0, NULL, &charHeight );
CL_SetFontRendermode( font );
CL_SetFontColor( font, colorDefault );
for( i = 0; i < clgame.centerPrint.lines; i++ )
{
lineLength = 0;
@@ -482,7 +458,7 @@ void CL_DrawCenterPrint( void )
for( j = 0; j < lineLength; j++ )
{
if( x >= 0 && y >= 0 && x <= refState.width )
x += CL_DrawCharacter( x, y, line[j], NULL, font, FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE | FONT_DRAW_NOCOLOR );
x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE );
}
y += charHeight;
}
@@ -579,18 +555,31 @@ and hold them into permament memory pool
*/
static void CL_InitTitles( const char *filename )
{
fs_offset_t fileSize;
byte *pMemFile;
int i;
// initialize text messages (game_text)
for( i = 0; i < MAX_TEXTCHANNELS; i++ )
{
char name[MAX_VA_STRING];
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
cl_textmessage[i].pMessage = cl_textbuffer[i];
}
// clear out any old data that's sitting around.
Mem_Free( clgame.titles );
if( clgame.titles ) Mem_Free( clgame.titles );
clgame.titles = NULL;
clgame.numTitles = 0;
fs_offset_t fileSize = 0;
char *pMemFile = (char *)FS_LoadFile( filename, &fileSize, false );
if( !pMemFile )
return;
pMemFile = FS_LoadFile( filename, &fileSize, false );
if( !pMemFile ) return;
clgame.titles = CL_TextMessageParse( clgame.mempool, pMemFile, fileSize, &clgame.numTitles );
CL_TextMessageParse( pMemFile, fileSize );
Mem_Free( pMemFile );
}
@@ -603,10 +592,8 @@ Template to show hud messages
*/
void CL_HudMessage( const char *pMessage )
{
if( COM_StringEmptyOrNULL( pMessage ))
return;
CL_DispatchUserMessage( "HudText", Q_strlen( pMessage ) + 1, (void *)pMessage );
if( !COM_CheckString( pMessage )) return;
CL_DispatchUserMessage( "HudText", Q_strlen( pMessage ), (void *)pMessage );
}
/*
@@ -659,6 +646,54 @@ void CL_ParseTextMessage( sizebuf_t *msg )
CL_HudMessage( text->pName );
}
/*
================
CL_ParseFinaleCutscene
show display finale or cutscene message
================
*/
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level )
{
static int msgindex = 0;
client_textmessage_t *text;
int channel;
cl.intermission = level;
channel = msgindex;
msgindex = (msgindex + 1) & (MAX_TEXTCHANNELS - 1);
// grab message channel
text = &cl_textmessage[channel];
// NOTE: svc_finale and svc_cutscene has a
// predefined settings like Quake-style
text->x = -1.0f;
text->y = 0.15f;
text->effect = 2; // scan out effect
text->r1 = 245;
text->g1 = 245;
text->b1 = 245;
text->a1 = 0; // unused
text->r2 = 0;
text->g2 = 0;
text->b2 = 0;
text->a2 = 0;
text->fadein = 0.15f;
text->fadeout = 0.0f;
text->holdtime = 99999.0f;
text->fxtime = 0.0f;
// to prevent grab too long messages
Q_strncpy( (char *)text->pMessage, MSG_ReadString( msg ), 2048 );
if( *text->pMessage == '\0' )
return; // no real text
CL_HudMessage( text->pName );
}
/*
====================
CL_GetMaxlients
@@ -1075,12 +1110,7 @@ void CL_ClearSpriteTextures( void )
int i;
for( i = 1; i < MAX_CLIENT_SPRITES; i++ )
{
if( clgame.sprites[i].needload == NL_UNREFERENCED )
continue;
clgame.sprites[i].needload = NL_FREE_UNUSED;
}
clgame.sprites[i].needload = NL_UNREFERENCED;
}
// it's a Valve default value for LoadMapSprite (probably must be power of two)
@@ -1251,8 +1281,8 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
else
{
Mod_LoadSpriteModel( m_pSprite, buf, size, &loaded );
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf, size );
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
}
Mem_Free( buf );
@@ -1282,7 +1312,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
model_t *mod;
int i, start;
if( COM_StringEmptyOrNULL( filename ))
if( !COM_CheckString( filename ))
{
Con_Reportf( S_ERROR "%s: bad name!\n", __func__ );
return NULL;
@@ -1314,7 +1344,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
for( i = 0, mod = &clgame.sprites[start]; i < MAX_CLIENT_SPRITES / 2; i++, mod++ )
{
if( mod->needload == NL_UNREFERENCED )
if( !mod->name[0] )
break; // this is a valid spot
}
@@ -1426,7 +1456,7 @@ int EXPORT pfnSPR_Frames( HSPRITE hPic )
{
int numFrames = 0;
R_GetSpriteParms( NULL, NULL, &numFrames, 0, CL_GetSpritePointer( hPic ));
ref.dllFuncs.R_GetSpriteParms( NULL, NULL, &numFrames, 0, CL_GetSpritePointer( hPic ));
return numFrames;
}
@@ -1441,7 +1471,7 @@ static int GAME_EXPORT pfnSPR_Height( HSPRITE hPic, int frame )
{
int sprHeight = 0;
R_GetSpriteParms( NULL, &sprHeight, NULL, frame, CL_GetSpritePointer( hPic ));
ref.dllFuncs.R_GetSpriteParms( NULL, &sprHeight, NULL, frame, CL_GetSpritePointer( hPic ));
return sprHeight;
}
@@ -1456,7 +1486,7 @@ static int GAME_EXPORT pfnSPR_Width( HSPRITE hPic, int frame )
{
int sprWidth = 0;
R_GetSpriteParms( &sprWidth, NULL, NULL, frame, CL_GetSpritePointer( hPic ));
ref.dllFuncs.R_GetSpriteParms( &sprWidth, NULL, NULL, frame, CL_GetSpritePointer( hPic ));
return sprWidth;
}
@@ -1801,7 +1831,7 @@ pfnServerCmd
*/
static int GAME_EXPORT pfnServerCmd( const char *szCmdString )
{
if( COM_StringEmptyOrNULL( szCmdString ))
if( !COM_CheckString( szCmdString ))
return 0;
// just like the client typed "cmd xxxxx" at the console
@@ -1819,7 +1849,7 @@ pfnClientCmd
*/
static int GAME_EXPORT pfnClientCmd( const char *szCmdString )
{
if( COM_StringEmptyOrNULL( szCmdString ))
if( !COM_CheckString( szCmdString ))
return 0;
if( cls.initialized )
@@ -1844,7 +1874,7 @@ pfnFilteredClientCmd
*/
static int GAME_EXPORT pfnFilteredClientCmd( const char *szCmdString )
{
if( COM_StringEmptyOrNULL( szCmdString ))
if( !COM_CheckString( szCmdString ))
return 0;
// a1ba:
@@ -1932,12 +1962,13 @@ client_textmessage_t *CL_TextMessageGet( const char *pName )
int i;
// first check internal messages
if( Q_strlen( pName ) == sizeof( TEXT_MSGNAME ) // including the digit
&& !Q_strncmp( pName, TEXT_MSGNAME, sizeof( TEXT_MSGNAME ) - 1 ))
for( i = 0; i < MAX_TEXTCHANNELS; i++ )
{
i = pName[sizeof( TEXT_MSGNAME ) - 1] - '0';
char name[MAX_VA_STRING];
if( i >= 0 && i < MAX_TEXTCHANNELS )
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
if( !Q_strcmp( pName, name ))
return cl_textmessage + i;
}
@@ -2025,7 +2056,7 @@ prints directly into console (can skip notify)
*/
static void GAME_EXPORT pfnConsolePrint( const char *string )
{
if( COM_StringEmptyOrNULL( string ))
if( !COM_CheckString( string ))
return;
// WON GoldSrc behavior
@@ -2175,7 +2206,7 @@ pfnGetViewModel
=============
*/
static cl_entity_t *GAME_EXPORT CL_GetViewModel( void )
static cl_entity_t* GAME_EXPORT CL_GetViewModel( void )
{
return &clgame.viewent;
}
@@ -2397,7 +2428,7 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
char filepath[MAX_QPATH];
int i;
if( COM_StringEmptyOrNULL( m ))
if( !COM_CheckString( m ))
return 0;
Q_strncpy( filepath, m, sizeof( filepath ));
@@ -2698,7 +2729,7 @@ static const char *pfnGetLevelName( void )
// a1ba: don't return maps/.bsp if no map is loaded yet
// in GoldSrc this is handled by cl.levelname field but we don't have it
// so emulate this behavior here
if( cls.state >= ca_connected && !COM_StringEmpty( clgame.mapname ))
if( cls.state >= ca_connected && COM_CheckStringEmpty( clgame.mapname ))
Q_snprintf( mapname, sizeof( mapname ), "maps/%s.bsp", clgame.mapname );
else mapname[0] = '\0'; // not in game
@@ -2769,7 +2800,7 @@ static int GAME_EXPORT COM_ExpandFilename( const char *fileName, char *nameOutBu
{
char result[MAX_SYSPATH];
if( COM_StringEmptyOrNULL( fileName ) || !nameOutBuffer || nameOutBufferSize <= 0 )
if( !COM_CheckString( fileName ) || !nameOutBuffer || nameOutBufferSize <= 0 )
return 0;
// filename examples:
@@ -2882,7 +2913,7 @@ pfnServerCmdUnreliable
*/
static int GAME_EXPORT pfnServerCmdUnreliable( char *szCmdString )
{
if( COM_StringEmptyOrNULL( szCmdString ))
if( !COM_CheckString( szCmdString ))
return 0;
MSG_BeginClientCmd( &cls.datagram, clc_stringcmd );
@@ -2899,15 +2930,10 @@ pfnGetMousePos
*/
static void GAME_EXPORT pfnGetMousePos( struct tagPOINT *ppt )
{
int x, y;
if( !ppt )
return;
Platform_GetMousePos( &x, &y );
ppt->x = x;
ppt->y = y;
Platform_GetMousePos( &ppt->x, &ppt->y );
}
/*
@@ -3176,8 +3202,7 @@ handle colon separately
*/
static char *pfnParseFile( char *data, char *token )
{
// GoldSrc uses 1024 byte tokens
return COM_ParseFileSafe( data, token, 1024, PFILE_HANDLECOLON, NULL, NULL );
return COM_ParseFileSafe( data, token, PFILE_TOKEN_MAX_LENGTH, PFILE_HANDLECOLON, NULL, NULL );
}
/*
@@ -3326,7 +3351,7 @@ int TriSpriteTexture( model_t *pSpriteModel, int frame )
{
int gl_texturenum;
if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) <= 0 )
if(( gl_texturenum = ref.dllFuncs.R_GetSpriteTexture( pSpriteModel, frame )) <= 0 )
return 0;
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, gl_texturenum );
@@ -3456,7 +3481,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
nr->flags = flags;
// local servers request
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, A2A_NETINFO" %i %i %i", PROTOCOL_VERSION, context, request );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, A2A_NETINFO" %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
}
/*
@@ -3919,7 +3944,7 @@ void CL_UnloadProgs( void )
if( GI->internal_vgui_support )
VGui_Shutdown();
Cvar_DirectFullSet( &cl_background, "0", FCVAR_READ_ONLY );
Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
Cvar_FullSet( "host_clientloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_CLIENTDLL );
@@ -3931,76 +3956,12 @@ void CL_UnloadProgs( void )
memset( &clgame, 0, sizeof( clgame ));
}
static model_t *pfnStudio_Mod_ForName( const char *name, int crash )
{
return Mod_ForName( name, crash, false );
}
static void *pfnStudio_Mod_Extradata( model_t *mod )
{
return Mod_StudioExtradata( mod );
}
static void pfnStudio_GetAliasScale( float *x, float *y )
{
if( x ) *x = 1.0f;
if( y ) *y = 1.0f;
}
static float ***pfnStudio_GetAliasTransform( void )
{
return NULL;
}
static model_t *pfnStudio_GetChromeSprite( void )
{
return cl_sprite_shell;
}
static int pfnStudio_IsHardware( void )
{
return 1;
}
static engine_studio_api_t gStudioAPI =
{
.Mem_Calloc = Mod_Calloc,
.Cache_Check = Mod_CacheCheck,
.LoadCacheFile = Mod_LoadCacheFile,
.Mod_ForName = pfnStudio_Mod_ForName,
.Mod_Extradata = pfnStudio_Mod_Extradata,
.GetModelByIndex = CL_ModelHandle,
.GetCvar = pfnCVarGetPointer,
.GetChromeSprite = pfnStudio_GetChromeSprite,
.GetAliasScale = pfnStudio_GetAliasScale,
.StudioGetAliasTransform = pfnStudio_GetAliasTransform,
.GetViewEntity = CL_GetViewModel,
.IsHardware = pfnStudio_IsHardware,
};
static void CL_InitStudioAPI( void )
{
static r_studio_interface_t gDefaultStudioDraw;
r_studio_interface_t *pStudioDraw;
if( !ref.dllFuncs.R_StudioFillAPI( &gStudioAPI, &gDefaultStudioDraw ))
return;
pStudioDraw = &gDefaultStudioDraw;
if( clgame.dllFuncs.pfnGetStudioModelInterface )
clgame.dllFuncs.pfnGetStudioModelInterface( STUDIO_INTERFACE_VERSION, &pStudioDraw, &gStudioAPI );
ref.dllFuncs.R_StudioSetDrawInterface( pStudioDraw );
}
qboolean CL_LoadProgs( const char *name )
{
static playermove_t gpMove;
CL_EXPORT_FUNCS GetClientAPI; // single export
qboolean valid_single_export = false;
qboolean missed_exports = false;
qboolean try_internal_vgui_support = GI->internal_vgui_support;
int i;
if( clgame.hInstance ) CL_UnloadProgs();
@@ -4021,10 +3982,10 @@ qboolean CL_LoadProgs( const char *name )
// NOTE: important stuff!
// vgui must startup BEFORE loading client.dll to avoid get error ERROR_NOACESS during LoadLibrary
if( !try_internal_vgui_support && VGui_LoadProgs( NULL ))
if( !GI->internal_vgui_support && VGui_LoadProgs( NULL ))
VGui_Startup( refState.width, refState.height );
else
try_internal_vgui_support = true; // we failed to load vgui_support, but let's probe client.dll for support anyway
GI->internal_vgui_support = true; // we failed to load vgui_support, but let's probe client.dll for support anyway
clgame.hInstance = COM_LoadLibrary( name, false, false );
@@ -4032,21 +3993,21 @@ qboolean CL_LoadProgs( const char *name )
return false;
// delayed vgui initialization for internal support
if( try_internal_vgui_support && VGui_LoadProgs( clgame.hInstance ))
if( GI->internal_vgui_support && VGui_LoadProgs( clgame.hInstance ))
VGui_Startup( refState.width, refState.height );
// clear exports
ClearExports( cdll_exports, ARRAYSIZE( cdll_exports ));
// trying to get single export
if(( GetClientAPI = COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
{
Con_Reportf( "%s: found single callback export\n", __func__ );
// trying to fill interface now
GetClientAPI( &clgame.dllFuncs );
}
else if(( GetClientAPI = COM_GetProcAddress( clgame.hInstance, "F" )) != NULL )
else if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "F" )) != NULL )
{
Con_Reportf( "%s: found single callback export (secured client dlls)\n", __func__ );
@@ -4060,7 +4021,7 @@ qboolean CL_LoadProgs( const char *name )
for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ )
{
if( *(cdll_exports[i].func) != NULL )
continue; // already got through 'F' or 'GetClientAPI'
continue; // already gott through 'F' or 'GetClientAPI'
// functions are cleared before all the extensions are evaluated
if(( *(cdll_exports[i].func) = (void *)COM_GetProcAddress( clgame.hInstance, cdll_exports[i].name )) == NULL )
@@ -4074,11 +4035,6 @@ qboolean CL_LoadProgs( const char *name )
if( missed_exports )
{
if( clgame.dllFuncs.pfnInit && clgame.dllFuncs.pfnRedraw && clgame.dllFuncs.pfnReset && clgame.dllFuncs.pfnUpdateClientData && clgame.dllFuncs.pfnVidInit && clgame.dllFuncs.pfnInitialize )
COM_PushLibraryError( "missing essential exports; outdated DLL!!!" );
else
COM_PushLibraryError( "missing essential exports" );
COM_FreeLibrary( clgame.hInstance );
clgame.hInstance = NULL;
return false;
@@ -4101,7 +4057,6 @@ qboolean CL_LoadProgs( const char *name )
if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION ))
{
COM_PushLibraryError( "can't init client API" );
COM_FreeLibrary( clgame.hInstance );
Con_Reportf( "%s: can't init client API\n", __func__ );
clgame.hInstance = NULL;
@@ -4115,14 +4070,14 @@ qboolean CL_LoadProgs( const char *name )
CL_InitCDAudio( "media/cdaudio.txt" );
CL_InitTitles( "titles.txt" );
CL_InitParticles( );
CL_InitViewBeams( );
CL_InitTempEnts( );
CL_InitParticles ();
CL_InitViewBeams ();
CL_InitTempEnts ();
if( !R_InitRenderAPI( )) // Xash3D extension
if( !R_InitRenderAPI()) // Xash3D extension
Con_Reportf( S_WARN "%s: couldn't get render API\n", __func__ );
if( !Mobile_Init( )) // Xash3D FWGS extension: mobile interface
if( !Mobile_Init() ) // Xash3D FWGS extension: mobile interface
Con_Reportf( S_WARN "%s: couldn't get mobility API\n", __func__ );
CL_InitEdicts( cl.maxclients ); // initailize local player and world
@@ -4131,7 +4086,7 @@ qboolean CL_LoadProgs( const char *name )
// initialize game
clgame.dllFuncs.pfnInit();
CL_InitStudioAPI();
ref.dllFuncs.CL_InitStudioAPI();
return true;
}

View File

@@ -37,11 +37,8 @@ void UI_UpdateMenu( float realtime )
{
if( !gameui.hInstance ) return;
// don't draw menu over console
if( cls.key_dest == key_console ) return;
// if some deferred cmds is waiting
if( UI_IsVisible() && !COM_StringEmptyOrNULL( host.deferred_cmd ))
if( UI_IsVisible() && COM_CheckString( host.deferred_cmd ))
{
Cbuf_AddText( host.deferred_cmd );
host.deferred_cmd[0] = '\0';
@@ -202,6 +199,24 @@ void UI_ShowConnectionWarning( void )
}
}
/*
=================
UI_ShowConnectionWarning
show update dialog
=================
*/
void UI_ShowUpdateDialog( qboolean preferStore )
{
if( gameui.dllFuncs2.pfnShowUpdateDialog )
{
gameui.dllFuncs2.pfnShowUpdateDialog( preferStore );
}
Con_Printf( S_WARN "This version is not supported anymore. To continue, install latest engine version\n" );
}
/*
=================
UI_ShowConnectionWarning
@@ -499,7 +514,7 @@ static HIMAGE GAME_EXPORT pfnPIC_Load( const char *szPicName, const byte *image_
{
HIMAGE tx;
if( COM_StringEmptyOrNULL( szPicName ))
if( !COM_CheckString( szPicName ))
{
Con_Reportf( S_ERROR "%s: refusing to load image with empty name\n", __func__ );
return 0;
@@ -695,9 +710,7 @@ pfnPlaySound
*/
static void GAME_EXPORT pfnPlaySound( const char *szSound )
{
if( COM_StringEmptyOrNULL( szSound ))
return;
if( !COM_CheckString( szSound )) return;
S_StartLocalSound( szSound, VOL_NORM, false );
}
@@ -982,7 +995,7 @@ pfnGetFilesList
release prev search on a next call
=========
*/
char **GAME_EXPORT CL_GetFilesList( const char *pattern, int *numFiles, int gamedironly )
static char ** GAME_EXPORT pfnGetFilesList( const char *pattern, int *numFiles, int gamedironly )
{
static search_t *t = NULL;
@@ -1083,9 +1096,6 @@ UI_ShellExecute
*/
static void GAME_EXPORT UI_ShellExecute( const char *path, const char *parms, int shouldExit )
{
if( !Q_strcmp( path, GENERIC_UPDATE_PAGE ) || !Q_strcmp( path, PLATFORM_UPDATE_PAGE ))
path = DEFAULT_UPDATE_PAGE;
Platform_ShellExecute( path, parms );
if( shouldExit )
@@ -1222,7 +1232,7 @@ static const ui_enginefuncs_t gEngfuncs =
pfnMemFree,
pfnGetOldGameInfo,
pfnGetGamesList,
CL_GetFilesList,
pfnGetFilesList,
SV_GetSaveComment,
CL_GetDemoComment,
pfnCheckGameDll,
@@ -1344,6 +1354,7 @@ qboolean UI_LoadProgs( void )
UITEXTAPI GiveTextApi;
MENUAPI GetMenuAPI;
string dllpath;
int i;
if( gameui.hInstance ) UI_UnloadProgs();

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@ GNU General Public License for more details.
#include "common.h"
#include "client.h"
#include "kbutton.h"
#if XASH_LOW_MEMORY == 0
#define NET_TIMINGS 1024
@@ -171,7 +172,7 @@ get frame data info, like chokes, packet losses, also update graph, packet and c
static void NetGraph_GetFrameData( float *latency, int *latency_count )
{
int i, choke_count = 0, loss_count = 0;
double newtime = Platform_DoubleTime();
double newtime = Sys_DoubleTime();
static double nexttime = 0;
float loss, choke;

File diff suppressed because it is too large Load Diff

633
engine/client/cl_parse_48.c Normal file
View File

@@ -0,0 +1,633 @@
/*
cl_parse.c - parse a message received from the server
Copyright (C) 2008 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "client.h"
#include "net_encode.h"
#include "particledef.h"
#include "cl_tent.h"
#include "shake.h"
#include "hltv.h"
#include "input.h"
/*
==================
CL_ParseStaticEntity
static client entity
==================
*/
static void CL_LegacyParseStaticEntity( sizebuf_t *msg )
{
int i;
entity_state_t state = { 0 };
cl_entity_t *ent;
if( !clgame.static_entities )
clgame.static_entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
state.modelindex = MSG_ReadShort( msg );
state.sequence = MSG_ReadByte( msg );
state.frame = MSG_ReadByte( msg );
state.colormap = MSG_ReadWord( msg );
state.skin = MSG_ReadByte( msg );
for( i = 0; i < 3; i++ )
{
state.origin[i] = MSG_ReadCoord( msg );
state.angles[i] = MSG_ReadBitAngle( msg, 16 );
}
state.rendermode = MSG_ReadByte( msg );
if( state.rendermode != kRenderNormal )
{
state.renderamt = MSG_ReadByte( msg );
state.rendercolor.r = MSG_ReadByte( msg );
state.rendercolor.g = MSG_ReadByte( msg );
state.rendercolor.b = MSG_ReadByte( msg );
state.renderfx = MSG_ReadByte( msg );
}
i = clgame.numStatics;
if( i >= MAX_STATIC_ENTITIES )
{
Con_Printf( S_ERROR "MAX_STATIC_ENTITIES limit exceeded!\n" );
return;
}
ent = &clgame.static_entities[i];
clgame.numStatics++;
// all states are same
ent->baseline = ent->curstate = ent->prevstate = state;
ent->index = 0; // static entities doesn't has the numbers
// statics may be respawned in game e.g. for demo recording
if( cls.state == ca_connected || cls.state == ca_validate )
ent->trivial_accept = INVALID_HANDLE;
// setup the new static entity
VectorCopy( ent->curstate.origin, ent->origin );
VectorCopy( ent->curstate.angles, ent->angles );
ent->model = CL_ModelHandle( state.modelindex );
ent->curstate.framerate = 1.0f;
CL_ResetLatchedVars( ent, true );
if( ent->curstate.rendermode == kRenderNormal && ent->model != NULL )
{
// auto 'solid' faces
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && Host_IsQuakeCompatible( ))
{
ent->curstate.rendermode = kRenderTransAlpha;
ent->curstate.renderamt = 255;
}
}
R_AddEfrags( ent ); // add link
}
static void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
{
vec3_t pos;
int chan, sound;
float volume, attn;
int flags, pitch, entnum;
sound_t handle = 0;
flags = MSG_ReadWord( msg );
if( flags & SND_LEGACY_LARGE_INDEX )
{
sound = MSG_ReadWord( msg );
flags &= ~SND_LEGACY_LARGE_INDEX;
}
else
sound = MSG_ReadByte( msg );
chan = MSG_ReadByte( msg );
if( FBitSet( flags, SND_VOLUME ))
volume = (float)MSG_ReadByte( msg ) / 255.0f;
else volume = VOL_NORM;
if( FBitSet( flags, SND_ATTENUATION ))
attn = (float)MSG_ReadByte( msg ) / 64.0f;
else attn = ATTN_NONE;
if( FBitSet( flags, SND_PITCH ))
pitch = MSG_ReadByte( msg );
else pitch = PITCH_NORM;
// entity reletive
entnum = MSG_ReadWord( msg );
// positioned in space
MSG_ReadVec3Coord( msg, pos );
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
if( !cl.audio_prepped )
return; // too early
// g-cont. sound and ambient sound have only difference with channel
if( is_ambient )
{
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
else
{
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
}
}
/*
================
CL_PrecacheSound
prceache sound from server
================
*/
static void CL_LegacyPrecacheSound( sizebuf_t *msg )
{
int soundIndex;
soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
Host_Error( "%s: bad soundindex %i\n", __func__, soundIndex );
Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] ));
// when we loading map all resources is precached sequentially
//if( !cl.audio_prepped ) return;
cl.sound_index[soundIndex] = S_RegisterSound( cl.sound_precache[soundIndex] );
}
static void CL_LegacyPrecacheModel( sizebuf_t *msg )
{
int modelIndex;
string model;
modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS );
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
Host_Error( "%s: bad modelindex %i\n", __func__, modelIndex );
Q_strncpy( model, MSG_ReadString( msg ), sizeof( model ));
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
// when we loading map all resources is precached sequentially
//if( !cl.video_prepped ) return;
if( modelIndex == 1 && !cl.worldmodel )
{
CL_ClearWorld ();
cl.models[modelIndex] = cl.worldmodel = Mod_LoadWorld( model, true );
return;
}
//Mod_RegisterModel( cl.model_precache[modelIndex], modelIndex );
cl.models[modelIndex] = Mod_ForName( model, false, false );
cl.nummodels = Q_max( cl.nummodels, modelIndex );
}
static void CL_LegacyPrecacheEvent( sizebuf_t *msg )
{
int eventIndex;
eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
Host_Error( "%s: bad eventindex %i\n", __func__, eventIndex );
Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] ));
// can be set now
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
}
#if XASH_LOW_MEMORY == 0
#define MAX_LEGACY_RESOURCES 2048
#elif XASH_LOW_MEMORY == 2
#define MAX_LEGACY_RESOURCES 1
#elif XASH_LOW_MEMORY == 1
#define MAX_LEGACY_RESOURCES 512
#endif
/*
==============
CL_ParseResourceList
==============
*/
static void CL_LegacyParseResourceList( sizebuf_t *msg )
{
int i = 0;
static struct
{
int rescount;
int restype[MAX_LEGACY_RESOURCES];
char resnames[MAX_LEGACY_RESOURCES][MAX_QPATH];
} reslist;
memset( &reslist, 0, sizeof( reslist ));
reslist.rescount = MSG_ReadWord( msg ) - 1;
if( reslist.rescount > MAX_LEGACY_RESOURCES )
Host_Error( "MAX_RESOURCES reached\n" );
for( i = 0; i < reslist.rescount; i++ )
{
reslist.restype[i] = MSG_ReadWord( msg );
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), sizeof( reslist.resnames[i] ));
}
if( cls.demoplayback )
return;
if( !cl_allow_download.value )
{
Con_DPrintf( "Refusing new resource, cl_allowdownload set to 0\n" );
reslist.rescount = 0;
}
if( cls.state == ca_active && !cl_download_ingame.value )
{
Con_DPrintf( "Refusing new resource, cl_download_ingame set to 0\n" );
reslist.rescount = 0;
}
HTTP_ResetProcessState();
host.downloadcount = 0;
for( i = 0; i < reslist.rescount; i++ )
{
char soundpath[MAX_VA_STRING];
const char *path;
if( reslist.restype[i] == t_sound )
{
Q_snprintf( soundpath, sizeof( soundpath ), DEFAULT_SOUNDPATH "%s", reslist.resnames[i] );
path = soundpath;
}
else path = reslist.resnames[i];
if( FS_FileExists( path, false ))
continue; // already exists
host.downloadcount++;
HTTP_AddDownload( path, -1, true, NULL );
}
if( !host.downloadcount )
{
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_WriteString( &cls.netchan.message, "continueloading" );
}
}
/*
=====================
CL_ParseLegacyServerMessage
dispatch messages
=====================
*/
void CL_ParseLegacyServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd;
int old_background;
const char *s;
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "%s: overflow!\n", __func__ );
return;
}
// mark start position
bufStart = MSG_GetNumBytesRead( msg );
// end of message (align bits)
if( MSG_GetNumBitsLeft( msg ) < 8 )
break;
cmd = MSG_ReadServerCmd( msg );
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_LEGACY, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
// this does nothing
break;
case svc_disconnect:
CL_Drop ();
Host_AbortCurrentFrame ();
break;
case svc_legacy_event:
CL_ParseEvent( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_changing:
old_background = cl.background;
if( MSG_ReadOneBit( msg ))
{
int maxclients = cl.maxclients;
// we can only changelevel in singleplayer
// and singleplayer always runs in current protocol
// cls.changelevel = true;
S_StopAllSounds( true );
Con_Printf( "Server changing, reconnecting\n" );
if( cls.demoplayback )
{
SCR_BeginLoadingPlaque( cl.background );
cls.changedemo = true;
}
CL_ClearState( );
// a1ba: need to restore cl.maxclients because engine chooses
// frame backups count depending on this value
// In general, it's incorrect to call CL_InitEdicts right after
// CL_ClearState because of this bug. Some time later this logic
// should be re-done.
CL_InitEdicts( maxclients ); // re-arrange edicts
}
else Con_Printf( "Server disconnected, reconnecting\n" );
if( cls.demoplayback )
{
cl.background = (cls.demonum != -1) ? true : false;
cls.state = ca_connected;
}
else
{
// g-cont. local client skip the challenge
if( SV_Active( ))
cls.state = ca_disconnected;
else cls.state = ca_connecting;
cl.background = old_background;
cls.connect_time = MAX_HEARTBEAT;
cls.connect_retry = 0;
}
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_LegacyParseSoundPacket( msg, false );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_ambientsound:
CL_LegacyParseSoundPacket( msg, true );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_LEGACY );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
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
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_LEGACY );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_LEGACY );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_LEGACY );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
case svc_clientdata:
CL_ParseClientData( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resource:
CL_ParseResource( msg );
break;
case svc_pings:
CL_UpdateUserPings( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_LEGACY );
break;
case svc_restoresound:
Con_Printf( S_ERROR "%s: svc_restoresound: implement me!\n", __func__ );
break;
case svc_spawnstatic:
CL_LegacyParseStaticEntity( msg );
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_ParseBaseline( msg, PROTO_LEGACY );
break;
case svc_setpause:
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_LEGACY );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_legacy_modelindex:
CL_LegacyPrecacheModel( msg );
break;
case svc_legacy_soundindex:
CL_LegacyPrecacheSound( msg );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_legacy_eventindex:
CL_LegacyPrecacheEvent(msg);
break;
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg, PROTO_LEGACY );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntities( msg, true, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_legacy_chokecount:
{
int i, j;
i = MSG_ReadByte( msg );
j = cls.netchan.incoming_acknowledged - 1;
for( ; i > 0 && j > cls.netchan.outgoing_sequence - CL_UPDATE_BACKUP; j-- )
{
if( cl.frames[j & CL_UPDATE_MASK].receivedtime != -3.0 )
{
cl.frames[j & CL_UPDATE_MASK].choked = true;
cl.frames[j & CL_UPDATE_MASK].receivedtime = -2.0;
i--;
}
}
break;
}
//cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
//cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
CL_LegacyParseResourceList( msg );
break;
case svc_deltamovevars:
CL_ParseMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, PROTO_LEGACY );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_LEGACY );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
}
}
void CL_LegacyPrecache_f( void )
{
int spawncount, i;
model_t *mod;
if( cls.legacymode != PROTO_LEGACY )
return;
spawncount = Q_atoi( Cmd_Argv( 1 ));
Con_Printf( "Setting up renderer...\n" );
// load tempent sprites (glowshell, muzzleflashes etc)
CL_LoadClientSprites ();
// invalidate all decal indexes
memset( cl.decal_index, 0, sizeof( cl.decal_index ));
cl.video_prepped = true;
cl.audio_prepped = true;
if( clgame.entities )
clgame.entities->model = cl.worldmodel;
// load skybox
R_SetupSky( clgame.movevars.skyName );
// tell rendering system we have a new set of models.
ref.dllFuncs.R_NewMap ();
CL_SetupOverviewParams();
// release unused SpriteTextures
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
Mod_FreeModel( mod );
}
// Mod_FreeUnused ();
if( host_developer.value <= DEV_NONE )
Con_ClearNotify(); // clear any lines of console text
// done with all resources, issue prespawn command.
// Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS - 1;
}

View File

@@ -16,8 +16,10 @@ GNU General Public License for more details.
#include "common.h"
#include "client.h"
#include "net_encode.h"
#include "particledef.h"
#include "cl_tent.h"
#include "shake.h"
#include "hltv.h"
#include "input.h"
#include "server.h"
@@ -26,11 +28,18 @@ static void CL_ParseExtraInfo( sizebuf_t *msg )
string clientfallback;
Q_strncpy( clientfallback, MSG_ReadString( msg ), sizeof( clientfallback ));
if( !COM_StringEmpty( clientfallback ))
if( COM_CheckStringEmpty( clientfallback ))
Con_Reportf( S_ERROR "%s: TODO: add fallback directory %s!\n", __func__, clientfallback );
cls.allow_cheats = MSG_ReadByte( msg ) ? true : false;
CL_SetCheatState( cl.maxclients > 1, cls.allow_cheats );
if( MSG_ReadByte( msg ))
{
Cvar_FullSet( "sv_cheats", "1", FCVAR_READ_ONLY | FCVAR_SERVER );
}
else
{
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
}
}
static void CL_ParseNewMovevars( sizebuf_t *msg )
@@ -56,12 +65,12 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
clgame.movevars.footsteps = MSG_ReadByte( msg );
clgame.movevars.rollangle = MSG_ReadFloat( msg );
clgame.movevars.rollspeed = MSG_ReadFloat( msg );
clgame.movevars.skycolor[0] = MSG_ReadFloat( msg );
clgame.movevars.skycolor[1] = MSG_ReadFloat( msg );
clgame.movevars.skycolor[2] = MSG_ReadFloat( msg );
clgame.movevars.skyvec[0] = MSG_ReadFloat( msg );
clgame.movevars.skyvec[1] = MSG_ReadFloat( msg );
clgame.movevars.skyvec[2] = MSG_ReadFloat( msg );
clgame.movevars.skycolor_r = MSG_ReadFloat( msg );
clgame.movevars.skycolor_g = MSG_ReadFloat( msg );
clgame.movevars.skycolor_b = MSG_ReadFloat( msg );
clgame.movevars.skyvec_x = MSG_ReadFloat( msg );
clgame.movevars.skyvec_y = MSG_ReadFloat( msg );
clgame.movevars.skyvec_z = MSG_ReadFloat( msg );
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
@@ -204,7 +213,6 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
qboolean newent = from == NULL;
int pack = frame->num_entities;
qboolean has_update = msg != NULL;
static entity_state_t nullent;
// alloc next slot to store update
to = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
@@ -232,17 +240,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
if( hdr->instanced )
from = &cl.instanced_baseline[hdr->instanced_baseline_index];
else if( hdr->offset != 0 )
{
// FIXME: the usage of `offset` is incorrect here as the entities might
// not be ordered in cls.packet_entities the same way as on server
// catch the error, print the scary message and fix it up to nullent
if( cls.next_client_entities - hdr->offset < 0 )
{
Con_Printf( S_ERROR "%s: prevented delta-ing from invalid entity (%d - %d < 0)\n", __func__, cls.next_client_entities, hdr->offset );
from = &nullent;
}
else from = &cls.packet_entities[(cls.next_client_entities - hdr->offset ) % cls.num_client_entities];
}
from = &cls.packet_entities[(cls.next_client_entities - hdr->offset) % cls.num_client_entities];
else
from = &ent->baseline;
}
@@ -476,7 +474,7 @@ static void CL_ParseSoundPacketGS( sizebuf_t *msg )
chan = MSG_ReadUBitLong( msg, 3 );
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
if( FBitSet( flags, SND_GOLDSRC_LARGE_INDEX ))
if( FBitSet( flags, SND_LEGACY_LARGE_INDEX ))
sound = MSG_ReadWord( msg );
else sound = MSG_ReadByte( msg );
MSG_ReadGSBitVec3Coord( msg, pos );
@@ -487,7 +485,7 @@ static void CL_ParseSoundPacketGS( sizebuf_t *msg )
MSG_EndBitWriting( msg );
ClearBits( flags, SND_GOLDSRC_LARGE_INDEX );
ClearBits( flags, SND_LEGACY_LARGE_INDEX );
if( FBitSet( flags, SND_SENTENCE ))
{
@@ -514,26 +512,17 @@ static void CL_ParseSoundPacketGS( sizebuf_t *msg )
static void CL_ParseSpawnStaticSound( sizebuf_t *msg )
{
vec3_t pos;
int sound, entnum, pitch, flags;
int handle, entnum, pitch, flags;
float volume, attn;
sound_t handle = 0;
MSG_ReadVec3Coord( msg, pos );
sound = MSG_ReadShort( msg );
handle = MSG_ReadShort( msg );
volume = MSG_ReadByte( msg ) * ( 1.0f / 255.0f );
attn = MSG_ReadByte( msg ) * ( 1.0f / 64.0f );
entnum = MSG_ReadShort( msg );
pitch = MSG_ReadByte( msg );
flags = MSG_ReadByte( msg );
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
@@ -578,18 +567,25 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
if( CL_ParseCommonHLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
if( CL_ParseCommonDLLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
case svc_spawnstatic:
case svc_goldsrc_damage:
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
break;
case svc_disconnect:
s = MSG_ReadString( msg );
if( !COM_StringEmpty( s ))
if( COM_CheckStringEmpty( s ))
Con_Printf( "Server issued disconnect. Reason: %s\n", s );
CL_Drop ();
Host_AbortCurrentFrame ();
@@ -605,10 +601,47 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
if( param1 != PROTOCOL_GOLDSRC_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", param1, PROTOCOL_GOLDSRC_VERSION );
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseSoundPacketGS( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_GOLDSRC );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
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
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_GOLDSRC );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_GOLDSRC );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
break;
case svc_deltatable:
Delta_ParseTableField_GS( msg );
break;
@@ -628,9 +661,8 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
CL_UpdateUserPings( msg );
MSG_EndBitWriting( msg );
break;
case svc_goldsrc_damage:
case svc_spawnstatic:
// this does nothing
case svc_particle:
CL_ParseParticles( msg, PROTO_GOLDSRC );
break;
case svc_event_reliable:
MSG_StartBitWriting( msg );
@@ -646,18 +678,35 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_setpause:
cl.paused = ( MSG_ReadByte( msg ) != 0 );
break;
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
case svc_signonnum:
CL_ParseSignon( msg, PROTO_GOLDSRC );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_goldsrc_spawnstaticsound:
CL_ParseSpawnStaticSound( msg );
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_goldsrc_decalname:
param1 = MSG_ReadByte( msg );
s = MSG_ReadString( msg );
Q_strncpy( host.draw_decals[param1], s, sizeof( host.draw_decals[param1] ));
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg, PROTO_GOLDSRC );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
@@ -668,6 +717,10 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
MSG_StartBitWriting( msg );
CL_ParseResourceList( msg, PROTO_GOLDSRC );
@@ -676,6 +729,34 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_deltamovevars:
CL_ParseNewMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, PROTO_GOLDSRC );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_goldsrc_sendextrainfo:
CL_ParseExtraInfo( msg );
break;
@@ -685,8 +766,17 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ );
MSG_ReadFloat( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_GOLDSRC );
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}

View File

@@ -18,6 +18,7 @@ GNU General Public License for more details.
#include "const.h"
#include "cl_tent.h"
#include "pm_local.h"
#include "particledef.h"
#include "studio.h"
#define MAX_FORWARD 6 // forward probes for set idealpitch
@@ -775,7 +776,7 @@ void CL_InitClientMove( void )
clgame.pmove->COM_FileSize = COM_FileSize;
clgame.pmove->COM_LoadFile = COM_LoadFile;
clgame.pmove->COM_FreeFile = COM_FreeFile;
clgame.pmove->memfgets = Q_memfgets;
clgame.pmove->memfgets = COM_MemFgets;
clgame.pmove->PM_PlaySound = pfnPlaySound;
clgame.pmove->PM_TraceTexture = PM_CL_TraceTexture;
clgame.pmove->PM_PlaybackEventFull = pfnPlaybackEventFull;
@@ -826,6 +827,7 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
pmove->flFallVelocity = ps->flFallVelocity;
pmove->flSwimTime = (float)cd->flSwimTime;
VectorCopy( cd->punchangle, pmove->punchangle );
pmove->flNextPrimaryAttack = 0.0f; // not used by PM_ code
pmove->effects = ps->effects;
pmove->flags = cd->flags;
pmove->gravity = ps->gravity;
@@ -1009,11 +1011,6 @@ void CL_PredictMovement( qboolean repredicting )
if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK )
return;
// goldsrc checks for intermission here, so it technically allows sending commands
// during intermission but completely disables any client updates, predicted or not
if( cl.intermission )
return;
// this is the last frame received from the server
frame = &cl.frames[cl.parsecountmod];
@@ -1101,7 +1098,7 @@ void CL_PredictMovement( qboolean repredicting )
// now interpolate some fraction of the final frame
if( to_cmd->senttime != from_cmd->senttime )
f = bound( 0.0, ( host.realtime - from_cmd->senttime ) / ( to_cmd->senttime - from_cmd->senttime ), 1.0 );
f = bound( 0.0, (host.realtime - from_cmd->senttime) / (to_cmd->senttime - from_cmd->senttime) * 0.1, 1.0 );
else f = 0.0;
if( CL_PlayerTeleported( from, to ))

Some files were not shown because too many files have changed in this diff Show More