diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3b5ae35c..2cb22358 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -52,13 +52,13 @@ jobs:
- name: Build on Linux
if: startsWith(matrix.os, 'ubuntu')
run: |
- schroot --chroot steamrt_scout_i386 -- cmake -B build -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DCMAKE_INSTALL_PREFIX="$PWD/dist"
+ schroot --chroot steamrt_scout_i386 -- cmake -DCMAKE_BUILD_TYPE=Release -DPOLLY=ON -B build -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DCMAKE_INSTALL_PREFIX="$PWD/dist"
schroot --chroot steamrt_scout_i386 -- cmake --build build --target all
schroot --chroot steamrt_scout_i386 -- cmake --build build --target install
- name: Build on Linux with vgui
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.cc, 'gcc')
run: |
- schroot --chroot steamrt_scout_i386 -- cmake -B build-vgui -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VGUI=ON -DCMAKE_INSTALL_PREFIX="$PWD/dist-vgui"
+ schroot --chroot steamrt_scout_i386 -- cmake -DCMAKE_BUILD_TYPE=Release -DPOLLY=ON -B build-vgui -S . -DCMAKE_EXE_LINKER_FLAGS="-Wl,--no-undefined" -DUSE_VGUI=ON -DCMAKE_INSTALL_PREFIX="$PWD/dist-vgui"
cp vgui_support/vgui-dev/lib/vgui.so build-vgui/cl_dll
schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target all
schroot --chroot steamrt_scout_i386 -- cmake --build build-vgui --target install
diff --git a/.gitignore b/.gitignore
index 42594b50..2c5017bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,13 @@ CMakeSettings.json
CMakeFiles
CMakeCache.txt
Makefile
+
+# Android Studio/Gradle
+.gradle/
+.externalNativeBuild
+.cxx/
+.idea/
+local.properties
+.project
+.classpath
+.settings
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e2ea26c0..04cf5bce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,6 +33,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(CheckIncludeFile)
include(CheckCSourceCompiles)
include(VSForceXPToolchain) # Force XP toolchain for Visual Studio
+include(CheckIPOSupported)
project (HLSDK-PORTABLE)
@@ -46,16 +47,37 @@ option(USE_NOVGUI_SCOREBOARD "Prefer non-VGUI Scoreboard when USE_VGUI is enable
option(USE_VOICEMGR "Enable VOICE MANAGER." OFF)
option(BUILD_CLIENT "Build client dll" ON)
option(BUILD_SERVER "Build server dll" ON)
+option(POLLY "Enable pollyhedral optimization" OFF)
-if (CMAKE_SIZEOF_VOID_P EQUAL 4 OR
+if(CMAKE_SIZEOF_VOID_P EQUAL 4 OR
((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "x64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
- OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")))
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X86_64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "EM64T")))
option(64BIT "Disable auto -m32 appending to compiler flags" OFF)
- option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" ON)
else()
option(64BIT "Disable auto -m32 appending to compiler flags" ON)
+endif()
+
+# It seems CMAKE_SYSTEM_PROCESSOR parameter completely useless for APPLE platform,
+# so may need to set options here manually.
+if((WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ AND (((CMAKE_SYSTEM_PROCESSOR STREQUAL "x64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X86_64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "EM64T") AND NOT 64BIT)
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "x86"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "X86"
+ OR CMAKE_SYSTEM_PROCESSOR STREQUAL "i386"))
+ option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" ON)
+else()
option(GOLDSOURCE_SUPPORT "Build goldsource compatible client library" OFF)
endif()
@@ -131,6 +153,13 @@ if(VITA)
add_compile_options(-fno-use-cxa-atexit)
endif()
+check_ipo_supported(RESULT HAVE_LTO OUTPUT LTO_ERROR)
+if(HAVE_LTO)
+ message(STATUS "IPO / LTO enabled")
+else()
+ message(STATUS "IPO / LTO not supported: <${LTO_ERROR}>")
+endif()
+
check_include_file("tgmath.h" HAVE_TGMATH_H)
if(HAVE_TGMATH_H)
if(NOT MSVC)
@@ -157,3 +186,11 @@ endif()
if(NOT BUILD_SERVER AND NOT BUILD_CLIENT)
message(FATAL_ERROR "Nothing to build")
endif()
+
+if(POLLY)
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ add_compile_options(-mllvm -polly)
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ add_compile_options(-fgraphite-identity -floop-interchange -floop-block)
+ endif()
+endif()
diff --git a/README.md b/README.md
index 706fa58a..3bff2f52 100644
--- a/README.md
+++ b/README.md
@@ -164,7 +164,7 @@ sudo ./setup_chroot.sh --i386 --tarball ./com.valvesoftware.SteamRuntime.Sdk-i38
Now you can use cmake and make prepending the commands with `schroot --chroot steamrt_scout_i386 --`:
```
-schroot --chroot steamrt_scout_i386 -- cmake -B build-in-steamrt -S .
+schroot --chroot steamrt_scout_i386 -- cmake -DCMAKE_BUILD_TYPE=Release -B build-in-steamrt -S .
schroot --chroot steamrt_scout_i386 -- cmake --build build-in-steamrt
```
@@ -180,13 +180,20 @@ sudo apt install cmake build-essential gcc-multilib g++-multilib libsdl2-dev:i38
### Building
```
-cmake -B build -S .
+cmake -DCMAKE_BUILD_TYPE=Release -B build -S .
cmake --build build
```
Note that the libraries built this way might be not compatible with Steam Half-Life. If you have such issue you can configure it to build statically with c++ and gcc libraries:
```
-cmake .. -DCMAKE_C_FLAGS="-static-libstdc++ -static-libgcc"
+cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc" -B build -S .
+cmake --build build
+```
+
+Alternatively, you can avoid libstdc++/libgcc_s linking using small libsupc++ library and optimization build flags instead(Really just set Release build type and set C compiler as C++ compiler):
+```
+cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=cc -B build -S .
+cmake --build build
```
To ensure portability it's still better to build using Steam Runtime or another chroot of some older distro.
@@ -229,13 +236,36 @@ Insert your actual user name in place of `yourusername`.
Prepend any make or cmake call with `schroot -c jessie --`:
```
-schroot --chroot jessie -- cmake -B build-in-chroot -S .
+schroot --chroot jessie -- cmake -DCMAKE_BUILD_TYPE=Release -B build-in-chroot -S .
schroot --chroot jessie -- cmake --build build-in-chroot
```
## Android
+1. Set up [Android Studio/Android SDK](https://developer.android.com/studio).
-TODO
+### Android Studio
+Open the project located in the `android` folder and build.
+
+### Command-line
+```
+cd android
+./gradlew assembleRelease
+```
+
+### Customizing the build
+settings.gradle:
+* **rootProject.name** - project name displayed in Android Studio (optional).
+
+app/build.gradle:
+* **android->namespace** and **android->defaultConfig->applicationId** - set both to desired package name.
+* **getBuildNum** function - set **releaseDate** variable as desired.
+
+app/java/su/xash/hlsdk/MainActivity.java:
+* **.putExtra("gamedir", ...)** - set desired gamedir.
+
+src/main/AndroidManifest.xml:
+* **application->android:label** - set desired application name.
+* **su.xash.engine.gamedir** value - set to same as above.
## Nintendo Switch
@@ -307,7 +337,13 @@ Install C and C++ compilers (like gcc or clang), cmake and make.
### Building
```
-cmake -B build -S .
+cmake -DCMAKE_BUILD_TYPE=Release -B build -S .
+cmake --build build
+```
+
+Force 64-bit build:
+```
+cmake -DCMAKE_BUILD_TYPE=Release -D64BIT=1 -B build -S .
cmake --build build
```
@@ -316,15 +352,22 @@ cmake --build build
To use waf, you need to install python (2.7 minimum)
```
-(./waf configure -T release)
-(./waf)
+./waf configure -T release
+./waf
+```
+
+Force 64-bit build:
+```
+./waf configure -T release -8
+./waf
```
## Build options
Some useful build options that can be set during the cmake step.
-* **GOLDSOURCE_SUPPORT** - allows to turn off/on the support for GoldSource input. Set to **ON** by default on Windows and Linux, **OFF** on other platforms.
+* **GOLDSOURCE_SUPPORT** - allows to turn off/on the support for GoldSource input. Set to **ON** by default on x86 Windows and x86 Linux, **OFF** on other platforms.
+* **64BIT** - allows to turn off/on 64-bit build. Set to **OFF** by default on x86_64 Windows, x86_64 Linux and 32-bit platforms, **ON** on other 64-bit platforms.
* **USE_VGUI** - whether to use VGUI library. **OFF** by default. You need to init `vgui_support` submodule in order to build with VGUI.
This list is incomplete. Look at `CMakeLists.txt` to see all available options.
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 00000000..9952c3d1
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,73 @@
+import java.time.LocalDateTime
+import java.time.Month
+import java.time.temporal.ChronoUnit
+
+apply plugin: 'com.android.application'
+
+android {
+ ndkVersion '26.1.10909125'
+ namespace 'com.example.hlsdk'
+
+ defaultConfig {
+ applicationId 'com.example.hlsdk'
+ versionName '1.0'
+ versionCode getBuildNum()
+ minSdkVersion 3
+ targetSdk 34
+ compileSdk 34
+
+ externalNativeBuild {
+ cmake {
+ arguments '-DPOLLY=ON'
+ }
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ version '3.22.1'
+ path file('../../CMakeLists.txt')
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ buildTypes {
+ debug {
+ minifyEnabled false
+ shrinkResources false
+ debuggable true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+ }
+ release {
+ minifyEnabled false
+ shrinkResources false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+ }
+ }
+
+ lint {
+ abortOnError false
+ }
+
+ androidResources {
+ noCompress += ''
+ }
+
+ packagingOptions {
+ jniLibs {
+ useLegacyPackaging = true
+ }
+ }
+}
+
+static def getBuildNum() {
+ LocalDateTime now = LocalDateTime.now()
+ LocalDateTime releaseDate = LocalDateTime.of(2023, Month.DECEMBER, 28, 0, 0, 0)
+ int qBuildNum = releaseDate.until(now, ChronoUnit.DAYS)
+ int minuteOfDay = now.getHour() * 60 + now.getMinute()
+ return qBuildNum * 10000 + minuteOfDay
+}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..d928f396
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/java/su/xash/hlsdk/MainActivity.java b/android/app/src/main/java/su/xash/hlsdk/MainActivity.java
new file mode 100644
index 00000000..5d1dd353
--- /dev/null
+++ b/android/app/src/main/java/su/xash/hlsdk/MainActivity.java
@@ -0,0 +1,37 @@
+package su.xash.hlsdk;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class MainActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ String pkg = "su.xash.engine.test";
+
+ try {
+ getPackageManager().getPackageInfo(pkg, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ try {
+ pkg = "su.xash.engine";
+ getPackageManager().getPackageInfo(pkg, 0);
+ } catch (PackageManager.NameNotFoundException ex) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=su.xash.engine")).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
+ finish();
+ return;
+ }
+ }
+
+ startActivity(new Intent().setComponent(new ComponentName(pkg, "su.xash.engine.XashActivity"))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .putExtra("gamedir", "valve")
+ .putExtra("gamelibdir", getApplicationInfo().nativeLibraryDir)
+ .putExtra("package", getPackageName()));
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 00000000..61060cd6
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,17 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ google()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:8.2.0'
+ }
+}
+
+allprojects {
+ repositories {
+ mavenCentral()
+ google()
+ }
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 00000000..87cc72da
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=384m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# android.useDeprecatedNdk=true
+android.enableJetifier=true
+android.useAndroidX=true
\ No newline at end of file
diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..2b338a93
Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..61656665
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Dec 28 14:36:02 EET 2023
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/android/gradlew b/android/gradlew
new file mode 100755
index 00000000..9d82f789
--- /dev/null
+++ b/android/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/gradlew.bat b/android/gradlew.bat
new file mode 100644
index 00000000..8a0b282a
--- /dev/null
+++ b/android/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 00000000..8b31d676
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1,3 @@
+include ':app'
+
+rootProject.name = 'hlsdk-portable'
\ No newline at end of file
diff --git a/cl_dll/CMakeLists.txt b/cl_dll/CMakeLists.txt
index e12b2a13..e5fdfaa0 100644
--- a/cl_dll/CMakeLists.txt
+++ b/cl_dll/CMakeLists.txt
@@ -20,7 +20,7 @@
# SOFTWARE.
#
-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.9)
project (CLDLL)
set (CLDLL_LIBRARY client)
@@ -29,13 +29,25 @@ add_definitions(-DCLIENT_DLL)
if(NOT MSVC)
add_compile_options(-fno-exceptions) # GCC/Clang flag
- add_compile_options(-Wno-write-strings) # GCC/Clang flag
+ add_compile_options(-fno-rtti) # GCC/Clang flag
add_compile_options(-fvisibility=hidden) # GCC/Clang flag
add_definitions(-D_LINUX -DLINUX) # It seems enough for all non-Win32 systems
add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp)
if(NOT MINGW)
add_definitions(-D_snprintf=snprintf -D_vsnprintf=vsnprintf)
endif()
+ if(CMAKE_BUILD_TYPE MATCHES "Release"
+ OR (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo"
+ AND CMAKE_SYSTEM_NAME STREQUAL "Android"))
+ add_compile_options(-fno-unwind-tables -fno-asynchronous-unwind-tables) # GCC/Clang flag
+ add_compile_options(-fomit-frame-pointer) # GCC/Clang flag
+ add_compile_options(-ftree-vectorize) # GCC/Clang flag
+ add_compile_options(-funsafe-math-optimizations) # GCC/Clang flag
+ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
+ add_compile_options(-O3 -DNDEBUG) # gradle compiles release builds with RelWithDebInfo(-O2 -g) and strips debug symbols.
+ target_link_options(${CLDLL_LIBRARY} PUBLIC "LINKER:-O3")
+ endif()
+ endif()
else()
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
endif()
@@ -219,8 +231,16 @@ if(MSVC)
set_property(TARGET ${CLDLL_LIBRARY} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
endif()
+if(HAVE_LTO)
+ set_property(TARGET ${CLDLL_LIBRARY} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+endif()
+
install( TARGETS ${CLDLL_LIBRARY}
DESTINATION "${GAMEDIR}/${CLIENT_INSTALL_DIR}/"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE )
+
+add_custom_command(TARGET ${CLDLL_LIBRARY}
+ POST_BUILD DEPENDS ${CLDLL_LIBRARY}
+ COMMAND $<$:${CMAKE_STRIP}> -s $)
diff --git a/cl_dll/cl_util.h b/cl_dll/cl_util.h
index 91615660..65275c69 100644
--- a/cl_dll/cl_util.h
+++ b/cl_dll/cl_util.h
@@ -166,7 +166,8 @@ void VectorScale( const float *in, float scale, float *out );
float VectorNormalize( float *v );
void VectorInverse( float *v );
-extern vec3_t vec3_origin;
+// extern vec3_t vec3_origin;
+extern float vec3_origin[3];
// disable 'possible loss of data converting float to int' warning message
#pragma warning( disable: 4244 )
diff --git a/cl_dll/util.cpp b/cl_dll/util.cpp
index 7d6b6669..ec5c796f 100644
--- a/cl_dll/util.cpp
+++ b/cl_dll/util.cpp
@@ -33,11 +33,11 @@
#if !defined(M_PI_F)
#define M_PI_F (float)M_PI
#endif
-extern vec3_t vec3_origin;
+// extern vec3_t vec3_origin;
// if C++ mangling differs from C symbol name
#if _MSC_VER || __WATCOMC__
-vec3_t vec3_origin;
+float vec3_origin[3];
#endif
float Length( const float *v )
diff --git a/dlls/CMakeLists.txt b/dlls/CMakeLists.txt
index 5b5cd22a..afe449a7 100644
--- a/dlls/CMakeLists.txt
+++ b/dlls/CMakeLists.txt
@@ -20,17 +20,30 @@
# SOFTWARE.
#
-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.9)
project (SVDLL)
set (SVDLL_LIBRARY server)
if(NOT MSVC)
add_compile_options(-fno-exceptions) # GCC/Clang flag
+ add_compile_options(-fno-rtti) # GCC/Clang flag
add_compile_options(-Wno-invalid-offsetof) # GCC/Clang flag
add_compile_options(-fvisibility=hidden) # GCC/Clang flag
add_definitions(-D_LINUX) # It seems enough for all non-Win32 systems
add_definitions(-Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf )
+ if(CMAKE_BUILD_TYPE MATCHES "Release"
+ OR (CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo"
+ AND CMAKE_SYSTEM_NAME STREQUAL "Android"))
+ add_compile_options(-fno-unwind-tables -fno-asynchronous-unwind-tables) # GCC/Clang flag
+ add_compile_options(-fomit-frame-pointer) # GCC/Clang flag
+ add_compile_options(-ftree-vectorize) # GCC/Clang flag
+ add_compile_options(-funsafe-math-optimizations) # GCC/Clang flag
+ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
+ add_compile_options(-O3 -DNDEBUG) # gradle compiles release builds with RelWithDebInfo(-O2 -g) and strips debug symbols.
+ target_link_options(${SVDLL_LIBRARY} PUBLIC "LINKER:-O3")
+ endif()
+ endif()
else()
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
endif()
@@ -47,7 +60,6 @@ set (SVDLL_SOURCES
gearbox/eagle.cpp
gearbox/fgrunt.cpp
gearbox/func_tank_of.cpp
-# gearbox/gearbox_client.cpp
gearbox/gearbox_effects.cpp
gearbox/gearbox_triggers.cpp
gearbox/gearbox_utils.cpp
@@ -224,8 +236,16 @@ if(MSVC)
set_property(TARGET ${SVDLL_LIBRARY} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
endif()
+if(HAVE_LTO)
+ set_property(TARGET ${SVDLL_LIBRARY} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+endif()
+
install( TARGETS ${SVDLL_LIBRARY}
DESTINATION "${GAMEDIR}/${SERVER_INSTALL_DIR}/"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE)
+
+add_custom_command(TARGET ${SVDLL_LIBRARY}
+ POST_BUILD DEPENDS ${SVDLL_LIBRARY}
+ COMMAND $<$:${CMAKE_STRIP}> -s $)
diff --git a/dlls/client.cpp b/dlls/client.cpp
index 1e815ff7..c95cd17c 100644
--- a/dlls/client.cpp
+++ b/dlls/client.cpp
@@ -941,28 +941,6 @@ void ClientPrecache( void )
// Teleport sounds. Used by trigger_xen_return
PRECACHE_SOUND( "debris/beamstart7.wav" );
-
- PRECACHE_MODEL( "models/flag.mdl" );
- PRECACHE_MODEL( "models/civ_stand.mdl" );
- PRECACHE_MODEL( "models/mil_stand.mdl" );
-
- PRECACHE_MODEL( "models/w_accelerator.mdl" );
- PRECACHE_MODEL( "models/w_backpack.mdl" );
- PRECACHE_MODEL( "models/w_fgrenade.mdl" );
- PRECACHE_MODEL( "models/w_health.mdl" );
- PRECACHE_MODEL( "models/w_icon.mdl" );
- PRECACHE_MODEL( "models/w_jumppack.mdl" );
- PRECACHE_MODEL( "models/w_porthev.mdl" );
-
- PRECACHE_SOUND( "ctf/bm_flagtaken.wav" );
- PRECACHE_SOUND( "ctf/civ_flag_capture.wav" );
- PRECACHE_SOUND( "ctf/itemthrow.wav" );
- PRECACHE_SOUND( "ctf/marine_flag_capture.wav" );
- PRECACHE_SOUND( "ctf/pow_armor_charge.wav" );
- PRECACHE_SOUND( "ctf/pow_backpack.wav" );
- PRECACHE_SOUND( "ctf/pow_big_jump.wav" );
- PRECACHE_SOUND( "ctf/pow_health_charge.wav" );
- PRECACHE_SOUND( "ctf/soldier_flagtaken.wav" );
}
/*
diff --git a/dlls/game.cpp b/dlls/game.cpp
index 033c1f19..051cc325 100644
--- a/dlls/game.cpp
+++ b/dlls/game.cpp
@@ -726,7 +726,7 @@ cvar_t sk_plr_spore3 = { "sk_plr_spore3", "0" };
void GameDLLInit( void )
{
// Register cvars here:
- if( CVAR_GET_POINTER( "build" ) )
+ if( !CVAR_GET_POINTER( "sv_language" ) )
g_fIsXash3D = TRUE;
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
diff --git a/dlls/gearbox/ctf_gamerules.cpp b/dlls/gearbox/ctf_gamerules.cpp
index 6c5c1608..05848eb3 100644
--- a/dlls/gearbox/ctf_gamerules.cpp
+++ b/dlls/gearbox/ctf_gamerules.cpp
@@ -200,8 +200,8 @@ void CCTFMultiplay::Think(void)
frags_remaining = bestfrags;
}
- if (!g_bSpawnedRunes)
- SpawnRunes();
+ //if (!g_bSpawnedRunes)
+ // SpawnRunes();
if (m_flFlagStatusTime && m_flFlagStatusTime <= gpGlobals->time)
GetFlagStatus(NULL);
diff --git a/dlls/gearbox/ctf_powerups.cpp b/dlls/gearbox/ctf_powerups.cpp
index 1bbbd66d..855ff348 100644
--- a/dlls/gearbox/ctf_powerups.cpp
+++ b/dlls/gearbox/ctf_powerups.cpp
@@ -114,12 +114,18 @@ void CPowerupCTFBase::Spawn(void)
m_iszPrintName = ALLOC_STRING(printname);
}
-
- SET_MODEL(ENT(pev), SelectRuneRandom(&m_iRuneFlag) );
+ PRECACHE_MODEL("models/w_accelerator.mdl");
+ PRECACHE_MODEL("models/w_backpack.mdl");
+ PRECACHE_MODEL("models/w_health.mdl");
+ PRECACHE_MODEL("models/w_jumppack.mdl");
+ PRECACHE_MODEL("models/w_porthev.mdl");
+ SET_MODEL(ENT(pev), modelname);
}
else
{
- SET_MODEL(ENT(pev), GetRuneModel());
+ const char* modelname = GetRuneModel();
+ PRECACHE_MODEL(modelname);
+ SET_MODEL(ENT(pev), modelname);
m_iRuneFlag = GetRuneFlag();
}
diff --git a/dlls/gearbox/gearbox_client.cpp b/dlls/gearbox/gearbox_client.cpp
deleted file mode 100644
index c585e68e..00000000
--- a/dlls/gearbox/gearbox_client.cpp
+++ /dev/null
@@ -1,2096 +0,0 @@
-/***
-*
-* Copyright (c) 1996-2001, 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.
-*
-****/
-// Robin, 4-22-98: Moved set_suicide_frame() here from player.cpp to allow us to
-// have one without a hardcoded player.mdl in tf_client.cpp
-
-/*
-
-===== client.cpp ========================================================
-
- client/server game specific stuff
-
-*/
-
-#include "extdll.h"
-#include "util.h"
-#include "cbase.h"
-#include "saverestore.h"
-#include "player.h"
-#include "spectator.h"
-#include "client.h"
-#include "soundent.h"
-#include "gamerules.h"
-#include "game.h"
-#include "customentity.h"
-#include "weapons.h"
-#include "weaponinfo.h"
-#include "usercmd.h"
-#include "netadr.h"
-#include "pm_shared.h"
-
-#if defined ( GEARBOX_DLL )
-#include "gearbox_player.h"
-#endif // GEARBOX_DLL
-
-#if !defined ( _WIN32 )
-#include
-#endif
-
-extern DLL_GLOBAL ULONG g_ulModelIndexPlayer;
-extern DLL_GLOBAL BOOL g_fGameOver;
-extern DLL_GLOBAL int g_iSkillLevel;
-extern DLL_GLOBAL ULONG g_ulFrameCount;
-
-#if defined( GEARBOX_CTF )
-char* GetTeamName(int team);
-#endif
-
-extern void CopyToBodyQue(entvars_t* pev);
-extern int giPrecacheGrunt;
-extern int gmsgSayText;
-
-extern cvar_t allow_spectators;
-
-extern int g_teamplay;
-
-void LinkUserMessages( void );
-void LinkUserMessages_Op4( void );
-
-/*
- * used by kill command and disconnect command
- * ROBIN: Moved here from player.cpp, to allow multiple player models
- */
-void set_suicide_frame(entvars_t* pev)
-{
- if (!FStrEq(STRING(pev->model), "models/player.mdl"))
- return; // allready gibbed
-
-// pev->frame = $deatha11;
- pev->solid = SOLID_NOT;
- pev->movetype = MOVETYPE_TOSS;
- pev->deadflag = DEAD_DEAD;
- pev->nextthink = -1;
-}
-
-
-/*
-===========
-ClientConnect
-
-called when a player connects to a server
-============
-*/
-BOOL ClientConnect( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] )
-{
- return g_pGameRules->ClientConnected( pEntity, pszName, pszAddress, szRejectReason );
-
-// a client connecting during an intermission can cause problems
-// if (intermission_running)
-// ExitIntermission ();
-
-}
-
-
-/*
-===========
-ClientDisconnect
-
-called when a player disconnects from a server
-
-GLOBALS ASSUMED SET: g_fGameOver
-============
-*/
-void ClientDisconnect( edict_t *pEntity )
-{
- if (g_fGameOver)
- return;
-
- char text[256] = "" ;
- if ( pEntity->v.netname )
- _snprintf( text, sizeof(text), "- %s has left the game\n", STRING(pEntity->v.netname) );
- text[ sizeof(text) - 1 ] = 0;
- MESSAGE_BEGIN( MSG_ALL, gmsgSayText, NULL );
- WRITE_BYTE( ENTINDEX(pEntity) );
- WRITE_STRING( text );
- MESSAGE_END();
-
- CSound *pSound;
- pSound = CSoundEnt::SoundPointerForIndex( CSoundEnt::ClientSoundIndex( pEntity ) );
- {
- // since this client isn't around to think anymore, reset their sound.
- if ( pSound )
- {
- pSound->Reset();
- }
- }
-
-// since the edict doesn't get deleted, fix it so it doesn't interfere.
- pEntity->v.takedamage = DAMAGE_NO;// don't attract autoaim
- pEntity->v.solid = SOLID_NOT;// nonsolid
- UTIL_SetOrigin ( &pEntity->v, pEntity->v.origin );
-
- g_pGameRules->ClientDisconnected( pEntity );
-}
-
-
-// called by ClientKill and DeadThink
-void respawn(entvars_t* pev, BOOL fCopyCorpse)
-{
- if (gpGlobals->coop || gpGlobals->deathmatch)
- {
- if ( fCopyCorpse )
- {
- // make a copy of the dead body for appearances sake
- CopyToBodyQue(pev);
- }
-
- // respawn player
-#if 1
- GetClassPtr( (CGearboxPlayer *)pev)->Spawn( );
-#else
- GetClassPtr( (CBasePlayer *)pev)->Spawn( );
-#endif
- }
- else
- { // restart the entire server
- SERVER_COMMAND("reload\n");
- }
-}
-
-/*
-============
-ClientKill
-
-Player entered the suicide command
-
-GLOBALS ASSUMED SET: g_ulModelIndexPlayer
-============
-*/
-void ClientKill( edict_t *pEntity )
-{
- entvars_t *pev = &pEntity->v;
-
-#if 1
- CGearboxPlayer *pl = (CGearboxPlayer*)CGearboxPlayer::Instance(pev);
-#else
- CBasePlayer *pl = (CBasePlayer*) CBasePlayer::Instance( pev );
-#endif
-
- if ( pl->m_fNextSuicideTime > gpGlobals->time )
- return; // prevent suiciding too ofter
-
- pl->m_fNextSuicideTime = gpGlobals->time + 1; // don't let them suicide for 5 seconds after suiciding
-
- // have the player kill themself
- pev->health = 0;
- pl->Killed( pev, GIB_NEVER );
-
-// pev->modelindex = g_ulModelIndexPlayer;
-// pev->frags -= 2; // extra penalty
-// respawn( pev );
-}
-
-/*
-===========
-ClientPutInServer
-
-called each time a player is spawned
-============
-*/
-void ClientPutInServer( edict_t *pEntity )
-{
-#if 1
- CGearboxPlayer *pPlayer;
-#else
- CBasePlayer *pPlayer;
-#endif
-
- entvars_t *pev = &pEntity->v;
-
-#if 1
- pPlayer = GetClassPtr((CGearboxPlayer *)pev);
-#else
- pPlayer = GetClassPtr((CBasePlayer *)pev);
-#endif
- pPlayer->SetCustomDecalFrames(-1); // Assume none;
-
- // Allocate a CBasePlayer for pev, and call spawn
- pPlayer->Spawn() ;
-
- // Reset interpolation during first frame
- pPlayer->pev->effects |= EF_NOINTERP;
-
- pPlayer->pev->iuser1 = 0; // disable any spec modes
- pPlayer->pev->iuser2 = 0;
-}
-
-#include "voice_gamemgr.h"
-extern CVoiceGameMgr g_VoiceGameMgr;
-
-
-
-#if defined( _MSC_VER ) || defined( WIN32 )
-typedef wchar_t uchar16;
-typedef unsigned int uchar32;
-#else
-typedef unsigned short uchar16;
-typedef wchar_t uchar32;
-#endif
-
-//-----------------------------------------------------------------------------
-// Purpose: determine if a uchar32 represents a valid Unicode code point
-//-----------------------------------------------------------------------------
-bool Q_IsValidUChar32( uchar32 uVal )
-{
- // Values > 0x10FFFF are explicitly invalid; ditto for UTF-16 surrogate halves,
- // values ending in FFFE or FFFF, or values in the 0x00FDD0-0x00FDEF reserved range
- return ( uVal < 0x110000u ) && ( (uVal - 0x00D800u) > 0x7FFu ) && ( (uVal & 0xFFFFu) < 0xFFFEu ) && ( ( uVal - 0x00FDD0u ) > 0x1Fu );
-}
-
-
-// Decode one character from a UTF-8 encoded string. Treats 6-byte CESU-8 sequences
-// as a single character, as if they were a correctly-encoded 4-byte UTF-8 sequence.
-int Q_UTF8ToUChar32( const char *pUTF8_, uchar32 &uValueOut, bool &bErrorOut )
-{
- const uint8 *pUTF8 = (const uint8 *)pUTF8_;
-
- int nBytes = 1;
- uint32 uValue = pUTF8[0];
- uint32 uMinValue = 0;
-
- // 0....... single byte
- if ( uValue < 0x80 )
- goto decodeFinishedNoCheck;
-
- // Expecting at least a two-byte sequence with 0xC0 <= first <= 0xF7 (110...... and 11110...)
- if ( (uValue - 0xC0u) > 0x37u || ( pUTF8[1] & 0xC0 ) != 0x80 )
- goto decodeError;
-
- uValue = (uValue << 6) - (0xC0 << 6) + pUTF8[1] - 0x80;
- nBytes = 2;
- uMinValue = 0x80;
-
- // 110..... two-byte lead byte
- if ( !( uValue & (0x20 << 6) ) )
- goto decodeFinished;
-
- // Expecting at least a three-byte sequence
- if ( ( pUTF8[2] & 0xC0 ) != 0x80 )
- goto decodeError;
-
- uValue = (uValue << 6) - (0x20 << 12) + pUTF8[2] - 0x80;
- nBytes = 3;
- uMinValue = 0x800;
-
- // 1110.... three-byte lead byte
- if ( !( uValue & (0x10 << 12) ) )
- goto decodeFinishedMaybeCESU8;
-
- // Expecting a four-byte sequence, longest permissible in UTF-8
- if ( ( pUTF8[3] & 0xC0 ) != 0x80 )
- goto decodeError;
-
- uValue = (uValue << 6) - (0x10 << 18) + pUTF8[3] - 0x80;
- nBytes = 4;
- uMinValue = 0x10000;
-
- // 11110... four-byte lead byte. fall through to finished.
-
-decodeFinished:
- if ( uValue >= uMinValue && Q_IsValidUChar32( uValue ) )
- {
-decodeFinishedNoCheck:
- uValueOut = uValue;
- bErrorOut = false;
- return nBytes;
- }
-decodeError:
- uValueOut = '?';
- bErrorOut = true;
- return nBytes;
-
-decodeFinishedMaybeCESU8:
- // Do we have a full UTF-16 surrogate pair that's been UTF-8 encoded afterwards?
- // That is, do we have 0xD800-0xDBFF followed by 0xDC00-0xDFFF? If so, decode it all.
- if ( ( uValue - 0xD800u ) < 0x400u && pUTF8[3] == 0xED && (uint8)( pUTF8[4] - 0xB0 ) < 0x10 && ( pUTF8[5] & 0xC0 ) == 0x80 )
- {
- uValue = 0x10000 + ( ( uValue - 0xD800u ) << 10 ) + ( (uint8)( pUTF8[4] - 0xB0 ) << 6 ) + pUTF8[5] - 0x80;
- nBytes = 6;
- uMinValue = 0x10000;
- }
- goto decodeFinished;
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns true if UTF-8 string contains invalid sequences.
-//-----------------------------------------------------------------------------
-bool Q_UnicodeValidate( const char *pUTF8 )
-{
- bool bError = false;
- while ( *pUTF8 )
- {
- uchar32 uVal;
- // Our UTF-8 decoder silently fixes up 6-byte CESU-8 (improperly re-encoded UTF-16) sequences.
- // However, these are technically not valid UTF-8. So if we eat 6 bytes at once, it's an error.
- int nCharSize = Q_UTF8ToUChar32( pUTF8, uVal, bError );
- if ( bError || nCharSize == 6 )
- return false;
- pUTF8 += nCharSize;
- }
- return true;
-}
-
-//// HOST_SAY
-// String comes in as
-// say blah blah blah
-// or as
-// blah blah blah
-//
-void Host_Say( edict_t *pEntity, int teamonly )
-{
-#if 1
- CGearboxPlayer *client;
-#else
- CBasePlayer *client;
-#endif
- int j;
- char *p;
- char text[128];
- char szTemp[256];
- const char *cpSay = "say";
- const char *cpSayTeam = "say_team";
- const char *pcmd = CMD_ARGV(0);
-
- // We can get a raw string now, without the "say " prepended
- if ( CMD_ARGC() == 0 )
- return;
-
- entvars_t *pev = &pEntity->v;
-#if 1
- CGearboxPlayer* player = GetClassPtr((CGearboxPlayer *)pev);
-#else
- CBasePlayer* player = GetClassPtr((CBasePlayer *)pev);
-#endif
-
- //Not yet.
- if ( player->m_flNextChatTime > gpGlobals->time )
- return;
-
- if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) )
- {
- if ( CMD_ARGC() >= 2 )
- {
- p = (char *)CMD_ARGS();
- }
- else
- {
- // say with a blank message, nothing to do
- return;
- }
- }
- else // Raw text, need to prepend argv[0]
- {
- if ( CMD_ARGC() >= 2 )
- {
- sprintf( szTemp, "%s %s", ( char * )pcmd, (char *)CMD_ARGS() );
- }
- else
- {
- // Just a one word command, use the first word...sigh
- sprintf( szTemp, "%s", ( char * )pcmd );
- }
- p = szTemp;
- }
-
-// remove quotes if present
- if (*p == '"')
- {
- p++;
- p[strlen(p)-1] = 0;
- }
-
-// make sure the text has content
-
- if ( !p || !p[0] || !Q_UnicodeValidate ( p ) )
- return; // no character found, so say nothing
-
-// turn on color set 2 (color on, no sound)
- // turn on color set 2 (color on, no sound)
- if ( player->IsObserver() && ( teamonly ) )
- sprintf( text, "%c(SPEC) %s: ", 2, STRING( pEntity->v.netname ) );
- else if ( teamonly )
- sprintf( text, "%c(TEAM) %s: ", 2, STRING( pEntity->v.netname ) );
- else
- sprintf( text, "%c%s: ", 2, STRING( pEntity->v.netname ) );
-
- j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator
- if ( (int)strlen(p) > j )
- p[j] = 0;
-
- strcat( text, p );
- strcat( text, "\n" );
-
-
- player->m_flNextChatTime = gpGlobals->time + CHAT_INTERVAL;
-
- // loop through all players
- // Start with the first player.
- // This may return the world in single player if the client types something between levels or during spawn
- // so check it, or it will infinite loop
-
- client = NULL;
-#if 1
- while ( ((client = (CGearboxPlayer*)UTIL_FindEntityByClassname( client, "player" )) != NULL) && (!FNullEnt(client->edict())) )
-#else
- while ( ((client = (CBasePlayer*)UTIL_FindEntityByClassname( client, "player" )) != NULL) && (!FNullEnt(client->edict())) )
-#endif
- {
- if ( !client->pev )
- continue;
-
- if ( client->edict() == pEntity )
- continue;
-
- if ( !(client->IsNetClient()) ) // Not a client ? (should never be true)
- continue;
-
- // can the receiver hear the sender? or has he muted him?
- if ( g_VoiceGameMgr.PlayerHasBlockedPlayer( client, player ) )
- continue;
-
- if ( !player->IsObserver() && teamonly && g_pGameRules->PlayerRelationship(client, CBaseEntity::Instance(pEntity)) != GR_TEAMMATE )
- continue;
-
- // Spectators can only talk to other specs
- if ( player->IsObserver() && teamonly )
- if ( !client->IsObserver() )
- continue;
-
- MESSAGE_BEGIN( MSG_ONE, gmsgSayText, NULL, client->pev );
- WRITE_BYTE( ENTINDEX(pEntity) );
- WRITE_STRING( text );
- MESSAGE_END();
-
- }
-
- // print to the sending client
- MESSAGE_BEGIN( MSG_ONE, gmsgSayText, NULL, &pEntity->v );
- WRITE_BYTE( ENTINDEX(pEntity) );
- WRITE_STRING( text );
- MESSAGE_END();
-
- // echo to server console
- g_engfuncs.pfnServerPrint( text );
-
- char * temp;
- if ( teamonly )
- temp = "say_team";
- else
- temp = "say";
-
- // team match?
- if ( g_teamplay )
- {
- UTIL_LogPrintf( "\"%s<%i><%s><%s>\" %s \"%s\"\n",
- STRING( pEntity->v.netname ),
- GETPLAYERUSERID( pEntity ),
- GETPLAYERAUTHID( pEntity ),
- g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pEntity ), "model" ),
- temp,
- p );
- }
- else
- {
- UTIL_LogPrintf( "\"%s<%i><%s><%i>\" %s \"%s\"\n",
- STRING( pEntity->v.netname ),
- GETPLAYERUSERID( pEntity ),
- GETPLAYERAUTHID( pEntity ),
- GETPLAYERUSERID( pEntity ),
- temp,
- p );
- }
-}
-
-
-/*
-===========
-ClientCommand
-called each time a player uses a "cmd" command
-============
-*/
-extern float g_flWeaponCheat;
-
-// Use CMD_ARGV, CMD_ARGV, and CMD_ARGC to get pointers the character string command.
-void ClientCommand( edict_t *pEntity )
-{
- const char *pcmd = CMD_ARGV(0);
- const char *pstr;
-
- // Is the client spawned yet?
- if ( !pEntity->pvPrivateData )
- return;
-
- entvars_t *pev = &pEntity->v;
-
- if ( FStrEq(pcmd, "say" ) )
- {
- Host_Say( pEntity, 0 );
- }
- else if ( FStrEq(pcmd, "say_team" ) )
- {
- Host_Say( pEntity, 1 );
- }
- else if ( FStrEq(pcmd, "fullupdate" ) )
- {
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->ForceClientDllUpdate();
-#else
- GetClassPtr((CBasePlayer *)pev)->ForceClientDllUpdate();
-#endif
- }
- else if ( FStrEq(pcmd, "give" ) )
- {
- if ( g_flWeaponCheat != 0.0)
- {
- int iszItem = ALLOC_STRING( CMD_ARGV(1) ); // Make a copy of the classname
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->GiveNamedItem( STRING(iszItem) );
-#else
- GetClassPtr((CBasePlayer *)pev)->GiveNamedItem( STRING(iszItem) );
-#endif
- }
- }
-
- else if ( FStrEq(pcmd, "drop" ) )
- {
- // player is dropping an item.
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->DropPlayerItem((char *)CMD_ARGV(1));
-#else
- etClassPtr((CBasePlayer *)pev)->DropPlayerItem((char *)CMD_ARGV(1));
-#endif
- }
- else if ( FStrEq(pcmd, "fov" ) )
- {
- if ( g_flWeaponCheat && CMD_ARGC() > 1)
- {
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->m_iFOV = atoi( CMD_ARGV(1) );
-#else
- GetClassPtr((CBasePlayer *)pev)->m_iFOV = atoi( CMD_ARGV(1) );
-#endif
- }
- else
- {
-#if 1
- CLIENT_PRINTF( pEntity, print_console, UTIL_VarArgs( "\"fov\" is \"%d\"\n", (int)GetClassPtr((CGearboxPlayer *)pev)->m_iFOV ) );
-#else
- CLIENT_PRINTF( pEntity, print_console, UTIL_VarArgs( "\"fov\" is \"%d\"\n", (int)GetClassPtr((CBasePlayer *)pev)->m_iFOV ) );
-#endif
- }
- }
- else if ( FStrEq(pcmd, "use" ) )
- {
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->SelectItem((char *)CMD_ARGV(1));
-#else
- GetClassPtr((CBasePlayer *)pev)->SelectItem((char *)CMD_ARGV(1));
-#endif
- }
- else if (((pstr = strstr(pcmd, "weapon_")) != NULL) && (pstr == pcmd))
- {
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->SelectItem(pcmd);
-#else
- GetClassPtr((CBasePlayer *)pev)->SelectItem(pcmd);
-#endif
- }
- else if (FStrEq(pcmd, "lastinv" ))
- {
-#if 1
- GetClassPtr((CGearboxPlayer *)pev)->SelectLastItem();
-#else
- GetClassPtr((CBasePlayer *)pev)->SelectLastItem();
-#endif
- }
- else if ( FStrEq( pcmd, "spectate" ) ) // clients wants to become a spectator
- {
- // always allow proxies to become a spectator
- if ( (pev->flags & FL_PROXY) || allow_spectators.value )
- {
-#if 1
- CGearboxPlayer * pPlayer = GetClassPtr((CGearboxPlayer *)pev);
-#else
- CBasePlayer * pPlayer = GetClassPtr((CBasePlayer *)pev);
-#endif
-
- edict_t *pentSpawnSpot = g_pGameRules->GetPlayerSpawnSpot( pPlayer );
- pPlayer->StartObserver( pev->origin, VARS(pentSpawnSpot)->angles);
-
- // notify other clients of player switching to spectator mode
- UTIL_ClientPrintAll( HUD_PRINTNOTIFY, UTIL_VarArgs( "%s switched to spectator mode\n",
- ( pev->netname && STRING(pev->netname)[0] != 0 ) ? STRING(pev->netname) : "unconnected" ) );
- }
- else
- ClientPrint( pev, HUD_PRINTCONSOLE, "Spectator mode is disabled.\n" );
-
- }
- else if ( FStrEq( pcmd, "specmode" ) ) // new spectator mode
- {
-#if 1
- CGearboxPlayer * pPlayer = GetClassPtr((CGearboxPlayer *)pev);
-#else
- CBasePlayer * pPlayer = GetClassPtr((CBasePlayer *)pev);
-#endif
-
- if ( pPlayer->IsObserver() )
- pPlayer->Observer_SetMode( atoi( CMD_ARGV(1) ) );
- }
- else if ( FStrEq(pcmd, "closemenus" ) )
- {
- // just ignore it
- }
- else if ( FStrEq( pcmd, "follownext" ) ) // follow next player
- {
-#if 1
- CGearboxPlayer * pPlayer = GetClassPtr((CGearboxPlayer *)pev);
-#else
- CBasePlayer * pPlayer = GetClassPtr((CBasePlayer *)pev);
-#endif
-
- if ( pPlayer->IsObserver() )
- pPlayer->Observer_FindNextPlayer( atoi( CMD_ARGV(1) )?true:false );
- }
-#if 1
- else if ( g_pGameRules->ClientCommand( GetClassPtr((CGearboxPlayer *)pev), pcmd ) )
-#else
- else if ( g_pGameRules->ClientCommand( GetClassPtr((CBasePlayer *)pev), pcmd ) )
-#endif
- {
- // MenuSelect returns true only if the command is properly handled, so don't print a warning
- }
- else
- {
- // tell the user they entered an unknown command
- char command[128];
-
- // check the length of the command (prevents crash)
- // max total length is 192 ...and we're adding a string below ("Unknown command: %s\n")
- strncpy( command, pcmd, 127 );
- command[127] = '\0';
-
- // tell the user they entered an unknown command
- ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", command ) );
- }
-}
-
-
-/*
-========================
-ClientUserInfoChanged
-
-called after the player changes
-userinfo - gives dll a chance to modify it before
-it gets sent into the rest of the engine.
-========================
-*/
-void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer )
-{
- // Is the client spawned yet?
- if ( !pEntity->pvPrivateData )
- return;
-
- // msg everyone if someone changes their name, and it isn't the first time (changing no name to current name)
- if ( pEntity->v.netname && STRING(pEntity->v.netname)[0] != 0 && !FStrEq( STRING(pEntity->v.netname), g_engfuncs.pfnInfoKeyValue( infobuffer, "name" )) )
- {
- char sName[256];
- char *pName = g_engfuncs.pfnInfoKeyValue( infobuffer, "name" );
- strncpy( sName, pName, sizeof(sName) - 1 );
- sName[ sizeof(sName) - 1 ] = '\0';
-
- // First parse the name and remove any %'s
- for ( char *pApersand = sName; pApersand != NULL && *pApersand != 0; pApersand++ )
- {
- // Replace it with a space
- if ( *pApersand == '%' )
- *pApersand = ' ';
- }
-
- // Set the name
- g_engfuncs.pfnSetClientKeyValue( ENTINDEX(pEntity), infobuffer, "name", sName );
-
- if (gpGlobals->maxClients > 1)
- {
- char text[256];
- sprintf( text, "* %s changed name to %s\n", STRING(pEntity->v.netname), g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) );
- MESSAGE_BEGIN( MSG_ALL, gmsgSayText, NULL );
- WRITE_BYTE( ENTINDEX(pEntity) );
- WRITE_STRING( text );
- MESSAGE_END();
- }
-
- // team match?
- if ( g_teamplay )
- {
- UTIL_LogPrintf( "\"%s<%i><%s><%s>\" changed name to \"%s\"\n",
- STRING( pEntity->v.netname ),
- GETPLAYERUSERID( pEntity ),
- GETPLAYERAUTHID( pEntity ),
- g_engfuncs.pfnInfoKeyValue( infobuffer, "model" ),
- g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) );
- }
- else
- {
- UTIL_LogPrintf( "\"%s<%i><%s><%i>\" changed name to \"%s\"\n",
- STRING( pEntity->v.netname ),
- GETPLAYERUSERID( pEntity ),
- GETPLAYERAUTHID( pEntity ),
- GETPLAYERUSERID( pEntity ),
- g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) );
- }
- }
-
-#if 1
- g_pGameRules->ClientUserInfoChanged( GetClassPtr((CGearboxPlayer *)&pEntity->v), infobuffer );
-#else
- g_pGameRules->ClientUserInfoChanged( GetClassPtr((CBasePlayer *)&pEntity->v), infobuffer );
-#endif
-}
-
-static int g_serveractive = 0;
-
-void ServerDeactivate( void )
-{
- // It's possible that the engine will call this function more times than is necessary
- // Therefore, only run it one time for each call to ServerActivate
- if ( g_serveractive != 1 )
- {
- return;
- }
-
- g_serveractive = 0;
-
- // Peform any shutdown operations here...
- //
-}
-
-void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
-{
- int i;
- CBaseEntity *pClass;
-
- // Every call to ServerActivate should be matched by a call to ServerDeactivate
- g_serveractive = 1;
-
- // Clients have not been initialized yet
- for ( i = 0; i < edictCount; i++ )
- {
- if ( pEdictList[i].free )
- continue;
-
- // Clients aren't necessarily initialized until ClientPutInServer()
- if ( i < clientMax || !pEdictList[i].pvPrivateData )
- continue;
-
- pClass = CBaseEntity::Instance( &pEdictList[i] );
- // Activate this entity if it's got a class & isn't dormant
- if ( pClass && !(pClass->pev->flags & FL_DORMANT) )
- {
- pClass->Activate();
- }
- else
- {
- ALERT( at_console, "Can't instance %s\n", STRING(pEdictList[i].v.classname) );
- }
- }
-
- // Link user messages here to make sure first client can get them...
- LinkUserMessages();
-
-#if 1
- // Link Op4 user messages.
- LinkUserMessages_Op4();
-#endif
-}
-
-
-/*
-================
-PlayerPreThink
-
-Called every frame before physics are run
-================
-*/
-void PlayerPreThink( edict_t *pEntity )
-{
- entvars_t *pev = &pEntity->v;
-
-#if 1
- CGearboxPlayer *pPlayer = (CGearboxPlayer *)GET_PRIVATE(pEntity);
-#else
- CBasePlayer *pPlayer = (CBasePlayer *)GET_PRIVATE(pEntity);
-#endif
-
- if (pPlayer)
- pPlayer->PreThink( );
-}
-
-/*
-================
-PlayerPostThink
-
-Called every frame after physics are run
-================
-*/
-void PlayerPostThink( edict_t *pEntity )
-{
- entvars_t *pev = &pEntity->v;
-#if 1
- CGearboxPlayer *pPlayer = (CGearboxPlayer *)GET_PRIVATE(pEntity);
-#else
- CBasePlayer *pPlayer = (CBasePlayer *)GET_PRIVATE(pEntity);
-#endif
-
- if (pPlayer)
- pPlayer->PostThink( );
-}
-
-
-
-void ParmsNewLevel( void )
-{
-}
-
-
-void ParmsChangeLevel( void )
-{
- // retrieve the pointer to the save data
- SAVERESTOREDATA *pSaveData = (SAVERESTOREDATA *)gpGlobals->pSaveData;
-
- if ( pSaveData )
- pSaveData->connectionCount = BuildChangeList( pSaveData->levelList, MAX_LEVEL_CONNECTIONS );
-}
-
-
-//
-// GLOBALS ASSUMED SET: g_ulFrameCount
-//
-void StartFrame( void )
-{
- if ( g_pGameRules )
- g_pGameRules->Think();
-
- if ( g_fGameOver )
- return;
-
- gpGlobals->teamplay = teamplay.value;
- g_ulFrameCount++;
-}
-
-
-void ClientPrecache( void )
-{
- // setup precaches always needed
- PRECACHE_SOUND("player/sprayer.wav"); // spray paint sound for PreAlpha
-
- // PRECACHE_SOUND("player/pl_jumpland2.wav"); // UNDONE: play 2x step sound
-
- PRECACHE_SOUND("player/pl_fallpain2.wav");
- PRECACHE_SOUND("player/pl_fallpain3.wav");
-
- PRECACHE_SOUND("player/pl_step1.wav"); // walk on concrete
- PRECACHE_SOUND("player/pl_step2.wav");
- PRECACHE_SOUND("player/pl_step3.wav");
- PRECACHE_SOUND("player/pl_step4.wav");
-
- PRECACHE_SOUND("common/npc_step1.wav"); // NPC walk on concrete
- PRECACHE_SOUND("common/npc_step2.wav");
- PRECACHE_SOUND("common/npc_step3.wav");
- PRECACHE_SOUND("common/npc_step4.wav");
-
- PRECACHE_SOUND("player/pl_metal1.wav"); // walk on metal
- PRECACHE_SOUND("player/pl_metal2.wav");
- PRECACHE_SOUND("player/pl_metal3.wav");
- PRECACHE_SOUND("player/pl_metal4.wav");
-
- PRECACHE_SOUND("player/pl_dirt1.wav"); // walk on dirt
- PRECACHE_SOUND("player/pl_dirt2.wav");
- PRECACHE_SOUND("player/pl_dirt3.wav");
- PRECACHE_SOUND("player/pl_dirt4.wav");
-
- PRECACHE_SOUND("player/pl_duct1.wav"); // walk in duct
- PRECACHE_SOUND("player/pl_duct2.wav");
- PRECACHE_SOUND("player/pl_duct3.wav");
- PRECACHE_SOUND("player/pl_duct4.wav");
-
- PRECACHE_SOUND("player/pl_grate1.wav"); // walk on grate
- PRECACHE_SOUND("player/pl_grate2.wav");
- PRECACHE_SOUND("player/pl_grate3.wav");
- PRECACHE_SOUND("player/pl_grate4.wav");
-
- PRECACHE_SOUND("player/pl_slosh1.wav"); // walk in shallow water
- PRECACHE_SOUND("player/pl_slosh2.wav");
- PRECACHE_SOUND("player/pl_slosh3.wav");
- PRECACHE_SOUND("player/pl_slosh4.wav");
-
- PRECACHE_SOUND("player/pl_tile1.wav"); // walk on tile
- PRECACHE_SOUND("player/pl_tile2.wav");
- PRECACHE_SOUND("player/pl_tile3.wav");
- PRECACHE_SOUND("player/pl_tile4.wav");
- PRECACHE_SOUND("player/pl_tile5.wav");
-
- PRECACHE_SOUND("player/pl_swim1.wav"); // breathe bubbles
- PRECACHE_SOUND("player/pl_swim2.wav");
- PRECACHE_SOUND("player/pl_swim3.wav");
- PRECACHE_SOUND("player/pl_swim4.wav");
-
- PRECACHE_SOUND("player/pl_ladder1.wav"); // climb ladder rung
- PRECACHE_SOUND("player/pl_ladder2.wav");
- PRECACHE_SOUND("player/pl_ladder3.wav");
- PRECACHE_SOUND("player/pl_ladder4.wav");
-
- PRECACHE_SOUND("player/pl_wade1.wav"); // wade in water
- PRECACHE_SOUND("player/pl_wade2.wav");
- PRECACHE_SOUND("player/pl_wade3.wav");
- PRECACHE_SOUND("player/pl_wade4.wav");
-
- PRECACHE_SOUND("debris/wood1.wav"); // hit wood texture
- PRECACHE_SOUND("debris/wood2.wav");
- PRECACHE_SOUND("debris/wood3.wav");
-
- PRECACHE_SOUND("plats/train_use1.wav"); // use a train
-
- PRECACHE_SOUND("buttons/spark5.wav"); // hit computer texture
- PRECACHE_SOUND("buttons/spark6.wav");
- PRECACHE_SOUND("debris/glass1.wav");
- PRECACHE_SOUND("debris/glass2.wav");
- PRECACHE_SOUND("debris/glass3.wav");
-
- PRECACHE_SOUND( SOUND_FLASHLIGHT_ON );
- PRECACHE_SOUND( SOUND_FLASHLIGHT_OFF );
-
-// player gib sounds
- PRECACHE_SOUND("common/bodysplat.wav");
-
-// player pain sounds
- PRECACHE_SOUND("player/pl_pain2.wav");
- PRECACHE_SOUND("player/pl_pain4.wav");
- PRECACHE_SOUND("player/pl_pain5.wav");
- PRECACHE_SOUND("player/pl_pain6.wav");
- PRECACHE_SOUND("player/pl_pain7.wav");
-
- PRECACHE_MODEL("models/player.mdl");
-
- // hud sounds
-
- PRECACHE_SOUND("common/wpn_hudoff.wav");
- PRECACHE_SOUND("common/wpn_hudon.wav");
- PRECACHE_SOUND("common/wpn_moveselect.wav");
- PRECACHE_SOUND("common/wpn_select.wav");
- PRECACHE_SOUND("common/wpn_denyselect.wav");
-
-
- // geiger sounds
-
- PRECACHE_SOUND("player/geiger6.wav");
- PRECACHE_SOUND("player/geiger5.wav");
- PRECACHE_SOUND("player/geiger4.wav");
- PRECACHE_SOUND("player/geiger3.wav");
- PRECACHE_SOUND("player/geiger2.wav");
- PRECACHE_SOUND("player/geiger1.wav");
-
- if (giPrecacheGrunt)
- UTIL_PrecacheOther("monster_human_grunt");
-
- // Teleport sounds. Used by trigger_xen_return
- PRECACHE_SOUND("debris/beamstart7.wav");
-
-#if defined ( GEARBOX_CTF )
- PRECACHE_MODEL("models/flag.mdl");
- PRECACHE_MODEL("models/civ_stand.mdl");
- PRECACHE_MODEL("models/mil_stand.mdl");
-
- PRECACHE_MODEL("models/w_accelerator.mdl");
- PRECACHE_MODEL("models/w_backpack.mdl");
- PRECACHE_MODEL("models/w_fgrenade.mdl");
- PRECACHE_MODEL("models/w_health.mdl");
- PRECACHE_MODEL("models/w_icon.mdl");
- PRECACHE_MODEL("models/w_jumppack.mdl");
- PRECACHE_MODEL("models/w_porthev.mdl");
-
- PRECACHE_SOUND("ctf/bm_flagtaken.wav");
- PRECACHE_SOUND("ctf/civ_flag_capture.wav");
- PRECACHE_SOUND("ctf/itemthrow.wav");
- PRECACHE_SOUND("ctf/marine_flag_capture.wav");
- PRECACHE_SOUND("ctf/pow_armor_charge.wav");
- PRECACHE_SOUND("ctf/pow_backpack.wav");
- PRECACHE_SOUND("ctf/pow_big_jump.wav");
- PRECACHE_SOUND("ctf/pow_health_charge.wav");
- PRECACHE_SOUND("ctf/soldier_flagtaken.wav");
-#endif
-}
-
-/*
-===============
-GetGameDescription
-
-Returns the descriptive name of this .dll. E.g., Half-Life, or Team Fortress 2
-===============
-*/
-const char *GetGameDescription()
-{
- if ( g_pGameRules ) // this function may be called before the world has spawned, and the game rules initialized
- return g_pGameRules->GetGameDescription();
- else
- return "Half-Life";
-}
-
-/*
-================
-Sys_Error
-
-Engine is going to shut down, allows setting a breakpoint in game .dll to catch that occasion
-================
-*/
-void Sys_Error( const char *error_string )
-{
- // Default case, do nothing. MOD AUTHORS: Add code ( e.g., _asm { int 3 }; here to cause a breakpoint for debugging your game .dlls
-}
-
-/*
-================
-PlayerCustomization
-
-A new player customization has been registered on the server
-UNDONE: This only sets the # of frames of the spray can logo
-animation right now.
-================
-*/
-void PlayerCustomization( edict_t *pEntity, customization_t *pCust )
-{
- entvars_t *pev = &pEntity->v;
-#if 1
- CGearboxPlayer *pPlayer = (CGearboxPlayer *)GET_PRIVATE(pEntity);
-#else
- CBasePlayer *pPlayer = (CBasePlayer *)GET_PRIVATE(pEntity);
-#endif
-
- if (!pPlayer)
- {
- ALERT(at_console, "PlayerCustomization: Couldn't get player!\n");
- return;
- }
-
- if (!pCust)
- {
- ALERT(at_console, "PlayerCustomization: NULL customization!\n");
- return;
- }
-
- switch (pCust->resource.type)
- {
- case t_decal:
- pPlayer->SetCustomDecalFrames(pCust->nUserData2); // Second int is max # of frames.
- break;
- case t_sound:
- case t_skin:
- case t_model:
- // Ignore for now.
- break;
- default:
- ALERT(at_console, "PlayerCustomization: Unknown customization type!\n");
- break;
- }
-}
-
-/*
-================
-SpectatorConnect
-
-A spectator has joined the game
-================
-*/
-void SpectatorConnect( edict_t *pEntity )
-{
- entvars_t *pev = &pEntity->v;
- CBaseSpectator *pPlayer = (CBaseSpectator *)GET_PRIVATE(pEntity);
-
- if (pPlayer)
- pPlayer->SpectatorConnect( );
-}
-
-/*
-================
-SpectatorConnect
-
-A spectator has left the game
-================
-*/
-void SpectatorDisconnect( edict_t *pEntity )
-{
- entvars_t *pev = &pEntity->v;
- CBaseSpectator *pPlayer = (CBaseSpectator *)GET_PRIVATE(pEntity);
-
- if (pPlayer)
- pPlayer->SpectatorDisconnect( );
-}
-
-/*
-================
-SpectatorConnect
-
-A spectator has sent a usercmd
-================
-*/
-void SpectatorThink( edict_t *pEntity )
-{
- entvars_t *pev = &pEntity->v;
- CBaseSpectator *pPlayer = (CBaseSpectator *)GET_PRIVATE(pEntity);
-
- if (pPlayer)
- pPlayer->SpectatorThink( );
-}
-
-////////////////////////////////////////////////////////
-// PAS and PVS routines for client messaging
-//
-
-/*
-================
-SetupVisibility
-
-A client can have a separate "view entity" indicating that his/her view should depend on the origin of that
-view entity. If that's the case, then pViewEntity will be non-NULL and will be used. Otherwise, the current
-entity's origin is used. Either is offset by the view_ofs to get the eye position.
-
-From the eye position, we set up the PAS and PVS to use for filtering network messages to the client. At this point, we could
- override the actual PAS or PVS values, or use a different origin.
-
-NOTE: Do not cache the values of pas and pvs, as they depend on reusable memory in the engine, they are only good for this one frame
-================
-*/
-void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas )
-{
- Vector org;
- edict_t *pView = pClient;
-
- // Find the client's PVS
- if ( pViewEntity )
- {
- pView = pViewEntity;
- }
-
- if ( pClient->v.flags & FL_PROXY )
- {
- *pvs = NULL; // the spectator proxy sees
- *pas = NULL; // and hears everything
- return;
- }
-
- org = pView->v.origin + pView->v.view_ofs;
- if ( pView->v.flags & FL_DUCKING )
- {
- org = org + ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
- }
-
- *pvs = ENGINE_SET_PVS ( (float *)&org );
- *pas = ENGINE_SET_PAS ( (float *)&org );
-}
-
-#include "entity_state.h"
-
-/*
-AddToFullPack
-
-Return 1 if the entity state has been filled in for the ent and the entity will be propagated to the client, 0 otherwise
-
-state is the server maintained copy of the state info that is transmitted to the client
-a MOD could alter values copied into state to send the "host" a different look for a particular entity update, etc.
-e and ent are the entity that is being added to the update, if 1 is returned
-host is the player's edict of the player whom we are sending the update to
-player is 1 if the ent/e is a player and 0 otherwise
-pSet is either the PAS or PVS that we previous set up. We can use it to ask the engine to filter the entity against the PAS or PVS.
-we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to. Caching the value is valid in that case, but still only for the current frame
-*/
-int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet )
-{
- int i;
-
- // don't send if flagged for NODRAW and it's not the host getting the message
- if ( ( ent->v.effects & EF_NODRAW ) &&
- ( ent != host ) )
- return 0;
-
- // Ignore ents without valid / visible models
- if ( !ent->v.modelindex || !STRING( ent->v.model ) )
- return 0;
-
- // Don't send spectators to other players
- if ( ( ent->v.flags & FL_SPECTATOR ) && ( ent != host ) )
- {
- return 0;
- }
-
- // Ignore if not the host and not touching a PVS/PAS leaf
- // If pSet is NULL, then the test will always succeed and the entity will be added to the update
- if ( ent != host )
- {
- if ( !ENGINE_CHECK_VISIBILITY( (const struct edict_s *)ent, pSet ) )
- {
- return 0;
- }
- }
-
-
- // Don't send entity to local client if the client says it's predicting the entity itself.
- if ( ent->v.flags & FL_SKIPLOCALHOST )
- {
- if ( ( hostflags & 1 ) && ( ent->v.owner == host ) )
- return 0;
- }
-
- if ( host->v.groupinfo )
- {
- UTIL_SetGroupTrace( host->v.groupinfo, GROUP_OP_AND );
-
- // Should always be set, of course
- if ( ent->v.groupinfo )
- {
- if ( g_groupop == GROUP_OP_AND )
- {
- if ( !(ent->v.groupinfo & host->v.groupinfo ) )
- return 0;
- }
- else if ( g_groupop == GROUP_OP_NAND )
- {
- if ( ent->v.groupinfo & host->v.groupinfo )
- return 0;
- }
- }
-
- UTIL_UnsetGroupTrace();
- }
-
- memset( state, 0, sizeof( *state ) );
-
- // Assign index so we can track this entity from frame to frame and
- // delta from it.
- state->number = e;
- state->entityType = ENTITY_NORMAL;
-
- // Flag custom entities.
- if ( ent->v.flags & FL_CUSTOMENTITY )
- {
- state->entityType = ENTITY_BEAM;
- }
-
- //
- // Copy state data
- //
-
- // Round animtime to nearest millisecond
- state->animtime = (int)(1000.0 * ent->v.animtime ) / 1000.0;
-
- memcpy( state->origin, ent->v.origin, 3 * sizeof( float ) );
- memcpy( state->angles, ent->v.angles, 3 * sizeof( float ) );
- memcpy( state->mins, ent->v.mins, 3 * sizeof( float ) );
- memcpy( state->maxs, ent->v.maxs, 3 * sizeof( float ) );
-
- memcpy( state->startpos, ent->v.startpos, 3 * sizeof( float ) );
- memcpy( state->endpos, ent->v.endpos, 3 * sizeof( float ) );
-
- state->impacttime = ent->v.impacttime;
- state->starttime = ent->v.starttime;
-
- state->modelindex = ent->v.modelindex;
-
- state->frame = ent->v.frame;
-
- state->skin = ent->v.skin;
- state->effects = ent->v.effects;
-
- // This non-player entity is being moved by the game .dll and not the physics simulation system
- // make sure that we interpolate it's position on the client if it moves
- if ( !player &&
- ent->v.animtime &&
- ent->v.velocity[ 0 ] == 0 &&
- ent->v.velocity[ 1 ] == 0 &&
- ent->v.velocity[ 2 ] == 0 )
- {
- state->eflags |= EFLAG_SLERP;
- }
-
- state->scale = ent->v.scale;
- state->solid = ent->v.solid;
- state->colormap = ent->v.colormap;
-
- state->movetype = ent->v.movetype;
- state->sequence = ent->v.sequence;
- state->framerate = ent->v.framerate;
- state->body = ent->v.body;
-
- for (i = 0; i < 4; i++)
- {
- state->controller[i] = ent->v.controller[i];
- }
-
- for (i = 0; i < 2; i++)
- {
- state->blending[i] = ent->v.blending[i];
- }
-
- state->rendermode = ent->v.rendermode;
- state->renderamt = ent->v.renderamt;
- state->renderfx = ent->v.renderfx;
- state->rendercolor.r = ent->v.rendercolor.x;
- state->rendercolor.g = ent->v.rendercolor.y;
- state->rendercolor.b = ent->v.rendercolor.z;
-
- state->aiment = 0;
- if ( ent->v.aiment )
- {
- state->aiment = ENTINDEX( ent->v.aiment );
- }
-
- state->owner = 0;
- if ( ent->v.owner )
- {
- int owner = ENTINDEX( ent->v.owner );
-
- // Only care if owned by a player
- if ( owner >= 1 && owner <= gpGlobals->maxClients )
- {
- state->owner = owner;
- }
- }
-
- // HACK: Somewhat...
- // Class is overridden for non-players to signify a breakable glass object ( sort of a class? )
- if ( !player )
- {
- state->playerclass = ent->v.playerclass;
- }
-
- // Special stuff for players only
- if ( player )
- {
- memcpy( state->basevelocity, ent->v.basevelocity, 3 * sizeof( float ) );
-
- state->weaponmodel = MODEL_INDEX( STRING( ent->v.weaponmodel ) );
- state->gaitsequence = ent->v.gaitsequence;
- state->spectator = ent->v.flags & FL_SPECTATOR;
- state->friction = ent->v.friction;
-
- state->gravity = ent->v.gravity;
-// state->team = ent->v.team;
-//
- state->usehull = ( ent->v.flags & FL_DUCKING ) ? 1 : 0;
- state->health = ent->v.health;
- }
-
- return 1;
-}
-
-// defaults for clientinfo messages
-#define DEFAULT_VIEWHEIGHT 28
-
-/*
-===================
-CreateBaseline
-
-Creates baselines used for network encoding, especially for player data since players are not spawned until connect time.
-===================
-*/
-void CreateBaseline( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs )
-{
- baseline->origin = entity->v.origin;
- baseline->angles = entity->v.angles;
- baseline->frame = entity->v.frame;
- baseline->skin = (short)entity->v.skin;
-
- // render information
- baseline->rendermode = (byte)entity->v.rendermode;
- baseline->renderamt = (byte)entity->v.renderamt;
- baseline->rendercolor.r = (byte)entity->v.rendercolor.x;
- baseline->rendercolor.g = (byte)entity->v.rendercolor.y;
- baseline->rendercolor.b = (byte)entity->v.rendercolor.z;
- baseline->renderfx = (byte)entity->v.renderfx;
-
- if ( player )
- {
- baseline->mins = player_mins;
- baseline->maxs = player_maxs;
-
- baseline->colormap = eindex;
- baseline->modelindex = playermodelindex;
- baseline->friction = 1.0;
- baseline->movetype = MOVETYPE_WALK;
-
- baseline->scale = entity->v.scale;
- baseline->solid = SOLID_SLIDEBOX;
- baseline->framerate = 1.0;
- baseline->gravity = 1.0;
-
- }
- else
- {
- baseline->mins = entity->v.mins;
- baseline->maxs = entity->v.maxs;
-
- baseline->colormap = 0;
- baseline->modelindex = entity->v.modelindex;//SV_ModelIndex(pr_strings + entity->v.model);
- baseline->movetype = entity->v.movetype;
-
- baseline->scale = entity->v.scale;
- baseline->solid = entity->v.solid;
- baseline->framerate = entity->v.framerate;
- baseline->gravity = entity->v.gravity;
- }
-}
-
-typedef struct
-{
- char name[32];
- int field;
-} entity_field_alias_t;
-
-#define FIELD_ORIGIN0 0
-#define FIELD_ORIGIN1 1
-#define FIELD_ORIGIN2 2
-#define FIELD_ANGLES0 3
-#define FIELD_ANGLES1 4
-#define FIELD_ANGLES2 5
-
-static entity_field_alias_t entity_field_alias[]=
-{
- { "origin[0]", 0 },
- { "origin[1]", 0 },
- { "origin[2]", 0 },
- { "angles[0]", 0 },
- { "angles[1]", 0 },
- { "angles[2]", 0 },
-};
-
-void Entity_FieldInit( struct delta_s *pFields )
-{
- entity_field_alias[ FIELD_ORIGIN0 ].field = DELTA_FINDFIELD( pFields, entity_field_alias[ FIELD_ORIGIN0 ].name );
- entity_field_alias[ FIELD_ORIGIN1 ].field = DELTA_FINDFIELD( pFields, entity_field_alias[ FIELD_ORIGIN1 ].name );
- entity_field_alias[ FIELD_ORIGIN2 ].field = DELTA_FINDFIELD( pFields, entity_field_alias[ FIELD_ORIGIN2 ].name );
- entity_field_alias[ FIELD_ANGLES0 ].field = DELTA_FINDFIELD( pFields, entity_field_alias[ FIELD_ANGLES0 ].name );
- entity_field_alias[ FIELD_ANGLES1 ].field = DELTA_FINDFIELD( pFields, entity_field_alias[ FIELD_ANGLES1 ].name );
- entity_field_alias[ FIELD_ANGLES2 ].field = DELTA_FINDFIELD( pFields, entity_field_alias[ FIELD_ANGLES2 ].name );
-}
-
-/*
-==================
-Entity_Encode
-
-Callback for sending entity_state_t info over network.
-FIXME: Move to script
-==================
-*/
-void Entity_Encode( struct delta_s *pFields, const unsigned char *from, const unsigned char *to )
-{
- entity_state_t *f, *t;
- int localplayer = 0;
- static int initialized = 0;
-
- if ( !initialized )
- {
- Entity_FieldInit( pFields );
- initialized = 1;
- }
-
- f = (entity_state_t *)from;
- t = (entity_state_t *)to;
-
- // Never send origin to local player, it's sent with more resolution in clientdata_t structure
- localplayer = ( t->number - 1 ) == ENGINE_CURRENT_PLAYER();
- if ( localplayer )
- {
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
- }
-
- if ( ( t->impacttime != 0 ) && ( t->starttime != 0 ) )
- {
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
-
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ANGLES0 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ANGLES1 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ANGLES2 ].field );
- }
-
- if ( ( t->movetype == MOVETYPE_FOLLOW ) &&
- ( t->aiment != 0 ) )
- {
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
- }
- else if ( t->aiment != f->aiment )
- {
- DELTA_SETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_SETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_SETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
- }
-}
-
-static entity_field_alias_t player_field_alias[]=
-{
- { "origin[0]", 0 },
- { "origin[1]", 0 },
- { "origin[2]", 0 },
-};
-
-void Player_FieldInit( struct delta_s *pFields )
-{
- player_field_alias[ FIELD_ORIGIN0 ].field = DELTA_FINDFIELD( pFields, player_field_alias[ FIELD_ORIGIN0 ].name );
- player_field_alias[ FIELD_ORIGIN1 ].field = DELTA_FINDFIELD( pFields, player_field_alias[ FIELD_ORIGIN1 ].name );
- player_field_alias[ FIELD_ORIGIN2 ].field = DELTA_FINDFIELD( pFields, player_field_alias[ FIELD_ORIGIN2 ].name );
-}
-
-/*
-==================
-Player_Encode
-
-Callback for sending entity_state_t for players info over network.
-==================
-*/
-void Player_Encode( struct delta_s *pFields, const unsigned char *from, const unsigned char *to )
-{
- entity_state_t *f, *t;
- int localplayer = 0;
- static int initialized = 0;
-
- if ( !initialized )
- {
- Player_FieldInit( pFields );
- initialized = 1;
- }
-
- f = (entity_state_t *)from;
- t = (entity_state_t *)to;
-
- // Never send origin to local player, it's sent with more resolution in clientdata_t structure
- localplayer = ( t->number - 1 ) == ENGINE_CURRENT_PLAYER();
- if ( localplayer )
- {
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
- }
-
- if ( ( t->movetype == MOVETYPE_FOLLOW ) &&
- ( t->aiment != 0 ) )
- {
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_UNSETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
- }
- else if ( t->aiment != f->aiment )
- {
- DELTA_SETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN0 ].field );
- DELTA_SETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN1 ].field );
- DELTA_SETBYINDEX( pFields, entity_field_alias[ FIELD_ORIGIN2 ].field );
- }
-}
-
-#define CUSTOMFIELD_ORIGIN0 0
-#define CUSTOMFIELD_ORIGIN1 1
-#define CUSTOMFIELD_ORIGIN2 2
-#define CUSTOMFIELD_ANGLES0 3
-#define CUSTOMFIELD_ANGLES1 4
-#define CUSTOMFIELD_ANGLES2 5
-#define CUSTOMFIELD_SKIN 6
-#define CUSTOMFIELD_SEQUENCE 7
-#define CUSTOMFIELD_ANIMTIME 8
-
-entity_field_alias_t custom_entity_field_alias[]=
-{
- { "origin[0]", 0 },
- { "origin[1]", 0 },
- { "origin[2]", 0 },
- { "angles[0]", 0 },
- { "angles[1]", 0 },
- { "angles[2]", 0 },
- { "skin", 0 },
- { "sequence", 0 },
- { "animtime", 0 },
-};
-
-void Custom_Entity_FieldInit( struct delta_s *pFields )
-{
- custom_entity_field_alias[ CUSTOMFIELD_ORIGIN0 ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ORIGIN0 ].name );
- custom_entity_field_alias[ CUSTOMFIELD_ORIGIN1 ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ORIGIN1 ].name );
- custom_entity_field_alias[ CUSTOMFIELD_ORIGIN2 ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ORIGIN2 ].name );
- custom_entity_field_alias[ CUSTOMFIELD_ANGLES0 ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANGLES0 ].name );
- custom_entity_field_alias[ CUSTOMFIELD_ANGLES1 ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANGLES1 ].name );
- custom_entity_field_alias[ CUSTOMFIELD_ANGLES2 ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANGLES2 ].name );
- custom_entity_field_alias[ CUSTOMFIELD_SKIN ].field = DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_SKIN ].name );
- custom_entity_field_alias[ CUSTOMFIELD_SEQUENCE ].field= DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_SEQUENCE ].name );
- custom_entity_field_alias[ CUSTOMFIELD_ANIMTIME ].field= DELTA_FINDFIELD( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANIMTIME ].name );
-}
-
-/*
-==================
-Custom_Encode
-
-Callback for sending entity_state_t info ( for custom entities ) over network.
-FIXME: Move to script
-==================
-*/
-void Custom_Encode( struct delta_s *pFields, const unsigned char *from, const unsigned char *to )
-{
- entity_state_t *f, *t;
- int beamType;
- static int initialized = 0;
-
- if ( !initialized )
- {
- Custom_Entity_FieldInit( pFields );
- initialized = 1;
- }
-
- f = (entity_state_t *)from;
- t = (entity_state_t *)to;
-
- beamType = t->rendermode & 0x0f;
-
- if ( beamType != BEAM_POINTS && beamType != BEAM_ENTPOINT )
- {
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ORIGIN0 ].field );
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ORIGIN1 ].field );
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ORIGIN2 ].field );
- }
-
- if ( beamType != BEAM_POINTS )
- {
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANGLES0 ].field );
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANGLES1 ].field );
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANGLES2 ].field );
- }
-
- if ( beamType != BEAM_ENTS && beamType != BEAM_ENTPOINT )
- {
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_SKIN ].field );
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_SEQUENCE ].field );
- }
-
- // animtime is compared by rounding first
- // see if we really shouldn't actually send it
- if ( (int)f->animtime == (int)t->animtime )
- {
- DELTA_UNSETBYINDEX( pFields, custom_entity_field_alias[ CUSTOMFIELD_ANIMTIME ].field );
- }
-}
-
-/*
-=================
-RegisterEncoders
-
-Allows game .dll to override network encoding of certain types of entities and tweak values, etc.
-=================
-*/
-void RegisterEncoders( void )
-{
- DELTA_ADDENCODER( "Entity_Encode", Entity_Encode );
- DELTA_ADDENCODER( "Custom_Encode", Custom_Encode );
- DELTA_ADDENCODER( "Player_Encode", Player_Encode );
-}
-
-int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
-{
-#if CLIENT_WEAPONS
- int i;
- weapon_data_t *item;
- entvars_t *pev = &player->v;
-#if 1
- CGearboxPlayer *pl = dynamic_cast< CGearboxPlayer *>(CGearboxPlayer::Instance(pev));
-#else
- CBasePlayer *pl = dynamic_cast< CBasePlayer *>( CBasePlayer::Instance( pev ) );
-#endif
- CBasePlayerWeapon *gun;
-
- ItemInfo II;
-
- memset( info, 0, 32 * sizeof( weapon_data_t ) );
-
- if ( !pl )
- return 1;
-
- // go through all of the weapons and make a list of the ones to pack
- for ( i = 0 ; i < MAX_ITEM_TYPES ; i++ )
- {
- if ( pl->m_rgpPlayerItems[ i ] )
- {
- // there's a weapon here. Should I pack it?
- CBasePlayerItem *pPlayerItem = pl->m_rgpPlayerItems[ i ];
-
- while ( pPlayerItem )
- {
- gun = dynamic_cast( pPlayerItem->GetWeaponPtr() );
- if ( gun && gun->UseDecrement() )
- {
- // Get The ID.
- memset( &II, 0, sizeof( II ) );
- gun->GetItemInfo( &II );
-
- if ( II.iId >= 0 && II.iId < 32 )
- {
- item = &info[ II.iId ];
-
- item->m_iId = II.iId;
- item->m_iClip = gun->m_iClip;
-
- item->m_flTimeWeaponIdle = max( gun->m_flTimeWeaponIdle, -0.001 );
- item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001 );
- item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001 );
- item->m_fInReload = gun->m_fInReload;
- item->m_fInSpecialReload = gun->m_fInSpecialReload;
- item->fuser1 = max( gun->pev->fuser1, -0.001 );
- item->fuser2 = gun->m_flStartThrow;
- item->fuser3 = gun->m_flReleaseThrow;
- item->iuser1 = gun->m_chargeReady;
- item->iuser2 = gun->m_fInAttack;
- item->iuser3 = gun->m_fireState;
-
-
-// item->m_flPumpTime = max( gun->m_flPumpTime, -0.001 );
- }
- }
- pPlayerItem = pPlayerItem->m_pNext;
- }
- }
- }
-#else
- memset( info, 0, 32 * sizeof( weapon_data_t ) );
-#endif
- return 1;
-}
-
-/*
-=================
-UpdateClientData
-
-Data sent to current client only
-engine sets cd to 0 before calling.
-=================
-*/
-void UpdateClientData ( const edict_t *ent, int sendweapons, struct clientdata_s *cd )
-{
- if ( !ent || !ent->pvPrivateData )
- return;
- entvars_t * pev = (entvars_t *)&ent->v;
-#if 1
- CGearboxPlayer * pl = dynamic_cast< CGearboxPlayer *>(CGearboxPlayer::Instance(pev));
-#else
- CBasePlayer * pl = dynamic_cast< CBasePlayer *>(CBasePlayer::Instance( pev ));
-#endif
- entvars_t * pevOrg = NULL;
-
- // if user is spectating different player in First person, override some vars
- if ( pl && pl->pev->iuser1 == OBS_IN_EYE )
- {
- if ( pl->m_hObserverTarget )
- {
- pevOrg = pev;
- pev = pl->m_hObserverTarget->pev;
-#if 1
- pl = dynamic_cast< CGearboxPlayer *>(CGearboxPlayer::Instance(pev));
-#else
- pl = dynamic_cast< CBasePlayer *>(CBasePlayer::Instance( pev ) );
-#endif
- }
- }
-
- cd->flags = pev->flags;
- cd->health = pev->health;
-
- cd->viewmodel = MODEL_INDEX( STRING( pev->viewmodel ) );
-
- cd->waterlevel = pev->waterlevel;
- cd->watertype = pev->watertype;
- cd->weapons = pev->weapons;
-
- // Vectors
- cd->origin = pev->origin;
- cd->velocity = pev->velocity;
- cd->view_ofs = pev->view_ofs;
- cd->punchangle = pev->punchangle;
-
- cd->bInDuck = pev->bInDuck;
- cd->flTimeStepSound = pev->flTimeStepSound;
- cd->flDuckTime = pev->flDuckTime;
- cd->flSwimTime = pev->flSwimTime;
- cd->waterjumptime = pev->teleport_time;
-
- strcpy( cd->physinfo, ENGINE_GETPHYSINFO( ent ) );
-
- cd->maxspeed = pev->maxspeed;
- cd->fov = pev->fov;
- cd->weaponanim = pev->weaponanim;
-
- cd->pushmsec = pev->pushmsec;
-
- //Spectator mode
- if ( pevOrg != NULL )
- {
- // don't use spec vars from chased player
- cd->iuser1 = pevOrg->iuser1;
- cd->iuser2 = pevOrg->iuser2;
- }
- else
- {
- cd->iuser1 = pev->iuser1;
- cd->iuser2 = pev->iuser2;
- }
-
-
-
-#if CLIENT_WEAPONS
- if ( sendweapons )
- {
- if ( pl )
- {
- cd->m_flNextAttack = pl->m_flNextAttack;
- cd->fuser2 = pl->m_flNextAmmoBurn;
- cd->fuser3 = pl->m_flAmmoStartCharge;
- cd->vuser1.x = pl->ammo_9mm;
- cd->vuser1.y = pl->ammo_357;
- cd->vuser1.z = pl->ammo_argrens;
- cd->ammo_nails = pl->ammo_bolts;
- cd->ammo_shells = pl->ammo_buckshot;
- cd->ammo_rockets = pl->ammo_rockets;
- cd->ammo_cells = pl->ammo_uranium;
- cd->vuser2.x = pl->ammo_hornets;
-
- if ( pl->m_pActiveItem )
- {
- CBasePlayerWeapon *gun;
- gun = (CBasePlayerWeapon *)pl->m_pActiveItem->GetWeaponPtr();
- if ( gun && gun->UseDecrement() )
- {
- ItemInfo II;
- memset( &II, 0, sizeof( II ) );
- gun->GetItemInfo( &II );
-
- cd->m_iId = II.iId;
-
- cd->vuser3.z = gun->m_iSecondaryAmmoType;
- cd->vuser4.x = gun->m_iPrimaryAmmoType;
- cd->vuser4.y = pl->m_rgAmmo[gun->m_iPrimaryAmmoType];
- cd->vuser4.z = pl->m_rgAmmo[gun->m_iSecondaryAmmoType];
-
- if ( pl->m_pActiveItem->m_iId == WEAPON_RPG )
- {
- cd->vuser2.y = ( ( CRpg * )pl->m_pActiveItem)->m_fSpotActive;
- cd->vuser2.z = ( ( CRpg * )pl->m_pActiveItem)->m_cActiveRockets;
- }
-#if defined ( GEARBOX_DLL ) || defined ( GEARBOX_CLIENT_DLL )
- else if (pl->m_pActiveItem->m_iId == WEAPON_M249)
- {
- cd->vuser2.y = pl->ammo_556;
- }
- else if (pl->m_pActiveItem->m_iId == WEAPON_SHOCKRIFLE)
- {
- cd->vuser2.y = pl->ammo_shocks;
- }
- else if (pl->m_pActiveItem->m_iId == WEAPON_SNIPERRIFLE)
- {
- cd->vuser2.y = pl->ammo_762;
- }
- else if (pl->m_pActiveItem->m_iId == WEAPON_SPORELAUNCHER)
- {
- cd->vuser2.y = pl->ammo_spores;
- }
-#endif
- }
- }
- }
- }
-#endif
-}
-
-/*
-=================
-CmdStart
-
-We're about to run this usercmd for the specified player. We can set up groupinfo and masking here, etc.
-This is the time to examine the usercmd for anything extra. This call happens even if think does not.
-=================
-*/
-void CmdStart( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed )
-{
- entvars_t *pev = (entvars_t *)&player->v;
-#if 1
- CGearboxPlayer *pl = dynamic_cast< CGearboxPlayer *>(CGearboxPlayer::Instance(pev));
-#else
- CBasePlayer *pl = dynamic_cast< CBasePlayer *>( CBasePlayer::Instance( pev ) );
-#endif
-
- if( !pl )
- return;
-
- if ( pl->pev->groupinfo != 0 )
- {
- UTIL_SetGroupTrace( pl->pev->groupinfo, GROUP_OP_AND );
- }
-
- pl->random_seed = random_seed;
-}
-
-/*
-=================
-CmdEnd
-
-Each cmdstart is exactly matched with a cmd end, clean up any group trace flags, etc. here
-=================
-*/
-void CmdEnd ( const edict_t *player )
-{
- entvars_t *pev = (entvars_t *)&player->v;
-#if 1
- CGearboxPlayer *pl = dynamic_cast< CGearboxPlayer *>(CGearboxPlayer::Instance(pev));
-#else
- CBasePlayer *pl = dynamic_cast< CBasePlayer *>( CBasePlayer::Instance( pev ) );
-#endif
-
- if( !pl )
- return;
- if ( pl->pev->groupinfo != 0 )
- {
- UTIL_UnsetGroupTrace();
- }
-}
-
-/*
-================================
-ConnectionlessPacket
-
- Return 1 if the packet is valid. Set response_buffer_size if you want to send a response packet. Incoming, it holds the max
- size of the response_buffer, so you must zero it out if you choose not to respond.
-================================
-*/
-int ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
-{
- // Parse stuff from args
- int max_buffer_size = *response_buffer_size;
-
- // Zero it out since we aren't going to respond.
- // If we wanted to response, we'd write data into response_buffer
- *response_buffer_size = 0;
-
- // Since we don't listen for anything here, just respond that it's a bogus message
- // If we didn't reject the message, we'd return 1 for success instead.
- return 0;
-}
-
-/*
-================================
-GetHullBounds
-
- Engine calls this to enumerate player collision hulls, for prediction. Return 0 if the hullnumber doesn't exist.
-================================
-*/
-int GetHullBounds( int hullnumber, float *mins, float *maxs )
-{
- int iret = 0;
-
- switch ( hullnumber )
- {
- case 0: // Normal player
- mins = VEC_HULL_MIN;
- maxs = VEC_HULL_MAX;
- iret = 1;
- break;
- case 1: // Crouched player
- mins = VEC_DUCK_HULL_MIN;
- maxs = VEC_DUCK_HULL_MAX;
- iret = 1;
- break;
- case 2: // Point based hull
- mins = Vector( 0, 0, 0 );
- maxs = Vector( 0, 0, 0 );
- iret = 1;
- break;
- }
-
- return iret;
-}
-
-/*
-================================
-CreateInstancedBaselines
-
-Create pseudo-baselines for items that aren't placed in the map at spawn time, but which are likely
-to be created during play ( e.g., grenades, ammo packs, projectiles, corpses, etc. )
-================================
-*/
-void CreateInstancedBaselines ( void )
-{
- int iret = 0;
- entity_state_t state;
-
- memset( &state, 0, sizeof( state ) );
-
- // Create any additional baselines here for things like grendates, etc.
- // iret = ENGINE_INSTANCE_BASELINE( pc->pev->classname, &state );
-
- // Destroy objects.
- //UTIL_Remove( pc );
-}
-
-/*
-================================
-InconsistentFile
-
-One of the ENGINE_FORCE_UNMODIFIED files failed the consistency check for the specified player
- Return 0 to allow the client to continue, 1 to force immediate disconnection ( with an optional disconnect message of up to 256 characters )
-================================
-*/
-int InconsistentFile( const edict_t *player, const char *filename, char *disconnect_message )
-{
- // Server doesn't care?
- if ( CVAR_GET_FLOAT( "mp_consistency" ) != 1 )
- return 0;
-
- // Default behavior is to kick the player
- sprintf( disconnect_message, "Server is enforcing file consistency for %s\n", filename );
-
- // Kick now with specified disconnect message.
- return 1;
-}
-
-/*
-================================
-AllowLagCompensation
-
- The game .dll should return 1 if lag compensation should be allowed ( could also just set
- the sv_unlag cvar.
- Most games right now should return 0, until client-side weapon prediction code is written
- and tested for them ( note you can predict weapons, but not do lag compensation, too,
- if you want.
-================================
-*/
-int AllowLagCompensation( void )
-{
- return 1;
-}
diff --git a/dlls/gearbox/gearbox_explode.h b/dlls/gearbox/gearbox_explode.h
deleted file mode 100644
index c3332320..00000000
--- a/dlls/gearbox/gearbox_explode.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/***
-*
-* Copyright (c) 1996-2001, 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 GEARBOX_EXPLODE_H
-#define GEARBOX_EXPLODE_H
-
-extern DLL_GLOBAL short g_sModelIndexSpore1;
-extern DLL_GLOBAL short g_sModelIndexSpore2;
-extern DLL_GLOBAL short g_sModelIndexSpore3;
-
-extern DLL_GLOBAL short g_sModelIndexBigSpit;
-extern DLL_GLOBAL short g_sModelIndexTinySpit;
-
-#endif // GEARBOX_EXPLODE_H
\ No newline at end of file
diff --git a/dlls/gearbox/gearbox_monsters.h b/dlls/gearbox/gearbox_monsters.h
deleted file mode 100644
index b958a8b9..00000000
--- a/dlls/gearbox/gearbox_monsters.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/***
-*
-* Copyright (c) 1996-2001, 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 GEARBOX_MONSTERS_H
-#define GEARBOX_MONSTERS_H
-
-#define EF_GLOWSHELL 2048
-
-#endif // GEARBOX_MONSTERS_H
\ No newline at end of file
diff --git a/dlls/gearbox/gearbox_player.h b/dlls/gearbox/gearbox_player.h
deleted file mode 100644
index 512488c5..00000000
--- a/dlls/gearbox/gearbox_player.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/***
-*
-* Copyright (c) 1996-2001, 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 GEARBOX_PLAYER_H
-#define GEARBOX_PLAYER_H
-
-enum Player_Menu {
- Team_Menu,
- Team_Menu_IG,
-};
-
-#define PFLAG_ONROPE ( 1 << 6 )
-
-class CGearboxPlayer : public CBasePlayer
-{
-public:
- virtual int Save(CSave &save);
- virtual int Restore(CRestore &restore);
-
- BOOL FlashlightIsOn(void);
- void FlashlightTurnOn(void);
- void FlashlightTurnOff(void);
-
- static TYPEDESCRIPTION m_playerSaveData[];
-
- virtual void Spawn(void);
-
-private:
- BOOL m_fInXen;
- BOOL m_fIsFrozen;
-
-public:
- int m_bHasFlag;
- void ShowMenu(int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText);
- int m_iMenu;
-
- float m_flNextTeamChange;
-
- CBasePlayer *pFlagCarrierKiller;
- CBasePlayer *pFlagReturner;
- CBasePlayer *pCarrierHurter;
-
- float m_flCarrierHurtTime;
- float m_flCarrierPickupTime;
- float m_flFlagCarrierKillTime;
- float m_flFlagReturnTime;
- float m_flFlagStatusTime;
-
- float m_flRegenTime;
-
- int m_iRuneStatus;
-
- void W_FireHook(void);
- void Throw_Grapple(void);
-
- bool m_bHook_Out;
- bool m_bOn_Hook;
- CBaseEntity *m_ppHook;
-
- void Service_Grapple(void);
-private:
-
- friend class CDisplacer;
- friend class CTriggerXenReturn;
- friend class CPlayerFreeze;
-};
-
-#endif // GEARBOX_PLAYER_H
diff --git a/wscript b/wscript
index 02efd884..4e5503ed 100644
--- a/wscript
+++ b/wscript
@@ -211,7 +211,7 @@ def configure(conf):
conf.msg(msg='-> processing mod options', result='...', color='BLUE')
regex = re.compile('^([A-Za-z0-9_]+)=([A-Za-z0-9_]+)\ \#\ (.*)$')
- with open('mod_options.txt') as fd:
+ with open(str(conf.path.make_node('mod_options.txt'))) as fd:
lines = fd.readlines()
for line in lines:
m = regex.match(line.strip())
@@ -230,6 +230,10 @@ def configure(conf):
if conf.env.HLDEMO_BUILD and conf.env.OEM_BUILD:
conf.fatal('Don\'t mix Demo and OEM builds!')
+ # force to use server library name
+ if conf.env.DEST_OS == 'android':
+ conf.env.SERVER_LIBRARY_NAME = 'server' # can't be any other name, until specified
+
# strip lib from pattern
if conf.env.DEST_OS not in ['android']:
if conf.env.cxxshlib_PATTERN.startswith('lib'):