Compare commits

...

53 Commits

Author SHA1 Message Date
Alibek Omarov
3baeea1253 engine: client: handle hud_utf8 in client.dll's draw character functions, rather than in engine's CL_DrawCharacter 2025-03-12 07:31:18 +03:00
Alibek Omarov
9ba7cc88d9 engine: client: move Con_UtfProcessChar to cl_gameui. It is now deprecated 2025-03-12 07:26:58 +03:00
Alibek Omarov
9ef7759e05 engine: client: rewrite touch control text drawing with utflib and cl_font 2025-03-12 07:26:58 +03:00
Alibek Omarov
232224f52d engine: client: OSK doesn't need unicode conversion, as it only supports basic latin anyway 2025-03-12 07:26:58 +03:00
Alibek Omarov
18d09d80cc engine: client: like GoldSrc, expect UTF-8 encoded strings in pfnDrawString/pfnDrawStringReverse 2025-03-12 06:15:27 +03:00
Alibek Omarov
67f91fc100 engine: client: decode utf-8 string in CL_DrawCenterPrint, as CL_DrawCharacter requires unicode codepoints now 2025-03-12 06:04:35 +03:00
Alibek Omarov
ca22c4123d engine: client: make CL_DrawCharacter accept unicode codepoints, as it was intended to do 2025-03-11 08:23:16 +03:00
Alibek Omarov
8af0e2c8b4 readme: add missing system dependencies on Linux systems [skip ci] 2025-03-08 02:42:28 +03:00
Alibek Omarov
a5191d8948 engine: client: console: simplify Field_DrawInputLine, try to make it safer 2025-03-08 02:35:32 +03:00
Alibek Omarov
b2d8239829 engine: common: net_http: fix decompression for compressed but not chunked files 2025-03-06 19:10:48 +03:00
Alibek Omarov
34322f025b engine: client: limit ticket generator choices to revemu2013 only 2025-03-06 12:35:32 +03:00
Alibek Omarov
3e6b434733 mainui: update 2025-03-05 22:36:41 +03:00
Alibek Omarov
8359cbe76c scripts: waifulib: add flag --enable-limited-debuginfo which enables -gline-tables-only on GCC and Clang compilers
This saves ~30mb of APK size on Android.
2025-03-05 02:19:39 +03:00
Alibek Omarov
0e90e6285e engine: host: use #if instead of #ifdef when checking for extended hl25 structs compile option 2025-03-03 22:59:44 +03:00
Alibek Omarov
2f5840f650 engine: host: add a cvar that indicates whether engine was built with --enable-hl25-extended-structs or not 2025-03-03 22:53:20 +03:00
Alibek Omarov
3b51a554dd mainui: update 2025-03-02 20:20:54 +03:00
Alibek Omarov
5f0880d4a2 engine: client: lower the bandwidth test fragment sizes to 1400 and less, as using 64k, 32k and more is unreliable 2025-03-02 20:20:40 +03:00
Bohdan Shulyar
884a3c66ac client: touch: fix minor typo that prevented editing touch buttons commands 2025-03-02 20:19:58 +03:00
Alibek Omarov
c76752cc5f engine: server: validate uuid in protinfo, it's an md5 string 2025-03-01 22:45:01 +03:00
Alibek Omarov
fc2888e107 engine: server: fix incorrect ID string generation, hashedcdkey is already an MD5 string 2025-03-01 22:27:22 +03:00
Alibek Omarov
674b4c1506 engine: server: reorder sv_client_t struct for better memory efficiency, remove unused fields 2025-03-01 22:07:05 +03:00
Alibek Omarov
cddd50f1e9 engine: server: completely erase sv_client_t on client connect, so we always start from scratch for every user 2025-03-01 22:07:05 +03:00
Alibek Omarov
6c9d5bc1fb engine: server: cleanup penalties and warns for new players 2025-03-01 16:03:39 +03:00
Alibek Omarov
ec23860238 gitmodules: use github mirrors instead of xiph.org's git
It's not really a good idea to hammer upstream git servers with cloning same
data over and over. Besides, it's down right now.
2025-03-01 15:28:55 +03:00
Alibek Omarov
14a2e34b7e mainui: update 2025-03-01 15:21:20 +03:00
Alibek Omarov
29c8818557 engine: server: do not continue processing command if the player was kicked during it (for example, by speedhack prevention) 2025-03-01 14:58:15 +03:00
Andrey Akhmichin
7222830b28 Documentation: supported-mod-list.md: a little remark. 2025-02-28 23:56:28 +03:00
Alibek Omarov
9b0ad7daf0 engine: common: register forgotten net_clockwindow cvar 2025-02-28 22:44:44 +03:00
Alibek Omarov
73729827f4 engine: platform: win32: add forgotten SDL.h include 2025-02-28 21:55:26 +03:00
Alibek Omarov
97fa395a3b engine: platform: win32: fix build by restoring previous win32 header inclusion order 2025-02-28 21:44:22 +03:00
Alibek Omarov
1cef8ea7af Revert "ref: gl: check OES NPOT texture extension in BigGL mode"
This breaks mipmaps on PSVita

This reverts commit 54b0cf9991.
2025-02-28 17:08:27 +03:00
Alibek Omarov
eda4e95607 engine: client: draw version at bottom right in menu, regardless if dev_overview or net_graph are enabled (those only used in-game) 2025-02-28 15:11:24 +03:00
Alibek Omarov
a5f0ca38f1 engine: remove inclusion of SDL headers globally, helps to cleanup code before SDL3 migration 2025-02-28 13:14:47 +03:00
Alibek Omarov
bbbd7711c1 engine: platform: cleanup remnants of disabling vsync while loading mechanism for linux fbdev and dos ports 2025-02-28 12:33:30 +03:00
Alibek Omarov
38e922557d engine: platform: sdl: remove disabling vsync while we're not in game, as this is something users have been complaining a lot
It's not a big deal if level loading will take a few milliseconds more.
2025-02-28 08:27:38 +03:00
Alibek Omarov
4dec1785ed engine: client: touch: fix inverted file extension check 2025-02-28 06:44:21 +03:00
Alibek Omarov
9f77b7dc46 scripts: waifulib: enable HLSDK -mtune only on GCC and Clang, and not on Android 2025-02-26 17:11:10 +03:00
Alibek Omarov
5061a29f86 scripts: waifulib: enable asynchronous-unwind-tables for better stacktraces 2025-02-26 17:10:30 +03:00
Alibek Omarov
cb5dffd554 engine: server: don't bother printing about unsupported connectionless packets if sv_log_outofband is set to 0 2025-02-26 17:06:33 +03:00
Alibek Omarov
4eaa8ab40f android: bump minimum CMake version, so disabling unneeded features in SDL actually works 2025-02-26 14:21:58 +03:00
Alibek Omarov
2a82d265d6 scripts: waifulib: xcompile: add support for Android NDK r27 as well 2025-02-26 12:40:22 +03:00
Alibek Omarov
f2392b5709 scripts: waifulib: xcompile: add support for building on Windows. Drop using shortcut target clang symlinks, as those don't work on Windows at all (they are wrapped into batch files, which can't be invoked like exes) 2025-02-26 12:40:22 +03:00
Alibek Omarov
5620e7ab4c android: fixup CMAKE_LIBRARY_OUTPUT_DIRECTORY on Win32, merge stdout and stderr for waf output 2025-02-26 12:40:22 +03:00
Alibek Omarov
a76236ac5a scripts: waifulib: xcompile: add support for NDK 28, remove setting up custom PREFIX to not mess up installation path 2025-02-26 12:40:22 +03:00
Alibek Omarov
d1c5862bab android: bump NDK version to 28 2025-02-26 12:40:22 +03:00
Alibek Omarov
81400d0b01 android: use xcompile.py's support for Android NDK, fix tabs 2025-02-26 12:40:22 +03:00
Alibek Omarov
a129f13e25 android: enable verbose output for CMake running from Gradle 2025-02-26 12:40:22 +03:00
Alibek Omarov
ec8b4c0a84 android: rework how engine is built, instead of generating CMakeLists, just use included in CMake ExternalProject feature 2025-02-26 12:40:22 +03:00
Alibek Omarov
f1f726822c engine: client: restore cl_cmdrate default value at 30. It wasn't an intentional change. 2025-02-25 19:52:48 +03:00
Alibek Omarov
8982d55392 engine: client: set default rate value to 25000
3500 is barely playable these days. Those who have worse than usual internet
connection, should set appropriate value themselves.
2025-02-25 17:36:43 +03:00
Alibek Omarov
f499286a87 engine: platform: sdl: don't call SDL_GL_SetSwapInterval each frame while we're not in game 2025-02-25 11:52:03 +03:00
Alibek Omarov
a3aaa87147 ref: gl: enable polygon offset for fullbright textures when rendering them in separate from VBO pass 2025-02-25 11:49:31 +03:00
Alibek Omarov
15a6971aca engine: platform: posix: strip path from filename in backtrace 2025-02-25 11:46:57 +03:00
44 changed files with 647 additions and 520 deletions

6
.gitmodules vendored
View File

@@ -27,13 +27,13 @@
url = https://github.com/FWGS/MultiEmulator url = https://github.com/FWGS/MultiEmulator
[submodule "3rdparty/libogg/libogg"] [submodule "3rdparty/libogg/libogg"]
path = 3rdparty/libogg/libogg path = 3rdparty/libogg/libogg
url = https://gitlab.xiph.org/xiph/ogg.git url = https://github.com/xiph/ogg.git
[submodule "3rdparty/vorbis/vorbis-src"] [submodule "3rdparty/vorbis/vorbis-src"]
path = 3rdparty/vorbis/vorbis-src path = 3rdparty/vorbis/vorbis-src
url = https://gitlab.xiph.org/xiph/vorbis.git url = https://github.com/xiph/vorbis.git
[submodule "3rdparty/opusfile/opusfile"] [submodule "3rdparty/opusfile/opusfile"]
path = 3rdparty/opusfile/opusfile path = 3rdparty/opusfile/opusfile
url = https://gitlab.xiph.org/xiph/opusfile.git url = https://github.com/xiph/opusfile.git
[submodule "3rdparty/libbacktrace/libbacktrace"] [submodule "3rdparty/libbacktrace/libbacktrace"]
path = 3rdparty/libbacktrace/libbacktrace path = 3rdparty/libbacktrace/libbacktrace
url = https://github.com/ianlancetaylor/libbacktrace url = https://github.com/ianlancetaylor/libbacktrace

View File

@@ -874,7 +874,7 @@ To run this mods on specific platforms you may be need to compile libraries from
6. [They Hunger: Route666 Demo](https://yadi.sk/d/XKWCseAPohkG6) by *MadMapper* 6. [They Hunger: Route666 Demo](https://yadi.sk/d/XKWCseAPohkG6) by *MadMapper*
## List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS ## List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
Currently, fresh Xash3D FWGS builds uses libraries from this branch, so you can play mods below out-of-the-box. Currently, fresh Xash3D FWGS builds for Android, PS Vita and Nintendo Switch uses libraries from this branch, so you can play mods below out-of-the-box.
1. **[Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)** 1. **[Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)**
2. **[Big Lolly](https://www.moddb.com/mods/big-lolly)** 2. **[Big Lolly](https://www.moddb.com/mods/big-lolly)**

View File

@@ -66,21 +66,21 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
* Only for 32-bit engine on 64-bit x86 operating system: * Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`. * Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude` * Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`. * Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386 libvorbis-dev:i386 libopusfile-dev:i386 libogg-dev:i386`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`. * Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems: * For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfreetype6-dev libopus-dev libbz2-dev`. * Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfreetype6-dev libopus-dev libbz2-dev libvorbis-dev libopusfile-dev libogg-dev`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`. * Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
##### RedHat/Fedora ##### RedHat/Fedora
* Only for 32-bit engine on 64-bit x86 operating system: * Only for 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686`. * Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686 libvorbis-devel.i686 opusfile-devel.i686 libogg-devel.i686`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`. * Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems: * For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel`. * Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel libvorbis-devel opusfile-devel libogg-devel`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`. * Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.

View File

@@ -1,49 +1,39 @@
cmake_minimum_required(VERSION 3.6) cmake_minimum_required(VERSION 3.22)
# Only used to build Android project # Only used to build Android project
project(XASH_ANDROID) project(XASH_ANDROID)
# armeabi-v7a requires cpufeatures library # armeabi-v7a requires cpufeatures library
include(AndroidNdkModules) if(ANDROID)
android_ndk_import_module_cpufeatures() include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
target_link_libraries(cpufeatures dl)
endif()
find_package(PythonInterp 2.7 REQUIRED) include(FindPython)
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(BUILD_TYPE "debug") set(BUILD_TYPE "debug")
else() else()
set(BUILD_TYPE "release") set(BUILD_TYPE "release")
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto) list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto --enable-limited-debuginfo)
endif() endif()
if(CMAKE_SIZEOF_VOID_P MATCHES "8") if(ANDROID_ABI STREQUAL "x86")
set(64BIT ON CACHE BOOL "" FORCE) # HACKHACK: I don't know why but engine gets built as 64-bit binary here
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux list(APPEND WAF_EXTRA_ARGS -4)
endif() endif()
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
# not cleanest way to get upper directory # not cleanest way to get upper directory
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../") set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
execute_process( set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
COMMAND ${CMAKE_COMMAND} -E env set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
CC=${WAF_CC} CXX=${WAF_CXX} set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs)
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
${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}"
)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
# try to build minimal SDL. Enable features as we're gonna use them # try to build minimal SDL. Enable features as we're gonna use them
set(SDL_RENDER OFF) set(SDL_RENDER OFF)
@@ -56,5 +46,50 @@ set(SDL_VULKAN OFF)
set(SDL_OFFSCREEN OFF) set(SDL_OFFSCREEN OFF)
set(SDL_STATIC OFF) set(SDL_STATIC OFF)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL) add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui) include(ExternalProject)
# gradle passes backslashes to cmake, how does this even work for everybody else?
string(REPLACE "\\" "/" CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
ExternalProject_Add(
Xash3DFWGS
SOURCE_DIR ${ENGINE_SOURCE_DIR}
INSTALL_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
BUILD_IN_SOURCE TRUE
DEPENDS SDL2
BUILD_ALWAYS TRUE
LOG_CONFIGURE TRUE
LOG_BUILD TRUE
LOG_INSTALL TRUE
LOG_OUTPUT_ON_FAILURE TRUE
LOG_MERGED_STDOUTERR TRUE
# USES_TERMINAL_CONFIGURE TRUE
# USES_TERMINAL_BUILD TRUE
# USES_TERMINAL_INSTALL TRUE
# NOTE: setting up WAFLOCK is important to avoid possible race conditions
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
ANDROID_NDK=${ANDROID_NDK}
BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} configure -T ${BUILD_TYPE} --android=${ANDROID_ABI},,${CMAKE_SYSTEM_VERSION}
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --enable-bundled-deps ${WAF_EXTRA_ARGS}
BUILD_COMMAND ${CMAKE_COMMAND} -E env
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} build -v
INSTALL_COMMAND ${CMAKE_COMMAND} -E env
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
${WAF} install --destdir=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
# a1ba: without this, xash3d target will be ignored as nothing depends on it
add_dependencies(client Xash3DFWGS)
add_dependencies(server Xash3DFWGS)

View File

@@ -9,7 +9,7 @@ plugins {
android { android {
namespace = "su.xash.engine" namespace = "su.xash.engine"
ndkVersion = "27.2.12479018" ndkVersion = "28.0.13004108"
defaultConfig { defaultConfig {
applicationId = "su.xash" applicationId = "su.xash"

View File

@@ -21,3 +21,6 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
# Enable verbose output for CMake
android.native.buildOutput=verbose

View File

@@ -86,8 +86,4 @@ GNU General Public License for more details.
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#if defined XASH_SDL && !defined REF_DLL
#include <SDL.h>
#endif
#endif // PORT_H #endif // PORT_H

View File

@@ -13,10 +13,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include <ctype.h>
#include "common.h" #include "common.h"
#include "filesystem.h" #include "filesystem.h"
#include "client.h" #include "client.h"
#include "qfont.h" #include "qfont.h"
#include "utflib.h"
qboolean CL_FixedFont( cl_font_t *font ) qboolean CL_FixedFont( cl_font_t *font )
{ {
@@ -173,31 +175,27 @@ static int CL_CalcTabStop( const cl_font_t *font, int x )
return stop; return stop;
} }
int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_t *font, int flags ) static int CL_DrawBitmapCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags )
{ {
wrect_t *rc; wrect_t *rc;
float w, h; float w, h;
float s1, t1, s2, t2, half = 0.5f; float s1, t1, s2, t2, half = 0.5f;
int texw, texh; int texw, texh;
uint32_t number;
if( !font || !font->valid || y < -font->charHeight ) // bitmap fonts need conversion. Do this and validate the result
if( g_codepage == 1251 )
number = Q_UnicodeToCP1251( uc );
else if( g_codepage == 1252 )
number = Q_UnicodeToCP1252( uc );
else
number = uc;
if( !number || number >= ARRAYSIZE( font->charWidths ))
return 0; return 0;
// check if printable // start rendering
if( number <= 32 ) if( !font->charWidths[number] )
{
if( number == ' ' )
return font->charWidths[' '];
else if( number == '\t' )
return CL_CalcTabStop( font, x );
return 0;
}
if( FBitSet( flags, FONT_DRAW_UTF8 ))
number = Con_UtfProcessChar( number & 255 );
else number &= 255;
if( !number || !font->charWidths[number])
return 0; return 0;
R_GetTextureParms( &texw, &texh, font->hFontTexture ); R_GetTextureParms( &texw, &texh, font->hFontTexture );
@@ -231,29 +229,60 @@ int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_
return font->charWidths[number]; return font->charWidths[number];
} }
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags ) static int CL_DrawTrueTypeCharacter( float x, float y, uint32_t uc, const rgba_t color, cl_font_t *font, int flags )
{
// stub
return 0;
}
int CL_DrawCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags )
{
if( !font || !font->valid || y < -font->charHeight )
return 0;
// check if printable
if( uc <= 32 )
{
if( uc == ' ' )
return font->charWidths[' '];
else if( uc == '\t' )
return CL_CalcTabStop( font, x );
return 0;
}
if( font->type == FONT_TRUETYPE )
return CL_DrawTrueTypeCharacter( x, y, uc, color, font, flags );
return CL_DrawBitmapCharacter( x, y, uc, color, font, flags );
}
int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl_font_t *font, int flags )
{ {
rgba_t current_color; rgba_t current_color;
int draw_len = 0; int draw_len = 0;
utfstate_t utfstate = { 0 };
if( !font || !font->valid ) if( !font || !font->valid )
return 0; return 0;
if( FBitSet( flags, FONT_DRAW_UTF8 ))
Con_UtfProcessChar( 0 ); // clear utf state
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE )) if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
CL_SetFontRendermode( font ); CL_SetFontRendermode( font );
Vector4Copy( color, current_color ); Vector4Copy( color, current_color );
while( *s ) for( ; *s; s++ )
{ {
if( *s == '\n' ) uint32_t uc = (byte)*s;
{
s++;
if( !*s ) if( FBitSet( flags, FONT_DRAW_UTF8 ))
uc = Q_DecodeUTF8( &utfstate, uc );
if( !uc )
continue;
if( uc == '\n' )
{
if( !s[1] ) // ignore newline at end of string if next
break; break;
// some client functions ignore newlines // some client functions ignore newlines
@@ -264,30 +293,29 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_
} }
if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF )) if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF ))
Vector4Copy( color, current_color ); Vector4Copy( color, current_color );
continue; continue;
} }
if( IsColorString( s )) // check for colorstrings
if( uc == '^' && isdigit( s[1] ))
{ {
// don't copy alpha
if( !FBitSet( flags, FONT_DRAW_FORCECOL )) if( !FBitSet( flags, FONT_DRAW_FORCECOL ))
VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color ); VectorCopy( g_color_table[ColorIndex( s[1] )], current_color );
s += 2; s++;
continue; continue;
} }
// skip setting rendermode, it was changed for this string already // skip setting rendermode, it was changed for this string already
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, current_color, font, flags | FONT_DRAW_NORENDERMODE ); draw_len += CL_DrawCharacter( x + draw_len, y, uc, current_color, font, flags | FONT_DRAW_NORENDERMODE );
s++;
} }
return draw_len; return draw_len;
} }
int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... )
{ {
va_list va; va_list va;
char buf[MAX_VA_STRING]; char buf[MAX_VA_STRING];
@@ -299,20 +327,63 @@ int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int f
return CL_DrawString( x, y, buf, color, font, flags ); return CL_DrawString( x, y, buf, color, font, flags );
} }
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height ) static int CL_DrawBitmapCharacterLen( const cl_font_t *font, uint32_t uc )
{ {
if( !font || !font->valid ) return; int number;
if( width )
{ if( g_codepage == 1251 )
if( number == '\t' ) number = Q_UnicodeToCP1251( uc );
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop else if( g_codepage == 1252 )
else *width = font->charWidths[number & 255]; number = Q_UnicodeToCP1252( uc );
} else
if( height ) *height = font->charHeight; number = uc;
if( !number || number >= ARRAYSIZE( font->charWidths ))
return 0;
return font->charWidths[number];
} }
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags ) static int CL_DrawTrueTypeCharacterLen( const cl_font_t *font, uint32_t uc )
{ {
// stub
return 0;
}
void CL_DrawCharacterLen( const cl_font_t *font, uint32_t uc, int *width, int *height )
{
if( !font || !font->valid )
return;
if( height )
*height = font->charHeight;
if( width )
{
// basically matches logic of CL_DrawCharacter
if( uc <= 32 )
{
if( uc == ' ' )
*width = font->charWidths[' '];
else if( uc == '\t' )
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop
else
*width = 0;
}
else if( font->type == FONT_TRUETYPE )
{
*width = CL_DrawTrueTypeCharacterLen( font, uc );
}
else
{
*width = CL_DrawBitmapCharacterLen( font, uc );
}
}
}
void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *height, int flags )
{
utfstate_t utfstate = { 0 };
int draw_len = 0; int draw_len = 0;
if( !font || !font->valid ) if( !font || !font->valid )
@@ -327,54 +398,45 @@ void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height,
if( !COM_CheckString( s )) if( !COM_CheckString( s ))
return; return;
if( FBitSet( flags, FONT_DRAW_UTF8 )) for( ; *s; s++ )
Con_UtfProcessChar( 0 ); // reset utf state
while( *s )
{ {
int number; uint32_t uc = (byte)*s;
int char_width = 0;
if( *s == '\n' ) if( FBitSet( flags, FONT_DRAW_UTF8 ))
uc = Q_DecodeUTF8( &utfstate, uc );
if( !uc )
continue;
if( uc == '\n' )
{ {
// BUG: no check for end string here // BUG: no check for end string here
// but high chances somebody's relying on this // but high chances somebody's relying on this
s++;
draw_len = 0; draw_len = 0;
// some client functions ignore newlines
if( !FBitSet( flags, FONT_DRAW_NOLF )) if( !FBitSet( flags, FONT_DRAW_NOLF ))
{ {
if( height ) if( height )
*height += font->charHeight; *height += font->charHeight;
} }
continue;
} }
else if( *s == '\t' )
// check for colorstrings
if( uc == '^' && isdigit( s[1] ))
{ {
draw_len += CL_CalcTabStop( font, 0 ); // at least return max tabstop
s++; s++;
continue; continue;
} }
if( IsColorString( s )) CL_DrawCharacterLen( font, uc, &char_width, NULL );
draw_len += char_width;
if( width )
{ {
s += 2; if( *width < draw_len )
continue; *width = draw_len;
} }
if( FBitSet( flags, FONT_DRAW_UTF8 ))
number = Con_UtfProcessChar( (byte)*s );
else number = (byte)*s;
if( number )
{
draw_len += font->charWidths[number];
if( width )
{
if( draw_len > *width )
*width = draw_len;
}
}
s++;
} }
} }

View File

@@ -13,6 +13,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#if XASH_SDL
#include <SDL.h> // SDL_GetWindowPosition
#endif // XASH_SDL
#include "common.h" #include "common.h"
#include "client.h" #include "client.h"
#include "const.h" #include "const.h"
@@ -29,6 +33,7 @@ GNU General Public License for more details.
#include "vgui_draw.h" #include "vgui_draw.h"
#include "sound.h" // SND_STOP_LOOPING #include "sound.h" // SND_STOP_LOOPING
#include "platform/platform.h" #include "platform/platform.h"
#include "utflib.h"
#define MAX_LINELENGTH 80 #define MAX_LINELENGTH 80
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels) #define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
@@ -404,8 +409,10 @@ void CL_DrawCenterPrint( void )
char *pText; char *pText;
int i, j, x, y; int i, j, x, y;
int width, lineLength; int width, lineLength;
byte *colorDefault, line[MAX_LINELENGTH]; byte *colorDefault;
uint32_t line[MAX_LINELENGTH];
int charWidth, charHeight; int charWidth, charHeight;
utfstate_t utfstate = { 0 };
if( !clgame.centerPrint.time ) if( !clgame.centerPrint.time )
return; return;
@@ -428,14 +435,19 @@ void CL_DrawCenterPrint( void )
lineLength = 0; lineLength = 0;
width = 0; width = 0;
while( *pText && *pText != '\n' && lineLength < MAX_LINELENGTH ) for( ; *pText && *pText != '\n' && lineLength < MAX_LINELENGTH; pText++ )
{ {
byte c = *pText; byte c = *pText;
line[lineLength] = c; uint32_t uc = Q_DecodeUTF8( &utfstate, c );
CL_DrawCharacterLen( font, c, &charWidth, NULL );
if( !uc )
continue;
line[lineLength] = uc;
CL_DrawCharacterLen( font, uc, &charWidth, NULL );
width += charWidth; width += charWidth;
lineLength++; lineLength++;
pText++;
} }
if( lineLength == MAX_LINELENGTH ) if( lineLength == MAX_LINELENGTH )
@@ -449,7 +461,7 @@ void CL_DrawCenterPrint( void )
for( j = 0; j < lineLength; j++ ) for( j = 0; j < lineLength; j++ )
{ {
if( x >= 0 && y >= 0 && x <= refState.width ) if( x >= 0 && y >= 0 && x <= refState.width )
x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_UTF8 | FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE ); x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE );
} }
y += charHeight; y += charHeight;
} }
@@ -1985,7 +1997,13 @@ static int GAME_EXPORT pfnDrawCharacter( int x, int y, int number, int r, int g,
int flags = FONT_DRAW_HUD; int flags = FONT_DRAW_HUD;
if( hud_utf8.value ) if( hud_utf8.value )
flags |= FONT_DRAW_UTF8; {
static utfstate_t utfstate;
number = Q_DecodeUTF8( &utfstate, number );
if( !number )
return 0;
}
return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags ); return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags );
} }
@@ -3048,12 +3066,8 @@ pfnDrawString
*/ */
static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b ) static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b )
{ {
rgba_t color = { r, g, b, 255 }; const rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF; int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF | FONT_DRAW_UTF8;
if( hud_utf8.value )
SetBits( flags, FONT_DRAW_UTF8 );
return CL_DrawString( x, y, str, color, &cls.creditsFont, flags ); return CL_DrawString( x, y, str, color, &cls.creditsFont, flags );
} }
@@ -3065,13 +3079,10 @@ pfnDrawStringReverse
*/ */
static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b ) static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b )
{ {
rgba_t color = { r, g, b, 255 }; const rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF; int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF | FONT_DRAW_UTF8;
int width; int width;
if( hud_utf8.value )
SetBits( flags, FONT_DRAW_UTF8 );
CL_DrawStringLen( &cls.creditsFont, str, &width, NULL, flags ); CL_DrawStringLen( &cls.creditsFont, str, &width, NULL, flags );
x -= width; x -= width;

View File

@@ -1324,10 +1324,21 @@ static int pfnIsCvarReadOnly( const char *name )
return FBitSet( cv->flags, FCVAR_READ_ONLY ) ? 1 : 0; return FBitSet( cv->flags, FCVAR_READ_ONLY ) ? 1 : 0;
} }
static int GAME_EXPORT pfnUtfProcessChar( int in )
{
// compatibility export, deprecated, do not use
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return in;
// otherwise, decode it and convert to selected codepage
return Con_UtfProcessCharForce( in );
}
static ui_extendedfuncs_t gExtendedfuncs = static ui_extendedfuncs_t gExtendedfuncs =
{ {
pfnEnableTextInput, pfnEnableTextInput,
Con_UtfProcessChar, pfnUtfProcessChar,
Con_UtfMoveLeft, Con_UtfMoveLeft,
Con_UtfMoveRight, Con_UtfMoveRight,
pfnGetRenderers, pfnGetRenderers,

View File

@@ -68,7 +68,7 @@ CVAR_DEFINE_AUTO( hud_scale_minimal_width, "640", FCVAR_ARCHIVE|FCVAR_LATCH, "if
CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" ); CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" );
CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" ); CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" );
CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" ); CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" );
CVAR_DEFINE_AUTO( cl_cmdrate, "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" ); CVAR_DEFINE_AUTO( cl_cmdrate, "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" ); CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" );
CVAR_DEFINE_AUTO( cl_nointerp, "0", 0, "disable interpolation of entities and players" ); CVAR_DEFINE_AUTO( cl_nointerp, "0", 0, "disable interpolation of entities and players" );
static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" ); static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
@@ -94,11 +94,10 @@ static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRIN
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" ); static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" ); static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" ); static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" ); CVAR_DEFINE_AUTO( rate, "25000", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" ); static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" );
client_t cl; client_t cl;
client_static_t cls; client_static_t cls;
clgame_static_t clgame; clgame_static_t clgame;
@@ -1009,7 +1008,7 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
const char *s; const char *s;
uint32_t crc; uint32_t crc;
char buf[768] = { 0 }; // setti and steamemu return 768 char buf[768] = { 0 }; // setti and steamemu return 768
size_t i = sizeof( buf ); int i = sizeof( buf );
if( !Q_strcmp( cl_ticket_generator.string, "null" )) if( !Q_strcmp( cl_ticket_generator.string, "null" ))
{ {
@@ -1028,24 +1027,7 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
CRC32_Init( &crc ); CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, s, Q_strlen( s )); CRC32_ProcessBuffer( &crc, s, Q_strlen( s ));
crc = CRC32_Final( crc ); crc = CRC32_Final( crc );
i = GenerateRevEmu2013( buf, s, crc );
if( !Q_stricmp( cl_ticket_generator.string, "revemu2013" ))
i = GenerateRevEmu2013( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "sc2009" ))
i = GenerateSC2009( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "oldrevemu" ))
i = GenerateOldRevEmu( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "steamemu" ))
i = GenerateSteamEmu( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "revemu" ))
i = GenerateRevEmu( buf, crc );
else if( !Q_stricmp( cl_ticket_generator.string, "setti" ))
i = GenerateSetti( buf );
else if( !Q_stricmp( cl_ticket_generator.string, "avsmp" ))
i = GenerateAVSMP( buf, crc, true );
else
Con_Printf( "%s: unknown generator %s, supported are: null, revemu2003, sc2009, oldrevemu, steamemu, revemu, setti, avsmp\n", __func__, cl_ticket_generator.string );
MSG_WriteBytes( send, buf, i ); MSG_WriteBytes( send, buf, i );
} }
@@ -1183,7 +1165,11 @@ Returns bandwidth test fragment size
*/ */
static int CL_GetTestFragmentSize( void ) static int CL_GetTestFragmentSize( void )
{ {
const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 }; // const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
// it turns out, even if we pass the bandwidth test, it doesn't mean we can use such large fragments
// as a temporary solution, use smaller fragment sizes
const int fragmentSizes[CL_TEST_RETRIES] = { 1400, 1200, 1000, 800, 508 };
if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES ) if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES )
return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE ); return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE );
else else

View File

@@ -19,6 +19,7 @@ GNU General Public License for more details.
#include "library.h" #include "library.h"
#include "input.h" #include "input.h"
#include "platform/platform.h" #include "platform/platform.h"
#include "utflib.h"
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" ); static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" ); static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
@@ -58,7 +59,13 @@ static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b
int flags = FONT_DRAW_HUD; int flags = FONT_DRAW_HUD;
if( hud_utf8.value ) if( hud_utf8.value )
SetBits( flags, FONT_DRAW_UTF8 ); {
static utfstate_t utfstate;
number = Q_DecodeUTF8( &utfstate, number );
if( !number )
return 0;
}
if( fabs( g_font_scale - scale ) > 0.1f || if( fabs( g_font_scale - scale ) > 0.1f ||
g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture ) g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture )

View File

@@ -326,8 +326,12 @@ typedef struct
pfnEventHook func; // user-defined function pfnEventHook func; // user-defined function
} cl_user_event_t; } cl_user_event_t;
#define FONT_FIXED 0 enum
#define FONT_VARIABLE 1 {
FONT_FIXED,
FONT_VARIABLE,
FONT_TRUETYPE
};
#define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale #define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale
#define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar #define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar
@@ -807,11 +811,12 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags ); qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
void CL_FreeFont( cl_font_t *font ); void CL_FreeFont( cl_font_t *font );
void CL_SetFontRendermode( cl_font_t *font ); void CL_SetFontRendermode( cl_font_t *font );
int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_t *font, int flags ); int CL_DrawCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags );
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags ); void CL_DrawCharacterLen( const cl_font_t *font, uint32_t uc, int *width, int *height );
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags ); int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl_font_t *font, int flags );
int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 ); int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *height, int flags );
// //
@@ -1090,6 +1095,7 @@ void CL_ReadLineFile_f( void );
// console.c // console.c
// //
extern convar_t con_fontsize; extern convar_t con_fontsize;
extern int g_codepage;
int Con_Visible( void ); int Con_Visible( void );
qboolean Con_FixedFont( void ); qboolean Con_FixedFont( void );
void Con_VidInit( void ); void Con_VidInit( void );
@@ -1100,7 +1106,6 @@ void Con_DrawDebug( void );
void Con_RunConsole( void ); void Con_RunConsole( void );
void Con_DrawConsole( void ); void Con_DrawConsole( void );
void Con_DrawVersion( void ); void Con_DrawVersion( void );
int Con_UtfProcessChar( int in );
int Con_UtfProcessCharForce( int in ); int Con_UtfProcessCharForce( int in );
int Con_UtfMoveLeft( char *str, int pos ); int Con_UtfMoveLeft( char *str, int pos );
int Con_UtfMoveRight( char *str, int pos, int length ); int Con_UtfMoveRight( char *str, int pos, int length );

View File

@@ -34,7 +34,7 @@ static CVAR_DEFINE_AUTO( con_color, "240 180 24", FCVAR_ARCHIVE, "set a custom c
static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in menu or screenshots, doesn't affect console" ); static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in menu or screenshots, doesn't affect console" );
static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" ); static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" );
static int g_codepage = 0; int g_codepage = 0;
static qboolean g_messagemode_privileged = true; static qboolean g_messagemode_privileged = true;
@@ -632,15 +632,6 @@ int Con_UtfProcessCharForce( int in )
return '?'; // not implemented yet return '?'; // not implemented yet
} }
int GAME_EXPORT Con_UtfProcessChar( int in )
{
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
return in;
// otherwise, decode it and convert to selected codepage
return Con_UtfProcessCharForce( in );
}
/* /*
================= =================
Con_UtfMoveLeft Con_UtfMoveLeft
@@ -1267,45 +1258,16 @@ static void Field_CharEvent( field_t *edit, int ch )
Field_DrawInputLine Field_DrawInputLine
================== ==================
*/ */
static void Field_DrawInputLine( int x, int y, field_t *edit ) static void Field_DrawInputLine( int x, int y, const field_t *edit )
{ {
int len, cursorChar; int curPos;
int drawLen; char str[MAX_SYSPATH];
int prestep, curPos; const byte *colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
char str[MAX_SYSPATH]; const int prestep = bound( 0, edit->scroll, sizeof( edit->buffer ) - 1 );
byte *colorDefault; const int drawLen = bound( 0, edit->widthInChars, sizeof( str ));
const int cursorCharPos = bound( 0, edit->cursor - prestep, sizeof( str ));
drawLen = edit->widthInChars; Q_strncpy( str, edit->buffer + prestep, drawLen );
len = Q_strlen( edit->buffer ) + 1;
colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
// guarantee that cursor will be visible
if( len <= drawLen )
{
prestep = 0;
}
else
{
if( edit->scroll + drawLen > len )
{
edit->scroll = len - drawLen;
if( edit->scroll < 0 ) edit->scroll = 0;
}
prestep = edit->scroll;
}
if( prestep + drawLen > len )
drawLen = len - prestep;
// extract <drawLen> characters from the field at <prestep>
drawLen = Q_min( drawLen, MAX_SYSPATH - 1 );
memcpy( str, edit->buffer + prestep, drawLen );
str[drawLen] = 0;
// save char for overstrike
cursorChar = str[edit->cursor - prestep];
// draw it // draw it
CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 ); CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
@@ -1314,7 +1276,7 @@ static void Field_DrawInputLine( int x, int y, field_t *edit )
if((int)( host.realtime * 4 ) & 1 ) return; // off blink if((int)( host.realtime * 4 ) & 1 ) return; // off blink
// calc cursor position // calc cursor position
str[edit->cursor - prestep] = 0; str[cursorCharPos] = 0;
CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 ); CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
if( host.key_overstrike ) if( host.key_overstrike )
@@ -2031,7 +1993,7 @@ void Con_DrawVersion( void )
int start, height = refState.height; int start, height = refState.height;
string curbuild; string curbuild;
if( !scr_drawversion.value || CL_IsDevOverviewMode() == 2 || net_graph.value ) if( !scr_drawversion.value )
return; return;
if( cls.key_dest == key_menu ) if( cls.key_dest == key_menu )
@@ -2043,6 +2005,9 @@ void Con_DrawVersion( void )
{ {
qboolean draw_version; qboolean draw_version;
if( CL_IsDevOverviewMode() == 2 || net_graph.value )
return;
draw_version = cls.scrshot_action == scrshot_normal draw_version = cls.scrshot_action == scrshot_normal
|| cls.scrshot_action == scrshot_snapshot || cls.scrshot_action == scrshot_snapshot
|| host.force_draw_version_time > host.realtime; || host.force_draw_version_time > host.realtime;

View File

@@ -18,6 +18,7 @@ GNU General Public License for more details.
#include "math.h" #include "math.h"
#include "vgui_draw.h" #include "vgui_draw.h"
#include "mobility_int.h" #include "mobility_int.h"
#include "utflib.h"
typedef enum typedef enum
{ {
@@ -761,7 +762,7 @@ static void Touch_SetCommand_f( void )
{ {
touch_button_t *button = Touch_FindButtonNoPattern( &touch.list_user, Cmd_Argv( 1 ), Cmd_CurrentCommandIsPrivileged( )); touch_button_t *button = Touch_FindButtonNoPattern( &touch.list_user, Cmd_Argv( 1 ), Cmd_CurrentCommandIsPrivileged( ));
if( !button ) if( button )
Touch_SetCommand( button, Cmd_Argv( 2 ) ); Touch_SetCommand( button, Cmd_Argv( 2 ) );
else else
Con_Printf( S_ERROR "no such button" ); Con_Printf( S_ERROR "no such button" );
@@ -938,7 +939,7 @@ static void Touch_AddButton_f( void )
// to let imagelib choose better format // to let imagelib choose better format
// //
// Remove this when old engine migration would be done // Remove this when old engine migration would be done
if( Q_stricmp( COM_FileExtension( texture ), "tga" )) if( !Q_stricmp( COM_FileExtension( texture ), "tga" ))
COM_StripExtension( texture ); COM_StripExtension( texture );
if( Cmd_Argc( ) >= 8 ) if( Cmd_Argc( ) >= 8 )
@@ -1180,14 +1181,6 @@ void Touch_Init( void )
Cvar_RegisterVariable( &touch_enable ); Cvar_RegisterVariable( &touch_enable );
Cvar_RegisterVariable( &touch_emulate ); Cvar_RegisterVariable( &touch_emulate );
// TODO: touch platform
#if SDL_VERSION_ATLEAST( 2, 0, 10 )
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
#elif defined( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH )
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
#endif
touch.initialized = true; touch.initialized = true;
} }
@@ -1306,73 +1299,62 @@ static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 )
} }
} }
static float Touch_DrawCharacter( float x, float y, int number, float size ) static void Touch_DrawText( float x1, float y1, float x2, float y2, const char *s, byte *color, float size )
{ {
float s1, s2, t1, t2, width, height; float minx, maxy, maxx;
int w, h; const float scale = TO_SCRN_X( size / 1024.0f );
wrect_t *prc; const float backup_scale = cls.creditsFont.scale;
utfstate_t utfstate = { 0 };
rgba_t current_color;
if( !cls.creditsFont.valid ) if( !cls.creditsFont.valid )
return 0; return;
number &= 255; x1 = TO_SCRN_X( x1 );
number = Con_UtfProcessChar( number ); y1 = TO_SCRN_Y( y1 );
x2 = TO_SCRN_X( x2 );
y2 = TO_SCRN_Y( y2 );
if( !number ) minx = x1;
return 0; maxy = y2;
R_GetTextureParms( &w, &h, cls.creditsFont.hFontTexture );
prc = &cls.creditsFont.fontRc[number];
s1 = prc->left / (float)w;
t1 = prc->top / (float)h;
s2 = prc->right / (float)w;
t2 = prc->bottom / (float)h;
width = ( prc->right - prc->left ) / 1024.0f * size;
height = ( prc->bottom - prc->top ) / 1024.0f * size;
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( x ), TO_SCRN_Y( y ), TO_SCRN_X( width ), TO_SCRN_X( height ),
s1, t1, s2, t2, cls.creditsFont.hFontTexture );
return width;
}
static float Touch_DrawText( float x1, float y1, float x2, float y2, const char *s, byte *color, float size )
{
float x = x1;
float maxy = y2;
float maxx;
float alpha = color[3] / 255.0f;
if( x2 ) if( x2 )
maxx = x2 - cls.creditsFont.charWidths['M'] / 1024.0f * size; maxx = x2 - cls.creditsFont.charWidths['M'] * scale;
else else
maxx = 1; maxx = 1;
if( !cls.creditsFont.valid ) cls.creditsFont.scale = scale;
return GRID_X * 2;
Con_UtfProcessChar( 0 );
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
// text is additive and alpha does not work // text is additive and alpha does not work
ref.dllFuncs.Color4ub( color[0] * alpha, color[1] * alpha, color[2] * alpha, 255 ); ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
VectorScale( color, color[3] / 255.0f, current_color );
current_color[3] = 255;
while( *s ) for( ; *s; s++ )
{ {
while( *s && ( *s != '\n' ) && ( *s != ';' ) && ( x1 < maxx )) int draw_len;
x1 += Touch_DrawCharacter( x1, y1, *s++, size ); uint32_t uc = Q_DecodeUTF8( &utfstate, (byte)*s );
y1 += cls.creditsFont.charHeight / 1024.f * size / Touch_AspectRatio();
if( y1 >= maxy ) if( !uc )
break; continue;
if( *s == '\n' || *s == ';' ) if( uc == '\n' || uc == ';' || x1 >= maxx )
s++; {
x1 = x; x1 = minx;
y1 += cls.creditsFont.charHeight * scale;
if( y1 >= maxy )
break;
continue;
}
// because we override font scale without changing charWidths, scale it ourselves
draw_len = CL_DrawCharacter( x1, y1, uc, current_color, &cls.creditsFont, FONT_DRAW_NORENDERMODE );
x1 += draw_len * scale;
} }
return x1;
cls.creditsFont.scale = backup_scale;
} }
static void Touch_DrawButtons( touchbuttonlist_t *list ) static void Touch_DrawButtons( touchbuttonlist_t *list )

View File

@@ -205,9 +205,10 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
} }
} }
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose ) void IN_SetRelativeMouseMode( qboolean set )
{ {
static qboolean s_bRawInput; static qboolean s_bRawInput;
qboolean verbose = m_grab_debug.value ? true : false;
if( set && !s_bRawInput ) if( set && !s_bRawInput )
{ {
@@ -231,9 +232,10 @@ static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
} }
} }
static void IN_SetMouseGrab( qboolean set, qboolean verbose ) void IN_SetMouseGrab( qboolean set )
{ {
static qboolean s_bMouseGrab; static qboolean s_bMouseGrab;
qboolean verbose = m_grab_debug.value ? true : false;
if( set && !s_bMouseGrab ) if( set && !s_bMouseGrab )
{ {
@@ -258,7 +260,7 @@ static void IN_SetMouseGrab( qboolean set, qboolean verbose )
static void IN_CheckMouseState( qboolean active ) static void IN_CheckMouseState( qboolean active )
{ {
qboolean use_raw_input, verbose; qboolean use_raw_input;
#if XASH_WIN32 #if XASH_WIN32
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL; use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
@@ -266,20 +268,18 @@ static void IN_CheckMouseState( qboolean active )
use_raw_input = true; // always use SDL code use_raw_input = true; // always use SDL code
#endif #endif
verbose = m_grab_debug.value ? true : false;
if( m_ignore.value ) if( m_ignore.value )
active = false; active = false;
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active ) if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
IN_SetRelativeMouseMode( true, verbose ); IN_SetRelativeMouseMode( true );
else else
IN_SetRelativeMouseMode( false, verbose ); IN_SetRelativeMouseMode( false );
if( active && !host.mouse_visible && cls.state == ca_active ) if( active && !host.mouse_visible && cls.state == ca_active )
IN_SetMouseGrab( true, verbose ); IN_SetMouseGrab( true );
else else
IN_SetMouseGrab( false, verbose ); IN_SetMouseGrab( false );
} }
/* /*

View File

@@ -46,6 +46,9 @@ uint IN_CollectInputDevices( void );
void IN_LockInputDevices( qboolean lock ); void IN_LockInputDevices( qboolean lock );
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active ); void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
void IN_SetRelativeMouseMode( qboolean set );
void IN_SetMouseGrab( qboolean set );
extern convar_t m_yaw; extern convar_t m_yaw;
extern convar_t m_pitch; extern convar_t m_pitch;
// //

View File

@@ -957,6 +957,7 @@ enum
OSK_ENTER, OSK_ENTER,
OSK_SPECKEY_LAST OSK_SPECKEY_LAST
}; };
static const char *osk_keylayout[][4] = static const char *osk_keylayout[][4] =
{ {
{ {
@@ -973,7 +974,7 @@ static const char *osk_keylayout[][4] =
} }
}; };
struct osk_s static struct osk_s
{ {
qboolean enable; qboolean enable;
int curlayout; int curlayout;
@@ -1007,7 +1008,6 @@ static qboolean OSK_KeyEvent( int key, int down )
return false; return false;
} }
switch ( key ) switch ( key )
{ {
case K_ENTER: case K_ENTER:
@@ -1050,10 +1050,6 @@ static qboolean OSK_KeyEvent( int key, int down )
ch = (byte)osk.curbutton.val; ch = (byte)osk.curbutton.val;
// do not pass UTF-8 sequence into the engine, convert it here
if( !cls.accept_utf8 )
ch = Con_UtfProcessCharForce( ch );
if( !ch ) if( !ch )
break; break;
@@ -1188,13 +1184,15 @@ void OSK_Draw( void )
X_STEP * MAX_OSK_ROWS * refState.width, X_STEP * MAX_OSK_ROWS * refState.width,
Y_STEP * MAX_OSK_LINES * refState.height, 100, 100, 100, 100 ); Y_STEP * MAX_OSK_LINES * refState.height, 100, 100, 100, 100 );
OSK_DrawSpecialButton( "-]", X_START, Y_START + Y_STEP * 2, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "-]", X_START, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
OSK_DrawSpecialButton( "<-", X_START + X_STEP * 12, Y_START + Y_STEP * 2, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "<-", X_START + X_STEP * 12, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
OSK_DrawSpecialButton( "sh", X_START, Y_START + Y_STEP * 3, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "sh", X_START, Y_START + Y_STEP * 3, X_STEP, Y_STEP );
OSK_DrawSpecialButton( "en", X_START + X_STEP * 12, Y_START + Y_STEP * 3, X_STEP, Y_STEP ); OSK_DrawSpecialButton( "en", X_START + X_STEP * 12, Y_START + Y_STEP * 3, X_STEP, Y_STEP );
for( y = Y_START, j = 0; j < MAX_OSK_LINES; j++, y += Y_STEP ) for( y = Y_START, j = 0; j < MAX_OSK_LINES; j++, y += Y_STEP )
{
for( x = X_START, i = 0; i < MAX_OSK_ROWS; i++, x += X_STEP ) for( x = X_START, i = 0; i < MAX_OSK_ROWS; i++, x += X_STEP )
OSK_DrawSymbolButton( curlayout[j][i], x, y, X_STEP, Y_STEP ); OSK_DrawSymbolButton( curlayout[j][i], x, y, X_STEP, Y_STEP );
}
} }

View File

@@ -16,6 +16,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#if XASH_SDL
#include <SDL.h> // SDL_GetBasePath
#endif
#include <errno.h> #include <errno.h>
#include "common.h" #include "common.h"
#include "library.h" #include "library.h"

View File

@@ -1236,6 +1236,14 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit); Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit);
Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY ); Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY );
Cvar_Get( "host_hl25_extended_structs",
#if SUPPORT_HL25_EXTENDED_STRUCTS
"1",
#else
"0",
#endif
FCVAR_READ_ONLY, "indicates if engine was compiled with extended msurface_t struct" );
Mod_Init(); Mod_Init();
NET_Init(); NET_Init();
NET_InitMasters(); NET_InitMasters();

View File

@@ -844,7 +844,16 @@ static int HTTP_FileProcessStream( httpfile_t *curfile )
if( curfile->downloaded >= curfile->size ) if( curfile->downloaded >= curfile->size )
{ {
HTTP_FreeFile( curfile, false ); // success // chunked files are finalized in FileSaveReceivedData
if( curfile->compressed && !curfile->chunked )
{
curfile->pfn_process = HTTP_FileDecompress;
curfile->success = true;
}
else
{
HTTP_FreeFile( curfile, false ); // success
}
return 0; return 0;
} }
} }

View File

@@ -2027,6 +2027,7 @@ void NET_Init( void )
Cvar_RegisterVariable( &net_fakelag ); Cvar_RegisterVariable( &net_fakelag );
Cvar_RegisterVariable( &net_fakeloss ); Cvar_RegisterVariable( &net_fakeloss );
Cvar_RegisterVariable( &net_resolve_debug ); Cvar_RegisterVariable( &net_resolve_debug );
Cvar_RegisterVariable( &net_clockwindow );
Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER ); Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER );
Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY ); Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY );

View File

@@ -142,17 +142,10 @@ static qboolean vsync;
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
// disable VSync while level is loading if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
if( cls.state < ca_active )
{ {
// setup vsync here ClearBits( gl_vsync.flags, FCVAR_CHANGED );
vsync = false; vsync = gl_vsync.value;
SetBits( gl_vsync->flags, FCVAR_CHANGED );
}
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
{
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
vsync = true;
} }
} }

View File

@@ -161,17 +161,10 @@ void* GL_GetProcAddress( const char *name ) // RenderAPI requirement
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
// disable VSync while level is loading if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
if( cls.state < ca_active )
{
// setup fb vsync here
fb.vsync = false;
SetBits( gl_vsync.flags, FCVAR_CHANGED );
}
else if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
{ {
ClearBits( gl_vsync.flags, FCVAR_CHANGED ); ClearBits( gl_vsync.flags, FCVAR_CHANGED );
fb.vsync = true; fb.vsync = gl_vsync.value;
} }
} }

View File

@@ -31,6 +31,7 @@ GNU General Public License for more details.
============================================================================== ==============================================================================
*/ */
double Platform_DoubleTime( void ); double Platform_DoubleTime( void );
void Platform_Sleep( int msec );
void Platform_ShellExecute( const char *path, const char *parms ); void Platform_ShellExecute( const char *path, const char *parms );
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow ); void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow );
void Platform_SetStatus( const char *status ); void Platform_SetStatus( const char *status );
@@ -168,19 +169,6 @@ static inline void Platform_SetupSigtermHandling( void )
#endif #endif
} }
static inline void Platform_Sleep( int msec )
{
#if XASH_TIMER == TIMER_SDL
SDL_Delay( msec );
#elif XASH_TIMER == TIMER_POSIX
usleep( msec * 1000 );
#elif XASH_TIMER == TIMER_WIN32
Sleep( msec );
#else
// stub
#endif
}
static inline qboolean Platform_NanoSleep( int nsec ) static inline qboolean Platform_NanoSleep( int nsec )
{ {
// SDL2 doesn't have nanosleep, so use low-level functions here // SDL2 doesn't have nanosleep, so use low-level functions here

View File

@@ -17,9 +17,10 @@ GNU General Public License for more details.
// have backtrace() and backtrace_symbols() calls, which replace for us // have backtrace() and backtrace_symbols() calls, which replace for us
// platform-specific code // platform-specific code
#if HAVE_EXECINFO #if HAVE_EXECINFO
#include "common.h"
#include <execinfo.h> #include <execinfo.h>
#include <signal.h> #include <signal.h>
#include "common.h"
#include "input.h"
void Sys_Crash( int signal, siginfo_t *si, void *context ) void Sys_Crash( int signal, siginfo_t *si, void *context )
{ {
@@ -70,8 +71,8 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
// put MessageBox as Sys_Error // put MessageBox as Sys_Error
Msg( "%s\n", message ); Msg( "%s\n", message );
#ifdef XASH_SDL #if !XASH_DEDICATED
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.crashed = true;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );

View File

@@ -17,7 +17,7 @@ GNU General Public License for more details.
#include <signal.h> #include <signal.h>
#include "common.h" #include "common.h"
#include "backtrace.h" #include "backtrace.h"
#include "input.h"
static struct backtrace_state *g_bt_state; static struct backtrace_state *g_bt_state;
static qboolean enable_libbacktrace; static qboolean enable_libbacktrace;
@@ -111,8 +111,10 @@ static int Sys_BacktracePrintFull( void *data, uintptr_t pc, const char *filenam
module_name = dlinfo.dli_fname; module_name = dlinfo.dli_fname;
else module_name = NULL; else module_name = NULL;
if( filename && lineno && function ) if( filename && lineno >= 0 && function )
{ {
filename = COM_FileWithoutPath( filename );
if( module_name ) if( module_name )
Sys_AppendPrint( pd, "%2d: %s (%s:%d) (%s)\n", pd->idx++, function, filename, lineno, module_name ); Sys_AppendPrint( pd, "%2d: %s (%s:%d) (%s)\n", pd->idx++, function, filename, lineno, module_name );
else else
@@ -162,8 +164,8 @@ void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context )
// put MessageBox as Sys_Error // put MessageBox as Sys_Error
Msg( "%s\n", message ); Msg( "%s\n", message );
#ifdef XASH_SDL #if !XASH_DEDICATED
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.crashed = true;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );

View File

@@ -26,6 +26,7 @@ GNU General Public License for more details.
#include <signal.h> #include <signal.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "library.h" #include "library.h"
#include "input.h"
void Sys_Crash( int signal, siginfo_t *si, void *context ); void Sys_Crash( int signal, siginfo_t *si, void *context );
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context ); void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context );
@@ -192,8 +193,8 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
// put MessageBox as Sys_Error // put MessageBox as Sys_Error
Msg( "%s\n", message ); Msg( "%s\n", message );
#ifdef XASH_SDL #if !XASH_DEDICATED
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); IN_SetMouseGrab( false );
#endif #endif
host.crashed = true; host.crashed = true;
Platform_MessageBox( "Xash Error", message, false ); Platform_MessageBox( "Xash Error", message, false );

View File

@@ -174,5 +174,10 @@ double Platform_DoubleTime( void )
#endif #endif
return (double) ts.tv_sec + (double) ts.tv_nsec/1000000000.0; return (double) ts.tv_sec + (double) ts.tv_nsec/1000000000.0;
} }
void Platform_Sleep( int msec )
{
usleep( msec * 1000 );
}
#endif // XASH_TIMER == TIMER_POSIX #endif // XASH_TIMER == TIMER_POSIX

View File

@@ -32,6 +32,11 @@ double Platform_DoubleTime( void )
CurrentTime = SDL_GetPerformanceCounter(); CurrentTime = SDL_GetPerformanceCounter();
return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency ); return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );
} }
void Platform_Sleep( int msec )
{
SDL_Delay( msec );
}
#endif // XASH_TIMER == TIMER_SDL #endif // XASH_TIMER == TIMER_SDL
#if XASH_MESSAGEBOX == MSGBOX_SDL #if XASH_MESSAGEBOX == MSGBOX_SDL
@@ -109,8 +114,11 @@ void SDLash_Init( const char *basedir )
host.type = HOST_DEDICATED; host.type = HOST_DEDICATED;
} }
#if XASH_SDL == 2 #if SDL_MAJOR_VERSION >= 2
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); SDL_SetHint( SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0" );
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
SDL_StopTextInput(); SDL_StopTextInput();
#endif // XASH_SDL == 2 #endif // XASH_SDL == 2

View File

@@ -488,13 +488,7 @@ GL_UpdateSwapInterval
void GL_UpdateSwapInterval( void ) void GL_UpdateSwapInterval( void )
{ {
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
// disable VSync while level is loading if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
if( cls.state < ca_active )
{
SDL_GL_SetSwapInterval( 0 );
SetBits( gl_vsync.flags, FCVAR_CHANGED );
}
else if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
{ {
ClearBits( gl_vsync.flags, FCVAR_CHANGED ); ClearBits( gl_vsync.flags, FCVAR_CHANGED );

View File

@@ -14,11 +14,15 @@ GNU General Public License for more details.
*/ */
#include "platform/platform.h" #include "platform/platform.h"
#include "input.h"
#define DBGHELP 1 // we always enable dbghelp.dll on Windows targets #define DBGHELP 1 // we always enable dbghelp.dll on Windows targets
#if DBGHELP #if XASH_SDL
#include <SDL.h>
#endif // XASH_SDL
#if DBGHELP
#include <winnt.h> #include <winnt.h>
#include <dbghelp.h> #include <dbghelp.h>
#include <psapi.h> #include <psapi.h>
@@ -268,8 +272,8 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
// check to avoid recursive call // check to avoid recursive call
host.crashed = true; host.crashed = true;
#ifdef XASH_SDL #if !XASH_DEDICATED
SDL_SetWindowGrab( host.hWnd, SDL_FALSE ); IN_SetMouseGrab( false );
#endif // XASH_SDL #endif // XASH_SDL
#if DBGHELP #if DBGHELP

View File

@@ -36,6 +36,11 @@ double Platform_DoubleTime( void )
return (double)( CurrentTime.QuadPart - g_ClockStart.QuadPart ) / (double)( g_PerformanceFrequency.QuadPart ); return (double)( CurrentTime.QuadPart - g_ClockStart.QuadPart ) / (double)( g_PerformanceFrequency.QuadPart );
} }
void Platform_Sleep( int msec )
{
Sleep( msec );
}
#endif // XASH_TIMER == TIMER_WIN32 #endif // XASH_TIMER == TIMER_WIN32
void Win32_Init( qboolean con_showalways ) void Win32_Init( qboolean con_showalways )

View File

@@ -205,69 +205,62 @@ typedef struct
typedef struct sv_client_s typedef struct sv_client_s
{ {
cl_state_t state; cl_state_t state;
cl_upload_t upstate; // uploading state cl_upload_t upstate; // uploading state
char name[32]; // extracted from userinfo, color string allowed char name[32]; // extracted from userinfo, color string allowed
uint flags; // client flags, some info uint flags; // client flags, some info
CRC32_t crcValue; uint extensions; // protocol extensions
char userinfo[MAX_INFO_STRING]; // name, etc (received from client) char hashedcdkey[34]; // MD5 hash is 32 hex #'s, plus trailing 0
char physinfo[MAX_INFO_STRING]; // set on server (transmit to client) char userinfo[MAX_INFO_STRING]; // name, etc (received from client)
char physinfo[MAX_INFO_STRING]; // set on server (transmit to client)
char useragent[MAX_INFO_STRING];
netchan_t netchan; byte ignorecmdtime_warned; // did we warn our server operator in the log for this batch of commands?
int chokecount; // number of messages rate supressed byte m_bLoopback; // does this client want to hear his own voice?
int delta_sequence; // -1 = no compression. uint listeners; // which other clients does this guy's voice stream go to?
double next_messagetime; // time when we should send next world state update
double next_checkpingtime; // time to send all players pings to client
double next_sendinfotime; // time to send info about all players
double cl_updaterate; // client requested updaterate
double timebase; // client timebase
double connection_started;
char hashedcdkey[34]; // MD5 hash is 32 hex #'s, plus trailing 0
customization_t customdata; // player customization linked list
resource_t resourcesonhand;
resource_t resourcesneeded; // <mapname.res> from client (server downloading)
usercmd_t lastcmd; // for filling in big drops
double connecttime;
double cmdtime;
double ignorecmdtime;
int packet_loss;
float latency;
int ignored_ents; // if visibility list is full we should know how many entities will be ignored
edict_t *edict; // EDICT_NUM(clientnum+1)
edict_t *pViewEntity; // svc_setview member
edict_t *viewentity[MAX_VIEWENTS]; // list of portal cameras in player PVS
int num_viewents; // num of portal cameras that can merge PVS
qboolean m_bLoopback; // Does this client want to hear his own voice?
uint listeners; // which other clients does this guy's voice stream go to?
// the datagram is written to by sound calls, prints, temp ents, etc.
// it can be harmlessly overflowed.
sizebuf_t datagram;
byte datagram_buf[MAX_DATAGRAM];
client_frame_t *frames; // updates can be delta'd from here
event_state_t events; // delta-updated events cycle
int challenge; // challenge of this user, randomly generated
int userid; // identifying number on server
int extensions;
char useragent[MAX_INFO_STRING];
int ignorecmdtime_warns; // how many times client time was faster than server during this session int ignorecmdtime_warns; // how many times client time was faster than server during this session
qboolean ignorecmdtime_warned; // did we warn our server operator in the log for this batch of commands? int userid; // identifying number on server
netchan_t netchan;
sizebuf_t datagram; // the datagram is written to by sound calls, prints, temp ents, etc.
byte datagram_buf[MAX_DATAGRAM]; // it can be harmlessly overflowed.
int chokecount; // number of messages rate supressed
int delta_sequence; // -1 = no compression.
double next_messagetime; // time when we should send next world state update
double next_checkpingtime; // time to send all players pings to client
double next_sendinfotime; // time to send info about all players
double cl_updaterate; // client requested updaterate
double timebase; // client timebase
double connection_started;
customization_t customdata; // player customization linked list
resource_t resourcesonhand;
resource_t resourcesneeded; // <mapname.res> from client (server downloading)
usercmd_t lastcmd; // for filling in big drops
int packet_loss;
double connecttime;
double cmdtime;
double ignorecmdtime;
float latency;
int ignored_ents; // if visibility list is full we should know how many entities will be ignored
edict_t *edict; // EDICT_NUM(clientnum+1)
edict_t *pViewEntity; // svc_setview member
edict_t *viewentity[MAX_VIEWENTS]; // list of portal cameras in player PVS
int num_viewents; // num of portal cameras that can merge PVS
int userinfo_change_attempts;
double fullupdate_next_calltime; double fullupdate_next_calltime;
double userinfo_next_changetime; double userinfo_next_changetime;
double userinfo_penalty; double userinfo_penalty;
int userinfo_change_attempts;
client_frame_t *frames; // updates can be delta'd from here
event_state_t events; // delta-updated events cycle
} sv_client_t; } sv_client_t;
/* /*

View File

@@ -277,6 +277,25 @@ static sv_client_t *SV_FindEmptySlot( void )
return NULL; return NULL;
} }
static void SV_MaybeNotifyPlayerCountChange( const sv_client_t *cl, const char *address )
{
int i, count = 0;
// if this was the first client on the server, or the last client
// the server can hold, send a heartbeat to the master.
for( i = 0; i < svs.maxclients; i++ )
{
if( svs.clients[i].state >= cs_connected )
count++;
}
if( count == 1 || count == svs.maxclients )
NET_MasterClear();
Log_Printf( "\"%s<%i><%i><>\" connected, address \"%s\"\n",
cl->name, cl->userid, (int)( cl - svs.clients ), address );
}
/* /*
================== ==================
SV_ConnectClient SV_ConnectClient
@@ -288,9 +307,10 @@ static void SV_ConnectClient( netadr_t from )
{ {
char userinfo[MAX_INFO_STRING]; char userinfo[MAX_INFO_STRING];
char protinfo[MAX_INFO_STRING]; char protinfo[MAX_INFO_STRING];
client_frame_t *frames;
sv_client_t *newcl = NULL; sv_client_t *newcl = NULL;
int qport, version; int qport, version;
int i, count = 0; int i;
int challenge; int challenge;
const char *s; const char *s;
int extensions; int extensions;
@@ -335,12 +355,6 @@ static void SV_ConnectClient( netadr_t from )
if( !SV_ProcessUserAgent( from, protinfo )) if( !SV_ProcessUserAgent( from, protinfo ))
return; return;
if( Q_strlen( Info_ValueForKey( protinfo, "uuid" )) != 32 )
{
SV_RejectConnection( from, "invalid authentication certificate length\n" );
return;
}
// extract qport from protocol info // extract qport from protocol info
qport = Q_atoi( Info_ValueForKey( protinfo, "qport" )); qport = Q_atoi( Info_ValueForKey( protinfo, "qport" ));
extensions = Q_atoi( Info_ValueForKey( protinfo, "ext" )); extensions = Q_atoi( Info_ValueForKey( protinfo, "ext" ));
@@ -397,20 +411,20 @@ static void SV_ConnectClient( netadr_t from )
// build a new connection // build a new connection
// accept the new client // accept the new client
sv.current_client = newcl; sv.current_client = newcl;
frames = Mem_Realloc( host.mempool, newcl->frames, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
memset( frames, 0, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
SV_ClearResourceLists( newcl );
memset( newcl, 0, sizeof( *newcl ));
newcl->edict = EDICT_NUM(( newcl - svs.clients ) + 1 ); newcl->edict = EDICT_NUM(( newcl - svs.clients ) + 1 );
newcl->challenge = challenge; // save challenge for checksumming newcl->frames = frames;
newcl->frames = (client_frame_t *)Mem_Realloc( host.mempool, newcl->frames, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
memset( newcl->frames, 0, sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
newcl->userid = g_userid++; // create unique userid newcl->userid = g_userid++; // create unique userid
newcl->state = cs_connected; newcl->state = cs_connected;
newcl->extensions = extensions & (NET_EXT_SPLITSIZE); newcl->extensions = FBitSet( extensions, NET_EXT_SPLITSIZE );
Q_strncpy( newcl->useragent, protinfo, sizeof( newcl->useragent )); Q_strncpy( newcl->useragent, protinfo, sizeof( newcl->useragent ));
// reset viewentities (from previous level)
memset( newcl->viewentity, 0, sizeof( newcl->viewentity ));
newcl->num_viewents = 0;
// HACKHACK: can hear all players by default to avoid issues // HACKHACK: can hear all players by default to avoid issues
// with server.dll without voice game manager // with server.dll without voice game manager
newcl->listeners = -1; newcl->listeners = -1;
@@ -435,47 +449,18 @@ static void SV_ConnectClient( netadr_t from )
newcl->connection_started = host.realtime; newcl->connection_started = host.realtime;
newcl->cl_updaterate = 0.05; // 20 fps as default newcl->cl_updaterate = 0.05; // 20 fps as default
newcl->delta_sequence = -1; newcl->delta_sequence = -1;
newcl->flags = 0;
// reset any remaining events
memset( &newcl->events, 0, sizeof( newcl->events ));
// parse some info from the info strings (this can override cl_updaterate) // parse some info from the info strings (this can override cl_updaterate)
Q_strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo )); Q_strncpy( newcl->userinfo, userinfo, sizeof( newcl->userinfo ));
newcl->fullupdate_next_calltime = 0;
newcl->userinfo_next_changetime = 0;
newcl->userinfo_penalty = 0;
newcl->userinfo_change_attempts = 0;
SV_UserinfoChanged( newcl ); SV_UserinfoChanged( newcl );
SV_ClearResourceLists( newcl );
#if 0
memset( &newcl->resourcesneeded, 0, sizeof( resource_t ));
memset( &newcl->resourcesonhand, 0, sizeof( resource_t ));
newcl->resourcesneeded.pNext = newcl->resourcesneeded.pPrev = &newcl->resourcesneeded;
newcl->resourcesonhand.pNext = newcl->resourcesonhand.pPrev = &newcl->resourcesonhand;
#endif
newcl->next_messagetime = host.realtime + newcl->cl_updaterate; newcl->next_messagetime = host.realtime + newcl->cl_updaterate;
newcl->next_sendinfotime = 0.0;
newcl->ignored_ents = 0;
newcl->chokecount = 0;
// reset stats // reset stats
newcl->next_checkpingtime = -1.0; newcl->next_checkpingtime = -1.0;
newcl->packet_loss = 0;
// if this was the first client on the server, or the last client SV_MaybeNotifyPlayerCountChange( newcl, NET_AdrToString( newcl->netchan.remote_address ));
// the server can hold, send a heartbeat to the master.
for( i = 0; i < svs.maxclients; i++ )
{
if( svs.clients[i].state >= cs_connected )
count++;
}
Log_Printf( "\"%s<%i><%i><>\" connected, address \"%s\"\n", newcl->name, newcl->userid, i, NET_AdrToString( newcl->netchan.remote_address ));
if( count == 1 || count == svs.maxclients )
NET_MasterClear();
} }
/* /*
@@ -487,25 +472,21 @@ A connection request that came from the game module
*/ */
edict_t *GAME_EXPORT SV_FakeConnect( const char *netname ) edict_t *GAME_EXPORT SV_FakeConnect( const char *netname )
{ {
char userinfo[MAX_INFO_STRING]; char userinfo[MAX_INFO_STRING];
int i, count = 0; int i, count = 0;
sv_client_t *cl; sv_client_t *cl;
if( !COM_CheckString( netname ))
netname = "Bot";
// find a client slot // find a client slot
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ ) cl = SV_FindEmptySlot();
{
if( cl->state == cs_free )
break;
}
if( i == svs.maxclients ) if( !cl )
return NULL; // server is full return NULL; // server is full
userinfo[0] = '\0'; userinfo[0] = '\0';
if( !COM_CheckString( netname ))
netname = "Bot";
// setup fake client params // setup fake client params
Info_SetValueForKey( userinfo, "name", netname, sizeof( userinfo )); Info_SetValueForKey( userinfo, "name", netname, sizeof( userinfo ));
Info_SetValueForKey( userinfo, "model", "gordon", sizeof( userinfo )); Info_SetValueForKey( userinfo, "model", "gordon", sizeof( userinfo ));
@@ -515,34 +496,26 @@ edict_t *GAME_EXPORT SV_FakeConnect( const char *netname )
// build a new connection // build a new connection
// accept the new client // accept the new client
sv.current_client = cl; sv.current_client = cl;
if( cl->frames )
Mem_Free( cl->frames ); // fakeclients doesn't have frames
SV_ClearResourceLists( cl );
if( cl->frames ) Mem_Free( cl->frames ); // fakeclients doesn't have frames memset( cl, 0, sizeof( *cl ));
memset( cl, 0, sizeof( sv_client_t ));
cl->edict = EDICT_NUM( (cl - svs.clients) + 1 ); cl->state = cs_spawned;
cl->userid = g_userid++; // create unique userid cl->edict = EDICT_NUM(( cl - svs.clients ) + 1 );
cl->userid = g_userid++; // create unique userid
SetBits( cl->flags, FCL_FAKECLIENT ); SetBits( cl->flags, FCL_FAKECLIENT );
// parse some info from the info strings // parse some info from the info strings
Q_strncpy( cl->userinfo, userinfo, sizeof( cl->userinfo )); Q_strncpy( cl->userinfo, userinfo, sizeof( cl->userinfo ));
SV_UserinfoChanged( cl ); SV_UserinfoChanged( cl );
SetBits( cl->flags, FCL_RESEND_USERINFO ); SetBits( cl->flags, FCL_RESEND_USERINFO );
cl->next_sendinfotime = 0.0;
// if this was the first client on the server, or the last client
// the server can hold, send a heartbeat to the master.
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
if( cl->state >= cs_connected ) count++;
cl = sv.current_client;
Log_Printf( "\"%s<%i><%i><>\" connected, address \"local\"\n", cl->name, cl->userid, i );
SetBits( cl->edict->v.flags, FL_CLIENT|FL_FAKECLIENT ); // mark it as fakeclient SetBits( cl->edict->v.flags, FL_CLIENT|FL_FAKECLIENT ); // mark it as fakeclient
cl->connection_started = host.realtime; cl->connection_started = host.realtime;
cl->state = cs_spawned;
if( count == 1 || count == svs.maxclients ) SV_MaybeNotifyPlayerCountChange( cl, "local" );
NET_MasterClear();
return cl->edict; return cl->edict;
} }
@@ -772,7 +745,7 @@ const char *SV_GetClientIDString( sv_client_t *cl )
if( sv_lan.value ) if( sv_lan.value )
return "ID_LAN"; return "ID_LAN";
Q_snprintf( result, sizeof( result ), "ID_%s", MD5_Print( (byte *)cl->hashedcdkey )); Q_snprintf( result, sizeof( result ), "ID_%s", cl->hashedcdkey );
return result; return result;
} }
@@ -3196,10 +3169,8 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
if( len > 0 ) if( len > 0 )
Netchan_OutOfBand( NS_SERVER, from, len, (byte*)buf ); Netchan_OutOfBand( NS_SERVER, from, len, (byte*)buf );
} }
else else if( sv_log_outofband.value )
{
Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
}
} }
} }
@@ -3330,6 +3301,10 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
SV_RunCmd( cl, &cmds[i], cl->netchan.incoming_sequence - i ); SV_RunCmd( cl, &cmds[i], cl->netchan.incoming_sequence - i );
} }
// was player kicked? stop here
if( cl->state <= cs_zombie )
return;
cl->lastcmd = cmds[0]; cl->lastcmd = cmds[0];
// adjust latency time by 1/2 last client frame since // adjust latency time by 1/2 last client frame since

View File

@@ -763,6 +763,31 @@ qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent )
{ {
const char *input_devices_str = Info_ValueForKey( useragent, "d" ); const char *input_devices_str = Info_ValueForKey( useragent, "d" );
const char *id = Info_ValueForKey( useragent, "uuid" ); const char *id = Info_ValueForKey( useragent, "uuid" );
size_t len, i;
len = Q_strlen( id );
if( len != 32 )
{
SV_RejectConnection( from, "invalid authentication certificate\n" );
return false;
}
for( i = 0; i < len; i++ )
{
char c = id[i];
if( !isdigit( id[i] ) && !( c >= 'a' && c <= 'f' ))
{
SV_RejectConnection( from, "invalid authentication certificate\n" );
return false;
}
}
if( SV_CheckID( id ))
{
SV_RejectConnection( from, "You are banned!\n" );
return false;
}
if( !sv_allow_noinputdevices.value && ( !input_devices_str || !input_devices_str[0] ) ) if( !sv_allow_noinputdevices.value && ( !input_devices_str || !input_devices_str[0] ) )
{ {
@@ -796,17 +821,6 @@ qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent )
} }
} }
if( id )
{
qboolean banned = SV_CheckID( id );
if( banned )
{
SV_RejectConnection( from, "You are banned!\n" );
return false;
}
}
return true; return true;
} }

View File

@@ -892,6 +892,10 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
vec3_t oldvel; vec3_t oldvel;
usercmd_t cmd; usercmd_t cmd;
// if the player got kicked, do not process commands
if( cl->state <= cs_zombie )
return;
clent = cl->edict; clent = cl->edict;
cmd = *ucmd; cmd = *ucmd;

View File

@@ -907,13 +907,7 @@ static void GL_InitExtensionsBigGL( void )
GL_CheckExtension( "GL_ARB_seamless_cube_map", NULL, 0, "gl_texture_cubemap_seamless", GL_ARB_SEAMLESS_CUBEMAP, 0 ); GL_CheckExtension( "GL_ARB_seamless_cube_map", NULL, 0, "gl_texture_cubemap_seamless", GL_ARB_SEAMLESS_CUBEMAP, 0 );
} }
// NPOT textures support GL_CheckExtension( "GL_ARB_texture_non_power_of_two", NULL, 0, "gl_texture_npot", GL_ARB_TEXTURE_NPOT_EXT, 0 );
if( !GL_CheckExtension( "GL_ARB_texture_non_power_of_two", NULL, 0, "gl_texture_npot", GL_ARB_TEXTURE_NPOT_EXT, 0 ))
{
// vitaGL exposes OES extension
GL_CheckExtension( "GL_OES_texture_npot", NULL, 0, "gl_texture_npot", GL_ARB_TEXTURE_NPOT_EXT, 0 );
}
GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, ARRAYSIZE( texturecompressionfuncs ), "gl_texture_dxt_compression", GL_TEXTURE_COMPRESSION_EXT, 0 ); GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, ARRAYSIZE( texturecompressionfuncs ), "gl_texture_dxt_compression", GL_TEXTURE_COMPRESSION_EXT, 0 );
if( !GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, 0, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT, 2.0 )) // present in ES2 if( !GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, 0, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT, 2.0 )) // present in ES2
GL_CheckExtension( "GL_SGIS_texture_edge_clamp", NULL, 0, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT, 0 ); GL_CheckExtension( "GL_SGIS_texture_edge_clamp", NULL, 0, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT, 0 );

View File

@@ -1093,6 +1093,14 @@ static void R_RenderFullbrights( void )
pglBlendFunc( GL_ONE, GL_ONE ); pglBlendFunc( GL_ONE, GL_ONE );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// if fullbright textures are drawn in separate pass from VBO they
// cause z-fighting, this is noticeable on `slide_waifufu.bsp` map
if( R_HasEnabledVBO() && gl_polyoffset.value )
{
pglEnable( GL_POLYGON_OFFSET_FILL );
pglPolygonOffset( -1.0f, -gl_polyoffset.value );
}
for( i = draw_fullbrights.first; i <= draw_fullbrights.last; i++ ) for( i = draw_fullbrights.first; i <= draw_fullbrights.last; i++ )
{ {
es = fullbright_surfaces[i]; es = fullbright_surfaces[i];
@@ -1108,6 +1116,9 @@ static void R_RenderFullbrights( void )
es->lumachain = NULL; es->lumachain = NULL;
} }
if( R_HasEnabledVBO() && gl_polyoffset.value )
pglDisable( GL_POLYGON_OFFSET_FILL );
pglDisable( GL_BLEND ); pglDisable( GL_BLEND );
pglDepthMask( GL_TRUE ); pglDepthMask( GL_TRUE );
pglDisable( GL_ALPHA_TEST ); pglDisable( GL_ALPHA_TEST );

View File

@@ -61,8 +61,8 @@ CFLAGS = {
'common': { 'common': {
# disable thread-safe local static initialization for C++11 code, as it cause crashes on Windows XP # disable thread-safe local static initialization for C++11 code, as it cause crashes on Windows XP
'msvc': ['/D_USING_V110_SDK71_', '/FS', '/Zc:threadSafeInit-', '/MT', '/MP', '/Zc:__cplusplus'], 'msvc': ['/D_USING_V110_SDK71_', '/FS', '/Zc:threadSafeInit-', '/MT', '/MP', '/Zc:__cplusplus'],
'clang': ['-g', '-gdwarf-2', '-fvisibility=hidden', '-fno-threadsafe-statics'], 'clang': ['-g', '-gdwarf-2', '-fvisibility=hidden', '-fno-threadsafe-statics', '-fasynchronous-unwind-tables'],
'gcc': ['-g', '-fvisibility=hidden'], 'gcc': ['-g', '-fvisibility=hidden', '-fasynchronous-unwind-tables'],
'owcc': ['-fno-short-enum', '-ffloat-store', '-g3'] 'owcc': ['-fno-short-enum', '-ffloat-store', '-g3']
}, },
'fast': { 'fast': {
@@ -177,6 +177,9 @@ def options(opt):
grp.add_option('--enable-profile', action = 'store_true', dest = 'PROFILE_GENERATE', default = False, grp.add_option('--enable-profile', action = 'store_true', dest = 'PROFILE_GENERATE', default = False,
help = 'enable profile generating build (stored in xash3d-prof directory) [default: %(default)s]') help = 'enable profile generating build (stored in xash3d-prof directory) [default: %(default)s]')
grp.add_option('--enable-limited-debuginfo', action = 'store_true', dest = 'LIMITED_DEBUGINFO', default = False,
help = 'only save line debuginfo, useful for release builds [default: %(default)s]')
grp.add_option('--use-profile', action = 'store', dest = 'PROFILE_USE', default = None, grp.add_option('--use-profile', action = 'store', dest = 'PROFILE_USE', default = None,
help = 'use profile during build [default: %(default)s]') help = 'use profile during build [default: %(default)s]')
@@ -240,16 +243,28 @@ def get_optimization_flags(conf):
linkflags+= [conf.get_flags_by_compiler(PROFILE_USE_LINKFLAGS, conf.env.COMPILER_CC)[0] % conf.options.PROFILE_USE] linkflags+= [conf.get_flags_by_compiler(PROFILE_USE_LINKFLAGS, conf.env.COMPILER_CC)[0] % conf.options.PROFILE_USE]
cflags += [conf.get_flags_by_compiler(PROFILE_USE_CFLAGS, conf.env.COMPILER_CC)[0] % conf.options.PROFILE_USE] cflags += [conf.get_flags_by_compiler(PROFILE_USE_CFLAGS, conf.env.COMPILER_CC)[0] % conf.options.PROFILE_USE]
if conf.env.DEST_OS == 'nswitch' and conf.options.BUILD_TYPE == 'debug': if conf.env.DEST_OS == 'nswitch':
# enable remote debugger if conf.options.BUILD_TYPE == 'debug':
cflags.append('-DNSWITCH_DEBUG') # enable remote debugger
cflags.append('-DNSWITCH_DEBUG')
# this port don't have stack printing support
cflags.remove('-fasynchronous-unwind-tables')
elif conf.env.DEST_OS == 'psvita': elif conf.env.DEST_OS == 'psvita':
# this optimization is broken in vitasdk # this optimization is broken in vitasdk
cflags.append('-fno-optimize-sibling-calls') cflags.append('-fno-optimize-sibling-calls')
# remove fvisibility to allow everything to be exported by default # remove fvisibility to allow everything to be exported by default
cflags.remove('-fvisibility=hidden') cflags.remove('-fvisibility=hidden')
# this port don't have stack printing support
cflags.remove('-fasynchronous-unwind-tables')
if conf.env.COMPILER_CC != 'msvc' and conf.env.COMPILER_CC != 'owcc': if conf.env.COMPILER_CC in ['gcc', 'clang'] and conf.options.LIMITED_DEBUGINFO:
# probably not a good idea to do this, but it should save space on Android builds especially
# that are never going to be run under debugger, but we still want that readable fileline
# info in backtraces
# might enable this for release/fast/fastnative builds in the future
cflags = ['-gline-tables-only' if flag.startswith('-g') else flag for flag in cflags]
if conf.env.COMPILER_CC in ['gcc', 'clang'] and conf.env.DEST_OS not in ['android']:
# HLSDK by default compiles with these options under Linux # HLSDK by default compiles with these options under Linux
# no reason for us to not do the same # no reason for us to not do the same

View File

@@ -48,6 +48,12 @@ def sdl2_configure_path(conf, path, libname):
conf.env[FRAMEWORKPATH] = [my_dirname(path)] conf.env[FRAMEWORKPATH] = [my_dirname(path)]
conf.env[FRAMEWORK] = [libname] conf.env[FRAMEWORK] = [libname]
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[FRAMEWORK], conf.env[FRAMEWORKPATH], conf.env[INCLUDES])) conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[FRAMEWORK], conf.env[FRAMEWORKPATH], conf.env[INCLUDES]))
elif conf.env.DEST_OS == 'android':
# Special setup for waf called from CMake, through ExternalProject_Add
conf.env[INCLUDES] = [os.path.abspath(os.path.join(path, 'include'))]
conf.env[LIBPATH] = [os.environ['BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY']]
conf.env[LIB] = [libname]
conf.end_msg('yes: {0}, {1}, {2}'.format(conf.env[LIB], conf.env[LIBPATH], conf.env[INCLUDES]))
else: else:
conf.env[INCLUDES] = [ conf.env[INCLUDES] = [
os.path.abspath(os.path.join(path, 'include')), os.path.abspath(os.path.join(path, 'include')),

View File

@@ -20,12 +20,20 @@ import os
import sys import sys
ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK'] ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK']
ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25] ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25, 27, 28]
ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp
ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC
ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15 ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15
ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag
ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16, 23: 16, 25: 19 } # minimal API level ndk revision supports ANDROID_NDK_API_MIN = {
10: 3,
19: 16,
20: 16,
23: 16,
25: 19,
27: 19,
28: 19,
} # minimal API level ndk revision supports
ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21 ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21
ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets
@@ -50,6 +58,7 @@ class Android:
self.api = api self.api = api
self.toolchain = toolchain self.toolchain = toolchain
self.arch = arch self.arch = arch
self.exe = '.exe' if sys.platform.startswith('win32') or sys.platform.startswith('cygwin') else ''
for i in ANDROID_NDK_ENVVARS: for i in ANDROID_NDK_ENVVARS:
self.ndk_home = os.getenv(i) self.ndk_home = os.getenv(i)
@@ -196,10 +205,10 @@ class Android:
def gen_toolchain_path(self): def gen_toolchain_path(self):
if self.is_clang(): if self.is_clang():
triplet = '%s%d-' % (self.ndk_triplet(llvm_toolchain = True), self.api) base = ''
else: else:
triplet = self.ndk_triplet() + '-' base = self.ndk_triplet() + '-'
return os.path.join(self.gen_gcc_toolchain_path(), 'bin', triplet) return os.path.join(self.gen_gcc_toolchain_path(), 'bin', base)
def gen_binutils_path(self): def gen_binutils_path(self):
if self.ndk_rev >= 23: if self.ndk_rev >= 23:
@@ -215,7 +224,11 @@ class Android:
s = environ['CC'] s = environ['CC']
return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api) return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + ('clang' if self.is_clang() else 'gcc')
if self.is_clang():
return '%s --target=%s%d' % (self.gen_toolchain_path() + 'clang' + self.exe, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + 'gcc'
def cxx(self): def cxx(self):
if self.is_host(): if self.is_host():
@@ -226,19 +239,33 @@ class Android:
s = environ['CXX'] s = environ['CXX']
return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api) return '%s --target=%s%d' % (s, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + ('clang++' if self.is_clang() else 'g++')
if self.is_clang():
return '%s --target=%s%d' % (self.gen_toolchain_path() + 'clang++' + self.exe, self.ndk_triplet(), self.api)
return self.gen_toolchain_path() + 'g++'
def strip(self): def strip(self):
if self.is_host(): if self.is_host():
environ = getattr(self.ctx, 'environ', os.environ) environ = getattr(self.ctx, 'environ', os.environ)
if 'STRIP' in environ: if 'STRIP' in environ:
return environ['STRIP'] return environ['STRIP']
return 'llvm-strip' return 'llvm-strip'
if self.ndk_rev >= 23: if self.ndk_rev >= 23:
return os.path.join(self.gen_binutils_path(), 'llvm-strip') return os.path.join(self.gen_binutils_path(), 'llvm-strip' + self.exe)
return os.path.join(self.gen_binutils_path(), 'strip') return os.path.join(self.gen_binutils_path(), 'strip' + self.exe)
def ar(self):
if self.is_host():
environ = getattr(self.ctx, 'environ', os.environ)
if 'AR' in environ:
return environ['AR']
return 'llvm-ar'
if self.ndk_rev >= 23:
return os.path.join(self.gen_binutils_path(), 'llvm-ar' + self.exe)
return os.path.join(self.gen_binutils_path(), 'ar' + self.exe)
def system_stl(self): def system_stl(self):
# TODO: proper STL support # TODO: proper STL support
@@ -336,7 +363,7 @@ class Android:
ldflags += ['-lgcc'] ldflags += ['-lgcc']
if self.is_clang() or self.is_host(): if self.is_clang() or self.is_host():
ldflags += ['-stdlib=libstdc++'] ldflags += ['-stdlib=libstdc++', '-lc++abi']
else: ldflags += ['-no-canonical-prefixes'] else: ldflags += ['-no-canonical-prefixes']
if self.is_arm(): if self.is_arm():
@@ -521,25 +548,33 @@ def configure(conf):
valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64'] valid_archs = ['x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'armeabi-v7a-hard', 'aarch64']
if values[0] == 'arm64-v8a':
values[0] = 'aarch64'
if values[0] not in valid_archs: if values[0] not in valid_archs:
conf.fatal('Unknown arch: %s. Supported: %r' % (values[0], ', '.join(valid_archs))) conf.fatal('Unknown arch: %s. Supported: %r' % (values[0], ', '.join(valid_archs)))
conf.android = android = Android(conf, values[0], values[1], int(values[2])) conf.android = android = Android(conf, values[0], values[1], int(values[2]))
conf.environ['CC'] = android.cc() conf.environ['CC'] = android.cc()
conf.environ['CXX'] = android.cxx() conf.environ['CXX'] = android.cxx()
conf.environ['STRIP'] = android.strip() conf.environ['STRIP'] = android.strip()
conf.environ['AR'] = android.ar()
conf.env.CFLAGS += android.cflags() conf.env.CFLAGS += android.cflags()
conf.env.CXXFLAGS += android.cflags(True) conf.env.CXXFLAGS += android.cflags(True)
conf.env.LINKFLAGS += android.linkflags() conf.env.LINKFLAGS += android.linkflags()
conf.env.LDFLAGS += android.ldflags() conf.env.LDFLAGS += android.ldflags()
from waflib.Tools.compiler_c import c_compiler
from waflib.Tools.compiler_cxx import cxx_compiler
c_compiler['win32'] = ['clang' if android.is_clang() or android.is_host() else 'gcc']
cxx_compiler['win32'] = ['clang++' if android.is_clang() or android.is_host() else 'gxx']
conf.env.HAVE_M = True conf.env.HAVE_M = True
if android.is_hardfp(): if android.is_hardfp():
conf.env.LIB_M = ['m_hard'] conf.env.LIB_M = ['m_hard']
else: conf.env.LIB_M = ['m'] else: conf.env.LIB_M = ['m']
conf.env.PREFIX = '/lib/%s' % android.apk_arch()
conf.msg('Selected Android NDK', '%s, version: %d' % (android.ndk_home, android.ndk_rev)) conf.msg('Selected Android NDK', '%s, version: %d' % (android.ndk_home, android.ndk_rev))
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx # no need to print C/C++ compiler, as it would be printed by compiler_c/cxx
conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/')) conf.msg('... C/C++ flags', ' '.join(android.cflags()).replace(android.ndk_home, '$NDK/'))