mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-08 05:11:51 +08:00
Compare commits
48 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
989958e185 | ||
|
|
43ea65fffc | ||
|
|
a72d921c12 | ||
|
|
99b7d71824 | ||
|
|
67c73bdcbe | ||
|
|
8b1dbcf166 | ||
|
|
5f60095dc4 | ||
|
|
c7282b488b | ||
|
|
afa829d996 | ||
|
|
c06ea8d915 | ||
|
|
bf344282ec | ||
|
|
21f62910ac | ||
|
|
54552d93ef | ||
|
|
97455e7fd4 | ||
|
|
6087d43043 | ||
|
|
c1a96d3ff1 | ||
|
|
e27d20dfa3 | ||
|
|
890e12ec76 | ||
|
|
774d2ac28a | ||
|
|
960d724828 | ||
|
|
32aa1f91bf | ||
|
|
bd3634c815 | ||
|
|
eda0ac92cc | ||
|
|
546903ea05 | ||
|
|
4975001795 | ||
|
|
a078ad1f51 | ||
|
|
8307f671d4 | ||
|
|
241fab02b1 | ||
|
|
1bfee70477 | ||
|
|
eb51d17cd2 | ||
|
|
b5cb0b9f10 | ||
|
|
a955d1e957 | ||
|
|
2b2c967e85 | ||
|
|
c48d93e3ce | ||
|
|
8f257cc331 | ||
|
|
151e7fe37b | ||
|
|
add02dc6f9 | ||
|
|
d4c34abd6e | ||
|
|
1d81e611f0 | ||
|
|
6a0038e26a | ||
|
|
1d99f65e86 | ||
|
|
5e524bca60 | ||
|
|
cf3e56e275 | ||
|
|
ade560c601 | ||
|
|
62e3ba2126 | ||
|
|
674a4e5883 | ||
|
|
f911210b81 | ||
|
|
14eb07653c |
@@ -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
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- 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
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
|
||||
1
.github/workflows/c-cpp.yml
vendored
1
.github/workflows/c-cpp.yml
vendored
@@ -120,7 +120,6 @@ 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,3 +34,6 @@
|
||||
[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
|
||||
|
||||
1
3rdparty/libbacktrace/libbacktrace
vendored
Submodule
1
3rdparty/libbacktrace/libbacktrace
vendored
Submodule
Submodule 3rdparty/libbacktrace/libbacktrace added at 78af4ffa26
186
3rdparty/libbacktrace/wscript
vendored
Normal file
186
3rdparty/libbacktrace/wscript
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
#! /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('process_source')
|
||||
@TaskGen.before_method('apply_link')
|
||||
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/'
|
||||
)
|
||||
|
||||
@@ -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 or Dproto.
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
|
||||
Without this requirement, you will just get "Steam validation rejected" error on connecting.
|
||||
|
||||
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
|
||||
|
||||
@@ -37,7 +37,7 @@ 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
|
||||
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} -o "${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs" ${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}"
|
||||
|
||||
@@ -96,6 +96,7 @@ android {
|
||||
packaging {
|
||||
jniLibs {
|
||||
useLegacyPackaging = true
|
||||
keepDebugSymbols.add("**/*.so")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +113,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")
|
||||
|
||||
@@ -28,7 +28,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define PORT_ANY -1
|
||||
|
||||
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
|
||||
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;
|
||||
|
||||
/*
|
||||
Original Quake-2 structure:
|
||||
@@ -46,29 +56,60 @@ 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 a->type;
|
||||
|
||||
if( a->ip6_0[0] || a->ip6_0[1] )
|
||||
return NA_UNDEFINED;
|
||||
|
||||
return 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
|
||||
|
||||
@@ -306,21 +306,22 @@ 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 )
|
||||
{
|
||||
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum ))
|
||||
{
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
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( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
if(( filtering || xremainder ) && 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;
|
||||
}
|
||||
|
||||
*s1 /= width;
|
||||
@@ -1698,7 +1699,12 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
|
||||
clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
|
||||
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
|
||||
|
||||
if( scale_factor && scale_factor != 1.0f )
|
||||
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 )
|
||||
{
|
||||
float scaled_width = (float)refState.width / scale_factor;
|
||||
if( scaled_width >= hud_scale_minimal_width.value )
|
||||
@@ -1760,7 +1766,7 @@ static cvar_t *GAME_EXPORT pfnCvar_RegisterClientVariable( const char *szName, c
|
||||
|| !Q_stricmp( szName, "sensitivity" ))
|
||||
flags |= FCVAR_PRIVILEGED;
|
||||
|
||||
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL ));
|
||||
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, NULL );
|
||||
}
|
||||
|
||||
static int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function )
|
||||
@@ -3421,7 +3427,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
return;
|
||||
}
|
||||
|
||||
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
|
||||
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
|
||||
@@ -691,7 +691,7 @@ pfnCvar_RegisterVariable
|
||||
*/
|
||||
static cvar_t *GAME_EXPORT pfnCvar_RegisterGameUIVariable( const char *szName, const char *szValue, int flags )
|
||||
{
|
||||
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_GAMEUIDLL ));
|
||||
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, NULL );
|
||||
}
|
||||
|
||||
static int GAME_EXPORT Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function )
|
||||
|
||||
@@ -1063,6 +1063,7 @@ 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;
|
||||
|
||||
@@ -1073,14 +1074,16 @@ 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( adr.type != NA_LOOPBACK ? true : false );
|
||||
IN_LockInputDevices( adrtype != 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( adr.type != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
if( adrtype != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
{
|
||||
Cvar_SetCheatState();
|
||||
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
|
||||
@@ -1218,7 +1221,7 @@ static void CL_CheckForResend( void )
|
||||
cls.signon = 0;
|
||||
cls.state = ca_connecting;
|
||||
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
|
||||
cls.serveradr.type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK );
|
||||
cls.legacymode = PROTO_CURRENT;
|
||||
|
||||
// we don't need a challenge on the localhost
|
||||
@@ -1554,8 +1557,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
|
||||
MSG_WriteString( &buf, "dropclient\n" );
|
||||
else MSG_WriteString( &buf, "disconnect" );
|
||||
|
||||
if( !cls.netchan.remote_address.type )
|
||||
cls.netchan.remote_address.type = NA_LOOPBACK;
|
||||
if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED )
|
||||
NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK );
|
||||
|
||||
// make sure message will be delivered
|
||||
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
|
||||
@@ -1724,19 +1727,17 @@ CL_LocalServers_f
|
||||
*/
|
||||
static void CL_LocalServers_f( void )
|
||||
{
|
||||
netadr_t adr;
|
||||
|
||||
memset( &adr, 0, sizeof( adr ));
|
||||
netadr_t adr = { 0 };
|
||||
|
||||
Con_Printf( "Scanning for servers on the local network area...\n" );
|
||||
NET_Config( true, true ); // allow remote
|
||||
|
||||
// send a broadcast packet
|
||||
adr.type = NA_BROADCAST;
|
||||
NET_NetadrSetType( &adr, NA_BROADCAST );
|
||||
adr.port = MSG_BigShort( PORT_SERVER );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
|
||||
adr.type = NA_MULTICAST_IP6;
|
||||
NET_NetadrSetType( &adr, NA_MULTICAST_IP6 );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
@@ -2480,18 +2481,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
uint8_t addr[16];
|
||||
netadr_t servadr;
|
||||
netadr_t servadr = { 0 };
|
||||
|
||||
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
if( NET_NetadrType( &from ) == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
{
|
||||
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
||||
NET_IP6BytesToNetadr( &servadr, addr );
|
||||
servadr.type6 = NA_IP6;
|
||||
NET_NetadrSetType( &servadr, NA_IP6 );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||
servadr.type = NA_IP;
|
||||
NET_NetadrSetType( &servadr, NA_IP );
|
||||
}
|
||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||
|
||||
@@ -3139,6 +3140,9 @@ 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;
|
||||
}
|
||||
|
||||
@@ -3148,7 +3152,7 @@ qboolean CL_PrecacheResources( void )
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
g_fsapi.Rescan();
|
||||
FS_Rescan_f();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
|
||||
@@ -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", style );
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,6 +167,11 @@ 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 ))
|
||||
|
||||
@@ -410,6 +415,8 @@ 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,7 +498,6 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetItemsList
|
||||
@@ -508,6 +507,7 @@ 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,6 +544,8 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -555,6 +557,7 @@ 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;
|
||||
@@ -595,8 +598,9 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
===============
|
||||
@@ -604,13 +608,20 @@ Con_AddCommandToList
|
||||
|
||||
===============
|
||||
*/
|
||||
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList )
|
||||
static void Con_AddCommandToList( const char *s, const char *value, const void *ptoggle, 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
|
||||
|
||||
@@ -634,13 +645,11 @@ Cmd_GetCommandsList
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname, int length, qboolean cmds, qboolean cvars, qboolean toggle )
|
||||
{
|
||||
size_t i;
|
||||
string matchbuf;
|
||||
con_autocomplete_t list; // local autocomplete list
|
||||
|
||||
memset( &list, 0, sizeof( list ));
|
||||
con_autocomplete_t list = { 0 }; // local autocomplete list
|
||||
|
||||
list.completionString = s;
|
||||
|
||||
@@ -652,8 +661,16 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
|
||||
return false;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
if( cvars )
|
||||
{
|
||||
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( cmds )
|
||||
{
|
||||
toggle = false;
|
||||
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( !list.matchCount ) return false;
|
||||
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
|
||||
@@ -669,7 +686,7 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Con_Printf( "\n^3 %i commands found.\n", list.matchCount );
|
||||
Con_Printf( "\n^3 %i %s found.\n", list.matchCount, cmds ? "commands" : "variables" );
|
||||
|
||||
if( completedname && length )
|
||||
{
|
||||
@@ -691,6 +708,30 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
@@ -1010,36 +1051,38 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
|
||||
return Cmd_CheckMapsList_R( fRefresh, true );
|
||||
}
|
||||
|
||||
// keep this sorted
|
||||
static const autocomplete_list_t cmd_list[] =
|
||||
{
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "changelevel2", 1, Cmd_GetMapList },
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "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
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "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, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "reset", 1, Cmd_GetCvarsList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "set", 1, Cmd_GetCvarsList },
|
||||
{ "timedemo", 1, Cmd_GetDemoList },
|
||||
{ "toggle", 1, Cmd_GetCvarsList },
|
||||
{ "unbind", 1, Cmd_GetKeysList },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1160,6 +1203,7 @@ void Con_CompleteCommand( field_t *field )
|
||||
{
|
||||
field_t temp;
|
||||
string filename;
|
||||
qboolean toggle = false;
|
||||
qboolean nextcmd;
|
||||
int i;
|
||||
|
||||
@@ -1194,8 +1238,8 @@ void Con_CompleteCommand( field_t *field )
|
||||
con.shortestMatch[0] = 0;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
|
||||
@@ -103,16 +103,10 @@ Cvar_BuildAutoDescription
|
||||
build cvar auto description that based on the setup flags
|
||||
============
|
||||
*/
|
||||
const char *Cvar_BuildAutoDescription( const char *szName, int flags )
|
||||
static const char *Cvar_BuildAutoDescription( int flags )
|
||||
{
|
||||
static char desc[256];
|
||||
|
||||
if( FBitSet( flags, FCVAR_GLCONFIG ))
|
||||
{
|
||||
Q_snprintf( desc, sizeof( desc ), CVAR_GLCONFIG_DESCRIPTION, szName );
|
||||
return desc;
|
||||
}
|
||||
|
||||
desc[0] = '\0';
|
||||
|
||||
if( FBitSet( flags, FCVAR_EXTDLL ))
|
||||
@@ -447,7 +441,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
Cvar_DirectSet( var, value );
|
||||
}
|
||||
|
||||
if( FBitSet( var->flags, FCVAR_ALLOCATED ) && Q_strcmp( var_desc, var->desc ))
|
||||
if( FBitSet( var->flags, FCVAR_ALLOCATED ) && var_desc != NULL && Q_strcmp( var_desc, var->desc ))
|
||||
{
|
||||
if( !FBitSet( flags, FCVAR_GLCONFIG ))
|
||||
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
|
||||
@@ -460,6 +454,10 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
}
|
||||
|
||||
// allocate a new cvar
|
||||
|
||||
if( !var_desc )
|
||||
var_desc = Cvar_BuildAutoDescription( flags );
|
||||
|
||||
var = Mem_Malloc( cvar_pool, sizeof( *var ));
|
||||
var->name = copystringpool( cvar_pool, name );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
@@ -1206,7 +1204,7 @@ static void Cvar_List_f( void )
|
||||
|
||||
if( FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED ))
|
||||
Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, var->desc );
|
||||
else Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, Cvar_BuildAutoDescription( var->name, var->flags ));
|
||||
else Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, Cvar_BuildAutoDescription( var->flags ));
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ void Cvar_DirectSet( convar_t *var, const char *value );
|
||||
void Cvar_DirectSetValue( convar_t *var, float value );
|
||||
void Cvar_Set( const char *var_name, const char *value );
|
||||
void Cvar_SetValue( const char *var_name, float value );
|
||||
const char *Cvar_BuildAutoDescription( const char *szName, int flags ) RETURNS_NONNULL;
|
||||
float Cvar_VariableValue( const char *var_name );
|
||||
int Cvar_VariableInteger( const char *var_name );
|
||||
const char *Cvar_VariableString( const char *var_name ) RETURNS_NONNULL;
|
||||
|
||||
@@ -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,6 +21,12 @@ 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;
|
||||
|
||||
@@ -69,9 +75,23 @@ void *FS_GetNativeObject( const char *obj )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void FS_Rescan_f( void )
|
||||
void FS_Rescan_f( void )
|
||||
{
|
||||
FS_Rescan();
|
||||
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 );
|
||||
}
|
||||
|
||||
static void FS_ClearPaths_f( void )
|
||||
@@ -236,6 +256,13 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
return false;
|
||||
}
|
||||
|
||||
void FS_CheckConfig( void )
|
||||
{
|
||||
// only used to prevent rescan after reading config.cfg when user hasn't enabled any addon directories
|
||||
if( fs_mount_lv.value || fs_mount_hd.value || fs_mount_addon.value || fs_mount_l10n.value || Q_stricmp( ui_language.string, "english" ))
|
||||
FS_Rescan_f();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_Init
|
||||
@@ -288,6 +315,12 @@ 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 );
|
||||
Cvar_RegisterVariable( &ui_language );
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
|
||||
host.gamedll[0] = 0;
|
||||
|
||||
|
||||
@@ -1043,7 +1043,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
|
||||
if( !Sys_CheckParm( "-noch" ))
|
||||
Sys_SetupCrashHandler();
|
||||
Sys_SetupCrashHandler( argv[0] );
|
||||
|
||||
#if XASH_DLL_LOADER
|
||||
host.enabledll = !Sys_CheckParm( "-nodll" );
|
||||
@@ -1310,6 +1310,7 @@ 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,14 +419,21 @@ void NET_InitMasters( void )
|
||||
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
// 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
|
||||
{ // 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 );
|
||||
}
|
||||
|
||||
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
|
||||
{ // 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_LoadMasters( );
|
||||
}
|
||||
|
||||
@@ -151,17 +151,24 @@ static inline qboolean NET_IsSocketValid( int socket )
|
||||
|
||||
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
|
||||
{
|
||||
memcpy( ip6, adr->ip6, sizeof( adr->ip6 ));
|
||||
memcpy( &ip6[0], adr->ip6_0, 2 );
|
||||
memcpy( &ip6[2], adr->ip6_1, 14 );
|
||||
}
|
||||
|
||||
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
|
||||
{
|
||||
memcpy( adr->ip6, ip6, sizeof( adr->ip6 ));
|
||||
memcpy( adr->ip6_0, &ip6[0], 2 );
|
||||
memcpy( adr->ip6_1, &ip6[2], 14 );
|
||||
}
|
||||
|
||||
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
|
||||
{
|
||||
return memcmp( a->ip6, b->ip6, sizeof( a->ip6 ));
|
||||
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 ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -171,27 +178,29 @@ 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( a->type == NA_BROADCAST )
|
||||
if( 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( a->type == NA_IP )
|
||||
else if( 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( a->type6 == NA_IP6 )
|
||||
else if( type == 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( a->type6 == NA_MULTICAST_IP6 )
|
||||
else if( type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
@@ -208,13 +217,13 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
{
|
||||
if( s->ss_family == AF_INET )
|
||||
{
|
||||
a->type = NA_IP;
|
||||
NET_NetadrSetType( a, 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 )
|
||||
{
|
||||
a->type6 = NA_IP6;
|
||||
NET_NetadrSetType( a, NA_IP6 );
|
||||
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
|
||||
a->port = ((struct sockaddr_in6 *)s)->sin6_port;
|
||||
}
|
||||
@@ -549,8 +558,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;
|
||||
@@ -620,7 +629,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
adr->ip4 = ntohl( mask );
|
||||
}
|
||||
|
||||
adr->type = NA_IP;
|
||||
NET_NetadrSetType( adr, NA_IP );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -634,10 +643,11 @@ NET_AdrToString
|
||||
const char *NET_AdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -661,10 +671,11 @@ NET_BaseAdrToString
|
||||
const char *NET_BaseAdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -689,16 +700,19 @@ Compares without the port
|
||||
*/
|
||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
return a.ip4 == b.ip4;
|
||||
|
||||
if( a.type6 == NA_IP6 )
|
||||
if( type_a == NA_IP6 )
|
||||
{
|
||||
if( !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -716,13 +730,16 @@ Compare local masks
|
||||
*/
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
if( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] )
|
||||
return true;
|
||||
@@ -746,10 +763,13 @@ Checks if adr is a part of subnet
|
||||
*/
|
||||
qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
|
||||
{
|
||||
if( a.type6 != b.type6 || a.type == NA_LOOPBACK )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b || type_a == NA_LOOPBACK )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
uint32_t ipa = htonl( a.ip4 );
|
||||
uint32_t ipb = htonl( b.ip4 );
|
||||
@@ -757,7 +777,7 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
|
||||
if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
|
||||
return true;
|
||||
}
|
||||
else if( a.type6 == NA_IP6 )
|
||||
else if( type_a == NA_IP6 )
|
||||
{
|
||||
uint16_t a_[8], b_[8];
|
||||
size_t check = prefixlen / 16;
|
||||
@@ -798,11 +818,13 @@ Check for reserved ip's
|
||||
*/
|
||||
qboolean NET_IsReservedAdr( netadr_t a )
|
||||
{
|
||||
if( a.type == NA_LOOPBACK )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
// Following checks was imported from GameNetworkingSockets library
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
|
||||
( a.ip[0] == 127 ) || // 127.x.x.x
|
||||
@@ -814,7 +836,7 @@ qboolean NET_IsReservedAdr( netadr_t a )
|
||||
}
|
||||
}
|
||||
|
||||
if( a.type6 == NA_IP6 )
|
||||
if( type_a == NA_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -847,20 +869,23 @@ Compare full address
|
||||
*/
|
||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
if( a.ip4 == b.ip4 && a.port == b.port )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( a.type6 == NA_IP6 )
|
||||
if( type_a == NA_IP6 )
|
||||
{
|
||||
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -883,9 +908,13 @@ 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;
|
||||
|
||||
if( a->type6 != b->type6 )
|
||||
return bound( -1, (int)a->type6 - (int)b->type6, 1 );
|
||||
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 );
|
||||
|
||||
porta = ntohs( a->port );
|
||||
portb = ntohs( b->port );
|
||||
@@ -896,7 +925,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
else
|
||||
portdiff = 0;
|
||||
|
||||
switch( a->type6 )
|
||||
switch( type_a )
|
||||
{
|
||||
case NA_IP6:
|
||||
if(( addrdiff = NET_NetadrIP6Compare( a, b )))
|
||||
@@ -904,14 +933,7 @@ 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;
|
||||
@@ -946,7 +968,7 @@ static qboolean NET_StringToAdrEx( const char *string, netadr_t *adr, int family
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
adr->type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -971,7 +993,7 @@ net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
adr->type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
return NET_EAI_OK;
|
||||
}
|
||||
|
||||
@@ -1017,7 +1039,7 @@ static qboolean NET_GetLoopPacket( netsrc_t sock, netadr_t *from, byte *data, si
|
||||
*length = loop->msgs[i].datalen;
|
||||
|
||||
memset( from, 0, sizeof( *from ));
|
||||
from->type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( from, NA_LOOPBACK );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1546,19 +1568,20 @@ 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 || to.type == NA_LOOPBACK )
|
||||
if( !net.initialized || type == NA_LOOPBACK )
|
||||
{
|
||||
NET_SendLoopPacket( sock, length, data, to );
|
||||
return;
|
||||
}
|
||||
else if( to.type == NA_BROADCAST || to.type == NA_IP )
|
||||
else if( type == NA_BROADCAST || type == NA_IP )
|
||||
{
|
||||
net_socket = net.ip_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
return;
|
||||
}
|
||||
else if( to.type6 == NA_MULTICAST_IP6 || to.type6 == NA_IP6 )
|
||||
else if( type == NA_MULTICAST_IP6 || type == NA_IP6 )
|
||||
{
|
||||
net_socket = net.ip6_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
@@ -1566,7 +1589,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
}
|
||||
else
|
||||
{
|
||||
Host_Error( "%s: bad address type %i (%i)\n", __func__, to.type, to.type6 );
|
||||
Host_Error( "%s: bad address type %i (%i, %i)\n", __func__, to.type, to.ip6_0[0], to.ip6_0[1] );
|
||||
}
|
||||
|
||||
NET_NetadrToSockadr( &to, &addr );
|
||||
@@ -1582,7 +1605,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 && ( to.type == NA_BROADCAST || to.type6 == NA_MULTICAST_IP6 ))
|
||||
if( err == WSAEADDRNOTAVAIL && ( type == NA_BROADCAST || type == NA_MULTICAST_IP6 ))
|
||||
return;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
|
||||
@@ -80,7 +80,7 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
|
||||
|
||||
static inline qboolean NET_IsLocalAddress( netadr_t adr )
|
||||
{
|
||||
return adr.type == NA_LOOPBACK ? true : false;
|
||||
return NET_NetadrType( &adr ) == NA_LOOPBACK;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
|
||||
@@ -69,7 +69,6 @@ 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
|
||||
|
||||
@@ -80,7 +80,7 @@ void Sys_InitLog( void )
|
||||
{
|
||||
const char *mode;
|
||||
|
||||
if( Sys_CheckParm( "-log" ) && host.allow_console != 0 )
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
{
|
||||
s_ld.log_active = true;
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
|
||||
@@ -179,10 +179,10 @@ static inline void Platform_Sleep( int msec )
|
||||
}
|
||||
|
||||
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
|
||||
void Sys_SetupCrashHandler( void );
|
||||
void Sys_SetupCrashHandler( const char *argv0 );
|
||||
void Sys_RestoreCrashHandler( void );
|
||||
#else
|
||||
static inline void Sys_SetupCrashHandler( void )
|
||||
static inline void Sys_SetupCrashHandler( const char *argv0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,15 @@ 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)\n",
|
||||
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
|
||||
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 );
|
||||
@@ -41,10 +47,6 @@ 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 );
|
||||
|
||||
187
engine/platform/posix/crash_libbacktrace.c
Normal file
187
engine/platform/posix/crash_libbacktrace.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
if( g_bt_state )
|
||||
backtrace_full( g_bt_state, 0, 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,6 +28,8 @@ 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
|
||||
@@ -45,16 +47,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 )
|
||||
@@ -69,6 +71,10 @@ 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;
|
||||
@@ -116,8 +122,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)\n",
|
||||
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
|
||||
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
|
||||
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 );
|
||||
@@ -127,10 +133,6 @@ 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 );
|
||||
@@ -206,15 +208,25 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
|
||||
#endif // !HAVE_EXECINFO
|
||||
|
||||
void Sys_SetupCrashHandler( void )
|
||||
void Sys_SetupCrashHandler( const char *argv0 )
|
||||
{
|
||||
struct sigaction act = { 0 };
|
||||
act.sa_sigaction = Sys_Crash;
|
||||
#if HAVE_LIBBACKTRACE
|
||||
if( Sys_SetupLibbacktrace( argv0 ))
|
||||
{
|
||||
act.sa_sigaction = Sys_CrashLibbacktrace;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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:
|
||||
if( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
char val[32];
|
||||
{
|
||||
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" );
|
||||
|
||||
@@ -257,7 +257,8 @@ static void R_InitVideoModes( void )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
int displayIndex = 0; // TODO: handle multiple displays somehow
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
int displayIndex = SDL_GetPointDisplayIndex( &point );
|
||||
int i, modes;
|
||||
|
||||
num_vidmodes = 0;
|
||||
@@ -735,6 +736,24 @@ 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
|
||||
@@ -747,6 +766,8 @@ 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 ));
|
||||
|
||||
@@ -757,35 +778,43 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
|
||||
if( window_mode == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
SDL_Rect r;
|
||||
|
||||
SDL_Rect *display_rects = ( SDL_Rect * )malloc( num_displays * sizeof( SDL_Rect ));
|
||||
|
||||
SetBits( wndFlags, SDL_WINDOW_RESIZABLE );
|
||||
if( maximized )
|
||||
SetBits( wndFlags, SDL_WINDOW_MAXIMIZED );
|
||||
|
||||
#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
|
||||
if( !display_rects )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: SDL_GetDisplayBounds failed: %s\n", __func__, SDL_GetError( ));
|
||||
xpos = SDL_WINDOWPOS_CENTERED;
|
||||
ypos = SDL_WINDOWPOS_CENTERED;
|
||||
Con_Printf( S_ERROR "Failed to allocate memory for display rects!\n" );
|
||||
xpos = SDL_WINDOWPOS_UNDEFINED;
|
||||
ypos = SDL_WINDOWPOS_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 )
|
||||
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 = 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
|
||||
{
|
||||
@@ -795,7 +824,16 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
else
|
||||
SetBits( wndFlags, SDL_WINDOW_FULLSCREEN_DESKTOP );
|
||||
SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
|
||||
xpos = ypos = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
|
||||
@@ -1018,7 +1056,8 @@ qboolean R_Init_Video( const int type )
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_DisplayMode displayMode;
|
||||
SDL_GetCurrentDisplayMode( 0, &displayMode );
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
SDL_GetCurrentDisplayMode( SDL_GetPointDisplayIndex( &point ), &displayMode );
|
||||
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
|
||||
#else
|
||||
refState.desktopBitsPixel = 16;
|
||||
|
||||
@@ -318,7 +318,7 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
void Sys_SetupCrashHandler( void )
|
||||
void Sys_SetupCrashHandler( const char *argv0 )
|
||||
{
|
||||
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
|
||||
oldFilter = SetUnhandledExceptionFilter( Sys_Crash );
|
||||
|
||||
@@ -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( a->adr.type6 != b->adr.type6 )
|
||||
if( NET_NetadrType( &a->adr ) != NET_NetadrType( &b->adr ))
|
||||
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( entry->adr.type6 )
|
||||
switch( NET_NetadrType( &entry->adr ))
|
||||
{
|
||||
case NA_IP:
|
||||
case NA_IP6:
|
||||
|
||||
@@ -189,24 +189,15 @@ void SV_UpdateMovevars( qboolean initialize )
|
||||
if( !initialize && !host.movevars_changed )
|
||||
return;
|
||||
|
||||
// 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
|
||||
// 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" );
|
||||
|
||||
svgame.movevars.gravity = sv_gravity.value;
|
||||
svgame.movevars.stopspeed = sv_stopspeed.value;
|
||||
|
||||
@@ -948,12 +948,6 @@ 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 );
|
||||
|
||||
@@ -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']
|
||||
libs = ['engine_includes', 'public', 'dllemu', 'werror', 'backtrace']
|
||||
includes = ['server', 'client', 'client/vgui', 'common/soundlib']
|
||||
|
||||
# basic build: dedicated only
|
||||
|
||||
@@ -59,8 +59,9 @@ 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 char fs_basedir[MAX_SYSPATH]; // base game directory
|
||||
static char fs_gamedir[MAX_SYSPATH]; // game current directory
|
||||
static string fs_language;
|
||||
|
||||
// add archives in specific order PAK -> PK3 -> WAD
|
||||
// so raw WADs takes precedence over WADs included into PAKs and PK3s
|
||||
@@ -1249,14 +1250,39 @@ 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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,29 +1291,35 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
|
||||
FS_Rescan
|
||||
================
|
||||
*/
|
||||
void FS_Rescan( void )
|
||||
void FS_Rescan( uint32_t flags, const char *language )
|
||||
{
|
||||
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, extrasFlags );
|
||||
FS_MountArchive_Fullpath( str, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
|
||||
str = getenv( "XASH3D_EXTRAS_PAK2" );
|
||||
if( COM_CheckString( str ))
|
||||
FS_MountArchive_Fullpath( str, extrasFlags );
|
||||
FS_MountArchive_Fullpath( str, FS_NOWRITE_PATH|FS_CUSTOM_PATH );
|
||||
|
||||
if( Q_stricmp( GI->basedir, GI->gamefolder ))
|
||||
FS_AddGameHierarchy( GI->basedir, 0 );
|
||||
FS_AddGameHierarchy( GI->basedir, flags );
|
||||
if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamefolder, GI->falldir ))
|
||||
FS_AddGameHierarchy( GI->falldir, 0 );
|
||||
FS_AddGameHierarchy( GI->falldir, flags );
|
||||
|
||||
GI->added = true;
|
||||
FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH );
|
||||
FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH | flags );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1332,7 +1364,7 @@ void FS_LoadGameInfo( const char *rootfolder )
|
||||
FS_CreatePath( buf );
|
||||
}
|
||||
|
||||
FS_Rescan(); // create new filesystem
|
||||
FS_Rescan( 0, NULL ); // create new filesystem
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1575,6 +1607,7 @@ 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 ))
|
||||
@@ -1696,12 +1729,17 @@ 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 );
|
||||
|
||||
@@ -48,6 +48,11 @@ 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
|
||||
};
|
||||
|
||||
@@ -151,7 +156,7 @@ typedef struct fs_api_t
|
||||
void (*ShutdownStdio)( void );
|
||||
|
||||
// search path utils
|
||||
void (*Rescan)( void );
|
||||
void (*Rescan)( uint32_t flags, const char *language );
|
||||
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( void );
|
||||
void FS_Rescan( uint32_t flags, const char *language );
|
||||
void FS_ClearSearchPath( void );
|
||||
void FS_AllowDirectPaths( qboolean enable );
|
||||
void FS_AddGameDirectory( const char *dir, uint flags );
|
||||
|
||||
@@ -13,10 +13,11 @@ 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 *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
static const char *const 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 )
|
||||
@@ -38,9 +39,31 @@ 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;
|
||||
@@ -57,8 +80,13 @@ int Q_buildnum( void )
|
||||
{
|
||||
static int b = 0;
|
||||
|
||||
if( !b )
|
||||
b = Q_buildnum_date( __DATE__ );
|
||||
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 );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -15,4 +15,5 @@ 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,6 +339,9 @@ 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,6 +57,7 @@ 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 );
|
||||
@@ -64,6 +65,8 @@ 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
|
||||
@@ -138,24 +141,29 @@ static inline char Q_tolower( const char in )
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline qboolean Q_isdigit( const char *str )
|
||||
static inline qboolean Q_istype( const char *str, int (*istype)( int c ))
|
||||
{
|
||||
if( likely( str && *str ))
|
||||
{
|
||||
while( isdigit( *str )) str++;
|
||||
while( istype( *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 )
|
||||
{
|
||||
if( likely( str && *str ))
|
||||
{
|
||||
while( isspace( *str ) ) str++;
|
||||
if( !*str ) return true;
|
||||
}
|
||||
return false;
|
||||
return Q_istype( str, isspace );
|
||||
}
|
||||
|
||||
static inline int Q_strcmp( const char *s1, const char *s2 )
|
||||
|
||||
@@ -180,8 +180,14 @@ int main( void )
|
||||
if( Q_buildnum_date( "Apr 02 2015" ) != 1 )
|
||||
return 201;
|
||||
|
||||
if( Q_buildnum_date( "Apr 17 2023" ) != 2938 )
|
||||
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 EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# mittorn, 2018
|
||||
|
||||
from waflib import Logs, Configure
|
||||
from waflib.extras import gitversion
|
||||
import os
|
||||
|
||||
top = '.'
|
||||
@@ -60,6 +61,16 @@ 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')
|
||||
@@ -67,6 +78,11 @@ 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
|
||||
@@ -121,7 +137,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])
|
||||
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])
|
||||
|
||||
bld.stlib(source = bld.path.ant_glob('*.c', excl='build_vcs.c'),
|
||||
target = 'public',
|
||||
|
||||
@@ -81,6 +81,20 @@ 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;
|
||||
@@ -93,8 +107,12 @@ static void Mod_BrushUnloadTextures( model_t *mod )
|
||||
|
||||
if( tx->gl_texturenum != tr.defaultTexture )
|
||||
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
||||
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||
GL_FreeTexture( tx->dt_texturenum ); // detail texture
|
||||
|
||||
if( !Mod_LooksLikeWaterTexture( tx->name ))
|
||||
{
|
||||
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( dlight_t *light, int bit, mnode_t *node );
|
||||
void R_MarkLights( const dlight_t *light, int bit, const 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,7 +436,6 @@ 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 );
|
||||
@@ -813,6 +812,7 @@ 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,6 +38,7 @@ 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()
|
||||
|
||||
@@ -1155,6 +1156,7 @@ 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,48 +99,76 @@ void CL_RunLightStyles( lightstyle_t *ls )
|
||||
R_MarkLights
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
||||
void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node )
|
||||
{
|
||||
float dist;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
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;
|
||||
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 );
|
||||
firstsurface = node_firstsurface( node, RI.currentmodel );
|
||||
numsurfaces = node_numsurfaces( node, RI.currentmodel );
|
||||
|
||||
if( dist > light->radius )
|
||||
if( dist > virtual_radius )
|
||||
{
|
||||
R_MarkLights( light, bit, children[0] );
|
||||
return;
|
||||
node = children[0];
|
||||
goto start;
|
||||
}
|
||||
if( dist < -light->radius )
|
||||
|
||||
if( dist < -virtual_radius )
|
||||
{
|
||||
R_MarkLights( light, bit, children[1] );
|
||||
return;
|
||||
node = children[1];
|
||||
goto start;
|
||||
}
|
||||
|
||||
// mark the polygons
|
||||
surf = RI.currentmodel->surfaces + firstsurface;
|
||||
firstsurface = node_firstsurface( node, RI.currentmodel );
|
||||
numsurfaces = node_numsurfaces( node, RI.currentmodel );
|
||||
|
||||
for( i = 0; i < numsurfaces; i++, surf++ )
|
||||
for( i = 0; i < numsurfaces; i++ )
|
||||
{
|
||||
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
|
||||
continue; // no intersection
|
||||
vec3_t impact;
|
||||
float s, t, l;
|
||||
msurface_t *surf = &RI.currentmodel->surfaces[firstsurface + i];
|
||||
const mextrasurf_t *info = surf->info;
|
||||
|
||||
if( surf->plane->type < 3 )
|
||||
{
|
||||
VectorCopy( light->origin, impact );
|
||||
impact[surf->plane->type] -= dist;
|
||||
}
|
||||
else VectorMA( light->origin, -dist, surf->plane->normal, impact );
|
||||
|
||||
// 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;
|
||||
|
||||
if( surf->dlightframe != tr.dlightframecount )
|
||||
{
|
||||
surf->dlightbits = 0;
|
||||
surf->dlightbits = bit;
|
||||
surf->dlightframe = tr.dlightframecount;
|
||||
}
|
||||
surf->dlightbits |= bit;
|
||||
else surf->dlightbits |= bit;
|
||||
}
|
||||
|
||||
R_MarkLights( light, bit, children[0] );
|
||||
|
||||
@@ -26,7 +26,6 @@ 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];
|
||||
@@ -335,16 +334,16 @@ void GL_SubdivideSurface( model_t *loadmodel, msurface_t *fa )
|
||||
GL_BuildPolygonFromSurface
|
||||
================
|
||||
*/
|
||||
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
static int GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
{
|
||||
int i, lnumverts;
|
||||
int i, lnumverts, nColinElim = 0;
|
||||
float sample_size;
|
||||
texture_t *tex;
|
||||
gl_texture_t *glt;
|
||||
glpoly2_t *poly;
|
||||
|
||||
if( !mod || !fa->texinfo || !fa->texinfo->texture )
|
||||
return; // bad polygon ?
|
||||
return nColinElim; // bad polygon ?
|
||||
|
||||
if( FBitSet( fa->flags, SURF_CONVEYOR ) && fa->texinfo->texture->gl_texturenum != 0 )
|
||||
{
|
||||
@@ -417,6 +416,7 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
|
||||
}
|
||||
|
||||
poly->numverts = lnumverts;
|
||||
return nColinElim;
|
||||
}
|
||||
|
||||
|
||||
@@ -3844,7 +3844,7 @@ with all the surfaces from all brush models
|
||||
*/
|
||||
void GL_BuildLightmaps( void )
|
||||
{
|
||||
int i, j;
|
||||
int i, j, nColinElim = 0;
|
||||
model_t *m;
|
||||
|
||||
// release old lightmaps
|
||||
@@ -3868,7 +3868,6 @@ 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();
|
||||
@@ -3897,7 +3896,7 @@ void GL_BuildLightmaps( void )
|
||||
if( m->surfaces[j].flags & SURF_DRAWTURB )
|
||||
continue;
|
||||
|
||||
GL_BuildPolygonFromSurface( m, m->surfaces + j );
|
||||
nColinElim += GL_BuildPolygonFromSurface( m, m->surfaces + j );
|
||||
}
|
||||
|
||||
// clearing visframe
|
||||
|
||||
@@ -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,7 +60,6 @@ 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 );
|
||||
|
||||
@@ -21,6 +21,8 @@ build_engine()
|
||||
die
|
||||
fi
|
||||
|
||||
cat build/config.log
|
||||
|
||||
./waf build || die
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ 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,6 +15,8 @@ build_hlsdk()
|
||||
export VITASDK=/usr/local/vitasdk
|
||||
export PATH=$VITASDK/bin:$PATH
|
||||
|
||||
JOBS=$(($(nproc)+1))
|
||||
|
||||
cd "$BUILDDIR" || die
|
||||
|
||||
rm -rf artifacts build pkgtemp
|
||||
@@ -24,13 +26,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 -j2 install || die
|
||||
make -C vitaGL NO_TEX_COMBINER=1 HAVE_UNFLIPPED_FBOS=1 HAVE_PTHREAD=1 MATH_SPEEDHACK=1 DRAW_SPEEDHACK=1 -j$JOBS install || die
|
||||
|
||||
echo "Building vrtld..."
|
||||
|
||||
pushd vita-rtld || die
|
||||
cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release || die_configure
|
||||
cmake --build build -- -j2 || die
|
||||
cmake --build build -- -j$JOBS || die
|
||||
cmake --install build || die
|
||||
popd
|
||||
|
||||
@@ -38,7 +40,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 -- -j2 || die
|
||||
cmake --build build -- -j$JOBS || die
|
||||
cmake --install build || die
|
||||
popd
|
||||
|
||||
|
||||
47
wscript
47
wscript
@@ -84,6 +84,7 @@ SUBDIRS = [
|
||||
Subproject('filesystem'),
|
||||
Subproject('stub/server'),
|
||||
Subproject('dllemu'),
|
||||
Subproject('3rdparty/libbacktrace', lambda x: not x.env.HAVE_SYSTEM_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'),
|
||||
@@ -273,9 +274,13 @@ 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
|
||||
@@ -479,28 +484,38 @@ def configure(conf):
|
||||
else:
|
||||
conf.env.SHAREDIR = conf.env.LIBDIR = conf.env.BINDIR = conf.env.PREFIX
|
||||
|
||||
# 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 not conf.options.BUILD_BUNDLED_DEPS:
|
||||
frag='''#include <backtrace.h>
|
||||
#include <backtrace-supported.h>
|
||||
int main(int argc, char **argv) { return backtrace_create_state( argv[0], BACKTRACE_SUPPORTS_THREADS, 0, 0 ) != 0; }'''
|
||||
|
||||
# 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>
|
||||
conf.env.HAVE_SYSTEM_LIBBACKTRACE = conf.check_cc(lib='backtrace', fragment=frag, uselib_store='backtrace', mandatory=False)
|
||||
|
||||
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>
|
||||
int main(void) { return !opus_custom_encoder_init((OpusCustomEncoder *)1, (const OpusCustomMode *)1, 1); }'''
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
# search for bzip2
|
||||
BZIP2_CHECK='''#include <bzlib.h>
|
||||
# search for bzip2
|
||||
BZIP2_CHECK='''#include <bzlib.h>
|
||||
int main(void) { return (int)BZ2_bzlibVersion(); }'''
|
||||
|
||||
if conf.check_cc(lib='bz2', fragment=BZIP2_CHECK, uselib_store='bzip2', mandatory=False):
|
||||
conf.env.HAVE_SYSTEM_BZ2 = True
|
||||
conf.env.HAVE_SYSTEM_BZ2 = conf.check_cc(lib='bz2', fragment=BZIP2_CHECK, uselib_store='bzip2', mandatory=False)
|
||||
|
||||
conf.define('XASH_LOW_MEMORY', conf.options.LOW_MEMORY)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user