mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
1 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71b715875a |
@@ -4,7 +4,7 @@ task:
|
||||
image_family: freebsd-14-2
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
@@ -16,7 +16,7 @@ task:
|
||||
image_family: freebsd-15-0-snap
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
|
||||
3
.github/workflows/c-cpp.yml
vendored
3
.github/workflows/c-cpp.yml
vendored
@@ -66,7 +66,7 @@ jobs:
|
||||
targetos: apple
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.32.0
|
||||
SDL_VERSION: 2.30.12
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||
steps:
|
||||
@@ -120,6 +120,7 @@ jobs:
|
||||
--yes \
|
||||
--cleanup-tag \
|
||||
--repo "$GITHUB_REPOSITORY" || true
|
||||
sleep 20s
|
||||
gh run download "$GITHUB_RUN_ID" \
|
||||
--dir artifacts/ \
|
||||
--repo "$GITHUB_REPOSITORY"
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -34,6 +34,3 @@
|
||||
[submodule "3rdparty/opusfile/opusfile"]
|
||||
path = 3rdparty/opusfile/opusfile
|
||||
url = https://gitlab.xiph.org/xiph/opusfile.git
|
||||
[submodule "3rdparty/libbacktrace/libbacktrace"]
|
||||
path = 3rdparty/libbacktrace/libbacktrace
|
||||
url = https://github.com/ianlancetaylor/libbacktrace
|
||||
|
||||
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/extras/xash-extras
vendored
Submodule 3rdparty/extras/xash-extras updated: 0c83a63d00...4982e5edb0
2
3rdparty/gl4es/gl4es
vendored
2
3rdparty/gl4es/gl4es
vendored
Submodule 3rdparty/gl4es/gl4es updated: a744af14d4...e39434a2b1
1
3rdparty/libbacktrace/libbacktrace
vendored
1
3rdparty/libbacktrace/libbacktrace
vendored
Submodule 3rdparty/libbacktrace/libbacktrace deleted from 78af4ffa26
185
3rdparty/libbacktrace/wscript
vendored
185
3rdparty/libbacktrace/wscript
vendored
@@ -1,185 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from waflib import TaskGen
|
||||
|
||||
FRAGMENT_ATOMIC='''int i;
|
||||
int main(void) {
|
||||
__atomic_load_n(&i, __ATOMIC_ACQUIRE);
|
||||
__atomic_store_n(&i, 1, __ATOMIC_RELEASE);
|
||||
return 0;
|
||||
}'''
|
||||
|
||||
FRAGMENT_SYNC='''int i;
|
||||
int main (void) {
|
||||
__sync_bool_compare_and_swap (&i, i, i);
|
||||
__sync_lock_test_and_set (&i, 1);
|
||||
__sync_lock_release (&i);
|
||||
return 0;
|
||||
}'''
|
||||
|
||||
FRAGMENT_GETPAGESIZE='''#include <unistd.h>
|
||||
int main(void) { return getpagesize() }'''
|
||||
|
||||
FRAGMENT_GETEXECNAME='''#include <stdlib.h>
|
||||
int main(void) { return getexecname() != 0 }'''
|
||||
|
||||
FRAGMENT_STRNLEN='''#include <string.h>
|
||||
int main(int argc, char **argv) { return (int)strnlen(argv[0], 10); }'''
|
||||
|
||||
FRAGMENT_DL_ITERATE_PHDR='''#include <%s>
|
||||
int main(void) { return dl_iterate_phdr(0, 0); }'''
|
||||
|
||||
FRAGMENT_FCNTL='''#include <fcntl.h>
|
||||
int main(void) { return fcntl(0, 0, 0); }'''
|
||||
|
||||
FRAGMENT_GETIPINFO='''#include "unwind.h"
|
||||
struct _Unwind_Context *context;
|
||||
int ip_before_insn = 0;
|
||||
int main(void) { return _Unwind_GetIPInfo(context, &ip_before_insn); }'''
|
||||
|
||||
FRAGMENT_LOADQUERY='''#include <sys/ldr.h>
|
||||
#include <sys/debug.h>
|
||||
int main(void) { return loadquery(0, 0, 0); }'''
|
||||
|
||||
FRAGMENT_KERN_PROC='''#include <sys/sysctl.h>
|
||||
#if !defined(%s) || !defined(KERN_PROC_PATHNAME)
|
||||
#error
|
||||
#endif
|
||||
int main(void) { return 0; }'''
|
||||
|
||||
FRAGMENT_LSTAT='''#include <sys/stat.h>
|
||||
struct stat st;
|
||||
int main(int argc, char **argv) { return lstat(argv[0], &st); }'''
|
||||
|
||||
FRAGMENT_READLINK='''#include <unistd.h>
|
||||
char buf[100];
|
||||
int main(int argc, char **argv) { return readlink(argv[0], buf, sizeof(buf)); }'''
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
# add unsupported platforms here
|
||||
if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos']:
|
||||
conf.env.DISABLE_LIBBACKTRACE = True
|
||||
return
|
||||
|
||||
# win32 has it's own dbghelp-based backtrace, that's why we ship PDBs
|
||||
if conf.env.COMPILER_CC == 'msvc':
|
||||
conf.env.DISABLE_LIBBACKTRACE = True
|
||||
return
|
||||
|
||||
if not conf.path.find_dir('libbacktrace') or not conf.path.find_dir('libbacktrace/config'):
|
||||
conf.fatal('Can\'t find libbacktrace submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
if conf.env.DEST_SIZEOF_VOID_P == 8:
|
||||
conf.define('BACKTRACE_ELF_SIZE', 64)
|
||||
conf.define('BACKTRACE_XCOFF_SIZE', 64)
|
||||
else:
|
||||
conf.define('BACKTRACE_ELF_SIZE', 32)
|
||||
conf.define('BACKTRACE_XCOFF_SIZE', 32)
|
||||
|
||||
conf.define('_ALL_SOURCE', 1)
|
||||
conf.define('_GNU_SOURCE', 1)
|
||||
conf.define('_POSIX_PTHREAD_SEMANTICS', 1)
|
||||
conf.define('_TANDEM_SOURCE', 1)
|
||||
conf.define('__EXTENSIONS__', 1)
|
||||
conf.define('_DARWIN_USE_64_BIT_INODE', 1)
|
||||
conf.define('_LARGE_FILES', 1)
|
||||
conf.check_large_file(compiler='c', execute=False, mandatory=False) # sets _FILE_OFFSET_BITS
|
||||
|
||||
conf.env.CFLAGS_EXTRAFLAGS = conf.filter_cflags(['-funwind-tables', '-g'], [])
|
||||
|
||||
if conf.filter_cflags(['-frandom-seed=test'], []):
|
||||
conf.env.HAVE_FRANDOM_SEED = True
|
||||
|
||||
def check_header(hdr):
|
||||
return {'header_name':hdr, 'msg':'... %s header' % hdr, 'mandatory':False, 'id':hdr}
|
||||
|
||||
conf.multicheck(
|
||||
check_header('dlfcn.h'),
|
||||
check_header('inttypes.h'),
|
||||
check_header('link.h'),
|
||||
check_header('sys/link.h'),
|
||||
check_header('mach-o/dyld.h'),
|
||||
check_header('memory.h'),
|
||||
check_header('stdint.h'),
|
||||
check_header('stdlib.h'),
|
||||
check_header('strings.h'),
|
||||
check_header('string.h'),
|
||||
check_header('sys/ldr.h'),
|
||||
check_header('sys/mman.h'),
|
||||
check_header('sys/stat.h'),
|
||||
check_header('sys/types.h'),
|
||||
check_header('tlhelp32.h'),
|
||||
check_header('unistd.h'),
|
||||
check_header('windows.h'),
|
||||
|
||||
{'fragment':FRAGMENT_ATOMIC, 'msg':'... __atomic extensions', 'define_name':'HAVE_ATOMIC_FUNCTIONS', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_SYNC, 'msg':'... __sync extensions', 'define_name':'HAVE_SYNC_FUNCTIONS', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_GETPAGESIZE, 'msg':'... getpagesize function', 'define_name':'HAVE_DECL_GETPAGESIZE', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_STRNLEN, 'msg':'... strnlen function', 'define_name':'HAVE_DECL_STRNLEN', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'link.h', 'msg':'... dl_iterate_phdr function in link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['link.h'], 'mandatory':False},
|
||||
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', 'msg':'... dl_iterate_phdr function in sys/link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['sys/link.h'], 'mandatory':False},
|
||||
{'fragment':FRAGMENT_FCNTL,'msg':'... fnctl function', 'define_name':'HAVE_FCNTL', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_GETEXECNAME,'msg':'... getexecname function','define_name':'HAVE_GETEXECNAME', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_GETIPINFO, 'msg':'... _Unwind_GetIPInfo function', 'define_name':'HAVE_GETIPINFO', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC', 'msg': '... KERN_PROC and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC_ARGS', 'msg': '... KERN_PROC_ARGS and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC_ARGS', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_LOADQUERY, 'msg': '... loadquery function', 'define_name':'HAVE_LOADQUERY', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_LSTAT, 'msg': '... lstat function', 'define_name':'HAVE_LSTAT', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_READLINK, 'msg': '... readlink function', 'define_name':'HAVE_READLINK', 'mandatory':False},
|
||||
|
||||
# {'lib':'lzma', 'define_name':'HAVE_LIBLZMA', 'uselib_store':'lzma', 'msg':'... lzma library', 'mandatory':False},
|
||||
# {'lib':'z', 'define_name':'HAVE_ZLIB', 'uselib_store':'z', 'msg':'... zlib library', 'mandatory':False},
|
||||
# {'lib':'zstd', 'define_name':'HAVE_ZSTD', 'uselib_store':'zstd', 'msg':'... zstd library', 'mandatory':False},
|
||||
msg='Checking for in parallel'
|
||||
)
|
||||
|
||||
conf.write_config_header()
|
||||
|
||||
conf.define('BACKTRACE_SUPPORTED', 1)
|
||||
conf.define('BACKTRACE_USES_MALLOC', 0)
|
||||
conf.define('BACKTRACE_SUPPORTS_THREADS', 1)
|
||||
conf.define('BACKTRACE_SUPPORTS_DATA', conf.env.DEST_BINFMT in ['elf', 'mac-o'])
|
||||
|
||||
conf.write_config_header('backtrace-supported.h')
|
||||
|
||||
@TaskGen.feature('frandomseed')
|
||||
@TaskGen.after_method('propagate_uselib_vars')
|
||||
def process_frandom_seed(ctx):
|
||||
tasks = getattr(ctx, 'compiled_tasks', [])
|
||||
|
||||
for task in tasks:
|
||||
out = task.outputs[0]
|
||||
task.env.CFLAGS = list(task.env.CFLAGS) # need a copy
|
||||
task.env.CFLAGS += ['-frandom-seed=%s' % out.path_from(out.ctx.bldnode)]
|
||||
|
||||
def build(bld):
|
||||
if bld.env.DISABLE_LIBBACKTRACE:
|
||||
return
|
||||
|
||||
# we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers
|
||||
sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c', 'mmap.c', 'mmapio.c']
|
||||
|
||||
if bld.env.DEST_BINFMT == 'pe':
|
||||
sources += ['pecoff.c']
|
||||
elif bld.env.DEST_BINFMT == 'mac-o':
|
||||
sources += ['macho.c']
|
||||
elif bld.env.DEST_BINFMT == 'elf':
|
||||
sources += ['elf.c']
|
||||
else:
|
||||
sources += ['unknown.c']
|
||||
|
||||
task = bld.stlib(
|
||||
source = ['libbacktrace/' + i for i in sources],
|
||||
target = 'backtrace',
|
||||
features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '',
|
||||
use = 'EXTRAFLAGS lzma z zstd',
|
||||
includes = '. libbacktrace/',
|
||||
export_defines = 'HAVE_LIBBACKTRACE=1',
|
||||
export_includes = 'libbacktrace/'
|
||||
)
|
||||
|
||||
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: 1b6929d663...695ea1be2e
@@ -6,7 +6,7 @@ For connecting to GoldSrc-based servers, use this command:
|
||||
connect ip:port gs
|
||||
```
|
||||
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto.
|
||||
Without this requirement, you will just get "Steam validation rejected" error on connecting.
|
||||
|
||||
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
|
||||
|
||||
@@ -38,9 +38,6 @@ Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Ct
|
||||
## Deathmatch Classic
|
||||
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc
|
||||
|
||||
## Delta Particles
|
||||
Available on ModDB - https://www.moddb.com/mods/half-life-delta/downloads/delta-particles-full-sources-maps-and-c-code
|
||||
|
||||
## Earth Special Forces
|
||||
Alpha 2.0 - https://www.gamers-desire.de/details/2830
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
|
||||
[](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) \
|
||||
[](http://fwgsdiscord.mentality.rip/) [](https://t.me/flyingwithgauss) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ cmake_minimum_required(VERSION 3.6)
|
||||
project(XASH_ANDROID)
|
||||
|
||||
# armeabi-v7a requires cpufeatures library
|
||||
if(ANDROID)
|
||||
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||
target_link_libraries(cpufeatures dl)
|
||||
endif()
|
||||
include(AndroidNdkModules)
|
||||
android_ndk_import_module_cpufeatures()
|
||||
|
||||
include(FindPython)
|
||||
find_package(PythonInterp 2.7 REQUIRED)
|
||||
|
||||
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
|
||||
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(BUILD_TYPE "debug")
|
||||
@@ -20,20 +20,30 @@ else()
|
||||
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
|
||||
endif()
|
||||
|
||||
if(ANDROID_ABI STREQUAL "x86")
|
||||
# HACKHACK: I don't know why but engine gets built as 64-bit binary here
|
||||
list(APPEND WAF_EXTRA_ARGS -4)
|
||||
if(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
set(64BIT ON CACHE BOOL "" FORCE)
|
||||
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux
|
||||
endif()
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
|
||||
# not cleanest way to get upper directory
|
||||
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
CC=${WAF_CC} CXX=${WAF_CXX}
|
||||
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
|
||||
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} ${WAF_EXTRA_ARGS} cmake
|
||||
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
|
||||
-s "${ENGINE_SOURCE_DIR}/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
|
||||
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# try to build minimal SDL. Enable features as we're gonna use them
|
||||
set(SDL_RENDER OFF)
|
||||
@@ -46,50 +56,5 @@ set(SDL_VULKAN OFF)
|
||||
set(SDL_OFFSCREEN OFF)
|
||||
set(SDL_STATIC OFF)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
# gradle passes backslashes to cmake, how does this even work for everybody else?
|
||||
string(REPLACE "\\" "/" CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
||||
|
||||
ExternalProject_Add(
|
||||
Xash3DFWGS
|
||||
SOURCE_DIR ${ENGINE_SOURCE_DIR}
|
||||
INSTALL_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
BUILD_IN_SOURCE TRUE
|
||||
DEPENDS SDL2
|
||||
BUILD_ALWAYS TRUE
|
||||
LOG_CONFIGURE TRUE
|
||||
LOG_BUILD TRUE
|
||||
LOG_INSTALL TRUE
|
||||
LOG_OUTPUT_ON_FAILURE TRUE
|
||||
LOG_MERGED_STDOUTERR TRUE
|
||||
|
||||
# USES_TERMINAL_CONFIGURE TRUE
|
||||
# USES_TERMINAL_BUILD TRUE
|
||||
# USES_TERMINAL_INSTALL TRUE
|
||||
|
||||
# NOTE: setting up WAFLOCK is important to avoid possible race conditions
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
|
||||
ANDROID_NDK=${ANDROID_NDK}
|
||||
BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} configure -T ${BUILD_TYPE} --android=${ANDROID_ABI},,${CMAKE_SYSTEM_VERSION}
|
||||
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --enable-bundled-deps
|
||||
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E env
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} build -v
|
||||
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E env
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} install --destdir=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# a1ba: without this, xash3d target will be ignored as nothing depends on it
|
||||
add_dependencies(client Xash3DFWGS)
|
||||
add_dependencies(server Xash3DFWGS)
|
||||
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui)
|
||||
|
||||
@@ -9,7 +9,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "su.xash.engine"
|
||||
ndkVersion = "28.0.13004108"
|
||||
ndkVersion = "27.2.12479018"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "su.xash"
|
||||
@@ -96,7 +96,6 @@ android {
|
||||
packaging {
|
||||
jniLibs {
|
||||
useLegacyPackaging = true
|
||||
keepDebugSymbols.add("**/*.so")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +112,7 @@ dependencies {
|
||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
|
||||
implementation("com.madgag.spongycastle:prov:1.58.0.0")
|
||||
implementation("in.dragonbra:javasteam:1.2.0")
|
||||
|
||||
@@ -20,7 +20,4 @@ kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# Enable verbose output for CMake
|
||||
android.native.buildOutput=verbose
|
||||
android.nonTransitiveRClass=true
|
||||
@@ -28,17 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define PORT_ANY -1
|
||||
|
||||
typedef enum netadrtype_e
|
||||
{
|
||||
NA_UNDEFINED = 0,
|
||||
NA_LOOPBACK,
|
||||
NA_BROADCAST,
|
||||
NA_IP,
|
||||
NA_IPX,
|
||||
NA_BROADCAST_IPX,
|
||||
NA_IP6,
|
||||
NA_MULTICAST_IP6
|
||||
} netadrtype_t;
|
||||
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
|
||||
|
||||
/*
|
||||
Original Quake-2 structure:
|
||||
@@ -56,60 +46,29 @@ typedef struct
|
||||
#pragma pack( push, 1 )
|
||||
typedef struct netadr_s
|
||||
{
|
||||
// the reason we do this evil thing, is that when this struct contains IPv6
|
||||
// address the `type` is 2-byte wide, but when it doesn't `type` must 4-byte
|
||||
// wide _and_ ip6_0 must be zeroed, to keep it binary compatible.
|
||||
#if XASH_LITTLE_ENDIAN
|
||||
uint16_t type;
|
||||
uint8_t ip6_0[2];
|
||||
#elif XASH_BIG_ENDIAN
|
||||
uint8_t ip6_0[2];
|
||||
uint16_t type;
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
union
|
||||
{
|
||||
// IPv6 struct
|
||||
uint8_t ip6_1[14];
|
||||
struct
|
||||
{
|
||||
uint16_t type6;
|
||||
uint8_t ip6[16];
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t type; // must be netadrtype_t but will break with short enums
|
||||
union
|
||||
{
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4; // for easier conversions
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4; // for easier conversions
|
||||
};
|
||||
uint8_t ipx[10];
|
||||
};
|
||||
};
|
||||
uint16_t port;
|
||||
uint16_t port;
|
||||
} netadr_t;
|
||||
#pragma pack( pop )
|
||||
|
||||
static inline netadrtype_t NET_NetadrType( const netadr_t *a )
|
||||
{
|
||||
if( a->type == NA_IP6 || a->type == NA_MULTICAST_IP6 )
|
||||
return (netadrtype_t)a->type;
|
||||
|
||||
if( a->ip6_0[0] || a->ip6_0[1] )
|
||||
return NA_UNDEFINED;
|
||||
|
||||
return (netadrtype_t)a->type;
|
||||
}
|
||||
|
||||
static inline void NET_NetadrSetType( netadr_t *a, netadrtype_t type )
|
||||
{
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
a->type = type;
|
||||
return;
|
||||
}
|
||||
|
||||
a->ip6_0[0] = a->ip6_0[1] = 0;
|
||||
a->type = type;
|
||||
}
|
||||
|
||||
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
|
||||
|
||||
#endif // NET_ADR_H
|
||||
|
||||
@@ -13,19 +13,13 @@
|
||||
#endif // _WIN32
|
||||
|
||||
#include <sys/types.h> // off_t
|
||||
#ifdef STDINT_H
|
||||
#include STDINT_H
|
||||
#else // !STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif // !STDINT_H
|
||||
#include <assert.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec2_t[2];
|
||||
#ifndef vec3_t // SDK renames it to Vector
|
||||
typedef vec_t vec3_t[3];
|
||||
#endif
|
||||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t quat_t[4];
|
||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||
@@ -50,7 +44,6 @@ typedef int qboolean;
|
||||
|
||||
#define BIT( n ) ( 1U << ( n ))
|
||||
#define BIT64( n ) ( 1ULL << ( n ))
|
||||
|
||||
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
|
||||
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
|
||||
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
|
||||
@@ -67,8 +60,6 @@ typedef int qboolean;
|
||||
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
|
||||
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#if defined( __i386__ )
|
||||
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
|
||||
|
||||
@@ -173,7 +173,7 @@ static int CL_CalcTabStop( const cl_font_t *font, int x )
|
||||
return stop;
|
||||
}
|
||||
|
||||
int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_t *font, int flags )
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
wrect_t *rc;
|
||||
float w, h;
|
||||
@@ -231,7 +231,7 @@ int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_
|
||||
return font->charWidths[number];
|
||||
}
|
||||
|
||||
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags )
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
rgba_t current_color;
|
||||
int draw_len = 0;
|
||||
@@ -287,7 +287,7 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_
|
||||
return draw_len;
|
||||
}
|
||||
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... )
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
@@ -306,22 +306,21 @@ void SPR_AdjustSize( float *x, float *y, float *w, float *h )
|
||||
|
||||
static void SPR_AdjustTexCoords( int texnum, float width, float height, float *s1, float *t1, float *s2, float *t2 )
|
||||
{
|
||||
const qboolean filtering = REF_GET_PARM( PARM_TEX_FILTERING, texnum );
|
||||
const int xremainder = refState.width % clgame.scrInfo.iWidth;
|
||||
const int yremainder = refState.height % clgame.scrInfo.iHeight;
|
||||
|
||||
if(( filtering || xremainder ) && refState.width != clgame.scrInfo.iWidth )
|
||||
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum ))
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
|
||||
if(( filtering || yremainder ) && refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
if( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
*s1 /= width;
|
||||
@@ -1699,12 +1698,7 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
|
||||
clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
|
||||
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
|
||||
|
||||
if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value )
|
||||
{
|
||||
scale_factor = refState.width / hud_scale.value;
|
||||
apply_scale_factor = true;
|
||||
}
|
||||
else if( scale_factor && scale_factor != 1.0f )
|
||||
if( scale_factor && scale_factor != 1.0f )
|
||||
{
|
||||
float scaled_width = (float)refState.width / scale_factor;
|
||||
if( scaled_width >= hud_scale_minimal_width.value )
|
||||
@@ -3427,7 +3421,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
return;
|
||||
}
|
||||
|
||||
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
||||
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
|
||||
@@ -1063,7 +1063,6 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
||||
const char *key = ID_GetMD5();
|
||||
netadr_t adr = { 0 };
|
||||
int input_devices;
|
||||
netadrtype_t adrtype;
|
||||
|
||||
protinfo[0] = 0;
|
||||
|
||||
@@ -1074,16 +1073,14 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
||||
return;
|
||||
}
|
||||
|
||||
adrtype = NET_NetadrType( &adr );
|
||||
|
||||
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
|
||||
|
||||
input_devices = IN_CollectInputDevices();
|
||||
IN_LockInputDevices( adrtype != NA_LOOPBACK ? true : false );
|
||||
IN_LockInputDevices( adr.type != NA_LOOPBACK ? true : false );
|
||||
|
||||
// GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo
|
||||
// it also doesn't need useragent string
|
||||
if( adrtype != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
if( adr.type != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
{
|
||||
Cvar_SetCheatState();
|
||||
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
|
||||
@@ -1221,7 +1218,7 @@ static void CL_CheckForResend( void )
|
||||
cls.signon = 0;
|
||||
cls.state = ca_connecting;
|
||||
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
|
||||
NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK );
|
||||
cls.serveradr.type = NA_LOOPBACK;
|
||||
cls.legacymode = PROTO_CURRENT;
|
||||
|
||||
// we don't need a challenge on the localhost
|
||||
@@ -1557,8 +1554,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
|
||||
MSG_WriteString( &buf, "dropclient\n" );
|
||||
else MSG_WriteString( &buf, "disconnect" );
|
||||
|
||||
if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED )
|
||||
NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK );
|
||||
if( !cls.netchan.remote_address.type )
|
||||
cls.netchan.remote_address.type = NA_LOOPBACK;
|
||||
|
||||
// make sure message will be delivered
|
||||
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
|
||||
@@ -1727,17 +1724,19 @@ CL_LocalServers_f
|
||||
*/
|
||||
static void CL_LocalServers_f( void )
|
||||
{
|
||||
netadr_t adr = { 0 };
|
||||
netadr_t adr;
|
||||
|
||||
memset( &adr, 0, sizeof( adr ));
|
||||
|
||||
Con_Printf( "Scanning for servers on the local network area...\n" );
|
||||
NET_Config( true, true ); // allow remote
|
||||
|
||||
// send a broadcast packet
|
||||
NET_NetadrSetType( &adr, NA_BROADCAST );
|
||||
adr.type = NA_BROADCAST;
|
||||
adr.port = MSG_BigShort( PORT_SERVER );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
|
||||
NET_NetadrSetType( &adr, NA_MULTICAST_IP6 );
|
||||
adr.type = NA_MULTICAST_IP6;
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
@@ -2481,18 +2480,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
uint8_t addr[16];
|
||||
netadr_t servadr = { 0 };
|
||||
netadr_t servadr;
|
||||
|
||||
if( NET_NetadrType( &from ) == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
{
|
||||
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
||||
NET_IP6BytesToNetadr( &servadr, addr );
|
||||
NET_NetadrSetType( &servadr, NA_IP6 );
|
||||
servadr.type6 = NA_IP6;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||
NET_NetadrSetType( &servadr, NA_IP );
|
||||
servadr.type = NA_IP;
|
||||
}
|
||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||
|
||||
@@ -3140,9 +3139,6 @@ static qboolean CL_ShouldRescanFilesystem( void )
|
||||
}
|
||||
}
|
||||
|
||||
if( FBitSet( fs_mount_lv.flags|fs_mount_hd.flags|fs_mount_addon.flags|fs_mount_l10n.flags|ui_language.flags, FCVAR_CHANGED ))
|
||||
retval = true;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -3152,7 +3148,7 @@ qboolean CL_PrecacheResources( void )
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
FS_Rescan_f();
|
||||
g_fsapi.Rescan();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
|
||||
@@ -92,11 +92,6 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnSetCustomClientID( const char *id )
|
||||
{
|
||||
// deprecated
|
||||
}
|
||||
|
||||
static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
{
|
||||
MOBILITY_API_VERSION,
|
||||
@@ -111,7 +106,7 @@ static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
pfnDrawScaledCharacter,
|
||||
Sys_Warn,
|
||||
Sys_GetNativeObject,
|
||||
pfnSetCustomClientID,
|
||||
ID_SetCustomClientID,
|
||||
pfnParseFileSafe
|
||||
};
|
||||
|
||||
|
||||
@@ -83,10 +83,7 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
|
||||
// FIXME: set world wave height when entities will be allocated
|
||||
if( clgame.entities )
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
|
||||
// keep features an actual!
|
||||
clgame.oldmovevars.features = clgame.movevars.features = host.features;
|
||||
|
||||
@@ -2429,7 +2429,7 @@ void CL_SetLightstyle( int style, const char *s, float f )
|
||||
|
||||
if( unlikely( style < 0 || style >= MAX_LIGHTSTYLES ))
|
||||
{
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", style );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -807,11 +807,11 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
|
||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
|
||||
void CL_FreeFont( cl_font_t *font );
|
||||
void CL_SetFontRendermode( cl_font_t *font );
|
||||
int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
|
||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
|
||||
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags );
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
|
||||
|
||||
|
||||
//
|
||||
@@ -844,21 +844,19 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int index )
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
if( !clgame.entities ) // not in game yet
|
||||
if( !clgame.entities )
|
||||
{
|
||||
Host_Error( "%s: clgame.entities is NULL\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
{
|
||||
Host_Error( "%s: bad number %i\n", __func__, index );
|
||||
return NULL;
|
||||
}
|
||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
||||
return clgame.entities + n;
|
||||
|
||||
return clgame.entities + index;
|
||||
Host_Error( "%s: bad number %i\n", __func__, n );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
@@ -869,7 +867,10 @@ static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
return NULL;
|
||||
|
||||
return clgame.entities + index;
|
||||
if( index == 0 )
|
||||
return clgame.entities;
|
||||
|
||||
return CL_EDICT_NUM( index );
|
||||
}
|
||||
|
||||
static inline model_t *CL_ModelHandle( int modelindex )
|
||||
@@ -879,7 +880,7 @@ static inline model_t *CL_ModelHandle( int modelindex )
|
||||
|
||||
static inline qboolean CL_IsThirdPerson( void )
|
||||
{
|
||||
return clgame.dllFuncs.CL_IsThirdPerson();
|
||||
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false;
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetLocalPlayer( void )
|
||||
@@ -1107,7 +1108,7 @@ int Con_UtfMoveRight( char *str, int pos, int length );
|
||||
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
|
||||
cl_font_t *Con_GetCurFont( void );
|
||||
cl_font_t *Con_GetFont( int num );
|
||||
int Con_DrawString( int x, int y, const char *string, const rgba_t setColor ); // legacy, use cl_font.c
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
|
||||
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
|
||||
void Con_CharEvent( int key );
|
||||
void Key_Console( int key );
|
||||
@@ -1214,6 +1215,7 @@ void OSK_Draw( void );
|
||||
//
|
||||
void ID_Init( void );
|
||||
const char *ID_GetMD5( void );
|
||||
void GAME_EXPORT ID_SetCustomClientID( const char *id );
|
||||
|
||||
extern rgba_t g_color_table[8];
|
||||
extern triangleapi_t gTriApi;
|
||||
|
||||
@@ -759,7 +759,7 @@ Con_DrawString
|
||||
client version of routine
|
||||
====================
|
||||
*/
|
||||
int Con_DrawString( int x, int y, const char *string, const rgba_t setColor )
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor )
|
||||
{
|
||||
return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 );
|
||||
}
|
||||
@@ -843,14 +843,11 @@ If no console is visible, the notify window will pop up.
|
||||
*/
|
||||
void Con_Print( const char *txt )
|
||||
{
|
||||
static qboolean cr_pending = false;
|
||||
static qboolean colorstring = false;
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
static int lastlength = 0;
|
||||
static int bufpos = 0;
|
||||
static int charpos = 0;
|
||||
|
||||
qboolean norefresh = false;
|
||||
static int cr_pending = 0;
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
qboolean norefresh = false;
|
||||
static int lastlength = 0;
|
||||
static int bufpos = 0;
|
||||
int c, mask = 0;
|
||||
|
||||
// client not running
|
||||
@@ -876,7 +873,7 @@ void Con_Print( const char *txt )
|
||||
if( cr_pending )
|
||||
{
|
||||
Con_DeleteLastLine();
|
||||
cr_pending = false;
|
||||
cr_pending = 0;
|
||||
}
|
||||
c = *txt;
|
||||
|
||||
@@ -889,42 +886,23 @@ void Con_Print( const char *txt )
|
||||
{
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
cr_pending = true;
|
||||
cr_pending = 1;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
break;
|
||||
default:
|
||||
|
||||
buf[bufpos++] = c | mask;
|
||||
|
||||
if( IsColorString( txt ))
|
||||
{
|
||||
// first color string character
|
||||
colorstring = true;
|
||||
}
|
||||
else if( colorstring )
|
||||
{
|
||||
// second color string character
|
||||
colorstring = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a color string, move char counter
|
||||
charpos++;
|
||||
}
|
||||
|
||||
if(( bufpos >= sizeof( buf ) - 1 ) || charpos >= ( con.linewidth - 1 ))
|
||||
if(( bufpos >= sizeof( buf ) - 1 ) || bufpos >= ( con.linewidth - 1 ))
|
||||
{
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -940,7 +918,6 @@ void Con_Print( const char *txt )
|
||||
Con_AddLine( buf, bufpos, lastlength != 0 );
|
||||
lastlength = 0;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
|
||||
// pump messages to avoid window hanging
|
||||
@@ -1490,16 +1467,6 @@ Handles history and console scrollback
|
||||
*/
|
||||
void Key_Console( int key )
|
||||
{
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON || key == K_ESCAPE )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// ctrl-L clears screen
|
||||
if( key == 'l' && Key_IsDown( K_CTRL ))
|
||||
{
|
||||
@@ -1608,6 +1575,16 @@ void Key_Console( int key )
|
||||
return;
|
||||
}
|
||||
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// pass to the normal editline routine
|
||||
Field_KeyDownEvent( &con.input, key );
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ GNU General Public License for more details.
|
||||
#if !XASH_WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
static char id_md5[33];
|
||||
static char id_customid[MAX_STRING];
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
@@ -590,9 +590,25 @@ static void ID_Check( void )
|
||||
|
||||
const char *ID_GetMD5( void )
|
||||
{
|
||||
if( id_customid[0] )
|
||||
return id_customid;
|
||||
return id_md5;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
ID_SetCustomClientID
|
||||
|
||||
===============
|
||||
*/
|
||||
void GAME_EXPORT ID_SetCustomClientID( const char *id )
|
||||
{
|
||||
if( !id )
|
||||
return;
|
||||
|
||||
Q_strncpy( id_customid, id, sizeof( id_customid ) );
|
||||
}
|
||||
|
||||
void ID_Init( void )
|
||||
{
|
||||
MD5Context_t hash = { 0 };
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -332,7 +332,7 @@ static void IN_MouseMove( void )
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
if( Touch_WantVisibleCursor( ))
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
// touch emulation overrides all input
|
||||
Touch_KeyEvent( 0, 0 );
|
||||
@@ -363,7 +363,7 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
if( Touch_WantVisibleCursor( ))
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
qboolean Touch_WantVisibleCursor( void );
|
||||
qboolean Touch_Emulated( void );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
|
||||
@@ -726,8 +726,18 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
return; // handled in client.dll
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case key_message:
|
||||
Key_Message( key );
|
||||
return;
|
||||
case key_console:
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
case key_menu:
|
||||
UI_KeyEvent( key, true );
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,11 +167,6 @@ extern convar_t cl_filterstuffcmd;
|
||||
extern convar_t rcon_password;
|
||||
extern convar_t hpk_custom_file;
|
||||
extern convar_t con_gamemaps;
|
||||
extern convar_t fs_mount_lv;
|
||||
extern convar_t fs_mount_hd;
|
||||
extern convar_t fs_mount_addon;
|
||||
extern convar_t fs_mount_l10n;
|
||||
extern convar_t ui_language; // historically used for UI, but now controls mounted localization directory
|
||||
|
||||
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
|
||||
|
||||
@@ -415,8 +410,6 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
void FS_Rescan_f( void );
|
||||
void FS_CheckConfig( void );
|
||||
|
||||
//
|
||||
// cmd.c
|
||||
|
||||
@@ -498,6 +498,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetItemsList
|
||||
@@ -507,7 +508,6 @@ Prints or complete item classname (weapons only)
|
||||
*/
|
||||
static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
search_t *t;
|
||||
string matchbuf;
|
||||
int i, numitems;
|
||||
@@ -521,7 +521,7 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
Q_strncpy( completedname, matchbuf, length );
|
||||
if( t->numfilenames == 1 ) return true;
|
||||
|
||||
for( i = 0, numitems = 0; i < t->numfilenames; i++ )
|
||||
for(i = 0, numitems = 0; i < t->numfilenames; i++)
|
||||
{
|
||||
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" ))
|
||||
continue;
|
||||
@@ -544,8 +544,6 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -557,7 +555,6 @@ Autocomplete for bind command
|
||||
*/
|
||||
static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
size_t i, numkeys;
|
||||
string keys[256];
|
||||
string matchbuf;
|
||||
@@ -598,9 +595,8 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
===============
|
||||
@@ -608,20 +604,13 @@ Con_AddCommandToList
|
||||
|
||||
===============
|
||||
*/
|
||||
static void Con_AddCommandToList( const char *s, const char *value, const void *ptoggle, void *_autocompleteList )
|
||||
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList )
|
||||
{
|
||||
con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList;
|
||||
qboolean toggle = ptoggle != NULL && *(qboolean *)ptoggle;
|
||||
|
||||
if( *s == '@' ) return; // never show system cvars or cmds
|
||||
if( list->matchCount >= CON_MAXCMDS ) return; // list is full
|
||||
|
||||
if( toggle )
|
||||
{
|
||||
if( Q_strcmp( value, "0" ) && Q_strcmp( value, "1" ))
|
||||
return; // exclude non-toggable cvars
|
||||
}
|
||||
|
||||
if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) )
|
||||
return; // no match
|
||||
|
||||
@@ -645,11 +634,13 @@ Cmd_GetCommandsList
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname, int length, qboolean cmds, qboolean cvars, qboolean toggle )
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
size_t i;
|
||||
string matchbuf;
|
||||
con_autocomplete_t list = { 0 }; // local autocomplete list
|
||||
con_autocomplete_t list; // local autocomplete list
|
||||
|
||||
memset( &list, 0, sizeof( list ));
|
||||
|
||||
list.completionString = s;
|
||||
|
||||
@@ -661,16 +652,8 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
return false;
|
||||
|
||||
// find matching commands and variables
|
||||
if( cvars )
|
||||
{
|
||||
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( cmds )
|
||||
{
|
||||
toggle = false;
|
||||
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !list.matchCount ) return false;
|
||||
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
|
||||
@@ -686,7 +669,7 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Con_Printf( "\n^3 %i %s found.\n", list.matchCount, cmds ? "commands" : "variables" );
|
||||
Con_Printf( "\n^3 %i commands found.\n", list.matchCount );
|
||||
|
||||
if( completedname && length )
|
||||
{
|
||||
@@ -708,30 +691,6 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCommandsList
|
||||
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
return Cmd_GetCommandsAndCvarsList( s, completedname, length, true, true, false );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCvarList
|
||||
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCvarsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
qboolean toggle = !Q_stricmp( Cmd_Argv( 0 ), "toggle" );
|
||||
return Cmd_GetCommandsAndCvarsList( s, completedname, length, false, true, toggle );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
@@ -1051,38 +1010,36 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
|
||||
return Cmd_CheckMapsList_R( fRefresh, true );
|
||||
}
|
||||
|
||||
// keep this sorted
|
||||
static const autocomplete_list_t cmd_list[] =
|
||||
{
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "changelevel2", 1, Cmd_GetMapList },
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "drop", 1, Cmd_GetItemsList },
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "movie", 1, Cmd_GetMovieList },
|
||||
{ "mp3", 1, Cmd_GetCDList },
|
||||
{ "music", 1, Cmd_GetMusicList, },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "reset", 1, Cmd_GetCvarsList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "set", 1, Cmd_GetCvarsList },
|
||||
{ "timedemo", 1, Cmd_GetDemoList },
|
||||
{ "toggle", 1, Cmd_GetCvarsList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "music", 1, Cmd_GetMusicList, },
|
||||
{ "movie", 1, Cmd_GetMovieList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
#if !XASH_DEDICATED
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "drop", 1, Cmd_GetItemsList },
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "unbind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
#endif
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "mp3", 1, Cmd_GetCDList },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1203,7 +1160,6 @@ void Con_CompleteCommand( field_t *field )
|
||||
{
|
||||
field_t temp;
|
||||
string filename;
|
||||
qboolean toggle = false;
|
||||
qboolean nextcmd;
|
||||
int i;
|
||||
|
||||
@@ -1238,8 +1194,8 @@ void Con_CompleteCommand( field_t *field )
|
||||
con.shortestMatch[0] = 0;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
filesystem.c - game filesystem based on DP fs
|
||||
Copyright (C) 2003-2006 Mathieu Olivier
|
||||
Copyright (C) 2000-2007 DarkPlaces contributors
|
||||
@@ -21,12 +21,6 @@ GNU General Public License for more details.
|
||||
#include "library.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
CVAR_DEFINE_AUTO( fs_mount_hd, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount high definition content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_lv, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount low violence models content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_addon, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount addon content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_l10n, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount localization content folder" );
|
||||
CVAR_DEFINE_AUTO( ui_language, "english", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "selected game language" );
|
||||
|
||||
fs_api_t g_fsapi;
|
||||
fs_globals_t *FI;
|
||||
|
||||
@@ -75,23 +69,9 @@ void *FS_GetNativeObject( const char *obj )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FS_Rescan_f( void )
|
||||
static void FS_Rescan_f( void )
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
// FIXME: VFS shouldn't care about this, allow engine to mount gamedirs
|
||||
if( fs_mount_lv.value ) SetBits( flags, FS_MOUNT_LV );
|
||||
if( fs_mount_hd.value ) SetBits( flags, FS_MOUNT_HD );
|
||||
if( fs_mount_addon.value ) SetBits( flags, FS_MOUNT_ADDON );
|
||||
if( fs_mount_l10n.value ) SetBits( flags, FS_MOUNT_L10N );
|
||||
|
||||
g_fsapi.Rescan( flags, ui_language.string );
|
||||
|
||||
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
|
||||
ClearBits( ui_language.flags, FCVAR_CHANGED );
|
||||
FS_Rescan();
|
||||
}
|
||||
|
||||
static void FS_ClearPaths_f( void )
|
||||
@@ -256,12 +236,6 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
return false;
|
||||
}
|
||||
|
||||
void FS_CheckConfig( void )
|
||||
{
|
||||
if( fs_mount_lv.value || fs_mount_hd.value || fs_mount_addon.value || fs_mount_l10n.value )
|
||||
FS_Rescan_f();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_Init
|
||||
@@ -314,11 +288,6 @@ void FS_Init( const char *basedir )
|
||||
Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
|
||||
Cmd_AddRestrictedCommand( "fs_make_gameinfo", FS_MakeGameInfo_f, "create gameinfo.txt for current running game" );
|
||||
|
||||
Cvar_RegisterVariable( &fs_mount_hd );
|
||||
Cvar_RegisterVariable( &fs_mount_lv );
|
||||
Cvar_RegisterVariable( &fs_mount_addon );
|
||||
Cvar_RegisterVariable( &fs_mount_l10n );
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
|
||||
host.gamedll[0] = 0;
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ static void Sys_PrintUsage( const char *exename )
|
||||
|
||||
"\nCommon options:\n"
|
||||
O("-dev [level] ", "set log verbosity 0-2")
|
||||
O("-log [file name] ", "write log to \"engine.log\" or [file name] if specified")
|
||||
O("-logtime ", "enable writing timestamps to the log file")
|
||||
O("-log ", "write log to \"engine.log\"")
|
||||
O("-nowriteconfig ", "disable config save")
|
||||
O("-noch ", "disable crashhandler")
|
||||
#if XASH_WIN32 // !!!!
|
||||
@@ -698,17 +697,17 @@ static qboolean Host_Autosleep( double dt, double scale )
|
||||
static double timewindow; // allocate a time window for sleeps
|
||||
static int counter; // for debug
|
||||
static double realsleeptime;
|
||||
const double sleeptime = sleep * 0.000001;
|
||||
const double sleeptime = sleep * 0.001;
|
||||
|
||||
if( dt < targetframetime * scale )
|
||||
{
|
||||
// if we have allocated time window, try to sleep
|
||||
if( timewindow > realsleeptime )
|
||||
{
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of microseconds
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of milliseconds
|
||||
// so we measure the real sleep time and use it to decrease the window
|
||||
double t1 = Sys_DoubleTime(), t2;
|
||||
Platform_NanoSleep( sleep * 1000 ); // in usec!
|
||||
Platform_Sleep( sleep ); // in msec!
|
||||
t2 = Sys_DoubleTime();
|
||||
realsleeptime = t2 - t1;
|
||||
|
||||
@@ -1044,7 +1043,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
|
||||
if( !Sys_CheckParm( "-noch" ))
|
||||
Sys_SetupCrashHandler( argv[0] );
|
||||
Sys_SetupCrashHandler();
|
||||
|
||||
#if XASH_DLL_LOADER
|
||||
host.enabledll = !Sys_CheckParm( "-nodll" );
|
||||
@@ -1311,7 +1310,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cmd_RemoveCommand( "setgl" );
|
||||
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
|
||||
SCR_CheckStartupVids(); // must be last
|
||||
FS_CheckConfig();
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
|
||||
Cbuf_AddTextf( "timedemo %s\n", demoname );
|
||||
|
||||
@@ -419,21 +419,14 @@ void NET_InitMasters( void )
|
||||
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
{ // IPv4-only
|
||||
NET_AddMaster( "mentality.rip:27010", false, false );
|
||||
NET_AddMaster( "ms2.mentality.rip:27010", false, false );
|
||||
NET_AddMaster( "ms3.mentality.rip:27010", false, false );
|
||||
}
|
||||
// keep main master always there
|
||||
NET_AddMaster( MASTERSERVER_ADR, false, false );
|
||||
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
|
||||
NET_AddMaster( "ms2.mentality.rip:27010", false, false ); // secondary master
|
||||
|
||||
{ // IPv6-only
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true );
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, true );
|
||||
}
|
||||
|
||||
{ // testing servers, might be offline
|
||||
NET_AddMaster( "mentality.rip:27011", false, false );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true );
|
||||
}
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, false ); // secondary IPv6-only master
|
||||
|
||||
NET_LoadMasters( );
|
||||
}
|
||||
|
||||
@@ -382,7 +382,8 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
|
||||
for( j = numbones - 1; j >= 0; j-- )
|
||||
{
|
||||
i = boneused[j];
|
||||
R_StudioCalcBones( frame, s, &pbone[i], &panim[i], adj, pos[i], q[i] );
|
||||
R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] );
|
||||
R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
@@ -723,7 +724,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i
|
||||
{
|
||||
for( k = 0; k < pseqdesc->numframes; k++ )
|
||||
{
|
||||
R_StudioCalcBones( k, 0, &pbones[j], panim, NULL, pos, NULL );
|
||||
R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos );
|
||||
Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,24 +151,17 @@ static inline qboolean NET_IsSocketValid( int socket )
|
||||
|
||||
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
|
||||
{
|
||||
memcpy( &ip6[0], adr->ip6_0, 2 );
|
||||
memcpy( &ip6[2], adr->ip6_1, 14 );
|
||||
memcpy( ip6, adr->ip6, sizeof( adr->ip6 ));
|
||||
}
|
||||
|
||||
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
|
||||
{
|
||||
memcpy( adr->ip6_0, &ip6[0], 2 );
|
||||
memcpy( adr->ip6_1, &ip6[2], 14 );
|
||||
memcpy( adr->ip6, ip6, sizeof( adr->ip6 ));
|
||||
}
|
||||
|
||||
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
|
||||
{
|
||||
uint8_t ip6_a[16], ip6_b[16];
|
||||
|
||||
NET_NetadrToIP6Bytes( ip6_a, a );
|
||||
NET_NetadrToIP6Bytes( ip6_b, b );
|
||||
|
||||
return memcmp( ip6_a, ip6_b, sizeof( ip6_a ));
|
||||
return memcmp( a->ip6, b->ip6, sizeof( a->ip6 ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -178,29 +171,27 @@ NET_NetadrToSockadr
|
||||
*/
|
||||
static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
|
||||
{
|
||||
netadrtype_t type = NET_NetadrType( a );
|
||||
|
||||
memset( s, 0, sizeof( *s ));
|
||||
|
||||
if( type == NA_BROADCAST )
|
||||
if( a->type == NA_BROADCAST )
|
||||
{
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if( type == NA_IP )
|
||||
else if( a->type == NA_IP )
|
||||
{
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
|
||||
}
|
||||
else if( type == NA_IP6 )
|
||||
else if( a->type6 == NA_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a );
|
||||
}
|
||||
else if( type == NA_MULTICAST_IP6 )
|
||||
else if( a->type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
@@ -217,13 +208,13 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
{
|
||||
if( s->ss_family == AF_INET )
|
||||
{
|
||||
NET_NetadrSetType( a, NA_IP );
|
||||
a->type = NA_IP;
|
||||
a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->port = ((struct sockaddr_in *)s)->sin_port;
|
||||
}
|
||||
else if( s->ss_family == AF_INET6 )
|
||||
{
|
||||
NET_NetadrSetType( a, NA_IP6 );
|
||||
a->type6 = NA_IP6;
|
||||
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
|
||||
a->port = ((struct sockaddr_in6 *)s)->sin6_port;
|
||||
}
|
||||
@@ -558,8 +549,8 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
// try to parse as IPv6 first
|
||||
if( ParseIPv6Addr( copy, ip6, NULL, NULL ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_IP6 );
|
||||
NET_IP6BytesToNetadr( adr, ip6 );
|
||||
adr->type6 = NA_IP6;
|
||||
|
||||
if( !hasCIDR )
|
||||
*prefixlen = 128;
|
||||
@@ -629,7 +620,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
adr->ip4 = ntohl( mask );
|
||||
}
|
||||
|
||||
NET_NetadrSetType( adr, NA_IP );
|
||||
adr->type = NA_IP;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -643,11 +634,10 @@ NET_AdrToString
|
||||
const char *NET_AdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( type == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -671,11 +661,10 @@ NET_BaseAdrToString
|
||||
const char *NET_BaseAdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( type == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -700,19 +689,16 @@ Compares without the port
|
||||
*/
|
||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
return a.ip4 == b.ip4;
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
if( !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -721,6 +707,36 @@ qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_CompareClassBAdr
|
||||
|
||||
Compare local masks
|
||||
====================
|
||||
*/
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] )
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: we don't check for IPv6 here
|
||||
// this check is very dumb and only used for LAN restriction
|
||||
// Actual check is in IsReservedAdr
|
||||
|
||||
// for real mask compare use NET_CompareAdrByMask
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_CompareAdrByMask
|
||||
@@ -730,13 +746,10 @@ Checks if adr is a part of subnet
|
||||
*/
|
||||
qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b || type_a == NA_LOOPBACK )
|
||||
if( a.type6 != b.type6 || a.type == NA_LOOPBACK )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
uint32_t ipa = htonl( a.ip4 );
|
||||
uint32_t ipb = htonl( b.ip4 );
|
||||
@@ -744,7 +757,7 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
|
||||
if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
|
||||
return true;
|
||||
}
|
||||
else if( type_a == NA_IP6 )
|
||||
else if( a.type6 == NA_IP6 )
|
||||
{
|
||||
uint16_t a_[8], b_[8];
|
||||
size_t check = prefixlen / 16;
|
||||
@@ -785,13 +798,11 @@ Check for reserved ip's
|
||||
*/
|
||||
qboolean NET_IsReservedAdr( netadr_t a )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
// Following checks was imported from GameNetworkingSockets library
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
|
||||
( a.ip[0] == 127 ) || // 127.x.x.x
|
||||
@@ -803,7 +814,7 @@ qboolean NET_IsReservedAdr( netadr_t a )
|
||||
}
|
||||
}
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -836,23 +847,20 @@ Compare full address
|
||||
*/
|
||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if( a.ip4 == b.ip4 && a.port == b.port )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -875,13 +883,9 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
{
|
||||
const netadr_t *a = _a, *b = _b;
|
||||
int porta, portb, portdiff, addrdiff;
|
||||
netadrtype_t type_a, type_b;
|
||||
|
||||
type_a = NET_NetadrType( a );
|
||||
type_b = NET_NetadrType( b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return bound( -1, (int)type_a - (int)type_b, 1 );
|
||||
if( a->type6 != b->type6 )
|
||||
return bound( -1, (int)a->type6 - (int)b->type6, 1 );
|
||||
|
||||
porta = ntohs( a->port );
|
||||
portb = ntohs( b->port );
|
||||
@@ -892,7 +896,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
else
|
||||
portdiff = 0;
|
||||
|
||||
switch( type_a )
|
||||
switch( a->type6 )
|
||||
{
|
||||
case NA_IP6:
|
||||
if(( addrdiff = NET_NetadrIP6Compare( a, b )))
|
||||
@@ -900,7 +904,14 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
// fallthrough
|
||||
case NA_MULTICAST_IP6:
|
||||
return portdiff;
|
||||
}
|
||||
|
||||
// don't check for full type earlier, as it's value depends on v6 address
|
||||
if( a->type != b->type )
|
||||
return bound( -1, (int)a->type - (int)b->type, 1 );
|
||||
|
||||
switch( a->type )
|
||||
{
|
||||
case NA_IP:
|
||||
if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx ))))
|
||||
return addrdiff;
|
||||
@@ -935,7 +946,7 @@ static qboolean NET_StringToAdrEx( const char *string, netadr_t *adr, int family
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
adr->type = NA_LOOPBACK;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -960,7 +971,7 @@ net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
adr->type = NA_LOOPBACK;
|
||||
return NET_EAI_OK;
|
||||
}
|
||||
|
||||
@@ -1006,7 +1017,7 @@ static qboolean NET_GetLoopPacket( netsrc_t sock, netadr_t *from, byte *data, si
|
||||
*length = loop->msgs[i].datalen;
|
||||
|
||||
memset( from, 0, sizeof( *from ));
|
||||
NET_NetadrSetType( from, NA_LOOPBACK );
|
||||
from->type = NA_LOOPBACK;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1512,7 +1523,7 @@ static int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t
|
||||
total_sent += size;
|
||||
len -= size;
|
||||
packet_number++;
|
||||
Platform_NanoSleep( 100 * 1000 );
|
||||
Platform_Sleep( 1 );
|
||||
}
|
||||
|
||||
return total_sent;
|
||||
@@ -1535,20 +1546,19 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
int ret;
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
SOCKET net_socket = 0;
|
||||
netadrtype_t type = NET_NetadrType( &to );
|
||||
|
||||
if( !net.initialized || type == NA_LOOPBACK )
|
||||
if( !net.initialized || to.type == NA_LOOPBACK )
|
||||
{
|
||||
NET_SendLoopPacket( sock, length, data, to );
|
||||
return;
|
||||
}
|
||||
else if( type == NA_BROADCAST || type == NA_IP )
|
||||
else if( to.type == NA_BROADCAST || to.type == NA_IP )
|
||||
{
|
||||
net_socket = net.ip_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
return;
|
||||
}
|
||||
else if( type == NA_MULTICAST_IP6 || type == NA_IP6 )
|
||||
else if( to.type6 == NA_MULTICAST_IP6 || to.type6 == NA_IP6 )
|
||||
{
|
||||
net_socket = net.ip6_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
@@ -1556,7 +1566,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
}
|
||||
else
|
||||
{
|
||||
Host_Error( "%s: bad address type %i (%i, %i)\n", __func__, to.type, to.ip6_0[0], to.ip6_0[1] );
|
||||
Host_Error( "%s: bad address type %i (%i)\n", __func__, to.type, to.type6 );
|
||||
}
|
||||
|
||||
NET_NetadrToSockadr( &to, &addr );
|
||||
@@ -1572,7 +1582,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
return;
|
||||
|
||||
// some PPP links don't allow broadcasts
|
||||
if( err == WSAEADDRNOTAVAIL && ( type == NA_BROADCAST || type == NA_MULTICAST_IP6 ))
|
||||
if( err == WSAEADDRNOTAVAIL && ( to.type == NA_BROADCAST || to.type6 == NA_MULTICAST_IP6 ))
|
||||
return;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
|
||||
@@ -64,6 +64,7 @@ void NET_Config( qboolean net_enable, qboolean changeport );
|
||||
const char *NET_AdrToString( const netadr_t a ) RETURNS_NONNULL;
|
||||
const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL;
|
||||
qboolean NET_IsReservedAdr( netadr_t a );
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b );
|
||||
qboolean NET_StringToAdr( const char *string, netadr_t *adr );
|
||||
qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen );
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only );
|
||||
@@ -79,7 +80,7 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
|
||||
|
||||
static inline qboolean NET_IsLocalAddress( netadr_t adr )
|
||||
{
|
||||
return NET_NetadrType( &adr ) == NA_LOOPBACK;
|
||||
return adr.type == NA_LOOPBACK ? true : false;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
|
||||
@@ -69,6 +69,7 @@ GNU General Public License for more details.
|
||||
// bytes will be stripped by the networking channel layer
|
||||
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
|
||||
|
||||
#define MASTERSERVER_ADR "mentality.rip:27010"
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
|
||||
|
||||
#define PORT_MASTER 27010
|
||||
|
||||
@@ -31,14 +31,15 @@ GNU General Public License for more details.
|
||||
#define XASH_COLORIZE_CONSOLE 0
|
||||
#endif
|
||||
|
||||
static struct logdata_s {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
qboolean log_time;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} s_ld;
|
||||
typedef struct {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} LogData;
|
||||
|
||||
static LogData s_ld;
|
||||
|
||||
void Sys_DestroyConsole( void )
|
||||
{
|
||||
@@ -77,19 +78,14 @@ static void Sys_FlushLogfile( void )
|
||||
|
||||
void Sys_InitLog( void )
|
||||
{
|
||||
const char *mode;
|
||||
const char *mode;
|
||||
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
if( Sys_CheckParm( "-log" ) && host.allow_console != 0 )
|
||||
{
|
||||
if( !Sys_GetParmFromCmdLine( "-log", s_ld.log_path ) || !isalnum( s_ld.log_path[0] ))
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
|
||||
COM_DefaultExtension( s_ld.log_path, ".log", sizeof( s_ld.log_path ));
|
||||
s_ld.log_active = true;
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
}
|
||||
|
||||
s_ld.log_time = Sys_CheckParm( "-logtime" );
|
||||
|
||||
if( host.change_game && host.type != HOST_DEDICATED )
|
||||
mode = "a";
|
||||
else mode = "w";
|
||||
@@ -105,7 +101,7 @@ void Sys_InitLog( void )
|
||||
|
||||
if ( !s_ld.logfile )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: can't create log file %s: %s\n", __func__, s_ld.log_path, strerror( errno ));
|
||||
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -299,23 +295,17 @@ void Sys_PrintLog( const char *pMsg )
|
||||
// save last char to detect when line was not ended
|
||||
lastchar = len > 0 ? pMsg[len - 1] : 0;
|
||||
|
||||
// spew to engine.log
|
||||
if( s_ld.logfile )
|
||||
{
|
||||
if( s_ld.log_time && print_time )
|
||||
{
|
||||
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
|
||||
}
|
||||
else
|
||||
{
|
||||
logtime[0] = '\0';
|
||||
logtime_len = 0;
|
||||
}
|
||||
if( !s_ld.logfile )
|
||||
return;
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
if( print_time )
|
||||
{
|
||||
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
|
||||
}
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -65,8 +65,6 @@ typedef struct memheader_s
|
||||
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
|
||||
} memheader_t;
|
||||
|
||||
STATIC_CHECK_SIZEOF( memheader_t, 24, 40 );
|
||||
|
||||
typedef struct mempool_s
|
||||
{
|
||||
struct memheader_s *chain; // chain of individual memory allocations
|
||||
|
||||
@@ -184,7 +184,7 @@ qboolean SNDDMA_Init( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
dma.buffer = Mem_Calloc( sndpool, samples * 2 ); //allocate pcm frame buffer
|
||||
dma.buffer = Mem_Malloc( sndpool, samples * 2 ); //allocate pcm frame buffer
|
||||
dma.samplepos = 0;
|
||||
dma.samples = samples;
|
||||
dma.format.width = 2;
|
||||
|
||||
@@ -70,9 +70,6 @@ void Android_Shutdown( void );
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
void Win32_Init( qboolean con_showalways );
|
||||
void Win32_Shutdown( void );
|
||||
qboolean Win32_NanoSleep( int nsec );
|
||||
void Wcon_CreateConsole( qboolean con_showalways );
|
||||
void Wcon_DestroyConsole( void );
|
||||
void Wcon_InitConsoleCommands( void );
|
||||
@@ -127,7 +124,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
#elif XASH_DOS
|
||||
DOS_Init( );
|
||||
#elif XASH_WIN32
|
||||
Win32_Init( con_showalways );
|
||||
Wcon_CreateConsole( con_showalways );
|
||||
#elif XASH_LINUX
|
||||
Linux_Init( );
|
||||
#endif
|
||||
@@ -142,7 +139,7 @@ static inline void Platform_Shutdown( void )
|
||||
#elif XASH_DOS
|
||||
DOS_Shutdown( );
|
||||
#elif XASH_WIN32
|
||||
Win32_Shutdown( );
|
||||
Wcon_DestroyConsole( );
|
||||
#elif XASH_LINUX
|
||||
Linux_Shutdown( );
|
||||
#endif
|
||||
@@ -181,28 +178,11 @@ static inline void Platform_Sleep( int msec )
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline qboolean Platform_NanoSleep( int nsec )
|
||||
{
|
||||
// SDL2 doesn't have nanosleep, so use low-level functions here
|
||||
// When this code will be ported to SDL3, use SDL_DelayNS
|
||||
#if XASH_POSIX
|
||||
struct timespec ts = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = nsec, // just don't put large numbers here
|
||||
};
|
||||
return nanosleep( &ts, NULL ) == 0;
|
||||
#elif XASH_WIN32
|
||||
return Win32_NanoSleep( nsec );
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
|
||||
void Sys_SetupCrashHandler( const char *argv0 );
|
||||
void Sys_SetupCrashHandler( void );
|
||||
void Sys_RestoreCrashHandler( void );
|
||||
#else
|
||||
static inline void Sys_SetupCrashHandler( const char *argv0 )
|
||||
static inline void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,9 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
void *addrs[16];
|
||||
char **syms;
|
||||
|
||||
(void)context;
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
@@ -47,6 +41,10 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
crashhandler.c - advanced crashhandler
|
||||
Copyright (C) 2016 Mittorn
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if HAVE_LIBBACKTRACE
|
||||
#include <signal.h>
|
||||
#include "common.h"
|
||||
#include "backtrace.h"
|
||||
|
||||
|
||||
static struct backtrace_state *g_bt_state;
|
||||
static qboolean enable_libbacktrace;
|
||||
|
||||
static void Sys_BacktraceError( void *data, const char *msg, int errnum )
|
||||
{
|
||||
if( errnum < 0 )
|
||||
{
|
||||
Con_Printf( S_ERROR "no symbol info, no libbacktrace\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf( S_ERROR "libbacktrace error: %s (%d)\n", msg, errnum );
|
||||
|
||||
enable_libbacktrace = false;
|
||||
}
|
||||
|
||||
struct print_data
|
||||
{
|
||||
char *message;
|
||||
size_t message_size;
|
||||
int len;
|
||||
int idx;
|
||||
int logfd;
|
||||
};
|
||||
|
||||
static void Sys_AppendPrint( struct print_data *pd, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
int len;
|
||||
|
||||
va_start( va, fmt );
|
||||
len = Q_vsnprintf( pd->message, pd->message_size, fmt, va );
|
||||
va_end( va );
|
||||
|
||||
if( len > 0 )
|
||||
{
|
||||
char ch = '\n';
|
||||
|
||||
write( pd->logfd, pd->message, len );
|
||||
write( pd->logfd, &ch, 1 );
|
||||
|
||||
write( STDERR_FILENO, pd->message, len );
|
||||
write( STDERR_FILENO, &ch, 1 );
|
||||
|
||||
pd->message += len;
|
||||
pd->len += len;
|
||||
pd->message_size -= len;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sys_BacktracePrintError( void *data, const char *msg, int errnum )
|
||||
{
|
||||
struct print_data *pd = data;
|
||||
Sys_AppendPrint( pd, "%2d: error: %s (%d)\n", pd->idx++, msg, errnum );
|
||||
}
|
||||
|
||||
static void Sys_BacktracePrintSyminfo( void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize )
|
||||
{
|
||||
struct print_data *pd = data;
|
||||
Dl_info dlinfo = { 0 };
|
||||
const char *module_name;
|
||||
|
||||
if( dladdr((void *)pc, &dlinfo ))
|
||||
module_name = dlinfo.dli_fname;
|
||||
else module_name = NULL;
|
||||
|
||||
if( symname )
|
||||
{
|
||||
if( module_name )
|
||||
Sys_AppendPrint( pd, "%2d: <%s+%d> (%s)\n", pd->idx++, symname, pc - symval, module_name );
|
||||
else
|
||||
Sys_AppendPrint( pd, "%2d: <%s+%d>\n", pd->idx++, symname, pc - symval );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( module_name )
|
||||
Sys_AppendPrint( pd, "%2d: %p (%s)\n", pd->idx++, pc, module_name );
|
||||
else
|
||||
Sys_AppendPrint( pd, "%2d: %p\n", pd->idx++, pc );
|
||||
}
|
||||
}
|
||||
|
||||
static int Sys_BacktracePrintFull( void *data, uintptr_t pc, const char *filename, int lineno, const char *function )
|
||||
{
|
||||
struct print_data *pd = data;
|
||||
Dl_info dlinfo = { 0 };
|
||||
const char *module_name;
|
||||
|
||||
if( dladdr((void *)pc, &dlinfo ))
|
||||
module_name = dlinfo.dli_fname;
|
||||
else module_name = NULL;
|
||||
|
||||
if( filename && lineno && function )
|
||||
{
|
||||
if( module_name )
|
||||
Sys_AppendPrint( pd, "%2d: %s (%s:%d) (%s)\n", pd->idx++, function, filename, lineno, module_name );
|
||||
else
|
||||
Sys_AppendPrint( pd, "%2d: %s (%s:%d)\n", pd->idx++, function, filename, lineno );
|
||||
}
|
||||
else
|
||||
{
|
||||
backtrace_syminfo( g_bt_state, pc, Sys_BacktracePrintSyminfo, Sys_BacktraceError, data );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context )
|
||||
{
|
||||
char message[8192];
|
||||
int len, logfd;
|
||||
struct print_data pd = { .idx = 0 };
|
||||
|
||||
(void)context;
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
#else
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
|
||||
#endif
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
pd.logfd = logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
|
||||
pd.message = message + len;
|
||||
pd.message_size = sizeof( message ) - len;
|
||||
pd.len = 0;
|
||||
|
||||
backtrace_full( g_bt_state, 1, Sys_BacktracePrintFull, Sys_BacktracePrintError, &pd );
|
||||
|
||||
// put MessageBox as Sys_Error
|
||||
Msg( "%s\n", message );
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
host.crashed = true;
|
||||
Platform_MessageBox( "Xash Error", message, false );
|
||||
|
||||
// log saved, now we can try to save configs and close log correctly, it may crash
|
||||
if( host.type == HOST_NORMAL )
|
||||
CL_Crashed();
|
||||
host.status = HOST_CRASHED;
|
||||
|
||||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
qboolean Sys_SetupLibbacktrace( const char *argv0 )
|
||||
{
|
||||
enable_libbacktrace = true;
|
||||
g_bt_state = backtrace_create_state( argv0, true, Sys_BacktraceError, NULL );
|
||||
return g_bt_state != NULL && enable_libbacktrace;
|
||||
}
|
||||
|
||||
#endif // HAVE_EXECINFO
|
||||
@@ -28,8 +28,6 @@ GNU General Public License for more details.
|
||||
#include "library.h"
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context );
|
||||
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context );
|
||||
qboolean Sys_SetupLibbacktrace( const char *argv0 );
|
||||
static struct sigaction oldFilter;
|
||||
|
||||
#if !HAVE_EXECINFO
|
||||
@@ -47,16 +45,16 @@ static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
|
||||
if( len <= 0 )
|
||||
return 0; // overflow
|
||||
|
||||
if( dladdr( addr, &dlinfo ))
|
||||
{
|
||||
if( dlinfo.dli_sname )
|
||||
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
|
||||
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
|
||||
if( dladdr( addr, &dlinfo ))
|
||||
{
|
||||
if( dlinfo.dli_sname )
|
||||
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
|
||||
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
|
||||
|
||||
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
|
||||
}
|
||||
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
|
||||
}
|
||||
|
||||
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
|
||||
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
|
||||
}
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
@@ -71,10 +69,6 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
#endif
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
#if XASH_AMD64
|
||||
#if XASH_FREEBSD
|
||||
pc = (void*)ucontext->uc_mcontext.mc_rip;
|
||||
@@ -122,8 +116,8 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
#endif
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
@@ -133,6 +127,10 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
@@ -208,25 +206,15 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
|
||||
#endif // !HAVE_EXECINFO
|
||||
|
||||
void Sys_SetupCrashHandler( const char *argv0 )
|
||||
void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
struct sigaction act = { 0 };
|
||||
#if HAVE_LIBBACKTRACE
|
||||
if( Sys_SetupLibbacktrace( argv0 ))
|
||||
{
|
||||
act.sa_sigaction = Sys_CrashLibbacktrace;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
act.sa_sigaction = Sys_Crash;
|
||||
}
|
||||
act.sa_sigaction = Sys_Crash;
|
||||
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
sigaction( SIGSEGV, &act, &oldFilter );
|
||||
sigaction( SIGABRT, &act, &oldFilter );
|
||||
sigaction( SIGBUS, &act, &oldFilter );
|
||||
sigaction( SIGILL, &act, &oldFilter );
|
||||
|
||||
}
|
||||
|
||||
void Sys_RestoreCrashHandler( void )
|
||||
|
||||
@@ -481,19 +481,19 @@ static void SDLash_EventHandler( SDL_Event *event )
|
||||
switch( event->window.event )
|
||||
{
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
{
|
||||
char val[32];
|
||||
if( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
char val[32];
|
||||
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data1 );
|
||||
Cvar_DirectSet( &window_xpos, val );
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data1 );
|
||||
Cvar_DirectSet( &window_xpos, val );
|
||||
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data2 );
|
||||
Cvar_DirectSet( &window_ypos, val );
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data2 );
|
||||
Cvar_DirectSet( &window_ypos, val );
|
||||
|
||||
if ( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||
Cvar_DirectSet( &vid_maximized, "0" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
host.status = HOST_SLEEP;
|
||||
Cvar_DirectSet( &vid_maximized, "0" );
|
||||
|
||||
@@ -33,12 +33,6 @@ static struct
|
||||
} cursors;
|
||||
#endif
|
||||
|
||||
static struct
|
||||
{
|
||||
int x, y;
|
||||
qboolean pushed;
|
||||
} in_visible_cursor_pos;
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_GetMousePos
|
||||
@@ -209,6 +203,11 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
{
|
||||
qboolean visible;
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( !cursors.initialized )
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case dc_user:
|
||||
@@ -221,7 +220,7 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
}
|
||||
|
||||
// never disable cursor in touch emulation mode
|
||||
if( !visible && Touch_WantVisibleCursor( ))
|
||||
if( !visible && Touch_Emulated( ))
|
||||
return;
|
||||
|
||||
host.mouse_visible = visible;
|
||||
@@ -230,28 +229,11 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( host.mouse_visible )
|
||||
{
|
||||
if( cursors.initialized )
|
||||
SDL_SetCursor( cursors.cursors[type] );
|
||||
|
||||
SDL_SetCursor( cursors.cursors[type] );
|
||||
SDL_ShowCursor( true );
|
||||
|
||||
// restore the last mouse position
|
||||
if( in_visible_cursor_pos.pushed )
|
||||
{
|
||||
SDL_WarpMouseInWindow( host.hWnd, in_visible_cursor_pos.x, in_visible_cursor_pos.y );
|
||||
in_visible_cursor_pos.pushed = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// save last mouse position and warp it to the center
|
||||
if( !in_visible_cursor_pos.pushed )
|
||||
{
|
||||
SDL_GetMouseState( &in_visible_cursor_pos.x, &in_visible_cursor_pos.y );
|
||||
SDL_WarpMouseInWindow( host.hWnd, host.window_center_x, host.window_center_y );
|
||||
in_visible_cursor_pos.pushed = true;
|
||||
}
|
||||
|
||||
SDL_ShowCursor( false );
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -171,18 +171,6 @@ static void SDLash_GameControllerAdded( int device_index )
|
||||
return;
|
||||
}
|
||||
|
||||
// this "game controller" only exists on Android within emulator and tries to map
|
||||
// keyboard events into game controller events, which as you can expect, doesn't
|
||||
// work and I don't understand the intention here. When debugging Xash in Android
|
||||
// Studio emulator, just enable hardware input passthrough.
|
||||
#if XASH_ANDROID
|
||||
if( !Q_strcmp( SDL_GameControllerName( gc ), "qwerty2" ))
|
||||
{
|
||||
SDL_GameControllerClose( gc );
|
||||
return;
|
||||
}
|
||||
#endif // XASH_ANDROID
|
||||
|
||||
list = Mem_Realloc( host.mempool, g_gamepads, sizeof( *list ) * ( g_num_gamepads + 1 ));
|
||||
list[g_num_gamepads++] = gc;
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ qboolean SNDDMA_Init( void )
|
||||
if( !samplecount )
|
||||
samplecount = 0x8000;
|
||||
dma.samples = samplecount * obtained.channels;
|
||||
dma.buffer = Mem_Calloc( sndpool, dma.samples * 2 );
|
||||
dma.buffer = Mem_Malloc( sndpool, dma.samples * 2 );
|
||||
dma.samplepos = 0;
|
||||
|
||||
sdl_format = obtained.format;
|
||||
|
||||
@@ -257,8 +257,7 @@ static void R_InitVideoModes( void )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
int displayIndex = SDL_GetPointDisplayIndex( &point );
|
||||
int displayIndex = 0; // TODO: handle multiple displays somehow
|
||||
int i, modes;
|
||||
|
||||
num_vidmodes = 0;
|
||||
@@ -736,24 +735,6 @@ static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int y
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean RectFitsInDisplay( const SDL_Rect *rect, const SDL_Rect *display )
|
||||
{
|
||||
return rect->x >= display->x
|
||||
&& rect->y >= display->y
|
||||
&& rect->x + rect->w <= display->x + display->w
|
||||
&& rect->y + rect->h <= display->y + display->h;
|
||||
}
|
||||
// Function to check if the rectangle fits in any display
|
||||
static qboolean RectFitsInAnyDisplay( const SDL_Rect *rect, const SDL_Rect *display_rects, int num_displays )
|
||||
{
|
||||
for( int i = 0; i < num_displays; i++ )
|
||||
{
|
||||
if( RectFitsInDisplay( rect, &display_rects[i] ))
|
||||
return true; // Rectangle fits in this display
|
||||
}
|
||||
return false; // Rectangle does not fit in any display
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VID_CreateWindow
|
||||
@@ -766,8 +747,6 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
qboolean maximized = vid_maximized.value != 0.0f;
|
||||
Uint32 wndFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_MOUSE_FOCUS;
|
||||
int xpos, ypos;
|
||||
int num_displays = SDL_GetNumVideoDisplays();
|
||||
SDL_Rect rect = { window_xpos.value, window_ypos.value, width, height };
|
||||
|
||||
Q_strncpy( wndname, GI->title, sizeof( wndname ));
|
||||
|
||||
@@ -778,43 +757,35 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
|
||||
if( window_mode == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
SDL_Rect *display_rects = ( SDL_Rect * )malloc( num_displays * sizeof( SDL_Rect ));
|
||||
|
||||
SDL_Rect r;
|
||||
|
||||
SetBits( wndFlags, SDL_WINDOW_RESIZABLE );
|
||||
if( maximized )
|
||||
SetBits( wndFlags, SDL_WINDOW_MAXIMIZED );
|
||||
|
||||
if( !display_rects )
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 5 )
|
||||
if( SDL_GetDisplayUsableBounds( 0, &r ) < 0 &&
|
||||
SDL_GetDisplayBounds( 0, &r ) < 0 )
|
||||
#else
|
||||
if( SDL_GetDisplayBounds( 0, &r ) < 0 )
|
||||
#endif
|
||||
{
|
||||
Con_Printf( S_ERROR "Failed to allocate memory for display rects!\n" );
|
||||
xpos = SDL_WINDOWPOS_UNDEFINED;
|
||||
ypos = SDL_WINDOWPOS_UNDEFINED;
|
||||
Con_Reportf( S_ERROR "%s: SDL_GetDisplayBounds failed: %s\n", __func__, SDL_GetError( ));
|
||||
xpos = SDL_WINDOWPOS_CENTERED;
|
||||
ypos = SDL_WINDOWPOS_CENTERED;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < num_displays; i++ )
|
||||
{
|
||||
if( SDL_GetDisplayBounds( i, &display_rects[i] ) != 0 )
|
||||
{
|
||||
Con_Printf( S_ERROR "Failed to get bounds for display %d! SDL_Error: %s\n", i, SDL_GetError());
|
||||
display_rects[i] = ( SDL_Rect ){ 0, 0, 0, 0 };
|
||||
}
|
||||
}
|
||||
// Check if the rectangle fits in any display
|
||||
if( !RectFitsInAnyDisplay( &rect, display_rects, num_displays ))
|
||||
{
|
||||
// Rectangle doesn't fit in any display, center it
|
||||
xpos = window_xpos.value;
|
||||
ypos = window_ypos.value;
|
||||
|
||||
// don't create window outside of usable display space
|
||||
if( xpos < r.x || xpos + width > r.x + r.w )
|
||||
xpos = SDL_WINDOWPOS_CENTERED;
|
||||
|
||||
if( ypos < r.y || ypos + height > r.y + r.h )
|
||||
ypos = SDL_WINDOWPOS_CENTERED;
|
||||
Con_Printf( S_ERROR "Rectangle does not fit in any display. Centering window.\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = rect.x;
|
||||
ypos = rect.y;
|
||||
}
|
||||
}
|
||||
free( display_rects );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -824,16 +795,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
else
|
||||
SetBits( wndFlags, SDL_WINDOW_FULLSCREEN_DESKTOP );
|
||||
SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
|
||||
if ( window_xpos.value < 0 || window_ypos.value < 0 )
|
||||
{
|
||||
xpos = SDL_WINDOWPOS_UNDEFINED;
|
||||
ypos = SDL_WINDOWPOS_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = window_xpos.value;
|
||||
ypos = window_ypos.value;
|
||||
}
|
||||
xpos = ypos = 0;
|
||||
}
|
||||
|
||||
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
|
||||
@@ -1056,8 +1018,7 @@ qboolean R_Init_Video( const int type )
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_DisplayMode displayMode;
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
SDL_GetCurrentDisplayMode( SDL_GetPointDisplayIndex( &point ), &displayMode );
|
||||
SDL_GetCurrentDisplayMode( 0, &displayMode );
|
||||
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
|
||||
#else
|
||||
refState.desktopBitsPixel = 16;
|
||||
|
||||
@@ -49,6 +49,10 @@ typedef struct
|
||||
qboolean inputEnabled;
|
||||
qboolean consoleVisible;
|
||||
qboolean attached;
|
||||
|
||||
// log stuff
|
||||
qboolean log_active;
|
||||
char log_path[MAX_SYSPATH];
|
||||
} WinConData;
|
||||
|
||||
static WinConData s_wcd;
|
||||
@@ -498,13 +502,19 @@ create win32 console
|
||||
*/
|
||||
void Wcon_CreateConsole( qboolean con_showalways )
|
||||
{
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
s_wcd.log_active = true;
|
||||
|
||||
if( host.type == HOST_NORMAL )
|
||||
{
|
||||
Q_strncpy( s_wcd.title, XASH_ENGINE_NAME " " XASH_VERSION, sizeof( s_wcd.title ));
|
||||
Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path ));
|
||||
}
|
||||
else // dedicated console
|
||||
{
|
||||
Q_strncpy( s_wcd.title, XASH_DEDICATED_SERVER_NAME " " XASH_VERSION, sizeof( s_wcd.title ));
|
||||
Q_strncpy( s_wcd.log_path, "dedicated.log", sizeof( s_wcd.log_path ));
|
||||
s_wcd.log_active = true; // always make log
|
||||
}
|
||||
|
||||
s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 );
|
||||
@@ -586,8 +596,10 @@ void Wcon_DestroyConsole( void )
|
||||
// last text message into console or log
|
||||
Con_Reportf( "%s: Unloading xash.dll\n", __func__ );
|
||||
|
||||
Sys_CloseLog( NULL );
|
||||
|
||||
if( !s_wcd.attached )
|
||||
{
|
||||
{
|
||||
if( s_wcd.hWnd )
|
||||
{
|
||||
ShowWindow( s_wcd.hWnd, SW_HIDE );
|
||||
|
||||
@@ -318,7 +318,7 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
void Sys_SetupCrashHandler( const char *argv0 )
|
||||
void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
|
||||
oldFilter = SetUnhandledExceptionFilter( Sys_Crash );
|
||||
|
||||
@@ -18,8 +18,6 @@ GNU General Public License for more details.
|
||||
#include "server.h"
|
||||
#include <shellapi.h>
|
||||
|
||||
HANDLE g_waitable_timer;
|
||||
|
||||
#if XASH_TIMER == TIMER_WIN32
|
||||
double Platform_DoubleTime( void )
|
||||
{
|
||||
@@ -38,67 +36,6 @@ double Platform_DoubleTime( void )
|
||||
}
|
||||
#endif // XASH_TIMER == TIMER_WIN32
|
||||
|
||||
void Win32_Init( qboolean con_showalways )
|
||||
{
|
||||
HMODULE hModule = LoadLibrary( "kernel32.dll" );
|
||||
if( hModule )
|
||||
{
|
||||
HANDLE ( __stdcall *pfnCreateWaitableTimerExW)( LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess );
|
||||
|
||||
if(( pfnCreateWaitableTimerExW = (void *)GetProcAddress( hModule, "CreateWaitableTimerExW" )))
|
||||
{
|
||||
g_waitable_timer = pfnCreateWaitableTimerExW(
|
||||
NULL,
|
||||
NULL,
|
||||
0x1 /* CREATE_WAITABLE_TIMER_MANUAL_RESET */ | 0x2 /* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION */,
|
||||
0x0002 /* TIMER_MODIFY_STATE */ | SYNCHRONIZE | DELETE
|
||||
);
|
||||
}
|
||||
|
||||
FreeLibrary( hModule );
|
||||
}
|
||||
|
||||
#if 0 // FIXME: creates object but doesn't wait for specific time for me on Windows 10, with the code above commented
|
||||
if( !g_waitable_timer )
|
||||
g_waitable_timer = CreateWaitableTimer( NULL, TRUE, NULL );
|
||||
#endif
|
||||
|
||||
Wcon_CreateConsole( con_showalways );
|
||||
}
|
||||
|
||||
void Win32_Shutdown( void )
|
||||
{
|
||||
Wcon_DestroyConsole( );
|
||||
|
||||
if( g_waitable_timer )
|
||||
{
|
||||
CloseHandle( g_waitable_timer );
|
||||
g_waitable_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean Win32_NanoSleep( int nsec )
|
||||
{
|
||||
LARGE_INTEGER ts;
|
||||
|
||||
if( !g_waitable_timer )
|
||||
return false;
|
||||
|
||||
ts.QuadPart = -nsec / 100;
|
||||
|
||||
if( !SetWaitableTimer( g_waitable_timer, &ts, 0, NULL, NULL, FALSE ))
|
||||
{
|
||||
CloseHandle( g_waitable_timer );
|
||||
g_waitable_timer = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( WaitForSingleObject( g_waitable_timer, Q_max( 1, nsec / 1000000 )) != WAIT_OBJECT_0 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Platform_DebuggerPresent( void )
|
||||
{
|
||||
return IsDebuggerPresent();
|
||||
|
||||
@@ -348,7 +348,7 @@ typedef struct ref_api_s
|
||||
void (*Con_NXPrintf)( struct con_nprint_s *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
|
||||
void (*CL_CenterPrint)( const char *s, float y );
|
||||
void (*Con_DrawStringLen)( const char *pText, int *length, int *height );
|
||||
int (*Con_DrawString)( int x, int y, const char *string, const rgba_t setColor );
|
||||
int (*Con_DrawString)( int x, int y, const char *string, rgba_t setColor );
|
||||
void (*CL_DrawCenterPrint)( void );
|
||||
|
||||
// entity management
|
||||
|
||||
@@ -279,6 +279,19 @@ typedef struct sv_client_s
|
||||
a program error, like an overflowed reliable buffer
|
||||
=============================================================================
|
||||
*/
|
||||
// MAX_CHALLENGES is made large to prevent a denial
|
||||
// of service attack that could cycle all of them
|
||||
// out before legitimate users connected
|
||||
#define MAX_CHALLENGES 1024
|
||||
|
||||
typedef struct
|
||||
{
|
||||
netadr_t adr;
|
||||
double time;
|
||||
int challenge;
|
||||
qboolean connected;
|
||||
} challenge_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[32]; // in GoldSrc max name length is 12
|
||||
@@ -372,7 +385,7 @@ typedef struct
|
||||
entity_state_t *baselines; // [GI->max_edicts]
|
||||
entity_state_t *static_entities; // [MAX_STATIC_ENTITIES];
|
||||
|
||||
uint32_t challenge_salt[16]; // pregenerated random numbers for generating challenged based on IP's MD5 address
|
||||
challenge_t challenges[MAX_CHALLENGES]; // to prevent invalid IPs from connecting
|
||||
|
||||
sizebuf_t testpacket; // pregenerataed testpacket, only needs CRC32 patching
|
||||
byte *testpacket_buf; // check for NULL if testpacket is available
|
||||
|
||||
@@ -86,54 +86,38 @@ flood the server with invalid connection IPs. With a
|
||||
challenge, they must give a valid IP address.
|
||||
=================
|
||||
*/
|
||||
static int SV_GetChallenge( netadr_t from, qboolean *error )
|
||||
static void SV_GetChallenge( netadr_t from )
|
||||
{
|
||||
const netadrtype_t type = NET_NetadrType( &from );
|
||||
MD5Context_t ctx;
|
||||
byte digest[16];
|
||||
int i, oldest = 0;
|
||||
double oldestTime;
|
||||
|
||||
*error = false;
|
||||
oldestTime = 0x7fffffff;
|
||||
|
||||
MD5Init( &ctx );
|
||||
|
||||
switch( type )
|
||||
// see if we already have a challenge for this ip
|
||||
for( i = 0; i < MAX_CHALLENGES; i++ )
|
||||
{
|
||||
case NA_IP:
|
||||
MD5Update( &ctx, from.ip, sizeof( from.ip ));
|
||||
break;
|
||||
case NA_IPX:
|
||||
MD5Update( &ctx, from.ipx, sizeof( from.ipx ));
|
||||
break;
|
||||
case NA_IP6:
|
||||
{
|
||||
byte ip6[16];
|
||||
NET_NetadrToIP6Bytes( ip6, &from );
|
||||
MD5Update( &ctx, ip6, sizeof( ip6 ));
|
||||
break;
|
||||
}
|
||||
case NA_LOOPBACK:
|
||||
return 0;
|
||||
default:
|
||||
*error = true;
|
||||
return 0;
|
||||
if( !svs.challenges[i].connected && NET_CompareAdr( from, svs.challenges[i].adr ))
|
||||
break;
|
||||
|
||||
if( svs.challenges[i].time < oldestTime )
|
||||
{
|
||||
oldestTime = svs.challenges[i].time;
|
||||
oldest = i;
|
||||
}
|
||||
}
|
||||
|
||||
MD5Update( &ctx, (byte *)svs.challenge_salt, sizeof( svs.challenge_salt ));
|
||||
MD5Final( digest, &ctx );
|
||||
|
||||
return digest[0] | digest[1] << 8 | digest[2] << 16 | digest[3] << 24;
|
||||
}
|
||||
|
||||
static void SV_SendChallenge( netadr_t from )
|
||||
{
|
||||
qboolean error = false;
|
||||
int challenge = SV_GetChallenge( from, &error );
|
||||
|
||||
if( error )
|
||||
return;
|
||||
if( i == MAX_CHALLENGES )
|
||||
{
|
||||
// this is the first time this client has asked for a challenge
|
||||
svs.challenges[oldest].challenge = (COM_RandomLong( 0, 0x7FFF ) << 16) | COM_RandomLong( 0, 0xFFFF );
|
||||
svs.challenges[oldest].adr = from;
|
||||
svs.challenges[oldest].time = host.realtime;
|
||||
svs.challenges[oldest].connected = false;
|
||||
i = oldest;
|
||||
}
|
||||
|
||||
// send it back
|
||||
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_CHALLENGE" %i", challenge );
|
||||
Netchan_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, S2C_CHALLENGE" %i", svs.challenges[i].challenge );
|
||||
}
|
||||
|
||||
static int SV_GetFragmentSize( void *pcl, fragsize_t mode )
|
||||
@@ -227,16 +211,35 @@ Make sure connecting client is not spoofing
|
||||
*/
|
||||
static int SV_CheckChallenge( netadr_t from, int challenge )
|
||||
{
|
||||
qboolean error = false;
|
||||
int challenge2 = SV_GetChallenge( from, &error );
|
||||
int i;
|
||||
|
||||
if( error || challenge2 != challenge )
|
||||
// see if the challenge is valid
|
||||
// don't care if it is a local address.
|
||||
if( NET_IsLocalAddress( from ))
|
||||
return 1;
|
||||
|
||||
for( i = 0; i < MAX_CHALLENGES; i++ )
|
||||
{
|
||||
SV_RejectConnection( from, "no challenge for your address\n" );
|
||||
return false;
|
||||
if( NET_CompareAdr( from, svs.challenges[i].adr ))
|
||||
{
|
||||
if( challenge == svs.challenges[i].challenge )
|
||||
break; // valid challenge
|
||||
#if 0
|
||||
// g-cont. this breaks multiple connections from single machine
|
||||
SV_RejectConnection( from, "bad challenge %i\n", challenge );
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if( i == MAX_CHALLENGES )
|
||||
{
|
||||
SV_RejectConnection( from, "no challenge for your address\n" );
|
||||
return 0;
|
||||
}
|
||||
svs.challenges[i].connected = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -250,7 +253,7 @@ static int SV_CheckIPRestrictions( netadr_t from )
|
||||
{
|
||||
if( sv_lan.value )
|
||||
{
|
||||
if( !NET_IsReservedAdr( from ))
|
||||
if( !NET_CompareClassBAdr( from, net_local ) && !NET_IsReservedAdr( from ))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -264,17 +267,23 @@ Get slot # and set client_t pointer for player, if possible
|
||||
We don't do this search on a "reconnect, we just reuse the slot
|
||||
================
|
||||
*/
|
||||
static sv_client_t *SV_FindEmptySlot( void )
|
||||
static int SV_FindEmptySlot( netadr_t from, int *pslot, sv_client_t **ppClient )
|
||||
{
|
||||
int i;
|
||||
sv_client_t *cl;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
|
||||
{
|
||||
if( svs.clients[i].state == cs_free )
|
||||
return &svs.clients[i];
|
||||
if( cl->state == cs_free )
|
||||
{
|
||||
*ppClient = cl;
|
||||
*pslot = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
SV_RejectConnection( from, "server is full\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -286,13 +295,15 @@ A connection request that did not come from the master
|
||||
*/
|
||||
static void SV_ConnectClient( netadr_t from )
|
||||
{
|
||||
char userinfo[MAX_INFO_STRING];
|
||||
char protinfo[MAX_INFO_STRING];
|
||||
sv_client_t *newcl = NULL;
|
||||
int qport, version;
|
||||
int i, count = 0;
|
||||
int challenge;
|
||||
const char *s;
|
||||
char userinfo[MAX_INFO_STRING];
|
||||
char protinfo[MAX_INFO_STRING];
|
||||
sv_client_t *cl, *newcl = NULL;
|
||||
qboolean reconnect = false;
|
||||
int nClientSlot = 0;
|
||||
int qport, version;
|
||||
int i, count = 0;
|
||||
int challenge;
|
||||
const char *s;
|
||||
int extensions;
|
||||
uint netchan_flags = 0;
|
||||
|
||||
@@ -310,6 +321,39 @@ static void SV_ConnectClient( netadr_t from )
|
||||
return;
|
||||
}
|
||||
|
||||
challenge = Q_atoi( Cmd_Argv( 2 )); // get challenge
|
||||
|
||||
// see if the challenge is valid (local clients don't need to challenge)
|
||||
if( !SV_CheckChallenge( from, challenge ))
|
||||
return;
|
||||
|
||||
s = Cmd_Argv( 3 ); // protocol info
|
||||
|
||||
if( !Info_IsValid( s ))
|
||||
{
|
||||
SV_RejectConnection( from, "invalid protinfo in connect command\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( protinfo, s, sizeof( protinfo ));
|
||||
|
||||
if( !SV_ProcessUserAgent( from, protinfo ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// extract qport from protocol info
|
||||
qport = Q_atoi( Info_ValueForKey( protinfo, "qport" ));
|
||||
|
||||
s = Info_ValueForKey( protinfo, "uuid" );
|
||||
if( Q_strlen( s ) != 32 )
|
||||
{
|
||||
SV_RejectConnection( from, "invalid authentication certificate length\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
extensions = Q_atoi( Info_ValueForKey( protinfo, "ext" ) );
|
||||
|
||||
// LAN servers restrict to class b IP addresses
|
||||
if( !SV_CheckIPRestrictions( from ))
|
||||
{
|
||||
@@ -317,37 +361,9 @@ static void SV_ConnectClient( netadr_t from )
|
||||
return;
|
||||
}
|
||||
|
||||
challenge = Q_atoi( Cmd_Argv( 2 )); // get challenge
|
||||
|
||||
// see if the challenge is valid (local clients don't need to challenge)
|
||||
if( !SV_CheckChallenge( from, challenge ))
|
||||
return;
|
||||
|
||||
s = Cmd_Argv( 3 );
|
||||
if( Q_strlen( s ) > sizeof( protinfo ) || !Info_IsValid( s ))
|
||||
{
|
||||
SV_RejectConnection( from, "invalid protinfo in connect command\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( protinfo, s, sizeof( protinfo )); // protocol info
|
||||
|
||||
if( !SV_ProcessUserAgent( from, protinfo ))
|
||||
return;
|
||||
|
||||
if( Q_strlen( Info_ValueForKey( protinfo, "uuid" )) != 32 )
|
||||
{
|
||||
SV_RejectConnection( from, "invalid authentication certificate length\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// extract qport from protocol info
|
||||
qport = Q_atoi( Info_ValueForKey( protinfo, "qport" ));
|
||||
extensions = Q_atoi( Info_ValueForKey( protinfo, "ext" ));
|
||||
|
||||
s = Cmd_Argv( 4 ); // user info
|
||||
|
||||
if( Q_strlen( s ) > sizeof( userinfo ) || !Info_IsValid( s ))
|
||||
if( Q_strlen( s ) > MAX_INFO_STRING || !Info_IsValid( s ))
|
||||
{
|
||||
SV_RejectConnection( from, "invalid userinfo in connect command\n" );
|
||||
return;
|
||||
@@ -366,43 +382,43 @@ static void SV_ConnectClient( netadr_t from )
|
||||
}
|
||||
|
||||
// if there is already a slot for this ip, reuse it
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
|
||||
{
|
||||
sv_client_t *cl = &svs.clients[i];
|
||||
|
||||
if( cl->state == cs_free || cl->state == cs_zombie )
|
||||
continue;
|
||||
|
||||
if( NET_CompareBaseAdr( from, cl->netchan.remote_address ) && ( cl->netchan.qport == qport || from.port == cl->netchan.remote_address.port ))
|
||||
{
|
||||
reconnect = true;
|
||||
newcl = cl;
|
||||
Con_Reportf( S_NOTE "%s:reconnect\n", NET_AdrToString( from ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// A reconnecting client will re-use the slot found above when checking for reconnection.
|
||||
// the slot will be wiped clean.
|
||||
if( !newcl )
|
||||
if( !reconnect )
|
||||
{
|
||||
// connect the client if there are empty slots.
|
||||
newcl = SV_FindEmptySlot();
|
||||
|
||||
if( !newcl )
|
||||
{
|
||||
SV_RejectConnection( from, "server is full\n" );
|
||||
if( !SV_FindEmptySlot( from, &nClientSlot, &newcl ))
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Reportf( S_NOTE "%s:reconnect\n", NET_AdrToString( from ));
|
||||
}
|
||||
|
||||
// find a client slot
|
||||
ASSERT( newcl != NULL );
|
||||
|
||||
// build a new connection
|
||||
// accept the new client
|
||||
|
||||
sv.current_client = newcl;
|
||||
newcl->edict = EDICT_NUM(( newcl - svs.clients ) + 1 );
|
||||
newcl->edict = EDICT_NUM( (newcl - svs.clients) + 1 );
|
||||
newcl->challenge = challenge; // save challenge for checksumming
|
||||
newcl->frames = (client_frame_t *)Mem_Realloc( host.mempool, newcl->frames, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
|
||||
memset( newcl->frames, 0, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
|
||||
if( newcl->frames ) Mem_Free( newcl->frames );
|
||||
newcl->frames = (client_frame_t *)Z_Calloc( sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
|
||||
newcl->userid = g_userid++; // create unique userid
|
||||
newcl->state = cs_connected;
|
||||
newcl->extensions = extensions & (NET_EXT_SPLITSIZE);
|
||||
@@ -466,11 +482,8 @@ static void SV_ConnectClient( netadr_t from )
|
||||
|
||||
// if this was the first client on the server, or the last client
|
||||
// the server can hold, send a heartbeat to the master.
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
{
|
||||
if( svs.clients[i].state >= cs_connected )
|
||||
count++;
|
||||
}
|
||||
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
|
||||
if( cl->state >= cs_connected ) count++;
|
||||
|
||||
Log_Printf( "\"%s<%i><%i><>\" connected, address \"%s\"\n", newcl->name, newcl->userid, i, NET_AdrToString( newcl->netchan.remote_address ));
|
||||
|
||||
@@ -841,7 +854,7 @@ static void SV_TestBandWidth( netadr_t from )
|
||||
( packetsize > FRAGMENT_MAX_SIZE ))
|
||||
{
|
||||
// skip the test and just get challenge
|
||||
SV_SendChallenge( from );
|
||||
SV_GetChallenge( from );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -849,7 +862,7 @@ static void SV_TestBandWidth( netadr_t from )
|
||||
ofs = packetsize - svs.testpacket_filepos - 1;
|
||||
if(( ofs < 0 ) || ( ofs > svs.testpacket_filelen ))
|
||||
{
|
||||
SV_SendChallenge( from );
|
||||
SV_GetChallenge( from );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1772,7 +1785,7 @@ static qboolean SV_ShouldUpdateUserinfo( sv_client_t *cl )
|
||||
if( host.realtime < cl->userinfo_next_changetime + cl->userinfo_penalty * sv_userinfo_penalty_multiplier.value )
|
||||
{
|
||||
// player changes userinfo too quick! ignore!
|
||||
if( host.realtime < cl->userinfo_next_changetime && cl->userinfo_change_attempts > 0 )
|
||||
if( host.realtime < cl->userinfo_next_changetime )
|
||||
{
|
||||
Con_Reportf( "%s: ignore userinfo update for %s: penalty %f, attempts %i\n",
|
||||
__func__, cl->name, cl->userinfo_penalty, cl->userinfo_change_attempts );
|
||||
@@ -1783,15 +1796,15 @@ static qboolean SV_ShouldUpdateUserinfo( sv_client_t *cl )
|
||||
}
|
||||
|
||||
// they spammed too fast, increase penalty
|
||||
if( cl->userinfo_change_attempts >= (int)sv_userinfo_penalty_attempts.value )
|
||||
if( cl->userinfo_change_attempts > sv_userinfo_penalty_attempts.value )
|
||||
{
|
||||
Con_Reportf( "%s: penalty set %f for %s\n", __func__,
|
||||
cl->userinfo_penalty, cl->name );
|
||||
cl->userinfo_penalty *= sv_userinfo_penalty_multiplier.value;
|
||||
cl->userinfo_change_attempts = 0;
|
||||
|
||||
Con_Reportf( "%s: penalty set %f for %s\n", __func__, cl->userinfo_penalty, cl->name );
|
||||
}
|
||||
|
||||
cl->userinfo_next_changetime = host.realtime + cl->userinfo_penalty * sv_userinfo_penalty_multiplier.value;
|
||||
cl->userinfo_next_changetime = host.realtime + cl->userinfo_penalty;
|
||||
|
||||
return allow;
|
||||
}
|
||||
@@ -1895,10 +1908,13 @@ static void SV_UserinfoChanged( sv_client_t *cl )
|
||||
|
||||
val = Info_ValueForKey( cl->userinfo, "cl_updaterate" );
|
||||
|
||||
if( COM_CheckString( val ))
|
||||
if( COM_CheckString( val ) )
|
||||
{
|
||||
float rate = Q_atoi( val );
|
||||
cl->cl_updaterate = 1.0 / bound( sv_minupdaterate.value, rate, sv_maxupdaterate.value );
|
||||
if( Q_atoi( val ) != 0 )
|
||||
{
|
||||
cl->cl_updaterate = 1.0 / bound( sv_minupdaterate.value, Q_atoi( val ), sv_maxupdaterate.value );
|
||||
}
|
||||
else cl->cl_updaterate = 0.0;
|
||||
}
|
||||
|
||||
// call prog code to allow overrides
|
||||
@@ -3163,7 +3179,7 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
}
|
||||
else if( !Q_strcmp( pcmd, C2S_GETCHALLENGE ))
|
||||
{
|
||||
SV_SendChallenge( from );
|
||||
SV_GetChallenge( from );
|
||||
}
|
||||
else if( !Q_strcmp( pcmd, C2S_CONNECT ))
|
||||
{
|
||||
|
||||
@@ -573,7 +573,7 @@ static void SV_Kick_f( void )
|
||||
sv_client_t *cl;
|
||||
const char *param;
|
||||
|
||||
if( Cmd_Argc() < 2 )
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "kick <#id|name> [reason]\n" );
|
||||
return;
|
||||
|
||||
@@ -302,7 +302,7 @@ static int SV_FilterToString( char *dest, size_t size, qboolean config, ipfilter
|
||||
|
||||
static qboolean SV_IPFilterIncludesIPFilter( ipfilter_t *a, ipfilter_t *b )
|
||||
{
|
||||
if( NET_NetadrType( &a->adr ) != NET_NetadrType( &b->adr ))
|
||||
if( a->adr.type6 != b->adr.type6 )
|
||||
return false;
|
||||
|
||||
// can't include bigger subnet in small
|
||||
@@ -359,7 +359,7 @@ qboolean SV_CheckIP( netadr_t *adr )
|
||||
if( entry->endTime && host.realtime > entry->endTime )
|
||||
continue; // expired
|
||||
|
||||
switch( NET_NetadrType( &entry->adr ))
|
||||
switch( entry->adr.type6 )
|
||||
{
|
||||
case NA_IP:
|
||||
case NA_IP6:
|
||||
|
||||
@@ -2379,7 +2379,7 @@ void GAME_EXPORT pfnClientCommand( edict_t* pEdict, char* szFmt, ... )
|
||||
if( sv.state != ss_active )
|
||||
return; // early out
|
||||
|
||||
if(( cl = SV_ClientFromEdict( pEdict, false )) == NULL )
|
||||
if(( cl = SV_ClientFromEdict( pEdict, true )) == NULL )
|
||||
{
|
||||
Con_Printf( S_ERROR "stuffcmd: client is not spawned!\n" );
|
||||
return;
|
||||
@@ -4600,7 +4600,7 @@ static void GAME_EXPORT pfnQueryClientCvarValue( const edict_t *player, const ch
|
||||
if( !COM_CheckString( cvarName ))
|
||||
return;
|
||||
|
||||
if(( cl = SV_ClientFromEdict( player, false )) != NULL )
|
||||
if(( cl = SV_ClientFromEdict( player, true )) != NULL )
|
||||
{
|
||||
MSG_BeginServerCmd( &cl->netchan.message, svc_querycvarvalue );
|
||||
MSG_WriteString( &cl->netchan.message, cvarName );
|
||||
@@ -4627,7 +4627,7 @@ static void GAME_EXPORT pfnQueryClientCvarValue2( const edict_t *player, const c
|
||||
if( !COM_CheckString( cvarName ))
|
||||
return;
|
||||
|
||||
if(( cl = SV_ClientFromEdict( player, false )) != NULL )
|
||||
if(( cl = SV_ClientFromEdict( player, true )) != NULL )
|
||||
{
|
||||
MSG_BeginServerCmd( &cl->netchan.message, svc_querycvarvalue2 );
|
||||
MSG_WriteLong( &cl->netchan.message, requestID );
|
||||
|
||||
@@ -1027,9 +1027,6 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
|
||||
svs.timestart = Sys_DoubleTime();
|
||||
svs.spawncount++; // any partially connected client will be restarted
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( svs.challenge_salt ); i++ )
|
||||
svs.challenge_salt[i] = COM_RandomLong( 0, 0x7FFFFFFE );
|
||||
|
||||
cycle = Cvar_VariableString( "mapchangecfgfile" );
|
||||
|
||||
if( COM_CheckString( cycle ))
|
||||
|
||||
@@ -106,7 +106,7 @@ CVAR_DEFINE_AUTO( sv_skyvec_y, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skylight dir
|
||||
CVAR_DEFINE_AUTO( sv_skyvec_z, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skylight direction by z-axis" );
|
||||
CVAR_DEFINE_AUTO( sv_wateralpha, "1", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "world surfaces water transparency factor. 1.0 - solid, 0.0 - fully transparent" );
|
||||
CVAR_DEFINE_AUTO( sv_background_freeze, "1", FCVAR_ARCHIVE, "freeze player movement on background maps (e.g. to prevent falling)" );
|
||||
static CVAR_DEFINE_AUTO( showtriggers, "0", FCVAR_LATCH|FCVAR_TEMPORARY, "debug cvar shows triggers" );
|
||||
static CVAR_DEFINE_AUTO( showtriggers, "0", FCVAR_LATCH, "debug cvar shows triggers" );
|
||||
static CVAR_DEFINE_AUTO( sv_airmove, "1", FCVAR_SERVER, "obsolete, compatibility issues" );
|
||||
static CVAR_DEFINE_AUTO( sv_version, "", FCVAR_READ_ONLY, "engine version string" );
|
||||
CVAR_DEFINE_AUTO( hostname, "", FCVAR_PRINTABLEONLY, "name of current host" );
|
||||
@@ -189,15 +189,24 @@ void SV_UpdateMovevars( qboolean initialize )
|
||||
if( !initialize && !host.movevars_changed )
|
||||
return;
|
||||
|
||||
// NOTE: Natural Selection mod on ns_machina map that uses model as sky
|
||||
// it sets the value to 4000000 that even exceeds the coord limit, but
|
||||
// it's fine until the value fits in "zmax" delta field
|
||||
// However, some stupid mappers set an insane value like 999999999 which
|
||||
// overflows delta. In this case, just clamp it to something bigger
|
||||
if( sv_zmax.value < 256.0f )
|
||||
Cvar_DirectSet( &sv_zmax, "256" );
|
||||
else if( sv_zmax.value > 16777216.0f ) // 2^24
|
||||
Cvar_DirectSet( &sv_zmax, "16777216" );
|
||||
// NOTE: this breaks Natural Selection mod on ns_machina map that uses model as sky
|
||||
// it sets the value to 4000000 that even exceeds the coord limit
|
||||
#if 0
|
||||
// check range
|
||||
if( sv_zmax.value < 256.0f ) Cvar_SetValue( "sv_zmax", 256.0f );
|
||||
|
||||
// clamp it right
|
||||
if( FBitSet( host.features, ENGINE_WRITE_LARGE_COORD ))
|
||||
{
|
||||
if( sv_zmax.value > 131070.0f )
|
||||
Cvar_SetValue( "sv_zmax", 131070.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( sv_zmax.value > 32767.0f )
|
||||
Cvar_SetValue( "sv_zmax", 32767.0f );
|
||||
}
|
||||
#endif
|
||||
|
||||
svgame.movevars.gravity = sv_gravity.value;
|
||||
svgame.movevars.stopspeed = sv_stopspeed.value;
|
||||
|
||||
@@ -948,6 +948,12 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
|
||||
clent->v.light_level = ucmd->lightlevel;
|
||||
if( ucmd->impulse ) clent->v.impulse = ucmd->impulse;
|
||||
|
||||
if( ucmd->impulse == 204 )
|
||||
{
|
||||
// force client.dll update
|
||||
SV_RefreshUserinfo();
|
||||
}
|
||||
|
||||
svgame.globals->time = cl->timebase;
|
||||
svgame.dllFuncs.pfnPlayerPreThink( clent );
|
||||
SV_PlayerRunThink( clent, frametime, cl->timebase );
|
||||
|
||||
@@ -601,7 +601,7 @@ static void SV_FindTouchedLeafs( edict_t *ent, model_t *mod, mnode_t *node, int
|
||||
// add an efrag if the node is a leaf
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
if( ent->num_leafs >= MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )))
|
||||
if( ent->num_leafs > MAX_ENT_LEAFS( FBitSet( mod->flags, MODEL_QBSP2 )))
|
||||
{
|
||||
// continue counting leafs,
|
||||
// so we know how many it's overrun
|
||||
|
||||
@@ -136,7 +136,7 @@ def build(bld):
|
||||
# public includes for renderers and utils use
|
||||
bld(name = 'engine_includes', export_includes = '. common common/imagelib', use = 'filesystem_includes')
|
||||
|
||||
libs = ['engine_includes', 'public', 'dllemu', 'werror', 'backtrace']
|
||||
libs = ['engine_includes', 'public', 'dllemu', 'werror']
|
||||
includes = ['server', 'client', 'client/vgui', 'common/soundlib']
|
||||
|
||||
# basic build: dedicated only
|
||||
|
||||
@@ -59,9 +59,8 @@ char fs_rootdir[MAX_SYSPATH];
|
||||
searchpath_t *fs_writepath;
|
||||
|
||||
static searchpath_t *fs_searchpaths = NULL; // chain
|
||||
static char fs_basedir[MAX_SYSPATH]; // base game directory
|
||||
static char fs_gamedir[MAX_SYSPATH]; // game current directory
|
||||
static string fs_language;
|
||||
static char fs_basedir[MAX_SYSPATH]; // base game directory
|
||||
static char fs_gamedir[MAX_SYSPATH]; // game current directory
|
||||
|
||||
// add archives in specific order PAK -> PK3 -> WAD
|
||||
// so raw WADs takes precedence over WADs included into PAKs and PK3s
|
||||
@@ -1250,39 +1249,14 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
|
||||
if( isGameDir )
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_DOWNLOADED_DIRECTORY, dir );
|
||||
FS_AddGameDirectory( buf, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
}
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/", dir );
|
||||
FS_AddGameDirectory( buf, flags );
|
||||
|
||||
if( FBitSet( flags, FS_MOUNT_HD ))
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s_hd/", dir );
|
||||
FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FS_MOUNT_ADDON ))
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s_addon/", dir );
|
||||
FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FS_MOUNT_LV ))
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s_lv/", dir );
|
||||
FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FS_MOUNT_L10N ) && COM_CheckStringEmpty( fs_language ) && Q_isalpha( fs_language ))
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s_%s/", dir, fs_language );
|
||||
FS_AddGameDirectory( buf, flags|FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
}
|
||||
|
||||
if( isGameDir )
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "%s/" DEFAULT_CUSTOM_DIRECTORY, dir );
|
||||
FS_AddGameDirectory( buf, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
FS_AddGameDirectory( buf, FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1291,35 +1265,29 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
|
||||
FS_Rescan
|
||||
================
|
||||
*/
|
||||
void FS_Rescan( uint32_t flags, const char *language )
|
||||
void FS_Rescan( void )
|
||||
{
|
||||
const char *str;
|
||||
const int extrasFlags = FS_NOWRITE_PATH | FS_CUSTOM_PATH;
|
||||
Con_Reportf( "%s( %s )\n", __func__, GI->title );
|
||||
|
||||
FS_ClearSearchPath();
|
||||
|
||||
flags &= FS_MOUNT_HD|FS_MOUNT_LV|FS_MOUNT_ADDON|FS_MOUNT_L10N;
|
||||
|
||||
if( FBitSet( flags, FS_MOUNT_L10N ))
|
||||
Q_strncpy( fs_language, language, sizeof( fs_language ));
|
||||
else
|
||||
fs_language[0] = 0;
|
||||
|
||||
str = getenv( "XASH3D_EXTRAS_PAK1" );
|
||||
if( COM_CheckString( str ))
|
||||
FS_MountArchive_Fullpath( str, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
FS_MountArchive_Fullpath( str, extrasFlags );
|
||||
|
||||
str = getenv( "XASH3D_EXTRAS_PAK2" );
|
||||
if( COM_CheckString( str ))
|
||||
FS_MountArchive_Fullpath( str, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
FS_MountArchive_Fullpath( str, extrasFlags );
|
||||
|
||||
if( Q_stricmp( GI->basedir, GI->gamefolder ))
|
||||
FS_AddGameHierarchy( GI->basedir, flags );
|
||||
FS_AddGameHierarchy( GI->basedir, 0 );
|
||||
if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamefolder, GI->falldir ))
|
||||
FS_AddGameHierarchy( GI->falldir, flags );
|
||||
FS_AddGameHierarchy( GI->falldir, 0 );
|
||||
|
||||
GI->added = true;
|
||||
FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH | flags );
|
||||
FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1364,7 +1332,7 @@ void FS_LoadGameInfo( const char *rootfolder )
|
||||
FS_CreatePath( buf );
|
||||
}
|
||||
|
||||
FS_Rescan( 0, NULL ); // create new filesystem
|
||||
FS_Rescan(); // create new filesystem
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1607,7 +1575,6 @@ qboolean FS_InitStdio( qboolean unused_set_to_true, const char *rootdir, const c
|
||||
Q_strncpy( fs_gamedir, gamedir, sizeof( fs_gamedir ));
|
||||
Q_strncpy( fs_basedir, basedir, sizeof( fs_basedir ));
|
||||
Q_strncpy( fs_rodir, rodir, sizeof( fs_rodir ));
|
||||
fs_language[0] = 0;
|
||||
|
||||
// validate user input
|
||||
if( COM_CheckStringEmpty( fs_rodir ) && !Q_stricmp( fs_rodir, fs_rootdir ))
|
||||
@@ -1729,17 +1696,12 @@ FS_Shutdown
|
||||
void FS_ShutdownStdio( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
// release gamedirs
|
||||
for( i = 0; i < FI.numgames; i++ )
|
||||
{
|
||||
if( FI.games[i] )
|
||||
{
|
||||
Mem_Free( FI.games[i] );
|
||||
FI.games[i] = NULL;
|
||||
}
|
||||
}
|
||||
FI.numgames = 0;
|
||||
|
||||
FS_ClearSearchPath(); // release all wad files too
|
||||
Mem_FreePool( &fs_mempool );
|
||||
@@ -3119,10 +3081,6 @@ qboolean FS_Rename( const char *oldname, const char *newname )
|
||||
char oldname2[MAX_SYSPATH], newname2[MAX_SYSPATH], oldpath[MAX_SYSPATH], newpath[MAX_SYSPATH];
|
||||
int ret;
|
||||
|
||||
// a1ba: disallow path traversal
|
||||
if( FS_CheckNastyPath( oldname ) || FS_CheckNastyPath( newname ))
|
||||
return false;
|
||||
|
||||
if( !fs_writepath )
|
||||
return false;
|
||||
|
||||
@@ -3171,10 +3129,6 @@ qboolean GAME_EXPORT FS_Delete( const char *path )
|
||||
char path2[MAX_SYSPATH], real_path[MAX_SYSPATH];
|
||||
int ret;
|
||||
|
||||
// a1ba: disallow path traversal
|
||||
if( FS_CheckNastyPath( path ))
|
||||
return false;
|
||||
|
||||
if( !fs_writepath || !COM_CheckString( path ))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -48,11 +48,6 @@ enum
|
||||
FS_SKIP_ARCHIVED_WADS = BIT( 5 ), // don't mount wads inside archives automatically
|
||||
FS_LOAD_PACKED_WAD = BIT( 6 ), // this wad is packed inside other archive
|
||||
|
||||
FS_MOUNT_HD = BIT( 7 ), // mount high definition content folder
|
||||
FS_MOUNT_LV = BIT( 8 ), // mount low violence content folder
|
||||
FS_MOUNT_ADDON = BIT( 9 ), // mount addon folder
|
||||
FS_MOUNT_L10N = BIT( 10 ), // mount localization folder
|
||||
|
||||
FS_GAMEDIRONLY_SEARCH_FLAGS = FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH
|
||||
};
|
||||
|
||||
@@ -156,7 +151,7 @@ typedef struct fs_api_t
|
||||
void (*ShutdownStdio)( void );
|
||||
|
||||
// search path utils
|
||||
void (*Rescan)( uint32_t flags, const char *language );
|
||||
void (*Rescan)( void );
|
||||
void (*ClearSearchPath)( void );
|
||||
void (*AllowDirectPaths)( qboolean enable );
|
||||
void (*AddGameDirectory)( const char *dir, uint flags );
|
||||
|
||||
@@ -167,7 +167,7 @@ void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
|
||||
// search path utils
|
||||
void FS_Rescan( uint32_t flags, const char *language );
|
||||
void FS_Rescan( void );
|
||||
void FS_ClearSearchPath( void );
|
||||
void FS_AllowDirectPaths( qboolean enable );
|
||||
void FS_AddGameDirectory( const char *dir, uint flags );
|
||||
|
||||
@@ -13,11 +13,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "crtlib.h"
|
||||
#include "buildenums.h"
|
||||
|
||||
static const char *const mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
static const char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
static const char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
int Q_buildnum_date( const char *date )
|
||||
@@ -39,31 +38,9 @@ int Q_buildnum_date( const char *date )
|
||||
b = d + (int)((y - 1) * 365.25f );
|
||||
|
||||
if((( y % 4 ) == 0 ) && m > 1 )
|
||||
{
|
||||
b += 1;
|
||||
b -= 41728; // Apr 1 2015
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
int Q_buildnum_iso( const char *date )
|
||||
{
|
||||
int y, m, d, b, i;
|
||||
|
||||
if( sscanf( date, "%d-%d-%d", &y, &m, &d ) != 3 || y <= 1900 || m <= 0 || d <= 0 )
|
||||
return -1;
|
||||
|
||||
// fixup day and month
|
||||
m--;
|
||||
d--;
|
||||
|
||||
for( i = 0; i < m; i++ )
|
||||
d += mond[i];
|
||||
|
||||
y -= 1900;
|
||||
b = d + (int)((y - 1) * 365.25f );
|
||||
|
||||
if((( y % 4 ) == 0 ) && m > 1 )
|
||||
b += 1;
|
||||
}
|
||||
b -= 41728; // Apr 1 2015
|
||||
|
||||
return b;
|
||||
@@ -80,13 +57,8 @@ int Q_buildnum( void )
|
||||
{
|
||||
static int b = 0;
|
||||
|
||||
if( b ) return b;
|
||||
|
||||
if( COM_CheckString( g_buildcommit_date ))
|
||||
b = Q_buildnum_iso( g_buildcommit_date );
|
||||
|
||||
if( b <= 0 )
|
||||
b = Q_buildnum_date( g_build_date );
|
||||
if( !b )
|
||||
b = Q_buildnum_date( __DATE__ );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -15,5 +15,4 @@ GNU General Public License for more details.
|
||||
|
||||
const char *g_buildcommit = XASH_BUILD_COMMIT;
|
||||
const char *g_buildbranch = XASH_BUILD_BRANCH;
|
||||
const char *g_buildcommit_date = XASH_BUILD_COMMIT_DATE;
|
||||
const char *g_build_date = __DATE__;
|
||||
|
||||
|
||||
@@ -339,9 +339,6 @@ int Q_vsnprintf( char *buffer, size_t buffersize, const char *format, va_list ar
|
||||
{
|
||||
int result;
|
||||
|
||||
if( unlikely( buffersize == 0 ))
|
||||
return -1; // report as overflow
|
||||
|
||||
#ifndef _MSC_VER
|
||||
result = vsnprintf( buffer, buffersize, format, args );
|
||||
#else
|
||||
|
||||
@@ -57,7 +57,6 @@ enum
|
||||
//
|
||||
int Q_buildnum( void );
|
||||
int Q_buildnum_date( const char *date );
|
||||
int Q_buildnum_iso( const char *date );
|
||||
int Q_buildnum_compat( void );
|
||||
const char *Q_PlatformStringByID( const int platform );
|
||||
const char *Q_buildos( void );
|
||||
@@ -65,8 +64,6 @@ const char *Q_ArchitectureStringByID( const int arch, const uint abi, const int
|
||||
const char *Q_buildarch( void );
|
||||
extern const char *g_buildcommit;
|
||||
extern const char *g_buildbranch;
|
||||
extern const char *g_build_date;
|
||||
extern const char *g_buildcommit_date;
|
||||
|
||||
//
|
||||
// crtlib.c
|
||||
@@ -141,29 +138,24 @@ static inline char Q_tolower( const char in )
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline qboolean Q_istype( const char *str, int (*istype)( int c ))
|
||||
static inline qboolean Q_isdigit( const char *str )
|
||||
{
|
||||
if( likely( str && *str ))
|
||||
{
|
||||
while( istype( *str )) str++;
|
||||
while( isdigit( *str )) str++;
|
||||
if( !*str ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline qboolean Q_isdigit( const char *str )
|
||||
{
|
||||
return Q_istype( str, isdigit );
|
||||
}
|
||||
|
||||
static inline qboolean Q_isalpha( const char *str )
|
||||
{
|
||||
return Q_istype( str, isalpha );
|
||||
}
|
||||
|
||||
static inline qboolean Q_isspace( const char *str )
|
||||
{
|
||||
return Q_istype( str, isspace );
|
||||
if( likely( str && *str ))
|
||||
{
|
||||
while( isspace( *str ) ) str++;
|
||||
if( !*str ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int Q_strcmp( const char *s1, const char *s2 )
|
||||
|
||||
@@ -180,14 +180,8 @@ int main( void )
|
||||
if( Q_buildnum_date( "Apr 02 2015" ) != 1 )
|
||||
return 201;
|
||||
|
||||
if( Q_buildnum_date( "Apr 02 2015" ) != Q_buildnum_iso( "2015-04-02 21:19:10 +0300" ))
|
||||
return 202;
|
||||
|
||||
if( Q_buildnum_date( "Apr 17 2023" ) != 2938 )
|
||||
return 203;
|
||||
|
||||
if( Q_buildnum_date( "Apr 17 2023" ) != Q_buildnum_iso( "2023-04-17 21:19:10 +0300" ))
|
||||
return 204;
|
||||
return 202;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# mittorn, 2018
|
||||
|
||||
from waflib import Logs, Configure
|
||||
from waflib.extras import gitversion
|
||||
import os
|
||||
|
||||
top = '.'
|
||||
@@ -61,16 +60,6 @@ def export_define(conf, define, value=1):
|
||||
def simple_check(conf, fragment, msg, mandatory=False, **kw):
|
||||
return conf.check_cc(fragment=fragment, msg='Checking for %s' % msg, mandatory=mandatory, **kw)
|
||||
|
||||
@Configure.conf
|
||||
def get_git_commit_date(conf):
|
||||
node = conf.srcnode.find_node('.git')
|
||||
|
||||
if not node:
|
||||
Logs.debug('can\'t find .git in conf.srcnode')
|
||||
return None
|
||||
|
||||
return gitversion.run_git(conf, ['log', '-1', '--format=%ci'])
|
||||
|
||||
def options(opt):
|
||||
opt.add_option('--validate-target', action='store', dest='VALIDATE_TARGET', default=None,
|
||||
help='development option, needs --enable-tests flag')
|
||||
@@ -78,11 +67,6 @@ def options(opt):
|
||||
def configure(conf):
|
||||
# private to libpublic
|
||||
conf.load('gitversion')
|
||||
|
||||
conf.start_msg('Git commit date')
|
||||
conf.env.GIT_COMMIT_DATE = conf.get_git_commit_date()
|
||||
conf.end_msg(conf.env.GIT_COMMIT_DATE)
|
||||
|
||||
conf.env.VALIDATE_TARGET = conf.options.VALIDATE_TARGET
|
||||
|
||||
# need to expose it for everyone using libpublic headers
|
||||
@@ -137,7 +121,7 @@ def build(bld):
|
||||
# build it separately to slightly improve rebuild times
|
||||
bld.stlib(source = 'build_vcs.c',
|
||||
target = 'build_vcs',
|
||||
defines = ['XASH_BUILD_COMMIT=\"%s\"' % bld.env.GIT_VERSION, 'XASH_BUILD_BRANCH=\"%s\"' % bld.env.GIT_BRANCH, 'XASH_BUILD_COMMIT_DATE=\"%s\"' % bld.env.GIT_COMMIT_DATE])
|
||||
defines = ['XASH_BUILD_COMMIT=\"%s\"' % bld.env.GIT_VERSION, 'XASH_BUILD_BRANCH=\"%s\"' % bld.env.GIT_BRANCH])
|
||||
|
||||
bld.stlib(source = bld.path.ant_glob('*.c', excl='build_vcs.c'),
|
||||
target = 'public',
|
||||
|
||||
@@ -453,83 +453,174 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
return sides;
|
||||
}
|
||||
|
||||
void R_StudioCalcBones( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec3_t pos, vec4_t q )
|
||||
/*
|
||||
====================
|
||||
StudioCalcBoneQuaternion
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q )
|
||||
{
|
||||
float v1[6], v2[6];
|
||||
int i, max;
|
||||
vec3_t angles1;
|
||||
vec3_t angles2;
|
||||
int j, k;
|
||||
|
||||
max = q != NULL ? 6 : 3;
|
||||
|
||||
for( i = 0; i < max; i++ )
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[i] );
|
||||
int j = frame;
|
||||
float fadj = 0.0f;
|
||||
|
||||
if( pbone->bonecontroller[i] >= 0 && adj != NULL )
|
||||
fadj = adj[pbone->bonecontroller[i]];
|
||||
|
||||
if( panim->offset[i] == 0 )
|
||||
if( !panim || panim->offset[j+3] == 0 )
|
||||
{
|
||||
v1[i] = v2[i] = pbone->value[i] + fadj;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
j = 0;
|
||||
|
||||
while( panimvalue->num.total <= j )
|
||||
{
|
||||
j -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
j = 0;
|
||||
}
|
||||
|
||||
if( panimvalue->num.valid > j )
|
||||
{
|
||||
v1[i] = panimvalue[j + 1].value;
|
||||
|
||||
if( panimvalue->num.valid > j + 1 )
|
||||
v2[i] = panimvalue[j + 2].value;
|
||||
else if( panimvalue->num.total > j + 1 )
|
||||
v2[i] = v1[i];
|
||||
else
|
||||
v2[i] = panimvalue[panimvalue->num.valid + 2].value;
|
||||
angles2[j] = angles1[j] = pbone->value[j+3]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
v1[i] = panimvalue[panimvalue->num.valid].value;
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);
|
||||
|
||||
if( panimvalue->num.total > j + 1 )
|
||||
v2[i] = v1[i];
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
|
||||
// bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
angles1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
angles2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angles2[j] = angles1[j];
|
||||
else angles2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
v2[i] = panimvalue[panimvalue->num.valid + 2].value;
|
||||
{
|
||||
angles1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
angles2[j] = angles1[j];
|
||||
else angles2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
|
||||
angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3];
|
||||
angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3];
|
||||
}
|
||||
|
||||
v1[i] = pbone->value[i] + v1[i] * pbone->scale[i] + fadj;
|
||||
v2[i] = pbone->value[i] + v2[i] * pbone->scale[i] + fadj;
|
||||
if( pbone->bonecontroller[j+3] != -1 && adj != NULL )
|
||||
{
|
||||
angles1[j] += adj[pbone->bonecontroller[j+3]];
|
||||
angles2[j] += adj[pbone->bonecontroller[j+3]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( v1, v2 ))
|
||||
VectorLerp( v1, s, v2, pos );
|
||||
else
|
||||
VectorCopy( v1, pos );
|
||||
|
||||
if( q != NULL )
|
||||
if( !VectorCompare( angles1, angles2 ))
|
||||
{
|
||||
if( !VectorCompare( &v1[3], &v2[3] ))
|
||||
{
|
||||
vec4_t q1, q2;
|
||||
vec4_t q1, q2;
|
||||
|
||||
AngleQuaternion( &v1[3], q1, true );
|
||||
AngleQuaternion( &v2[3], q2, true );
|
||||
QuaternionSlerp( q1, q2, s, q );
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleQuaternion( &v1[3], q, true );
|
||||
}
|
||||
AngleQuaternion( angles1, q1, true );
|
||||
AngleQuaternion( angles2, q2, true );
|
||||
QuaternionSlerp( q1, q2, s, q );
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleQuaternion( angles1, q, true );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioCalcBonePosition
|
||||
|
||||
====================
|
||||
*/
|
||||
void R_StudioCalcBonePosition( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec3_t pos )
|
||||
{
|
||||
vec3_t origin1;
|
||||
vec3_t origin2;
|
||||
int j, k;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( !panim || panim->offset[j] == 0 )
|
||||
{
|
||||
origin2[j] = origin1[j] = pbone->value[j]; // default;
|
||||
}
|
||||
else
|
||||
{
|
||||
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);
|
||||
|
||||
k = frame;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
|
||||
// find span of values that includes the frame we want
|
||||
while( panimvalue->num.total <= k )
|
||||
{
|
||||
k -= panimvalue->num.total;
|
||||
panimvalue += panimvalue->num.valid + 1;
|
||||
|
||||
// debug
|
||||
if( panimvalue->num.total < panimvalue->num.valid )
|
||||
k = 0;
|
||||
}
|
||||
|
||||
// bah, missing blend!
|
||||
if( panimvalue->num.valid > k )
|
||||
{
|
||||
origin1[j] = panimvalue[k+1].value;
|
||||
|
||||
if( panimvalue->num.valid > k + 1 )
|
||||
{
|
||||
origin2[j] = panimvalue[k+2].value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
origin2[j] = origin1[j];
|
||||
else origin2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
origin1[j] = panimvalue[panimvalue->num.valid].value;
|
||||
if( panimvalue->num.total > k + 1 )
|
||||
origin2[j] = origin1[j];
|
||||
else origin2[j] = panimvalue[panimvalue->num.valid+2].value;
|
||||
}
|
||||
|
||||
origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j];
|
||||
origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j];
|
||||
}
|
||||
|
||||
if( pbone->bonecontroller[j] != -1 && adj != NULL )
|
||||
{
|
||||
origin1[j] += adj[pbone->bonecontroller[j]];
|
||||
origin2[j] += adj[pbone->bonecontroller[j]];
|
||||
}
|
||||
}
|
||||
|
||||
if( !VectorCompare( origin1, origin2 ))
|
||||
{
|
||||
VectorLerp( origin1, s, origin2, pos );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( origin1, pos );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,8 +168,8 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
||||
void PlaneIntersect( const mplane_t *plane, const vec3_t p0, const vec3_t p1, vec3_t out );
|
||||
qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir );
|
||||
void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
|
||||
|
||||
void R_StudioCalcBones( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec3_t pos, vec4_t q );
|
||||
void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q );
|
||||
void R_StudioCalcBonePosition( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const vec3_t adj, vec3_t pos );
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p );
|
||||
#define BOX_ON_PLANE_SIDE( emins, emaxs, p ) \
|
||||
((( p )->type < 3 ) ? \
|
||||
|
||||
@@ -81,20 +81,6 @@ static void CL_FillRGBA( int rendermode, float _x, float _y, float _w, float _h,
|
||||
pglDisable( GL_BLEND );
|
||||
}
|
||||
|
||||
static qboolean Mod_LooksLikeWaterTexture( const char *name )
|
||||
{
|
||||
if(( name[0] == '*' && Q_stricmp( name, REF_DEFAULT_TEXTURE )) || name[0] == '!' )
|
||||
return true;
|
||||
|
||||
if( !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
if( !Q_strncmp( name, "water", 5 ) || !Q_strnicmp( name, "laser", 5 ))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Mod_BrushUnloadTextures( model_t *mod )
|
||||
{
|
||||
int i;
|
||||
@@ -107,12 +93,8 @@ static void Mod_BrushUnloadTextures( model_t *mod )
|
||||
|
||||
if( tx->gl_texturenum != tr.defaultTexture )
|
||||
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
||||
|
||||
if( !Mod_LooksLikeWaterTexture( tx->name ))
|
||||
{
|
||||
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||
GL_FreeTexture( tx->dt_texturenum ); // detail texture
|
||||
}
|
||||
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||
GL_FreeTexture( tx->dt_texturenum ); // detail texture
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,7 +388,7 @@ void R_TextureReplacementReport( const char *modelname, int gl_texturenum, const
|
||||
void CL_RunLightStyles( lightstyle_t *ls );
|
||||
void R_PushDlights( void );
|
||||
void R_GetLightSpot( vec3_t lightspot );
|
||||
void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node );
|
||||
void R_MarkLights( dlight_t *light, int bit, mnode_t *node );
|
||||
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec );
|
||||
colorVec R_LightPoint( const vec3_t p0 );
|
||||
|
||||
@@ -436,6 +436,7 @@ void R_DrawWorld( void );
|
||||
void R_DrawWaterSurfaces( void );
|
||||
void R_DrawBrushModel( cl_entity_t *e );
|
||||
void GL_SubdivideSurface( model_t *mod, msurface_t *fa );
|
||||
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
|
||||
void GL_SetupFogColorForSurfaces( void );
|
||||
void R_DrawAlphaTextureChains( void );
|
||||
void GL_RebuildLightmaps( void );
|
||||
@@ -812,7 +813,6 @@ extern convar_t r_ripple;
|
||||
extern convar_t r_ripple_updatetime;
|
||||
extern convar_t r_ripple_spawntime;
|
||||
extern convar_t r_large_lightmaps;
|
||||
extern convar_t r_dlight_virtual_radius;
|
||||
|
||||
//
|
||||
// engine shared convars
|
||||
|
||||
@@ -38,7 +38,6 @@ CVAR_DEFINE_AUTO( r_ripple, "0", FCVAR_GLCONFIG, "enable software-like water tex
|
||||
CVAR_DEFINE_AUTO( r_ripple_updatetime, "0.05", FCVAR_GLCONFIG, "how fast ripple simulation is" );
|
||||
CVAR_DEFINE_AUTO( r_ripple_spawntime, "0.1", FCVAR_GLCONFIG, "how fast new ripples spawn" );
|
||||
CVAR_DEFINE_AUTO( r_large_lightmaps, "0", FCVAR_GLCONFIG|FCVAR_LATCH, "enable larger lightmap atlas textures (might break custom renderer mods)" );
|
||||
CVAR_DEFINE_AUTO( r_dlight_virtual_radius, "3", FCVAR_GLCONFIG, "increase dlight radius virtually by this amount, should help against ugly cut off dlights on highly scaled textures" );
|
||||
|
||||
DEFINE_ENGINE_SHARED_CVAR_LIST()
|
||||
|
||||
@@ -1156,7 +1155,6 @@ static void GL_InitCommands( void )
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_vbo_overbrightmode );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_vbo_detail );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_large_lightmaps );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_dlight_virtual_radius );
|
||||
|
||||
gEngfuncs.Cvar_RegisterVariable( &gl_extensions );
|
||||
gEngfuncs.Cvar_RegisterVariable( &gl_texture_nearest );
|
||||
|
||||
@@ -99,76 +99,48 @@ void CL_RunLightStyles( lightstyle_t *ls )
|
||||
R_MarkLights
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node )
|
||||
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
||||
{
|
||||
const float virtual_radius = light->radius * Q_max( 1.0f, r_dlight_virtual_radius.value );
|
||||
const float maxdist = light->radius * light->radius;
|
||||
float dist;
|
||||
int i;
|
||||
float dist;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
mnode_t *children[2];
|
||||
int firstsurface, numsurfaces;
|
||||
|
||||
start:
|
||||
|
||||
if( !node || node->contents < 0 )
|
||||
return;
|
||||
|
||||
dist = PlaneDiff( light->origin, node->plane );
|
||||
|
||||
node_children( children, node, RI.currentmodel );
|
||||
|
||||
if( dist > virtual_radius )
|
||||
{
|
||||
node = children[0];
|
||||
goto start;
|
||||
}
|
||||
|
||||
if( dist < -virtual_radius )
|
||||
{
|
||||
node = children[1];
|
||||
goto start;
|
||||
}
|
||||
|
||||
// mark the polygons
|
||||
firstsurface = node_firstsurface( node, RI.currentmodel );
|
||||
numsurfaces = node_numsurfaces( node, RI.currentmodel );
|
||||
|
||||
for( i = 0; i < numsurfaces; i++ )
|
||||
if( dist > light->radius )
|
||||
{
|
||||
vec3_t impact;
|
||||
float s, t, l;
|
||||
msurface_t *surf = &RI.currentmodel->surfaces[firstsurface + i];
|
||||
const mextrasurf_t *info = surf->info;
|
||||
R_MarkLights( light, bit, children[0] );
|
||||
return;
|
||||
}
|
||||
if( dist < -light->radius )
|
||||
{
|
||||
R_MarkLights( light, bit, children[1] );
|
||||
return;
|
||||
}
|
||||
|
||||
if( surf->plane->type < 3 )
|
||||
{
|
||||
VectorCopy( light->origin, impact );
|
||||
impact[surf->plane->type] -= dist;
|
||||
}
|
||||
else VectorMA( light->origin, -dist, surf->plane->normal, impact );
|
||||
// mark the polygons
|
||||
surf = RI.currentmodel->surfaces + firstsurface;
|
||||
|
||||
// a1ba: the fix was taken from JoeQuake, which traces back to FitzQuake,
|
||||
// which attributes it to LadyHavoc (Darkplaces author)
|
||||
// clamp center of light to corner and check brightness
|
||||
l = DotProduct( impact, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0];
|
||||
s = l + 0.5;
|
||||
s = bound( 0, s, info->lightextents[0] );
|
||||
s = l - s;
|
||||
|
||||
l = DotProduct( impact, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1];
|
||||
t = l + 0.5;
|
||||
t = bound( 0, t, info->lightextents[1] );
|
||||
t = l - t;
|
||||
|
||||
if( s * s + t * t + dist * dist >= maxdist )
|
||||
continue;
|
||||
for( i = 0; i < numsurfaces; i++, surf++ )
|
||||
{
|
||||
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
|
||||
continue; // no intersection
|
||||
|
||||
if( surf->dlightframe != tr.dlightframecount )
|
||||
{
|
||||
surf->dlightbits = bit;
|
||||
surf->dlightbits = 0;
|
||||
surf->dlightframe = tr.dlightframecount;
|
||||
}
|
||||
else surf->dlightbits |= bit;
|
||||
surf->dlightbits |= bit;
|
||||
}
|
||||
|
||||
R_MarkLights( light, bit, children[0] );
|
||||
|
||||
@@ -26,6 +26,7 @@ typedef struct
|
||||
byte lightmap_buffer[BLOCK_SIZE_MAX*BLOCK_SIZE_MAX*4];
|
||||
} gllightmapstate_t;
|
||||
|
||||
static int nColinElim; // stats
|
||||
static vec2_t world_orthocenter;
|
||||
static vec2_t world_orthohalf;
|
||||
static uint r_blocklights[BLOCK_SIZE_MAX*BLOCK_SIZE_MAX*3];
|
||||
@@ -334,16 +335,16 @@ void GL_SubdivideSurface( model_t *loadmodel, msurface_t *fa )
|
||||
GL_BuildPolygonFromSurface
|
||||
================
|
||||
*/
|
||||
static int GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
{
|
||||
int i, lnumverts, nColinElim = 0;
|
||||
int i, lnumverts;
|
||||
float sample_size;
|
||||
texture_t *tex;
|
||||
gl_texture_t *glt;
|
||||
glpoly2_t *poly;
|
||||
|
||||
if( !mod || !fa->texinfo || !fa->texinfo->texture )
|
||||
return nColinElim; // bad polygon ?
|
||||
return; // bad polygon ?
|
||||
|
||||
if( FBitSet( fa->flags, SURF_CONVEYOR ) && fa->texinfo->texture->gl_texturenum != 0 )
|
||||
{
|
||||
@@ -416,7 +417,6 @@ static int GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
}
|
||||
|
||||
poly->numverts = lnumverts;
|
||||
return nColinElim;
|
||||
}
|
||||
|
||||
|
||||
@@ -2476,14 +2476,10 @@ static void R_SetupVBOArrayDlight( vboarray_t *vbo, texture_t *texture )
|
||||
|
||||
static void R_SetupVBOArrayDecalDlight( int decalcount )
|
||||
{
|
||||
if( vbos.decal_dlight_vbo )
|
||||
{
|
||||
pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decal_dlight_vbo );
|
||||
pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vbos.decal_dlight_vbo );
|
||||
#if !SPARSE_DECALS_UPLOAD
|
||||
pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vbovertex_t ) * DECAL_VERTS_MAX * decalcount, vbos.decal_dlight, GL_STREAM_DRAW_ARB );
|
||||
pglBufferDataARB( GL_ARRAY_BUFFER_ARB, sizeof( vbovertex_t ) * DECAL_VERTS_MAX * decalcount, vbos.decal_dlight , GL_STREAM_DRAW_ARB );
|
||||
#endif
|
||||
}
|
||||
|
||||
R_SetDecalMode( true );
|
||||
// hack: fix decal dlights on gl_vbo_details == 2 (wrong state??)
|
||||
/*if( mtst.details_enabled && mtst.tmu_dt != -1 )
|
||||
@@ -3848,7 +3844,7 @@ with all the surfaces from all brush models
|
||||
*/
|
||||
void GL_BuildLightmaps( void )
|
||||
{
|
||||
int i, j, nColinElim = 0;
|
||||
int i, j;
|
||||
model_t *m;
|
||||
|
||||
// release old lightmaps
|
||||
@@ -3872,6 +3868,7 @@ void GL_BuildLightmaps( void )
|
||||
gl_lms.current_lightmap_texture = 0;
|
||||
tr.modelviewIdentity = false;
|
||||
tr.realframecount = 1;
|
||||
nColinElim = 0;
|
||||
|
||||
// setup the texture for dlights
|
||||
R_InitDlightTexture();
|
||||
@@ -3900,7 +3897,7 @@ void GL_BuildLightmaps( void )
|
||||
if( m->surfaces[j].flags & SURF_DRAWTURB )
|
||||
continue;
|
||||
|
||||
nColinElim += GL_BuildPolygonFromSurface( m, m->surfaces + j );
|
||||
GL_BuildPolygonFromSurface( m, m->surfaces + j );
|
||||
}
|
||||
|
||||
// clearing visframe
|
||||
|
||||
@@ -816,7 +816,10 @@ static void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, ms
|
||||
R_StudioCalcBoneAdj( dadt, adj, e->curstate.controller, e->latched.prevcontroller, e->mouth.mouthopen );
|
||||
|
||||
for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ )
|
||||
R_StudioCalcBones( frame, s, pbone, panim, adj, pos[i], q[i] );
|
||||
{
|
||||
R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] );
|
||||
R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f;
|
||||
|
||||
@@ -40,16 +40,16 @@ set rendermode
|
||||
void TriRenderMode( int mode )
|
||||
{
|
||||
ds.renderMode = mode;
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case kRenderNormal:
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglDisable( GL_BLEND );
|
||||
pglDepthMask( GL_TRUE );
|
||||
break;
|
||||
case kRenderTransAlpha:
|
||||
pglEnable( GL_BLEND );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglDepthMask( GL_FALSE );
|
||||
break;
|
||||
@@ -60,6 +60,7 @@ void TriRenderMode( int mode )
|
||||
break;
|
||||
case kRenderGlow:
|
||||
case kRenderTransAdd:
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
pglEnable( GL_BLEND );
|
||||
pglDepthMask( GL_FALSE );
|
||||
|
||||
@@ -835,7 +835,10 @@ static void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, ms
|
||||
R_StudioCalcBoneAdj( dadt, adj, e->curstate.controller, e->latched.prevcontroller, e->mouth.mouthopen );
|
||||
|
||||
for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ )
|
||||
R_StudioCalcBones( frame, s, pbone, panim, adj, pos[i], q[i] );
|
||||
{
|
||||
R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] );
|
||||
R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X )
|
||||
pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
|
||||
@@ -59,7 +59,6 @@ x-compat-i386-opts: &compat-i386-opts
|
||||
CC: i686-unknown-linux-gnu-gcc
|
||||
CXX: i686-unknown-linux-gnu-g++
|
||||
libdir: /app/lib32
|
||||
no-debuginfo: true # libbacktrace relies on this
|
||||
|
||||
modules:
|
||||
- name: bundle-setup
|
||||
|
||||
@@ -15,8 +15,6 @@ build_hlsdk()
|
||||
export VITASDK=/usr/local/vitasdk
|
||||
export PATH=$VITASDK/bin:$PATH
|
||||
|
||||
JOBS=$(($(nproc)+1))
|
||||
|
||||
cd "$BUILDDIR" || die
|
||||
|
||||
rm -rf artifacts build pkgtemp
|
||||
@@ -26,13 +24,13 @@ mkdir -p artifacts/ || die
|
||||
|
||||
echo "Building vitaGL..."
|
||||
|
||||
make -C vitaGL NO_TEX_COMBINER=1 HAVE_UNFLIPPED_FBOS=1 HAVE_PTHREAD=1 MATH_SPEEDHACK=1 DRAW_SPEEDHACK=1 -j$JOBS install || die
|
||||
make -C vitaGL NO_TEX_COMBINER=1 HAVE_UNFLIPPED_FBOS=1 HAVE_PTHREAD=1 MATH_SPEEDHACK=1 DRAW_SPEEDHACK=1 -j2 install || die
|
||||
|
||||
echo "Building vrtld..."
|
||||
|
||||
pushd vita-rtld || die
|
||||
cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release || die_configure
|
||||
cmake --build build -- -j$JOBS || die
|
||||
cmake --build build -- -j2 || die
|
||||
cmake --install build || die
|
||||
popd
|
||||
|
||||
@@ -40,7 +38,7 @@ echo "Building SDL..."
|
||||
|
||||
pushd SDL || die
|
||||
cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DVIDEO_VITA_VGL=ON -DSDL_RENDER=OFF || die_configure
|
||||
cmake --build build -- -j$JOBS || die
|
||||
cmake --build build -- -j2 || die
|
||||
cmake --install build || die
|
||||
popd
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ echo "Downloading vitasdk..."
|
||||
|
||||
export VITASDK=/usr/local/vitasdk
|
||||
|
||||
VITAGL_SRCREV="064db9efb15833e18777a3e768b8b1fb2abee78f" # lock vitaGL version to avoid compilation errors
|
||||
VITAGL_SRCREV="4d3ab1053424abe3b2164a50d15c5e355e33ed99" # lock vitaGL version to avoid compilation errors
|
||||
|
||||
install_package()
|
||||
{
|
||||
|
||||
@@ -48,12 +48,6 @@ def sdl2_configure_path(conf, path, libname):
|
||||
conf.env[FRAMEWORKPATH] = [my_dirname(path)]
|
||||
conf.env[FRAMEWORK] = [libname]
|
||||
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[FRAMEWORK], conf.env[FRAMEWORKPATH], conf.env[INCLUDES]))
|
||||
elif conf.env.DEST_OS == 'android':
|
||||
# Special setup for waf called from CMake, through ExternalProject_Add
|
||||
conf.env[INCLUDES] = [os.path.abspath(os.path.join(path, 'include'))]
|
||||
conf.env[LIBPATH] = [os.environ['BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY']]
|
||||
conf.env[LIB] = [libname]
|
||||
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[LIB], conf.env[LIBPATH], conf.env[INCLUDES]))
|
||||
else:
|
||||
conf.env[INCLUDES] = [
|
||||
os.path.abspath(os.path.join(path, 'include')),
|
||||
|
||||
@@ -20,20 +20,12 @@ import os
|
||||
import sys
|
||||
|
||||
ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK']
|
||||
ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25, 27, 28]
|
||||
ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25]
|
||||
ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp
|
||||
ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC
|
||||
ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15
|
||||
ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag
|
||||
ANDROID_NDK_API_MIN = {
|
||||
10: 3,
|
||||
19: 16,
|
||||
20: 16,
|
||||
23: 16,
|
||||
25: 19,
|
||||
27: 19,
|
||||
28: 19,
|
||||
} # minimal API level ndk revision supports
|
||||
ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16, 25: 19 } # minimal API level ndk revision supports
|
||||
|
||||
ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21
|
||||
ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets
|
||||
@@ -58,7 +50,6 @@ class Android:
|
||||
self.api = api
|
||||
self.toolchain = toolchain
|
||||
self.arch = arch
|
||||
self.exe = '.exe' if sys.platform.startswith('win32') or sys.platform.startswith('cygwin') else ''
|
||||
|
||||
for i in ANDROID_NDK_ENVVARS:
|
||||
self.ndk_home = os.getenv(i)
|
||||
@@ -205,10 +196,10 @@ class Android:
|
||||
|
||||
def gen_toolchain_path(self):
|
||||
if self.is_clang():
|
||||
base = ''
|
||||
triplet = '%s%d-' % (self.ndk_triplet(llvm_toolchain = True), self.api)
|
||||
else:
|
||||
base = self.ndk_triplet() + '-'
|
||||
return os.path.join(self.gen_gcc_toolchain_path(), 'bin', base)
|
||||
triplet = self.ndk_triplet() + '-'
|
||||
return os.path.join(self.gen_gcc_toolchain_path(), 'bin', triplet)
|
||||
|
||||
def gen_binutils_path(self):
|
||||
if self.ndk_rev >= 23:
|
||||
@@ -224,11 +215,7 @@ class Android:
|
||||
s = environ['CC']
|
||||
|
||||
return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api)
|
||||
|
||||
if self.is_clang():
|
||||
return '%s --target=%s%d' % (self.gen_toolchain_path() + 'clang' + self.exe, self.ndk_triplet(), self.api)
|
||||
|
||||
return self.gen_toolchain_path() + 'gcc'
|
||||
return self.gen_toolchain_path() + ('clang' if self.is_clang() else 'gcc')
|
||||
|
||||
def cxx(self):
|
||||
if self.is_host():
|
||||
@@ -239,33 +226,19 @@ class Android:
|
||||
s = environ['CXX']
|
||||
|
||||
return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api)
|
||||
|
||||
if self.is_clang():
|
||||
return '%s --target=%s%d' % (self.gen_toolchain_path() + 'clang++' + self.exe, self.ndk_triplet(), self.api)
|
||||
|
||||
return self.gen_toolchain_path() + 'g++'
|
||||
return self.gen_toolchain_path() + ('clang++' if self.is_clang() else 'g++')
|
||||
|
||||
def strip(self):
|
||||
if self.is_host():
|
||||
environ = getattr(self.ctx, 'environ', os.environ)
|
||||
|
||||
if 'STRIP' in environ:
|
||||
return environ['STRIP']
|
||||
return 'llvm-strip'
|
||||
|
||||
if self.ndk_rev >= 23:
|
||||
return os.path.join(self.gen_binutils_path(), 'llvm-strip' + self.exe)
|
||||
return os.path.join(self.gen_binutils_path(), 'strip' + self.exe)
|
||||
|
||||
def ar(self):
|
||||
if self.is_host():
|
||||
environ = getattr(self.ctx, 'environ', os.environ)
|
||||
if 'AR' in environ:
|
||||
return environ['AR']
|
||||
return 'llvm-ar'
|
||||
|
||||
if self.ndk_rev >= 23:
|
||||
return os.path.join(self.gen_binutils_path(), 'llvm-ar' + self.exe)
|
||||
return os.path.join(self.gen_binutils_path(), 'ar' + self.exe)
|
||||
return os.path.join(self.gen_binutils_path(), 'llvm-strip')
|
||||
return os.path.join(self.gen_binutils_path(), 'strip')
|
||||
|
||||
def system_stl(self):
|
||||
# TODO: proper STL support
|
||||
@@ -363,7 +336,7 @@ class Android:
|
||||
ldflags += ['-lgcc']
|
||||
|
||||
if self.is_clang() or self.is_host():
|
||||
ldflags += ['-stdlib=libstdc++', '-lc++abi']
|
||||
ldflags += ['-stdlib=libstdc++']
|
||||
else: ldflags += ['-no-canonical-prefixes']
|
||||
|
||||
if self.is_arm():
|
||||
@@ -548,33 +521,25 @@ def configure(conf):
|
||||
|
||||
valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64']
|
||||
|
||||
if values[0] == 'arm64-v8a':
|
||||
values[0] = 'aarch64'
|
||||
|
||||
if values[0] not in valid_archs:
|
||||
conf.fatal('Unknown arch: %s. Supported: %r' % (values[0], ', '.join(valid_archs)))
|
||||
|
||||
conf.android = android = Android(conf, values[0], values[1], int(values[2]))
|
||||
|
||||
conf.environ['CC'] = android.cc()
|
||||
conf.environ['CXX'] = android.cxx()
|
||||
conf.environ['STRIP'] = android.strip()
|
||||
conf.environ['AR'] = android.ar()
|
||||
conf.env.CFLAGS += android.cflags()
|
||||
conf.env.CXXFLAGS += android.cflags(True)
|
||||
conf.env.LINKFLAGS += android.linkflags()
|
||||
conf.env.LDFLAGS += android.ldflags()
|
||||
|
||||
from waflib.Tools.compiler_c import c_compiler
|
||||
from waflib.Tools.compiler_cxx import cxx_compiler
|
||||
c_compiler['win32'] = ['clang' if android.is_clang() or android.is_host() else 'gcc']
|
||||
cxx_compiler['win32'] = ['clang++' if android.is_clang() or android.is_host() else 'gxx']
|
||||
|
||||
conf.env.HAVE_M = True
|
||||
if android.is_hardfp():
|
||||
conf.env.LIB_M = ['m_hard']
|
||||
else: conf.env.LIB_M = ['m']
|
||||
|
||||
conf.env.PREFIX = '/lib/%s' % android.apk_arch()
|
||||
|
||||
conf.msg('Selected Android NDK', '%s, version: %d' % (android.ndk_home, android.ndk_rev))
|
||||
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx
|
||||
conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/'))
|
||||
|
||||
57
wscript
57
wscript
@@ -84,7 +84,6 @@ SUBDIRS = [
|
||||
Subproject('filesystem'),
|
||||
Subproject('stub/server'),
|
||||
Subproject('dllemu'),
|
||||
Subproject('3rdparty/libbacktrace'),
|
||||
|
||||
# disable only by engine feature, makes no sense to even parse subprojects in dedicated mode
|
||||
Subproject('3rdparty/extras', lambda x: x.env.CLIENT and x.env.DEST_OS != 'android'),
|
||||
@@ -274,13 +273,9 @@ def configure(conf):
|
||||
else:
|
||||
force_32bit = conf.options.FORCE32
|
||||
|
||||
# FIXME: move this whole logic to force_32bit.py, and ensure
|
||||
# DEST_SIZEOF_VOID_P is always set
|
||||
if force_32bit:
|
||||
Logs.info('WARNING: will build engine for 32-bit target')
|
||||
conf.force_32bit(True)
|
||||
else:
|
||||
conf.env.DEST_SIZEOF_VOID_P = 4 if conf.check_32bit() else 8
|
||||
|
||||
cflags, linkflags = conf.get_optimization_flags()
|
||||
cxxflags = list(cflags) # optimization flags are common between C and C++ but we need a copy
|
||||
@@ -468,16 +463,7 @@ def configure(conf):
|
||||
|
||||
# set _FILE_OFFSET_BITS=64 for filesystems with 64-bit inodes
|
||||
# must be set globally as it changes ABI
|
||||
if conf.env.DEST_OS == 'android' and conf.env.DEST_SIZEOF_VOID_P == 4:
|
||||
# Android in 32-bit mode don't have good enough large file support
|
||||
# with our native API level
|
||||
# https://android.googlesource.com/platform/bionic/+/HEAD/docs/32-bit-abi.md
|
||||
pass
|
||||
elif conf.env.DEST_OS == 'psvita':
|
||||
# PSVita don't have large file support at all
|
||||
pass
|
||||
else:
|
||||
# try to guess how to support large files
|
||||
if conf.env.DEST_OS not in ['psvita']:
|
||||
conf.check_large_file(compiler = 'c', execute = False)
|
||||
|
||||
# indicate if we are packaging for Linux/BSD
|
||||
@@ -493,35 +479,28 @@ def configure(conf):
|
||||
else:
|
||||
conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX
|
||||
|
||||
if not conf.options.BUILD_BUNDLED_DEPS:
|
||||
# there was a check for system libbacktrace but we can't be sure if it supports fileline or not
|
||||
# therefore, always build libbacktrace ourselves
|
||||
# dedicated server don't have external dependencies
|
||||
if not conf.options.BUILD_BUNDLED_DEPS and not conf.options.DEDICATED:
|
||||
for i in ('ogg','opusfile','vorbis','vorbisfile'):
|
||||
if conf.check_cfg(package=i, uselib_store=i, args='--cflags --libs', mandatory=False):
|
||||
conf.env['HAVE_SYSTEM_%s' % i.upper()] = True
|
||||
|
||||
if conf.env.CLIENT:
|
||||
for i in ('ogg','opusfile','vorbis','vorbisfile'):
|
||||
if conf.check_cfg(package=i, uselib_store=i, args='--cflags --libs', mandatory=False):
|
||||
conf.env['HAVE_SYSTEM_%s' % i.upper()] = True
|
||||
|
||||
if conf.env.HAVE_SYSTEM_OPUSFILE:
|
||||
frag='''#include <opusfile.h>
|
||||
int main(int argc, char **argv) { return opus_tagcompare(argv[0], argv[1]); }'''
|
||||
|
||||
conf.env.HAVE_SYSTEM_OPUSFILE = conf.check_cc(msg='Checking for libopusfile sanity', use='opusfile werror', fragment=frag, mandatory=False)
|
||||
|
||||
# search for opus 1.4 only, it has fixes for custom modes
|
||||
# 1.5 breaks custom modes: https://github.com/xiph/opus/issues/374
|
||||
if conf.check_cfg(package='opus', uselib_store='opus', args='opus = 1.4 --cflags --libs', mandatory=False):
|
||||
# now try to link with export that only exists with CUSTOM_MODES defined
|
||||
frag='''#include <opus_custom.h>
|
||||
# search for opus 1.4 only, it has fixes for custom modes
|
||||
# 1.5 breaks custom modes: https://github.com/xiph/opus/issues/374
|
||||
if conf.check_cfg(package='opus', uselib_store='opus', args='opus = 1.4 --cflags --libs', mandatory=False):
|
||||
# now try to link with export that only exists with CUSTOM_MODES defined
|
||||
frag='''#include <opus_custom.h>
|
||||
int main(void) { return !opus_custom_encoder_init((OpusCustomEncoder *)1, (const OpusCustomMode *)1, 1); }'''
|
||||
|
||||
conf.env.HAVE_SYSTEM_OPUS = conf.check_cc(msg='Checking if opus supports custom modes', defines='CUSTOM_MODES=1', use='opus werror', fragment=frag, mandatory=False)
|
||||
if conf.check_cc(msg='Checking if opus supports custom modes', defines='CUSTOM_MODES=1', use='opus werror', fragment=frag, mandatory=False):
|
||||
conf.env.HAVE_SYSTEM_OPUS = True
|
||||
|
||||
# search for bzip2
|
||||
BZIP2_CHECK='''#include <bzlib.h>
|
||||
# search for bzip2
|
||||
BZIP2_CHECK='''#include <bzlib.h>
|
||||
int main(void) { return (int)BZ2_bzlibVersion(); }'''
|
||||
|
||||
conf.env.HAVE_SYSTEM_BZ2 = conf.check_cc(lib='bz2', fragment=BZIP2_CHECK, uselib_store='bzip2', mandatory=False)
|
||||
if conf.check_cc(lib='bz2', fragment=BZIP2_CHECK, uselib_store='bzip2', mandatory=False):
|
||||
conf.env.HAVE_SYSTEM_BZ2 = True
|
||||
|
||||
conf.define('XASH_LOW_MEMORY', conf.options.LOW_MEMORY)
|
||||
|
||||
@@ -538,7 +517,7 @@ def build(bld):
|
||||
|
||||
# don't clean QtCreator files and reconfigure saved options
|
||||
bld.clean_files = bld.bldnode.ant_glob('**',
|
||||
excl='*.user configuration.py .lock* *conf_check_*/** config.log 3rdparty/libbacktrace/*.h %s/*' % Build.CACHE_DIR,
|
||||
excl='*.user configuration.py .lock* *conf_check_*/** config.log %s/*' % Build.CACHE_DIR,
|
||||
quiet=True, generator=True)
|
||||
|
||||
bld.load('xshlib')
|
||||
|
||||
Reference in New Issue
Block a user