Compare commits

..

884 Commits

Author SHA1 Message Date
Alibek Omarov
fa90a4aaa2 Documentation: add doc explaining VGUI2 support status, and how to enable it 2023-05-02 08:55:03 +03:00
Alibek Omarov
50dbfb3747 3rdparty: vgui_support: update submodule 2023-05-02 08:55:03 +03:00
Alibek Omarov
41e51c530a engine: client: vgui: add funcs for VGUI2 support to the new API, change VGui_Startup to include VGUI2 initialization 2023-05-02 08:55:03 +03:00
Alibek Omarov
05b32e4caf engine: client: vgui: add support for new API, make an adapter for legacy API to new 2023-05-02 08:55:03 +03:00
Alibek Omarov
7e6b5253b2 engine: first draft for VGUI support API 2023-05-02 08:55:03 +03:00
Alibek Omarov
3629448f0c engine: rename vguiapi_t to legacy_vguiapi_t as new VGUI support API is now being developed 2023-05-02 08:55:03 +03:00
Alibek Omarov
78e239d883 engine: soundlib: wav: attempt to make FindNextChunk more safe 2023-05-02 08:54:37 +03:00
Alibek Omarov
5a7b68fcc1 filesystem: add new export FS_GetFullDiskPath, similar to FS_GetDiskPath, but generates full path to the file, including searchpath 2023-05-02 08:52:54 +03:00
Alibek Omarov
c33a384975 engine: client: s_vox: do not crash in VOX if sentence wasn't sound in sequences 2023-05-02 08:51:53 +03:00
Alibek Omarov
5b582b744a engine: client: check if filesystem was initialized during client shutdown 2023-04-30 10:14:02 +03:00
Alibek Omarov
c96f8ba722 engine: client: in_joy: do not create cvar on shutdown 2023-04-30 10:14:02 +03:00
Alibek Omarov
9f92e2a1f7 engine: client: console: do not save history if nothing was executed in console 2023-04-30 10:14:02 +03:00
Alibek Omarov
710b234493 engine: add new pretty --help output 2023-04-30 10:14:02 +03:00
Alibek Omarov
75759530e3 engine: remove doublecolons from MSGBOX macros 2023-04-30 10:14:02 +03:00
Alibek Omarov
5162ab62fd engine: filesystem: do not crash if engine was shutdown before filesystem was loaded 2023-04-30 10:14:02 +03:00
Alibek Omarov
3e2a215c15 engine: client: in_joy: rename -nojoy to -noenginejoy to avoid conflict with client.dll's joystick support 2023-04-30 10:14:02 +03:00
Alibek Omarov
e2540bd446 filesystem: turn unused caseinsensitive argument in InitStdio into a reserved argument (set to true by default) 2023-04-30 10:14:02 +03:00
Alibek Omarov
07fd4f37ef engine: remove unused -caseinsensitive command line argument 2023-04-30 10:14:02 +03:00
Alibek Omarov
92b72a7d33 game_launch: add icons that were used for Android port 2023-04-30 00:56:28 +03:00
Alibek Omarov
cb3b16e2ec engine: client: implement v_dark in engine, instead of making it ref-specific 2023-04-28 16:52:22 +03:00
Alibek Omarov
bd3dc71f39 engine: server: refactor banid, explicitly does not allow ban using userid for now 2023-04-28 16:24:41 +03:00
Alibek Omarov
48176233bd public: move FOV calculating functions out of libpublic, as they are very specific to engine view 2023-04-26 05:22:34 +03:00
Alibek Omarov
a292d2fd53 platform: win32: replace Q_sprintf calls by Q_snprintf 2023-04-26 05:20:45 +03:00
Alibek Omarov
27aad9f4a0 ref: gl: add size argument to COM_Default/ReplaceExtension calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
71a3cedba8 filesystem: add size argument to COM_Default/ReplaceExtension calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
ec2951cf45 engine: add size argument to COM_Default/ReplaceExtension calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
ff436ae100 public: crtlib: add safe COM_DefaultExtension and COM_ReplaceExtension 2023-04-26 05:20:45 +03:00
Alibek Omarov
cfdfdd5c93 utils: mdldec: add size argument to COM_FileBase calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
8b96e7ca87 ref: add size argument to COM_FileBase calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
1603b8028c filesystem: add size argument to COM_FileBase calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
8c7db8499f engine: add size argument to COM_FileBase calls 2023-04-26 05:20:45 +03:00
Alibek Omarov
fbdd79644b public: test new COM_FileBase and compare it's results with old implementation (embedded into test itself) 2023-04-26 05:20:45 +03:00
Alibek Omarov
ac39090f6e public: crtlib: add safe COM_FileBase implementation 2023-04-26 05:20:45 +03:00
Alibek Omarov
8f207362a5 public: remove Q_sprintf, and patch all code that used it to use Q_snprintf instead 2023-04-26 05:20:45 +03:00
Alibek Omarov
b16fa8eddc public: remove Q_strcat and Q_strcpy, and patch the code that uses it 2023-04-26 05:20:45 +03:00
Alibek Omarov
2261b0dcab scripts: gha: set --disable-werror for building HLSDK 2023-04-25 13:10:12 +03:00
Alibek Omarov
9eb49fc673 scripts: gha: win32: finally use destdir instead of prefix on Windows 2023-04-25 13:05:34 +03:00
Alibek Omarov
c61c84ad4f Revert "wscript: check malloc.h first to make checks on Windows slightly faster"
This reverts commit 1464e1e2be.
2023-04-25 12:39:47 +03:00
Alibek Omarov
71c9fd2772 wscript: do not check for --prefix without --enable-packaging, as it's still valid to use 2023-04-25 03:01:35 +03:00
Alibek Omarov
1464e1e2be wscript: check malloc.h first to make checks on Windows slightly faster 2023-04-25 02:39:07 +03:00
Alibek Omarov
cf557d191a wscript: make prefix vs destdir installing more safe and predictable 2023-04-25 02:38:36 +03:00
Alibek Omarov
b72033eb74 engine: client: fix master server query through NetAPI 2023-04-23 22:05:11 +03:00
Alibek Omarov
cec903fd10 mainui: update 2023-04-23 18:44:17 +03:00
Alibek Omarov
b333edeefe public: crtlib: remove unused Q_strlwr macro 2023-04-23 18:31:08 +03:00
Alibek Omarov
76c7273600 utils: mdldec: remove usage of string functions with unspecified size 2023-04-23 18:30:44 +03:00
Alibek Omarov
096ee34f67 public: remove Q_vsprintf, replace by proper Q_vsnprintf proper calls
Fixes weird off by one error caused by glibc updates? I didn't tracked
what causes it exactly but replacing it seems to work. Anyway, we should
remove all 99999 hacks in libpublic.
2023-04-23 18:19:28 +03:00
Alibek Omarov
5b52a9a19f engine: protocol: increase MAX_LIGHTSTYLES from 64 to 256, protocol limit as it encoded as unsigned byte 2023-04-20 10:35:21 +03:00
Alibek Omarov
cacfff008f engine: common: enable autocomplete for mp3 command 2023-04-19 17:54:45 +03:00
Alibek Omarov
398cec626e engine: client: remove media/ prefix for CD tracks, add it while parsing cdaudio.txt for compatibility 2023-04-19 17:54:28 +03:00
Alibek Omarov
cadad6ce34 github: attempt to avoid release draft issue by sleeping for 20s 2023-04-19 16:32:21 +03:00
Alibek Omarov
588d080a63 github: migrate to softprops/action-gh-release to avoid drafts being randomly created (thanks @SNMetamorph) 2023-04-19 15:05:41 +03:00
Alibek Omarov
1affc36f06 engine: client: more accurate ScreenShake implementation, thanks @vasiavasiavasia95 for sharing it 2023-04-18 17:28:27 +03:00
Alibek Omarov
8d6ac3fad4 engine: common: net_encode: cosmetic changes, static-ize functions, move private macros 2023-04-18 05:16:57 +03:00
Alibek Omarov
0d5d30398b filesystem: VFileSystem009: refactoring 2023-04-18 04:50:47 +03:00
Alibek Omarov
eb0686fca1 filesystem: fix wrong data type for character in Gets and Ungetc 2023-04-18 04:47:55 +03:00
Alibek Omarov
41025c0049 engine: client: reset connection retries counter on changelevel
Fixes an issue when connection retry counter near the failure state
and the server changes level
2023-04-18 04:45:27 +03:00
Tim Schumacher
6518a5cf8b engine: whereami: Add SerenityOS 2023-04-17 19:30:11 +03:00
Alibek Omarov
49936120ca public: tests: add new test to check return values of Q_Architecture/PlatformStringByID and Q_buildnum 2023-04-17 19:11:16 +03:00
Alibek Omarov
e4a5b95e81 public: build: split Q_buildnum to separate function that calculates build number from arbitrary date string 2023-04-17 19:10:40 +03:00
Alibek Omarov
84fc8d4281 public: build: fix naming for 32-bit RISCV with double precision float ABI 2023-04-17 19:09:59 +03:00
Alibek Omarov
e9da3e2976 public: build: reorder enums by probability, rename ARCHITECTURE_ ABI macros to just ARCH_ for easier matching 2023-04-17 06:37:08 +03:00
Alibek Omarov
c1252b5642 scripts: waifulib: vgui: fix Logs aren't being imported 2023-04-17 06:36:58 +03:00
Alibek Omarov
7d54952422 3rdparty: vgui_support: update submodule 2023-04-17 05:22:02 +03:00
Alibek Omarov
b28d10f69f scripts: waifulib: split vgui_support VGUI detection to separate module 2023-04-17 05:20:22 +03:00
Alibek Omarov
6cb3b2f01a wscript: print modules help before engine common options 2023-04-17 05:19:56 +03:00
Alibek Omarov
248be5458f engine: common: hpak: do not print hashpak contents in quiet mode 2023-04-17 04:39:21 +03:00
Alibek Omarov
2e7306e96a engine: network: fix missing newline in IP port allocation error message 2023-04-17 04:37:16 +03:00
Alibek Omarov
558ded6d6a filesystem: tests: interface: use correct type for module on Win32 2023-04-15 04:58:29 +03:00
Alibek Omarov
c52dc69360 scripts: gha, cirrus: fix failing workflows because of --enable-fs-tests flag removal 2023-04-15 04:24:45 +03:00
Alibek Omarov
ba1648c689 mainui: update 2023-04-15 04:19:14 +03:00
Alibek Omarov
101a7a1240 engine: client: try to fix random crash in CL_ClearWorld when using legacy protocol 2023-04-15 04:08:40 +03:00
Alibek Omarov
25d6b2b069 engine: client: fix FlushEntityPacket message overflow on legacy servers 2023-04-15 04:08:40 +03:00
Alibek Omarov
f67b97e63c engine: common: mod_bmodel: remove useless copy before Q_strnlwr, as Q_strnlwr already copies string 2023-04-15 04:08:40 +03:00
Alibek Omarov
9a24cb8c96 engine: client: console: remove useless function Con_StringLength 2023-04-15 04:08:40 +03:00
Alibek Omarov
c157b7def3 filesystem: tests: interface: various fixes
* correctly check success variable value in CreateInterface
* get rid of C language quirks because this file is C++
* check that globals were filled
2023-04-15 04:08:12 +03:00
Alibek Omarov
de88aec958 filesystem: restore DarkPlaces contributors copyrights lost in filesystem_stdio
* Add Xash3D FWGS contributors copyrights
2023-04-15 02:39:38 +03:00
Alibek Omarov
7f31871b5a engine: common: zone: restore Id Software and Darkplaces copyrights, add Xash3D FWGS copyrights 2023-04-15 02:39:16 +03:00
Alibek Omarov
f55ef63e26 ref: optimize R_LightLambert function
* Quick exit if no local lights
* Try to minimize Q_min() checks by apply it on temp variables
* Cap final light values only once, after all local lights are calculated
2023-04-14 20:33:07 +03:00
Alibek Omarov
824a34ee1e engine: common: imgelib: fix declaration after statement in test code 2023-04-14 18:58:43 +03:00
Alibek Omarov
46e2ccd2bf filesystem: wscript: check interface test before everything else
It makes sense since we're using sequential execution here anyway
2023-04-13 20:07:58 +03:00
Alibek Omarov
339c08d89f public: add basic test for our strcpy, strcmp and strcat functions 2023-04-13 19:56:31 +03:00
Alibek Omarov
2db2375b4d waifu: upgrade to latest revision 2023-04-13 18:43:08 +03:00
Alibek Omarov
d86ab19351 wscript: refactoring, replace --enable-fs-tests with --enable-tests
* Run filesystem tests in sequential order, to avoid tests being run
before filesystem_stdio DLL is linked
* Include new interface test in filesystem
2023-04-13 18:40:27 +03:00
Alibek Omarov
db40d58208 filesystem: add test for probing all interfaces 2023-04-13 18:39:21 +03:00
Alibek Omarov
33ff7bbd61 scripts: waifulib: compiler_optimizations: set default build type to release
I think this will make configuration less confusing, also we're stable enough to be built
with optimizations and without debug information
2023-04-13 16:14:09 +03:00
Alibek Omarov
4d4162336a engine: common: mod_bmodel: apply code style fixes to match existing code, for consistency 2023-04-11 03:11:23 +03:00
Jonathan Poncelet
372514151d engine: common: mod_bmodel: Fixed default texture name check
REF_DEFAULT_TEXTURE defines the canonical name, so is used
instead of a string literal.
2023-04-11 01:41:20 +03:00
Jonathan Poncelet
6c9ce478a9 engine: common: mod_bmodel: Fixed Con_Printf warnings
Some formatting characters did not match up with their
values.
2023-04-11 01:41:20 +03:00
Jonathan Poncelet
78555ab125 engine: common: mod_bmodel: Tidied texture loading procedure 2023-04-11 01:41:20 +03:00
Andrey Akhmichin
f2c671d809 utils: mdldec: Fix typo. 2023-04-10 01:03:52 +03:00
Alibek Omarov
4bce193645 mainui: update 2023-04-03 06:45:05 +03:00
Alibek Omarov
129de871e3 engine: common: hpak: use statically allocated hpk_maxsize cvar because gamedll can re-register it for some reason 2023-04-03 06:22:55 +03:00
Alibek Omarov
c24a1fafc5 engine: add missing HPAK_CheckSize/Integrity calls 2023-04-03 06:04:48 +03:00
Alibek Omarov
cee3757e6f engine: common: hpak: add hpak deletion in validate function 2023-04-03 06:04:18 +03:00
Alibek Omarov
12ed092446 engine: client: register VGui surface cvars 2023-04-03 06:03:29 +03:00
Alibek Omarov
2fb19a0cfd public: matrixlib: cleanup unused functions 2023-04-03 05:14:59 +03:00
Alibek Omarov
79624fa400 ref: gl: cleanup unused functions 2023-04-03 05:09:33 +03:00
Alibek Omarov
550ced9c36 ref: gl: cleanup unused functions in frustum 2023-04-03 05:05:32 +03:00
Alibek Omarov
fd795d5612 ref: soft: cleanup unused functions 2023-04-03 04:57:41 +03:00
Alibek Omarov
dc0982932b engine: common: sequence: static-ize private functions 2023-04-03 04:33:19 +03:00
Alibek Omarov
5d387101b9 engine: client: remove unused Key_IsBind 2023-04-03 04:33:19 +03:00
Alibek Omarov
eef1e1868a engine: common: remove unused BaseCmd_Replace 2023-04-03 04:33:19 +03:00
Alibek Omarov
4005ef831a engine: common: remove unused IsBackgroundMap/Demo calls, remove unused gamma function 2023-04-03 04:33:19 +03:00
Alibek Omarov
b0c71c598f engine: common: remove unused Mod_AmbientLevels 2023-04-03 04:33:19 +03:00
Alibek Omarov
d7848b7b8d engine: client: efx: remove unused CL_FreeParticle 2023-04-03 04:33:19 +03:00
Alibek Omarov
9cdce1ce69 engine: network: remove unused MSG_Read/WriteBitFloat 2023-04-03 04:17:54 +03:00
Alibek Omarov
84edd9d0c4 engine: client: use ReadVec3Angles in svc_setangle, as server uses WriteVec3Angles 2023-04-03 04:17:02 +03:00
Alibek Omarov
d8355a651f engine: add missing Sequence_Init and Sequence_OnLevelLoad calls 2023-04-03 04:12:47 +03:00
Alibek Omarov
004ac8105e engine: common: identification: static-ize all functions 2023-04-03 04:04:25 +03:00
Alibek Omarov
2e8ab13242 engine: client: fix parsing svc_spawnentity on old protocol 2023-04-03 03:56:31 +03:00
Alibek Omarov
27d9fc0afe engine: client: sound: remove unused functions 2023-04-03 03:55:57 +03:00
Alibek Omarov
192d510924 engine: client: remove unused function CL_FreeEntity and everything that used it 2023-04-03 03:55:57 +03:00
Alibek Omarov
3614cfa878 engine: client: avi: remove unused function 2023-04-03 03:55:57 +03:00
Alibek Omarov
12efcf1c44 engine: network: remove some totally ununsed functions 2023-04-03 03:13:50 +03:00
Alibek Omarov
a8de11643c engine: platform: sdl: make GL_CreateContext and GL_DeleteContext functions static 2023-04-03 03:13:33 +03:00
Alibek Omarov
597027277c engine: server: remove some totally unused functions 2023-04-03 03:12:52 +03:00
Alibek Omarov
48988e66bd engine: client: fix missing HTTP_ResetProcessState call 2023-04-03 03:11:39 +03:00
Alibek Omarov
37e3cf7e86 public: crtlib: remove unused functions 2023-04-03 02:46:23 +03:00
Alibek Omarov
01e0542223 engine: server: move master announce logic to masterlist, keep unique heartbeat challenge and heartbeat timer for each master 2023-04-03 00:57:47 +03:00
Alibek Omarov
93a7ccd14f engine: network: add net_gai_state_t enum for NET_StringToAdrNB result value 2023-04-03 00:15:35 +03:00
Alibek Omarov
892e5c59eb engine: server: convert public_server cvar to static allocation 2023-04-02 22:48:47 +03:00
Alibek Omarov
c2992afb4a engine: network: make all HTTP commands and cvars restricted, except http_addcustomserver. Also zero http_useragent by default (it's autogenerated now) 2023-03-31 01:22:41 +03:00
Alibek Omarov
b99e7a6304 engine: network: include build info to default HTTP useragent 2023-03-31 01:16:17 +03:00
Alibek Omarov
8888b456df engine: client: cl_tent: rewrite R_Sprite_Explode to be closer to original function but support Xash extensions 2023-03-30 04:42:48 +03:00
Alibek Omarov
53987f47e2 engine: client: use alternative ease-in ease-out function in sound fade 2023-03-30 04:40:54 +03:00
Alibek Omarov
7cac1d290d scripts: gha: it's pretty safe to not do clean on Waf, since it's much better at tracking modified files 2023-03-29 00:22:47 +03:00
Alibek Omarov
55b048aab9 github: enable nswitch and psvita CI builds back, test if continuous tag gets correctly deleted 2023-03-29 00:05:40 +03:00
Alibek Omarov
881a7edb9f github: try to fix uploading release again 2023-03-28 23:54:49 +03:00
Alibek Omarov
6c62136f11 engine: client: avi: convert filename to wide characters before passing it into VFW API 2023-03-28 22:42:16 +03:00
Alibek Omarov
f34b35be5a engine: client: avi: re-attribute AVI support code by restoring original author copyright 2023-03-28 22:42:16 +03:00
Alibek Omarov
4b5ee87de1 engine: client: adapt to RefAPI 4 changes. Fix interpolation issue after reloading a save 2023-03-28 21:34:51 +03:00
Alibek Omarov
67903b55cc ref: soft: adapt to RefAPI 4 changes 2023-03-28 21:34:43 +03:00
Alibek Omarov
55bf0e8a53 ref: gl: adapt to RefAPI 4 changes 2023-03-28 20:45:26 +03:00
Alibek Omarov
f1487cf576 engine: ref_api: bump RefAPI version to 4, R_StudioEstimateFrame now has time argument 2023-03-28 20:42:18 +03:00
Alibek Omarov
29e32310cf github: update linux builds to ubuntu-20.04 2023-03-28 20:08:42 +03:00
Alibek Omarov
2ea549f250 github: update upload-release-action to 2.5.0, print outputs in repackage binaries step 2023-03-28 19:49:35 +03:00
SNMetamorph
b2ea8c9d18 engine: platform: win32: enabled attaching to existing console instead of creating new 2023-03-27 20:31:52 +03:00
Alibek Omarov
6e27926a10 engine: simplify XASH_USE_EVDEV macro usage by giving it's defined positive value 2023-03-27 17:28:19 +03:00
Alibek Omarov
96c30371b7 engine: client: better specify rawinput enabling condition on Win32 2023-03-27 17:22:48 +03:00
Alibek Omarov
9a42f4149f engine: client: disable enabling mouse cursor in key_message (typing in chat) 2023-03-27 17:22:48 +03:00
Alibek Omarov
dca4226e4b github: re-use PrimeXT's actions to upload artifacts to GitHub Releases 2023-03-27 06:01:19 +03:00
Alibek Omarov
b3c1c173a9 scripts: gha: exit if we can't move to a specified directory 2023-03-27 04:30:21 +03:00
Alibek Omarov
3e67445ef3 scripts: gha: psvita: fix building HLSDK, exit if we can't move to a directory 2023-03-27 04:27:55 +03:00
Alibek Omarov
127bd89b44 filesystem: remove unused watch.c file, added by mistake from inotify branch 2023-03-27 03:56:57 +03:00
SNMetamorph
3361e74f54 engine: client: console: fixed console scrolling on psvita platform 2023-03-27 03:52:51 +03:00
SNMetamorph
48e199bfa1 engine: common: enabled printing logs to stderr for psvita platform only in developer mode 2023-03-27 03:52:51 +03:00
SNMetamorph
575179dbf5 engine: client: added default dead zone values for psvita platform 2023-03-27 03:52:51 +03:00
SNMetamorph
e024a67436 engine: platform: psvita: fixed vrtld error reporting 2023-03-27 03:52:51 +03:00
SNMetamorph
e3103249f4 engine: platform: psvita: added developer mode button to launcher 2023-03-27 03:52:51 +03:00
SNMetamorph
0746cb5365 engine: platform: psvita: disabled back touch sensor 2023-03-27 03:52:51 +03:00
Alibek Omarov
fcda7517fe engine: common: soundlib: add support for MP3 looping through custom ID3v2.4.0 tagging 2023-03-27 03:51:42 +03:00
Alibek Omarov
2c77f4c566 engine: client: notify client.dll about local player in firstplayer mode for use in custom renderers 2023-03-27 03:47:42 +03:00
Alibek Omarov
1caa276531 engine: common: imagelib: fix loading cubemaps
Loop break was a bug that was added after refactoring imagelib loader.

In fact, it was mindlessly copypasted from old code, where same break was
used to quickly exit from inner format bruteforcing loop, than outer cubemap
loading loop.
2023-03-25 07:02:29 +03:00
Alibek Omarov
e673fe9a02 filesystem: only create readwrite directories if they look like a gamedirectory in rodir 2023-03-25 03:27:32 +03:00
Alibek Omarov
3ccbc7a28c engine: client: ref_common: r_refdll is not a VIDRESTART cvar 2023-03-24 18:03:06 +03:00
Alibek Omarov
8bb5ec5e26 ref: remove renderer description export, it's unused now 2023-03-24 02:54:14 +03:00
Alibek Omarov
35ff062407 wscript: restore NSwitch and PSVita specific link and compiler flags 2023-03-24 02:28:25 +03:00
Alibek Omarov
ec355a83d1 engine: client: ref_common: eliminate COM_FreeLibrary in renderer names query, hardcoding them instead 2023-03-24 01:52:14 +03:00
Alibek Omarov
182d8edb42 engine: wscript: define enabled renderers as macros 2023-03-24 01:50:53 +03:00
Alibek Omarov
762e4da7a0 wscript: generic refactoring
* Add RefDll class to aid in enabling renderers, creating help options, etc
* Fix optimization flags and werrors are being added twice
* Rewrite if not win32: if elif elif into a set of elifs
* Remove mandatory=True in checks, as it's a default option
2023-03-24 01:50:21 +03:00
Alibek Omarov
098c4c009b engine: platform: sdl: fix incorrect HICON cast in SetClassLongPtr call 2023-03-21 05:16:07 +03:00
Alibek Omarov
f8cf2c8953 scripts: continious_upload: retry if upload failed 2023-03-21 05:15:30 +03:00
Alibek Omarov
cc6838ec97 scripts: gha: psvita: try to fix vitaGL dependency fetching 2023-03-21 04:32:37 +03:00
Alibek Omarov
dca637d4bb engine: client: eliminate pfnServerCmd limit and, like GoldSrc, send our server command immediately to netchan 2023-03-21 04:25:32 +03:00
Alibek Omarov
3949422430 scripts: gha: psvita: fix HLSDK branches names, as all needed PSVita changes have been merged to hlsdk-portable 2023-03-20 18:14:51 +03:00
Alibek Omarov
2c8488f07a scripts: gha: psvita: disable SINGLE_THREADED_GC for vitaGL as it was fixed in upstream (thanks, @fgsfds) 2023-03-20 18:05:24 +03:00
Alibek Omarov
1df1fc32df scripts: gha: psvita: lock vitaGL revision, use --depth=1 in git clone 2023-03-20 18:05:24 +03:00
SNMetamorph
eac8c116a8 engine: server: sv_init: compiling error fix & minor cleanup 2023-03-20 16:29:43 +03:00
SNMetamorph
a03019f5e4 engine: server: sv_init: enabled handling sound resources specifically
This is for timely precaching on client side. Otherwise, files are being downloaded to client, but not precached immediatly after it, and therefore causing a late precaching of sound (obvious, this is bad)
2023-03-20 16:29:43 +03:00
SNMetamorph
714b4f45e4 engine: common: added COM_GetResourceTypeName function 2023-03-20 16:29:43 +03:00
SNMetamorph
68be8157ea engine: common: soundlib: added Sound_SupportedFileFormat function 2023-03-20 16:29:43 +03:00
Alibek Omarov
ea2a8b6785 3rdparty: update submodules (extras, mainui, opus) 2023-03-20 16:03:36 +03:00
Alibek Omarov
8c80d3b85d engine: common: cvar: add exception for cl_dodmusic cvar to fix Day of Defeat Beta 1.3 music issue 2023-03-18 20:34:30 +03:00
Alibek Omarov
33c0764e65 engine: common: system: fix inverted COM_CheckStringEmpty in Sys_GetCurrentUser for Vita
Thanks @fgsfdsfgs for pointing out
2023-03-17 17:29:40 +03:00
Alibek Omarov
d085c5a843 ref: gl: gl_cull: remove thirdperson check, as it handled in client instead 2023-03-15 06:29:29 +03:00
Alibek Omarov
4ada40e8a8 engine: client: check if we should discard local player entity before HUD_AddEntity call, allowing CL_IsThirdPerson hack used in MMod 2023-03-15 06:28:20 +03:00
Alibek Omarov
1630d87c0d engine: client: do not alter the state if invalid HANDLE was passed to pfnSPR_Set. Fixes Half-Life: MMod 2023-03-15 04:58:33 +03:00
Alibek Omarov
3a956a1ad3 engine: client: initialize variables in SPR_Width/Height/Frames functions, in case R_GetSpriteParms fails 2023-03-15 04:58:00 +03:00
Alibek Omarov
774ced312f wscript: enforce -Werror=strict-aliasing 2023-03-14 21:29:35 +03:00
Alibek Omarov
fec3d33dcf engine: client: cl_securedstub: fix strict aliasing in secured module initializing 2023-03-14 21:29:35 +03:00
Alibek Omarov
d4610e30fd engine: common: net_encode: fix strict aliasing by converting it to use float_bits_t union 2023-03-14 21:29:35 +03:00
Alibek Omarov
885cda971d engine: common: net_buffer: fix strict aliasing by converting it to use float_bits_t union 2023-03-14 21:29:35 +03:00
Alibek Omarov
ef0b227967 ref: gl: alias: fix strict aliasing by converting it to use float_bits_t union 2023-03-14 21:29:35 +03:00
Alibek Omarov
19a785a98a public: mathlib: convert rsqrt to use float_bits_t union 2023-03-14 21:29:35 +03:00
Alibek Omarov
b96bfcfe7a public: mathlib: convert FloatToHalf and HalfToFloat to use float_bits_t union 2023-03-14 21:29:35 +03:00
Alibek Omarov
412c635499 public: add float_bits_t union to access float as 32-bit signed or unsigned integer 2023-03-14 21:29:35 +03:00
Alibek Omarov
da5ec56567 engine: common: con_utils: fix const qualifier discard in Con_CheckName 2023-03-14 00:35:07 +03:00
Alibek Omarov
e664e80b27 engine: common: mod_bmodel: replace few more obvious va calls by temp buffer and Q_snprintf 2023-03-13 06:25:57 +03:00
Alibek Omarov
d177b6f528 engine: cvar: consolidate auto description for GLCONFIG cvars
Fix bug when GLCONFIG cvars didn't had it's respective CLIENTDLL or GAMEUIDLL flags
2023-03-13 06:22:54 +03:00
Alibek Omarov
2ef3d78d9f engine: client: netgraph: replace CL_DrawString with va calls by CL_DrawStringf 2023-03-13 06:16:17 +03:00
Alibek Omarov
5ea5e1167b engine: client: font: add CL_DrawStringf wrapper 2023-03-13 06:15:45 +03:00
Alibek Omarov
116a605248 engine: common: replace some obvious va uses by temp buffer and Q_snprintf or equivalent code 2023-03-13 06:08:36 +03:00
Alibek Omarov
9690fe9334 engine: client: replace some obvious va uses by temp buffer and Q_snprintf 2023-03-13 06:03:44 +03:00
Alibek Omarov
a81fa84321 engine: server: replace some obvious va uses to temp buffer and Q_snprintf 2023-03-13 06:00:38 +03:00
Alibek Omarov
5ef97ae99e engine: convert Info_SetValueForKey with va to Info_SetValueForKeyf 2023-03-13 05:37:45 +03:00
Alibek Omarov
d667845777 engine: convert Cbuf_AddText with va to Cbuf_AddTextf 2023-03-13 05:31:27 +03:00
Alibek Omarov
b12b2aaf79 engine: common: cmd: add Cbuf_AddTextf wrapper 2023-03-13 05:28:53 +03:00
Alibek Omarov
6b62f9c1b9 engine: convert Cvar_Get with va to Cvar_Getf 2023-03-13 05:19:32 +03:00
Alibek Omarov
ba1cf25314 engine: convert MSG_WriteString with va to MSG_WriteStringf 2023-03-13 05:13:52 +03:00
Alibek Omarov
fb2ba6a6e2 engine: common: net_buffer: add MSG_WriteStringf wrapper 2023-03-13 05:12:46 +03:00
Alibek Omarov
fb6e310eab public: move va() function back to engine, it's not recommended to use in shared modules 2023-03-13 02:44:59 +03:00
Alibek Omarov
bcbd1a59c6 engine: common: base_cmd: add a simple benchmark within basecmd_test command 2023-03-13 02:40:48 +03:00
Alibek Omarov
8e45a43ad2 engine: common: base_cmd: alphabetically order inserts for faster lookups 2023-03-13 02:39:54 +03:00
Alibek Omarov
115ed82c19 engine: common: base_cmd: static-ize internal fuctions 2023-03-13 02:39:02 +03:00
Alibek Omarov
5c1e06ae74 public: crclib: optimize COM_HashKey, implement typical djb hashing as this function is used for hashtables with string lookup 2023-03-13 02:37:19 +03:00
SNMetamorph
f9205825b6 engine: platform: sdl: fixed psvita & nswitch platform initializing 2023-03-12 16:09:20 +03:00
Andrey Akhmichin
9040c34f48 ref: gl: replace va function calls. 2023-03-11 17:56:05 +03:00
Andrey Akhmichin
9e9703e6de engine: common: imagelib: replace va function calls. 2023-03-11 17:37:16 +03:00
Andrey Akhmichin
6486533355 engine: platform: android: replace va function calls. 2023-03-11 16:29:55 +03:00
Andrey Akhmichin
34160151a4 filesystem: replace va function calls. 2023-03-11 16:28:54 +03:00
Andrey Akhmichin
daaaa324bd engine: platform: emscripten: replace va function calls. 2023-03-11 15:32:14 +03:00
Andrey Akhmichin
af5c74981b ref: soft: replace va function calls. 2023-03-11 15:31:17 +03:00
Andrey Akhmichin
249ce6bca1 engine: platform: win32: replace va function calls. 2023-03-11 15:30:56 +03:00
Andrey Akhmichin
b648c74815 engine: platform: posix: replace va function calls. 2023-03-11 15:30:29 +03:00
Andrey Akhmichin
a2d459ae84 engine: common: add printf-like version of Cvar_Get function. 2023-03-11 15:29:54 +03:00
Andrey Akhmichin
573781b45d engine: platform: sdl: replace va function calls. 2023-03-11 15:29:34 +03:00
Andrey Akhmichin
3299999f3d engine: common: add printf-like version of Info_SetValueForKey function. 2023-03-11 15:28:54 +03:00
Alibek Omarov
91be4f6521 engine: common: cmd: fix inverted check in apropos 2023-03-11 07:50:33 +03:00
fgsfds
f2f21b24a1 scripts: psvita: no need for fsigned-char either 2023-03-11 07:09:19 +03:00
fgsfds
9ef43a4794 scripts: psvita: no need to force GNU_SOURCE everywhere 2023-03-11 07:09:19 +03:00
fgsfds
fc02a69686 docs: add nswitch and psvita to ports.md 2023-03-11 07:09:19 +03:00
fgsfds
b10a0dc5c5 ci: psvita: build bshift libraries 2023-03-11 07:09:19 +03:00
fgsfds
e5f0d1557c docs: psvita: add install/build instructions 2023-03-11 07:09:19 +03:00
fgsfds
d8a3f4850a ci: psvita: libk is not required 2023-03-11 07:09:19 +03:00
fgsfds
882d957b5c ci: psvita: vdpm is in the current directory 2023-03-11 07:09:19 +03:00
fgsfds
afd1727898 ci: psvita: only download necessary packages 2023-03-11 07:09:19 +03:00
fgsfds
70a73e47a7 psvita: use crtlib where possible 2023-03-11 07:09:19 +03:00
fgsfds
fe3f15ad33 engine: input: psvita: reimplement OSK manually 2023-03-11 07:09:19 +03:00
fgsfds
66f625f840 engine: psvita: use a macro for ioctlsocket like on all other platforms 2023-03-11 07:09:19 +03:00
fgsfds
3e1833722f engine: psvita: check req in ioctlsocket() 2023-03-11 07:09:19 +03:00
fgsfds
4b8e11f561 engine: remove stray #if XASH_PSVITA 2023-03-11 07:09:19 +03:00
fgsfds
0d04c20578 ref: gl: psvita: skip deleting the shaders since glDeleteProgram can block for a long time 2023-03-11 07:09:19 +03:00
fgsfds
41c819f3d3 engine: psvita: keep old arguments in Sys_NewInstance 2023-03-11 07:09:19 +03:00
fgsfds
957154f097 scripts: psvita: move TITLEID and APPNAME to engine elf build arguments 2023-03-11 07:09:19 +03:00
fgsfds
fad506ef03 ref: gl: vgl_shim: remove normal support, it's not necessary 2023-03-11 07:09:19 +03:00
fgsfds
9150bbdfd8 ref: gl: psvita: remove the GL_CheckExtension hack 2023-03-11 07:09:19 +03:00
fgsfds
aa4e2f0ae4 ref: gl: psvita: use Cvar_FullSet to disable r_studio_drawelements 2023-03-11 07:09:19 +03:00
fgsfds
2bacc91922 ref: gl: move vgl_shim to ref/gl 2023-03-11 07:09:19 +03:00
fgsfds
458aa6d8b8 ci: psvita: copy the vpk as well 2023-03-11 07:09:19 +03:00
fgsfds
6963741020 ci: psvita: fix copypaste error 2023-03-11 07:09:19 +03:00
fgsfds
b55aa982b0 ci: psvita: vrtld uses cmake 2023-03-11 07:09:19 +03:00
fgsfds
492481eea8 ci: basic psvita scripts 2023-03-11 07:09:19 +03:00
fgsfds
76bff9cd4b ref: gl: psvita: fix long hang on shutdown 2023-03-11 07:09:19 +03:00
fgsfds
47a6be86b1 engine: psvita: export stpcpy 2023-03-11 07:09:18 +03:00
fgsfds
287688d985 engine: psvita: implement Sys_NewInstance 2023-03-11 07:09:18 +03:00
fgsfds
610d528042 engine: psvita: implement Sys_GetCurrentUser 2023-03-11 07:09:18 +03:00
fgsfds
89ec39821e ref: gl: psvita: add fog support; bump max verts to 32768 2023-03-11 07:09:18 +03:00
fgsfds
82cfd3ecc3 ref: gl: psvita: revert arrayverts change, it doesn't matter that much 2023-03-11 07:09:18 +03:00
fgsfds
5a3e3b3977 ref: gl: add immediate mode shim for psvita 2023-03-11 07:09:18 +03:00
fgsfds
9cf6e421cb ref: gl: psvita: force-enable NPOT textures 2023-03-11 07:09:18 +03:00
fgsfds
5c56b51044 engine: client: don't pop up OSK during loading screens on the PSVita either 2023-03-11 07:09:18 +03:00
fgsfds
577add56f1 filesystem: fs is non case sensitive on nswitch and psvita 2023-03-11 07:09:18 +03:00
fgsfds
adc5aa4659 psvita: don't default to -dev 255 2023-03-11 07:09:18 +03:00
fgsfds
5beed5ab29 engine: psvita: rebalance memory pools a bit 2023-03-11 07:09:18 +03:00
fgsfds
34dd52ca90 ref: gl: trust the GL_EXTENSIONS string on psvita 2023-03-11 07:09:18 +03:00
fgsfds
6304b51f32 psvita: fno-short-enums, make ref_gl function somewhat 2023-03-11 07:09:18 +03:00
fgsfds
97a7de3377 engine: server: remove duplicate registration for sv_autosave 2023-03-11 07:09:18 +03:00
fgsfds
7424b29e56 engine: initial psvita build support 2023-03-11 07:09:14 +03:00
Alibek Omarov
3c64d2ad80 public: build: don't confuse other libcs with built with glibc game libraries by specifying them into separate platform, like Android 2023-03-11 05:45:11 +03:00
Alibek Omarov
1274fa13c8 engine: common: cmd: slightly simplify apropos taking all arguments and checking for filtering symbols 2023-03-11 05:38:28 +03:00
Alibek Omarov
3765686077 public: make va() buffer size public 2023-03-11 05:28:17 +03:00
SNMetamorph
9fffd7a270 Documentation: added page about debugging mods using minidump files 2023-03-11 04:28:25 +03:00
SNMetamorph
e37c07f44f engine: crashhandler: added support for minidumps generation 2023-03-11 04:28:25 +03:00
SNMetamorph
214a3cce73 engine: host: added -minidumps startup parameter for win32 platform 2023-03-11 04:28:25 +03:00
Andrey Akhmichin
d738b07660 Documentation: mod-porting-guide.md: Update. 2023-03-11 04:22:30 +03:00
Alibek Omarov
48ca8f9a70 engine: server: fix call to non existent function, in this tree it's called IsMasterAdr 2023-03-02 17:36:56 +03:00
Alibek Omarov
c565b0a505 mainui: update 2023-03-02 17:35:50 +03:00
Alibek Omarov
474833a3bf engine: server: send heartbeats to master server if sv_nat is active, despite public cvar value 2023-03-01 15:57:30 +03:00
Alibek Omarov
602f23fbdf engine: server: check if we got info request from master server, that acts as a bridge for NAT servers 2023-03-01 15:57:30 +03:00
Alibek Omarov
7e9d46689c engine: client: fix multiline CenterPrint 2023-02-24 19:46:02 +03:00
Alibek Omarov
b6347d17c9 engine: client: sound: don't print sound/ twice in soundlist command 2023-02-19 12:25:03 +03:00
Alibek Omarov
8293bc91d4 engine: client: sound: fix PickDynamicChannel to correctly find channel with minimum time left 2023-02-18 03:37:20 +03:00
Alibek Omarov
fb0f184d6b engine: common: lib_common: fix offset by one UB 2023-02-17 22:51:56 +03:00
Alibek Omarov
58e95c7d6f engine: client: console: elinimate unneeded Sys_DoubleTime call in Con_DrawDebug 2023-02-17 22:50:42 +03:00
Alibek Omarov
7a5381e658 engine: common: mod_studio: fix uninitialized adj array 2023-02-17 22:50:12 +03:00
Alibek Omarov
375c06400c engine: server: avoid unaligned access in pfnMessageEnd 2023-02-17 22:48:56 +03:00
Alibek Omarov
e481c86ba2 engine: client: console: fix NXPrintf newlines, small refactoring 2023-02-15 05:53:39 +03:00
Alibek Omarov
21b9f07323 engine: platform: sdl: remove legacy XASH_NANOGL macro from vid code, it's only relevant for ref_gl 2023-02-14 18:52:51 +03:00
Alibek Omarov
0bff62e696 engine: sprite: migrate header to stdint.h, remove usage of enums in data structs for portability, add static sizeof checks 2023-02-14 18:29:27 +03:00
Alibek Omarov
858597832d engine: alias: migrate header to stdint.h, remove usage of enums in data structs for portability, add static sizeof checks 2023-02-14 18:29:18 +03:00
Alibek Omarov
9b0ac7cb32 common: add shared synctype_t definition header, borrowed from Quake's modelgen.h 2023-02-14 18:18:16 +03:00
Alibek Omarov
3c27384b6b filesystem: speedup fs_ext_path case in FS_FindFile 2023-02-13 06:49:52 +03:00
Alibek Omarov
1e8c26a527 filesystem: wad: fix loading WADs by absolute paths 2023-02-13 06:49:29 +03:00
Alibek Omarov
f4069de7f2 engine: move SlerpBones, CalcBonePosition/Quaternion from engine to libpublic 2023-02-13 05:23:13 +03:00
Alibek Omarov
e95161aa14 filesystem: fix ClearSearchPath 2023-02-12 17:09:53 +03:00
Alibek Omarov
0984368a31 engine: server: GoldSrc compliant pfnServerExecute(), don't execute config.cfg for server! 2023-02-11 07:22:04 +03:00
Alibek Omarov
f4961d9da7 engine: client: return empty string in pfnGetLevelName if no map is loaded yet 2023-02-11 06:50:46 +03:00
Alibek Omarov
f42a174482 engine: client: empty current map name in CL_ClearState 2023-02-11 06:45:20 +03:00
Alibek Omarov
13bf607031 engine: client: call VidInit early in svc_serverdata parsing, GoldSrc compatibility 2023-02-11 06:43:38 +03:00
Alibek Omarov
3cfdb1213b engine: client: consolidate modern and legacy protocol parsing functions, if possible 2023-02-11 06:06:21 +03:00
Alibek Omarov
d58105d64d scripts: flatpak: fix Half-Life directory detection 2023-02-11 03:56:40 +03:00
Alibek Omarov
1bdd844860 scripts: flatpak: minimize filesystem permissions, add Steam Flatpak data directory 2023-02-11 03:36:40 +03:00
Alibek Omarov
11f3d97cd7 scripts: flatpak: respect XDG data home in launcher script, add Steam Flatpak data directory 2023-02-11 03:36:40 +03:00
Alibek Omarov
fccf044976 engine: initialize network buffers used on player connect and after 2023-02-09 17:57:45 +03:00
Alibek Omarov
c23396f533 engine: client: keys: hardcode K_START_BUTTON as escape button, cancelselect doesn't exist anymore and many games seems to use this button for menu access, and back for pause 2023-02-09 06:32:14 +03:00
Alibek Omarov
33c9f7118b engine: platform: sdl: sanitize buttons/axes from SDL, add ABXY->BAYX swap for NSwitch 2023-02-09 06:31:19 +03:00
Alibek Omarov
c741ec223f engine: client: keys: reserve some more buttons as gamepad buttons according to latest SDL2 GameController header 2023-02-09 06:30:08 +03:00
Alibek Omarov
d6d98bd297 engine: platform: sdl: minor style changes 2023-02-09 05:59:34 +03:00
Alibek Omarov
5e1b5d89f7 engine: client: console: allow opening OSK and existing console with gamepads for all platforms 2023-02-09 05:58:54 +03:00
Alibek Omarov
a0edfd28b2 engine: common: host: use DEFAULT_ALLOWCONSOLE macro to set default console state 2023-02-09 05:56:11 +03:00
Alibek Omarov
555fd02407 defaults: reorganize platform default overrides, disable touch for nswitch 2023-02-09 05:55:35 +03:00
Alibek Omarov
f7f9cfecfc ci: nswitch: use waf install to copy build artifacts 2023-02-09 05:35:30 +03:00
Alibek Omarov
2aeee59a31 Merge remote-tracking branch 'fgsfds/switch_newer' 2023-02-09 05:18:06 +03:00
Alibek Omarov
12b8965a8c mainui: update 2023-02-08 20:01:06 +03:00
Alibek Omarov
b5b6b8b785 engine: network: fix some unitialized sockaddr_storage's 2023-02-08 20:00:51 +03:00
fgsfds
35e073ceff ci: nswitch: don't forget filesystem_stdio 2023-02-08 01:53:26 +01:00
fgsfds
b2cc96cf0d scripts: wscript: nswitch: do the libstdc++ hack right before build to not pollute the environment 2023-02-08 01:37:35 +01:00
fgsfds
f7489a3747 scripts: nswitch: it's arm64, not aarch64 2023-02-08 01:04:31 +01:00
fgsfds
0e7ebf6d44 Merge branch 'master' of https://github.com/FWGS/xash3d-fwgs into switch_newer 2023-02-08 00:56:20 +01:00
fgsfds
69607d7890 nswitch: do not link libstdc++ into dynamic libraries
instead only link it to the main executable with --whole-archive, letting the dynamic libs import anything they want from it
2023-02-08 00:52:48 +01:00
fgsfds
4e87eb068a engine: common: nswitch: use #if instead of #ifdef 2023-02-07 23:03:59 +01:00
Alibek Omarov
03a7c67731 public: build: revert arm64 renaming to aarch64, we shouldn't enforce naming changes without a reason 2023-02-08 00:03:15 +03:00
Alibek Omarov
5ba2449d10 engine: common: static-ify functions in mod_studio.c 2023-02-08 00:03:15 +03:00
fgsfds
0ee2fd8a8a ci: nswitch: do not dumb, 00 penalty 2023-02-07 20:52:23 +01:00
fgsfds
080b9b30a1 ci: nswitch: do not put the pkgtemp folder into the .7z 2023-02-07 20:45:42 +01:00
fgsfds
749ac5ed54 ci: nswitch: do not rely on dkp-pacman at all 2023-02-07 20:38:40 +01:00
fgsfds
6c8b9af6bb ci: nswitch: fix artifact packaging 2023-02-07 20:35:24 +01:00
fgsfds
07922c0239 ci: nswitch: actually set env vars properly 2023-02-07 20:26:24 +01:00
fgsfds
1a54ec92e0 github: ref name not required 2023-02-07 20:26:13 +01:00
fgsfds
663b574b8b github: checkout the switch_newer branch for now 2023-02-07 20:22:30 +01:00
fgsfds
430c51b71a ci: nswitch: there is no python-is-python3 where we're going 2023-02-07 20:14:11 +01:00
fgsfds
20bcd03f19 ci: nswitch: ...and set it to be the default python install 2023-02-07 20:07:48 +01:00
fgsfds
dab959fc32 ci: nswitch: the docker container is missing python, install it 2023-02-07 20:04:36 +01:00
fgsfds
eff75e5d50 ci: nswitch: the docker container is missing dkp-toolchain-vars, install it 2023-02-07 20:00:49 +01:00
fgsfds
d103f022b4 ci: nswitch: forgot run 2023-02-07 19:55:33 +01:00
fgsfds
72b8246969 ci: nswitch: attempt to use dkp's docker image
because they banned the ci server from accessing their pacman repo
2023-02-07 19:54:00 +01:00
fgsfds
030d05f018 ci: nswitch: make install with sudo 2023-02-07 18:38:18 +01:00
fgsfds
59cd5493e7 github: add nswitch build target 2023-02-07 18:35:08 +01:00
fgsfds
98a7f6fa3f ci: add nswitch build scripts 2023-02-07 18:34:58 +01:00
fgsfds
65095df124 Merge branch 'master' of https://github.com/FWGS/xash3d-fwgs into switch_newer 2023-02-07 17:15:01 +01:00
fgsfds
ee370ea007 Merge branch 'master' of https://github.com/FWGS/xash3d-fwgs into switch_newer 2023-02-07 17:14:47 +01:00
Alibek Omarov
05016f8639 engine: vgui: add EnableTextInput to the API 2023-02-06 16:42:09 +03:00
Alibek Omarov
12154de6f5 ref: soft: fix -Wsequence-point 2023-02-06 16:42:09 +03:00
Alibek Omarov
3fca567b81 wscript: few more warnings-as-errors 2023-02-06 16:42:09 +03:00
Alibek Omarov
634574f249 engine: platform: sdl: don't enable text mode with cursor??? 2023-02-06 00:29:14 +03:00
fgsfds
f782d444a8 engine: platform: posix: don't redefine _GNU_SOURCE 2023-02-06 00:05:41 +03:00
fgsfds
b68def2b9c engine: touch: only pop up touch keyboard on FINGERDOWN events 2023-02-06 00:05:32 +03:00
fgsfds
d944301a60 engine: client: add barebones gamepad controls to input fields 2023-02-06 00:05:28 +03:00
fgsfds
15ba932046 engine: server: add sv_autosave cvar
* a1ba: added FCVAR_PRIVILEGED just in case
2023-02-06 00:05:20 +03:00
fgsfds
b73c16c216 engine: net_ws: pass correct sockaddr lengths where needed 2023-02-05 23:51:48 +03:00
fgsfds
0ba4ef678c engine: net_ws: pass correct sockaddr lengths where needed 2023-02-05 03:39:32 +01:00
fgsfds
919d510f63 Merge branch 'master' of https://github.com/FWGS/xash3d-fwgs into switch_newer 2023-02-05 02:37:40 +01:00
fgsfds
6557ac7fb4 server: add sv_autosave cvar 2023-02-05 02:29:22 +01:00
Alibek Omarov
87c307f47e scripts: flatpak: install vgui 2023-02-05 04:27:58 +03:00
fgsfds
f3e50b5500 add barebones gamepad controls for input fields and console 2023-02-05 02:27:12 +01:00
fgsfds
705f252ed8 nswitch: don't automatically pop up OSK when opening console 2023-02-05 02:26:48 +01:00
fgsfds
cb28101732 touch: only pop up OSK on FINGERDOWN events 2023-02-05 02:26:17 +01:00
fgsfds
f87863b8bc nswitch: always enable console 2023-02-05 02:18:11 +01:00
fgsfds
25fb89f717 nswitch: don't redefine O_BINARY 2023-02-05 02:16:56 +01:00
fgsfds
36e7856b9c don't redefine _GNU_SOURCE 2023-02-05 02:16:38 +01:00
Alibek Omarov
34b0cdc125 scripts: flatpak: use relative paths as RoDir doesn't allow absolute paths for now 2023-02-05 04:13:45 +03:00
fgsfds
25a1cb8ce7 Nintendo Switch support (again) 2023-02-05 02:09:32 +01:00
Alibek Omarov
a610b1545b scripts: flatpak: check .local directory for steam library 2023-02-05 03:44:58 +03:00
Alibek Omarov
30b698067a scripts: flatpak: allow easy debugger attach 2023-02-05 03:25:07 +03:00
Alibek Omarov
f63f1a0dc6 scripts: flatpak: add another default Steam library path 2023-02-05 02:43:36 +03:00
Alibek Omarov
9cb867a7d4 filesystem: wad: print errno if wad can't be opened 2023-02-05 02:42:35 +03:00
Alibek Omarov
00ddd95c27 scripts: flatpak: try to add ourselves to desktop menu entries 2023-02-05 02:25:21 +03:00
Alibek Omarov
0ffd1b9ff1 github: try to enable building flatpak bundle 2023-02-05 00:40:08 +03:00
Alibek Omarov
2109d49aa3 ci: disable xash-extras fetching, it's a submodule now 2023-02-05 00:06:19 +03:00
Alibek Omarov
f910f4896c engine: client: font: finally add support for tab character in engine 2023-02-04 22:53:10 +03:00
Alibek Omarov
6eae3471cf engine: client: font: fix consecutive newlines skipped, add flag to reset color after a newline 2023-02-04 21:59:46 +03:00
Alibek Omarov
c0fa91bec9 engine: client: consolidate client and menu scissor functions 2023-02-04 21:24:19 +03:00
Alibek Omarov
ba6dd3c751 engine: client: font: fix another inverted check 2023-02-04 21:23:51 +03:00
Alibek Omarov
fd63018fb5 engine: client: make client string drawing functions ignore linefeeds 2023-02-04 20:58:33 +03:00
Alibek Omarov
2225915702 engine: client: font: fix CL_DrawStringLen 2023-02-04 20:54:17 +03:00
Alibek Omarov
d14e486721 engine: client: font: add special flag to ignore linefeeds when drawing strings 2023-02-04 20:53:52 +03:00
Alibek Omarov
82b6da493a wscript: enforce GCC suspicious sizeof operations warnings as errors 2023-02-03 18:51:50 +03:00
Alibek Omarov
bec0b36bb9 engine: client: font: fix colorcodes, don't reset Colo4ub, it will be reset by consequent draw calls anyway 2023-02-03 18:20:02 +03:00
Alibek Omarov
e2c2821191 engine: client: font: do not apply filtering hack when fonts aren't upscaled 2023-02-03 18:06:07 +03:00
Alibek Omarov
a19d34035d engine: client: font: do not use OpenFile on WADs >_< 2023-02-03 17:49:06 +03:00
Alibek Omarov
77ea03a62c engine: client: introduce bare-bones font manager and text drawing manager
* wire hud_fontscale so HUD font scaling can be used independently from
  hud_scale
* allow small optimizatinons, like optional UTF-8 decoding, or not calling
  SetRenderMode for each character
* even less copypasted code in text drawing between client code and console
* get rid of direct DrawCharacter calls when it can be just DrawString
* fix net_speeds, r_speeds with scaled console fonts
* try to fix MobilityAPI's pfnDrawCharacterScaled
* center keyboard keys in OSK code
2023-02-03 08:51:18 +03:00
Alibek Omarov
402a0f129d engine: platform: sdl: use SDL joystick rumble for Platform_Vibrate 2023-02-03 08:50:41 +03:00
Alibek Omarov
d7116afc92 engine: client: add hud_fontscale cvar to control HUD font scaling (not wired to any logic yet) 2023-02-02 04:57:53 +03:00
Alibek Omarov
d5fe491c14 engine: client: add a little auto-disconnect message in case of server timeout 2023-02-02 02:49:25 +03:00
Alibek Omarov
92138428c5 engine: touch: don't emulate touch and mouse through SDL2 (taken from @Velaron branch) 2023-02-01 06:42:31 +03:00
Alibek Omarov
f3ff942ea9 scripts: flatpak: add basic i386 flatpak script 2023-02-01 04:58:12 +03:00
Alibek Omarov
ced6e8869a ref: fix chrome texture being misaligned 2023-02-01 04:55:47 +03:00
Alibek Omarov
d7af50ea6c engine: ref: remove direction vectors from Ref API, renderers calculate them from viewangles to local data anyway 2023-01-31 07:18:23 +03:00
Alibek Omarov
f7d4e5a2ea engine: server: don't show GAMESAVED message in autosaves, small refactoring 2023-01-31 07:16:08 +03:00
Alibek Omarov
2e3788f23d engine: dedicated: add CL_HudMessage to dedicated stubs 2023-01-31 07:14:26 +03:00
Alibek Omarov
eaf9a9283a Revert "engine: network: do not read from uninitialized sockaddr storage"
This reverts commit 4f78ec01cf.
2023-01-31 04:33:27 +03:00
Alibek Omarov
ae66291272 scripts: compiler_optimizations: added MSan target 2023-01-31 04:28:08 +03:00
Alibek Omarov
4f78ec01cf engine: network: do not read from uninitialized sockaddr storage 2023-01-31 04:14:18 +03:00
Alibek Omarov
be084d5603 engine: crashhandler: fully initialize struct sigaction 2023-01-31 00:50:48 +03:00
Alibek Omarov
aac0be1ab3 engine: imagelib: img_bmp: fully initialize local palette array 2023-01-31 00:50:04 +03:00
Alibek Omarov
6282acc825 engine: client: simplify drawing loading or paused bar, fix position with hud_scale active 2023-01-30 23:17:53 +03:00
Alibek Omarov
39fd30a472 engine: client: fix HUD font loading 2023-01-27 19:07:26 +03:00
Alibek Omarov
279e391949 engine: sound: allow mouth move for CHAN_STREAM 2023-01-27 06:19:31 +03:00
Alibek Omarov
6df25392b8 engine: server: redirect special sounds, detected by leading asterisk, into CHAN_STREAM
In GoldSrc this magic symbol means that we should not override channel this
sound is playing on. Originally handled on client but for both static and dynamic sounds
so let's redirect channel on server side instead.
2023-01-27 06:19:31 +03:00
Alibek Omarov
327372e253 engine: client: call SND_ForceOpen/CloseMouth within SND_Open/CloseMouth to avoid copypasted code 2023-01-27 06:19:31 +03:00
Andrey Akhmichin
801dbaa387 engine: common: soundlib: libmpg: backport fix for CVE-2017-11126.
Original patch: https://www.mpg123.de/cgi-bin/scm/mpg123/trunk/src/libmpg123/layer3.c?view=patch&r1=4275&r2=4274
Same as: f246a0cdfd
2023-01-25 15:57:52 +03:00
Andrey Akhmichin
ffd5c2d3d0 engine: common: soundlib: libmpg: backport fix for CVE-2017-12839.
Original patch: https://www.mpg123.de/cgi-bin/scm/mpg123/trunk/src/libmpg123/getbits.h?view=patch&r1=2024&r2=4323
Same as: 8a5e21a2a2
2023-01-25 15:57:52 +03:00
Alibek Omarov
84c14b32ec engine: client: fix filtering errors by adjusting texcoords by half of a pixel
Remove useless wrapper functions and conversions
Don't scale texcoords and position if hud_scale is not active
2023-01-25 04:17:48 +03:00
Alibek Omarov
c481e52558 engine: client: consolidate variable and quake fixed width font loading functions 2023-01-25 02:38:18 +03:00
Alibek Omarov
b946ed4625 engine: platform: sdl: don't flood about closest display mode in case of no changes 2023-01-18 20:05:00 +03:00
Alibek Omarov
ef1572b15b engine: crashhandler: fix build on FreeBSD (and probably on NetBSD and OpenBSD) 2023-01-18 19:45:21 +03:00
Alibek Omarov
aaeb18f433 engine: inline version of MSG_BigShort 2023-01-18 19:29:27 +03:00
Alibek Omarov
dd1d86c289 engine: platform: sdl: check usable display rect before creating window 2023-01-18 19:28:16 +03:00
Alibek Omarov
16b162f7bb engine: vid: position window in center by default 2023-01-18 19:27:40 +03:00
Alibek Omarov
500ca54550 Revert "engine: get rid of MSG_BigShort, use htons instead, since network headers are always included"
This reverts commit a6475f530b.
2023-01-18 19:21:51 +03:00
Alibek Omarov
5313dc9475 engine: client: fix uninitialized fadeTotalEnd in screenfade parsing code 2023-01-16 09:21:30 +03:00
Alibek Omarov
9c0c1a802c filesystem: fix strict order of loading archives 2023-01-15 13:12:39 +03:00
Alibek Omarov
fbedbdca7d engine: client: fix fullscreen reapplied on window resize 2023-01-14 18:52:38 +03:00
Alibek Omarov
6232e288e1 engine: client: fool proof R_SaveVideoMode 2023-01-14 11:45:42 +03:00
Alibek Omarov
a6475f530b engine: get rid of MSG_BigShort, use htons instead, since network headers are always included 2023-01-14 10:58:04 +03:00
Alibek Omarov
de84df99f3 engine: fix functions returning void returning void value 2023-01-14 10:58:03 +03:00
Alibek Omarov
a5d5c1f60b wscript: cast-align is less effective than ubsan 2023-01-14 10:58:03 +03:00
Alibek Omarov
6ac3156a82 engine: fix discarded const pointer qualifier in PM_HullPointContents 2023-01-14 10:57:22 +03:00
Alibek Omarov
2705e77a4e ci: don't spew config.log when it's not needed, less verbosity 2023-01-14 10:06:32 +03:00
Alibek Omarov
a09aa31b7a github: comment out CI builds for MAGX and Android 2023-01-14 09:52:44 +03:00
Xav101
9466461ce0 engine: preliminary support for SGI IRIX (#1211)
* Added definitions for IRIX

* Patchset to get dedicated server to compile on IRIX.

* Cleaned up debug statements in wscript

* Potential bug in IRIX implementation of isnan? For now just use the portable macro.

* Include the platform port files in the build

* Temporary execution script for setting appropriate library search paths to the right locations in the build directory. This should probably get replaced with a more permanent script at some point which lives in the same directory as the normal xash binary, or be replaced by a solution that sets the rpath during config or modifies rpath during install.

* Clean up formatting and remove unneeded debugging statements

* Added GPL copyright notice and description

* Moved to irix platform folder and edited script

* Re-introduced _inline macro

* Replace spaces with tabs

Co-authored-by: Xav101 <xaviernye@msn.com>
2023-01-14 09:35:30 +03:00
Alibek Omarov
74ce7e9b10 ref: don't apply rendercolor to studio models where it's not needed 2023-01-13 15:25:58 +03:00
Alibek Omarov
10481a4ecc github: upgrade SDL2 2023-01-13 11:50:01 +03:00
Alibek Omarov
acd86ce490 engine: sound: select which to buffer raw channels will be painted to, choose stream buffer for voice 2023-01-13 08:50:33 +03:00
Alibek Omarov
1119a9ac22 engine: network: reenable DNS resolving in separate thread for Windows 2023-01-13 08:09:16 +03:00
Alibek Omarov
171c0c8d3b engine: common: zone: use stdint types 2023-01-12 04:04:53 +03:00
Alibek Omarov
9b5e0fef01 engine: common: zone: make Mem_Alloc return aligned addresses on ILP32, thanks Xav101 on Discord for heads up 2023-01-12 04:02:04 +03:00
Alibek Omarov
2f5e3b0aea mainui: update 2023-01-11 13:41:54 +03:00
Alibek Omarov
ca3b0e6246 Documentation: document the _i?86 quirk in library naming scheme 2023-01-10 04:59:28 +03:00
Alibek Omarov
eb0459a045 engine: strip Intel suffixes from server library name, but only on special platforms
Remove same code from filesystem, it's not what filesystem should do
2023-01-10 04:51:34 +03:00
Alibek Omarov
5d98e13fb8 public: add Q_ArcitectureStringByID function to get library naming compliant CPU and ABI string 2023-01-09 22:53:05 +03:00
Alibek Omarov
113904ea91 public: fix build 2023-01-09 22:47:54 +03:00
Alibek Omarov
1dc3cc2d57 public: add Q_PlatformStringByID function that returns library naming compliant string by platform identifier from buildenums 2023-01-09 08:06:58 +03:00
Alibek Omarov
15a5975abf public: build.h refactoring, removed XASH_MSVC, XASH_MINGW, as this header never intended to detect the compiler 2023-01-09 08:05:59 +03:00
Alibek Omarov
65debeb738 public: add header buildenums.h declaring all platforms, architectures and ABIs as integer constants. 2023-01-09 08:04:58 +03:00
Alibek Omarov
209a03a12a engine, public: prepare to removal of XASH_MSVC macro 2023-01-09 08:01:52 +03:00
Alibek Omarov
c28aeb2362 engine: make crashhandler implementation choice private to crashhandler code 2023-01-09 07:55:54 +03:00
Alibek Omarov
9152bbf106 engine: client: more accurate decompilation of CL_LerpPoint and ComputeInterpolationAmount 2023-01-07 11:08:32 +03:00
Alibek Omarov
40ba0238f8 engine: client: cosmetic changes in pmove code 2023-01-07 11:07:32 +03:00
Alibek Omarov
4a3efa511c engine: client: correctly decompiled version of CL_AdjustClock (with removed useless float-to-int operation) 2023-01-07 07:23:14 +03:00
Alibek Omarov
2479d28cd5 engine: remove useless pfnHullPointContents wrapper 2023-01-06 00:38:05 +03:00
Alibek Omarov
787d3bc5dd engine: share playermove ClearPhysEnts function 2023-01-06 00:28:24 +03:00
Alibek Omarov
0bec78a958 engine: client: make few function between pmove and client interface shared, remove unused CL_PointContents wrapper 2023-01-06 00:09:36 +03:00
Alibek Omarov
e305b81df0 engine: merge PM_TraceTexture into PM_TraceTexturePmove 2023-01-05 23:59:31 +03:00
Alibek Omarov
4cb109abe0 engine: make playermove funcs truly shared between client and server 2023-01-05 23:50:42 +03:00
Alibek Omarov
49a65edfc3 engine: imagelib: img_quant: fix a bug in quantizer (thanks, @SNMetamorph for fix) 2023-01-05 07:24:24 +03:00
Alibek Omarov
c6bfc82019 ref: soft: implement screenshots 2023-01-05 07:09:23 +03:00
Alibek Omarov
a4865fd2fc engine: client: fix ScreenFade FFADE_MODULATE rendering, more accurate alpha blending 2023-01-05 06:09:10 +03:00
Alibek Omarov
4bbd0cc404 ref: add new special rendermode that specifically used for modulate mode in engine's ScreenFade 2023-01-05 06:07:56 +03:00
Alibek Omarov
4684f174ee public: completely get rid of PATH_SEPARATOR macros 2023-01-05 06:06:07 +03:00
Alibek Omarov
34eb258cae filesystem: dir: remove PATH_SEPARATOR, fix return value when directory is caseinsensitive 2023-01-04 22:34:45 +03:00
Alibek Omarov
b4c0ccbede filesystem: fix _wstat usage under Windows, remove PATH_SEPARATOR usage, fix listdirectory 2023-01-04 22:33:59 +03:00
Alibek Omarov
51b5d7a41d engine: host: ensure we always have right slashes under Windows 2023-01-04 19:39:52 +03:00
Alibek Omarov
15846a8ea8 filesystem: use POSIX funcs for Windows too, where possible, apply wide char conversion for Sys functions 2023-01-04 18:10:33 +03:00
Alibek Omarov
e694081626 filesystem: dir: guarantee file existense in FS_FixFileCase for caseinsensitive directories 2023-01-04 18:09:00 +03:00
Alibek Omarov
cb9605430d filesystem: bump FS_API_VERSION (removed unused argument from SysFileExists) 2023-01-04 18:07:18 +03:00
Alibek Omarov
80507b2eca engine: mod_bmodel: fix const qualifier discard warning 2023-01-04 17:55:59 +03:00
Alibek Omarov
ed47346ef1 engine: crashhandler: fix _GNU_SOURCE redefined warning 2023-01-04 17:54:45 +03:00
Alibek Omarov
75ccd2283b public: fix Q_memmem counting haystack size incorrectly 2023-01-04 17:17:18 +03:00
Alibek Omarov
409edf5a70 filesystem: zip: use stdint types, use enum for errors 2023-01-04 17:15:40 +03:00
Alibek Omarov
d047dfc319 engine: add few lines in mod_bmodel back, got removed in previous commits accidentally 2023-01-03 18:26:18 +03:00
Alibek Omarov
13ed2742b2 engine: check for bsp30ext before trying to use extended clipnodes, fix 32-bit clipnodes check 2023-01-03 07:50:50 +03:00
Alibek Omarov
03a3fb83b6 filesystem: write extended fields to gameinfo.txt, as this function is used to write game info when using rodir 2023-01-03 07:34:05 +03:00
Alibek Omarov
df1c9a5029 engine: simplify blue shift swapped lump check, change TestBmodelLumps to avoid reading past mod buffer 2023-01-03 07:01:39 +03:00
Alibek Omarov
07e622f224 public: add generic implementation for Q_memmem 2023-01-03 06:58:58 +03:00
Alibek Omarov
aa3a0fa392 engine: server: increase infostring size in SV_Info allowing longer hostnames but try to cut off if it's even longer than that 2023-01-03 04:01:53 +03:00
Alibek Omarov
c1287b3950 engine: client: speed up reconnect for legacy servers 2023-01-03 03:19:46 +03:00
Alibek Omarov
e5763e2e9a filesystem: dir: check dir casesensitivity after dir entries list was properly initialized 2023-01-03 01:15:28 +03:00
Alibek Omarov
42a3c7b059 filesystem: dir: fix dir entry cache init in case of directory was empty previously 2023-01-03 00:24:57 +03:00
Alibek Omarov
e621c98602 engine: network: do not crash if one of v4 or v6 socket opening failed but crash if both. Fix hostport/clientport cvars usage 2022-12-30 02:06:15 +03:00
Alibek Omarov
eb7eb4acbc engine: client: cl_scrn: minor refactoring 2022-12-30 01:58:26 +03:00
Alibek Omarov
e5b32fe8ac engine: client: force nearest filter for HUD textures and sprites to avoid artifacts with hud_scale 2022-12-30 01:57:10 +03:00
Alibek Omarov
52061621ac engine: client: do not let client.dll overwrite usercmd that's was read from demo 2022-12-27 23:10:11 +03:00
Alibek Omarov
339711c3c7 filesystem: dir: check casefold directory flag 2022-12-27 02:31:46 +03:00
Alibek Omarov
256fe7ede9 scripts: make sure to test filesystem on CI 2022-12-27 02:31:46 +03:00
Alibek Omarov
2febe632c5 filesystem: add caseinsensitive emulation test 2022-12-27 02:31:46 +03:00
Alibek Omarov
c454e37064 filesystem: allow to init with NULL overrides 2022-12-27 02:31:46 +03:00
Alibek Omarov
fe1aba3561 filesystem: apply caseinsensitivity to file creation
Replace fs_writedir with fs_writepath, exposing current writeable searchpath.
Fix caseinsensitive FS_Search
Remove unused argument from listdirectory()
Minor optimizations and refactoring
2022-12-27 02:31:46 +03:00
Alibek Omarov
41aa867a21 engine: common: don't try to delete now non-existing config file after backing up 2022-12-27 02:31:46 +03:00
Alibek Omarov
b36ebc294f filesystem: dir: exit from loop immediately if directory is caseinsensitive 2022-12-27 02:31:46 +03:00
Alibek Omarov
3d71e5d111 filesystem: dir: fix merging existing cache with new directory entries 2022-12-27 02:31:46 +03:00
Alibek Omarov
ac59f25375 DO NOT MERGE filesystem: add naive FixFileCase 2022-12-27 02:31:46 +03:00
Alibek Omarov
3393e2d95c filesystem: implement directory entries caching, to avoid excessive directory listing syscalls to emulate case-insensitive filesystems
* simplify game directory initialization code
2022-12-27 02:31:46 +03:00
Alibek Omarov
e1ea3387ee common: rename PATH_SPLITTER to PATH_SEPARATOR, change it's type to character 2022-12-27 02:31:46 +03:00
Alibek Omarov
071638794a public: redefine Q_strpbrk to C standard version, add Q_strchrnul 2022-12-27 02:31:46 +03:00
Alibek Omarov
953dd3d1a7 wscript: tidy up checks, add check for GNU strchrnul 2022-12-27 02:31:46 +03:00
Andrey Akhmichin
12bb0ca44b engine: server: Fix broken description for saves. 2022-12-25 04:26:00 +03:00
MoeMod Server #2
499cd48e83 filesystem: fix lseek for mpg123 2022-12-24 22:02:58 +03:00
Andrey Akhmichin
444e08f59a engine: common: simplify strings operations. 2022-12-21 03:26:41 +03:00
Andrey Akhmichin
9450c08eec engine: server: simplify strings operations. 2022-12-21 03:26:11 +03:00
Alibek Omarov
18e68f1ab3 filesystem: fix missing cast 2022-12-20 16:34:23 +03:00
Andrey Akhmichin
7555fefc18 ref: gl: simplify strings operations. 2022-12-20 16:11:21 +03:00
Andrey Akhmichin
f4fb8b4ac2 engine: client: simplify strings operation. 2022-12-20 16:07:34 +03:00
Andrey Akhmichin
0d5cd89144 engine: client: Fix access to uninitialized variable. 2022-12-20 16:06:41 +03:00
Andrey Akhmichin
e273e09fc9 engine: platform: win32: simplify strings operations. 2022-12-20 16:06:25 +03:00
Alibek Omarov
327017421c engine: common: zone: redefine poolhandle_t back to pointer for 32-bit systems 2022-12-19 18:38:49 +03:00
Alibek Omarov
6e179346c9 common: redefine poolhandle_t back to pointer for 32-bit systems 2022-12-19 18:36:31 +03:00
Alibek Omarov
ee218f36e0 filesystem: pak: no need to free files ptr anymore 2022-12-17 00:25:20 +03:00
Alibek Omarov
f3400c983e engine: network: fix address comparator 2022-12-15 12:25:03 +03:00
Alibek Omarov
9397301a73 filesystem: remove excessive filename field from archive structs, use common in searchpath_t. Small optimizations for PAK 2022-12-15 04:06:38 +03:00
Alibek Omarov
f1ec612819 filesystem: hungry 2022-12-15 01:06:20 +03:00
Alibek Omarov
08f834cd82 filesystem: make all archive searchpath functions private 2022-12-15 00:59:52 +03:00
Alibek Omarov
48c17d08d9 filesystem: dir: move searchpath initialization to dir.c, make all DIR functions static 2022-12-15 00:52:09 +03:00
Alibek Omarov
f20fddee1c common: bspfile: add separate definitions for clipnodes limit for HLBSP and QBSP2 2022-12-15 00:42:40 +03:00
Alibek Omarov
754d55beef engine: common: fix for HLBSP extended clipnodes hack when BSP2 support is enabled 2022-12-13 11:34:42 +03:00
Alibek Omarov
cd813bbfbe engine: server: do not apply sound precache check for sentences, as they may start with 0 index 2022-12-13 11:12:08 +03:00
Alibek Omarov
07afbd64d4 engine: common: host: force set HOST_FRAME status for dedicated as it finished initializing 2022-12-13 10:54:06 +03:00
Alibek Omarov
af7d6f6fa8 engine: common: no point to allow if and else commands in unprivileged mode since scripting is available only for privileged 2022-12-12 08:18:00 +03:00
Alibek Omarov
cb0f513bf0 engine: common: allow cvar substituion in privileged mode only to prevent leaking sensitive data 2022-12-12 08:14:01 +03:00
Alibek Omarov
a3ef6c955c engine: don't double register rcon_password cvar 2022-12-12 08:13:24 +03:00
Alibek Omarov
60e7a7aa23 engine: server: set correct flags for rcon_ cvars on server 2022-12-12 08:05:55 +03:00
Alibek Omarov
e1431e1040 engine: server: add rcon_enable cvar to control whether server should accept remote commands 2022-12-12 08:02:56 +03:00
Alibek Omarov
b794f2fda0 mainui: update 2022-12-12 07:56:03 +03:00
Alibek Omarov
934d9ba69a filesystem: fix FS_GetDiskPath 2022-12-12 06:54:42 +03:00
Alibek Omarov
9e54ddfd55 engine: client: treat dem_unknown as no-op, until we find real cause of empty holes in demoheader 2022-12-12 06:31:54 +03:00
Alibek Omarov
a86a24d33d mainui: update 2022-12-12 06:30:47 +03:00
Alibek Omarov
fe9ed0ac9b engine: client: gameui: add new NET_CompareAdrSort function to menu API 2022-12-12 06:30:47 +03:00
Alibek Omarov
18c94b6ec4 engine: common: add network address comparator function 2022-12-12 06:30:47 +03:00
SNMetamorph
8fa0290e25 Documentation: extensions: added page about expanded common structures 2022-12-11 22:59:17 +03:00
SNMetamorph
080cd146dd common: com_model: changed common structs reserved fields type to intptr_t 2022-12-11 22:59:17 +03:00
SNMetamorph
b1d910a3a5 engine: client: fixed connection hang when all resources downloaded (fix #829) 2022-12-09 19:20:53 +03:00
SNMetamorph
840283d6e5 engine: netchan: fixed fragbufs very high memory usage 2022-12-09 19:20:53 +03:00
SNMetamorph
d72481e5ac engine: netchan: fixed downloading files output directory 2022-12-09 19:20:53 +03:00
SNMetamorph
dbe9309475 engine: netchan: fixed wrong compressed file size calculation 2022-12-09 19:20:53 +03:00
Alibek Omarov
9fa4de6ee8 mainui: update 2022-12-08 06:55:32 +03:00
Alibek Omarov
fd3c5e8384 ref: gl: VBO is disabled unless somebody picks it up and fixes memory corruption and other bugs 2022-12-08 06:50:12 +03:00
Alibek Omarov
d50ed1c087 engine: common: host: don't prepend # to command arguments when changing game to dedicated, it wasn't used and implement anymore 2022-12-08 05:44:17 +03:00
Alibek Omarov
e48133bf4b engine: server: fix sv_log output for enttools usage 2022-12-08 05:40:36 +03:00
Alibek Omarov
ea3bfd969c engine: imagelib: img_wad: dirty hack to fix black holes in console background images 2022-12-08 05:40:11 +03:00
Alibek Omarov
7469d6a248 engine: server: implement server-to-master challenge extension, to secure server from IP spoofing 2022-12-07 23:39:57 +03:00
Alibek Omarov
859f36afce engine: server: remove Master_Add call in ActivateServer, server will announce itself through heartbeat 2022-12-07 23:14:34 +03:00
Alibek Omarov
436a788ac8 engine: client: disable FPS counter by default 2022-12-07 21:54:23 +03:00
Velaron
5098e24806 engine: client: touch: fix empty list when opening touch buttons menu for the first time 2022-12-07 15:35:51 +03:00
Alibek Omarov
1d8acc16f1 engine: server: give master server a small time window to reply (by default 4000 ms, should be enough even when master server is overloaded) 2022-12-06 20:28:44 +03:00
Alibek Omarov
802c7a86a9 engine: platform: sdl: add pause and scrolllock handlers 2022-12-06 11:50:38 +03:00
Alibek Omarov
406eb828da ref: gl: disable underwater distortion by default, enable for Quake compatible mode only 2022-12-05 11:59:29 +03:00
Alibek Omarov
0e9106685b engine: imagelib: img_png: fix Mem_Free on null ptr 2022-12-05 06:13:04 +03:00
Alibek Omarov
9b001987e9 engine: imagelib: fix crash when chunk length is more than file size 2022-12-05 05:39:41 +03:00
Alibek Omarov
5c2c02c317 engine: common: custom: use IL_LOAD_PLAYER_DECAL flag when loading custom player decals 2022-12-05 04:56:07 +03:00
Alibek Omarov
21c898d796 engine: imagelib: validate player decal image size (max 512x512) 2022-12-05 04:55:24 +03:00
Alibek Omarov
e48b708fa6 engine: imagelib: img_png: validate image size through common engine function 2022-12-05 04:54:20 +03:00
Alibek Omarov
ccf7619ae5 engine: imagelib: refactor image loading function 2022-12-05 03:22:07 +03:00
Alibek Omarov
eabbd0061f mainui: update 2022-12-05 03:22:07 +03:00
Alibek Omarov
7d0d6b8e0d engine: common: host: implement adaptive sleeptime, log time to first time for debug purposes 2022-12-05 03:22:07 +03:00
Alibek Omarov
eb36fe0155 filesystem: fill searchpath DIR functions only if file was found in direct path 2022-12-05 03:22:07 +03:00
Alibek Omarov
9381a40506 filesystem: check only DLLs for encryption 2022-12-05 03:22:07 +03:00
SNMetamorph
a19270a0dc engine: client: max fragment size test retries increased to 3 2022-12-04 23:29:26 +03:00
SNMetamorph
c34ce2d9e1 engine: client: fixed max fragment size wrong calculation 2022-12-04 23:29:26 +03:00
SNMetamorph
58465c3727 engine: common: fixed dedicated server bug
The problem is server wasn't executing server.cfg if map specified in startup parameters
2022-12-04 23:29:26 +03:00
Andrey Akhmichin
177ed2c603 engine: common: simplify strings operations. 2022-12-04 22:37:45 +03:00
Andrey Akhmichin
7bb994f7bc engine: common: imagelib: img_png.c: fix wrong palette decoding. 2022-12-04 22:09:24 +03:00
Andrey Akhmichin
0c4f35e2d0 filesystem: simplify strings operations. 2022-12-04 22:08:06 +03:00
Andrey Akhmichin
3287501f97 engine: client: simplify strings operations. 2022-12-04 22:04:07 +03:00
Andrey Akhmichin
2454594a18 engine: server: simplify strings operations. 2022-12-04 22:03:48 +03:00
Alibek Omarov
4daab23e2d mainui: update 2022-12-04 05:31:02 +03:00
Alibek Omarov
51161004eb engine: common: simplify string operations 2022-12-04 05:26:22 +03:00
Alibek Omarov
6477f1656e filesystem: simplify string operation 2022-12-04 05:26:22 +03:00
Alibek Omarov
270e2a76a8 engine: soundlib: simplify string operation 2022-12-04 05:26:22 +03:00
Alibek Omarov
c61442e960 engine: imagelib: simplify string operation 2022-12-04 05:26:22 +03:00
Alibek Omarov
d0928af355 mainui: update to png-decals branch 2022-12-04 05:26:22 +03:00
Alibek Omarov
674093517e 3rdparty: update various submodules 2022-12-02 21:29:51 +03:00
Alibek Omarov
ebf3877cda engine: common: throw an error message into log in normal mode too! 2022-12-02 21:22:22 +03:00
Alibek Omarov
e97310c441 engine: common: net_ws: fix uninitialized family in IPSocket 2022-12-02 21:21:53 +03:00
Alibek Omarov
cbe3e608b6 engine: client: add cl_logoext cvar that's used by mainui to tell the engine which logo must be packed 2022-12-01 18:25:21 +03:00
Alibek Omarov
f30f23ba51 engine: common: validate and load PNG images in customization 2022-12-01 18:25:11 +03:00
Alibek Omarov
1ba117a8e9 engine: client: netgraph: fix few global-buffer-overflow errors 2022-12-01 18:23:52 +03:00
Alibek Omarov
d9a245dcb5 engine: reset cheat cvars on remote games 2022-12-01 02:44:01 +03:00
Alibek Omarov
9cbf5ab6a6 engine: client: streamline constructing master server scan request through common function 2022-12-01 01:51:07 +03:00
Alibek Omarov
c9e4e62474 engine: client: allow IPv6 in NetAPI 2022-12-01 00:35:05 +03:00
Alibek Omarov
aa6a1db0a9 engine: remove duplicate svc_strings definition 2022-12-01 00:34:33 +03:00
Alibek Omarov
e9d66be10a mainui: update 2022-11-29 13:30:06 +03:00
Alibek Omarov
8b6f12418e engine: common: make few network cvars privileged 2022-11-29 13:29:47 +03:00
Alibek Omarov
7013d447ca engine: client: get rid of s_registration_sequence, it was incorrect way to look for unused sounds. We're trying to rely on cl.servercount here 2022-11-28 07:54:24 +03:00
Alibek Omarov
93b2f535e2 engine: client: tune max commands/max backup commands values for legacy protocol 2022-11-27 18:26:53 +03:00
Alibek Omarov
591d572870 mainui: update 2022-11-27 06:02:42 +03:00
SNMetamorph
3ab749cc2e engine: client: cl_tent: fixed incorrect players spray textures update 2022-11-27 04:50:30 +03:00
SNMetamorph
084fac3606 engine: common: hpak: fixed rest of bugs in HPAK_AddLump 2022-11-27 04:50:30 +03:00
Alibek Omarov
f377461fdf engine: common: made a filter for a filter (lol), so it's possible to play selected games with cl_filterstuffcmd enabled 2022-11-27 04:45:03 +03:00
SNMetamorph
a2971ce939 filesystem: fixed uninitialized pointers in FS_FindFile when fs_ext_path enabled 2022-11-26 02:45:18 +03:00
SNMetamorph
65671d8788 engine: common: minor code fixes in hpak.c 2022-11-25 23:05:48 +03:00
Andrey Akhmichin
809d5f1aa8 engine: client: in_touch.c: add spray button. 2022-11-25 22:32:33 +03:00
SNMetamorph
49fc6143ab engine: common: imagelib: fixed loading 32 bits per pixel BMP files 2022-11-25 22:30:49 +03:00
SNMetamorph
8717843333 engine: common: imagelib: fixed BMP files estimate size calculation with NPOT textures 2022-11-25 22:30:49 +03:00
SNMetamorph
f6d8996968 engine: common: imagelib: added missed BMP compression type macros 2022-11-25 22:30:49 +03:00
Alibek Omarov
9389305072 engine: common: set cl_filterstuffcmd to 1 by default 2022-11-25 22:23:51 +03:00
Alibek Omarov
b6bd4bc6f8 engine: server: precisely set client connected time after they were spawned 2022-11-25 05:45:20 +03:00
Alibek Omarov
4c6fbafd20 mainui: update 2022-11-25 02:37:07 +03:00
Velaron
43c6175918 filesystem: dir.c: safer string operations 2022-11-24 03:19:21 +03:00
Velaron
fcd741e2b8 filesystem: fix FS_FixFileCase behavior 2022-11-24 03:19:15 +03:00
Velaron
89807250e5 filesystem: dir.c: optimize string operations 2022-11-24 03:19:10 +03:00
Velaron
24f7db19d8 filesystem: switch file operations to an interface 2022-11-24 03:19:05 +03:00
SNMetamorph
49d93c0e76 engine: common: custom: increased custom decal size limit to 128Kb, added wrong size warning 2022-11-22 17:59:41 +03:00
SNMetamorph
707c93c32c engine: common: hpak: all file operations made to use gamedir only 2022-11-22 17:59:41 +03:00
SNMetamorph
e204f05726 engine: client: fixed players spray textures not being updated 2022-11-22 17:59:41 +03:00
SNMetamorph
3bd8ad50d2 ref: gl: fixed crash when opening "Customize" menu 2022-11-21 22:52:27 +03:00
Andrey Akhmichin
3488d4e65f public: simplified strings operations. 2022-11-18 19:32:17 +03:00
Alibek Omarov
3da736a1eb engine: server: try to solve issue when server dll has no voice mgr 2022-11-17 21:06:15 +03:00
Alibek Omarov
e30c61c0e2 common: netadr: use static_assert macro 2022-11-17 19:44:47 +03:00
Alibek Omarov
64e97124c3 Merge master to ipv6 2022-11-17 19:34:46 +03:00
Alibek Omarov
46979419ae wscript: check Android's log library globally 2022-11-17 01:23:33 +03:00
Alibek Omarov
30d9b6d844 engine: platform: win32: fix compile 2022-11-17 01:20:01 +03:00
Alibek Omarov
88045ce3be ref: gl: link liblog for Android 2022-11-17 01:08:11 +03:00
Alibek Omarov
dd881d3da9 engine: server: remove duplicate function 2022-11-16 23:37:26 +03:00
Alibek Omarov
76d0608ee1 ref: fix beams end point 2022-11-16 22:54:07 +03:00
Alibek Omarov
a894ca60c6 engine: client: vgui: fix vgui viewport height being limited at 480 pixels 2022-11-16 22:05:31 +03:00
Alibek Omarov
023f6712f9 engine: client: always toggle mouse on when in console, menu or typing chat message 2022-11-16 21:14:48 +03:00
Alibek Omarov
42740149ac engine: client: fix mouse cursor being hidden in background map 2022-11-16 21:02:41 +03:00
Alibek Omarov
7b74015c4d engine: server: check if player can hear other before sending voicedata 2022-11-16 20:59:18 +03:00
Alibek Omarov
57c71efe53 Documentation: fix wrong envvar in windows xcompile instructions, better wording 2022-11-16 04:25:34 +03:00
Alibek Omarov
45de874598 wscript: always load msvc options 2022-11-16 04:20:02 +03:00
Alibek Omarov
aa702f0678 scripts: waifulib: xcompile: add msvc-wine support in cross-compile helper script 2022-11-16 04:19:46 +03:00
Alibek Omarov
927dccc71d Documentation: add simple instructions on how to cross-compile for Windows from normal operating systems 2022-11-16 04:19:07 +03:00
Alibek Omarov
c2a24fbbce engine: client: put internal vgui shutdown AFTER HUD_Shutdown, to simulate default, external behavior 2022-11-14 20:12:10 +03:00
SNMetamorph
ae94a6aeba engine: client: fixed client VGUI API shutdown 2022-11-14 20:09:20 +03:00
Alibek Omarov
e9da43666c engine: client: fix loading internal vgui (thx @SNMetamorph) 2022-11-14 20:08:01 +03:00
Alibek Omarov
d27dd68072 engine: client: vgui: rework loading VGUI and probing client for internal vgui support API 2022-11-12 16:35:18 +03:00
Alibek Omarov
b1ee27a3f3 filesystem: add new token internal_vgui_support to mark client dlls that have internal VGUI implementation(to support other UI systems) 2022-11-12 16:35:18 +03:00
SNMetamorph
32372654c2 engine: server: sv_client: fixed working ent_create command on XashXT/PrimeXT 2022-11-11 16:12:56 +03:00
Alibek Omarov
17d0b19f9e engine: use generic S_USAGE macro everywhere 2022-11-10 13:18:20 +03:00
Alibek Omarov
d13f7f06e4 engine: fix framerate being capped to 60FPS with vsync, remove vid_displayfrequency cvar. Never sleep with vsync or timedemo, for accuracy 2022-11-10 13:05:03 +03:00
Alibek Omarov
f469b56b93 engine: host: only sleep once between frames 2022-11-10 12:42:48 +03:00
Alibek Omarov
ef74f86ce2 Documentation: restore enttools docs from old engine wiki 2022-11-10 12:37:51 +03:00
Alibek Omarov
616cbdb1eb engine: client: change cl_cmdrate and cl_smoothtime default values to match GoldSrc 2022-11-10 12:11:16 +03:00
Alibek Omarov
0a49e69818 engine: introduce Sys_DebugBreak function to raise an exception for debugger 2022-11-10 12:10:48 +03:00
Alibek Omarov
adb8ec1da8 filesystem: try to normalize linux gamedll path for liblist.gam 2022-11-10 11:58:44 +03:00
SNMetamorph
5d73c6cb84 engine: server: backported enttools from old engine 2022-11-10 11:56:10 +03:00
SNMetamorph
afa1d429fe engine: client: backported enttool from old engine 2022-11-10 11:56:10 +03:00
SNMetamorph
d1309c3aeb engine: common: backported "set" command from old engine 2022-11-10 11:56:10 +03:00
SNMetamorph
b35cf6e30c engine: platform: update VGUI cursor state in Platform_SetCursorType 2022-11-08 06:39:09 +06:00
SNMetamorph
8cbe0e5b30 engine: client: vgui: added VGui_UpdateInternalCursorState function 2022-11-08 06:39:09 +06:00
Andrey Akhmichin
c1fe547925 public: update miniz to version 3.0.0 from upstream. 2022-11-06 12:35:04 +06:00
Andrey Akhmichin
1064b41ab2 readme: update. 2022-11-05 10:45:47 +06:00
Andrey Akhmichin
2a6c2e5db4 .github: workflows: update github actions. 2022-11-05 10:43:15 +06:00
Bien Pham
816337a7bb filesystem: set root directory as static
Counter-Strike uses COM_ExpandFileName to get
full path to filesystem_stdio. When reading liblist.gam,
the engine will clear the search path and the root search path
will be cleared. Set it as static so it will be excluded from clearing.
2022-11-02 18:07:25 +06:00
Andrey Akhmichin
d237114962 engine: common: imagelib: img_png.c: unroll loops. 2022-11-02 14:14:05 +06:00
Andrey Akhmichin
c1ca2c1a95 Documentation: opensource-mods.md: add "Oz Deathmatch". 2022-10-27 01:53:27 +06:00
SNMetamorph
44a43c2c09 engine: client: cl_parse: minor code fix in CL_ParseLegacyServerData 2022-10-27 00:52:16 +06:00
SNMetamorph
ee8098839e engine: common: pm_trace: fixed non portable code in PM_ConvertTrace 2022-10-27 00:52:16 +06:00
Alibek Omarov
305b2579eb engine: client: voice: fix crackling voice file input on low FPS 2022-10-19 01:08:39 +03:00
Alibek Omarov
1a09d297ee engine: minimize SetCursorType calls count 2022-10-13 14:49:48 +03:00
Alibek Omarov
d45e6e0ad1 engine: platform: sdl: SetCursorType shouldn't know about current game state 2022-10-13 14:07:48 +03:00
Alibek Omarov
2d2523df4a engine: client: touch: generalise touch emulation code
* fix doubleclicks and wheels in VGUI
2022-10-12 05:18:19 +03:00
Alibek Omarov
5a0fcfffb0 mainui: update 2022-10-10 13:09:01 +03:00
Alibek Omarov
f252161d90 readme: fix typo and wording 2022-10-04 15:14:54 +03:00
Alibek Omarov
e0216e2658 wscript: don't clean QtCreator files and reconfigure saved options
Cleanup imports
2022-10-04 03:02:49 +03:00
Alibek Omarov
0f2bb5720b wscript: respect --libdir argument with packaging enabled. Fix a typo in --disable-soft description 2022-10-02 22:28:53 +03:00
Alibek Omarov
0621e365ff mainui: update 2022-09-27 17:19:32 +03:00
Alibek Omarov
8ea455def7 mainui: update 2022-09-27 14:00:18 +03:00
Alibek Omarov
8cf822c426 mainui: update 2022-09-27 14:00:18 +03:00
Alibek Omarov
4a009c1c2c engine: client: touch: move copypasted code from export & writeconfig into separate function 2022-09-27 14:00:18 +03:00
Alibek Omarov
360dc4f7ed engine: try to make hashpaks more compatible between 32-bit and 64-bit platforms 2022-09-20 21:57:13 +03:00
Alibek Omarov
ffe43e1f22 scripts: waifulib: fix error reporting in zip.py 2022-09-20 21:56:25 +03:00
Alibek Omarov
a52d901f25 common: add STATIC_ASSERT macro
We're trying to guess if we have C11 static_assert defined in assert.h
otherwise use good ol' trick with negative array
2022-09-20 21:55:32 +03:00
Alibek Omarov
5bae2f06ad engine: platform: sdl: do not lock audio device, for some reason it sometimes causes problems although it shouldn't 2022-09-20 21:29:19 +03:00
Alibek Omarov
69b0954007 engine: change RenderAPI's RenderGetParm return type to intptr_t to insure compatibility with 64-bit 2022-09-20 18:06:19 +03:00
Alibek Omarov
0645402946 engine: fix crash when reading GoldSrc hashpaks 2022-09-19 06:03:01 +03:00
Владислав Сухов
c59b244d04 scripts: gha: fix path to vgui_support submodule 2022-09-17 15:55:40 +03:00
Alibek Omarov
5678d9a253 engine: server: support MAP_ANON synonym for MAP_ANONYMOUS, disable allocating string pool near server library for OSX 2022-09-12 08:42:50 +03:00
dettlaff
a520d245a6 wscript: fix typo in --enable-bundled-deps configure option 2022-09-12 07:18:24 +03:00
Alibek Omarov
b56f6fa330 scripts: waifulib: fix zipfile init for older Python 2022-09-11 02:50:52 +03:00
Alibek Omarov
f141869ce3 wscript: disable building extras.pk3 for Android 2022-09-11 02:22:26 +03:00
Alibek Omarov
807f3852bd scripts: gha: remove building extras.pak, as it's already being built 2022-09-11 02:20:36 +03:00
Alibek Omarov
084089b919 3rdparty: extras: build ZIP archive and install to engine default gamefolder 2022-09-11 02:13:23 +03:00
Alibek Omarov
f571a41cf3 wscript: allow to setup engine default gamedir during configure 2022-09-11 02:12:44 +03:00
Alibek Omarov
686a966ff7 wscript: now waf builds extras archive by itself, using Python standard library's zipfile 2022-09-11 01:39:29 +03:00
Alibek Omarov
c29eb458ea 3rdparty: add xash-extras submodule 2022-09-11 01:38:17 +03:00
Alibek Omarov
234c843f60 filesystem: integrate inotify for file changes 2022-09-10 22:55:07 +03:00
Alibek Omarov
7ed0499aa9 game_launch: wscript: fix Windows build 2022-09-10 22:52:52 +03:00
Alibek Omarov
401b145040 utils: mdldec: fix wscript to build 2022-09-10 22:52:52 +03:00
Alibek Omarov
3853ff5435 3rdparty: gl4es: add wscript to build 2022-09-10 22:52:52 +03:00
Alibek Omarov
744c6b2680 vgui_support: update submodule 2022-09-10 22:52:52 +03:00
Alibek Omarov
030a17fc58 mainui: update submodule 2022-09-10 22:52:52 +03:00
Alibek Omarov
b1e2e84a11 wscript: adapt main and ref_gl wscripts to new directory layout, add flag to build all renderers at once 2022-09-10 22:52:52 +03:00
Alibek Omarov
12a6088912 ref: gl: move GLES wrappers libraries to 3rdparty folder 2022-09-10 22:52:52 +03:00
Alibek Omarov
fe9f3f78a0 ref: soft: minimize dependency on internal engine headers 2022-09-10 22:52:52 +03:00
Alibek Omarov
327eb330ed ref: gl: minimize dependency on internal engine headers 2022-09-10 22:52:52 +03:00
Alibek Omarov
470121512a utils: mdldec: convert to include targets usage 2022-09-10 22:52:52 +03:00
Alibek Omarov
dedc144b8b ref: soft: convert to include targets usage 2022-09-10 22:52:52 +03:00
Alibek Omarov
6d37398fad ref: gl: convert to include targets usage 2022-09-10 22:52:52 +03:00
Alibek Omarov
3c8fe508f0 game_launch: convert to include targets usage 2022-09-10 22:52:52 +03:00
Alibek Omarov
8ffb3aac8a engine: wscript: add dummy engine_includes target that only exposes few internal Xash headers for renderers and utils use 2022-09-10 22:52:52 +03:00
Alibek Omarov
0ed9391969 filesystem: wscript: add dummy filesystem_includes target that only exposes public filesystem_stdio include paths 2022-09-10 22:52:52 +03:00
Alibek Omarov
e54289f811 public: wscript: add dummy sdk_includes target that only exposes standard HLSDK include paths 2022-09-10 22:52:52 +03:00
Alibek Omarov
17b091e5a9 wscript: adapt to new folder structure 2022-09-10 22:52:52 +03:00
Alibek Omarov
61c142e2db ref: move renderers into ref subdirectory 2022-09-10 22:52:52 +03:00
Alibek Omarov
7e664679a0 3rdparty: move mainui and vgui_support submodules into 3rdparty folder 2022-09-10 22:52:52 +03:00
Andrey Akhmichin
fd152e82e8 engine: common: imagelib: img_png.c: add support for indexed and grayscale PNG images. 2022-09-08 12:11:02 +03:00
Alibek Omarov
0c50e43663 engine: client: enable sound for TE_TAREXPLOSION, use same sound parameters as GoldSrc 2022-09-08 04:16:29 +03:00
Alibek Omarov
7a2ac4a9c0 engine: client: use generic particles code for blob particles (from tempentity code) only if Quake compatibility was enabled 2022-09-08 04:16:29 +03:00
Andrey Akhmichin
e6bb9d980d engine: client: in_touch.c: make touch buttons extention-independent. 2022-09-05 11:25:52 +03:00
Alibek Omarov
45cc7e5bcc 3rdparty: opus: update submodule 2022-08-31 19:51:52 +03:00
Alibek Omarov
4be4870982 engine: client: remove voice_codecinfo command, as Opus Custom don't give any encoder info, possibly an Opus bug 2022-08-31 19:50:31 +03:00
Alibek Omarov
19c2061831 wscript: define CUSTOM_MODES and try to link with export that only exists when CUSTOM_MODES was defined in build-time 2022-08-31 19:48:42 +03:00
Alibek Omarov
3a8c58d192 engine: platform: sdl: fix parentheses around IsAudioError macro 2022-08-31 07:13:02 +03:00
Alibek Omarov
24763f9b07 engine: server: request client to use Opus Custom codec 2022-08-31 06:54:58 +03:00
Alibek Omarov
0d7a2e7bad engine: platform: change capture API to allow locking/unlocking buffer to prevent race condition, use single function for pause 2022-08-31 06:50:06 +03:00
Alibek Omarov
82ab06efdd engine: client: voice: new version, move to Opus Custom codec
* Despite Opus Custom have strict requirements, it's more barebones, allowing us to use maximum
frame size and custom sample rate, without resampling
* Encode each frame size to network buffer, allowing smooth voice chat even in 10 FPS
* Fix possible buffer overruns, underruns and races with platform side
* Revise all usages of offset variables, samples vs bytes
2022-08-31 06:44:45 +03:00
Alibek Omarov
4110ee0928 wscript: require Opus Custom for build
Apparently, not all Linux distributions enable it. Anyway, we can build codec ourselves
2022-08-31 05:44:23 +03:00
Alibek Omarov
4b05cf4399 engine: client: better fix for notify debug messages, rely on host.allow_console variable to don't allow uninitialized console usage 2022-08-31 02:46:33 +03:00
Alibek Omarov
f29a9f5f58 ref_gl: use skybox names generated by CheckSkybox function, don't checking same file twice
Also fixes priority for skyboxes
2022-08-31 02:42:19 +03:00
Alibek Omarov
28001ea150 engine: client: enable notify messages in non-developer mode 2022-08-28 00:48:12 +03:00
Alibek Omarov
f633b3dbf6 engine: increase MAX_INIT_MSG to 192 kilobytes limit
* also avoid magic number in sv_client.c
2022-08-27 22:13:21 +03:00
Alibek Omarov
bebfa611fc mainui: update 2022-08-25 21:47:17 +03:00
Alibek Omarov
3e9f2df2bf engine: client: fix incorrect mark for ConsolePrint notifications 2022-08-25 21:21:22 +03:00
Alibek Omarov
fce8afabfb filesystem: allow acquiring C interface through CreateInterface export 2022-08-25 20:33:16 +03:00
Alibek Omarov
9d49985100 scripts: gha: build tarball for dedicated server 2022-08-25 19:40:27 +03:00
Alibek Omarov
a7d4cafe10 wscript: finally disable building opus for dedicated 2022-08-25 19:33:16 +03:00
Alibek Omarov
ca2a6635b6 engine: common: fix cmdlist and cvarlist to match the beginning of command or cvar 2022-08-25 19:22:06 +03:00
Alibek Omarov
7f1bb9b4a6 public: introduce Q_strnicmpext function
The goal is to provide both string compare with fixed length and simple pattern match
2022-08-25 19:21:47 +03:00
Alibek Omarov
7341a6b020 engine: client: add old GoldSrc feature where ConsolePrint could print to notification zone, similar to Con_NPrintf( 0, ... ) 2022-08-25 18:22:43 +03:00
Alibek Omarov
ac05acf6dc engine: network: I'm fucking blind 2022-08-23 20:04:59 +03:00
Alibek Omarov
3e1db432df engine: network: fix IPv4 private address checks according to RFC1918
Thanks to @Mr0maks for the fix
2022-08-23 19:15:50 +03:00
Alibek Omarov
3c682507e7 engine: client: voice: notify client.dll about localplayer twice, through special loopback index and normal index 2022-08-22 11:44:13 +03:00
SNMetamorph
e9ae6d08b5 engine: client: enable interpolation of local player angles 2022-08-22 10:24:15 +03:00
Alibek Omarov
f435a81c97 engine: soundlib: rewrite sfx resampler, fix possible crash if sfx is too long
- make same rate and same width resamples noop, as everything signed now
- minimize comparisons in loop body
2022-08-22 10:14:01 +03:00
Alibek Omarov
cb34c23844 common: increase MAX_MAP_MODELS to 1024, to match PrimeXT compilers 2022-08-21 17:27:48 +03:00
SNMetamorph
9f9141823a engine: added audio backend print to s_info command 2022-08-20 15:36:02 +03:00
Владислав Сухов
d3437c70bd engine: soundlib: fix wrong sample rate unit 2022-08-20 15:35:14 +03:00
Alibek Omarov
8630ef2c67 engine: client: voice: allow using inputfromfile when microphone isn't connected 2022-08-20 06:13:33 +03:00
Alibek Omarov
0b50678912 engine: client: voice: refactor, fix issues when missing mic disables voice chat, fix few possible crashes and memory leaks 2022-08-20 03:56:54 +03:00
Alibek Omarov
22ff45f5d0 engine: platform: add audio capture shutdown functions 2022-08-20 03:17:51 +03:00
Alibek Omarov
905bbf1515 engine: server: read full voicedata message even if voice is disabled server wide 2022-08-19 22:22:40 +03:00
Alibek Omarov
88c1b1400d gitignore: add enc_temp_folder by the request of @SNMetamorph 2022-08-19 22:18:22 +03:00
SNMetamorph
8e48a98d48 engine: client: voice: codec quality levels changed 2022-08-19 20:47:01 +03:00
SNMetamorph
76dbefb9ec engine: client: voice: fixed initialization checks 2022-08-19 20:47:01 +03:00
Alibek Omarov
327dcc0293 engine: client: voice: simplify code, simplify including voice.h, do not depend on opus headers globally
Autofix few code style mistakes
2022-08-19 05:52:53 +03:00
Alibek Omarov
e6c55107c7 wscript: fix game_launch not being included 2022-08-19 05:38:47 +03:00
Alibek Omarov
c5dbbea9ef engine: server: drop bots fake ping to zero 2022-08-19 04:33:41 +03:00
SNMetamorph
74707551ae engine: client: voice: fixed hanging voice status 2022-08-19 04:14:25 +03:00
SNMetamorph
2f5f5ef0a6 engine: client: voice: fixed sound playback from file 2022-08-19 04:14:25 +03:00
SNMetamorph
f7dc9d8e72 engine: client: voice: frame size increased to 40 msec 2022-08-19 04:14:25 +03:00
Alibek Omarov
238162bb79 wscript: move system opus detection to main wscript, so we can avoid including subproject 2022-08-19 04:03:53 +03:00
Alibek Omarov
1fda8753bd wscript: rework subproject filtering, use lambdas everywhere. Deprecate --ignore-projects flag, use Waf capability to select targets instead 2022-08-19 03:10:34 +03:00
SNMetamorph
a688bed79f engine: client: cl_parse: moved buffer to stack in CL_ParseVoiceData 2022-08-18 04:46:11 +03:00
SNMetamorph
b0ff51d5a0 engine: client: voice: changed bitrate units to kbps in voice_codecinfo 2022-08-18 04:46:11 +03:00
SNMetamorph
68f633e9cd wscript: fixed opus include path 2022-08-18 04:46:11 +03:00
SNMetamorph
a520af42e8 wscript: opus subproject set as mandatory 2022-08-18 04:46:11 +03:00
SNMetamorph
0a6885e02d engine: client: voice chat cvars set as privileged 2022-08-18 04:46:11 +03:00
SNMetamorph
aa5a509316 engine: client: voice: added GPL notice 2022-08-18 04:46:11 +03:00
SNMetamorph
97879430e9 engine: small code fixes related to voice chat 2022-08-18 04:46:11 +03:00
SNMetamorph
ae97eae42f engine: client: voice: implemented automatic gain control 2022-08-18 04:46:11 +03:00
SNMetamorph
c5d7e3c783 engine: client: fixed players voice state changing 2022-08-18 04:46:11 +03:00
SNMetamorph
9bcd36cc24 engine: voice code minor refactoring 2022-08-18 04:46:11 +03:00
SNMetamorph
c6881a425f engine: client: added support for variable voice chat quality 2022-08-18 04:46:11 +03:00
SNMetamorph
8d0209b122 engine: server: added support for variable voice chat quality 2022-08-18 04:46:11 +03:00
SNMetamorph
279894cfd4 engine: client: added console command voice_codecinfo 2022-08-18 04:46:11 +03:00
SNMetamorph
169ee14724 engine: client: disabled voice on legacy protocol servers 2022-08-18 04:46:11 +03:00
SNMetamorph
8866d5cfd6 engine: wscript: added Opus headers to include directories 2022-08-18 04:46:11 +03:00
SNMetamorph
3b9a7910d0 opus: fixed path to submodule 2022-08-18 04:46:11 +03:00
SNMetamorph
b5885d4107 3rdparty: opus: wscript: removed Opus demo sources from build 2022-08-18 04:46:11 +03:00
SNMetamorph
a254a342b1 engine: voice: minor code fixes 2022-08-18 04:46:11 +03:00
SNMetamorph
0db95d76a8 engine: wscript: removed opus from opt.load() 2022-08-18 04:46:11 +03:00
Alibek Omarov
69a9211fc9 engine: include voice.h globally 2022-08-18 04:46:11 +03:00
Alibek Omarov
44cd03f464 wscript: refactor opus wscript files, now it builds only if system package wasn't found 2022-08-18 04:46:11 +03:00
Velaron
9242a0a510 engine: update voice 2022-08-18 04:46:11 +03:00
Velaron
2b9e050f57 engine: voice support 2022-08-18 04:46:11 +03:00
Alibek Omarov
9d4fe707bb engine: client: carefully check legacy server response, check info string before passing it to UI 2022-08-17 21:52:54 +03:00
Alibek Omarov
0d2552c3f6 engine: server: prevent DoS through master server query 2022-08-17 21:23:08 +03:00
Alibek Omarov
b3c9637422 engine: server: send server info to all master servers 2022-08-17 21:18:16 +03:00
Alibek Omarov
01a3321d63 engine: client: only accept server list from master servers (thanks @tyabus for idea) 2022-08-17 21:17:51 +03:00
Alibek Omarov
5a5e72c424 engine: print current bug-compatibility level, if enabled 2022-08-17 14:44:03 +03:00
Alibek Omarov
b8dc7494eb engine: client: move timescale pitch apply to channel mixing 2022-08-16 00:03:44 +03:00
Alibek Omarov
532cd779a7 Documentation: document bug compatibility mode 2022-08-15 06:00:00 +03:00
Alibek Omarov
d202a6c572 engine: server: emulate pfnPEntityOfEntIndex bug only with explicitly enabled GoldSrc bug compatibility 2022-08-15 06:00:00 +03:00
Alibek Omarov
6e864e4f8f engine: introduce bug compatibility levels
* for now we only have GoldSrc bug compatibility, can be used for
  games that require precise GoldSrc behaviour, like CSCZDS
* enabled with -bugcomp command line
* added text in --help
2022-08-15 06:00:00 +03:00
Alibek Omarov
6ef76fe665 engine: server: fix bots are counted as real players 2022-08-13 22:46:20 +03:00
Alibek Omarov
314672d82c engine: client: fix invalid playerinfo being accessed by renderer 2022-08-13 01:29:45 +03:00
Alibek Omarov
1d558b33d6 engine: client: don't let set unsupported con_charset 2022-08-13 00:58:45 +03:00
Alibek Omarov
911385d019 engine: client: fix memory leak on player disconnect 2022-08-13 00:47:04 +03:00
SNMetamorph
5b97c2135a engine: server: fixed "wrong version" spamming in NAT bypass mode (fix #953) 2022-08-10 04:11:17 +03:00
Alibek Omarov
365f24e1fe waf.bat: use unicode charset
Fixes compiler messages in Russian
2022-08-09 13:47:38 +03:00
Alibek Omarov
7157c3b441 engine: platform: sdl: don't enable high dpi code for Apple
It seems enables HighDPI awareness but doesn't create HighDPI OpenGL context
It needs some plist magic to be enabled back again
2022-08-08 23:53:20 +03:00
Andrey Akhmichin
28d7f2eaa2 Documentation: not-supported-mod-list-and-reasons-why.md: update. 2022-08-07 22:49:04 +03:00
Alibek Omarov
0d449370e0 filesystem: fixes for GCC 3 2022-08-06 20:33:01 +03:00
Alibek Omarov
10ad1c3b38 filesystem: use correct flushing function for file descriptors on Win32 2022-08-06 20:19:42 +03:00
Alibek Omarov
90c566dde3 wscript: enable GCC's -Wmisleading-indentation 2022-08-06 20:17:42 +03:00
Alibek Omarov
33cbead4a4 filesystem: wscript: fix library name on Android 2022-08-06 20:17:41 +03:00
Alibek Omarov
d6dfeaeba7 engine: fix searching filesystem_stdio on mobile platforms 2022-08-06 20:16:56 +03:00
Alibek Omarov
bc00c6c54b vgui_support: update 2022-08-06 20:16:56 +03:00
Alibek Omarov
3d5aa7c20c engine: remove mistakingly placed NORETURN attributes 2022-08-05 18:05:40 +03:00
SNMetamorph
a5ba43ea39 engine: fixed vulnerability in NAT bypass mechanism 2022-08-02 18:01:28 +03:00
Alibek Omarov
3eb4862794 common: remove unneeded typedef for wad file type 2022-08-01 15:06:54 +03:00
Alibek Omarov
c025606739 engine: whereami: fix C89 in Android detection 2022-08-01 14:33:36 +03:00
Alibek Omarov
067e9be37a scripts: upgrade to Android NDK 25 2022-08-01 14:25:44 +03:00
Alibek Omarov
b7b9c611cf filesystem: wscript: disable RTTI and exceptions(useful on Android), we don't need it here. Link as C++ library. 2022-08-01 14:06:00 +03:00
Alibek Omarov
3c4eec62ae engine: let engine find the filesystem library, if it wasn't loaded yet 2022-08-01 13:25:51 +03:00
SNMetamorph
fd7dba74cd filesystem: fixed build for Windows 2022-08-01 12:54:26 +03:00
SNMetamorph
a8674c18df engine: platform: win32: fixed build for Windows 2022-08-01 12:54:26 +03:00
SNMetamorph
b26cd6cc94 wscript: added /Zc:__cplusplus compiler flag for MSVC 2022-08-01 12:54:26 +03:00
Alibek Omarov
55a29e6e6b filesystem: implement VFileSystem009 interface 2022-07-28 18:56:02 +03:00
Alibek Omarov
56d7c05b51 filesystem: generated VFileSystem009 from pdwtags output, removed unneeded in C++ this first argument 2022-07-28 18:56:02 +03:00
Alibek Omarov
5e4fc64430 filesystem: introduce new module, based on engine filesystem.
The goal is to share filesystem code between engine and
utilities and provide C++ VFileSystem interface in the future
2022-07-28 18:56:02 +03:00
Alibek Omarov
12ea6dcfd7 public: move build.c from engine to public library, in preparation of filesystem_stdio merge 2022-07-26 04:10:36 +03:00
Alibek Omarov
a41f8cb01b engine: move version strings to com_strings.h file, in preparation of filesystem_stdio branch merge 2022-07-26 04:07:52 +03:00
Alibek Omarov
a9c82dbe21 public: make crtlib linkable with C++ 2022-07-26 03:17:11 +03:00
Alibek Omarov
5350d88f57 public: crtlib: add quotation mark support for ParseFile, required for filesystem_stdio 2022-07-26 03:17:11 +03:00
Alibek Omarov
fc132e87f4 engine, game_launch: fix rpath usage 2022-07-26 02:54:20 +03:00
Alibek Omarov
c326853617 engine: server: restore original PEntityOfEntIndex function, but still bug-compatible with GoldSrc 2022-07-21 01:52:10 +03:00
Valery Klachkov
3ad60a0fa1 engine: fix uninitialized variable in demo parsing code, fix incorrect size counter in memory allocator 2022-07-16 16:59:41 +03:00
Alibek Omarov
772f4dcb60 scripts: gha: win32: fix build type from debug to release 2022-07-14 18:26:47 +03:00
Alibek Omarov
657a6af9dc mainui: update 2022-07-13 19:45:42 +03:00
Alibek Omarov
5e1f189db3 engine: platform: posix: use RTLD_NOW instead of lazy.
It actually was a misconception coming from old engine fork
We want to track unresolved symbols before library could be loaded

Also, disable "symbol not found" spam in FunctionFromName. Due to how
savefile mangling convert works and compatibility with GoldSrc saves,
this function is used to bruteforce possible symbol names.
2022-07-13 19:26:38 +03:00
Alibek Omarov
a2d11f670a engine, public: fix float precision issues in mathlib and monster navigation code 2022-07-13 19:26:38 +03:00
Andrey Akhmichin
5bf6f814ef Documentation: opensource-mods.md: update links. 2022-07-13 15:09:22 +03:00
a1batross
fc84cd2a0a engine: common: always show message box when we're in normal mode
Only dedicated server is expected to throw errors to console
2022-07-11 02:45:40 +03:00
a1batross
ab43486ee0 engine: client: don't segfault when client wasn't loaded 2022-07-11 02:43:26 +03:00
SNMetamorph
d8724f0be4 engine: common: net_ws: disabled read-only flag for ip cvar 2022-07-10 18:28:06 +03:00
SNMetamorph
fce3959d15 engine: server: added "c" command to SV_ConnectionlessPacket 2022-07-10 18:28:06 +03:00
SNMetamorph
36b0d47f5f engine: common: net_ws: fixed sockets reinitialization in NET_OpenIP 2022-07-10 18:28:06 +03:00
SNMetamorph
cf84ad12f1 engine: server: backported NAT bypass feature 2022-07-10 18:28:06 +03:00
SNMetamorph
ffe7114a47 engine: client: backported NAT bypass feature 2022-07-10 18:28:06 +03:00
SNMetamorph
6891ed8064 engine: common: net_ws: backported NAT bypass feature 2022-07-10 18:28:06 +03:00
SNMetamorph
8f91830997 engine: added changeport parameter for NET_Config 2022-07-10 18:28:06 +03:00
SNMetamorph
fbdfed84be engine: platform: sdl: fixed bug with unhidable mouse cursor in center of screen 2022-07-09 00:31:49 +03:00
Alibek Omarov
786c408f6e engine: client: fix sprites array size, it wasn't meant to be increased after previous commit 2022-07-01 14:12:32 +03:00
Alibek Omarov
6e031b518a engine: client: increase limit of client sprites, lower part of it can be used only for HUD sprites
higher part used for client sprites
map overview sprites are loaded as normal models

thus we have equal internal engine and hud sprite indices and it fixes compatibility issues
for mods like Half-Rats Parasomnia
2022-07-01 03:41:55 +03:00
Владислав Сухов
500dd0a82b Documentation: supported-mod-list: fix dead links
Restored some mods at Google Drive
2022-06-30 19:37:57 +03:00
Alibek Omarov
d562642e26 utils: mdldec: fix build on Windows, use GetFileAttributes instead of stat here 2022-06-30 18:33:09 +03:00
Andrey Akhmichin
cbcb90638b utils: mdldec: try to create user defined destination directory. 2022-06-30 18:13:46 +03:00
Владислав Сухов
8211acf4e0 Documentation: supported-mod-list: fix link for Lost in Black Mesa 2022-06-30 16:15:21 +03:00
Владислав Сухов
c4a25e0d70 Documentation: supported-mod-list: fix dead links
Renamed domains:
hl-lab.ru -> gamer-lab.com
planetphilip.com -> runthinkshootlive.com
2022-06-30 16:15:21 +03:00
SNMetamorph
3ec9977212 wscript: added parallel builds compiler flag for MSVC 2022-06-30 16:14:21 +03:00
Alibek Omarov
64eb0a694d engine: client: also drop loading plaque on toggleconsole, in case if it's stuck 2022-06-29 18:58:07 +03:00
Alibek Omarov
d46d62bf03 engine: client: drop loading plaque on second signon, remove servercount check 2022-06-29 18:57:10 +03:00
Alibek Omarov
95ed044fee engine: common: disable cl_filterstuffcmd by default 2022-06-29 18:14:53 +03:00
Alibek Omarov
3fe392b41f ref: fix processing indexed textures 2022-06-29 18:05:51 +03:00
Alibek Omarov
854bfb8673 wscript: woops, msvcrt don't actually have stristr 2022-06-29 04:02:57 +03:00
Alibek Omarov
fb43a5590f public: Q_strstr should return pointer to non-const data 2022-06-29 04:02:40 +03:00
Alibek Omarov
5d4f8373c4 common: fix usage of __has_builtin for old GCC releases 2022-06-29 03:53:36 +03:00
Alibek Omarov
ac9664c7ae mainui: update 2022-06-29 03:23:51 +03:00
Alibek Omarov
2905f951bd engine: menu_int: expose TF_EXPAND_SOURCE imagelib flag 2022-06-29 03:20:55 +03:00
Alibek Omarov
79dc090aae engine: platform: sdl: use SetClassLongPtr function to be compatible with 64-bit Windows API 2022-06-29 02:44:50 +03:00
Alibek Omarov
d52b07beac wscript: add stristr/strcasestr presense check 2022-06-29 02:43:09 +03:00
Alibek Omarov
12815bfbf2 public: remove naive implementations of standard function, add them with standard C with few extensions 2022-06-29 02:42:47 +03:00
Alibek Omarov
b9b8b0521b common: add unlikely()/likely() macros 2022-06-29 02:36:39 +03:00
Alibek Omarov
af8febabd1 engine: client: make temp entity buffer larger in case of long textmessages 2022-06-26 15:10:21 +03:00
Alibek Omarov
f0a856d9c8 engine: server: fix writing message size for engine messages, as it's expected to be 2-bytes 2022-06-26 15:05:06 +03:00
Alibek Omarov
85895c5311 engine: pmove: initialize trace argument in PM_TraceModel 2022-06-26 04:39:52 +03:00
Alibek Omarov
c076f4ff8e engine: common: add generic trace_t initialize function 2022-06-26 04:39:15 +03:00
Andrey Akhmichin
87ce35b32d engine: common: imagelib: img_utils.c: change formats priority. 2022-06-25 17:23:44 +03:00
Alibek Omarov
5285f51a26 engine: platform: sdl: fix loading ICO when it's in RoDir 2022-06-25 17:12:08 +03:00
Alibek Omarov
3e23634369 engine: platform: sdl: enable ICO support on Win64 2022-06-25 17:04:02 +03:00
Alibek Omarov
36cec298c2 Revert "engine: common: imagelib: img_tga.c: fix broken tga flip."
This reverts commit 99de598ea4.
2022-06-25 17:03:13 +03:00
Alibek Omarov
6199426e5e Revert "engine: common: imagelib: img_tga.c: fix broken tga flip again."
This reverts commit e5720cf8b9.
2022-06-25 17:03:12 +03:00
Alibek Omarov
4e295622be Revert "engine: platform: sdl: try to enable ICO icons for 64-bit Windows, ignore TGA flip attribute for icons"
This reverts commit 2182ba9630.
2022-06-25 17:03:11 +03:00
Alibek Omarov
2182ba9630 engine: platform: sdl: try to enable ICO icons for 64-bit Windows, ignore TGA flip attribute for icons 2022-06-24 19:15:28 +03:00
Andrey Akhmichin
e5720cf8b9 engine: common: imagelib: img_tga.c: fix broken tga flip again. 2022-06-24 14:18:30 +03:00
Andrey Akhmichin
6063ca2ad1 Documentation: opensource-mods: add Urbicide and Sewer. 2022-06-24 08:06:26 +03:00
Andrey Akhmichin
99de598ea4 engine: common: imagelib: img_tga.c: fix broken tga flip. 2022-06-24 07:38:21 +03:00
Jesse Buhagiar
b23d5ed354 Build: Add SerenityOS to list of compatible systems
This is required by the build system to spit out a library with
the correct name/platform.
2022-06-20 00:01:37 +03:00
Tim Schumacher
a1ce5faac2 Engine: Keep HTTP from endlessly formatting NaN values
For whatever reason, our progress count for HTTP downloads stays at 0.
This results in the engine calculating a NaN progress value many times
each frame, which results in a significant performance hit.
2022-06-20 00:01:37 +03:00
SNMetamorph
afaabe26a6 engine: client: cl_netgraph: fixed netgraph position calculation in center mode 2022-06-16 00:44:23 +04:00
SNMetamorph
a68afcc672 engine: client: cl_netgraph: added kilobytes per seconds unit to in/out fields 2022-06-16 00:42:57 +04:00
SNMetamorph
d4bb5423ae engine: client: cl_netgraph: set rendermode to transparent instead additive 2022-06-16 00:41:11 +04:00
SNMetamorph
ce8e5880e2 engine: client: cl_netgraph: added clamp for bars height 2022-06-16 00:39:48 +04:00
SNMetamorph
0cef18af86 engine: client: cl_netgraph: fixed uninitialized alpha in netcolors 2022-06-16 00:37:38 +04:00
Alibek Omarov
ad4d0cf00a vgui_support: update 2022-06-15 18:26:51 +03:00
Alibek Omarov
a6f12d3009 ref_gl: gl4es: update 2022-06-15 18:26:41 +03:00
Alibek Omarov
fa09854671 engine: client: deprecate and remove ChangeInstance menu call 2022-06-15 18:22:57 +03:00
Alibek Omarov
78d2cd848a mainui: update 2022-06-15 18:20:19 +03:00
Alibek Omarov
463997da51 engine: common: delete unused Mod_Handle function 2022-06-15 13:54:54 +03:00
SNMetamorph
fef0993f54 engine: client: cl_game: fixed hudGetModelByIndex function in client API (fix #518) 2022-06-15 13:53:53 +03:00
Alibek Omarov
2218126c75 engine: disable stdout output and flush on Windows, Wcon already does the job 2022-06-14 04:41:37 +03:00
Alibek Omarov
2388260848 engine: optimize colored output
* removed unneeded formatting for Android
* make generic function to output colorless and colorized strings
* disable color output on low memory devices to not waste CPU cycles on it
2022-06-14 04:23:09 +03:00
Alibek Omarov
40298cefb6 engine: client: don't save configs if shutdown was issued before client was initialized. Remove dead ucmd 2022-06-14 03:30:14 +03:00
Alibek Omarov
45bf927c74 engine: filesystem: avoid FS_SysFolderExists spam if stat returned ENOTDIR 2022-06-14 03:27:56 +03:00
Alibek Omarov
347c6d6a91 engine: common: don't output log to stdout on Win32 where it's done by Wcon. Better colorcode filtration 2022-06-14 03:27:21 +03:00
Alibek Omarov
ab6214142f public: remove custom str(r)chr functions 2022-06-14 03:23:46 +03:00
Velaron
402b38951d engine: better color code stripping 2022-06-13 23:36:13 +03:00
Velaron
6807cf5849 engine: fix build on android 2022-06-13 23:36:13 +03:00
Velaron
15dc25d2cd engine: rename Q_cleanstr to something more meaningful 2022-06-13 23:36:13 +03:00
Velaron
568c7fd917 engine: strip color codes when writing to log 2022-06-13 23:36:13 +03:00
Alibek Omarov
e5562a7b61 engine: whereami: fix C89 2022-06-13 04:33:12 +03:00
Alibek Omarov
ac308f7298 engine: platform: sdl: fix SDL1.2 build 2022-06-13 04:27:54 +03:00
Alibek Omarov
7a88379917 game_launch: fix win32 build 2022-06-13 04:21:57 +03:00
Alibek Omarov
e44718d531 engine: fix build 2022-06-13 04:17:02 +03:00
Alibek Omarov
e6a2c207de engine: implement change game with execv in-engine. For now it enabled for all platforms, will probably disabled selectively 2022-06-13 03:42:20 +03:00
Alibek Omarov
df83b155a1 game_launch: rip out execv code 2022-06-13 03:26:44 +03:00
Alibek Omarov
cc2c97cfad engine: include whereami library to detect current executable path, may be reworked later if needed 2022-06-13 03:07:37 +03:00
Alibek Omarov
c69ea00e79 wscript: better _FILE_OFFSET_BITS check, as suggested by @nekonomicon 2022-06-12 04:25:09 +03:00
Alibek Omarov
f63dd72260 scripts: gha: fix including vgui.dll 2022-06-12 04:16:41 +03:00
Alibek Omarov
5b0b917468 vgui_support: re-add as submodule 2022-06-12 04:15:41 +03:00
Alibek Omarov
b138a63502 vgui_support: remove it from the engine 2022-06-12 03:54:35 +03:00
Alibek Omarov
2b8b3e1993 engine: server: new IP filter, rewritten with IPv6 in mind 2022-06-09 03:10:02 +03:00
Alibek Omarov
b0a889d1a1 engine: bring back simple netadr_t, as we don't care about IPv4-to-IPv6 mapped addresses anymore 2022-06-09 03:10:02 +03:00
Alibek Omarov
bd1bfea695 engine: second iteration of IPv6 support
Made code smaller
Fixed problem where v6 and v4 socket can't use same port
Added support for v4-to-v6 mapped addresses, although it's kept unused
Probably final version
2022-06-09 03:10:02 +03:00
Alibek Omarov
a1299e1dfe common: third iteration of ipv6 netadr_t, now binary compatible with v4-to-v6 mapped addresses 2022-06-09 03:10:02 +03:00
Alibek Omarov
1a5a76a201 engine: common: minor fixes to ipv6text library 2022-06-09 03:10:02 +03:00
Alibek Omarov
b072b627a2 engine: enable getaddrinfo on Windows, fix build 2022-06-09 03:10:02 +03:00
Alibek Omarov
5d18c6d678 engine: fix declaration-after-statement 2022-06-09 03:10:02 +03:00
Alibek Omarov
59fba30a52 engine: IPv6 support
* v6 equivalent cvars
* hostname resolving for v6
* fix for nonblocking hostname resolve (inverted check)
* enabled by default, probably should be disabled for dedicated servers
2022-06-09 03:10:02 +03:00
Alibek Omarov
193cde83b6 engine: add IPv6 address parsing/printing library from GameNetworkingSockets 2022-06-09 03:10:02 +03:00
Alibek Omarov
12bfb8f795 common: another approach on netadr_t with better compatibility 2022-06-09 03:10:02 +03:00
Alibek Omarov
9ae72dbc47 common: update netadr_t structure to include IPv6 addresses 2022-06-09 03:10:02 +03:00
349 changed files with 24280 additions and 15121 deletions

View File

@@ -13,27 +13,33 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
targetos: linux
targetarch: amd64
- os: ubuntu-18.04
- os: ubuntu-20.04
targetos: linux
targetarch: i386
# - os: ubuntu-aarch64-20.04
# targetos: linux
# targetarch: aarch64
- os: ubuntu-18.04
targetos: android
targetarch: 32
- os: ubuntu-18.04
targetos: android
targetarch: 64
# - os: ubuntu-20.04
# targetos: android
# targetarch: 32
# - os: ubuntu-20.04
# targetos: android
# targetarch: 64
- os: ubuntu-18.04
targetos: motomagx
targetarch: armv6
# - os: ubuntu-20.04
# targetos: motomagx
# targetarch: armv6
- os: ubuntu-20.04
targetos: nswitch
targetarch: arm64
- os: ubuntu-20.04
targetos: psvita
targetarch: armv7hf
- os: windows-latest
targetos: win32
targetarch: amd64
@@ -41,32 +47,80 @@ jobs:
targetos: win32
targetarch: i386
env:
SDL_VERSION: 2.0.14
SDL_VERSION: 2.26.2
GH_CPU_ARCH: ${{ matrix.targetarch }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANDROID_SDK_TOOLS_VER: 4333796
UPLOADTOOL_ISPRERELEASE: true
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: recursive
- name: Checkout xash-extras
uses: actions/checkout@v2
with:
repository: FWGS/xash-extras
path: xash-extras
- name: Install dependencies
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
- name: Build engine
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
- name: Upload engine (prereleases)
run: bash scripts/continious_upload.sh artifacts/*
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
flatpak:
name: "Flatpak"
runs-on: ubuntu-latest
strategy:
matrix:
include:
- app: su.xash.Engine.Compat.i386
container:
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v5
with:
bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v3
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
release:
name: "Upload releases"
runs-on: ubuntu-latest
needs: [build, flatpak]
if: ${{ github.event_name == 'push' }}
steps:
- name: Remove old release
uses: FWGS/delete-tag-and-release@v0.2.1-dev
with:
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
delete_release: true
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Fetch artifacts
uses: actions/download-artifact@v3.0.1
with:
path: artifacts/
- name: Repackage binaries and allow GitHub to process removed release for few seconds
run: |
cd artifacts/
for i in artifact-* su.xash.Engine.*; do
mv "$i"/* .
rm -rf "$i"
done
ls -R .
cd ../
sleep 20s
- name: Upload new release
uses: FWGS/action-gh-release@v0.1.15
with:
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
prerelease: true
token: ${{ secrets.GITHUB_TOKEN }}
files: artifacts/*
draft: false

3
.gitignore vendored
View File

@@ -331,4 +331,5 @@ __pycache__
.vscode/*
*.code-workspace
.history/*
.cache/*
.cache/*
enc_temp_folder/

20
.gitmodules vendored
View File

@@ -1,15 +1,21 @@
[submodule "mainui"]
path = mainui
path = 3rdparty/mainui
url = https://github.com/FWGS/mainui_cpp
[submodule "ref_gl/nanogl"]
path = ref_gl/nanogl
path = 3rdparty/nanogl
url = https://github.com/FWGS/nanogl
[submodule "ref_gl/gl-wes-v2"]
path = ref_gl/gl-wes-v2
path = 3rdparty/gl-wes-v2
url = https://github.com/FWGS/gl-wes-v2
[submodule "vgui-dev"]
path = vgui-dev
url = https://github.com/FWGS/vgui-dev
[submodule "ref_gl/gl4es"]
path = ref_gl/gl4es
path = 3rdparty/gl4es/gl4es
url = https://github.com/ptitSeb/gl4es
[submodule "vgui_support"]
path = 3rdparty/vgui_support
url = https://github.com/FWGS/vgui_support
[submodule "opus"]
path = 3rdparty/opus/opus
url = https://github.com/xiph/opus
[submodule "3rdparty/xash-extras"]
path = 3rdparty/extras/xash-extras
url = https://github.com/FWGS/xash-extras

29
3rdparty/extras/wscript vendored Normal file
View File

@@ -0,0 +1,29 @@
#! /usr/bin/env python
# encoding: utf-8
import os
def options(opt):
pass
def configure(conf):
if not conf.path.find_dir('xash-extras'):
conf.fatal('Can\'t find xash-extras submodule.')
return
conf.load('zip')
def build(bld):
srcdir = bld.path.find_dir('xash-extras')
if bld.env.DEST_OS in ['android']:
install_path = bld.env.PREFIX
else:
install_path = os.path.join(bld.env.SHAREDIR, bld.env.GAMEDIR)
bld(features='zip',
name = 'extras.pk3',
files = srcdir.ant_glob('**/*'),
relative_to = srcdir,
compresslevel = 0,
install_path = install_path)

1
3rdparty/extras/xash-extras vendored Submodule

1
3rdparty/gl-wes-v2 vendored Submodule

Submodule 3rdparty/gl-wes-v2 added at 0be6803f81

1
3rdparty/gl4es/gl4es vendored Submodule

Submodule 3rdparty/gl4es/gl4es added at 277be116c1

24
3rdparty/gl4es/wscript vendored Normal file
View File

@@ -0,0 +1,24 @@
#! /usr/bin/env python
# encoding: utf-8
import os
def options(opt):
pass
def configure(conf):
if not conf.path.find_dir('gl4es') or not conf.path.find_dir('gl4es/src'):
conf.fatal('Can\'t find gl4es submodule. Run `git submodule update --init --recursive`.')
return
def build(bld):
gl4es_srcdir = bld.path.find_node('gl4es/src')
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
target = 'gl4es',
features = 'c',
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'EXTERNAL_GETPROCADDRESS=GL4ES_GetProcAddress', 'NO_LOADER', 'STATICLIB'],
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = '.')

1
3rdparty/mainui vendored Submodule

Submodule 3rdparty/mainui added at 262128c0d1

1
3rdparty/nanogl vendored Submodule

Submodule 3rdparty/nanogl added at 5f2892a37e

1
3rdparty/opus/opus vendored Submodule

Submodule 3rdparty/opus/opus added at 8cf872a186

40
3rdparty/opus/wscript vendored Normal file
View File

@@ -0,0 +1,40 @@
#! /usr/bin/env python
# encoding: utf-8
import os
def options(opt):
pass
def configure(conf):
if not conf.path.find_dir('opus') or not conf.path.find_dir('opus/src'):
conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.')
return
# TODO: ARM/x86 intrinsics detection
# TODO: maybe call autotools/cmake/meson instead?
def build(bld):
sources = bld.path.ant_glob([
'opus/src/*.c',
'opus/celt/*.c',
'opus/silk/*.c',
'opus/silk/float/*.c'
], excl = [
'opus/src/repacketizer_demo.c',
'opus/src/opus_demo.c',
'opus/src/opus_compare.c',
'opus/celt/opus_custom_demo.c'
])
includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/']
defines = ['USE_ALLOCA', 'OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.3.1"', 'CUSTOM_MODES']
bld.stlib(
source = sources,
target = 'opus',
features = 'c',
includes = includes,
defines = defines,
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = ['opus/include/']
)

1
3rdparty/vgui_support vendored Submodule

Submodule 3rdparty/vgui_support added at 27fbcbf2bf

View File

@@ -0,0 +1,17 @@
# Bug-compatibility in Xash3D FWGS
Xash3D FWGS has special mode for games that rely on original engine bugs.
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
## GoldSrc bug-compatibility
### Emulated bugs
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
### Games and mods that require this
* Counter-Strike: Condition Zero - Deleted Scenes

View File

@@ -0,0 +1,9 @@
# Cross-compiling for Windows with Wine
This can be useful to test engine in Wine without using virtual machines or dual-booting to Windows.
0. Clone and install https://github.com/mstorsjo/msvc-wine (you can skip CMake part)
1. Set environment variable MSVC_WINE_PATH to the path to installed MSVC toolchain
2. Pre-load wine: `wineserver -k; wineserver -p; wine64 wineboot`
3. Run `./waf configure -T <build-type> --enable-wine-msvc --sdl2=../SDL2_VC`. Configuration step will take more time than usual.
4. .. other typical steps to build from console ...

View File

@@ -0,0 +1,10 @@
# Debugging your mod using minidump files (Windows only)
Minidump files is awesome instrument for debugging your mod after it's being released, or for catch specific crashes which are presented only in one specific configuration, but doesn't happens in other configurations or even on developer machine. It contains a lot of information useful for debugging, and therefore it size is not so small: around hundreds or even thousands of megabytes. But this is not a problem, since minidump files compresses very effectively using common algorithms.
There are short algorithm, explaining how to use this debugging instrument:
1. User starts your mod with `-minidumps` startup parameter
2. Finally, crash happened on user's machine, and minidump file being written. This file has `.mdmp` extension and located in same folder, where mod folder located
3. User packs this minidump file to .zip/.7z archive, and somehow sends it to developer
4. Developer just opens minidump file in Visual Studio, then a virtual debugging session is opened and now reasons of crash is pretty easy to detect: you can see call stack, local function variables and global variables, information about exception and a lot of other information
You can find more information about minidumps in this [awesome article](https://learn.microsoft.com/en-us/windows/win32/dxtecharts/crash-dump-analysis?source=recommendations#writing-a-minidump).

View File

@@ -0,0 +1,150 @@
# There are few new commands availiable in xash3d fork:
## Commands:
### ent_create
Create entity with specified classname and key/values
`ent_create <classname> <key> <value> <key> <value> ...`
for example:
`ent_create monster_zombie targetname zomb1`
after creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description
### ent_fire
Make some actions on entity
`ent_fire <pattern> <command> <args>`
Availiavle commands:
* Set fields (Only set entity field, does not call any functions):
* health
* gravity
* movetype
* solid
* rendermode
* rendercolor (vector)
* renderfx
* renderamt
* hullmin (vector)
* hullmax (vector)
* Actions
* rename: set entity targetname
* settarget: set entity target (only targetnames)
* setmodel: set entity model (does not update)
* set: set key/value by server library
* See game FGD to get list.
* command takes two arguments
* touch: touch entity by current player.
* use: use entity by current player.
* movehere: place entity in player fov.
* drop2floor: place entity to nearest floor surface
* moveup: move entity to 25 units up
* moveup (value): move by y axis relatively to specified value
* Flags (Set/clear specified flag bit, arg is bit number):
* setflag
* clearflag
* setspawnflag
* clearspawnflag
### ent_info
Print information about entity by identificator
`ent_info <identificator>`
### ent_getvars
Set client cvars containing entity information (useful for [[Scripting]]) and call ent_last_cb
`ent_getvars <identificator>`
These cvars are set:
```
ent_last_name
ent_last_num
ent_last_inst
ent_last_origin
ent_last_class
```
### ent_list
Print short information about antities, filtered by pattern
`ent_list <pattern>`
## Syntax description
### \<identificator\>
* !cross: entity under aim
* Instance code: !\<number\>_\<seria\l>
* set by ent_getvars command
* Entity index
* targetname pattern
### \<pattern\>
Pattern is like identificator, but may filter many entities by classname
### (vector)
used by ent_fire command. vector means three float values, entered without quotes
### key/value
All entities parameters may be set by specifiing key and value strings.
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
If value contains spaces, it must be put in quotes:
`ent_fire !cross set origin "0 0 0"`
## Using with scripting
ent_create and ent_getvars commands are setting cvars on client
It can be used with ent_last_cb alias that is executed after setting cvars.
Simple example:
```
ent_create weapon_c4
alias ent_last_cb "ent_fire \$ent_last_inst use"
```
Use weapon_c4 after creating it.
Note that you cannot use many dfferent callbacks at the same time.
You can set entity name by by pattern and create special script, contatning all callbacks.
Example:
example.cfg
```
alias ent_last_cb exec entity_cb.cfg
ent create \<class\> targetname my_ent1_$name
ent_create \<class\> targetname my_ent2_$name
```
entity_cb.cfg
```
if $ent_last_name == my_ent1_$name
:(ent1 actions)
if $ent_last_name == my_ent2_$name
:(ent2 actions)
```
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
## Server side
To enable entity tools on server, set sv_enttools_enable to 1
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
To enable actions on players, set sv_enttools_players to 1.
To enable entity tools for player by nickname, set sv_enttools_godplayer to nickname. Useful to temporary enable from rcon.
To prevent crash on some actions, set host_mapdesign_fatal to 0

View File

@@ -0,0 +1,8 @@
# Expanded structures that used by engine and mods
To make porting and developing mods on 64-bit platforms less painful, we decided to expand size of several structures.
This information important in case you are using codebase like XashXT, Paranoia 2: Savior and want to compile your mod for platform with 64-bit pointer size: you should replace old definitions with new ones, otherwise your mod will not work with Xash3D FWGS (typically, it's just crashing when starting map).
| Structure name | Locates in file | Original size on 64-bit | Current size on 64-bit |
|----------------|-----------------|-------------------------|------------------------|
|`mfaceinfo_t` | `common/com_model.h` | 176 bytes | 304 bytes |
|`decal_s` | `common/com_model.h` | 72 bytes | 88 bytes |
|`mextrasurf_t` | `common/com_model.h` | 376 bytes | 504 bytes |

View File

@@ -31,11 +31,14 @@ Issue #0. Inconsistency between ABI and Q_buildarch.\
Resolution: Change Q_buildarch return value to use Debian-styled architectures list: https://www.debian.org/ports/, which includes a special naming for big/little-endian and hard/soft-float ARM.
Issue #1: Build-system integration.\
Resolution: implemented as [LibraryNaming.cmake](https://github.com/FWGS/hlsdk-xash3d/blob/master/cmake/LibraryNaming.cmake) and [library_naming.py](https://github.com/FWGS/hlsdk-xash3d/blob/master/scripts/waifulib/library_naming.py) extensions, see
Resolution: implemented as [LibraryNaming.cmake](https://github.com/FWGS/hlsdk-portable/blob/master/cmake/LibraryNaming.cmake) and [library_naming.py](https://github.com/FWGS/hlsdk-portable/blob/master/scripts/waifulib/library_naming.py) extensions, see
Issue #2(related to #0): Which ARM flavours we actually need to handle?\
Resolution: Little-endian only, as there is no known big-endian ARM platforms in the wild.
Architecture is coded this way:
* ```armvxy```, where `x` is ARM instruction set level and `y` is hard-float ABI presence: `hf` where hard float ABI used, otherwise `l`.
Issue #3: Some mods (like The Specialists, Tyrian, ...) already apply suffixes _i386, _i686 to the gamedll path:\
Resolution: On x86 on **Win/Lin/Mac**, don't change anything. Otherwise, strip the _i?86 part and follow the usual scheme.
See discussion: https://github.com/FWGS/xash3d-fwgs/issues/39

View File

@@ -0,0 +1,22 @@
## Looping MP3 extension
It is now possible to loop MP3 file in Xash3D FWGS by adding a custom text tag with `LOOP_START` or `LOOPSTART` in description and time point (in raw samples) in value.
### Example with foobar2000
1. Open Foobar2000
2. Add your .mp3 file to playlist
3. Right click to newly added file and select Properties
4. In Metadata tab, at the bottom of the table, select "+add new"
5. In newly added line replace `<60>input field name<6D>` with `LOOP_START` (without any symbols).
6. Press Tab and enter loop time point in raw samples. For example, `0` will replay sound file from beginning to end indefinitely.
### Possible alternatives
1. Classic WAV files looping. HQ WAV files can take too much disk space, and recommended software supporting cue points is paid, outdated and can't run on modern systems. (Although there is alternative that's proven to work with idTech-based engines called LoopAuditioneer.)
2. Vorbis looping through comment. Engine doesn't support Vorbis but this extension was highly inspired by this hack.
### Known bugs and limitations
1. At this time using MP3 as SFX requires complete decoding. This can cause noticeable stutters, so keep MP3 file length in mind.
2. We deliberately only support modern ID3v2.3 and ID3v2.4 tags. Using ID3v1 is not possible.

View File

@@ -1,7 +1,40 @@
# Server porting
# Self-made port
## Compatibility with RISC architectures
### Unaligned access
Unaligned access on **i386** causes only performance penalty, but on **RISC** it can cause unstable work.
For HLSDK at least you need such patches in util.cpp:
- https://github.com/FWGS/halflife/commit/7bfefe86e35d67867ae7af830ac1fc38f2908360
- https://github.com/FWGS/hlsdk-portable/commit/617d75545f2ecb9b2d46cc30728dc37c9eb6d35e
### Signed chars
`char` type defined as **signed** for **x86** and as **unsigned** for **arm**.
And sometimes such difference can break logic.
As a solution you can use `signed char` type in code directly or use `-fsigned-char` option for gcc/clang compilers.
For HLSDK at least you need such [fix](https://github.com/FWGS/hlsdk-portable/commit/1ca34fcb4381682bd517612b530db22a1354a795) in nodes.cpp/.h.
## Compatibility with 64bit architectures
You need list of patches for Studio Model Render, MAKE_STRING macro and nodes:
- https://github.com/FWGS/hlsdk-portable/commit/d287ed446332e615ab5fb25ca81b99fa14d18a73
- https://github.com/FWGS/hlsdk-portable/commit/3bce17e3a04f8af10a927a07ceb8ab0f09152ec4
- https://github.com/FWGS/hlsdk-portable/commit/9ebfc981773ec4c7a89ffe52d9c249e1fbef9634
- https://github.com/FWGS/hlsdk-portable/commit/00833188dab87ef5746286479ba5aeb9d83b4a0c
- https://github.com/FWGS/hlsdk-portable/commit/4661b5c1a5245b27a5532745c11e44b5540e4172
- https://github.com/FWGS/hlsdk-portable/commit/2b61380146b1d58a8c465f0e312c061b12bda115
- https://github.com/FWGS/hlsdk-portable/commit/8ef6cb2427ee16a763103bd3f315f38e2f01cfe2
## Mobility API
Xash3D FWGS has special extended interface in `mobility_int.h` which adds some new features like vibration on mobile platforms.
## Porting server-side code
Original valve's server code was compatible with linux and gcc 2.x.
Newer gcc versions have restriction which breaks build.
Now, to make it building with gcc 4.x, you need do following:
Now, to make it building with gcc 4.x+ or clang, you need to do following:
* Go to cbase.h and redefine macros as following
```
#define SetThink( a ) m_pfnThink = static_cast <void (CBaseEntity::*)(void)> (&a)
@@ -18,58 +51,60 @@ Now, to make it building with gcc 4.x, you need do following:
* Replace all SetThink(NULL), SetTouch(NULL), setUse(NULL) and SetBlocked(NULL) by ResetThink(), ResetTouch(), ResetUse() and ResetBlocked()
* Sometimes you may need to add #include <ctype.h> if functions tolower or isspace are missing
# Client porting
## Porting client-side code
## VGUI library
Valve's client uses vgui library which is available only on x86 systems and has big amount of mistakes in headers. The best and simplest way of porting is removing VGUI dependency at all.
Most singleplayer mods don't really use VGUI at all. It is used in multiplayer only to show score table and MOTD window
## Porting
### First strategy: full port
#### Basic port (Stage 1)
* First, remove all files and headers which use vgui (contains "vgui" in file name).
* After that, try to build it and remove vgui includes.
* Remove all gViewPort usings.
* Remove all CVoiceManager usings (xash3d does not support voice)
* Redefine all DLLEXPORT defines as empty field (Place it under _WIN32 macro if you want to keep windows compatibility).
* Remove hud_servers.cpp and Servers_Init/Servers_Shutdown from hud.cpp
* Remove hud_servers.cpp and Servers_Init/Servers_Shutdown from hud.cpp.
* Fix CAPS filenames in includes (like STDIO.H, replace by stdio.h).
* Replace broken macros as DECLARE_MESSAGE, DECLARE_COMMAND by fixed examples from our hlsdk-xash3d port (cl_util.h)
* Add ctype.h where it is need (tolower, isspace functions)
* Add string.h where it is need (memcpy, strcpy, etc)
* Use in_defs.h from hlsdk_client
* Add scoreboard_stub.cpp and input_stub.cpp from hlsdk-xash3d to fix linking.
Now your client should be able to build and work correctly. Add input_xash3d.cpp from hlsdk-xash3d project to fix input.
* Replace broken macros as DECLARE_MESSAGE, DECLARE_COMMAND by fixed examples from our hlsdk-portable port (cl_util.h).
* Add ctype.h where is needed (tolower, isspace functions).
* Add string.h where is needed (memcpy, strcpy, etc).
* Use in_defs.h from hlsdk-portable.
* Add input_xash3d.cpp from hlsdk-portable project to fix input.
#### Multiplayer fix (Stage 2)
Look at hlsdk-xash3d project.
Now your client should be able to build and work correctly.
Main changes are:
* Add MOTD.cpp, scoreboard.cpp and input_xash3d.cpp
* Add missing functions to hud_redraw.cpp, hud.cpp and tri.cpp, fix class defination in hud.h
* Remove duplicate functions from hud.cpp and HOOK_MESSAGE's for it
* Remove +showscores/-showscores hooks from input.h
* Fix cl_util.h
# Porting mod to hlsdk-portable
Look at changes which was made.
### Second way: move mod to hlsdk-xash3d
Look at changes you made in client.
If there are not too much changes (for example, only some weapons was added), add these changes in hlsdk-portable.
If there are not much changes (for example, only some weapons was add), add these changes in hlsdk-xash3d.
You may use diff with original HLSDK you used and apply it as patch to hlsdk-xash3d.
You can use diff with original HLSDK and apply it as patch to hlsdk-portable.
```
NOTE: Many an old mods was made on HLSDK 2.0-2.1 and some rare mods on HLSDK 1.0.
So you need to have different versions of HLSDK to make diffs.
Plus different Spirit of Half-Life versions if mod was made on it.
Also, weapons in old HLSDK versions does not use client weapon prediction system and you may be need to port standart half-life weapons to server side.
```
Files must have same line endings (use dos2unix on all files).
I recommend to enable ignoring space changes in diff.
### Writing Makefiles
We recommend to enable ignoring space changes in diff.
Use Makefile from hlsdk-xash3d as Makefile example.
Move all new files to separate directories.
Get .c and .cpp file lists from Visual Studio project and fill SRCS and SRCS_C variables to Makefile.
# Possible replacements for non-portable external dependencies
1. If mod uses **fmod.dll** or **base.dll** to play mp3/ogg on client-side or to precache sounds on server-side, you can replace it with:
- [pfnPrimeMusicStream](https://github.com/FWGS/hlsdk-portable/blob/master/engine/cdll_int.h#L293=) engine callback;
- [miniaudio](https://github.com/mackron/miniaudio);
- [phonon](https://community.kde.org/Phonon).
Remove all files containing vgui in name from list, add missing include dirs.
2. If mod uses **OpenGL**, porting code to Xash3D render interface is recommended.
3. If mod uses **cg.dll**, you can try to port code to [NVFX](https://github.com/tlorach/nvFX).
4. If mod uses detours, comment code or try to find replacement somehow by yourself.
# Additional recommendations
1. If mod uses STL, you can replace it with [MiniUTL](https://github.com/FWGS/MiniUTL).
2. Avoid to use dynamic casts to make small size binaries.
3. Avoid to use exceptions to make small size binaries.
# Writing build scripts
Use wscript/CMakeLists.txt files from hlsdk-portable as build scripts example.
Get .c and .cpp file lists from Visual Studio project.
Add missing include dirs.
Do same for Android.mk if you are building for android.

View File

@@ -7,6 +7,5 @@
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Sven-Coop |5.0+ |Uses filesystem_stdio library which xash3d does not support |filesystem_stdio replacement already was made: https://github.com/FWGS/filesystem_stdio_xash
|XDM |3.0.4.0 | |
|Sven-Coop |5.0+ |Uses custom GoldSrc engine |

View File

@@ -17,13 +17,16 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth
Mirrored on github - https://github.com/nekonomicon/BattleGrounds
## Bubblemod
Download page on official site - http://www.bubblemod.org/dl_default.php
Download page on official site - http://www.bubblemod.org/dl_default.php (dead link!)
Mirrored on github - https://github.com/HLSources/BubbleMod
## Chicken Fortress
Official github repository - https://github.com/CKFDevPowered/CKF3Alpha
## Cold Ice
Version 1.9 is available on ModDB - https://www.moddb.com/mods/cold-ice/downloads/cold-ice-sdk
Version 1.9 mirrored on github - https://github.com/solidi/hl-mods/tree/master/ci
## Cold Ice Ressurection
@@ -42,11 +45,13 @@ Official github repository - https://github.com/adslbarxatov/xash3d-for-ESHQ
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Half-Life_2D_(Flat-Life)
## Gang Wars
Mirrored on github - https://github.com/hammermaps/gw1.45src
Mirrored on github - https://github.com/nekonomicon/gw1.45src
## Go-mod
Versions 2.0 and 3.0, available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads
Version 3.0, mirrored on github - https://github.com/nekonomicon/Go-mod30
## GT mod
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki)
@@ -63,10 +68,10 @@ Available on ModDB - https://www.moddb.com/mods/half-life-echoes
Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal
## Half-Life: Gravgun mod
Branch **gravgun** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/gravgun
Branch **gravgun** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/gravgun
## Half-Life: Invasion
official github repository - https://github.com/jlecorre/hlinvasion
Official github repository - https://github.com/jlecorre/hlinvasion
## Half-Life: Pong
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/pong
@@ -105,7 +110,7 @@ Official github repository - https://github.com/desukuran/half-screwed
Version 1.3 on ModDB - https://www.moddb.com/mods/headcrab-frenzy/downloads/headcrab-frenzy-13-beta-source-code
## Heart of Evil
Available on ModDB - https://www.moddb.com/mods/heart-of-evil/downloads/heart-of-evil-dlls-source-code
Mirrored on github - https://github.com/nekonomicon/HeartOfEvil
## Ingram Chillin' Mod
Official SourceForge repository - https://sourceforge.net/projects/icm-hl/
@@ -122,6 +127,9 @@ Official github repository - https://github.com/unknownworlds/NS
## Overturn
Available in mod archive on ModDB - https://www.moddb.com/mods/overturn
## Oz Deathmatch
Mirrored on github - https://github.com/nekonomicon/OZDM
## Spirit of Half-Life
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
@@ -168,7 +176,7 @@ Mirrored on github - https://github.com/ZXCmod/ZXCmod
# Reimplementation
## Absolute Redemption
Branch **redempt** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/redempt
Branch **redempt** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/redempt
## Adrenaline Gamer
OpenAG by YaLTeR - https://github.com/YaLTeR/OpenAG
@@ -176,34 +184,34 @@ OpenAG by YaLTeR - https://github.com/YaLTeR/OpenAG
## Afraid of Monsters
malortie's recreation - https://github.com/malortie/hl-aom
Branch **aom** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/aom
Branch **aom** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aom
## Afraid of Monsters: Director's cut
Reverse-engineered code, branch **aomdc** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/aomdc
Reverse-engineered code, branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
## Azure Sheep
malortie's recreation - https://github.com/malortie/hl-asheep
Reverse-engineered code, branch **asheep** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/asheep
Reverse-engineered code, branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
## Big Lolly
malortie's recreation - https://github.com/malortie/hl-biglolly
Branch **biglolly** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/biglolly
Branch **biglolly** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/biglolly
## Black Ops
malortie's recreation - https://github.com/malortie/hl-blackops
Branch **blackops** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/blackops
Branch **blackops** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/blackops
## Bloody Pizza: Vendetta
Branch **caseclosed** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/caseclosed
Branch **caseclosed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/caseclosed
## Case Closed
Branch **caseclosed** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/caseclosed
Branch **caseclosed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/caseclosed
## Cleaner's Adventures
Branch **CAd** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/CAd
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd
## Counter Strike
Reverse-engineered code of client part by a1batross - https://github.com/FWGS/cs16-client/tree/v1.32
@@ -221,54 +229,60 @@ Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_lif
## Escape from the Darkness
malortie's recreation - https://github.com/malortie/hl-eftd
Reverse-engineered code, branch **eftd** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/eftd
Reverse-engineered code, branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
## Half-Life: Blue Shift
Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
Reverse-engineered code, branch **bshift** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/bshift
Reverse-engineered code, branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
## Half-Life: Induction
Branch **induction** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/induction
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction
## Half-Life: Opposing Force
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
Reverse-engineered code, clean branch **opfor** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/opfor
Reverse-engineered code, clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
Spirit of Half Life: Opposing-Force Edition - https://github.com/Hammermaps-DEV/SOHL-V1.9-Opposing-Force-Edition
## Half-Life: Rebellion
Reverse-engineered code, branch **rebellion** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/rebellion
Reverse-engineered code, branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
## Half-Life: Urbicide
Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hl_urbicide
## Half-Life: Visitors
malortie's recreation - https://github.com/malortie/hl-visitors
Reverse-engineered code, branch **visitors** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/visitors
Reverse-engineered code, branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
## Half-Secret
Branch **half-secret** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/half-secret
Branch **half-secret** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-secret
## Night at the Office
malortie's recreation - https://github.com/malortie/hl-nato
Branch **noffice** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/noffice
Branch **noffice** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/noffice
## Poke 646
malortie's recreation - https://github.com/malortie/hl-poke646
Reverse-engineered code, branch **poke646** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/poke646
Reverse-engineered code, branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
## Poke 646: Vendetta
malortie's recreation - https://github.com/malortie/hl-poke646-vendetta
Reverse-engineered code, branch **poke646_vendetta** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/poke646_vendetta
Reverse-engineered code, branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
## Residual Life
Reverse-engineered code, branch **residual_point** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/residual_point
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
## Residual Point
Reverse-engineered code, branch **residual_point** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/residual_point
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
## Sewer Beta
Branch **sewer_beta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sewer_beta
## Team Fortress Classic
Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client
@@ -276,59 +290,64 @@ Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client
## The Gate
malortie's recreation - https://github.com/malortie/hl-thegate
Reverse-engineered code, branch **thegate** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/thegate
Reverse-engineered code, branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
## They Hunger
malortie's recreation - https://github.com/malortie/hl-theyhunger
Reverse-engineered code, branch **theyhunger** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/theyhunger
Reverse-engineered code, branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
They Hunger: Tactical - https://www.moddb.com/mods/they-hunger-tactical/downloads/tht-source-code-documentation
## Times of Troubles
malortie's recreation - https://github.com/malortie/hl-tot
Branch **tot** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/tot
Branch **tot** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/tot
# Derived work
## Adrenaline Gamer
Branch **aghl** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/aghl
Branch **aghl** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aghl
## Bubblemod
Branch **bubblemod** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/bubblemod
Branch **bubblemod** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bubblemod
## Deathmatch Classic
Deathmatch Classic: Adrenaline Gamer Edition - https://github.com/martinwebrant/agmod/tree/master/src/dmc
Deathmatch Quaked - https://www.moddb.com/games/deathmatch-classic/downloads/dmq2
Branch **dmc** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/dmc
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc
## Half-Life: Echoes
Branch **echoes** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/echoes
Branch **echoes** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/echoes
## Half-Life: Invasion
Port to HLSDK 2.4 by malortie - https://github.com/malortie/hl-invasion
Port to Linux by fmoraw - https://github.com/fmoraw/hlinvasion
Branch **invasion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/invasion
## Half-Life: Top-Down
Branch **hltopdown** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/hltopdown
Branch **hltopdown** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hltopdown
## Half-Screwed
Branch **half-screwed** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/half-screwed
Branch **half-screwed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-screwed
## Natural Selection
Port to Linux - https://github.com/fmoraw/NS
## Spirit of Half-Life
Version 1.2, branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
## Swiss Cheese Halloween 2002
Just more playable version by malortie - https://github.com/malortie/hl-shall
Branch **halloween** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/halloween
Branch **halloween** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/halloween
## Threewave CTF
Branch **dmc** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/dmc
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc
## Zombie-X
Branch **zombie-x** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/zombie-x
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x

View File

@@ -26,7 +26,8 @@ Table is sorted by status.
| Haiku | Supported | not maintained | Was added by #478 and #483
| DOS4GW | Supported | @mittorn |
| GNU/Linux(mipsel) | Supported | @mittorn |
| Switch | In progress | @fgsfdsfgs | [GitHub Repository](https://github.com/fgsfdsfgs/xash3d-fwgs/tree/switch_new)
| PSVita | Supported | @fgsfdsfgs |
| Switch | Supported | @fgsfdsfgs |
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs)
| Emscripten | Old Engine | not maintained |

49
Documentation/psvita.md Normal file
View File

@@ -0,0 +1,49 @@
## PlayStation Vita port
### Prerequisites
1. Make sure your PSVita is [set up to run homebrew applications](https://vita.hacks.guide/).
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/) by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`) and add it to your `config.txt`, for example:
```
*KERNEL
ux0:tai/kubridge.skprx
```
3. Install `libshacccg.suprx` by following [this guide](https://cimmerian.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx).
### Installation
1. If you have an old vitaXash3D install, remove it.
2. Get `xash3d-fwgs-psvita.7z` from the latest [automatic build](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous).
3. Install `xash.vpk` from the 7z archive onto your PSVita.
4. Copy the `data` directory from the 7z archive to the root of your PSVita's SD card.
5. Copy the valve folder and any other mod folders from your Half-Life install to `ux0:/data/xash3d/` (you can use other mountpoints instead of `ux0`). **Do not overwrite anything.**
### Build instructions
1. Install [VitaSDK](https://vitasdk.org/).
2. Build and install [vitaGL](https://github.com/Rinnegatamante/vitaGL):
```
git clone https://github.com/Rinnegatamante/vitaGL.git
make -C vitaGL NO_TEX_COMBINER=1 HAVE_UNFLIPPED_FBOS=1 HAVE_PTHREAD=1 SINGLE_THREADED_GC=1 MATH_SPEEDHACK=1 DRAW_SPEEDHACK=1 HAVE_CUSTOM_HEAP=1 -j2 install
```
3. Build and install [vita-rtld](https://github.com/fgsfdsfgs/vita-rtld):
```
git clone https://github.com/fgsfdsfgs/vita-rtld.git && cd vita-rtld
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j2 install
```
4. Build and install [this SDL2 fork](https://github.com/Northfear/SDL) with vitaGL integration:
```
git clone https://github.com/Northfear/SDL.git && cd SDL
mkdir build && cd build
cmake -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DVIDEO_VITA_VGL=ON ..
make -j2 install
```
5. Use `waf`:
```
./waf configure -T release --psvita
./waf build
```
6. Copy all the resulting `.so` files into a single folder:
```
./waf install --destdir=xash3d
```
7. `xash.vpk` is located in `build/engine/`.

View File

@@ -46,7 +46,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
16. [Betrayal](http://www.moddb.com/mods/betrayal) (this mod has inner bugs; set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas)
17. [Between Two Worlds](https://www.runthinkshootlive.com/posts/between-two-worlds/)
18. [Black Mesa Energy Testing Chamber](http://twhl.info/competitions.php?results=17)
19. [Black Mesa Sideline](http://www.isolated-design.de/half-life-mods/black-mesa-sideline/) (set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas)
19. [Black Mesa Sideline](https://www.moddb.com/mods/black-mesa-sideline) (set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas)
20. [BlackMesa 2007( Black Mesa Missions 2007 )](http://www.moddb.com/addons/blackmesa-2007)
21. [Blood and Bones](https://www.runthinkshootlive.com/posts/blood-and-bones/)
22. Boom (Huknenn) v1.0 & [HL Boom: Gold Edition v1.1](http://www.moddb.com/mods/boom)
@@ -103,8 +103,8 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
72. [Freeman](https://www.runthinkshootlive.com/posts/freeman/)
73. [Freeman's Escape](http://www.moddb.com/mods/freeman-escape-french) (2 maps by *JiggZ*)
74. [Freeman's Fight](https://www.runthinkshootlive.com/posts/freemans-fight/)
75. [Freeman's Return](http://jpmaps.wz.cz/epizody.htm)
76. [Freeman's Return 2](http://jpmaps.wz.cz/epizody.htm)
75. [Freeman's Return](https://www.moddb.com/games/half-life/addons/freemans-return-v12)
76. [Freeman's Return 2](https://www.moddb.com/games/half-life/addons/freemans-return-2-v11)
77. [Freeman's Revenge](https://www.runthinkshootlive.com/posts/freemans-revenge/)
78. [Freeman's Tomb( The Crypt )](http://twhl.info/vault.php?map=3787)
79. [G-Invasion v2.5](http://www.moddb.com/mods/g-man-invasion) aka G-Man Invasion (there is an inner crash bug on final titles: some text lines are too long and cannot be properly displayed)
@@ -129,7 +129,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
96. [Haunted](https://www.runthinkshootlive.com/posts/haunted/) (set **sv_validate_changelevel** to **0** to avoid a problem with level change between maps **pagan7** and **pagan8**)
97. [Hazardous Materials: Episode 1 & 2](http://www.moddb.com/mods/half-life-hazardous-materials)
98. [Hazardous-Course 2](http://www.moddb.com/mods/hazardous-course-2)
99. [Help Wanted](http://maps.mrsucko.org/work/)
99. [Help Wanted](https://www.moddb.com/games/half-life/addons/help-wanted)
100. [Hidden Evil v1.01](https://www.runthinkshootlive.com/posts/hidden-evil/)
101. [High Speed](http://www.moddb.com/games/half-life/addons/high-speed-english-version)
102. [hlife_hotdog_compo26](http://twhl.info/vault.php?map=5181)
@@ -155,7 +155,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
122. [Mario Keys](http://www.moddb.com/mods/mario-keys)
123. [McBeth](https://www.runthinkshootlive.com/posts/mcbeth/)
124. [Medieval World](http://www.moddb.com/mods/medieval-world)
125. [Mel Soaring 2: Star Rancor](http://www.etherealhell.com/etherealhell/index.php/my-levels/half-life)
125. [Mel Soaring 2: Star Rancor](https://www.moddb.com/addons/mel-soaring-2-star-rancor)
126. [MINIMICUS](http://twhl.info/vault.php?map=163)
127. [Mission Failed](http://www.moddb.com/mods/mission-failed)
128. [Mission MC Poker](http://www.moddb.com/mods/half-life-mission-mc-poker)
@@ -176,7 +176,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
145. [Outrun](http://www.moddb.com/mods/outrun)
146. [Outwards (Day One)](http://www.visgi.info/maps/)
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing)
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
149. [pagoda](http://www.moddb.com/mods/pagoda1)
@@ -184,7 +184,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
151. [Phobos IV](http://www.moddb.com/mods/phobos-iv)
152. [Pimp My Car](https://www.runthinkshootlive.com/posts/pimp-my-car/) (there is an inner issue with incorrect responses of buttons on combination locks)
153. [Point Blank Stackdeath Complex](https://www.runthinkshootlive.com/posts/half-life-point-blank-stackdeath-complex/)
154. [Prisoner Escaped](http://four0four.org/downloads/maps/)
154. [Prisoner Escaped](https://www.moddb.com/mods/prisoner-escaped-1-2)
155. [Prisoner of Event](http://wp.vondur.net/?page_id=40)
156. [Prisoner of War](https://www.runthinkshootlive.com/posts/prisoner-of-war/)
157. [Project Quantum Leap](http://www.moddb.com/mods/project-quantum-leap)
@@ -282,7 +282,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
9. [Hazardous-Course (first version of Hazardous-Course 2)](http://www.richmans-maps.ch.vu/) (link dead!)
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing)
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
@@ -305,11 +305,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
32. [Technology Test 2](http://www.richmans-maps.ch.vu/) (link dead!)
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing)
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
36. [Time-Shift](http://www.richmans-maps.ch.vu/) (link dead!)
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing)
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
@@ -379,7 +379,7 @@ Mods:
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
8. [Lost in Black Mesa(first version without HLFX)](http://half-life.ru/forum/showthread.php?threadid=13959)
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
@@ -440,7 +440,7 @@ Mods:
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
53. [De-railed](http://twhl.info/competitions.php?results=7)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://www.gamefront.com/files/13532512) (3rd link dead!)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing)
55. [Deep](http://twhl.info/vault.php?map=1669)
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
@@ -469,7 +469,7 @@ Mods:
80. [Extinct Lifeform Hunt](https://www.fileplanet.com/13501/10000/fileinfo/Extinct-Lifeform-Hunt)
81. [Facility](http://twhl.info/vault.php?map=5482)
82. [Facility Escape](http://twhl.info/vault.php?map=3673)
83. [Fallout](http://www.thewall.de/forum/thread/hl1-sp-48h-mapping-contest/64975.4.html) (map by *simb*)
83. [Fallout](http://www.thewall.de/forum/thread/hl1-sp-48h-mapping-contest/64975.4.html) (map by *simb*) (link dead!)
84. [Final Assault](http://twhl.info/vault.php?map=4500)
85. [Flat](http://hl.loess.ru/?mods=&search=Flat)
86. [Freeman's Allegiance](https://www.runthinkshootlive.com/posts/freemans-allegiance/)
@@ -498,8 +498,8 @@ Mods:
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing)
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)
@@ -668,7 +668,7 @@ Mods:
279. [X-treme Violence](http://www.moddb.com/mods/x-treme-violence)
280. [XargoL's Entry for Vassy's Compo](http://twhl.info/vault.php?map=769)
281. [Xen Again](https://www.fileplanet.com/9132/0/fileinfo/XEN-AGAIN)
282. [Xen World](http://www.lambda-force.org/load/half_life/karty/half_life_xen_world/18-1-0-481)
282. [Xen World](http://www.lambda-force.org/load/half_life/karty/half_life_xen_world/18-1-0-481) (link dead!)
283. [XUnil](https://www.fileplanet.com/7883/0/fileinfo/XUNIL)
284. [Zeeba-G's TWHL Compo 26 Entry](http://twhl.info/competitions.php?results=26)
285. [Zombies!](https://gamebanana.com/maps/160812)
@@ -694,7 +694,7 @@ For Linux and OS X you must download crossbuild from [here](http://www.moddb.com
2. [Big Scientists](http://www.moddb.com/mods/big-scientists)
3. [Black Silla Assault DEMO v1.2](http://www.moddb.com/mods/black-silla-assault)
4. [Blbej Den](http://www.moddb.com/mods/blbej-den)
5. [Cold Experiment v1](http://jpmaps.wz.cz/epizody.htm) (you will need some files from SoHL to play it properly; download SoHL 1.2, extract files and copy following folders into **coldexv1** folder: cl_dlls, dlls, models, sprites)
5. [Cold Experiment v1](https://www.moddb.com/games/half-life/addons/cold-experiment) (you will need some files from SoHL to play it properly; download SoHL 1.2, extract files and copy following folders into **coldexv1** folder: cl_dlls, dlls, models, sprites)
6. [Dead Sector v1.0a](http://www.moddb.com/mods/dead-sector)
7. [Death Is Dead](http://www.moddb.com/games/half-life/addons/death-is-dead) (there is a fog-related inner bug at the first map)
8. [Escape from Black Mesa Alpha](http://www.moddb.com/mods/escape-from-black-mesa)
@@ -710,9 +710,9 @@ For Linux and OS X you must download crossbuild from [here](http://www.moddb.com
18. [Santa's Revenge](http://twhl.info/vault.php?map=4332) (set **fps_max** to **60** to avoid an inner problem of the last map with final scripted sequence, otherwise the mod can not be finished properly)
19. [Sector 6](https://www.moddb.com/mods/sector-6/)
20. [Space Prisoner v1.1](http://www.moddb.com/games/half-life/addons/space-prisoner-v11) (after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\prison\dlls\spirit.dll"** for **gamedll "dlls\spirit.dll"**, otherwise you'll not be able to start a game; there is also a scripting error on a third map of the mod, so you'll be forced to use **noclip** to pass around bugged place)
21. [Terrorist Attack 2](http://terroristattack.wz.cz/mody.html) (link dead!)
21. [Terrorist Attack 2](https://www.moddb.com/games/half-life/addons/terrorist-attack-2)
22. [Timeline III: The Heart of Darkness](http://www.moddb.com/mods/timeline-series)
23. [Underground 2 Demo](http://www.isolated-design.de/half-life-mods/underground-2/)
23. [Underground 2 Demo](https://www.moddb.com/games/half-life/addons/underground-2-demo)
## Mods which based on modified Spirit of Half-Life 1.2 or older(Partially playable with SoHL 1.2 libraries or not playable at all)
1. [Black Death](http://www.moddb.com/mods/half-life-black-death)
@@ -825,10 +825,10 @@ Mods:
3. [Bomb Squad](http://www.snarkpit.net/index.php?s=maps&map=3471)
4. [Corruption](http://www.snarkpit.net/index.php?s=maps&map=3154)
5. [Critical Mass](http://www.moddb.com/mods/half-life-critical-mass) [C3M1 Build 1 Demo](https://www.fileplanet.com/125746/120000/fileinfo/C3M1-Build-1)
6. [EPRST!](http://www.planetphillip.com/posts/ep-rst-opposing-force/) (link dead!)
6. [EPRST!](https://www.runthinkshootlive.com/posts/ep-rst/)
7. [Firing Range](https://www.runthinkshootlive.com/posts/firing-range/)
8. [Friendly Fire](https://www.runthinkshootlive.com/posts/friendly-fire/)
9. [Guitar Star Pre-Alpha](http://hl-lab.ru/eng/mods_goldsrc/Guitar_Star_(Prealpha)) (link dead!)
9. [Guitar Star Pre-Alpha](http://gamer-lab.com/rus/mods_goldsrc/Guitar_Star_(Prealpha))
10. [J2000](https://www.runthinkshootlive.com/posts/j2000/)
11. [Killing House for OF](https://www.runthinkshootlive.com/posts/scientist-rescue-aka-cqb/)
12. [Klabautermann](https://www.runthinkshootlive.com/posts/klabautermann/) (though the map has some inner issues, it can be properly finished, just don't let the welder soldier die and don't press the fifth button until you mount a special gun in its' place)

View File

@@ -0,0 +1,41 @@
# Experimental VGUI2 Support
Thanks to @kungfulon contributions, Xash3D FWGS now supports VGUI2.
VGUI2 is undocumented UI system from Source Engine that GoldSrc used in some games and it's main menu.
## Support status
Doesn't draw anything, doesn't take any input.
## List of games that require VGUI2 support
- Counter-Strike 1.6
- Counter-Strike: Condition Zero
- Counter-Strike: Condition Zero Deleted Scenes
- Day of Defeat
- Half-Life: Blue Shift
## How to enable VGUI2 support
By default, engine doesn't initialize VGUI2 to not confuse existing games and mods that use or do not use VGUI1. This support also relies on a number of proprietary libraries, that we better not redistribute, so you have to supply them yourself. Keep in mind, that these libraries are compiled only for 32-bit Windows, Linux and OSX, you shouldn't expect them running anywhere else.
1. Download latest Half-Life from Steam.
2. Open local files.
3. Copy libraries in the list below according to your platform, to folder where Xash3D searches it's libraries (usually in same folder where executable is located)
| Linux | Windows
| -------- | --------
| `chromehtml.so` | `chromehtml.dll`
| `vgui2.so` | `vgui2.dll`
| `libcef.so` | `libcef.dll`
| `libtier0.so` | `tier0.dll`
| `libvstdlib.so` | `vstdlib.dll`
| `libsteam_api.so` | `steam_api.dll`
Some files must also be copied:
- `cef_gtk.pak`
Additionally, on Linux other libraries must be provided. Use `ldd` tool to figure out which libraries you miss. Many of them can be pulled from Steam Runtime.
Do not recommend using RoDir with VGUI2 games. Many of them are broken. Steam API will crash without `steam_appid.txt` in Xash root directory.

View File

@@ -18,19 +18,22 @@ Read more about Xash3D on ModDB: https://www.moddb.com/engines/xash3d-engine
* Mobility API: allows better game integration on mobile devices(vibration, touch controls)
* Different input methods: touch, gamepad and classic mouse & keyboard.
* TrueType font rendering, as a part of mainui_cpp.
* Multiple renderers support: OpenGL, GLESv1, GLESv2, Software
* Multiple renderers support: OpenGL, GLESv1, GLESv2, Software.
* Voice support.
* External filesystem module like in GoldSrc engine.
* External vgui support module.
* PNG image format support.
* A set of small improvements, without broken compatibility.
## Planned fork features
* Virtual Reality support and game API
* Voice support
* Vulkan renderer
* Virtual Reality support and game API.
* Vulkan renderer.
## Installation & Running
0) Get Xash3D FWGS binaries: you can use [testing](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous) build or you can compile engine from source code.
1) Copy engine binaries to some directory.
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d).
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
You still needed to copy `valve` directory as all game resources located there.
3) Run the main executable (`xash3d.exe` or AppImage).
@@ -49,10 +52,10 @@ NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependenc
### Prerequisites
If your CPU is x86 compatible, we are building 32-bit code by default. This was dont for keeping compatibility with Steam releases of Half-Life and based on it's engine games.
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d).
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
#### Windows (Visual Studio)

View File

@@ -29,12 +29,6 @@ GNU General Public License for more details.
#define SOUND_OPENSLES 2
#define SOUND_ALSA 3
// crash handler (XASH_CRASHHANDLER)
#define CRASHHANDLER_NULL 0
#define CRASHHANDLER_UCONTEXT 1
#define CRASHHANDLER_DBGHELP 2
#define CRASHHANDLER_WIN32 3
// input (XASH_INPUT)
#define INPUT_NULL 0
#define INPUT_SDL 1
@@ -53,6 +47,7 @@ GNU General Public License for more details.
#define MSGBOX_SDL 1
#define MSGBOX_ANDROID 2
#define MSGBOX_WIN32 3
#define MSGBOX_NSWITCH 4
// library loading (XASH_LIB)

View File

@@ -61,23 +61,27 @@ BRUSH MODELS
#define LS_UNUSED 0xFE
#define LS_NONE 0xFF
#define MAX_MAP_CLIPNODES_HLBSP 32767
#define MAX_MAP_CLIPNODES_BSP2 524288
// these limis not using by modelloader but only for displaying 'mapstats' correctly
#ifdef SUPPORT_BSP2_FORMAT
#define MAX_MAP_MODELS 2048 // embedded models
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
#define MAX_MAP_PLANES 131072 // can be increased without problems
#define MAX_MAP_NODES 262144 // can be increased without problems
#define MAX_MAP_CLIPNODES 524288 // can be increased without problems
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_BSP2 // can be increased without problems
#define MAX_MAP_LEAFS 131072 // CRITICAL STUFF to run ad_sepulcher!!!
#define MAX_MAP_VERTS 524288 // can be increased without problems
#define MAX_MAP_FACES 262144 // can be increased without problems
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
#else
#define MAX_MAP_MODELS 768 // embedded models
// increased to match PrimeXT compilers
#define MAX_MAP_MODELS 1024 // embedded models
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
#define MAX_MAP_PLANES 65536 // can be increased without problems
#define MAX_MAP_NODES 32767 // because negative shorts are leafs
#define MAX_MAP_CLIPNODES 32767 // because negative shorts are contents
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_HLBSP // because negative shorts are contents
#define MAX_MAP_LEAFS 32767 // signed short limit
#define MAX_MAP_VERTS 65535 // unsigned short limit
#define MAX_MAP_FACES 65535 // unsigned short limit

View File

@@ -49,6 +49,7 @@ typedef enum
IL_DDS_HARDWARE = BIT(4), // DXT compression is support
IL_LOAD_DECAL = BIT(5), // special mode for load gradient decals
IL_OVERVIEW = BIT(6), // overview required some unque operations
IL_LOAD_PLAYER_DECAL = BIT(7), // special mode for player decals
} ilFlags_t;
// goes into rgbdata_t->encode

View File

@@ -105,7 +105,7 @@ typedef struct
vec3_t mins, maxs; // terrain bounds (fill by user)
int reserved[32]; // just for future expansions or mod-makers
intptr_t reserved[32]; // just for future expansions or mod-makers
} mfaceinfo_t;
typedef struct
@@ -173,8 +173,8 @@ struct decal_s
short entityIndex; // Entity this is attached to
// Xash3D specific
vec3_t position; // location of the decal center in world space.
glpoly_t *polys; // precomputed decal vertices
int reserved[4]; // just for future expansions or mod-makers
glpoly_t *polys; // precomputed decal vertices
intptr_t reserved[4]; // just for future expansions or mod-makers
};
typedef struct mleaf_s
@@ -228,7 +228,7 @@ typedef struct mextrasurf_s
unsigned short numverts; // world->vertexes[]
int firstvertex; // fisrt look up in tr.tbn_vectors[], then acess to world->vertexes[]
int reserved[32]; // just for future expansions or mod-makers
intptr_t reserved[32]; // just for future expansions or mod-makers
} mextrasurf_t;
struct msurface_s
@@ -530,7 +530,7 @@ typedef struct
#define MAX_DEMOS 32
#define MAX_MOVIES 8
#define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 256 // SpriteTextures
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_EFRAGS 8192 // Arcane Dimensions required
#define MAX_REQUESTS 64

View File

@@ -47,7 +47,9 @@ SETUP BACKENDS DEFINITIONS
#endif // XASH_TIMER
#ifndef XASH_MESSAGEBOX
#define XASH_MESSAGEBOX MSGBOX_SDL
#if !XASH_NSWITCH // SDL2 messageboxes not available
#define XASH_MESSAGEBOX MSGBOX_SDL
#endif
#endif // XASH_MESSAGEBOX
#endif
#elif XASH_ANDROID
@@ -68,7 +70,7 @@ SETUP BACKENDS DEFINITIONS
#define XASH_MESSAGEBOX MSGBOX_ANDROID
#endif // XASH_MESSAGEBOX
#define XASH_USE_EVDEV
#define XASH_USE_EVDEV 1
#define XASH_DYNAMIC_DLADDR
#elif XASH_LINUX
// we are building for Linux without SDL2, can draw only to framebuffer yet
@@ -84,7 +86,7 @@ SETUP BACKENDS DEFINITIONS
#define XASH_SOUND SOUND_ALSA
#endif // XASH_SOUND
#define XASH_USE_EVDEV
#define XASH_USE_EVDEV 1
#elif XASH_DOS4GW
#ifndef XASH_VIDEO
#define XASH_VIDEO VIDEO_DOS
@@ -105,22 +107,13 @@ SETUP BACKENDS DEFINITIONS
#ifndef XASH_MESSAGEBOX
#if XASH_WIN32
#define XASH_MESSAGEBOX MSGBOX_WIN32
#elif XASH_NSWITCH
#define XASH_MESSAGEBOX MSGBOX_NSWITCH
#else // !XASH_WIN32
#define XASH_MESSAGEBOX MSGBOX_STDERR
#endif // !XASH_WIN32
#endif // XASH_MESSAGEBOX
//
// select crashhandler based on defines
//
#ifndef XASH_CRASHHANDLER
#if XASH_WIN32 && defined(DBGHELP)
#define XASH_CRASHHANDLER CRASHHANDLER_DBGHELP
#elif XASH_LINUX || XASH_BSD
#define XASH_CRASHHANDLER CRASHHANDLER_UCONTEXT
#endif // !(XASH_LINUX || XASH_BSD || XASH_WIN32)
#endif
//
// no timer - no xash
//
@@ -157,10 +150,6 @@ SETUP BACKENDS DEFINITIONS
#define XASH_INPUT INPUT_NULL
#endif // XASH_INPUT
#ifndef XASH_CRASHHANDLER
#define XASH_CRASHHANDLER CRASHHANDLER_NULL
#endif // XASH_CRASHHANDLER
/*
=========================================================================
@@ -169,25 +158,51 @@ Default build-depended cvar and constant values
=========================================================================
*/
#if XASH_MOBILE_PLATFORM
#define DEFAULT_TOUCH_ENABLE "1"
#define DEFAULT_M_IGNORE "1"
#else // !XASH_MOBILE_PLATFORM
// Platform overrides
#if XASH_NSWITCH
#define DEFAULT_TOUCH_ENABLE "0"
#define DEFAULT_M_IGNORE "0"
#endif // !XASH_MOBILE_PLATFORM
#define DEFAULT_M_IGNORE "1"
#define DEFAULT_MODE_WIDTH 1280
#define DEFAULT_MODE_HEIGHT 720
#define DEFAULT_ALLOWCONSOLE 1
#elif XASH_PSVITA
#define DEFAULT_TOUCH_ENABLE "0"
#define DEFAULT_M_IGNORE "1"
#define DEFAULT_MODE_WIDTH 960
#define DEFAULT_MODE_HEIGHT 544
#define DEFAULT_ALLOWCONSOLE 1
#elif XASH_MOBILE_PLATFORM
#define DEFAULT_TOUCH_ENABLE "1"
#define DEFAULT_M_IGNORE "1"
#endif // !XASH_MOBILE_PLATFORM && !XASH_NSWITCH
#if XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN
#define XASH_INTERNAL_GAMELIBS
// this means that libraries are provided with engine, but not in game data
// You need add library loading code to library.c when adding new platform
// this means that libraries are provided with engine, but not in game data
// You need add library loading code to library.c when adding new platform
#define XASH_INTERNAL_GAMELIBS
#endif // XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN
// allow override for developer/debug builds
// Defaults
#ifndef DEFAULT_TOUCH_ENABLE
#define DEFAULT_TOUCH_ENABLE "0"
#endif // DEFAULT_TOUCH_ENABLE
#ifndef DEFAULT_M_IGNORE
#define DEFAULT_M_IGNORE "0"
#endif // DEFAULT_M_IGNORE
#ifndef DEFAULT_JOY_DEADZONE
#define DEFAULT_JOY_DEADZONE "4096"
#endif // DEFAULT_JOY_DEADZONE
#ifndef DEFAULT_DEV
#define DEFAULT_DEV 0
#endif // DEFAULT_DEV
#ifndef DEFAULT_ALLOWCONSOLE
#define DEFAULT_ALLOWCONSOLE 0
#endif // DEFAULT_ALLOWCONSOLE
#ifndef DEFAULT_FULLSCREEN
#define DEFAULT_FULLSCREEN 1
#endif // DEFAULT_FULLSCREEN

View File

@@ -16,22 +16,61 @@
#ifndef NETADR_H
#define NETADR_H
#include "build.h"
#include STDINT_H
typedef enum
{
NA_UNUSED,
NA_UNUSED = 0,
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX
NA_BROADCAST_IPX,
NA_IP6,
NA_MULTICAST_IP6, // all nodes multicast
} netadrtype_t;
// Original structure:
// typedef struct netadr_s
// {
// netadrtype_t type;
// unsigned char ip[4];
// unsigned char ipx[10];
// unsigned short port;
// } netadr_t;
#pragma pack( push, 1 )
typedef struct netadr_s
{
netadrtype_t type;
unsigned char ip[4];
unsigned char ipx[10];
unsigned short port;
union
{
struct
{
uint32_t type;
union
{
uint8_t ip[4];
uint32_t ip4;
};
uint8_t ipx[10];
};
struct
{
#if XASH_LITTLE_ENDIAN
uint16_t type6;
uint8_t ip6[16];
#elif XASH_BIG_ENDIAN
uint8_t ip6_0[2];
uint16_t type6;
uint8_t ip6_2[14];
#endif
};
};
uint16_t port;
} netadr_t;
#pragma pack( pop )
STATIC_ASSERT( sizeof( netadr_t ) == 20, "invalid netadr_t size" );
#endif//NETADR_H

View File

@@ -39,16 +39,20 @@ GNU General Public License for more details.
#if XASH_POSIX
#include <unistd.h>
#include <dlfcn.h>
#define PATH_SPLITTER "/"
#define HAVE_DUP
#define O_BINARY 0
#define O_TEXT 0
#if XASH_NSWITCH
#define SOLDER_LIBDL_COMPAT
#include <solder.h>
#elif XASH_PSVITA
#define VRTLD_LIBDL_COMPAT
#include <vrtld.h>
#define O_BINARY 0
#else
#include <dlfcn.h>
#define HAVE_DUP
#define O_BINARY 0
#endif
#define O_TEXT 0
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
#elif XASH_DOS4GW
#define PATH_SPLITTER "\\"
#endif
typedef void* HANDLE;
@@ -59,7 +63,6 @@ GNU General Public License for more details.
int x, y;
} POINT;
#else // WIN32
#define PATH_SPLITTER "\\"
#ifdef __MINGW32__
#define _inline static inline
#define FORCEINLINE inline __attribute__((always_inline))

View File

@@ -161,7 +161,7 @@ struct ref_viewpass_s;
typedef struct render_api_s
{
// Get renderer info (doesn't changes engine state at all)
int (*RenderGetParm)( int parm, int arg ); // generic
intptr_t (*RenderGetParm)( int parm, int arg ); // generic
void (*GetDetailScaleForTexture)( int texture, float *xScale, float *yScale );
void (*GetExtraParmsForTexture)( int texture, byte *red, byte *green, byte *blue, byte *alpha );
lightstyle_t* (*GetLightStyle)( int number );

24
common/synctype.h Normal file
View File

@@ -0,0 +1,24 @@
/*
synctype.h -- shared synctype_t definition
Copyright (C) 1996-1997 Id Software, Inc.
Copyright (C) 2023 Alibek Omarov
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef SYNCTYPE_H
#define SYNCTYPE_H
typedef enum {ST_SYNC=0, ST_RAND } synctype_t;
#endif

View File

@@ -4,12 +4,17 @@
#include "build.h"
#if XASH_IRIX
#include <port.h>
#endif
#if XASH_WIN32
#include <wchar.h> // off_t
#endif // _WIN32
#include <sys/types.h> // off_t
#include STDINT_H
#include <assert.h>
typedef unsigned char byte;
typedef int sound_t;
@@ -22,7 +27,12 @@ typedef byte rgba_t[4]; // unsigned byte colorpack
typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4];
typedef vec_t matrix4x4[4][4];
#if XASH_64BIT
typedef uint32_t poolhandle_t;
#else
typedef void* poolhandle_t;
#endif
#undef true
#undef false
@@ -40,6 +50,7 @@ typedef uint64_t longtime_t;
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
#define MAX_SYSPATH 1024 // system filepath
#define MAX_VA_STRING 1024 // string length returned by va()
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_MODS 512 // environment games that engine can keep visible
@@ -87,6 +98,27 @@ typedef uint64_t longtime_t;
#define NORETURN
#endif
#if ( __GNUC__ >= 3 )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#elif defined( __has_builtin )
#if __has_builtin( __builtin_expect )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#else
#define unlikely(x) (x)
#define likely(x) (x)
#endif
#else
#define unlikely(x) (x)
#define likely(x) (x)
#endif
#if defined( static_assert ) // C11 static_assert
#define STATIC_ASSERT static_assert
#else
#define STATIC_ASSERT( x, y ) extern int _static_assert_##__LINE__[( x ) ? 1 : -1]
#endif
#ifdef XASH_BIG_ENDIAN
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
@@ -122,7 +154,6 @@ typedef unsigned int dword;
typedef unsigned int uint;
typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file
typedef struct wfile_s wfile_t; // wad file
typedef struct stream_s stream_t; // sound stream for background music playing
typedef off_t fs_offset_t;
#if XASH_WIN32

View File

@@ -16,6 +16,10 @@
#ifndef ALIAS_H
#define ALIAS_H
#include "build.h"
#include STDINT_H
#include "synctype.h"
/*
==============================================================================
@@ -39,16 +43,6 @@ Alias models are position independent, so the cache manager can move them.
#define ALIAS_TRACER2 0x0040 // orange split trail + rotate
#define ALIAS_TRACER3 0x0080 // purple trail
// must match definition in sprite.h
#ifndef SYNCTYPE_T
#define SYNCTYPE_T
typedef enum
{
ST_SYNC = 0,
ST_RAND
} synctype_t;
#endif
typedef enum
{
ALIAS_SINGLE = 0,
@@ -63,36 +57,42 @@ typedef enum
typedef struct
{
int ident;
int version;
int32_t ident;
int32_t version;
vec3_t scale;
vec3_t scale_origin;
float boundingradius;
vec3_t eyeposition;
int numskins;
int skinwidth;
int skinheight;
int numverts;
int numtris;
int numframes;
synctype_t synctype;
int flags;
int32_t numskins;
int32_t skinwidth;
int32_t skinheight;
int32_t numverts;
int32_t numtris;
int32_t numframes;
uint32_t synctype; // was synctype_t
int32_t flags;
float size;
} daliashdr_t;
STATIC_ASSERT( sizeof( daliashdr_t ) == 84, "invalid daliashdr_t size" );
typedef struct
{
int onseam;
int s;
int t;
int32_t onseam;
int32_t s;
int32_t t;
} stvert_t;
STATIC_ASSERT( sizeof( stvert_t ) == 12, "invalid stvert_t size" );
typedef struct dtriangle_s
{
int facesfront;
int vertindex[3];
int32_t facesfront;
int32_t vertindex[3];
} dtriangle_t;
STATIC_ASSERT( sizeof( dtriangle_t ) == 16, "invalid dtriangle_t size" );
#define DT_FACES_FRONT 0x0010
#define ALIAS_ONSEAM 0x0020
@@ -103,36 +103,50 @@ typedef struct
char name[16]; // frame name from grabbing
} daliasframe_t;
STATIC_ASSERT( sizeof( daliasframe_t ) == 24, "invalid daliasframe_t size" );
typedef struct
{
int numframes;
int32_t numframes;
trivertex_t bboxmin; // lightnormal isn't used
trivertex_t bboxmax; // lightnormal isn't used
} daliasgroup_t;
STATIC_ASSERT( sizeof( daliasgroup_t ) == 12, "invalid daliasgrou_t size" );
typedef struct
{
int numskins;
int32_t numskins;
} daliasskingroup_t;
STATIC_ASSERT( sizeof( daliasskingroup_t ) == 4, "invalid daliasskingroup_t size" );
typedef struct
{
float interval;
} daliasinterval_t;
STATIC_ASSERT( sizeof( daliasinterval_t ) == 4, "invalid daliasinterval_t size" );
typedef struct
{
float interval;
} daliasskininterval_t;
STATIC_ASSERT( sizeof( daliasskininterval_t ) == 4, "invalid daliasskininterval_t size" );
typedef struct
{
aliasframetype_t type;
uint32_t type; // was aliasframetype_t
} daliasframetype_t;
STATIC_ASSERT( sizeof( daliasframetype_t ) == 4, "invalid daliasframetype_t size" );
typedef struct
{
aliasskintype_t type;
uint32_t type; // was aliasskintype_t
} daliasskintype_t;
STATIC_ASSERT( sizeof( daliasskintype_t ) == 4, "invalid daliasskintype_t size" );
#endif//ALIAS_H

View File

@@ -27,7 +27,6 @@ int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int leng
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet );
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio );
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time );
int AVI_GetVideoFrameCount( movie_state_t *Avi );
void AVI_CloseVideo( movie_state_t *Avi );
qboolean AVI_IsActive( movie_state_t *Avi );
void AVI_FreeVideo( movie_state_t *Avi );

View File

@@ -57,11 +57,6 @@ int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
return 0;
}
int AVI_GetVideoFrameCount( movie_state_t *Avi )
{
return 0;
}
void AVI_CloseVideo( movie_state_t *Avi )
{
;

View File

@@ -1,5 +1,6 @@
/*
avi_win.c - playing AVI files (based on original AVIKit code, Win32 version)
Copyright (c) 2003-2004, Ruari O'Sullivan
Copyright (C) 2010 Uncle Mike
This program is free software: you can redistribute it and/or modify
@@ -63,7 +64,7 @@ static int (_stdcall *pAVIStreamTimeToSample)( PAVISTREAM pavi, LONG lTime );
static void* (_stdcall *pAVIStreamGetFrame)( PGETFRAME pg, LONG lPos );
static int (_stdcall *pAVIStreamGetFrameClose)( PGETFRAME pg );
static dword (_stdcall *pAVIStreamRelease)( PAVISTREAM pavi );
static int (_stdcall *pAVIFileOpen)( PAVIFILE *ppfile, LPCSTR szFile, UINT uMode, LPCLSID lpHandler );
static int (_stdcall *pAVIFileOpenW)( PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode, LPCLSID lpHandler );
static int (_stdcall *pAVIFileGetStream)( PAVIFILE pfile, PAVISTREAM *ppavi, DWORD fccType, LONG lParam );
static int (_stdcall *pAVIStreamReadFormat)( PAVISTREAM pavi, LONG lPos,LPVOID lpFormat, LONG *lpcbFormat );
static int (_stdcall *pAVIStreamStart)( PAVISTREAM pavi );
@@ -76,7 +77,7 @@ static dllfunc_t avifile_funcs[] =
{ "AVIFileExit", (void **) &pAVIFileExit },
{ "AVIFileGetStream", (void **) &pAVIFileGetStream },
{ "AVIFileInit", (void **) &pAVIFileInit },
{ "AVIFileOpenA", (void **) &pAVIFileOpen },
{ "AVIFileOpenW", (void **) &pAVIFileOpenW },
{ "AVIFileRelease", (void **) &pAVIFileRelease },
{ "AVIStreamGetFrame", (void **) &pAVIStreamGetFrame },
{ "AVIStreamGetFrameClose", (void **) &pAVIStreamGetFrameClose },
@@ -278,14 +279,6 @@ int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
return (time * Avi->video_fps);
}
int AVI_GetVideoFrameCount( movie_state_t *Avi )
{
if( !Avi->active )
return 0;
return Avi->video_frames;
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
if( !Avi->active || !Avi->audio_stream )
@@ -493,6 +486,7 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi
AVISTREAMINFO stream_info;
int opened_streams = 0;
LONG hr;
wchar_t pathBuffer[MAX_PATH];
// default state: non-working.
Avi->active = false;
@@ -501,8 +495,15 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi
// can't load Video For Windows :-(
if( !avi_initialized ) return;
// convert to wide char
if( MultiByteToWideChar( CP_UTF8, 0, filename, -1, pathBuffer, ARRAYSIZE( pathBuffer )) <= 0 )
{
Con_DPrintf( S_ERROR "filename buffer limit exceeded\n" );
return;
}
// load the AVI
hr = pAVIFileOpen( &Avi->pfile, filename, OF_SHARE_DENY_WRITE, 0L );
hr = pAVIFileOpenW( &Avi->pfile, pathBuffer, OF_SHARE_DENY_WRITE, 0L );
if( hr != 0 ) // error opening AVI:
{
@@ -657,7 +658,7 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
// open cinematic
Q_snprintf( path, sizeof( path ), "media/%s", filename );
COM_DefaultExtension( path, ".avi" );
COM_DefaultExtension( path, ".avi", sizeof( path ));
fullpath = FS_GetDiskPath( path, false );
if( FS_FileExists( path, false ) && !fullpath )

View File

@@ -145,7 +145,7 @@ void CL_PlayCDTrack_f( void )
CL_ScreenshotGetName
==================
*/
qboolean CL_ScreenshotGetName( int lastnum, char *filename )
static qboolean CL_ScreenshotGetName( int lastnum, char *filename, size_t size )
{
if( lastnum < 0 || lastnum > 9999 )
{
@@ -153,9 +153,7 @@ qboolean CL_ScreenshotGetName( int lastnum, char *filename )
return false;
}
Q_sprintf( filename, "scrshots/%s_shot%04d.png", clgame.mapname, lastnum );
return true;
return Q_snprintf( filename, size, "scrshots/%s_shot%04d.png", clgame.mapname, lastnum ) > 0;
}
/*
@@ -163,7 +161,7 @@ qboolean CL_ScreenshotGetName( int lastnum, char *filename )
CL_SnapshotGetName
==================
*/
qboolean CL_SnapshotGetName( int lastnum, char *filename )
static qboolean CL_SnapshotGetName( int lastnum, char *filename, size_t size )
{
if( lastnum < 0 || lastnum > 9999 )
{
@@ -172,9 +170,7 @@ qboolean CL_SnapshotGetName( int lastnum, char *filename )
return false;
}
Q_sprintf( filename, "../%s_%04d.png", clgame.mapname, lastnum );
return true;
return Q_snprintf( filename, size, "../%s_%04d.png", clgame.mapname, lastnum ) > 0;
}
/*
@@ -207,7 +203,7 @@ void CL_ScreenShot_f( void )
// scan for a free filename
for( i = 0; i < 9999; i++ )
{
if( !CL_ScreenshotGetName( i, checkname ))
if( !CL_ScreenshotGetName( i, checkname, sizeof( checkname )))
return; // no namespace
if( !FS_FileExists( checkname, false ))
@@ -247,7 +243,7 @@ void CL_SnapShot_f( void )
// scan for a free filename
for( i = 0; i < 9999; i++ )
{
if( !CL_SnapshotGetName( i, checkname ))
if( !CL_SnapshotGetName( i, checkname, sizeof( checkname )))
return; // no namespace
if( !FS_FileExists( checkname, false ))
@@ -278,7 +274,7 @@ void CL_EnvShot_f( void )
return;
}
Q_sprintf( cls.shotname, "gfx/env/%s", Cmd_Argv( 1 ));
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "gfx/env/%s", Cmd_Argv( 1 ));
cls.scrshot_action = scrshot_envshot; // build new frame for envshot
cls.envshot_vieworg = NULL; // no custom view
cls.envshot_viewsize = 0;
@@ -299,7 +295,7 @@ void CL_SkyShot_f( void )
return;
}
Q_sprintf( cls.shotname, "gfx/env/%s", Cmd_Argv( 1 ));
Q_snprintf( cls.shotname, sizeof( cls.shotname ),"gfx/env/%s", Cmd_Argv( 1 ));
cls.scrshot_action = scrshot_skyshot; // build new frame for skyshot
cls.envshot_vieworg = NULL; // no custom view
cls.envshot_viewsize = 0;
@@ -323,7 +319,8 @@ void CL_LevelShot_f( void )
// check for exist
if( cls.demoplayback && ( cls.demonum != -1 ))
{
Q_sprintf( cls.shotname, "levelshots/%s_%s.bmp", cls.demoname, refState.wideScreen ? "16x9" : "4x3" );
Q_snprintf( cls.shotname, sizeof( cls.shotname ),
"levelshots/%s_%s.bmp", cls.demoname, refState.wideScreen ? "16x9" : "4x3" );
Q_snprintf( filename, sizeof( filename ), "%s.dem", cls.demoname );
// make sure what levelshot is newer than demo
@@ -332,7 +329,8 @@ void CL_LevelShot_f( void )
}
else
{
Q_sprintf( cls.shotname, "levelshots/%s_%s.bmp", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" );
Q_snprintf( cls.shotname, sizeof( cls.shotname ),
"levelshots/%s_%s.bmp", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" );
// make sure what levelshot is newer than bsp
ft1 = FS_FileTime( cl.worldmodel->name, false );
@@ -360,7 +358,7 @@ void CL_SaveShot_f( void )
return;
}
Q_sprintf( cls.shotname, DEFAULT_SAVE_DIRECTORY "%s.bmp", Cmd_Argv( 1 ));
Q_snprintf( cls.shotname, sizeof( cls.shotname ), DEFAULT_SAVE_DIRECTORY "%s.bmp", Cmd_Argv( 1 ));
cls.scrshot_action = scrshot_savegame; // build new frame for saveshot
}

View File

@@ -78,7 +78,7 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
}
MSG_BeginClientCmd( msg, clc_stringcmd );
MSG_WriteString( msg, va( "dlfile %s", filepath ));
MSG_WriteStringf( msg, "dlfile %s", filepath );
host.downloadcount++;
return false;

View File

@@ -25,70 +25,6 @@ GNU General Public License for more details.
#define MSG_COUNT 32 // last 32 messages parsed
#define MSG_MASK (MSG_COUNT - 1)
const char *svc_strings[svc_lastmsg+1] =
{
"svc_bad",
"svc_nop",
"svc_disconnect",
"svc_event",
"svc_changing",
"svc_setview",
"svc_sound",
"svc_time",
"svc_print",
"svc_stufftext",
"svc_setangle",
"svc_serverdata",
"svc_lightstyle",
"svc_updateuserinfo",
"svc_deltatable",
"svc_clientdata",
"svc_resource",
"svc_pings",
"svc_particle",
"svc_restoresound",
"svc_spawnstatic",
"svc_event_reliable",
"svc_spawnbaseline",
"svc_temp_entity",
"svc_setpause",
"svc_signonnum",
"svc_centerprint",
"svc_unused27",
"svc_unused28",
"svc_unused29",
"svc_intermission",
"svc_finale",
"svc_cdtrack",
"svc_restore",
"svc_cutscene",
"svc_weaponanim",
"svc_bspdecal",
"svc_roomtype",
"svc_addangle",
"svc_usermessage",
"svc_packetentities",
"svc_deltapacketentities",
"svc_choke",
"svc_resourcelist",
"svc_deltamovevars",
"svc_resourcerequest",
"svc_customization",
"svc_crosshairangle",
"svc_soundfade",
"svc_filetxferfailed",
"svc_hltv",
"svc_director",
"svc_voiceinit",
"svc_voicedata",
"svc_deltapacketbones",
"svc_unused55",
"svc_resourcelocation",
"svc_querycvarvalue",
"svc_querycvarvalue2",
"svc_exec",
};
typedef struct
{
int command;
@@ -109,7 +45,7 @@ const char *CL_MsgInfo( int cmd )
{
static string sz;
Q_strcpy( sz, "???" );
Q_strncpy( sz, "???", sizeof( sz ));
if( cmd >= 0 && cmd <= svc_lastmsg )
{

View File

@@ -518,14 +518,26 @@ CL_ReadDemoCmdHeader
read the demo command
=================
*/
void CL_ReadDemoCmdHeader( byte *cmd, float *dt )
qboolean CL_ReadDemoCmdHeader( byte *cmd, float *dt )
{
// read the command
FS_Read( cls.demofile, cmd, sizeof( byte ));
Assert( *cmd >= 1 && *cmd <= dem_lastcmd );
// HACKHACK: skip NOPs
do
{
FS_Read( cls.demofile, cmd, sizeof( byte ));
} while( *cmd == dem_unknown );
if( *cmd > dem_lastcmd )
{
Con_Printf( S_ERROR "Demo cmd %d > %d, file offset = %d\n", *cmd, dem_lastcmd, (int)FS_Tell( cls.demofile ));
CL_DemoCompleted();
return false;
}
// read the timestamp
FS_Read( cls.demofile, dt, sizeof( float ));
return true;
}
/*
@@ -888,7 +900,7 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
qboolean swallowmessages = true;
static int tdlastdemoframe = 0;
byte *userbuf = NULL;
size_t size;
size_t size = 0;
byte cmd;
if( !cls.demofile )
@@ -913,7 +925,8 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
if( !cls.demofile ) break;
curpos = FS_Tell( cls.demofile );
CL_ReadDemoCmdHeader( &cmd, &demo.timestamp );
if( !CL_ReadDemoCmdHeader( &cmd, &demo.timestamp ))
return false;
fElapsedTime = CL_GetDemoPlaybackClock() - demo.starttime;
if( !cls.timedemo ) bSkipMessage = ((demo.timestamp - cl_serverframetime()) >= fElapsedTime) ? true : false;
@@ -1304,16 +1317,16 @@ void CL_CheckStartupDemos( void )
CL_DemoGetName
==================
*/
static void CL_DemoGetName( int lastnum, char *filename )
static void CL_DemoGetName( int lastnum, char *filename, size_t size )
{
if( lastnum < 0 || lastnum > 9999 )
{
// bound
Q_strcpy( filename, "demo9999" );
Q_strncpy( filename, "demo9999.dem", size );
return;
}
Q_sprintf( filename, "demo%04d", lastnum );
Q_snprintf( filename, size, "demo%04d.dem", lastnum );
}
/*
@@ -1367,8 +1380,8 @@ void CL_Record_f( void )
// scan for a free filename
for( n = 0; n < 10000; n++ )
{
CL_DemoGetName( n, demoname );
if( !FS_FileExists( va( "%s.dem", demoname ), true ))
CL_DemoGetName( n, demoname, sizeof( demoname ));
if( !FS_FileExists( demoname, true ))
break;
}
@@ -1381,7 +1394,7 @@ void CL_Record_f( void )
else Q_strncpy( demoname, name, sizeof( demoname ));
// open the demo file
Q_sprintf( demopath, "%s.dem", demoname );
Q_snprintf( demopath, sizeof( demopath ), "%s.dem", demoname );
// make sure that old demo is removed
if( FS_FileExists( demopath, false ))
@@ -1408,7 +1421,7 @@ void CL_PlayDemo_f( void )
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "playdemo <demoname>\n" );
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
return;
}
@@ -1535,12 +1548,6 @@ timedemo <demoname>
*/
void CL_TimeDemo_f( void )
{
if( Cmd_Argc() != 2 )
{
Con_Printf( S_USAGE "timedemo <demoname>\n" );
return;
}
CL_PlayDemo_f ();
// cls.td_starttime will be grabbed at the second frame of the demo, so

View File

@@ -33,46 +33,6 @@ static mnode_t *r_pefragtopnode;
static vec3_t r_emins, r_emaxs;
static cl_entity_t *r_addent;
/*
================
R_RemoveEfrags
Call when removing an object from the world or moving it to another position
================
*/
void R_RemoveEfrags( cl_entity_t *ent )
{
efrag_t *ef, *old, *walk, **prev;
ef = ent->efrag;
while( ef )
{
prev = &ef->leaf->efrags;
while( 1 )
{
walk = *prev;
if( !walk ) break;
if( walk == ef )
{
// remove this fragment
*prev = ef->leafnext;
break;
}
else prev = &walk->leafnext;
}
old = ef;
ef = ef->entnext;
// put it on the free list
old->entnext = clgame.free_efrags;
clgame.free_efrags = old;
}
ent->efrag = NULL;
}
/*
===================
R_SplitEntityOnNode

View File

@@ -140,26 +140,6 @@ void CL_FreeParticles( void )
cl_particles = NULL;
}
/*
================
CL_FreeParticle
move particle to freelist
================
*/
void CL_FreeParticle( particle_t *p )
{
if( p->deathfunc )
{
// call right the deathfunc before die
p->deathfunc( p );
p->deathfunc = NULL;
}
p->next = cl_free_particles;
cl_free_particles = p;
}
/*
================
CL_AllocParticleFast
@@ -1111,9 +1091,13 @@ R_ParticleExplosion2
void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength )
{
int i, j;
int colorMod = 0;
int colorMod = 0, packedColor;
particle_t *p;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 512; i++ )
{
p = R_AllocParticle( NULL );
@@ -1121,7 +1105,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
p->die = cl.time + 0.3f;
p->color = colorStart + ( colorMod % colorLength );
p->packedColor = 255; // use old code for blob particles
p->packedColor = packedColor;
colorMod++;
p->type = pt_blob;
@@ -1143,15 +1127,19 @@ R_BlobExplosion
void GAME_EXPORT R_BlobExplosion( const vec3_t org )
{
particle_t *p;
int i, j;
int i, j, packedColor;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 1024; i++ )
{
p = R_AllocParticle( NULL );
if( !p ) return;
p->die = cl.time + COM_RandomFloat( 2.0f, 2.4f );
p->packedColor = 255; // use old code for blob particles
p->die = cl.time + COM_RandomFloat( 1.0f, 1.4f );
p->packedColor = packedColor;
if( i & 1 )
{

350
engine/client/cl_font.c Normal file
View File

@@ -0,0 +1,350 @@
/*
cl_font.c - bare bones engine font manager
Copyright (C) 2023 Alibek Omarov
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "filesystem.h"
#include "client.h"
#include "qfont.h"
qboolean CL_FixedFont( cl_font_t *font )
{
return font && font->valid && font->type == FONT_FIXED;
}
static int CL_LoadFontTexture( const char *fontname, uint texFlags, int *width )
{
int font_width;
int tex;
if( !g_fsapi.FileExists( fontname, false ))
return 0;
tex = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, texFlags );
if( !tex )
return 0;
font_width = REF_GET_PARM( PARM_TEX_WIDTH, tex );
if( !font_width )
{
ref.dllFuncs.GL_FreeTexture( tex );
return 0;
}
*width = font_width;
return tex;
}
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
{
int font_width, i;
if( font->valid )
return true; // already loaded
font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width );
if( !font->hFontTexture )
return false;
font->type = FONT_FIXED;
font->valid = true;
font->scale = scale;
font->nearest = FBitSet( texFlags, TF_NEAREST );
font->rendermode = rendermode;
font->charHeight = Q_rint( font_width / 16 * scale );
for( i = 0; i < ARRAYSIZE( font->fontRc ); i++ )
{
font->fontRc[i].left = ( i * font_width / 16 ) % font_width;
font->fontRc[i].right = font->fontRc[i].left + font_width / 16;
font->fontRc[i].top = ( i / 16 ) * ( font_width / 16 );
font->fontRc[i].bottom = font->fontRc[i].top + font_width / 16;
font->charWidths[i] = Q_rint( font_width / 16 * scale );
}
return true;
}
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
{
fs_offset_t length;
qfont_t src;
byte *pfile;
int font_width, i;
if( font->valid )
return true;
pfile = g_fsapi.LoadFile( fontname, &length, false );
if( !pfile )
return false;
if( length < sizeof( src ))
{
Mem_Free( pfile );
return false;
}
memcpy( &src, pfile, sizeof( src ));
Mem_Free( pfile );
font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width );
if( !font->hFontTexture )
return false;
font->type = FONT_VARIABLE;
font->valid = true;
font->scale = scale;
font->nearest = FBitSet( texFlags, TF_NEAREST );
font->rendermode = rendermode;
font->charHeight = Q_rint( src.rowheight * scale );
for( i = 0; i < ARRAYSIZE( font->fontRc ); i++ )
{
const charinfo *ci = &src.fontinfo[i];
font->fontRc[i].left = (word)ci->startoffset % font_width;
font->fontRc[i].right = font->fontRc[i].left + ci->charwidth;
font->fontRc[i].top = (word)ci->startoffset / font_width;
font->fontRc[i].bottom = font->fontRc[i].top + src.rowheight;
font->charWidths[i] = Q_rint( src.fontinfo[i].charwidth * scale );
}
return true;
}
void CL_FreeFont( cl_font_t *font )
{
if( !font || !font->valid )
return;
ref.dllFuncs.GL_FreeTexture( font->hFontTexture );
memset( font, 0, sizeof( *font ));
}
static int CL_CalcTabStop( const cl_font_t *font, int x )
{
int space = font->charWidths[' '];
int tab = space * 6; // 6 spaces
int stop = tab - x % tab;
if( stop < space )
return tab * 2 - x % tab; // select next
return stop;
}
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags )
{
wrect_t *rc;
float w, h;
float s1, t1, s2, t2, half = 0.5f;
int texw, texh;
if( !font || !font->valid || y < -font->charHeight )
return 0;
// check if printable
if( number <= 32 )
{
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;
R_GetTextureParms( &texw, &texh, font->hFontTexture );
if( !texw || !texh )
return font->charWidths[number];
rc = &font->fontRc[number];
if( font->nearest || font->scale <= 1.0f )
half = 0;
s1 = ((float)rc->left + half ) / texw;
t1 = ((float)rc->top + half ) / texh;
s2 = ((float)rc->right - half ) / texw;
t2 = ((float)rc->bottom - half ) / texh;
w = ( rc->right - rc->left ) * font->scale;
h = ( rc->bottom - rc->top ) * font->scale;
if( FBitSet( flags, FONT_DRAW_HUD ))
SPR_AdjustSize( &x, &y, &w, &h );
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
// don't apply color to fixed fonts it's already colored
if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] );
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, font->hFontTexture );
return font->charWidths[number];
}
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags )
{
rgba_t current_color;
int draw_len = 0;
if( !font || !font->valid )
return 0;
if( FBitSet( flags, FONT_DRAW_UTF8 ))
Con_UtfProcessChar( 0 ); // clear utf state
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
Vector4Copy( color, current_color );
while( *s )
{
if( *s == '\n' )
{
s++;
if( !*s )
break;
// some client functions ignore newlines
if( !FBitSet( flags, FONT_DRAW_NOLF ))
{
draw_len = 0;
y += font->charHeight;
}
if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF ))
Vector4Copy( color, current_color );
continue;
}
if( IsColorString( s ))
{
// don't copy alpha
if( !FBitSet( flags, FONT_DRAW_FORCECOL ))
VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color );
s += 2;
continue;
}
// skip setting rendermode, it was changed for this string already
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, current_color, font, flags | FONT_DRAW_NORENDERMODE );
s++;
}
return draw_len;
}
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... )
{
va_list va;
char buf[MAX_VA_STRING];
va_start( va, fmt );
Q_vsnprintf( buf, sizeof( buf ), fmt, va );
va_end( va );
return CL_DrawString( x, y, buf, color, font, flags );
}
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height )
{
if( !font || !font->valid ) return;
if( width )
{
if( number == '\t' )
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop
else *width = font->charWidths[number & 255];
}
if( height ) *height = font->charHeight;
}
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags )
{
int draw_len = 0;
if( !font || !font->valid )
return;
if( height )
*height = font->charHeight;
if( width )
*width = 0;
if( !COM_CheckString( s ))
return;
if( FBitSet( flags, FONT_DRAW_UTF8 ))
Con_UtfProcessChar( 0 ); // reset utf state
while( *s )
{
int number;
if( *s == '\n' )
{
// BUG: no check for end string here
// but high chances somebody's relying on this
s++;
draw_len = 0;
if( !FBitSet( flags, FONT_DRAW_NOLF ))
{
if( height )
*height += font->charHeight;
}
continue;
}
else if( *s == '\t' )
{
draw_len += CL_CalcTabStop( font, 0 ); // at least return max tabstop
s++;
continue;
}
if( IsColorString( s ))
{
s += 2;
continue;
}
if( FBitSet( flags, FONT_DRAW_UTF8 ))
number = Con_UtfProcessChar( (byte)*s );
else number = (byte)*s;
if( number )
{
draw_len += font->charWidths[number];
if( draw_len > *width )
*width = draw_len;
}
s++;
}
}

View File

@@ -241,7 +241,7 @@ CL_GetStudioEstimatedFrame
====================
*/
float CL_GetStudioEstimatedFrame( cl_entity_t *ent )
static float CL_GetStudioEstimatedFrame( cl_entity_t *ent )
{
studiohdr_t *pstudiohdr;
mstudioseqdesc_t *pseqdesc;
@@ -255,7 +255,7 @@ float CL_GetStudioEstimatedFrame( cl_entity_t *ent )
{
sequence = bound( 0, ent->curstate.sequence, pstudiohdr->numseq - 1 );
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
return ref.dllFuncs.R_StudioEstimateFrame( ent, pseqdesc );
return ref.dllFuncs.R_StudioEstimateFrame( ent, pseqdesc, cl.time );
}
}
@@ -534,7 +534,7 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent )
vec3_t origin;
vec3_t angles;
if( !ent->player || ent->index == ( cl.playernum + 1 ))
if( !ent->player )
return;
if( cl_nointerp->value > 0.f )
@@ -654,6 +654,24 @@ FRAME PARSING
=========================================================================
*/
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum )
{
if( cls.legacymode )
{
*newnum = MSG_ReadWord( msg );
if( *newnum == 0 )
return false;
}
else
{
*newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
if( *newnum == LAST_EDICT )
return false;
}
return true;
}
/*
=================
CL_FlushEntityPacket
@@ -674,8 +692,8 @@ void CL_FlushEntityPacket( sizebuf_t *msg )
// read it all, but ignore it
while( 1 )
{
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
if( newnum == LAST_EDICT ) break; // done
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
break; // done
if( MSG_CheckOverflow( msg ))
Host_Error( "CL_FlushEntityPacket: overflow\n" );
@@ -847,21 +865,12 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
while( 1 )
{
int lastedict;
if( cls.legacymode )
{
newnum = MSG_ReadWord( msg );
lastedict = 0;
}
else
{
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
lastedict = LAST_EDICT;
}
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
break; // done
if( newnum == lastedict ) break; // end of packet entities
if( MSG_CheckOverflow( msg ))
Host_Error( "CL_ParsePacketEntities: overflow\n" );
player = CL_IsPlayerIndex( newnum );
while( oldnum < newnum )
@@ -970,9 +979,25 @@ all the visible entities should pass this filter
*/
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
{
qboolean draw_player = true;
if( !ent || !ent->model )
return false;
// don't add the player in firstperson mode
if( RP_LOCALCLIENT( ent ))
{
cl.local.apply_effects = true;
if( !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity ))
{
// we don't draw player in default renderer in firstperson mode
// but let the client.dll know about player entity anyway
// for use in custom renderers
draw_player = false;
}
}
// check for adding this entity
if( !clgame.dllFuncs.pfnAddEntity( entityType, ent, ent->model->name ))
{
@@ -982,14 +1007,8 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
return false;
}
// don't add the player in firstperson mode
if( RP_LOCALCLIENT( ent ))
{
cl.local.apply_effects = true;
if( !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity ))
return false;
}
if( !draw_player )
return false;
if( entityType == ET_BEAM )
{
@@ -1094,6 +1113,9 @@ void CL_LinkPlayers( frame_t *frame )
if ( i == cl.playernum )
{
// using interpolation only for local player angles
CL_ComputePlayerOrigin( ent );
if( cls.demoplayback == DEMO_QUAKE1 )
VectorLerp( ent->prevstate.origin, cl.lerpFrac, ent->curstate.origin, cl.simorg );
VectorCopy( cl.simorg, ent->origin );

File diff suppressed because it is too large Load Diff

View File

@@ -309,7 +309,7 @@ static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, flo
// run cinematic if not
Q_snprintf( path, sizeof( path ), "media/%s", filename );
COM_DefaultExtension( path, ".avi" );
COM_DefaultExtension( path, ".avi", sizeof( path ));
fullpath = FS_GetDiskPath( path, false );
if( FS_FileExists( path, false ) && !fullpath )
@@ -421,54 +421,6 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
out->flags |= GFL_RENDER_PICBUTTON_TEXT;
}
static qboolean PIC_Scissor( float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 )
{
float dudx, dvdy;
// clip sub rect to sprite
if(( width == 0 ) || ( height == 0 ))
return false;
if( *x + *width <= gameui.ds.scissor_x )
return false;
if( *x >= gameui.ds.scissor_x + gameui.ds.scissor_width )
return false;
if( *y + *height <= gameui.ds.scissor_y )
return false;
if( *y >= gameui.ds.scissor_y + gameui.ds.scissor_height )
return false;
dudx = (*u1 - *u0) / *width;
dvdy = (*v1 - *v0) / *height;
if( *x < gameui.ds.scissor_x )
{
*u0 += (gameui.ds.scissor_x - *x) * dudx;
*width -= gameui.ds.scissor_x - *x;
*x = gameui.ds.scissor_x;
}
if( *x + *width > gameui.ds.scissor_x + gameui.ds.scissor_width )
{
*u1 -= (*x + *width - (gameui.ds.scissor_x + gameui.ds.scissor_width)) * dudx;
*width = gameui.ds.scissor_x + gameui.ds.scissor_width - *x;
}
if( *y < gameui.ds.scissor_y )
{
*v0 += (gameui.ds.scissor_y - *y) * dvdy;
*height -= gameui.ds.scissor_y - *y;
*y = gameui.ds.scissor_y;
}
if( *y + *height > gameui.ds.scissor_y + gameui.ds.scissor_height )
{
*v1 -= (*y + *height - (gameui.ds.scissor_y + gameui.ds.scissor_height)) * dvdy;
*height = gameui.ds.scissor_y + gameui.ds.scissor_height - *y;
}
return true;
}
/*
====================
PIC_DrawGeneric
@@ -487,10 +439,10 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const
if( prc )
{
// calc user-defined rectangle
s1 = (float)prc->left / (float)w;
t1 = (float)prc->top / (float)h;
s2 = (float)prc->right / (float)w;
t2 = (float)prc->bottom / (float)h;
s1 = prc->left / (float)w;
t1 = prc->top / (float)h;
s2 = prc->right / (float)w;
t2 = prc->bottom / (float)h;
if( width == -1 && height == -1 )
{
@@ -511,10 +463,9 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const
}
// pass scissor test if supposed
if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
if( !CL_Scissor( &gameui.ds.scissor, &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
return;
PicAdjustSize( &x, &y, &width, &height );
ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, gameui.ds.gl_texturenum );
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
}
@@ -659,11 +610,7 @@ static void GAME_EXPORT pfnPIC_EnableScissor( int x, int y, int width, int heigh
width = bound( 0, width, gameui.globals->scrWidth - x );
height = bound( 0, height, gameui.globals->scrHeight - y );
gameui.ds.scissor_x = x;
gameui.ds.scissor_width = width;
gameui.ds.scissor_y = y;
gameui.ds.scissor_height = height;
gameui.ds.scissor_test = true;
CL_EnableScissor( &gameui.ds.scissor, x, y, width, height );
}
/*
@@ -674,11 +621,7 @@ pfnPIC_DisableScissor
*/
static void GAME_EXPORT pfnPIC_DisableScissor( void )
{
gameui.ds.scissor_x = 0;
gameui.ds.scissor_width = 0;
gameui.ds.scissor_y = 0;
gameui.ds.scissor_height = 0;
gameui.ds.scissor_test = false;
CL_DisableScissor( &gameui.ds.scissor );
}
/*
@@ -766,7 +709,7 @@ static void GAME_EXPORT pfnDrawCharacter( int ix, int iy, int iwidth, int iheigh
t2 = t1 + size;
// pass scissor test if supposed
if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
if( !CL_Scissor( &gameui.ds.scissor, &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
return;
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
@@ -895,7 +838,7 @@ send client connect
*/
static void GAME_EXPORT pfnClientJoin( const netadr_t adr )
{
Cbuf_AddText( va( "connect %s\n", NET_AdrToString( adr )));
Cbuf_AddTextf( "connect %s\n", NET_AdrToString( adr ));
}
/*
@@ -980,7 +923,7 @@ pfnGetGamesList
*/
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
{
if( numGames ) *numGames = SI.numgames;
if( numGames ) *numGames = FI->numgames;
return gameui.modsInfo;
}
@@ -1060,10 +1003,7 @@ pfnChangeInstance
*/
static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage )
{
if( !szFinalMessage ) szFinalMessage = "";
if( !newInstance || !*newInstance ) return;
Host_NewInstance( newInstance, szFinalMessage );
Con_Reportf( S_ERROR "ChangeInstance menu call is deprecated!\n" );
}
/*
@@ -1120,6 +1060,30 @@ static char *pfnParseFile( char *buf, char *token )
return COM_ParseFile( buf, token, INT_MAX );
}
/*
=============
pfnFileExists
legacy wrapper
=============
*/
static int pfnFileExists( const char *path, int gamedironly )
{
return FS_FileExists( path, gamedironly );
}
/*
=============
pfnDelete
legacy wrapper
=============
*/
static int pfnDelete( const char *path )
{
return FS_Delete( path );
}
// engine callbacks
static ui_enginefuncs_t gEngfuncs =
{
@@ -1166,7 +1130,7 @@ static ui_enginefuncs_t gEngfuncs =
pfnRenderScene,
pfnAddEntity,
Host_Error,
FS_FileExists,
pfnFileExists,
pfnGetGameDir,
Cmd_CheckMapsList,
CL_Active,
@@ -1205,7 +1169,7 @@ static ui_enginefuncs_t gEngfuncs =
COM_CompareFileTime,
VID_GetModeString,
(void*)COM_SaveFile,
(void*)FS_Delete
pfnDelete
};
static void pfnEnableTextInput( int enable )
@@ -1227,6 +1191,11 @@ static int pfnGetRenderers( unsigned int num, char *shortName, size_t size1, cha
return 1;
}
static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned int flags, int *len )
{
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static ui_extendedfuncs_t gExtendedfuncs =
{
pfnEnableTextInput,
@@ -1235,8 +1204,9 @@ static ui_extendedfuncs_t gExtendedfuncs =
Con_UtfMoveRight,
pfnGetRenderers,
Sys_DoubleTime,
_COM_ParseFileSafe,
NET_AdrToString
pfnParseFileSafe,
NET_AdrToString,
NET_CompareAdrSort,
};
void UI_UnloadProgs( void )
@@ -1356,13 +1326,13 @@ qboolean UI_LoadProgs( void )
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
// setup gameinfo
for( i = 0; i < SI.numgames; i++ )
for( i = 0; i < FI->numgames; i++ )
{
gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO ));
UI_ConvertGameInfo( gameui.modsInfo[i], SI.games[i] );
UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] );
}
UI_ConvertGameInfo( &gameui.gameInfo, SI.GameInfo ); // current gameinfo
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo
// setup globals
gameui.globals->developer = host.allow_console;

View File

@@ -22,12 +22,14 @@ GNU General Public License for more details.
#include "vgui_draw.h"
#include "library.h"
#include "vid_common.h"
#include "pm_local.h"
#include "sequence.h"
#define MAX_TOTAL_CMDS 32
#define MAX_CMD_BUFFER 8000
#define CONNECTION_PROBLEM_TIME 15.0 // 15 seconds
#define CL_CONNECTION_RETRIES 10
#define CL_TEST_RETRIES_NORESPONCE 2
#define CL_TEST_RETRIES_NORESPONCE 3
#define CL_TEST_RETRIES 5
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
@@ -38,8 +40,8 @@ CVAR_DEFINE_AUTO( cl_allow_upload, "1", FCVAR_ARCHIVE, "allow to uploading resou
CVAR_DEFINE_AUTO( cl_download_ingame, "1", FCVAR_ARCHIVE, "allow to downloading resources while client is active" );
CVAR_DEFINE_AUTO( cl_logofile, "lambda", FCVAR_ARCHIVE, "player logo name" );
CVAR_DEFINE_AUTO( cl_logocolor, "orange", FCVAR_ARCHIVE, "player logo color" );
CVAR_DEFINE_AUTO( cl_logoext, "bmp", FCVAR_ARCHIVE, "temporary cvar to tell engine which logo must be packed" );
CVAR_DEFINE_AUTO( cl_test_bandwidth, "1", FCVAR_ARCHIVE, "test network bandwith before connection" );
convar_t *rcon_client_password;
convar_t *rcon_address;
convar_t *cl_timeout;
convar_t *cl_nopred;
@@ -56,6 +58,7 @@ convar_t *cl_nosmooth;
convar_t *cl_smoothtime;
convar_t *cl_clockreset;
convar_t *cl_fixtimerate;
convar_t *hud_fontscale;
convar_t *hud_scale;
convar_t *cl_solid_players;
convar_t *cl_draw_beams;
@@ -70,6 +73,7 @@ convar_t *cl_upmax;
convar_t *cl_lw;
convar_t *cl_charset;
convar_t *cl_trace_messages;
convar_t *cl_nat;
convar_t *hud_utf8;
convar_t *ui_renderworld;
@@ -146,16 +150,6 @@ qboolean CL_DisableVisibility( void )
return cls.envshot_disable_vis;
}
qboolean CL_IsBackgroundDemo( void )
{
return ( cls.demoplayback && cls.demonum != -1 );
}
qboolean CL_IsBackgroundMap( void )
{
return ( cl.background && !cls.demoplayback );
}
char *CL_Userinfo( void )
{
return cls.userinfo;
@@ -195,8 +189,6 @@ void CL_CheckClientState( void )
Netchan_ReportFlow( &cls.netchan );
Con_DPrintf( "client connected at %.2f sec\n", Sys_DoubleTime() - cls.timestart );
if(( cls.demoplayback || cls.disable_servercount != cl.servercount ) && cl.video_prepped )
SCR_EndLoadingPlaque(); // get rid of loading plaque
}
}
@@ -234,18 +226,17 @@ void CL_SignonReply( void )
Mem_PrintStats();
break;
case 2:
SCR_EndLoadingPlaque();
if( cl.proxy_redirect && !cls.spectator )
CL_Disconnect();
cl.proxy_redirect = false;
if( cls.demoplayback )
Sequence_OnLevelLoad( clgame.mapname );
break;
}
}
float CL_LerpInterval( void )
{
return Q_max( cl_interp->value, 1.f / cl_updaterate->value );
}
/*
===============
CL_LerpPoint
@@ -256,55 +247,26 @@ should be put at.
*/
static float CL_LerpPoint( void )
{
float frac = 1.0f;
float server_frametime = cl_serverframetime();
double f = cl_serverframetime();
double frac;
if( server_frametime == 0.0f || cls.timedemo )
if( f == 0.0 || cls.timedemo )
{
double fgap = cl_clientframetime();
cl.time = cl.mtime[0];
// maybe don't need for Xash demos
if( cls.demoplayback )
cl.oldtime = cl.mtime[0] - fgap;
return 1.0f;
}
if( server_frametime > 0.1f )
{
// dropped packet, or start of demo
cl.mtime[1] = cl.mtime[0] - 0.1f;
server_frametime = 0.1f;
}
#if 0
/*
g-cont: this code more suitable for singleplayer
NOTE in multiplayer causes significant framerate stutter/jitter and
occuring frames with zero time delta and even with negative time delta.
game becomes more twitchy and as if without interpolation.
*/
frac = (cl.time - cl.mtime[1]) / f;
if( frac < 0.0f )
{
if( frac < -0.01f )
cl.time = cl.mtime[1];
frac = 0.0f;
}
else if( frac > 1.0f )
{
if( frac > 1.01f )
cl.time = cl.mtime[0];
frac = 1.0f;
}
#else
// for multiplayer
if( cl_interp->value > 0.001f )
{
// manual lerp value (goldsrc mode)
float td = Q_max( 0.f, cl.time - cl.mtime[0] );
frac = td / CL_LerpInterval();
}
else if( server_frametime > 0.001f )
{
// automatic lerp (classic mode)
frac = ( cl.time - cl.mtime[1] ) / server_frametime;
}
#endif
if( cl_interp->value <= 0.001 )
return 1.0f;
frac = ( cl.time - cl.mtime[0] ) / cl_interp->value;
return frac;
}
@@ -346,7 +308,7 @@ Validate interpolation cvars, calc interpolation window
void CL_ComputeClientInterpolationAmount( usercmd_t *cmd )
{
const float epsilon = 0.001f; // to avoid float invalid comparision
float min_interp = MIN_EX_INTERP;
float min_interp;
float max_interp = MAX_EX_INTERP;
float interpolation_time;
@@ -366,8 +328,8 @@ void CL_ComputeClientInterpolationAmount( usercmd_t *cmd )
max_interp = 0.2f;
min_interp = 1.0f / cl_updaterate->value;
interpolation_time = CL_LerpInterval( );
interpolation_time = cl_interp->value * 1000.0;
if( (cl_interp->value + epsilon) < min_interp )
{
Con_Printf( "ex_interp forced up to %.1f msec\n", min_interp * 1000.f );
@@ -622,7 +584,7 @@ CL_CreateCmd
*/
void CL_CreateCmd( void )
{
usercmd_t cmd;
usercmd_t nullcmd, *cmd;
runcmd_t *pcmd;
vec3_t angles;
qboolean active;
@@ -635,7 +597,6 @@ void CL_CreateCmd( void )
// store viewangles in case it's will be freeze
VectorCopy( cl.viewangles, angles );
ms = bound( 1, host.frametime * 1000, 255 );
memset( &cmd, 0, sizeof( cmd ));
input_override = 0;
CL_SetSolidEntities();
@@ -654,12 +615,18 @@ void CL_CreateCmd( void )
pcmd->receivedtime = -1.0;
pcmd->heldback = false;
pcmd->sendsize = 0;
cmd = &pcmd->cmd;
}
else
{
memset( &nullcmd, 0, sizeof( nullcmd ));
cmd = &nullcmd;
}
active = (( cls.signon == SIGNONS ) && !cl.paused && !cls.demoplayback );
Platform_PreCreateMove();
clgame.dllFuncs.CL_CreateMove( host.frametime, &pcmd->cmd, active );
IN_EngineAppendMove( host.frametime, &pcmd->cmd, active );
clgame.dllFuncs.CL_CreateMove( host.frametime, cmd, active );
IN_EngineAppendMove( host.frametime, cmd, active );
CL_PopPMStates();
@@ -736,15 +703,22 @@ void CL_WritePacket( void )
CL_ComputePacketLoss ();
memset( data, 0, sizeof( data ));
MSG_Init( &buf, "ClientData", data, sizeof( data ));
// Determine number of backup commands to send along
numbackup = bound( 0, cl_cmdbackup->value, MAX_BACKUP_COMMANDS );
numbackup = bound( 0, cl_cmdbackup->value, cls.legacymode ? MAX_LEGACY_BACKUP_CMDS : MAX_BACKUP_COMMANDS );
if( cls.state == ca_connected ) numbackup = 0;
// clamp cmdrate
if( cl_cmdrate->value < 0.0f ) Cvar_SetValue( "cl_cmdrate", 0.0f );
else if( cl_cmdrate->value > 100.0f ) Cvar_SetValue( "cl_cmdrate", 100.0f );
if( cl_cmdrate->value < 10.0f )
{
Cvar_SetValue( "cl_cmdrate", 10.0f );
}
else if( cl_cmdrate->value > 100.0f )
{
Cvar_SetValue( "cl_cmdrate", 100.0f );
}
// Check to see if we can actually send this command
@@ -774,6 +748,7 @@ void CL_WritePacket( void )
if(( host.realtime - cls.netchan.last_received ) > CONNECTION_PROBLEM_TIME )
{
Con_NPrintf( 1, "^3Warning:^1 Connection Problem^7\n" );
Con_NPrintf( 2, "^1Auto-disconnect in %.1f seconds^7", cl_timeout->value - ( host.realtime - cls.netchan.last_received ));
cl.validsequence = 0;
}
}
@@ -813,12 +788,13 @@ void CL_WritePacket( void )
newcmds = ( cls.netchan.outgoing_sequence - cls.lastoutgoingcommand );
// put an upper/lower bound on this
newcmds = bound( 0, newcmds, cls.legacymode?MAX_LEGACY_TOTAL_CMDS:MAX_TOTAL_CMDS );
newcmds = bound( 0, newcmds, cls.legacymode ? MAX_LEGACY_TOTAL_CMDS: MAX_TOTAL_CMDS );
if( cls.state == ca_connected ) newcmds = 0;
MSG_WriteByte( &buf, newcmds );
numcmds = newcmds + numbackup;
from = -1;
for( i = numcmds - 1; i >= 0; i-- )
@@ -864,6 +840,9 @@ void CL_WritePacket( void )
cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].sendsize = MSG_GetNumBytesWritten( &buf );
cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].heldback = false;
// send voice data to the server
CL_AddVoiceToDatagram();
// composite the rest of the datagram..
if( MSG_GetNumBitsWritten( &cls.datagram ) <= MSG_GetNumBitsLeft( &buf ))
MSG_WriteBits( &buf, MSG_GetData( &cls.datagram ), MSG_GetNumBitsWritten( &cls.datagram ));
@@ -1041,9 +1020,12 @@ void CL_SendConnectPacket( void )
input_devices = IN_CollectInputDevices();
IN_LockInputDevices( true );
Info_SetValueForKey( protinfo, "d", va( "%d", input_devices ), sizeof( protinfo ) );
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
Info_SetValueForKeyf( protinfo, "d", sizeof( protinfo ), "%d", input_devices );
Info_SetValueForKey( protinfo, "v", XASH_VERSION, sizeof( protinfo ) );
Info_SetValueForKey( protinfo, "b", va( "%d", Q_buildnum() ), sizeof( protinfo ) );
Info_SetValueForKeyf( protinfo, "b", sizeof( protinfo ), "%d", Q_buildnum( ));
Info_SetValueForKey( protinfo, "o", Q_buildos(), sizeof( protinfo ) );
Info_SetValueForKey( protinfo, "a", Q_buildarch(), sizeof( protinfo ) );
}
@@ -1077,7 +1059,7 @@ void CL_SendConnectPacket( void )
Info_SetValueForKey( protinfo, "uuid", key, sizeof( protinfo ));
Info_SetValueForKey( protinfo, "qport", qport, sizeof( protinfo ));
Info_SetValueForKey( protinfo, "ext", va("%d", extensions), sizeof( protinfo ));
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", extensions);
Netchan_OutOfBandPrint( NS_CLIENT, adr, "connect %i %i \"%s\" \"%s\"\n", PROTOCOL_VERSION, cls.challenge, protinfo, cls.userinfo );
Con_Printf( "Trying to connect by modern protocol\n" );
@@ -1095,8 +1077,9 @@ Resend a connect message if the last one has timed out
*/
void CL_CheckForResend( void )
{
netadr_t adr;
int res;
netadr_t adr;
net_gai_state_t res;
qboolean bandwidthTest;
if( cls.internetservers_wait )
CL_InternetServers_f();
@@ -1128,13 +1111,13 @@ void CL_CheckForResend( void )
res = NET_StringToAdrNB( cls.servername, &adr );
if( !res )
if( res == NET_EAI_NONAME )
{
CL_Disconnect();
return;
}
if( res == 2 )
if( res == NET_EAI_AGAIN )
{
cls.connect_time = MAX_HEARTBEAT;
return;
@@ -1161,14 +1144,18 @@ void CL_CheckForResend( void )
return;
}
bandwidthTest = !cls.legacymode && cl_test_bandwidth.value;
cls.serveradr = adr;
cls.max_fragment_size = Q_max( FRAGMENT_MAX_SIZE, cls.max_fragment_size >> Q_min( 1, cls.connect_retry ));
cls.max_fragment_size = Q_min( FRAGMENT_MAX_SIZE, cls.max_fragment_size / (cls.connect_retry + 1));
cls.connect_time = host.realtime; // for retransmit requests
cls.connect_retry++;
Con_Printf( "Connecting to %s... [retry #%i]\n", cls.servername, cls.connect_retry );
if( bandwidthTest )
Con_Printf( "Connecting to %s... [retry #%i, max fragment size %i]\n", cls.servername, cls.connect_retry, cls.max_fragment_size );
else
Con_Printf( "Connecting to %s... [retry #%i]\n", cls.servername, cls.connect_retry );
if( !cls.legacymode && cl_test_bandwidth.value )
if( bandwidthTest )
Netchan_OutOfBandPrint( NS_CLIENT, adr, "bandwidth %i %i\n", PROTOCOL_VERSION, cls.max_fragment_size );
else
Netchan_OutOfBandPrint( NS_CLIENT, adr, "getchallenge\n" );
@@ -1193,7 +1180,7 @@ resource_t *CL_AddResource( resourcetype_t type, const char *name, int size, qbo
void CL_CreateResourceList( void )
{
char szFileName[MAX_OSPATH];
char szFileName[MAX_OSPATH];
byte rgucMD5_hash[16];
resource_t *pNewResource;
int nSize;
@@ -1201,30 +1188,36 @@ void CL_CreateResourceList( void )
HPAK_FlushHostQueue();
cl.num_resources = 0;
Q_snprintf( szFileName, sizeof( szFileName ), "logos/remapped.bmp" );
memset( rgucMD5_hash, 0, sizeof( rgucMD5_hash ));
// sanitize cvar value
if( Q_strcmp( cl_logoext.string, "bmp" ) &&
Q_strcmp( cl_logoext.string, "png" ))
Cvar_DirectSet( &cl_logoext, "bmp" );
Q_snprintf( szFileName, sizeof( szFileName ),
"logos/remapped.%s", cl_logoext.string );
fp = FS_Open( szFileName, "rb", true );
if( fp )
if( !fp )
return;
MD5_HashFile( rgucMD5_hash, szFileName, NULL );
nSize = FS_FileLength( fp );
if( nSize != 0 )
{
MD5_HashFile( rgucMD5_hash, szFileName, NULL );
nSize = FS_FileLength( fp );
pNewResource = CL_AddResource( t_decal, szFileName, nSize, false, 0 );
if( nSize != 0 )
if( pNewResource )
{
pNewResource = CL_AddResource( t_decal, szFileName, nSize, false, 0 );
if( pNewResource )
{
SetBits( pNewResource->ucFlags, RES_CUSTOM );
memcpy( pNewResource->rgucMD5_hash, rgucMD5_hash, 16 );
HPAK_AddLump( false, CUSTOM_RES_PATH, pNewResource, NULL, fp );
}
SetBits( pNewResource->ucFlags, RES_CUSTOM );
memcpy( pNewResource->rgucMD5_hash, rgucMD5_hash, 16 );
HPAK_AddLump( false, CUSTOM_RES_PATH, pNewResource, NULL, fp );
}
FS_Close( fp );
}
FS_Close( fp );
}
/*
@@ -1253,7 +1246,7 @@ void CL_Connect_f( void )
// if running a local server, kill it and reissue
if( SV_Active( )) Host_ShutdownServer();
NET_Config( true ); // allow remote
NET_Config( true, !CVAR_TO_BOOL( cl_nat )); // allow remote
Con_Printf( "server %s\n", server );
CL_Disconnect();
@@ -1287,7 +1280,7 @@ void CL_Rcon_f( void )
string command;
int i;
if( !COM_CheckString( rcon_client_password->string ))
if( !COM_CheckString( rcon_password.string ))
{
Con_Printf( "You must set 'rcon_password' before issuing an rcon command.\n" );
return;
@@ -1299,17 +1292,17 @@ void CL_Rcon_f( void )
message[3] = (char)255;
message[4] = 0;
NET_Config( true ); // allow remote
NET_Config( true, false ); // allow remote
Q_strcat( message, "rcon " );
Q_strcat( message, rcon_client_password->string );
Q_strcat( message, " " );
Q_strncat( message, "rcon ", sizeof( message ));
Q_strncat( message, rcon_password.string, sizeof( message ));
Q_strncat( message, " ", sizeof( message ) );
for( i = 1; i < Cmd_Argc(); i++ )
{
Cmd_Escape( command, Cmd_Argv( i ), sizeof( command ));
Q_strcat( message, command );
Q_strcat( message, " " );
Q_strncat( message, command, sizeof( message ));
Q_strncat( message, " ", sizeof( message ));
}
if( cls.state >= ca_connected )
@@ -1351,7 +1344,7 @@ void CL_ClearState( void )
CL_ClearEffects ();
CL_FreeEdicts ();
CL_ClearPhysEnts ();
PM_ClearPhysEnts( clgame.pmove );
NetAPI_CancelAllRequests();
// wipe the entire cl structure
@@ -1359,6 +1352,7 @@ void CL_ClearState( void )
MSG_Clear( &cls.netchan.message );
memset( &clgame.fade, 0, sizeof( clgame.fade ));
memset( &clgame.shake, 0, sizeof( clgame.shake ));
clgame.mapname[0] = '\0';
Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
cl.maxclients = 1; // allow to drawing player in menu
cl.mtime[0] = cl.mtime[1] = 1.0f; // because level starts from 1.0f second
@@ -1500,6 +1494,7 @@ void CL_Disconnect( void )
cls.connect_time = 0;
cls.changedemo = false;
cls.max_fragment_size = FRAGMENT_MAX_SIZE; // reset fragment size
Voice_Disconnect();
CL_Stop_f();
// send a disconnect message to the server
@@ -1562,16 +1557,43 @@ void CL_LocalServers_f( void )
netadr_t adr;
Con_Printf( "Scanning for servers on the local network area...\n" );
NET_Config( true ); // allow remote
NET_Config( true, true ); // allow remote
// send a broadcast packet
adr.type = NA_BROADCAST;
adr.port = MSG_BigShort( PORT_SERVER );
Netchan_OutOfBandPrint( NS_CLIENT, adr, "info %i", PROTOCOL_VERSION );
adr.type = NA_MULTICAST_IP6;
Netchan_OutOfBandPrint( NS_CLIENT, adr, "info %i", PROTOCOL_VERSION );
}
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
/*
=================
CL_BuildMasterServerScanRequest
=================
*/
size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat )
{
size_t remaining;
char *info;
if( unlikely( size < sizeof( MS_SCAN_REQUEST )))
return 0;
Q_strncpy( buf, MS_SCAN_REQUEST, size );
info = buf + sizeof( MS_SCAN_REQUEST ) - 1;
remaining = size - sizeof( MS_SCAN_REQUEST );
info[0] = 0;
Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining );
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
return sizeof( MS_SCAN_REQUEST ) + Q_strlen( info );
}
/*
=================
@@ -1580,18 +1602,17 @@ CL_InternetServers_f
*/
void CL_InternetServers_f( void )
{
char fullquery[512] = MS_SCAN_REQUEST;
char *info = fullquery + sizeof( MS_SCAN_REQUEST ) - 1;
const size_t remaining = sizeof( fullquery ) - sizeof( MS_SCAN_REQUEST );
char fullquery[512];
size_t len;
qboolean nat = cl_nat->value != 0.0f;
NET_Config( true ); // allow remote
len = CL_BuildMasterServerScanRequest( fullquery, sizeof( fullquery ), nat );
Con_Printf( "Scanning for servers on the internet area...\n" );
Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining );
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version
// Info_SetValueForKey( info, "nat", cl_nat->string, remaining );
cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ), fullquery );
NET_Config( true, true ); // allow remote
cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, len, fullquery );
cls.internetservers_pending = true;
if( !cls.internetservers_wait )
@@ -1625,6 +1646,8 @@ void CL_Reconnect_f( void )
if( COM_CheckString( cls.servername ))
{
qboolean legacy = cls.legacymode;
if( cls.state >= ca_connected )
CL_Disconnect();
@@ -1632,6 +1655,7 @@ void CL_Reconnect_f( void )
cls.demonum = cls.movienum = -1; // not in the demo loop now
cls.state = ca_connecting;
cls.signon = 0;
cls.legacymode = legacy; // don't change protocol
Con_Printf( "reconnecting...\n" );
}
@@ -1713,16 +1737,23 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
static char infostring[MAX_INFO_STRING+8];
char *s = MSG_ReadString( msg );
int i;
const char *magic = ": wrong version\n";
size_t len = Q_strlen( s ), magiclen = Q_strlen( magic );
CL_FixupColorStringsForInfoString( s, infostring );
if( Q_strstr( infostring, "wrong version" ) )
if( len >= magiclen && !Q_strcmp( s + len - magiclen, magic ))
{
Netchan_OutOfBandPrint( NS_CLIENT, from, "info %i", PROTOCOL_LEGACY_VERSION );
Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring );
return;
}
if( !Info_IsValid( s ))
{
Con_Printf( "^1Server^7: %s, invalid infostring\n", NET_AdrToString( from ));
return;
}
CL_FixupColorStringsForInfoString( s, infostring );
if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" )))
{
Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring );
@@ -1732,11 +1763,13 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
if( !COM_CheckString( Info_ValueForKey( infostring, "p" )))
{
Info_SetValueForKey( infostring, "legacy", "1", sizeof( infostring ) );
Con_Print("Legacy: ");
Con_Printf( "^3Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" ));
}
else
{
// more info about servers
Con_Printf( "^2Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" ));
}
// more info about servers
Con_Printf( "^2Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" ));
UI_AddServerToList( from, infostring );
}
@@ -2047,7 +2080,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
if( NET_CompareAdr( from, cls.legacyserver ))
{
Cbuf_AddText( va( "connect %s legacy\n", NET_AdrToString( from )));
Cbuf_AddTextf( "connect %s legacy\n", NET_AdrToString( from ));
memset( &cls.legacyserver, 0, sizeof( cls.legacyserver ));
}
}
@@ -2095,6 +2128,12 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
else if( !Q_strcmp( c, "f" ))
{
if( !NET_IsMasterAdr( from ))
{
Con_Printf( S_WARN "unexpected server list packet from %s\n", NET_AdrToString( from ));
return;
}
// serverlist got from masterserver
while( MSG_GetNumBitsLeft( msg ) > 8 )
{
@@ -2153,7 +2192,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
else if( clgame.request_type == NET_REQUEST_GAMEUI )
{
NET_Config( true ); // allow remote
NET_Config( true, false ); // allow remote
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
}
}
@@ -2405,11 +2444,18 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{
if( filename[0] != '!' )
Con_Printf( "processing %s\n", filename );
if( !Q_strnicmp( filename, "downloaded/", 11 ))
{
// skip "downloaded/" part to avoid mismatch with needed resources list
filename += 11;
}
}
else if( !successfully_received )
{
Con_Printf( S_ERROR "server failed to transmit file '%s'\n", CL_CleanFileName( filename ));
}
if( cls.legacymode )
{
if( host.downloadcount > 0 )
@@ -2537,7 +2583,7 @@ void CL_ServerCommand( qboolean reliable, const char *fmt, ... )
return;
va_start( argptr, fmt );
Q_vsprintf( string, fmt, argptr );
Q_vsnprintf( string, sizeof( string ), fmt, argptr );
va_end( argptr );
if( reliable )
@@ -2806,8 +2852,12 @@ void CL_InitLocal( void )
Cvar_RegisterVariable( &cl_download_ingame );
Cvar_RegisterVariable( &cl_logofile );
Cvar_RegisterVariable( &cl_logocolor );
Cvar_RegisterVariable( &cl_logoext );
Cvar_RegisterVariable( &cl_test_bandwidth );
Voice_RegisterCvars();
VGui_RegisterCvars();
// register our variables
cl_crosshair = Cvar_Get( "crosshair", "1", FCVAR_ARCHIVE, "show weapon chrosshair" );
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0, "disable delta-compression for server messages" );
@@ -2818,7 +2868,6 @@ void CL_InitLocal( void )
cl_charset = Cvar_Get( "cl_charset", "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
hud_utf8 = Cvar_Get( "hud_utf8", "0", FCVAR_ARCHIVE, "Use utf-8 encoding for hud text" );
rcon_client_password = Cvar_Get( "rcon_password", "", FCVAR_PRIVILEGED, "remote control client password" );
rcon_address = Cvar_Get( "rcon_address", "", FCVAR_PRIVILEGED, "remote control address" );
cl_trace_messages = Cvar_Get( "cl_trace_messages", "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)");
@@ -2830,6 +2879,7 @@ void CL_InitLocal( void )
cl_updaterate = Cvar_Get( "cl_updaterate", "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" );
cl_dlmax = Cvar_Get( "cl_dlmax", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
cl_upmax = Cvar_Get( "cl_upmax", "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
cl_nat = Cvar_Get( "cl_nat", "0", 0, "show servers running under NAT" );
rate = Cvar_Get( "rate", "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
topcolor = Cvar_Get( "topcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player top color" );
bottomcolor = Cvar_Get( "bottomcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player bottom color" );
@@ -2841,9 +2891,9 @@ void CL_InitLocal( void )
cl_nosmooth = Cvar_Get( "cl_nosmooth", "0", FCVAR_ARCHIVE, "disable smooth up stair climbing" );
cl_nointerp = Cvar_Get( "cl_nointerp", "0", FCVAR_CLIENTDLL, "disable interpolation of entities and players" );
cl_smoothtime = Cvar_Get( "cl_smoothtime", "0", FCVAR_ARCHIVE, "time to smooth up" );
cl_smoothtime = Cvar_Get( "cl_smoothtime", "0.1", FCVAR_ARCHIVE, "time to smooth up" );
cl_cmdbackup = Cvar_Get( "cl_cmdbackup", "10", FCVAR_ARCHIVE, "how many additional history commands are sent" );
cl_cmdrate = Cvar_Get( "cl_cmdrate", "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
cl_cmdrate = Cvar_Get( "cl_cmdrate", "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
cl_draw_particles = Cvar_Get( "r_drawparticles", "1", FCVAR_CHEAT, "render particles" );
cl_draw_tracers = Cvar_Get( "r_drawtracers", "1", FCVAR_CHEAT, "render tracers" );
cl_draw_beams = Cvar_Get( "r_drawbeams", "1", FCVAR_CHEAT, "render beams" );
@@ -2852,6 +2902,7 @@ void CL_InitLocal( void )
cl_bmodelinterp = Cvar_Get( "cl_bmodelinterp", "1", FCVAR_ARCHIVE, "enable bmodel interpolation" );
cl_clockreset = Cvar_Get( "cl_clockreset", "0.1", FCVAR_ARCHIVE, "frametime delta maximum value before reset" );
cl_fixtimerate = Cvar_Get( "cl_fixtimerate", "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" );
hud_fontscale = Cvar_Get( "hud_fontscale", "1.0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud font texture" );
hud_scale = Cvar_Get( "hud_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" );
Cvar_Get( "cl_background", "0", FCVAR_READ_ONLY, "indicate what background map is running" );
cl_showevents = Cvar_Get( "cl_showevents", "0", FCVAR_ARCHIVE, "show events playback" );
@@ -2872,7 +2923,12 @@ void CL_InitLocal( void )
Cmd_AddRestrictedCommand ("kill", NULL, "die instantly" );
Cmd_AddCommand ("god", NULL, "enable godmode" );
Cmd_AddCommand ("fov", NULL, "set client field of view" );
Cmd_AddCommand ("log", NULL, "logging server events" );
Cmd_AddRestrictedCommand ("ent_list", NULL, "list entities on server" );
Cmd_AddRestrictedCommand ("ent_fire", NULL, "fire entity command (be careful)" );
Cmd_AddRestrictedCommand ("ent_info", NULL, "dump entity information" );
Cmd_AddRestrictedCommand ("ent_create", NULL, "create entity with specified values (be careful)" );
Cmd_AddRestrictedCommand ("ent_getvars", NULL, "put parameters of specified entities to client's' ent_last_* cvars" );
// register our commands
Cmd_AddCommand ("pause", NULL, "pause the game (if the server allows pausing)" );
@@ -2940,12 +2996,12 @@ void CL_AdjustClock( void )
if( fabs( cl.timedelta ) >= 0.001f )
{
double msec, adjust;
float sign;
double sign;
msec = ( cl.timedelta * 1000.0f );
sign = ( msec < 0 ) ? 1.0f : -1.0f;
msec = fabs( msec );
adjust = sign * ( cl_fixtimerate->value / 1000.0f );
msec = ( cl.timedelta * 1000.0 );
sign = ( msec < 0 ) ? 1.0 : -1.0;
msec = Q_min( cl_fixtimerate->value, fabs( msec ));
adjust = sign * ( msec / 1000.0 );
if( fabs( adjust ) < fabs( cl.timedelta ))
{
@@ -3009,8 +3065,8 @@ void Host_ClientFrame( void )
// a new portion updates from server
CL_RedoPrediction ();
// TODO: implement
// Voice_Idle( host.frametime );
// update voice
Voice_Idle( host.frametime );
// emit visible entities
CL_EmitEntities ();
@@ -3030,9 +3086,6 @@ void Host_ClientFrame( void )
// catch changes video settings
VID_CheckChanges();
// process VGUI
VGui_RunFrame ();
// update the screen
SCR_UpdateScreen ();
@@ -3064,6 +3117,8 @@ void CL_Init( void )
VID_Init(); // init video
S_Init(); // init sound
Voice_Init( VOICE_DEFAULT_CODEC, 3 ); // init voice
Sequence_Init();
// unreliable buffer. unsed for unreliable commands and voice stream
MSG_Init( &cls.datagram, "cls.datagram", cls.datagram_buf, sizeof( cls.datagram_buf ));
@@ -3091,7 +3146,7 @@ void CL_Shutdown( void )
{
Con_Printf( "CL_Shutdown()\n" );
if( !host.crashed )
if( !host.crashed && cls.initialized )
{
Host_WriteOpenGLConfig ();
Host_WriteVideoConfig ();
@@ -3107,9 +3162,12 @@ void CL_Shutdown( void )
CL_UnloadProgs ();
cls.initialized = false;
VGui_Shutdown();
// for client-side VGUI support we use other order
if( FI && FI->GameInfo && !FI->GameInfo->internal_vgui_support )
VGui_Shutdown();
FS_Delete( "demoheader.tmp" ); // remove tmp file
if( g_fsapi.Delete )
g_fsapi.Delete( "demoheader.tmp" ); // remove tmp file
SCR_FreeCinematic (); // release AVI's *after* client.dll because custom renderer may use them
S_Shutdown ();
R_Shutdown ();

View File

@@ -25,6 +25,9 @@ mobile_engfuncs_t *gMobileEngfuncs;
convar_t *vibration_length;
convar_t *vibration_enable;
static cl_font_t g_scaled_font;
static float g_font_scale;
static void pfnVibrate( float life, char flags )
{
if( !vibration_enable->value )
@@ -60,28 +63,28 @@ static void pfnEnableTextInput( int enable )
static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b, float scale )
{
int width = clgame.scrInfo.charWidths[number] * scale * hud_scale->value;
int height = clgame.scrInfo.iCharHeight * scale * hud_scale->value;
// this call is very ineffective and possibly broken!
rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD;
if( !cls.creditsFont.valid )
return 0;
if( hud_utf8->value )
SetBits( flags, FONT_DRAW_UTF8 );
x *= hud_scale->value;
y *= hud_scale->value;
if( fabs( g_font_scale - scale ) > 0.1f ||
g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture )
{
int i;
number &= 255;
number = Con_UtfProcessChar( number );
g_scaled_font = cls.creditsFont;
g_scaled_font.scale *= scale;
g_scaled_font.charHeight *= scale;
for( i = 0; i < ARRAYSIZE( g_scaled_font.charWidths ); i++ )
g_scaled_font.charWidths[i] *= scale;
if( number < 32 )
return 0;
g_font_scale = scale;
}
if( y < -height )
return 0;
pfnPIC_Set( cls.creditsFont.hFontTexture, r, g, b, 255 );
pfnPIC_DrawAdditive( x, y, width, height, &cls.creditsFont.fontRc[number] );
return width;
return CL_DrawCharacter( x, y, number, color, &g_scaled_font, flags );
}
static void *pfnGetNativeObject( const char *obj )
@@ -103,6 +106,11 @@ static void pfnTouch_RemoveButton( const char *name )
Touch_RemoveButton( name, true );
}
static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned int flags, int *len )
{
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static mobile_engfuncs_t gpMobileEngfuncs =
{
MOBILITY_API_VERSION,
@@ -118,7 +126,7 @@ static mobile_engfuncs_t gpMobileEngfuncs =
Sys_Warn,
pfnGetNativeObject,
ID_SetCustomClientID,
_COM_ParseFileSafe
pfnParseFileSafe
};
qboolean Mobile_Init( void )

View File

@@ -158,6 +158,7 @@ static void NetGraph_InitColors( void )
f = (float)(i - hfrac) / (float)(NETGRAPH_LERP_HEIGHT - hfrac );
VectorMA( mincolor[1], f, dc[1], netcolors[NETGRAPH_NET_COLORS + i] );
}
netcolors[NETGRAPH_NET_COLORS + i][3] = 255;
}
}
@@ -259,7 +260,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
for( a = 0; a < w; a++ )
{
i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK;
h = ( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT;
h = Q_min(( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT, net_graphheight->value * 0.7f);
fill.left = x + w - a - 1;
fill.right = fill.bottom = 1;
@@ -280,7 +281,10 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
for( j = start; j < h; j++ )
{
NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + extrap_point] );
int color = NETGRAPH_NET_COLORS + j + extrap_point;
color = Q_min( color, ARRAYSIZE( netcolors ) - 1 );
NetGraph_DrawRect( &fill, netcolors[color] );
fill.top--;
}
}
@@ -296,7 +300,10 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
for( j = 0; j < h; j++ )
{
NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + oldh] );
int color = NETGRAPH_NET_COLORS + j + oldh;
color = Q_min( color, ARRAYSIZE( netcolors ) - 1 );
NetGraph_DrawRect( &fill, netcolors[color] );
fill.top--;
}
}
@@ -357,6 +364,7 @@ NetGraph_DrawTextFields
static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke, int graphtype )
{
static int lastout;
cl_font_t *font = Con_GetFont( 0 );
rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 };
int ptx = Q_max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 );
int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 );
@@ -378,16 +386,17 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
// move rolling average
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate;
Con_SetFont( 0 );
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
if( framerate > 0.0f )
{
y -= net_graphheight->value;
Con_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors );
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE, "%.1f fps" , 1.0f / framerate);
if( avg > 1.0f )
Con_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors );
CL_DrawStringf( font, x + 75, y, colors, FONT_DRAW_NORENDERMODE, "%i ms" , (int)avg );
y += 15;
@@ -395,10 +404,12 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
if( !out ) out = lastout;
else lastout = out;
Con_DrawString( x, y, va( "in : %i %.2f k/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors );
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE,
"in : %i %.2f kb/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec );
y += 15;
Con_DrawString( x, y, va( "out: %i %.2f k/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors );
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE,
"out: %i %.2f kb/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec );
y += 15;
if( graphtype > 2 )
@@ -406,16 +417,14 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01f );
int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01f );
Con_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors );
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE, "loss: %i choke: %i", loss, choke );
}
}
if( graphtype < 3 )
Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors );
CL_DrawStringf( font, ptx, pty, colors, FONT_DRAW_NORENDERMODE, "%i/s", (int)cl_cmdrate->value );
Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors );
Con_RestoreFont();
CL_DrawStringf( font, ptx, last_y, colors, FONT_DRAW_NORENDERMODE, "%i/s" , (int)cl_updaterate->value );
}
/*
@@ -615,7 +624,7 @@ static void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y )
*x = rect->left + rect->right - 5 - *w;
break;
case 2: // center
*x = rect->left + ( rect->right - 10 - *w ) / 2;
*x = ( rect->left + ( rect->right - 10 - *w )) / 2;
break;
default: // left sided
*x = rect->left + 5;
@@ -672,7 +681,7 @@ void SCR_DrawNetGraph( void )
if( graphtype < 3 )
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
ref.dllFuncs.GL_SetRenderMode( kRenderTransColor );
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, R_GetBuiltinTexture( REF_WHITE_TEXTURE ) );
ref.dllFuncs.Begin( TRI_QUADS ); // draw all the fills as a long solid sequence of quads for speedup reasons

View File

@@ -499,7 +499,7 @@ void CL_BatchResourceRequest( qboolean initialize )
if( !FBitSet( p->ucFlags, RES_REQUESTED ))
{
MSG_BeginClientCmd( &msg, clc_stringcmd );
MSG_WriteString( &msg, va( "dlfile !MD5%s", MD5_Print( p->rgucMD5_hash ) ) );
MSG_WriteStringf( &msg, "dlfile !MD5%s", MD5_Print( p->rgucMD5_hash ));;
SetBits( p->ucFlags, RES_REQUESTED );
}
break;
@@ -587,7 +587,7 @@ int CL_EstimateNeededResources( void )
return nTotalSize;
}
void CL_StartResourceDownloading( const char *pszMessage, qboolean bCustom )
static void CL_StartResourceDownloading( const char *pszMessage, qboolean bCustom )
{
resourceinfo_t ri;
@@ -603,6 +603,8 @@ void CL_StartResourceDownloading( const char *pszMessage, qboolean bCustom )
}
else
{
HTTP_ResetProcessState();
cls.state = ca_validate;
cls.dl.custom = false;
}
@@ -843,54 +845,76 @@ void CL_ParseFileTransferFailed( sizebuf_t *msg )
CL_ParseServerData
==================
*/
void CL_ParseServerData( sizebuf_t *msg )
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
{
char gamefolder[MAX_QPATH];
qboolean background;
int i;
Con_Reportf( "Serverdata packet received.\n" );
cls.timestart = Sys_DoubleTime();
HPAK_CheckSize( CUSTOM_RES_PATH );
Con_Reportf( "%s packet received.\n", legacy ? "Legacy serverdata" : "Serverdata" );
cls.timestart = Sys_DoubleTime();
cls.demowaiting = false; // server is changed
// wipe the client_t struct
if( !cls.changelevel && !cls.changedemo )
CL_ClearState ();
// Re-init hud video, especially if we changed game directories
clgame.dllFuncs.pfnVidInit();
cls.state = ca_connected;
// parse protocol version number
i = MSG_ReadLong( msg );
if( i != PROTOCOL_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
if( legacy )
{
if( i != PROTOCOL_LEGACY_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_LEGACY_VERSION );
}
else
{
if( i != PROTOCOL_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
}
cl.servercount = MSG_ReadLong( msg );
cl.checksum = MSG_ReadLong( msg );
cl.playernum = MSG_ReadByte( msg );
cl.maxclients = MSG_ReadByte( msg );
clgame.maxEntities = MSG_ReadWord( msg );
clgame.maxEntities = bound( MIN_EDICTS, clgame.maxEntities, MAX_EDICTS );
clgame.maxModels = MSG_ReadWord( msg );
Q_strncpy( clgame.mapname, MSG_ReadString( msg ), MAX_STRING );
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING );
if( legacy )
{
clgame.maxEntities = bound( MIN_LEGACY_EDICTS, clgame.maxEntities, MAX_LEGACY_EDICTS );
clgame.maxModels = 512; // ???
}
else
{
clgame.maxEntities = bound( MIN_EDICTS, clgame.maxEntities, MAX_EDICTS );
clgame.maxModels = MSG_ReadWord( msg );
}
Q_strncpy( clgame.mapname, MSG_ReadString( msg ), sizeof( clgame.mapname ));
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
background = MSG_ReadOneBit( msg );
Q_strncpy( gamefolder, MSG_ReadString( msg ), MAX_QPATH );
Q_strncpy( gamefolder, MSG_ReadString( msg ), sizeof( gamefolder ));
host.features = (uint)MSG_ReadLong( msg );
// receive the player hulls
for( i = 0; i < MAX_MAP_HULLS * 3; i++ )
if( !legacy )
{
host.player_mins[i/3][i%3] = MSG_ReadChar( msg );
host.player_maxs[i/3][i%3] = MSG_ReadChar( msg );
// receive the player hulls
for( i = 0; i < MAX_MAP_HULLS * 3; i++ )
{
host.player_mins[i/3][i%3] = MSG_ReadChar( msg );
host.player_maxs[i/3][i%3] = MSG_ReadChar( msg );
}
}
if( clgame.maxModels > MAX_MODELS )
Con_Printf( S_WARN "server model limit is above client model limit %i > %i\n", clgame.maxModels, MAX_MODELS );
// Re-init hud video, especially if we changed game directories
clgame.dllFuncs.pfnVidInit();
if( Con_FixedFont( ))
{
// seperate the printfs so the server message can have a color
@@ -914,11 +938,7 @@ void CL_ParseServerData( sizebuf_t *msg )
// set the background state
if( cls.demoplayback && ( cls.demonum != -1 ))
{
// re-init mouse
host.mouse_visible = false;
cl.background = true;
}
else cl.background = background;
if( cl.background ) // tell the game parts about background state
@@ -965,8 +985,11 @@ void CL_ParseServerData( sizebuf_t *msg )
COM_ClearCustomizationList( &cl.players[i].customdata, true );
CL_CreateCustomizationList();
// request resources from server
CL_ServerCommand( true, "sendres %i\n", cl.servercount );
if( !legacy )
{
// request resources from server
CL_ServerCommand( true, "sendres %i\n", cl.servercount );
}
memset( &clgame.movevars, 0, sizeof( clgame.movevars ));
memset( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars ));
@@ -1141,7 +1164,7 @@ void CL_ParseClientData( sizebuf_t *msg )
CL_ParseBaseline
==================
*/
void CL_ParseBaseline( sizebuf_t *msg )
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
{
int i, newnum;
entity_state_t nullstate;
@@ -1154,8 +1177,15 @@ void CL_ParseBaseline( sizebuf_t *msg )
while( 1 )
{
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
if( newnum == LAST_EDICT ) break; // end of baselines
if( legacy )
{
newnum = MSG_ReadWord( msg );
}
else
{
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
if( newnum == LAST_EDICT ) break; // end of baselines
}
player = CL_IsPlayerIndex( newnum );
if( newnum >= clgame.maxEntities )
@@ -1166,14 +1196,22 @@ void CL_ParseBaseline( sizebuf_t *msg )
ent->index = newnum;
MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f );
if( legacy )
{
break; // only one baseline allowed in legacy protocol
}
}
cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 );
for( i = 0; i < cl.instanced_baseline_count; i++ )
if( !legacy )
{
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f );
cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 );
for( i = 0; i < cl.instanced_baseline_count; i++ )
{
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f );
}
}
}
@@ -1202,11 +1240,9 @@ CL_ParseSetAngle
set the view angle to this absolute value
================
*/
void CL_ParseSetAngle( sizebuf_t *msg )
static void CL_ParseSetAngle( sizebuf_t *msg )
{
cl.viewangles[0] = MSG_ReadBitAngle( msg, 16 );
cl.viewangles[1] = MSG_ReadBitAngle( msg, 16 );
cl.viewangles[2] = MSG_ReadBitAngle( msg, 16 );
MSG_ReadVec3Angles( msg, cl.viewangles );
}
/*
@@ -1321,7 +1357,7 @@ CL_UpdateUserinfo
collect userinfo from all players
================
*/
void CL_UpdateUserinfo( sizebuf_t *msg )
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
{
int slot, id;
qboolean active;
@@ -1332,7 +1368,8 @@ void CL_UpdateUserinfo( sizebuf_t *msg )
if( slot >= MAX_CLIENTS )
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" );
id = MSG_ReadLong( msg ); // unique user ID
if( !legacy )
id = MSG_ReadLong( msg ); // unique user ID
player = &cl.players[slot];
active = MSG_ReadOneBit( msg ) ? true : false;
@@ -1344,11 +1381,17 @@ void CL_UpdateUserinfo( sizebuf_t *msg )
player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" ));
player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" ));
player->spectator = Q_atoi( Info_ValueForKey( player->userinfo, "*hltv" ));
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
if( !legacy )
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
}
else memset( player, 0, sizeof( *player ));
else
{
COM_ClearCustomizationList( &player->customdata, true );
memset( player, 0, sizeof( *player ));
}
}
/*
@@ -1500,6 +1543,42 @@ void CL_SendConsistencyInfo( sizebuf_t *msg )
MSG_WriteOneBit( msg, 0 );
}
/*
==================
CL_StartDark
==================
*/
static void CL_StartDark( void )
{
if( Cvar_VariableValue( "v_dark" ))
{
screenfade_t *sf = &clgame.fade;
float fadetime = 5.0f;
client_textmessage_t *title;
title = CL_TextMessageGet( "GAMETITLE" );
if( Host_IsQuakeCompatible( ))
fadetime = 1.0f;
if( title )
{
// get settings from titles.txt
sf->fadeEnd = title->holdtime + title->fadeout;
sf->fadeReset = title->fadeout;
}
else sf->fadeEnd = sf->fadeReset = fadetime;
sf->fadeFlags = FFADE_IN;
sf->fader = sf->fadeg = sf->fadeb = 0;
sf->fadealpha = 255;
sf->fadeSpeed = (float)sf->fadealpha / sf->fadeReset;
sf->fadeReset += cl.time;
sf->fadeEnd += sf->fadeReset;
Cvar_SetValue( "v_dark", 0.0f );
}
}
/*
==================
CL_RegisterResources
@@ -1549,6 +1628,9 @@ void CL_RegisterResources( sizebuf_t *msg )
// tell rendering system we have a new set of models.
ref.dllFuncs.R_NewMap ();
// check if this map must start from dark screen
CL_StartDark ();
CL_SetupOverviewParams();
// release unused SpriteTextures
@@ -1566,7 +1648,7 @@ void CL_RegisterResources( sizebuf_t *msg )
// done with all resources, issue prespawn command.
// Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( msg, clc_stringcmd );
MSG_WriteString( msg, va( "spawn %i", cl.servercount ));
MSG_WriteStringf( msg, "spawn %i", cl.servercount );
}
}
else
@@ -1680,7 +1762,10 @@ CL_ParseVoiceInit
*/
void CL_ParseVoiceInit( sizebuf_t *msg )
{
// TODO: ???
char *pszCodec = MSG_ReadString( msg );
int quality = MSG_ReadByte( msg );
Voice_Init( pszCodec, quality );
}
/*
@@ -1691,7 +1776,31 @@ CL_ParseVoiceData
*/
void CL_ParseVoiceData( sizebuf_t *msg )
{
// TODO: ???
int size, idx, frames;
byte received[8192];
idx = MSG_ReadByte( msg ) + 1;
frames = MSG_ReadByte( msg );
size = MSG_ReadShort( msg );
size = Q_min( size, sizeof( received ));
MSG_ReadBytes( msg, received, size );
if ( idx <= 0 || idx > cl.maxclients )
return;
// must notify through as both local player and normal client
if( idx == cl.playernum + 1 )
Voice_StatusAck( &voice.local, VOICE_LOOPBACK_INDEX );
Voice_StatusAck( &voice.players_status[idx], idx );
if ( !size )
return;
Voice_AddIncomingData( idx, received, size, frames );
}
/*
@@ -1784,10 +1893,17 @@ Set screen shake
*/
void CL_ParseScreenShake( sizebuf_t *msg )
{
clgame.shake.amplitude = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12));
clgame.shake.duration = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12));
clgame.shake.frequency = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<8));
clgame.shake.time = cl.time + Q_max( clgame.shake.duration, 0.01f );
float amplitude = (float)(word)MSG_ReadShort( msg ) * ( 1.0f / (float)( 1 << 12 ));
float duration = (float)(word)MSG_ReadShort( msg ) * ( 1.0f / (float)( 1 << 12 ));
float frequency = (float)(word)MSG_ReadShort( msg ) * ( 1.0f / (float)( 1 << 8 ));
// don't overwrite larger existing shake
if( amplitude > clgame.shake.amplitude )
clgame.shake.amplitude = amplitude;
clgame.shake.duration = duration;
clgame.shake.time = cl.time + clgame.shake.duration;
clgame.shake.frequency = frequency;
clgame.shake.next_shake = 0.0f; // apply immediately
}
@@ -1807,7 +1923,7 @@ void CL_ParseScreenFade( sizebuf_t *msg )
duration = (float)MSG_ReadWord( msg );
holdTime = (float)MSG_ReadWord( msg );
sf->fadeFlags = MSG_ReadShort( msg );
flScale = ( sf->fadeFlags & FFADE_LONGFADE ) ? (1.0f / 256.0f) : (1.0f / 4096.0f);
flScale = FBitSet( sf->fadeFlags, FFADE_LONGFADE ) ? (1.0f / 256.0f) : (1.0f / 4096.0f);
sf->fader = MSG_ReadByte( msg );
sf->fadeg = MSG_ReadByte( msg );
@@ -1820,7 +1936,7 @@ void CL_ParseScreenFade( sizebuf_t *msg )
// calc fade speed
if( duration > 0 )
{
if( sf->fadeFlags & FFADE_OUT )
if( FBitSet( sf->fadeFlags, FFADE_OUT ))
{
if( sf->fadeEnd )
{
@@ -1828,6 +1944,7 @@ void CL_ParseScreenFade( sizebuf_t *msg )
}
sf->fadeEnd += cl.time;
sf->fadeTotalEnd = sf->fadeEnd;
sf->fadeReset += sf->fadeEnd;
}
else
@@ -1929,10 +2046,10 @@ void CL_ParseExec( sizebuf_t *msg )
{
Cbuf_AddText( "exec mapdefault.cfg\n" );
COM_FileBase( clgame.mapname, mapname );
COM_FileBase( clgame.mapname, mapname, sizeof( mapname ));
if ( COM_CheckString( mapname ) )
Cbuf_AddText( va( "exec %s.cfg\n", mapname ) );
Cbuf_AddTextf( "exec %s.cfg\n", mapname );
}
}
@@ -2172,6 +2289,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
else cls.state = ca_connecting;
cl.background = old_background;
cls.connect_time = MAX_HEARTBEAT;
cls.connect_retry = 0;
}
break;
case svc_setview:
@@ -2201,13 +2319,13 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg );
CL_ParseServerData( msg, false );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg );
CL_UpdateUserinfo( msg, false );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
@@ -2237,7 +2355,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_ParseBaseline( msg );
CL_ParseBaseline( msg, false );
break;
case svc_temp_entity:
CL_ParseTempEntity( msg );
@@ -2335,6 +2453,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
break;
case svc_voicedata:
CL_ParseVoiceData( msg );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
@@ -2373,160 +2492,6 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
}
}
/*
==================
CL_ParseBaseline
==================
*/
void CL_LegacyParseBaseline( sizebuf_t *msg )
{
int i, newnum;
qboolean player;
cl_entity_t *ent;
Delta_InitClient (); // finalize client delta's
newnum = MSG_ReadWord( msg );
player = CL_IsPlayerIndex( newnum );
if( newnum >= clgame.maxEntities )
Host_Error( "CL_AllocEdict: no free edicts\n" );
ent = CL_EDICT_NUM( newnum );
memset( &ent->prevstate, 0, sizeof( ent->prevstate ));
ent->index = newnum;
MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f );
}
/*
==================
CL_ParseServerData
==================
*/
void CL_ParseLegacyServerData( sizebuf_t *msg )
{
string gamefolder;
qboolean background;
int i;
Con_Reportf( "Legacy serverdata packet received.\n" );
cls.timestart = Sys_DoubleTime();
cls.demowaiting = false; // server is changed
//clgame.load_sequence++; // now all hud sprites are invalid
// wipe the client_t struct
if( !cls.changelevel && !cls.changedemo )
CL_ClearState ();
cls.state = ca_connected;
// parse protocol version number
i = MSG_ReadLong( msg );
//cls.serverProtocol = i;
if( i != 48 )
Host_Error( "Server uses invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
cl.servercount = MSG_ReadLong( msg );
cl.checksum = MSG_ReadLong( msg );
cl.playernum = MSG_ReadByte( msg );
cl.maxclients = MSG_ReadByte( msg );
clgame.maxEntities = MSG_ReadWord( msg );
clgame.maxEntities = bound( 30, clgame.maxEntities, 4096 );
clgame.maxModels = 512;
Q_strncpy( clgame.mapname, MSG_ReadString( msg ), MAX_STRING );
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING );
background = MSG_ReadOneBit( msg );
Q_strncpy( gamefolder, MSG_ReadString( msg ), MAX_STRING );
host.features = (uint)MSG_ReadLong( msg );
// Re-init hud video, especially if we changed game directories
clgame.dllFuncs.pfnVidInit();
if( Con_FixedFont( ))
{
// seperate the printfs so the server message can have a color
Con_Print( "\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n" );
Con_Print( va( "%c%s\n\n", 2, clgame.maptitle ));
}
// multiplayer game?
if( cl.maxclients > 1 )
{
// allow console in multiplayer games
host.allow_console = true;
// loading user settings
CSCR_LoadDefaultCVars( "user.scr" );
if( r_decals->value > mp_decals.value )
Cvar_SetValue( "r_decals", mp_decals.value );
}
else Cvar_Reset( "r_decals" );
// set the background state
if( cls.demoplayback && ( cls.demonum != -1 ))
{
// re-init mouse
host.mouse_visible = false;
cl.background = true;
}
else cl.background = background;
if( cl.background ) // tell the game parts about background state
Cvar_FullSet( "cl_background", "1", FCVAR_READ_ONLY );
else Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
if( !cls.changelevel )
{
// continue playing if we are changing level
S_StopBackgroundTrack ();
}
if( !cls.changedemo )
UI_SetActiveMenu( cl.background );
else if( !cls.demoplayback )
Key_SetKeyDest( key_menu );
// don't reset cursor in background mode
if( cl.background )
IN_MouseRestorePos();
// will be changed later
cl.viewentity = cl.playernum + 1;
gameui.globals->maxClients = cl.maxclients;
Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle ));
if( !cls.changelevel && !cls.changedemo )
CL_InitEdicts (); // re-arrange edicts
// get splash name
if( cls.demoplayback && ( cls.demonum != -1 ))
Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", cls.demoname, refState.wideScreen ? "16x9" : "4x3" ));
else Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" ));
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
if(( cl_allow_levelshots->value && !cls.changelevel ) || cl.background )
{
if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name->string ), true ))
Cvar_Set( "cl_levelshot_name", "*black" ); // render a black screen
cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime)
}
for( i = 0; i < MAX_CLIENTS; i++ )
COM_ClearCustomizationList( &cl.players[i].customdata, true );
CL_CreateCustomizationList();
memset( &clgame.movevars, 0, sizeof( clgame.movevars ));
memset( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars ));
memset( &clgame.centerPrint, 0, sizeof( clgame.centerPrint ));
cl.video_prepped = false;
cl.audio_prepped = false;
}
/*
==================
CL_ParseStaticEntity
@@ -2602,8 +2567,6 @@ void CL_LegacyParseStaticEntity( sizebuf_t *msg )
R_AddEfrags( ent ); // add link
}
void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
{
vec3_t pos;
@@ -2735,36 +2698,6 @@ void CL_LegacyPrecacheEvent( sizebuf_t *msg )
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
}
void CL_LegacyUpdateUserinfo( sizebuf_t *msg )
{
int slot, id = 0;
qboolean active;
player_info_t *player;
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
if( slot >= MAX_CLIENTS )
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" );
//id = MSG_ReadLong( msg ); // unique user ID
player = &cl.players[slot];
active = MSG_ReadOneBit( msg ) ? true : false;
if( active )
{
Q_strncpy( player->userinfo, MSG_ReadString( msg ), sizeof( player->userinfo ));
Q_strncpy( player->name, Info_ValueForKey( player->userinfo, "name" ), sizeof( player->name ));
Q_strncpy( player->model, Info_ValueForKey( player->userinfo, "model" ), sizeof( player->model ));
player->topcolor = Q_atoi( Info_ValueForKey( player->userinfo, "topcolor" ));
player->bottomcolor = Q_atoi( Info_ValueForKey( player->userinfo, "bottomcolor" ));
player->spectator = Q_atoi( Info_ValueForKey( player->userinfo, "*hltv" ));
//MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
}
else memset( player, 0, sizeof( *player ));
}
#if XASH_LOW_MEMORY == 0
#define MAX_LEGACY_RESOURCES 2048
#elif XASH_LOW_MEMORY == 2
@@ -2781,15 +2714,14 @@ CL_ParseResourceList
void CL_LegacyParseResourceList( sizebuf_t *msg )
{
int i = 0;
static struct
{
int rescount;
int restype[MAX_LEGACY_RESOURCES];
char resnames[MAX_LEGACY_RESOURCES][MAX_QPATH];
} reslist;
memset( &reslist, 0, sizeof( reslist ));
memset( &reslist, 0, sizeof( reslist ));
reslist.rescount = MSG_ReadWord( msg ) - 1;
if( reslist.rescount > MAX_LEGACY_RESOURCES )
@@ -2806,14 +2738,21 @@ void CL_LegacyParseResourceList( sizebuf_t *msg )
return;
}
HTTP_ResetProcessState();
host.downloadcount = 0;
for( i = 0; i < reslist.rescount; i++ )
{
char soundpath[MAX_VA_STRING];
const char *path;
if( reslist.restype[i] == t_sound )
path = va( DEFAULT_SOUNDPATH "%s", reslist.resnames[i] );
{
Q_snprintf( soundpath, sizeof( soundpath ), DEFAULT_SOUNDPATH "%s", reslist.resnames[i] );
path = soundpath;
}
else path = reslist.resnames[i];
if( FS_FileExists( path, false ))
@@ -2932,6 +2871,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
else cls.state = ca_connecting;
cl.background = old_background;
cls.connect_time = MAX_HEARTBEAT;
cls.connect_retry = 0;
}
break;
case svc_setview:
@@ -2968,13 +2908,13 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseLegacyServerData( msg );
CL_ParseServerData( msg, true );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg );
break;
case svc_updateuserinfo:
CL_LegacyUpdateUserinfo( msg );
CL_UpdateUserinfo( msg, true );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
@@ -2997,14 +2937,14 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnstatic:
CL_ParseStaticEntity( msg );
CL_LegacyParseStaticEntity( msg );
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_LegacyParseBaseline( msg );
CL_ParseBaseline( msg, true );
break;
case svc_temp_entity:
CL_ParseTempEntity( msg );
@@ -3024,7 +2964,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
break;
case svc_legacy_modelindex:
CL_LegacyPrecacheModel( msg );
break;
case svc_legacy_soundindex:
CL_LegacyPrecacheSound( msg );
@@ -3040,7 +2979,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
CL_ParseRestore( msg );
break;
case svc_legacy_eventindex:
//CL_ParseFinaleCutscene( msg, 3 );
CL_LegacyPrecacheEvent(msg);
break;
case svc_weaponanim:
@@ -3117,12 +3055,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_director:
CL_ParseDirector( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
@@ -3202,7 +3134,7 @@ void CL_LegacyPrecache_f( void )
// done with all resources, issue prespawn command.
// Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteString( &cls.netchan.message, va( "begin %i", spawncount ));
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS;
}

View File

@@ -26,20 +26,6 @@ GNU General Public License for more details.
#define MIN_PREDICTION_EPSILON 0.5f // complain if error is > this and we have cl_showerror set
#define MAX_PREDICTION_ERROR 64.0f // above this is assumed to be a teleport, don't smooth, etc.
/*
=============
CL_ClearPhysEnts
=============
*/
void CL_ClearPhysEnts( void )
{
clgame.pmove->numtouch = 0;
clgame.pmove->numvisent = 0;
clgame.pmove->nummoveent = 0;
clgame.pmove->numphysent = 0;
}
/*
=============
CL_PushPMStates
@@ -208,7 +194,7 @@ check for instant movement in case
we don't want interpolate this
==================
*/
qboolean CL_PlayerTeleported( local_state_t *from, local_state_t *to )
static qboolean CL_PlayerTeleported( local_state_t *from, local_state_t *to )
{
int len, maxlen;
vec3_t delta;
@@ -713,33 +699,7 @@ static int GAME_EXPORT pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
static void GAME_EXPORT pfnStuckTouch( int hitent, pmtrace_t *tr )
{
int i;
for( i = 0; i < clgame.pmove->numtouch; i++ )
{
if( clgame.pmove->touchindex[i].ent == hitent )
return;
}
if( clgame.pmove->numtouch >= MAX_PHYSENTS )
return;
VectorCopy( clgame.pmove->velocity, tr->deltavelocity );
tr->ent = hitent;
clgame.pmove->touchindex[clgame.pmove->numtouch++] = *tr;
}
static int GAME_EXPORT pfnPointContents( float *p, int *truecontents )
{
int cont, truecont;
truecont = cont = PM_PointContents( clgame.pmove, p );
if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
cont = CONTENTS_WATER;
return cont;
PM_StuckTouch( clgame.pmove, hitent, tr );
}
static int GAME_EXPORT pfnTruePointContents( float *p )
@@ -747,99 +707,19 @@ static int GAME_EXPORT pfnTruePointContents( float *p )
return PM_TruePointContents( clgame.pmove, p );
}
static int GAME_EXPORT pfnHullPointContents( struct hull_s *hull, int num, float *p )
{
return PM_HullPointContents( hull, num, p );
}
static pmtrace_t GAME_EXPORT pfnPlayerTrace( float *start, float *end, int traceFlags, int ignore_pe )
{
return PM_PlayerTraceExt( clgame.pmove, start, end, traceFlags, clgame.pmove->numphysent, clgame.pmove->physents, ignore_pe, NULL );
}
pmtrace_t *PM_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe )
{
static pmtrace_t tr;
int old_usehull;
old_usehull = clgame.pmove->usehull;
clgame.pmove->usehull = usehull;
switch( flags )
{
case PM_TRACELINE_PHYSENTSONLY:
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numphysent, clgame.pmove->physents, ignore_pe, NULL );
break;
case PM_TRACELINE_ANYVISIBLE:
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numvisent, clgame.pmove->visents, ignore_pe, NULL );
break;
}
clgame.pmove->usehull = old_usehull;
return &tr;
}
static hull_t *pfnHullForBsp( physent_t *pe, float *offset )
static void *pfnHullForBsp( physent_t *pe, float *offset )
{
return PM_HullForBsp( pe, clgame.pmove, offset );
}
static float GAME_EXPORT pfnTraceModel( physent_t *pe, float *start, float *end, trace_t *trace )
{
int old_usehull;
vec3_t start_l, end_l;
vec3_t offset, temp;
qboolean rotated;
matrix4x4 matrix;
hull_t *hull;
old_usehull = clgame.pmove->usehull;
clgame.pmove->usehull = 2;
hull = PM_HullForBsp( pe, clgame.pmove, offset );
clgame.pmove->usehull = old_usehull;
if( pe->solid == SOLID_BSP && !VectorIsNull( pe->angles ))
rotated = true;
else rotated = false;
if( rotated )
{
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
Matrix4x4_VectorITransform( matrix, start, start_l );
Matrix4x4_VectorITransform( matrix, end, end_l );
}
else
{
VectorSubtract( start, offset, start_l );
VectorSubtract( end, offset, end_l );
}
PM_RecursiveHullCheck( hull, hull->firstclipnode, 0, 1, start_l, end_l, (pmtrace_t *)trace );
trace->ent = NULL;
if( rotated )
{
VectorCopy( trace->plane.normal, temp );
Matrix4x4_TransformPositivePlane( matrix, temp, trace->plane.dist, trace->plane.normal, &trace->plane.dist );
}
VectorLerp( start, trace->fraction, end, trace->endpos );
return trace->fraction;
}
static const char *pfnTraceTexture( int ground, float *vstart, float *vend )
{
physent_t *pe;
if( ground < 0 || ground >= clgame.pmove->numphysent )
return NULL; // bad ground
pe = &clgame.pmove->physents[ground];
return PM_TraceTexture( pe, vstart, vend );
return PM_TraceModel( clgame.pmove, pe, start, end, trace );
}
static void GAME_EXPORT pfnPlaySound( int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch )
@@ -868,25 +748,7 @@ static int GAME_EXPORT pfnTestPlayerPositionEx( float *pos, pmtrace_t *ptrace, p
static pmtrace_t *pfnTraceLineEx( float *start, float *end, int flags, int usehull, pfnIgnore pmFilter )
{
static pmtrace_t tr;
int old_usehull;
old_usehull = clgame.pmove->usehull;
clgame.pmove->usehull = usehull;
switch( flags )
{
case PM_TRACELINE_PHYSENTSONLY:
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numphysent, clgame.pmove->physents, -1, pmFilter );
break;
case PM_TRACELINE_ANYVISIBLE:
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numvisent, clgame.pmove->visents, -1, pmFilter );
break;
}
clgame.pmove->usehull = old_usehull;
return &tr;
return PM_TraceLineEx( clgame.pmove, start, end, flags, usehull, pmFilter );
}
/*
@@ -926,23 +788,23 @@ void CL_InitClientMove( void )
clgame.pmove->Con_Printf = Con_Printf;
clgame.pmove->Sys_FloatTime = Sys_DoubleTime;
clgame.pmove->PM_StuckTouch = pfnStuckTouch;
clgame.pmove->PM_PointContents = pfnPointContents;
clgame.pmove->PM_PointContents = (void*)PM_CL_PointContents;
clgame.pmove->PM_TruePointContents = pfnTruePointContents;
clgame.pmove->PM_HullPointContents = pfnHullPointContents;
clgame.pmove->PM_HullPointContents = (void*)PM_HullPointContents;
clgame.pmove->PM_PlayerTrace = pfnPlayerTrace;
clgame.pmove->PM_TraceLine = PM_TraceLine;
clgame.pmove->PM_TraceLine = PM_CL_TraceLine;
clgame.pmove->RandomLong = COM_RandomLong;
clgame.pmove->RandomFloat = COM_RandomFloat;
clgame.pmove->PM_GetModelType = pfnGetModelType;
clgame.pmove->PM_GetModelBounds = pfnGetModelBounds;
clgame.pmove->PM_HullForBsp = (void*)pfnHullForBsp;
clgame.pmove->PM_HullForBsp = pfnHullForBsp;
clgame.pmove->PM_TraceModel = pfnTraceModel;
clgame.pmove->COM_FileSize = COM_FileSize;
clgame.pmove->COM_LoadFile = COM_LoadFile;
clgame.pmove->COM_FreeFile = COM_FreeFile;
clgame.pmove->memfgets = COM_MemFgets;
clgame.pmove->PM_PlaySound = pfnPlaySound;
clgame.pmove->PM_TraceTexture = pfnTraceTexture;
clgame.pmove->PM_TraceTexture = PM_CL_TraceTexture;
clgame.pmove->PM_PlaybackEventFull = pfnPlaybackEventFull;
clgame.pmove->PM_PlayerTraceEx = pfnPlayerTraceEx;
clgame.pmove->PM_TestPlayerPositionEx = pfnTestPlayerPositionEx;
@@ -953,21 +815,10 @@ void CL_InitClientMove( void )
clgame.dllFuncs.pfnPlayerMoveInit( clgame.pmove );
}
static void PM_CheckMovingGround( clientdata_t *cd, entity_state_t *state, float frametime )
static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const usercmd_t *ucmd, qboolean runfuncs, double time )
{
if(!( cd->flags & FL_BASEVELOCITY ))
{
// apply momentum (add in half of the previous frame of velocity first)
VectorMA( cd->velocity, 1.0f + (frametime * 0.5f), state->basevelocity, cd->velocity );
VectorClear( state->basevelocity );
}
cd->flags &= ~FL_BASEVELOCITY;
}
void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time )
{
entity_state_t *ps;
clientdata_t *cd;
const entity_state_t *ps;
const clientdata_t *cd;
ps = &from->playerstate;
cd = &from->client;
@@ -984,13 +835,13 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
VectorCopy( ps->basevelocity, pmove->basevelocity );
VectorCopy( cd->view_ofs, pmove->view_ofs );
VectorClear( pmove->movedir );
pmove->flDuckTime = cd->flDuckTime;
pmove->flDuckTime = (float)cd->flDuckTime;
pmove->bInDuck = cd->bInDuck;
pmove->usehull = ps->usehull;
pmove->flTimeStepSound = cd->flTimeStepSound;
pmove->iStepLeft = ps->iStepLeft;
pmove->flFallVelocity = ps->flFallVelocity;
pmove->flSwimTime = cd->flSwimTime;
pmove->flSwimTime = (float)cd->flSwimTime;
VectorCopy( cd->punchangle, pmove->punchangle );
pmove->flNextPrimaryAttack = 0.0f; // not used by PM_ code
pmove->effects = ps->effects;
@@ -998,7 +849,7 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
pmove->gravity = ps->gravity;
pmove->friction = ps->friction;
pmove->oldbuttons = ps->oldbuttons;
pmove->waterjumptime = cd->waterjumptime;
pmove->waterjumptime = (float)cd->waterjumptime;
pmove->dead = (cl.local.health <= 0);
pmove->deadflag = cd->deadflag;
pmove->spectator = (cls.spectator != 0);
@@ -1025,7 +876,7 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
Q_strncpy( pmove->physinfo, cls.physinfo, MAX_INFO_STRING );
}
void CL_FinishPMove( playermove_t *pmove, local_state_t *to )
const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )
{
entity_state_t *ps;
clientdata_t *cd;
@@ -1036,7 +887,7 @@ void CL_FinishPMove( playermove_t *pmove, local_state_t *to )
cd->flags = pmove->flags;
cd->bInDuck = pmove->bInDuck;
cd->flTimeStepSound = pmove->flTimeStepSound;
cd->flDuckTime = pmove->flDuckTime;
cd->flDuckTime = (int)pmove->flDuckTime;
cd->flSwimTime = (int)pmove->flSwimTime;
cd->waterjumptime = (int)pmove->waterjumptime;
cd->watertype = pmove->watertype;
@@ -1049,7 +900,7 @@ void CL_FinishPMove( playermove_t *pmove, local_state_t *to )
VectorCopy( pmove->angles, ps->angles );
VectorCopy( pmove->basevelocity, ps->basevelocity );
VectorCopy( pmove->punchangle, cd->punchangle );
ps->oldbuttons = pmove->cmd.buttons;
ps->oldbuttons = (uint)pmove->cmd.buttons;
ps->friction = pmove->friction;
ps->movetype = pmove->movetype;
ps->onground = pmove->onground;
@@ -1157,13 +1008,9 @@ void CL_PredictMovement( qboolean repredicting )
{
runcmd_t *to_cmd = NULL, *from_cmd;
local_state_t *from = NULL, *to = NULL;
uint current_command;
uint current_command_mod;
frame_t *frame = NULL;
frame_t *frame = NULL;
uint i, stoppoint;
qboolean runfuncs;
double f = 1.0;
cl_entity_t *ent;
double time;
if( cls.state != ca_active || cls.spectator )
@@ -1174,7 +1021,7 @@ void CL_PredictMovement( qboolean repredicting )
CL_SetUpPlayerPrediction( false, false );
if( cls.state != ca_active || !cl.validsequence )
if( !cl.validsequence )
return;
if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK )
@@ -1215,6 +1062,10 @@ void CL_PredictMovement( qboolean repredicting )
for( i = 1; i < CL_UPDATE_MASK && cls.netchan.incoming_acknowledged + i < cls.netchan.outgoing_sequence + stoppoint; i++ )
{
uint current_command;
uint current_command_mod;
qboolean runfuncs;
current_command = cls.netchan.incoming_acknowledged + i;
current_command_mod = current_command & CL_UPDATE_MASK;
@@ -1291,7 +1142,7 @@ void CL_PredictMovement( qboolean repredicting )
if( FBitSet( to->client.flags, FL_ONGROUND ))
{
ent = CL_GetEntityByIndex( cl.local.lastground );
cl_entity_t *ent = CL_GetEntityByIndex( cl.local.lastground );
cl.local.onground = cl.local.lastground;
cl.local.moving = false;
@@ -1313,13 +1164,13 @@ void CL_PredictMovement( qboolean repredicting )
else
{
cl.local.onground = -1;
cl.local.moving = 0;
cl.local.moving = false;
}
if( cls.correction_time > 0 && !cl_nosmooth->value && cl_smoothtime->value )
{
vec3_t delta;
float frac;
vec3_t delta;
float frac;
// only decay timer once per frame
if( !repredicting )

View File

@@ -237,10 +237,6 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
}
else Cvar_Reset( "r_decals" );
// re-init mouse
if( cl.background )
host.mouse_visible = false;
if( cl.background ) // tell the game parts about background state
Cvar_FullSet( "cl_background", "1", FCVAR_READ_ONLY );
else Cvar_FullSet( "cl_background", "0", FCVAR_READ_ONLY );
@@ -864,7 +860,7 @@ void CL_QuakeExecStuff( void )
if( !*text ) break;
text = _COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL );
text = COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL, NULL );
if( !text ) break;

View File

@@ -157,7 +157,7 @@ void CL_UpdateStudioTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, in
// build name of original texture
Q_strncpy( mdlname, entity->model->name, sizeof( mdlname ));
COM_FileBase( ptexture->name, name );
COM_FileBase( ptexture->name, name, sizeof( name ));
COM_StripExtension( mdlname );
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );

View File

@@ -133,7 +133,7 @@ const char *CL_GenericHandle( int fileindex )
return cl.files_precache[fileindex];
}
int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
{
switch( parm )
{
@@ -161,9 +161,9 @@ int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
case PARM_WATER_ALPHA:
return FBitSet( world.flags, FWORLD_WATERALPHA );
case PARM_DELUXEDATA:
return *(int *)&world.deluxedata;
return (intptr_t)world.deluxedata;
case PARM_SHADOWDATA:
return *(int *)&world.shadowdata;
return (intptr_t)world.shadowdata;
default:
// indicates call from client.dll
if( checkRef )
@@ -204,7 +204,7 @@ int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
return 0;
}
static int pfnRenderGetParm( int parm, int arg )
static intptr_t pfnRenderGetParm( int parm, int arg )
{
return CL_RenderGetParm( parm, arg, true );
}

View File

@@ -150,8 +150,7 @@ same as r_speeds but for network channel
void SCR_NetSpeeds( void )
{
static char msg[MAX_SYSPATH];
int x, y, height;
char *p, *start, *end;
int x, y;
float time = cl.mtime[0];
static int min_svfps = 100;
static int max_svfps = 0;
@@ -160,6 +159,7 @@ void SCR_NetSpeeds( void )
static int max_clfps = 0;
int cur_clfps = 0;
rgba_t color;
cl_font_t *font = Con_GetCurFont();
if( !host.allow_console )
return;
@@ -196,25 +196,11 @@ void SCR_NetSpeeds( void )
Q_memprint( cls.netchan.total_sended )
);
x = refState.width - 320;
x = refState.width - 320 * font->scale;
y = 384;
Con_DrawStringLen( NULL, NULL, &height );
MakeRGBA( color, 255, 255, 255, 255 );
p = start = msg;
do
{
end = Q_strchr( p, '\n' );
if( end ) msg[end-start] = '\0';
Con_DrawString( x, y, p, color );
y += height;
if( end ) p = end + 1;
else break;
} while( 1 );
CL_DrawString( x, y, msg, color, font, FONT_DRAW_RESETCOLORONLF );
}
/*
@@ -231,31 +217,15 @@ void SCR_RSpeeds( void )
if( ref.dllFuncs.R_SpeedsMessage( msg, sizeof( msg )))
{
int x, y, height;
char *p, *start, *end;
int x, y;
rgba_t color;
cl_font_t *font = Con_GetCurFont();
x = refState.width - 340;
x = refState.width - 340 * font->scale;
y = 64;
Con_DrawStringLen( NULL, NULL, &height );
MakeRGBA( color, 255, 255, 255, 255 );
p = start = msg;
do
{
end = Q_strchr( p, '\n' );
if( end ) msg[end-start] = '\0';
Con_DrawString( x, y, p, color );
y += height;
// handle '\n\n'
if( *p == '\n' )
y += height;
if( end ) p = end + 1;
else break;
} while( 1 );
CL_DrawString( x, y, msg, color, font, FONT_DRAW_RESETCOLORONLF );
}
}
@@ -418,7 +388,6 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
cls.draw_changelevel = !is_background;
SCR_UpdateScreen();
cls.disable_screen = host.realtime;
cls.disable_servercount = cl.servercount;
cl.background = is_background; // set right state before svc_serverdata is came
if( !Host_IsDedicated() )
@@ -578,77 +547,6 @@ void SCR_UpdateScreen( void )
V_PostRender();
}
qboolean SCR_LoadFixedWidthFont( const char *fontname )
{
int i, fontWidth;
if( cls.creditsFont.valid )
return true; // already loaded
if( !FS_FileExists( fontname, false ))
return false;
cls.creditsFont.hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_IMAGE|TF_KEEP_SOURCE );
R_GetTextureParms( &fontWidth, NULL, cls.creditsFont.hFontTexture );
cls.creditsFont.charHeight = clgame.scrInfo.iCharHeight = fontWidth / 16;
cls.creditsFont.type = FONT_FIXED;
cls.creditsFont.valid = true;
// build fixed rectangles
for( i = 0; i < 256; i++ )
{
cls.creditsFont.fontRc[i].left = (i * (fontWidth / 16)) % fontWidth;
cls.creditsFont.fontRc[i].right = cls.creditsFont.fontRc[i].left + fontWidth / 16;
cls.creditsFont.fontRc[i].top = (i / 16) * (fontWidth / 16);
cls.creditsFont.fontRc[i].bottom = cls.creditsFont.fontRc[i].top + fontWidth / 16;
cls.creditsFont.charWidths[i] = clgame.scrInfo.charWidths[i] = fontWidth / 16;
}
return true;
}
qboolean SCR_LoadVariableWidthFont( const char *fontname )
{
int i, fontWidth;
byte *buffer;
fs_offset_t length;
qfont_t *src;
if( cls.creditsFont.valid )
return true; // already loaded
if( !FS_FileExists( fontname, false ))
return false;
cls.creditsFont.hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_IMAGE );
R_GetTextureParms( &fontWidth, NULL, cls.creditsFont.hFontTexture );
// half-life font with variable chars witdh
buffer = FS_LoadFile( fontname, &length, false );
// setup creditsfont
if( buffer && length >= sizeof( qfont_t ))
{
src = (qfont_t *)buffer;
cls.creditsFont.charHeight = clgame.scrInfo.iCharHeight = src->rowheight;
cls.creditsFont.type = FONT_VARIABLE;
// build rectangles
for( i = 0; i < 256; i++ )
{
cls.creditsFont.fontRc[i].left = (word)src->fontinfo[i].startoffset % fontWidth;
cls.creditsFont.fontRc[i].right = cls.creditsFont.fontRc[i].left + src->fontinfo[i].charwidth;
cls.creditsFont.fontRc[i].top = (word)src->fontinfo[i].startoffset / fontWidth;
cls.creditsFont.fontRc[i].bottom = cls.creditsFont.fontRc[i].top + src->rowheight;
cls.creditsFont.charWidths[i] = clgame.scrInfo.charWidths[i] = src->fontinfo[i].charwidth;
}
cls.creditsFont.valid = true;
}
if( buffer ) Mem_Free( buffer );
return true;
}
/*
================
SCR_LoadCreditsFont
@@ -658,22 +556,41 @@ INTERNAL RESOURCE
*/
void SCR_LoadCreditsFont( void )
{
const char *path = "gfx/creditsfont.fnt";
dword crc;
cl_font_t *const font = &cls.creditsFont;
qboolean success = false;
float scale = hud_fontscale->value;
dword crc = 0;
// replace default gfx.wad textures by current charset's font
if( !CRC32_File( &crc, "gfx.wad" ) || crc == 0x49eb9f16 )
{
const char *path2 = va("creditsfont_%s.fnt", Cvar_VariableString( "con_charset" ) );
if( FS_FileExists( path2, false ) )
path = path2;
string charsetFnt;
if( Q_snprintf( charsetFnt, sizeof( charsetFnt ),
"creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 )
{
if( FS_FileExists( charsetFnt, false ))
success = Con_LoadVariableWidthFont( charsetFnt, font, scale, kRenderTransAdd, TF_FONT );
}
}
if( !SCR_LoadVariableWidthFont( path ))
if( !success )
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, kRenderTransAdd, TF_FONT );
if( !success )
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransAdd, TF_FONT );
// copy font size for client.dll
if( success )
{
if( !SCR_LoadFixedWidthFont( "gfx/conchars" ))
Con_DPrintf( S_ERROR "failed to load HUD font\n" );
int i;
clgame.scrInfo.iCharHeight = cls.creditsFont.charHeight;
for( i = 0; i < ARRAYSIZE( cls.creditsFont.charWidths ); i++ )
clgame.scrInfo.charWidths[i] = cls.creditsFont.charWidths[i];
}
else Con_DPrintf( S_ERROR "failed to load HUD font\n" );
}
/*
@@ -781,7 +698,6 @@ SCR_VidInit
*/
void SCR_VidInit( void )
{
string libpath;
if( !ref.initialized ) // don't call VidInit too soon
return;
@@ -796,8 +712,13 @@ void SCR_VidInit( void )
gameui.globals->scrHeight = refState.height;
}
COM_GetCommonLibraryPath( LIBRARY_CLIENT, libpath, sizeof( libpath ));
VGui_Startup( libpath, refState.width, refState.height );
// notify vgui about screen size change
if( clgame.hInstance )
{
// do not pass client pointer, we do not want to
// re-initialize vgui2
VGui_Startup( NULL, refState.width, refState.height );
}
CL_ClearSpriteTextures(); // now all hud sprites are invalid
@@ -828,7 +749,7 @@ void SCR_Init( void )
v_dark = Cvar_Get( "v_dark", "0", 0, "starts level from dark screen" );
scr_viewsize = Cvar_Get( "viewsize", "120", FCVAR_ARCHIVE, "screen size" );
net_speeds = Cvar_Get( "net_speeds", "0", FCVAR_ARCHIVE, "show network packets" );
cl_showfps = Cvar_Get( "cl_showfps", "1", FCVAR_ARCHIVE, "show client fps" );
cl_showfps = Cvar_Get( "cl_showfps", "0", FCVAR_ARCHIVE, "show client fps" );
cl_showpos = Cvar_Get( "cl_showpos", "0", FCVAR_ARCHIVE, "show local player position and velocity" );
// register our commands

View File

@@ -405,12 +405,15 @@ static cldll_func_dst_t cldllFuncDst =
void CL_GetSecuredClientAPI( CL_EXPORT_FUNCS F )
{
cldll_func_src_t cldllFuncSrc = { 0 };
modfuncs_t modFuncs = { 0 };
// secured client dlls need these
*(cldll_func_dst_t **)&cldllFuncSrc.pfnVidInit = &cldllFuncDst;
*(modfuncs_t **)&cldllFuncSrc.pfnInitialize = &modFuncs;
cldll_func_src_t cldllFuncSrc =
{
(void *)&modFuncs,
NULL,
(void *)&cldllFuncDst
};
// trying to fill interface now
F( &cldllFuncSrc );

View File

@@ -1037,7 +1037,7 @@ void GAME_EXPORT R_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t
vecSpot[1] = pos[1] + COM_RandomFloat( -0.5f, 0.5f ) * size[1];
vecSpot[2] = pos[2] + COM_RandomFloat( -0.5f, 0.5f ) * size[2];
if( CL_PointContents( vecSpot ) != CONTENTS_SOLID )
if( PM_CL_PointContents( vecSpot, NULL ) != CONTENTS_SOLID )
break; // valid spot
}
@@ -1245,37 +1245,28 @@ apply params for exploding sprite
*/
void GAME_EXPORT R_Sprite_Explode( TEMPENTITY *pTemp, float scale, int flags )
{
if( !pTemp ) return;
qboolean noadditive, drawalpha, rotate;
if( FBitSet( flags, TE_EXPLFLAG_NOADDITIVE ))
{
// solid sprite
pTemp->entity.curstate.rendermode = kRenderNormal;
pTemp->entity.curstate.renderamt = 255;
}
else if( FBitSet( flags, TE_EXPLFLAG_DRAWALPHA ))
{
// alpha sprite (came from hl2)
pTemp->entity.curstate.rendermode = kRenderTransAlpha;
pTemp->entity.curstate.renderamt = 180;
}
else
{
// additive sprite
pTemp->entity.curstate.rendermode = kRenderTransAdd;
pTemp->entity.curstate.renderamt = 180;
}
if( !pTemp )
return;
if( FBitSet( flags, TE_EXPLFLAG_ROTATE ))
{
// came from hl2
pTemp->entity.angles[2] = COM_RandomLong( 0, 360 );
}
noadditive = FBitSet( flags, TE_EXPLFLAG_NOADDITIVE );
drawalpha = FBitSet( flags, TE_EXPLFLAG_DRAWALPHA );
rotate = FBitSet( flags, TE_EXPLFLAG_ROTATE );
pTemp->entity.curstate.renderfx = kRenderFxNone;
pTemp->entity.baseline.origin[2] = 8;
pTemp->entity.origin[2] += 10;
pTemp->entity.curstate.scale = scale;
pTemp->entity.baseline.origin[2] = 8.0f;
pTemp->entity.origin[2] = pTemp->entity.origin[2] + 10.0f;
if( rotate )
pTemp->entity.angles[2] = COM_RandomFloat( 0.0, 360.0f );
pTemp->entity.curstate.rendermode = noadditive ? kRenderNormal :
drawalpha ? kRenderTransAlpha : kRenderTransAdd;
pTemp->entity.curstate.renderamt = noadditive ? 0xff : 0xb4;
pTemp->entity.curstate.renderfx = 0;
pTemp->entity.curstate.rendercolor.r = 0;
pTemp->entity.curstate.rendercolor.g = 0;
pTemp->entity.curstate.rendercolor.b = 0;
}
/*
@@ -1904,7 +1895,7 @@ handle temp-entity messages
void CL_ParseTempEntity( sizebuf_t *msg )
{
sizebuf_t buf;
byte pbuf[256];
byte pbuf[2048];
int iSize;
int type, color, count, flags;
int decalIndex, modelIndex, entityIndex;
@@ -1923,6 +1914,10 @@ void CL_ParseTempEntity( sizebuf_t *msg )
decalIndex = modelIndex = entityIndex = 0;
// this will probably be fatal anyway
if( iSize > sizeof( pbuf ))
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __FUNCTION__ );
// parse user message into buffer
MSG_ReadBytes( msg, pbuf, iSize );
@@ -1970,6 +1965,9 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
R_BlobExplosion( pos );
hSound = S_RegisterSound( cl_explode_sounds[0] );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
break;
case TE_SMOKE:
pos[0] = MSG_ReadCoord( &buf );
@@ -2023,7 +2021,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
dl->decay = 300;
hSound = S_RegisterSound( cl_explode_sounds[0] );
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
break;
case TE_BSPDECAL:
case TE_DECAL:
@@ -2921,7 +2919,15 @@ void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos
{
if( !pCust->nUserData1 )
{
const char *decalname = va( "player%dlogo%d", playernum, customIndex );
int sprayTextureIndex;
char decalname[MAX_VA_STRING];
Q_snprintf( decalname, sizeof( decalname ), "player%dlogo%d", playernum, customIndex );
sprayTextureIndex = ref.dllFuncs.GL_FindTexture( decalname );
if( sprayTextureIndex != 0 )
{
ref.dllFuncs.GL_FreeTexture( sprayTextureIndex );
}
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );
}
textureIndex = pCust->nUserData1;

View File

@@ -209,7 +209,7 @@ qboolean SCR_PlayCinematic( const char *arg )
if( FS_FileExists( arg, false ) && !fullpath )
{
Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", path );
Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", arg );
return false;
}

View File

@@ -229,6 +229,53 @@ void V_RefApplyOverview( ref_viewpass_t *rvp )
ref.dllFuncs.GL_OrthoBounds( mins, maxs );
}
/*
====================
V_CalcFov
====================
*/
static float V_CalcFov( float *fov_x, float width, float height )
{
float x, half_fov_y;
if( *fov_x < 1.0f || *fov_x > 179.0f )
*fov_x = 90.0f; // default value
x = width / tan( DEG2RAD( *fov_x ) * 0.5f );
half_fov_y = atan( height / x );
return RAD2DEG( half_fov_y ) * 2;
}
/*
====================
V_AdjustFov
====================
*/
static void V_AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x )
{
float x, y;
if( width * 3 == 4 * height || width * 4 == height * 5 )
{
// 4:3 or 5:4 ratio
return;
}
if( lock_x )
{
*fov_y = 2 * atan((width * 3) / (height * 4) * tan( *fov_y * M_PI_F / 360.0f * 0.5f )) * 360 / M_PI_F;
return;
}
y = V_CalcFov( fov_x, 640, 480 );
x = *fov_x;
*fov_x = V_CalcFov( &y, height, width );
if( *fov_x < x ) *fov_x = x;
else *fov_y = y;
}
/*
=============
V_GetRefParams
@@ -286,9 +333,6 @@ qboolean V_PreRender( void )
if( !ref.initialized )
return false;
if( host.status == HOST_NOFOCUS )
return false;
if( host.status == HOST_SLEEP )
return false;

View File

@@ -33,6 +33,7 @@ GNU General Public License for more details.
#include "net_api.h"
#include "world.h"
#include "ref_common.h"
#include "voice.h"
// client sprite types
#define SPR_CLIENT 0 // client sprite for temp-entities or user-textures
@@ -107,7 +108,6 @@ extern int CL_UPDATE_BACKUP;
#define MIN_UPDATERATE 10.0f
#define MAX_UPDATERATE 102.0f
#define MIN_EX_INTERP 0.005f
#define MAX_EX_INTERP 0.1f
#define CL_MIN_RESEND_TIME 1.5f // mininum time gap (in seconds) before a subsequent connection request is sent.
@@ -138,7 +138,7 @@ typedef struct
int light_level;
int waterlevel;
int usehull;
int moving;
qboolean moving;
int pushmsec;
int weapons;
float maxspeed;
@@ -210,7 +210,7 @@ typedef struct
// a lerp point for other data
double oldtime; // previous cl.time, time-oldtime is used
// to decay light values and smooth step ups
float timedelta; // floating delta between two updates
double timedelta; // floating delta between two updates
char serverinfo[MAX_SERVERINFO_STRING];
player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself
@@ -318,32 +318,46 @@ typedef struct
pfnEventHook func; // user-defined function
} cl_user_event_t;
#define FONT_FIXED 0
#define FONT_VARIABLE 1
#define FONT_FIXED 0
#define FONT_VARIABLE 1
#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_FORCECOL BIT( 2 ) // ignore colorcodes
#define FONT_DRAW_NORENDERMODE BIT( 3 ) // ignore font's default rendermode
#define FONT_DRAW_NOLF BIT( 4 ) // ignore \n
#define FONT_DRAW_RESETCOLORONLF BIT( 5 ) // yet another flag to simulate consecutive Con_DrawString calls...
typedef struct
{
int hFontTexture; // handle to texture
wrect_t fontRc[256]; // rectangles
byte charWidths[256];
int charHeight;
int type;
qboolean valid; // all rectangles are valid
int hFontTexture; // handle to texture
wrect_t fontRc[256]; // tex coords
float scale; // scale factor
byte charWidths[256]; // scaled widths
int charHeight; // scaled height
int type; // fixed width font or variable
int rendermode; // default rendermode
qboolean nearest; // nearest filtering enabled
qboolean valid; // all rectangles are valid
} cl_font_t;
typedef struct scissor_state_s
{
int x;
int y;
int width;
int height;
qboolean test;
} scissor_state_t;
typedef struct
{
// scissor test
scissor_state_t scissor;
// temp handle
const model_t *pSprite; // pointer to current SpriteTexture
// scissor test
int scissor_x;
int scissor_y;
int scissor_width;
int scissor_height;
qboolean scissor_test;
qboolean adjust_size; // allow to adjust scale for fonts
int renderMode; // override kRenderMode from TriAPI
TRICULLSTYLE cullMode; // override CULL FACE from TriAPI
@@ -370,14 +384,10 @@ typedef struct cl_predicted_player_s
typedef struct
{
int gl_texturenum; // this is a real texnum
// scissor test
int scissor_x;
int scissor_y;
int scissor_width;
int scissor_height;
qboolean scissor_test;
scissor_state_t scissor;
int gl_texturenum; // this is a real texnum
// holds text color
rgba_t textColor;
@@ -465,7 +475,7 @@ typedef struct
string cdtracks[MAX_CDTRACKS]; // 32 cd-tracks read from cdaudio.txt
model_t sprites[MAX_CLIENT_SPRITES]; // client spritetextures
model_t sprites[MAX_CLIENT_SPRITES]; // hud&client spritetexturesz
int viewport[4]; // viewport sizes
client_draw_t ds; // draw2d stuff (hud, weaponmenu etc)
@@ -527,9 +537,6 @@ typedef struct
float disable_screen; // showing loading plaque between levels
// or changing rendering dlls
// if time gets > 30 seconds ahead, break it
int disable_servercount; // when we receive a frame and cl.servercount
// > cls.disable_servercount, clear disable_screen
qboolean draw_changelevel; // draw changelevel image 'Loading...'
keydest_t key_dest;
@@ -674,6 +681,7 @@ extern convar_t *cl_levelshot_name;
extern convar_t *cl_draw_beams;
extern convar_t *cl_clockreset;
extern convar_t *cl_fixtimerate;
extern convar_t *hud_fontscale;
extern convar_t *hud_scale;
extern convar_t *gl_showtextures;
extern convar_t *cl_bmodelinterp;
@@ -705,7 +713,7 @@ dlight_t *CL_GetEntityLight( int number );
//
// cl_cmds.c
//
void CL_Quit_f( void ) NORETURN;
void CL_Quit_f( void );
void CL_ScreenShot_f( void );
void CL_SnapShot_f( void );
void CL_PlayCDTrack_f( void );
@@ -756,6 +764,7 @@ int CL_IsDevOverviewMode( void );
void CL_PingServers_f( void );
void CL_SignonReply( void );
void CL_ClearState( void );
size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat );
//
// cl_demo.c
@@ -797,6 +806,20 @@ void CL_ResetEvent( event_info_t *ei );
word CL_EventIndex( const char *name );
void CL_FireEvents( void );
//
// cl_font.c
//
qboolean CL_FixedFont( cl_font_t *font );
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
void CL_FreeFont( cl_font_t *font );
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags );
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) _format( 6 );
//
// cl_game.c
//
@@ -812,7 +835,6 @@ void CL_FreeEdicts( void );
void CL_ClearWorld( void );
void CL_DrawCenterPrint( void );
void CL_ClearSpriteTextures( void );
void CL_FreeEntity( cl_entity_t *pEdict );
void CL_CenterPrint( const char *text, float y );
void CL_TextMessageParse( byte *pMemFile, int fileSize );
client_textmessage_t *CL_TextMessageGet( const char *pName );
@@ -826,11 +848,15 @@ model_t *CL_LoadClientSprite( const char *filename );
model_t *CL_LoadModel( const char *modelname, int *index );
HSPRITE EXPORT pfnSPR_Load( const char *szPicName );
HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags );
void PicAdjustSize( float *x, float *y, float *w, float *h );
void SPR_AdjustSize( float *x, float *y, float *w, float *h );
void SPR_AdjustTexCoords( float width, float height, float *s1, float *t1, float *s2, float *t2 );
int CL_GetScreenInfo( SCREENINFO *pscrinfo );
void CL_FillRGBA( int x, int y, int width, int height, int r, int g, int b, int a );
void CL_PlayerTrace( float *start, float *end, int traceFlags, int ignore_pe, pmtrace_t *tr );
void CL_PlayerTraceExt( float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ), pmtrace_t *tr );
pmtrace_t *PM_CL_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe );
const char *PM_CL_TraceTexture( int ground, float *vstart, float *vend );
int PM_CL_PointContents( const float *p, int *truecontents );
void CL_SetTraceHull( int hull );
void CL_GetMousePosition( int *mx, int *my ); // TODO: move to input
cl_entity_t* CL_GetViewModel( void );
@@ -838,6 +864,9 @@ void pfnGetScreenFade( struct screenfade_s *fade );
physent_t *pfnGetPhysent( int idx );
struct msurface_s *pfnTraceSurface( int ground, float *vstart, float *vend );
movevars_t *pfnGetMoveVars( void );
void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int height );
void CL_DisableScissor( scissor_state_t *scissor );
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
_inline cl_entity_t *CL_EDICT_NUM( int n )
{
@@ -862,7 +891,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message );
void CL_LegacyPrecache_f( void );
void CL_ParseTempEntity( sizebuf_t *msg );
void CL_StartResourceDownloading( const char *pszMessage, qboolean bCustom );
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
qboolean CL_RequestMissingResources( void );
void CL_RegisterResources ( sizebuf_t *msg );
@@ -913,10 +941,8 @@ void CL_PredictMovement( qboolean repredicting );
void CL_CheckPredictionError( void );
qboolean CL_IsPredicted( void );
int CL_TruePointContents( const vec3_t p );
int CL_PointContents( const vec3_t p );
int CL_WaterEntity( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time );
int CL_TestLine( const vec3_t start, const vec3_t end, int flags );
pmtrace_t *CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags );
@@ -925,7 +951,6 @@ void CL_PopTraceBounds( void );
void CL_MoveSpectatorCamera( void );
void CL_SetLastUpdate( void );
void CL_RedoPrediction( void );
void CL_ClearPhysEnts( void );
void CL_PushPMStates( void );
void CL_PopPMStates( void );
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient );
@@ -966,7 +991,7 @@ void CL_ClearAllRemaps( void );
// cl_render.c
//
qboolean R_InitRenderAPI( void );
int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef );
intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef );
lightstyle_t *CL_GetLightStyle( int number );
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis );
const ref_overview_t *GL_GetOverviewParms( void );
@@ -976,7 +1001,6 @@ const ref_overview_t *GL_GetOverviewParms( void );
//
void R_StoreEfrags( efrag_t **ppefrag, int framecount );
void R_AddEfrags( cl_entity_t *ent );
void R_RemoveEfrags( cl_entity_t *ent );
//
// cl_tent.c
//
@@ -1030,13 +1054,13 @@ int Con_UtfProcessChar( int in );
int Con_UtfProcessCharForce( int in );
int Con_UtfMoveLeft( char *str, int pos );
int Con_UtfMoveRight( char *str, int pos, int length );
void Con_DrawStringLen( const char *pText, int *length, int *height );
int Con_DrawString( int x, int y, const char *string, rgba_t setColor );
int Con_DrawCharacter( int x, int y, int number, rgba_t color );
void Con_DrawCharacterLen( int number, int *width, int *height );
void Con_DefaultColor( int r, int g, int b );
void Con_InvalidateFonts( void );
void Con_SetFont( int fontNum );
cl_font_t *Con_GetCurFont( void );
cl_font_t *Con_GetFont( int num );
void Con_DrawCharacterLen( int number, int *width, int *height );
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
void Con_CharEvent( int key );
void Con_RestoreFont( void );
void Key_Console( int key );
@@ -1131,7 +1155,6 @@ void CL_PlayVideo_f( void );
// keys.c
//
int Key_IsDown( int keynum );
const char *Key_IsBind( int keynum );
void Key_Event( int key, int down );
void Key_Init( void );
void Key_WriteBindings( file_t *f );

View File

@@ -116,7 +116,7 @@ typedef struct
// console fonts
cl_font_t chars[CON_NUMFONTS];// fonts.wad/font1.fnt
cl_font_t *curFont, *lastUsedFont;
cl_font_t *curFont;
// console input
field_t input;
@@ -213,37 +213,6 @@ void Con_ClearTyping( void )
Cmd_AutoCompleteClear();
}
/*
============
Con_StringLength
skipped color prefixes
============
*/
int Con_StringLength( const char *string )
{
int len;
const char *p;
if( !string ) return 0;
len = 0;
p = string;
while( *p )
{
if( IsColorString( p ))
{
p += 2;
continue;
}
len++;
p++;
}
return len;
}
/*
================
Con_MessageMode_f
@@ -283,6 +252,8 @@ void Con_ToggleConsole_f( void )
if( !host.allow_console || UI_CreditsActive( ))
return; // disabled
SCR_EndLoadingPlaque();
// show console only in game or by special call from menu
if( cls.state != ca_active || cls.key_dest == key_menu )
return;
@@ -553,89 +524,9 @@ Con_FixedFont
*/
qboolean Con_FixedFont( void )
{
if( con.curFont && con.curFont->valid && con.curFont->type == FONT_FIXED )
return true;
return false;
return CL_FixedFont( con.curFont );
}
static qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font )
{
int i, fontWidth;
if( font->valid )
return true; // already loaded
if( !FS_FileExists( fontname, false ))
return false;
// keep source to print directly into conback image
font->hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_FONT|TF_KEEP_SOURCE );
R_GetTextureParms( &fontWidth, NULL, font->hFontTexture );
if( font->hFontTexture && fontWidth != 0 )
{
font->charHeight = fontWidth / 16 * con_fontscale->value;
font->type = FONT_FIXED;
// build fixed rectangles
for( i = 0; i < 256; i++ )
{
font->fontRc[i].left = (i * (fontWidth / 16)) % fontWidth;
font->fontRc[i].right = font->fontRc[i].left + fontWidth / 16;
font->fontRc[i].top = (i / 16) * (fontWidth / 16);
font->fontRc[i].bottom = font->fontRc[i].top + fontWidth / 16;
font->charWidths[i] = fontWidth / 16 * con_fontscale->value;
}
font->valid = true;
}
return true;
}
static qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font )
{
int i, fontWidth;
byte *buffer;
fs_offset_t length;
qfont_t *src;
if( font->valid )
return true; // already loaded
if( !FS_FileExists( fontname, false ))
return false;
font->hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_FONT|TF_NEAREST );
R_GetTextureParms( &fontWidth, NULL, font->hFontTexture );
// setup consolefont
if( font->hFontTexture && fontWidth != 0 )
{
// half-life font with variable chars witdh
buffer = FS_LoadFile( fontname, &length, false );
if( buffer && length >= sizeof( qfont_t ))
{
src = (qfont_t *)buffer;
font->charHeight = src->rowheight * con_fontscale->value;
font->type = FONT_VARIABLE;
// build rectangles
for( i = 0; i < 256; i++ )
{
font->fontRc[i].left = (word)src->fontinfo[i].startoffset % fontWidth;
font->fontRc[i].right = font->fontRc[i].left + src->fontinfo[i].charwidth;
font->fontRc[i].top = (word)src->fontinfo[i].startoffset / fontWidth;
font->fontRc[i].bottom = font->fontRc[i].top + src->rowheight;
font->charWidths[i] = src->fontinfo[i].charwidth * con_fontscale->value;
}
font->valid = true;
}
if( buffer ) Mem_Free( buffer );
}
return true;
}
/*
================
@@ -646,32 +537,46 @@ INTERNAL RESOURCE
*/
static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
{
const char *path = NULL;
dword crc = 0;
qboolean success = false;
float scale = con_fontscale->value;
if( font->valid ) return; // already loaded
// replace default fonts.wad textures by current charset's font
if( !CRC32_File( &crc, "fonts.wad" ) || crc == 0x3c0a0029 )
{
const char *path2 = va("font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" ) );
if( FS_FileExists( path2, false ) )
path = path2;
}
if( font->valid )
return; // already loaded
// loading conchars
if( Sys_CheckParm( "-oldfont" ))
Con_LoadVariableWidthFont( "gfx/conchars.fnt", font );
{
success = Con_LoadVariableWidthFont( "gfx/conchars.fnt", font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
}
else
{
if( !path )
path = va( "fonts/font%i", fontNumber );
string path;
dword crc = 0;
Con_LoadVariableWidthFont( path, font );
// replace default fonts.wad textures by current charset's font
if( !CRC32_File( &crc, "fonts.wad" ) || crc == 0x3c0a0029 )
{
if( Q_snprintf( path, sizeof( path ),
"font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" )) > 0 )
{
success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
}
}
if( !success )
{
Q_snprintf( path, sizeof( path ), "fonts/font%i", fontNumber );
success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
}
}
// quake fixed font as fallback
if( !font->valid ) Con_LoadFixedWidthFont( "gfx/conchars", font );
if( !success )
{
// quake fixed font as fallback
// keep source to print directly into conback image
if( !Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransTexture, TF_FONT|TF_KEEP_SOURCE ))
Con_DPrintf( S_ERROR "failed to load console font\n" );
}
}
/*
@@ -700,7 +605,7 @@ static void Con_LoadConchars( void )
fontSize = CON_NUMFONTS - 1;
// sets the current font
con.lastUsedFont = con.curFont = &con.chars[fontSize];
con.curFont = &con.chars[fontSize];
}
// CP1251 table
@@ -873,129 +778,25 @@ static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
/*
====================
Con_TextAdjustSize
Con_GetFont
draw charcters routine
====================
*/
static void Con_TextAdjustSize( int *x, int *y, int *w, int *h )
cl_font_t *Con_GetFont( int num )
{
float xscale, yscale;
if( !x && !y && !w && !h ) return;
// scale for screen sizes
xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
if( x ) *x *= xscale;
if( y ) *y *= yscale;
if( w ) *w *= xscale;
if( h ) *h *= yscale;
num = bound( 0, num, CON_NUMFONTS - 1 );
return &con.chars[num];
}
/*
====================
Con_DrawGenericChar
Con_GetCurFont
draw console single character
====================
*/
static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
cl_font_t *Con_GetCurFont( void )
{
int width, height;
float s1, t1, s2, t2;
wrect_t *rc;
number &= 255;
if( !con.curFont || !con.curFont->valid )
return 0;
number = Con_UtfProcessChar(number);
if( !number )
return 0;
if( y < -con.curFont->charHeight )
return 0;
rc = &con.curFont->fontRc[number];
R_GetTextureParms( &width, &height, con.curFont->hFontTexture );
if( !width || !height )
return con.curFont->charWidths[number];
// don't apply color to fixed fonts it's already colored
if( con.curFont->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, con.curFont->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] );
// calc rectangle
s1 = (float)rc->left / width;
t1 = (float)rc->top / height;
s2 = (float)rc->right / width;
t2 = (float)rc->bottom / height;
width = ( rc->right - rc->left ) * con_fontscale->value;
height = ( rc->bottom - rc->top ) * con_fontscale->value;
if( clgame.ds.adjust_size )
Con_TextAdjustSize( &x, &y, &width, &height );
ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, con.curFont->hFontTexture );
ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); // don't forget reset color
return con.curFont->charWidths[number];
}
/*
====================
Con_SetFont
choose font size
====================
*/
void Con_SetFont( int fontNum )
{
fontNum = bound( 0, fontNum, CON_NUMFONTS - 1 );
con.curFont = &con.chars[fontNum];
}
/*
====================
Con_RestoreFont
restore auto-selected console font
(that based on screen resolution)
====================
*/
void Con_RestoreFont( void )
{
con.curFont = con.lastUsedFont;
}
/*
====================
Con_DrawCharacter
client version of routine
====================
*/
int Con_DrawCharacter( int x, int y, int number, rgba_t color )
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
return Con_DrawGenericChar( x, y, number, color );
}
/*
====================
Con_DrawCharacterLen
returns character sizes in screen pixels
====================
*/
void Con_DrawCharacterLen( int number, int *width, int *height )
{
if( width && con.curFont ) *width = con.curFont->charWidths[number];
if( height && con.curFont ) *height = con.curFont->charHeight;
return con.curFont;
}
/*
@@ -1007,105 +808,7 @@ compute string width and height in screen pixels
*/
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height )
{
int curLength = 0;
if( !con.curFont )
return;
if( height )
*height = con.curFont->charHeight;
if (!length)
return;
*length = 0;
while( *pText )
{
byte c = *pText;
if( *pText == '\n' )
{
pText++;
curLength = 0;
}
// skip color strings they are not drawing
if( IsColorString( pText ))
{
pText += 2;
continue;
}
// Convert to unicode
c = Con_UtfProcessChar( c );
if( c )
curLength += con.curFont->charWidths[c];
pText++;
if( curLength > *length )
*length = curLength;
}
}
/*
==================
Con_DrawString
Draws a multi-colored string, optionally forcing
to a fixed color.
==================
*/
int Con_DrawGenericString( int x, int y, const char *string, rgba_t setColor, qboolean forceColor, int hideChar )
{
rgba_t color;
int drawLen = 0;
int numDraws = 0;
const char *s;
if( !con.curFont ) return 0; // no font set
Con_UtfProcessChar( 0 );
// draw the colored text
memcpy( color, setColor, sizeof( color ));
s = string;
while( *s )
{
if( *s == '\n' )
{
s++;
if( !*s ) break; // at end the string
drawLen = 0; // begin new row
y += con.curFont->charHeight;
}
if( IsColorString( s ))
{
if( !forceColor )
{
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ));
color[3] = setColor[3];
}
s += 2;
numDraws++;
continue;
}
// hide char for overstrike mode
if( hideChar == numDraws )
drawLen += con.curFont->charWidths[*s];
else drawLen += Con_DrawCharacter( x + drawLen, y, *s, color );
numDraws++;
s++;
}
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
return drawLen;
return CL_DrawStringLen( con.curFont, pText, length, height, FONT_DRAW_UTF8 );
}
/*
@@ -1117,10 +820,9 @@ client version of routine
*/
int Con_DrawString( int x, int y, const char *string, rgba_t setColor )
{
return Con_DrawGenericString( x, y, string, setColor, false, -1 );
return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 );
}
/*
================
Con_Init
@@ -1497,7 +1199,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
return;
}
if( key == K_BACKSPACE )
if( key == K_BACKSPACE || key == K_X_BUTTON )
{
if( edit->cursor > 0 )
{
@@ -1509,7 +1211,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
return;
}
if( key == K_RIGHTARROW )
if( key == K_RIGHTARROW || key == K_DPAD_RIGHT )
{
if( edit->cursor < len ) edit->cursor = Con_UtfMoveRight( edit->buffer, edit->cursor, edit->widthInChars );
if( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= len )
@@ -1517,7 +1219,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
return;
}
if( key == K_LEFTARROW )
if( key == K_LEFTARROW || key == K_DPAD_LEFT )
{
if( edit->cursor > 0 ) edit->cursor = Con_UtfMoveLeft( edit->buffer, edit->cursor );
if( edit->cursor < edit->scroll ) edit->scroll--;
@@ -1612,7 +1314,7 @@ Field_DrawInputLine
void Field_DrawInputLine( int x, int y, field_t *edit )
{
int len, cursorChar;
int drawLen, hideChar = -1;
int drawLen;
int prestep, curPos;
char str[MAX_SYSPATH];
byte *colorDefault;
@@ -1649,35 +1351,23 @@ void Field_DrawInputLine( int x, int y, field_t *edit )
// save char for overstrike
cursorChar = str[edit->cursor - prestep];
if( host.key_overstrike && cursorChar && !((int)( host.realtime * 4 ) & 1 ))
hideChar = edit->cursor - prestep; // skip this char
// draw it
Con_DrawGenericString( x, y, str, colorDefault, false, hideChar );
CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
// draw the cursor
if((int)( host.realtime * 4 ) & 1 ) return; // off blink
// calc cursor position
str[edit->cursor - prestep] = 0;
Con_DrawStringLen( str, &curPos, NULL );
Con_UtfProcessChar( 0 );
CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
if( host.key_overstrike && cursorChar )
if( host.key_overstrike )
{
// overstrike cursor
#if 0
pglEnable( GL_BLEND );
pglDisable( GL_ALPHA_TEST );
pglBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
#endif
Con_DrawGenericChar( x + curPos, y, cursorChar, colorDefault );
CL_DrawCharacter( x + curPos, y, '|', colorDefault, con.curFont, 0 );
}
else
{
Con_UtfProcessChar( 0 );
Con_DrawCharacter( x + curPos, y, '_', colorDefault );
CL_DrawCharacter( x + curPos, y, '_', colorDefault, con.curFont, 0 );
}
}
@@ -1791,6 +1481,10 @@ static void Con_SaveHistory( con_history_t *self )
int historyStart = self->next - CON_HISTORY, i;
file_t *f;
// do not save history if nothing was executed
if( self->next == 0 )
return;
if( historyStart < 0 )
historyStart = 0;
@@ -1826,8 +1520,8 @@ void Key_Console( int key )
return;
}
// enter finishes the line
if( key == K_ENTER || key == K_KP_ENTER )
// enter or A finish the line
if( key == K_ENTER || key == K_KP_ENTER || key == K_A_BUTTON )
{
// backslash text are commands, else chat
if( con.input.buffer[0] == '\\' || con.input.buffer[0] == '/' )
@@ -1854,7 +1548,7 @@ void Key_Console( int key )
}
// command completion
if( key == K_TAB )
if( key == K_TAB || key == K_L2_BUTTON )
{
Con_CompleteCommand( &con.input );
Con_Bottom();
@@ -1875,13 +1569,13 @@ void Key_Console( int key )
}
// console scrolling
if( key == K_PGUP )
if( key == K_PGUP || key == K_DPAD_UP )
{
Con_PageUp( 1 );
return;
}
if( key == K_PGDN )
if( key == K_PGDN || key == K_DPAD_DOWN )
{
Con_PageDown( 1 );
return;
@@ -1917,6 +1611,23 @@ void Key_Console( int key )
return;
}
// enable the OSK with button press
if( key == K_Y_BUTTON )
{
Key_EnableTextInput( true, true );
return;
}
// exit the console by pressing MINUS on NSwitch
// or both Back(Select)/Start buttons for everyone else
if( key == K_BACK_BUTTON || key == K_START_BUTTON )
{
if( cls.state == ca_active && !cl.background )
Key_SetKeyDest( key_game );
else UI_SetActiveMenu( true );
return;
}
// pass to the normal editline routine
Field_KeyDownEvent( &con.input, key );
}
@@ -1932,14 +1643,14 @@ void Key_Message( int key )
{
char buffer[MAX_SYSPATH];
if( key == K_ESCAPE )
if( key == K_ESCAPE || key == K_BACK_BUTTON )
{
Key_SetKeyDest( key_game );
Con_ClearField( &con.chat );
return;
}
if( key == K_ENTER || key == K_KP_ENTER )
if( key == K_ENTER || key == K_KP_ENTER || key == K_A_BUTTON )
{
if( con.chat.buffer[0] && cls.state == ca_active )
{
@@ -1981,7 +1692,7 @@ void Con_DrawInput( int lines )
return;
y = lines - ( con.curFont->charHeight * 2 );
Con_DrawCharacter( con.curFont->charWidths[' '], y, ']', g_color_table[7] );
CL_DrawCharacter( con.curFont->charWidths[' '], y, ']', g_color_table[7], con.curFont, 0 );
Field_DrawInputLine( con.curFont->charWidths[' ']*2, y, &con.input );
}
@@ -1994,30 +1705,37 @@ Custom debug messages
*/
int Con_DrawDebugLines( void )
{
notify_t *notify = con.notify;
int i, count = 0;
int defaultX;
int y = 20;
int fontTall;
if( !con.curFont || !con.curFont->valid )
return 0;
defaultX = refState.width / 4;
fontTall = con.curFont->charHeight + 1;
for( i = 0; i < MAX_DBG_NOTIFY; i++ )
for( i = 0; i < ARRAYSIZE( con.notify ); i++, notify++ )
{
if( host.realtime < con.notify[i].expire && con.notify[i].key_dest == cls.key_dest )
{
int x, len;
int fontTall = 0;
int x, len;
Con_DrawStringLen( con.notify[i].szNotify, &len, &fontTall );
x = refState.width - Q_max( defaultX, len ) - 10;
fontTall += 1;
if( host.realtime > notify->expire )
continue;
if( y + fontTall > refState.height - 20 )
return count;
if( notify->key_dest != cls.key_dest )
continue;
count++;
y = 20 + fontTall * i;
Con_DrawString( x, y, con.notify[i].szNotify, con.notify[i].color );
}
Con_DrawStringLen( notify->szNotify, &len, NULL );
x = refState.width - Q_max( defaultX, len ) - 10;
if( y + fontTall > refState.height - 20 )
return count;
count++;
y += fontTall;
CL_DrawString( x, y, notify->szNotify, notify->color, con.curFont, FONT_DRAW_UTF8 | FONT_DRAW_NOLF );
}
return count;
@@ -2039,17 +1757,17 @@ void Con_DrawDebug( void )
if( scr_download->value != -1.0f )
{
Q_snprintf( dlstring, sizeof( dlstring ), "Downloading [%d remaining]: ^2%s^7 %5.1f%% time %.f secs",
host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart );
host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart );
x = refState.width - 500;
y = con.curFont->charHeight * 1.05f;
Con_DrawString( x, y, dlstring, g_color_table[7] );
}
else
{
timeStart = Sys_DoubleTime();
timeStart = host.realtime;
}
if( !host_developer.value || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" ))
if( !host.allow_console || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" ))
return;
if( con.draw_notify && !Con_Visible( ))
@@ -2075,7 +1793,7 @@ void Con_DrawNotify( void )
x = con.curFont->charWidths[' ']; // offset one space at left screen side
if( host_developer.value && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
{
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
{
@@ -2126,7 +1844,11 @@ int Con_DrawConsoleLine( int y, int lineno )
return 0; // this string will be shown only at notify
if( y >= con.curFont->charHeight )
Con_DrawGenericString( con.curFont->charWidths[' '], y, li->start, g_color_table[7], false, -1 );
{
float x = con.curFont->charWidths[' '];
CL_DrawString( x, y, li->start, g_color_table[7], con.curFont, FONT_DRAW_UTF8 );
}
return con.curFont->charHeight;
}
@@ -2193,17 +1915,15 @@ void Con_DrawSolidConsole( int lines )
// draw current version
memcpy( color, g_color_table[7], sizeof( color ));
Q_snprintf( curbuild, MAX_STRING, "%s %i/%s (%s-%s build %i)", XASH_ENGINE_NAME, PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
Q_snprintf( curbuild, MAX_STRING, XASH_ENGINE_NAME " %i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
Con_DrawStringLen( curbuild, &stringLen, &charH );
start = refState.width - stringLen;
stringLen = Con_StringLength( curbuild );
start = refState.width - stringLen;
fraction = lines / (float)refState.height;
color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number
for( i = 0; i < stringLen; i++ )
width += Con_DrawCharacter( start + width, 0, curbuild[i], color );
Con_DrawString( start, 0, curbuild, color );
// draw the text
if( CON_LINES_COUNT > 0 )
@@ -2220,7 +1940,7 @@ void Con_DrawSolidConsole( int lines )
// draw red arrows to show the buffer is backscrolled
for( x = 0; x < con.linewidth; x += 4 )
Con_DrawCharacter(( x + 1 ) * start, y, '^', g_color_table[1] );
CL_DrawCharacter( ( x + 1 ) * start, y, '^', g_color_table[1], con.curFont, 0 );
y -= con.curFont->charHeight;
}
x = lastline;
@@ -2323,7 +2043,7 @@ void Con_DrawVersion( void )
{
// draws the current build
byte *color = g_color_table[7];
int i, stringLen, width = 0, charH = 0;
int stringLen, charH = 0;
int start, height = refState.height;
qboolean draw_version = false;
string curbuild;
@@ -2346,16 +2066,14 @@ void Con_DrawVersion( void )
host.force_draw_version = false;
if( host.force_draw_version || draw_version )
Q_snprintf( curbuild, MAX_STRING, "%s v%i/%s (%s-%s build %i)", XASH_ENGINE_NAME, PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
else Q_snprintf( curbuild, MAX_STRING, "v%i/%s (%s-%s build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
Q_snprintf( curbuild, MAX_STRING, XASH_ENGINE_NAME " v%i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
else Q_snprintf( curbuild, MAX_STRING, "v%i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
Con_DrawStringLen( curbuild, &stringLen, &charH );
start = refState.width - stringLen * 1.05f;
stringLen = Con_StringLength( curbuild );
height -= charH * 1.05f;
for( i = 0; i < stringLen; i++ )
width += Con_DrawCharacter( start + width, height, curbuild[i], color );
Con_DrawString( start, height, curbuild, color );
}
/*
@@ -2395,28 +2113,35 @@ void Con_RunConsole( void )
con.vislines = con.showlines;
}
if( FBitSet( con_charset->flags, FCVAR_CHANGED ) ||
if( FBitSet( con_charset->flags, FCVAR_CHANGED ) ||
FBitSet( con_fontscale->flags, FCVAR_CHANGED ) ||
FBitSet( con_fontnum->flags, FCVAR_CHANGED ) ||
FBitSet( cl_charset->flags, FCVAR_CHANGED ) )
FBitSet( cl_charset->flags, FCVAR_CHANGED ))
{
// update codepage parameters
g_codepage = 0;
if( !Q_stricmp( con_charset->string, "cp1251" ) )
if( !Q_stricmp( con_charset->string, "cp1251" ))
{
g_codepage = 1251;
else if( !Q_stricmp( con_charset->string, "cp1252" ) )
}
else if( !Q_stricmp( con_charset->string, "cp1252" ))
{
g_codepage = 1252;
}
else
{
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset->string );
Cvar_DirectSet( con_charset, "cp1252" );
g_codepage = 1252;
}
g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" );
Con_InvalidateFonts();
Con_LoadConchars();
cls.creditsFont.valid = false;
SCR_LoadCreditsFont();
ClearBits( con_charset->flags, FCVAR_CHANGED );
ClearBits( con_fontnum->flags, FCVAR_CHANGED );
ClearBits( con_fontscale->flags, FCVAR_CHANGED );
ClearBits( cl_charset->flags, FCVAR_CHANGED );
}
}
@@ -2551,8 +2276,10 @@ Con_InvalidateFonts
*/
void Con_InvalidateFonts( void )
{
memset( con.chars, 0, sizeof( con.chars ));
con.curFont = con.lastUsedFont = NULL;
int i;
for( i = 0; i < ARRAYSIZE( con.chars ); i++ )
CL_FreeFont( &con.chars[i] );
con.curFont = NULL;
}
/*

View File

@@ -44,6 +44,7 @@ static struct joy_axis_s
short prevval;
} joyaxis[MAX_AXES] = { 0 };
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
static qboolean joy_initialized;
convar_t *joy_enable;
static convar_t *joy_pitch;
static convar_t *joy_yaw;
@@ -244,7 +245,7 @@ void Joy_AxisMotionEvent( byte axis, short value )
return;
}
return Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
}
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value )
@@ -393,10 +394,10 @@ void Joy_Init( void )
joy_forward_key_threshold = Cvar_Get( "joy_forward_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis key event emit threshold. Value from 0 to 32767");
// by default, we rely on deadzone detection come from system, but some glitchy devices report false deadzones
joy_side_deadzone = Cvar_Get( "joy_side_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" );
joy_forward_deadzone = Cvar_Get( "joy_forward_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767");
joy_pitch_deadzone = Cvar_Get( "joy_pitch_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767");
joy_yaw_deadzone = Cvar_Get( "joy_yaw_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
joy_side_deadzone = Cvar_Get( "joy_side_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" );
joy_forward_deadzone = Cvar_Get( "joy_forward_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767");
joy_pitch_deadzone = Cvar_Get( "joy_pitch_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767");
joy_yaw_deadzone = Cvar_Get( "joy_yaw_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
joy_axis_binding = Cvar_Get( "joy_axis_binding", "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
@@ -407,13 +408,17 @@ void Joy_Init( void )
joy_enable = Cvar_Get( "joy_enable", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
if( Sys_CheckParm( "-nojoy" ))
// renamed from -nojoy to -noenginejoy to not conflict with
// client.dll's joystick support
if( Sys_CheckParm( "-noenginejoy" ))
{
Cvar_FullSet( "joy_enable", "0", FCVAR_READ_ONLY );
return;
}
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index->value )), FCVAR_READ_ONLY );
joy_initialized = true;
}
/*
@@ -425,5 +430,8 @@ Shutdown joystick code
*/
void Joy_Shutdown( void )
{
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
if( joy_initialized )
{
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
}
}

View File

@@ -87,7 +87,7 @@ typedef struct touchbuttonlist_s
touch_button_t *last;
} touchbuttonlist_t;
struct touch_s
static struct touch_s
{
qboolean initialized;
qboolean config_loaded;
@@ -151,7 +151,6 @@ convar_t *touch_exp_mult;
convar_t *touch_grid_enable;
convar_t *touch_grid_count;
convar_t *touch_config_file;
convar_t *touch_enable;
convar_t *touch_in_menu;
convar_t *touch_joy_radius;
convar_t *touch_dpad_radius;
@@ -162,7 +161,9 @@ convar_t *touch_highlight_b;
convar_t *touch_highlight_a;
convar_t *touch_precise_amount;
convar_t *touch_joy_texture;
convar_t *touch_emulate;
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
// code looks smaller with it
#define B(x) (button->x)
@@ -214,6 +215,74 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
return 0;
}
/*
=================
Touch_DumpConfig
Dump config to file
=================
*/
qboolean Touch_DumpConfig( const char *name, const char *profilename )
{
file_t *f;
touch_button_t *button;
f = FS_Open( name, "w", true );
if( !f )
{
Con_Printf( S_ERROR "Couldn't write %s.\n", name );
return false;
}
FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tCopyright FWGS & XashXT group %s (c)\n", Q_timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\t\ttouchscreen config\n" );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
FS_Printf( f, "\n// touch cvars\n" );
FS_Printf( f, "\n// sensitivity settings\n" );
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch->value );
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw->value );
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone->value );
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone->value );
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", CVAR_TO_BOOL(touch_nonlinear_look));
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor->value );
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult->value );
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult->value );
FS_Printf( f, "\n// grid settings\n" );
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count->value );
FS_Printf( f, "touch_grid_enable \"%d\"\n", CVAR_TO_BOOL(touch_grid_enable));
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
FS_Printf( f, "\n// highlight when pressed\n" );
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r->value );
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g->value );
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b->value );
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a->value );
FS_Printf( f, "\n// _joy and _dpad options\n" );
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius->value );
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius->value );
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount->value );
FS_Printf( f, "\n// enable/disable move indicator\n" );
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator->value );
FS_Printf( f, "\n// reset menu state when execing config\n" );
FS_Printf( f, "touch_setclientonly 0\n" );
FS_Printf( f, "\n// touch buttons\n" );
FS_Printf( f, "touch_removeall\n" );
for( button = touch.list_user.first; button; button = button->next )
{
Touch_ExportButtonToConfig( f, button, false );
}
FS_Close( f );
return true;
}
/*
=================
Touch_WriteConfig
@@ -237,61 +306,14 @@ void Touch_WriteConfig( void )
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file->string );
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file->string );
f = FS_Open( newconfigfile, "w", true );
if( f )
if( Touch_DumpConfig( newconfigfile, touch_config_file->string ))
{
touch_button_t *button;
FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tCopyright FWGS & XashXT group %s (c)\n", Q_timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\t\ttouchscreen config\n" );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "\ntouch_config_file \"%s\"\n", touch_config_file->string );
FS_Printf( f, "\n// touch cvars\n" );
FS_Printf( f, "\n// sensitivity settings\n" );
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch->value );
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw->value );
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone->value );
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone->value );
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", CVAR_TO_BOOL(touch_nonlinear_look));
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor->value );
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult->value );
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult->value );
FS_Printf( f, "\n// grid settings\n" );
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count->value );
FS_Printf( f, "touch_grid_enable \"%d\"\n", CVAR_TO_BOOL(touch_grid_enable));
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
FS_Printf( f, "\n// highlight when pressed\n" );
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r->value );
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g->value );
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b->value );
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a->value );
FS_Printf( f, "\n// _joy and _dpad options\n" );
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius->value );
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius->value );
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount->value );
FS_Printf( f, "\n// enable/disable move indicator\n" );
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator->value );
FS_Printf( f, "\n// reset menu state when execing config\n" );
FS_Printf( f, "touch_setclientonly 0\n" );
FS_Printf( f, "\n// touch buttons\n" );
FS_Printf( f, "touch_removeall\n" );
for( button = touch.list_user.first; button; button = button->next )
{
Touch_ExportButtonToConfig( f, button, false );
}
FS_Close( f );
FS_Delete( oldconfigfile );
FS_Rename( touch_config_file->string, oldconfigfile );
FS_Delete( touch_config_file->string );
FS_Rename( newconfigfile, touch_config_file->string );
}
else Con_Printf( S_ERROR "Couldn't write %s.\n", touch_config_file->string );
}
/*
@@ -303,8 +325,8 @@ export current touch configuration into profile
*/
static void Touch_ExportConfig_f( void )
{
file_t *f;
const char *name;
string profilename, profilebase;
if( Cmd_Argc() != 2 )
{
@@ -316,65 +338,15 @@ static void Touch_ExportConfig_f( void )
name = Cmd_Argv( 1 );
Con_Reportf( "Exporting config to %s\n", name );
f = FS_Open( name, "w", true );
if( f )
if( Q_strstr( name, "touch_presets/" ))
{
string profilename, profilebase;
touch_button_t *button;
if( Q_strstr( name, "touch_presets/" ) )
{
COM_FileBase( name, profilebase );
Q_snprintf( profilename, sizeof( profilebase ), "touch_profiles/%s (copy).cfg", profilebase );
}
else Q_strncpy( profilename, name, sizeof( profilename ));
FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tCopyright FWGS & XashXT group %s (c)\n", Q_timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\t\ttouchscreen preset\n" );
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
FS_Printf( f, "\n// touch cvars\n" );
FS_Printf( f, "\n// sensitivity settings\n" );
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch->value );
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw->value );
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone->value );
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone->value );
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", CVAR_TO_BOOL(touch_nonlinear_look) );
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor->value );
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult->value );
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult->value );
FS_Printf( f, "\n// grid settings\n" );
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count->value );
FS_Printf( f, "touch_grid_enable \"%d\"\n", CVAR_TO_BOOL(touch_grid_enable) );
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
FS_Printf( f, "\n// highlight when pressed\n" );
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r->value );
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g->value );
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b->value );
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a->value );
FS_Printf( f, "\n// _joy and _dpad options\n" );
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius->value );
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius->value );
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount->value );
FS_Printf( f, "\n// enable/disable move indicator\n" );
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator->value );
FS_Printf( f, "\n// reset menu state when execing config\n" );
FS_Printf( f, "touch_setclientonly 0\n" );
FS_Printf( f, "\n// touch buttons\n" );
FS_Printf( f, "touch_removeall\n" );
for( button = touch.list_user.first; button; button = button->next )
{
Touch_ExportButtonToConfig( f, button, true );
}
FS_Printf( f, "\n// round button coordinates to grid\n" );
FS_Printf( f, "touch_roundall\n" );
FS_Close( f );
COM_FileBase( name, profilebase, sizeof( profilebase ));
Q_snprintf( profilename, sizeof( profilebase ), "touch_profiles/%s (copy).cfg", profilebase );
}
else Con_Printf( S_ERROR "Couldn't write %s.\n", name );
else Q_strncpy( profilename, name, sizeof( profilename ));
Con_Reportf( "Exporting config to \"%s\", profile name \"%s\"\n", name, profilename );
Touch_DumpConfig( name, profilename );
}
/*
@@ -497,8 +469,8 @@ static touch_button_t *Touch_FindFirst( touchbuttonlist_t *list, const char *nam
void Touch_SetClientOnly( byte state )
{
// TODO: fix clash with vgui cursors
touch.clientonly = state;
host.mouse_visible = state;
touch.move_finger = touch.look_finger = -1;
touch.forward = touch.side = 0;
@@ -765,7 +737,7 @@ static void Touch_ReloadConfig_f( void )
touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
Cbuf_AddText( va("exec %s\n", touch_config_file->string ) );
Cbuf_AddTextf( "exec %s\n", touch_config_file->string );
}
static touch_button_t *Touch_AddButton( touchbuttonlist_t *list,
@@ -994,7 +966,7 @@ static void Touch_InitEditor( void )
Touch_ClearList( &touch.list_edit );
temp = Touch_AddButton( &touch.list_edit, "close", "touch_default/edit_close.tga", "touch_disableedit", 0, y, x, y + 0.1f, color, true );
temp = Touch_AddButton( &touch.list_edit, "close", "touch_default/edit_close", "touch_disableedit", 0, y, x, y + 0.1f, color, true );
SetBits( temp->flags, TOUCH_FL_NOEDIT );
temp = Touch_AddButton( &touch.list_edit, "close", "#Close and save", "", x, y, x + 0.2f, y + 0.1f, color, true );
@@ -1002,7 +974,7 @@ static void Touch_InitEditor( void )
y += 0.2f;
temp = Touch_AddButton( &touch.list_edit, "cancel", "touch_default/edit_reset.tga", "touch_reloadconfig", 0, y, x, y + 0.1f, color, true );
temp = Touch_AddButton( &touch.list_edit, "cancel", "touch_default/edit_reset", "touch_reloadconfig", 0, y, x, y + 0.1f, color, true );
SetBits( temp->flags, TOUCH_FL_NOEDIT );
temp = Touch_AddButton( &touch.list_edit, "close", "#Cancel and reset", "", x, y, x + 0.2f, y + 0.1f, color, true );
@@ -1010,7 +982,7 @@ static void Touch_InitEditor( void )
y += 0.2f;
touch.hidebutton = Touch_AddButton( &touch.list_edit, "showhide", "touch_default/edit_hide.tga", "touch_toggleselection", 0, y, x, y + 0.1f, color, true );
touch.hidebutton = Touch_AddButton( &touch.list_edit, "showhide", "touch_default/edit_hide", "touch_toggleselection", 0, y, x, y + 0.1f, color, true );
SetBits( touch.hidebutton->flags, TOUCH_FL_HIDE | TOUCH_FL_NOEDIT );
}
@@ -1038,24 +1010,24 @@ void Touch_Init( void )
MakeRGBA( color, 255, 255, 255, 255 );
Touch_AddDefaultButton( "look", "", "_look", 0.500000, 0.000000, 1.000000, 1, color, 0, 0, 0 );
Touch_AddDefaultButton( "move", "", "_move", 0.000000, 0.000000, 0.500000, 1, color, 0, 0, 0 );
Touch_AddDefaultButton( "invnext", "touch_default/next_weap.tga", "invnext", 0.000000, 0.530200, 0.120000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "invprev", "touch_default/prev_weap.tga", "invprev", 0.000000, 0.075743, 0.120000, 0.302971, color, 2, 1, 0 );
Touch_AddDefaultButton( "use", "touch_default/use.tga", "+use", 0.880000, 0.454457, 1.000000, 0.681685, color, 2, 1, 0 );
Touch_AddDefaultButton( "jump", "touch_default/jump.tga", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack", "touch_default/shoot.tga", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt.tga", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "loadquick", "touch_default/load.tga", "loadquick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save.tga", "savequick", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard.tga", "messagemode", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "reload", "touch_default/reload.tga", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled.tga", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
Touch_AddDefaultButton( "scores", "touch_default/map.tga", "+showscores", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons.tga", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "duck", "touch_default/crouch.tga", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "tduck", "touch_default/tduck.tga", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
Touch_AddDefaultButton( "edit", "touch_default/settings.tga", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
Touch_AddDefaultButton( "menu", "touch_default/menu.tga", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "invnext", "touch_default/next_weap", "invnext", 0.000000, 0.530200, 0.120000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "invprev", "touch_default/prev_weap", "invprev", 0.000000, 0.075743, 0.120000, 0.302971, color, 2, 1, 0 );
Touch_AddDefaultButton( "use", "touch_default/use", "+use", 0.880000, 0.454457, 1.000000, 0.681685, color, 2, 1, 0 );
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 0 );
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
@@ -1106,14 +1078,19 @@ void Touch_Init( void )
touch_dpad_radius = Cvar_Get( "touch_dpad_radius", "1.0", FCVAR_FILTERABLE, "dpad radius multiplier" );
touch_joy_radius = Cvar_Get( "touch_joy_radius", "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
touch_move_indicator = Cvar_Get( "touch_move_indicator", "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy.tga", FCVAR_FILTERABLE, "texture for move indicator");
touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
// input devices cvar
touch_enable = Cvar_Get( "touch_enable", DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
touch_emulate = Cvar_Get( "touch_emulate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
Cvar_RegisterVariable( &touch_enable );
Cvar_RegisterVariable( &touch_emulate );
/// TODO: touch sdl platform
// SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
// 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" );
#else
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
#endif
touch.initialized = true;
}
@@ -1133,8 +1110,14 @@ static void Touch_InitConfig( void )
/// TODO: hud font
//pfnGetScreenInfo( NULL ); //HACK: update hud screen parameters like iHeight
if( FS_FileExists( touch_config_file->string, true ) )
Cbuf_AddText( va( "exec \"%s\"\n", touch_config_file->string ) );
else Touch_LoadDefaults_f( );
{
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file->string );
Cbuf_Execute();
}
else
{
Touch_LoadDefaults_f();
}
Touch_InitEditor();
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture->string, NULL, 0, TF_NOMIPMAP );
@@ -1372,7 +1355,7 @@ void Touch_Draw( void )
{
touch_button_t *button;
if( !touch.initialized || (!CVAR_TO_BOOL(touch_enable) && !touch.clientonly) )
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
return;
Touch_InitConfig();
@@ -1515,9 +1498,9 @@ static void Touch_EditMove( touchEventType type, int fingerID, float x, float y,
touch.hidebutton->flags &= ~TOUCH_FL_HIDE;
if( FBitSet( button->flags, TOUCH_FL_HIDE ))
Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_show.tga" );
Q_strncpy( touch.hidebutton->texturefile, "touch_default/edit_show", sizeof( touch.hidebutton->texturefile ));
else
Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_hide.tga" );
Q_strncpy( touch.hidebutton->texturefile, "touch_default/edit_hide", sizeof( touch.hidebutton->texturefile ));
}
}
if( type == event_motion ) // shutdown button move
@@ -1966,15 +1949,15 @@ static int Touch_ControlsEvent( touchEventType type, int fingerID, float x, floa
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy )
{
// simulate menu mouse click
if( cls.key_dest != key_game && !CVAR_TO_BOOL(touch_in_menu) )
if( cls.key_dest != key_game && !CVAR_TO_BOOL( touch_in_menu ))
{
touch.move_finger = touch.resize_finger = touch.look_finger = -1;
// Hack for keyboard, hope it help
if( cls.key_dest == key_console || cls.key_dest == key_message )
{
Key_EnableTextInput( true, true );
if ( type == event_down ) // don't pop it again on event_up
Key_EnableTextInput( true, true );
if( cls.key_dest == key_console )
{
static float y1 = 0;
@@ -2011,25 +1994,20 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
{
VGui_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) );
if( type != event_motion )
VGui_KeyEvent( K_MOUSE1, type == event_down ? 1 : 0 );
// allow scoreboard scroll
if( host.mouse_visible && type == event_motion )
return 0;
switch( type )
{
case event_down:
VGui_MouseEvent( K_MOUSE1, 1 );
break;
case event_up:
VGui_MouseEvent( K_MOUSE1, 0 );
break;
default: break;
}
}
if( !touch.initialized || (!CVAR_TO_BOOL(touch_enable) && !touch.clientonly) )
{
#if 0
if( type == event_down )
Key_Event( K_MOUSE1, true );
if( type == event_up )
Key_Event( K_MOUSE1, false );
Android_AddMove( dx * (float)refState.width, dy * (float)refState.height );
#endif
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
return 0;
}
if( clgame.dllFuncs.pfnTouchEvent && clgame.dllFuncs.pfnTouchEvent( type, fingerID, x, y, dx, dy ) )
return true;
@@ -2048,35 +2026,65 @@ void Touch_GetMove( float *forward, float *side, float *yaw, float *pitch )
void Touch_KeyEvent( int key, int down )
{
int xi, yi;
float x, y;
static float lx, ly;
static int kidNamedFinger = -1;
touchEventType event;
float x, y;
int finger, xi, yi;
if( !CVAR_TO_BOOL(touch_emulate) )
if( !touch_emulate.value )
{
if( CVAR_TO_BOOL(touch_enable) )
if( touch_enable.value )
return;
if( !touch.clientonly )
return;
}
Platform_GetMousePos( &xi, &yi );
x = xi/SCR_W;
y = yi/SCR_H;
if( cls.key_dest == key_menu && down < 2 && key == K_MOUSE1 )
if( !key )
{
UI_MouseMove( xi, yi );
UI_KeyEvent( key, down );
if( kidNamedFinger < 0 )
return;
finger = kidNamedFinger;
event = event_motion;
}
else
{
finger = key == K_MOUSE1 ? 0 : 1;
if( down )
{
event = event_down;
kidNamedFinger = finger;
}
else
{
event = event_up;
kidNamedFinger = -1;
}
}
if( down == 1 )
Touch_ControlsEvent( event_down, key == K_MOUSE1?0:1, x, y, 0, 0 );
else
Touch_ControlsEvent( down? event_motion: event_up, key == K_MOUSE1?0:1, x, y, x-lx, y-ly );
lx = x, ly = y;
// don't deactivate mouse in game
// checking a case when mouse and touchscreen
// can be used simultaneously
Platform_SetCursorType( dc_arrow );
Platform_GetMousePos( &xi, &yi );
x = xi / SCR_W;
y = yi / SCR_H;
Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n",
event, x, y, x - lx, y - ly );
IN_TouchEvent( event, finger, x, y, x - lx, y - ly );
lx = x;
ly = y;
}
qboolean Touch_WantVisibleCursor( void )
{
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly;
}
void Touch_Shutdown( void )

View File

@@ -47,8 +47,6 @@ convar_t *cl_backspeed;
convar_t *look_filter;
convar_t *m_rawinput;
static qboolean s_bRawInput, s_bMouseGrab;
/*
================
IN_CollectInputDevices
@@ -63,7 +61,7 @@ uint IN_CollectInputDevices( void )
if( !m_ignore->value ) // no way to check is mouse connected, so use cvar only
ret |= INPUT_DEVICE_MOUSE;
if( CVAR_TO_BOOL(touch_enable) )
if( touch_enable.value )
ret |= INPUT_DEVICE_TOUCH;
if( Joy_IsActive() ) // connected or enabled
@@ -94,13 +92,13 @@ void IN_LockInputDevices( qboolean lock )
{
SetBits( m_ignore->flags, FCVAR_READ_ONLY );
SetBits( joy_enable->flags, FCVAR_READ_ONLY );
SetBits( touch_enable->flags, FCVAR_READ_ONLY );
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
}
else
{
ClearBits( m_ignore->flags, FCVAR_READ_ONLY );
ClearBits( joy_enable->flags, FCVAR_READ_ONLY );
ClearBits( touch_enable->flags, FCVAR_READ_ONLY );
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
}
}
@@ -173,7 +171,33 @@ Called when key_dest is changed
*/
void IN_ToggleClientMouse( int newstate, int oldstate )
{
if( newstate == oldstate ) return;
if( newstate == oldstate )
return;
// since SetCursorType controls cursor visibility
// execute it first, and then check mouse grab state
if( newstate == key_menu || newstate == key_console )
{
Platform_SetCursorType( dc_arrow );
#if XASH_ANDROID
Android_ShowMouse( true );
#endif
#if XASH_USE_EVDEV
Evdev_SetGrab( false );
#endif
}
else
{
Platform_SetCursorType( dc_none );
#if XASH_ANDROID
Android_ShowMouse( false );
#endif
#if XASH_USE_EVDEV
Evdev_SetGrab( true );
#endif
}
if( oldstate == key_game )
{
@@ -183,31 +207,14 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
{
IN_ActivateMouse();
}
if( ( newstate == key_menu || newstate == key_console || newstate == key_message ) && ( !CL_IsBackgroundMap() || CL_IsBackgroundDemo( )))
{
#if XASH_ANDROID
Android_ShowMouse( true );
#endif
#ifdef XASH_USE_EVDEV
Evdev_SetGrab( false );
#endif
}
else
{
#if XASH_ANDROID
Android_ShowMouse( false );
#endif
#ifdef XASH_USE_EVDEV
Evdev_SetGrab( true );
#endif
}
}
void IN_CheckMouseState( qboolean active )
{
static qboolean s_bRawInput, s_bMouseGrab;
#if XASH_WIN32
qboolean useRawInput = CVAR_TO_BOOL( m_rawinput ) && clgame.client_dll_uses_sdl || clgame.dllFuncs.pfnLookEvent;
qboolean useRawInput = ( CVAR_TO_BOOL( m_rawinput ) && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
#else
qboolean useRawInput = true; // always use SDL code
#endif
@@ -276,7 +283,8 @@ void IN_ActivateMouse( void )
return;
IN_CheckMouseState( true );
clgame.dllFuncs.IN_ActivateMouse();
if( clgame.dllFuncs.IN_ActivateMouse )
clgame.dllFuncs.IN_ActivateMouse();
in_mouseactive = true;
}
@@ -293,7 +301,8 @@ void IN_DeactivateMouse( void )
return;
IN_CheckMouseState( false );
clgame.dllFuncs.IN_DeactivateMouse();
if( clgame.dllFuncs.IN_DeactivateMouse )
clgame.dllFuncs.IN_DeactivateMouse();
in_mouseactive = false;
}
@@ -306,25 +315,25 @@ IN_MouseMove
*/
void IN_MouseMove( void )
{
POINT current_pos;
int x, y;
if( !in_mouseinitialized )
return;
if( touch_emulate.value )
{
// touch emulation overrides all input
Touch_KeyEvent( 0, 0 );
return;
}
// find mouse movement
Platform_GetMousePos( &current_pos.x, &current_pos.y );
Platform_GetMousePos( &x, &y );
VGui_MouseMove( current_pos.x, current_pos.y );
// HACKHACK: show cursor in UI, as mainui doesn't call
// platform-dependent SetCursor anymore
#if XASH_SDL
if( UI_IsVisible() )
SDL_ShowCursor( SDL_TRUE );
#endif
VGui_MouseMove( x, y );
// if the menu is visible, move the menu cursor
UI_MouseMove( current_pos.x, current_pos.y );
UI_MouseMove( x, y );
}
/*
@@ -334,8 +343,6 @@ IN_MouseEvent
*/
void IN_MouseEvent( int key, int down )
{
int i;
if( !in_mouseinitialized )
return;
@@ -343,10 +350,15 @@ void IN_MouseEvent( int key, int down )
SetBits( in_mstate, BIT( key ));
else ClearBits( in_mstate, BIT( key ));
if( cls.key_dest == key_game )
// touch emulation overrides all input
if( touch_emulate.value )
{
Touch_KeyEvent( K_MOUSE1 + key, down );
}
else if( cls.key_dest == key_game )
{
// perform button actions
VGui_KeyEvent( K_MOUSE1 + key, down );
VGui_MouseEvent( K_MOUSE1 + key, down );
// don't do Key_Event here
// client may override IN_MouseEvent
@@ -361,6 +373,23 @@ void IN_MouseEvent( int key, int down )
}
}
/*
==============
IN_MWheelEvent
direction is negative for wheel down, otherwise wheel up
==============
*/
void IN_MWheelEvent( int y )
{
int b = y > 0 ? K_MWHEELUP : K_MWHEELDOWN;
VGui_MWheelEvent( y );
Key_Event( b, true );
Key_Event( b, false );
}
/*
===========
IN_Shutdown
@@ -370,7 +399,7 @@ void IN_Shutdown( void )
{
IN_DeactivateMouse( );
#ifdef XASH_USE_EVDEV
#if XASH_USE_EVDEV
Evdev_Shutdown();
#endif
@@ -397,7 +426,7 @@ void IN_Init( void )
Touch_Init();
#ifdef XASH_USE_EVDEV
#if XASH_USE_EVDEV
Evdev_Init();
#endif
}
@@ -503,7 +532,7 @@ static void IN_CollectInput( float *forward, float *side, float *pitch, float *y
*pitch += y * m_pitch->value;
*yaw -= x * m_yaw->value;
#ifdef XASH_USE_EVDEV
#if XASH_USE_EVDEV
IN_EvdevMove( yaw, pitch );
#endif
}
@@ -561,7 +590,7 @@ void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
void IN_Commands( void )
{
#ifdef XASH_USE_EVDEV
#if XASH_USE_EVDEV
IN_EvdevFrame();
#endif

View File

@@ -34,6 +34,7 @@ void IN_Init( void );
void Host_InputFrame( void );
void IN_Shutdown( void );
void IN_MouseEvent( int key, int down );
void IN_MWheelEvent( int direction );
void IN_ActivateMouse( void );
void IN_DeactivateMouse( void );
void IN_MouseSavePos( void );
@@ -57,8 +58,8 @@ typedef enum
event_motion
} touchEventType;
extern convar_t *touch_enable;
extern convar_t *touch_emulate;
extern convar_t touch_enable;
extern convar_t touch_emulate;
void Touch_Draw( void );
void Touch_SetClientOnly( byte state );
@@ -73,6 +74,7 @@ void Touch_GetMove( float * forward, float *side, float *yaw, float *pitch );
void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void );
//
// in_joy.c

View File

@@ -104,9 +104,9 @@ keyname_t keynames[] =
{"B_BUTTON", K_B_BUTTON, "+use"},
{"X_BUTTON", K_X_BUTTON, "+reload"},
{"Y_BUTTON", K_Y_BUTTON, "impulse 100"}, // Flashlight
{"BACK", K_BACK_BUTTON, "cancelselect"}, // Menu
{"BACK", K_BACK_BUTTON, "pause"}, // Menu
{"MODE", K_MODE_BUTTON, ""},
{"START", K_START_BUTTON, "pause"},
{"START", K_START_BUTTON, "escape"},
{"STICK1", K_LSTICK, "+speed"},
{"STICK2", K_RSTICK, "+duck"},
{"L1_BUTTON", K_L1_BUTTON, "+duck"},
@@ -123,13 +123,13 @@ keyname_t keynames[] =
{"JOY4" , K_JOY4 , ""},
{"C_BUTTON", K_C_BUTTON, ""},
{"Z_BUTTON", K_Z_BUTTON, ""},
{"AUX20", K_AUX20, ""}, // generic
{"AUX21", K_AUX21, ""},
{"AUX22", K_AUX22, ""},
{"AUX23", K_AUX23, ""},
{"AUX24", K_AUX24, ""},
{"AUX25", K_AUX25, ""},
{"AUX26", K_AUX26, ""},
{"MISC_BUTTON", K_MISC_BUTTON, ""},
{"PADDLE1", K_PADDLE1_BUTTON, ""},
{"PADDLE2", K_PADDLE2_BUTTON, ""},
{"PADDLE3", K_PADDLE3_BUTTON, ""},
{"PADDLE4", K_PADDLE4_BUTTON, ""},
{"TOUCHPAD", K_TOUCHPAD, ""},
{"AUX26", K_AUX26, ""}, // generic
{"AUX27", K_AUX27, ""},
{"AUX28", K_AUX28, ""},
{"AUX29", K_AUX29, ""},
@@ -159,18 +159,6 @@ int GAME_EXPORT Key_IsDown( int keynum )
return keys[keynum].down;
}
/*
===================
Key_GetBind
===================
*/
const char *Key_IsBind( int keynum )
{
if( keynum == -1 || !keys[keynum].binding )
return NULL;
return keys[keynum].binding;
}
/*
===================
Key_StringToKeynum
@@ -374,7 +362,7 @@ void Key_Unbindall_f( void )
{
int i;
for( i = 0; i < 256; i++ )
for( i = 0; i < ARRAYSIZE( keys ); i++ )
{
if( keys[i].binding )
Key_SetBinding( i, "" );
@@ -382,6 +370,7 @@ void Key_Unbindall_f( void )
// set some defaults
Key_SetBinding( K_ESCAPE, "escape" );
Key_SetBinding( K_START_BUTTON, "escape" );
}
/*
@@ -395,7 +384,7 @@ void Key_Reset_f( void )
int i;
// clear all keys first
for( i = 0; i < 256; i++ )
for( i = 0; i < ARRAYSIZE( keys ); i++ )
{
if( keys[i].binding )
Key_SetBinding( i, "" );
@@ -445,8 +434,8 @@ void Key_Bind_f( void )
for( i = 2; i < c; i++ )
{
Q_strcat( cmd, Cmd_Argv( i ));
if( i != ( c - 1 )) Q_strcat( cmd, " " );
Q_strncat( cmd, Cmd_Argv( i ), sizeof( cmd ));
if( i != ( c - 1 )) Q_strncat( cmd, " ", sizeof( cmd ));
}
Key_SetBinding( b, cmd );
@@ -552,8 +541,8 @@ void Key_AddKeyCommands( int key, const char *kb, qboolean down )
if( button[0] == '+' )
{
// button commands add keynum as a parm
if( down ) Q_sprintf( cmd, "%s %i\n", button, key );
else Q_sprintf( cmd, "-%s %i\n", button + 1, key );
if( down ) Q_snprintf( cmd, sizeof( cmd ), "%s %i\n", button, key );
else Q_snprintf( cmd, sizeof( cmd ), "-%s %i\n", button + 1, key );
Cbuf_AddText( cmd );
}
else if( down )
@@ -712,7 +701,6 @@ void GAME_EXPORT Key_Event( int key, int down )
}
VGui_KeyEvent( key, down );
Touch_KeyEvent( key, down );
// console key is hardcoded, so the user can never unbind it
if( key == '`' || key == '~' )
@@ -842,7 +830,9 @@ void GAME_EXPORT Key_SetKeyDest( int key_dest )
cls.key_dest = key_menu;
break;
case key_console:
#if !XASH_NSWITCH && !XASH_PSVITA // if we don't disable this, pops up the keyboard during load
Key_EnableTextInput( true, false );
#endif
cls.key_dest = key_console;
break;
case key_message:
@@ -1149,7 +1139,7 @@ Draw button with symbol on it
*/
static void OSK_DrawSymbolButton( int symb, float x, float y, float width, float height )
{
char str[] = {symb & 255, 0};
cl_font_t *font = Con_GetCurFont();
byte color[] = { 255, 255, 255, 255 };
int x1 = x * refState.width,
y1 = y * refState.height,
@@ -1157,14 +1147,15 @@ static void OSK_DrawSymbolButton( int symb, float x, float y, float width, float
h = height * refState.height;
if( symb == osk.curbutton.val )
{
ref.dllFuncs.FillRGBABlend( x1, y1, w, h, 255, 160, 0, 100 );
}
if( !symb || symb == ' ' || (symb >= OSK_TAB && symb < OSK_SPECKEY_LAST ) )
return;
Con_DrawCharacter( x1 + 1, y1, symb, color );
CL_DrawCharacter(
x1 + width * 0.4 * refState.width,
y1 + height * 0.4 * refState.height,
symb, color, font, 0 );
}
/*
@@ -1178,7 +1169,11 @@ static void OSK_DrawSpecialButton( const char *name, float x, float y, float wid
{
byte color[] = { 0, 255, 0, 255 };
Con_DrawString( x * refState.width, y * refState.height, name, color );
Con_DrawString(
x * refState.width + width * 0.4 * refState.width,
y * refState.height + height * 0.4 * refState.height,
name,
color );
}

View File

@@ -55,12 +55,11 @@ void GL_RenderFrame( const ref_viewpass_t *rvp )
VectorCopy( rvp->vieworigin, refState.vieworg );
VectorCopy( rvp->viewangles, refState.viewangles );
AngleVectors( refState.viewangles, refState.vforward, refState.vright, refState.vup );
ref.dllFuncs.GL_RenderFrame( rvp );
}
static int pfnEngineGetParm( int parm, int arg )
static intptr_t pfnEngineGetParm( int parm, int arg )
{
return CL_RenderGetParm( parm, arg, false ); // prevent recursion
}
@@ -75,16 +74,6 @@ static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
clgame.dllFuncs.pfnStudioEvent( event, e );
}
static efrag_t* pfnGetEfragsFreeList( void )
{
return clgame.free_efrags;
}
static void pfnSetEfragsFreeList( efrag_t *list )
{
clgame.free_efrags = list;
}
static model_t *pfnGetDefaultSprite( enum ref_defaultsprite_e spr )
{
switch( spr )
@@ -151,7 +140,7 @@ static player_info_t *pfnPlayerInfo( int index )
if( index == -1 ) // special index for menu
return &gameui.playerinfo;
if( index < 0 || index > cl.maxclients )
if( index < 0 || index >= cl.maxclients )
return NULL;
return &cl.players[index];
@@ -225,7 +214,7 @@ static qboolean R_DoResetGamma( void )
static qboolean R_Init_Video_( const int type )
{
host.apply_opengl_config = true;
Cbuf_AddText( va( "exec %s.cfg", ref.dllFuncs.R_GetConfigName()));
Cbuf_AddTextf( "exec %s.cfg", ref.dllFuncs.R_GetConfigName());
Cbuf_Execute();
host.apply_opengl_config = false;
@@ -279,9 +268,6 @@ static ref_api_t gEngfuncs =
Mod_PointInLeaf,
Mod_CreatePolygonsForHull,
R_StudioSlerpBones,
R_StudioCalcBoneQuaternion,
R_StudioCalcBonePosition,
R_StudioGetAnim,
pfnStudioEvent,
@@ -330,14 +316,10 @@ static ref_api_t gEngfuncs =
_Mem_Realloc,
_Mem_Free,
_COM_LoadLibrary,
COM_LoadLibrary,
COM_FreeLibrary,
COM_GetProcAddress,
FS_LoadFile,
FS_FileExists,
FS_AllowDirectPaths,
R_Init_Video_,
R_Free_Video,
@@ -363,7 +345,7 @@ static ref_api_t gEngfuncs =
pfnGetPhysent,
pfnTraceSurface,
PM_TraceLine,
PM_CL_TraceLine,
CL_VisTraceLine,
CL_TraceLine,
pfnGetMoveVars,
@@ -383,7 +365,9 @@ static ref_api_t gEngfuncs =
pfnDrawNormalTriangles,
pfnDrawTransparentTriangles,
&clgame.drawFuncs
&clgame.drawFuncs,
&g_fsapi,
};
static void R_UnloadProgs( void )
@@ -528,7 +512,7 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
else
{
// full path
Q_strcpy( dest, opt );
Q_strncpy( dest, opt, size );
}
}
@@ -571,66 +555,62 @@ static void SetWidthAndHeightFromCommandLine( void )
static void SetFullscreenModeFromCommandLine( void )
{
#if !XASH_MOBILE_PLATFORM
if ( Sys_CheckParm("-fullscreen") )
if( Sys_CheckParm( "-fullscreen" ))
{
Cvar_Set( "fullscreen", "1" );
}
else if ( Sys_CheckParm( "-windowed" ) )
else if( Sys_CheckParm( "-windowed" ))
{
Cvar_Set( "fullscreen", "0" );
}
#endif
}
void R_CollectRendererNames( void )
static void R_CollectRendererNames( void )
{
const char *renderers[] = DEFAULT_RENDERERS;
int i, cur;
cur = 0;
for( i = 0; i < DEFAULT_RENDERERS_LEN; i++ )
// ordering is important!
static const char *shortNames[] =
{
string temp;
void *dll, *pfn;
#if XASH_REF_GL_ENABLED
"gl",
#endif
#if XASH_REF_NANOGL_ENABLED
"gles1",
#endif
#if XASH_REF_GLWES_ENABLED
"gles2",
#endif
#if XASH_REF_GL4ES_ENABLED
"gl4es",
#endif
#if XASH_REF_SOFT_ENABLED
"soft",
#endif
};
R_GetRendererName( temp, sizeof( temp ), renderers[i] );
// ordering is important here too!
static const char *readableNames[ARRAYSIZE( shortNames )] =
{
#if XASH_REF_GL_ENABLED
"OpenGL",
#endif
#if XASH_REF_NANOGL_ENABLED
"GLES1 (NanoGL)",
#endif
#if XASH_REF_GLWES_ENABLED
"GLES2 (gl-wes-v2)",
#endif
#if XASH_REF_GL4ES_ENABLED
"GL4ES",
#endif
#if XASH_REF_SOFT_ENABLED
"Software",
#endif
};
dll = COM_LoadLibrary( temp, false, true );
if( !dll )
{
Con_Reportf( "R_CollectRendererNames: can't load library %s: %s\n", temp, COM_GetLibraryError() );
continue;
}
pfn = COM_GetProcAddress( dll, GET_REF_API );
if( !pfn )
{
Con_Reportf( "R_CollectRendererNames: can't find API entry point in %s\n", temp );
COM_FreeLibrary( dll );
continue;
}
Q_strncpy( ref.shortNames[cur], renderers[i], sizeof( ref.shortNames[cur] ));
pfn = COM_GetProcAddress( dll, GET_REF_HUMANREADABLE_NAME );
if( !pfn ) // just in case
{
Con_Reportf( "R_CollectRendererNames: can't find GetHumanReadableName export in %s\n", temp );
Q_strncpy( ref.readableNames[cur], renderers[i], sizeof( ref.readableNames[cur] ));
}
else
{
REF_HUMANREADABLE_NAME GetHumanReadableName = (REF_HUMANREADABLE_NAME)pfn;
GetHumanReadableName( ref.readableNames[cur], sizeof( ref.readableNames[cur] ));
}
Con_Printf( "Found renderer %s: %s\n", ref.shortNames[cur], ref.readableNames[cur] );
cur++;
COM_FreeLibrary( dll );
}
ref.numRenderers = cur;
ref.numRenderers = ARRAYSIZE( shortNames );
ref.shortNames = shortNames;
ref.readableNames = readableNames;
}
qboolean R_Init( void )
@@ -645,7 +625,7 @@ qboolean R_Init( void )
gl_msaa_samples = Cvar_Get( "gl_msaa_samples", "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" );
gl_clear = Cvar_Get( "gl_clear", "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
r_showtree = Cvar_Get( "r_showtree", "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
r_refdll = Cvar_Get( "r_refdll", "", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "choose renderer implementation, if supported" );
r_refdll = Cvar_Get( "r_refdll", "", FCVAR_RENDERINFO, "choose renderer implementation, if supported" );
// cvars that are expected to exist
Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
@@ -684,30 +664,28 @@ qboolean R_Init( void )
// 1. Command line `-ref` argument.
// 2. `ref_dll` cvar.
// 3. Detected renderers in `DEFAULT_RENDERERS` order.
requested[0] = '\0';
if( !Sys_GetParmFromCmdLine( "-ref", requested ) && COM_CheckString( r_refdll->string ) )
// r_refdll is set to empty by default, so we can change hardcoded defaults just in case
Q_strncpy( requested, r_refdll->string, sizeof( requested ) );
requested[0] = 0;
if ( requested[0] )
if( !success && Sys_GetParmFromCmdLine( "-ref", requested ))
success = R_LoadRenderer( requested );
if( !success && COM_CheckString( r_refdll->string ))
{
Q_strncpy( requested, r_refdll->string, sizeof( requested ));
success = R_LoadRenderer( requested );
}
if( !success )
{
int i;
// cycle through renderers that we collected in CollectRendererNames
for( i = 0; i < ref.numRenderers; i++ )
for( i = 0; i < ref.numRenderers && !success; i++ )
{
// skip renderer that was requested but failed to load
if( !Q_strcmp( requested, ref.shortNames[i] ) )
if( !Q_strcmp( requested, ref.shortNames[i] ))
continue;
success = R_LoadRenderer( ref.shortNames[i] );
// yay, found working one
if( success )
break;
}
}

View File

@@ -27,9 +27,10 @@ struct ref_state_s
HINSTANCE hInstance;
ref_interface_t dllFuncs;
// depends on build configuration
int numRenderers;
string shortNames[DEFAULT_RENDERERS_LEN];
string readableNames[DEFAULT_RENDERERS_LEN];
const char **shortNames;
const char **readableNames;
};
extern struct ref_state_s ref;

View File

@@ -14,6 +14,7 @@ GNU General Public License for more details.
*/
#include "common.h"
#include "client.h"
#include "sound.h"
// during registration it is possible to have more sounds
@@ -28,7 +29,6 @@ static sfx_t s_knownSfx[MAX_SFX];
static sfx_t *s_sfxHashList[MAX_SFX_HASH];
static string s_sentenceImmediateName; // keep dummy sentence name
qboolean s_registering = false;
int s_registration_sequence = 0;
/*
=================
@@ -54,7 +54,7 @@ void S_SoundList_f( void )
if( sc->loopStart >= 0 ) Con_Printf( "L" );
else Con_Printf( " " );
if( sfx->name[0] == '*' )
if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ))
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
totalSfx++;
@@ -199,7 +199,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
*pfInCache = ( sfx->cache != NULL ) ? true : false;
}
// prolonge registration
sfx->servercount = s_registration_sequence;
sfx->servercount = cl.servercount;
return sfx;
}
}
@@ -219,7 +219,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
memset( sfx, 0, sizeof( *sfx ));
if( pfInCache ) *pfInCache = false;
Q_strncpy( sfx->name, name, MAX_STRING );
sfx->servercount = s_registration_sequence;
sfx->servercount = cl.servercount;
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
// link it in
@@ -273,7 +273,6 @@ void S_BeginRegistration( void )
{
int i;
s_registration_sequence++;
snd_ambient = false;
// check for automatic ambient sounds
@@ -309,7 +308,7 @@ void S_EndRegistration( void )
if( !sfx->name[0] || !Q_stricmp( sfx->name, "*default" ))
continue; // don't release default sound
if( sfx->servercount != s_registration_sequence )
if( sfx->servercount != cl.servercount )
S_FreeSound( sfx ); // don't need this sound
}
@@ -349,7 +348,7 @@ sound_t S_RegisterSound( const char *name )
sfx = S_FindName( name, NULL );
if( !sfx ) return -1;
sfx->servercount = s_registration_sequence;
sfx->servercount = cl.servercount;
if( !s_registering ) S_LoadSound( sfx );
return sfx - s_knownSfx;

View File

@@ -159,7 +159,7 @@ void S_UpdateSoundFade( void )
}
// spline it.
f = SimpleSpline( f );
f = -( cos( M_PI * f ) - 1 ) / 2;
f = bound( 0.0f, f, 1.0f );
soundfade.percent = soundfade.initial_percent * f;
@@ -197,6 +197,65 @@ qboolean SND_FStreamIsPlaying( sfx_t *sfx )
return false;
}
/*
=================
SND_GetChannelTimeLeft
TODO: this function needs to be removed after whole sound subsystem rewrite
=================
*/
static int SND_GetChannelTimeLeft( const channel_t *ch )
{
int remaining;
if( ch->pMixer.finished || !ch->sfx || !ch->sfx->cache )
return 0;
if( ch->isSentence ) // sentences are special, count all remaining words
{
int i;
if( !ch->currentWord )
return 0;
// current word
remaining = ch->currentWord->forcedEndSample - ch->currentWord->sample;
// here we count all remaining words, stopping if no sfx or sound file is available
// see VOX_LoadWord
for( i = ch->wordIndex + 1; i < ARRAYSIZE( ch->words ); i++ )
{
wavdata_t *sc;
int end;
// don't continue with broken sentences
if( !ch->words[i].sfx )
break;
if( !( sc = S_LoadSound( ch->words[i].sfx )))
break;
end = ch->words[i].end;
if( end )
remaining += sc->samples * 0.01f * end;
else remaining += sc->samples;
}
}
else
{
int curpos;
int samples;
// handle position looping
samples = ch->sfx->cache->samples;
curpos = S_ConvertLoopedPosition( ch->sfx->cache, ch->pMixer.sample, ch->use_loop );
remaining = bound( 0, samples - curpos, samples );
}
return remaining;
}
/*
=================
SND_PickDynamicChannel
@@ -246,11 +305,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
continue;
// try to pick the sound with the least amount of data left to play
timeleft = 0;
if( ch->sfx )
{
timeleft = 1; // ch->end - paintedtime
}
timeleft = SND_GetChannelTimeLeft( ch );
if( timeleft < life_left )
{
@@ -533,8 +588,6 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
// spatialize
memset( target_chan, 0, sizeof( *target_chan ));
pitch *= (sys_timescale.value + 1) / 2;
VectorCopy( pos, target_chan->origin );
target_chan->staticsound = ( ent == 0 ) ? true : false;
target_chan->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
@@ -1129,7 +1182,7 @@ static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend,
S_RawEntSamples
===================
*/
static void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
{
rawchan_t *ch;
@@ -1239,36 +1292,6 @@ void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float sy
}
}
/*
===================
S_GetRawSamplesLength
===================
*/
uint S_GetRawSamplesLength( int entnum )
{
rawchan_t *ch;
if( !( ch = S_FindRawChannel( entnum, false )))
return 0;
return ch->s_rawend <= paintedtime ? 0 : (float)(ch->s_rawend - paintedtime) * DMA_MSEC_PER_SAMPLE;
}
/*
===================
S_ClearRawChannel
===================
*/
void S_ClearRawChannel( int entnum )
{
rawchan_t *ch;
if( !( ch = S_FindRawChannel( entnum, false )))
return;
ch->s_rawend = 0;
}
/*
===================
S_FreeIdleRawChannels
@@ -1288,6 +1311,9 @@ static void S_FreeIdleRawChannels( void )
if( ch->s_rawend >= paintedtime )
continue;
if ( ch->entnum > 0 )
SND_ForceCloseMouth( ch->entnum );
if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
{
@@ -1786,8 +1812,12 @@ void S_Music_f( void )
for( i = 0; i < 2; i++ )
{
const char *intro_path = va( "media/%s.%s", intro, ext[i] );
const char *main_path = va( "media/%s.%s", main, ext[i] );
char intro_path[MAX_VA_STRING];
char main_path[MAX_VA_STRING];
char track_path[MAX_VA_STRING];
Q_snprintf( intro_path, sizeof( intro_path ), "media/%s.%s", intro, ext[i] );
Q_snprintf( main_path, sizeof( main_path ), "media/%s.%s", main, ext[i] );
if( FS_FileExists( intro_path, false ) && FS_FileExists( main_path, false ))
{
@@ -1795,7 +1825,10 @@ void S_Music_f( void )
S_StartBackgroundTrack( intro, main, 0, false );
break;
}
else if( FS_FileExists( va( "media/%s.%s", track, ext[i] ), false ))
Q_snprintf( track_path, sizeof( track_path ), "media/%s.%s", track, ext[i] );
if( FS_FileExists( track_path, false ))
{
// single non-looped theme
S_StartBackgroundTrack( track, NULL, 0, false );
@@ -1850,7 +1883,7 @@ S_SoundInfo_f
*/
void S_SoundInfo_f( void )
{
Con_Printf( "Audio: DirectSound\n" );
Con_Printf( "Audio backend: %s\n", dma.backendName );
Con_Printf( "%5d channel(s)\n", 2 );
Con_Printf( "%5d samples\n", dma.samples );
Con_Printf( "%5d bits/sample\n", 16 );
@@ -1860,6 +1893,33 @@ void S_SoundInfo_f( void )
S_PrintBackgroundTrackState ();
}
/*
=================
S_VoiceRecordStart_f
=================
*/
void S_VoiceRecordStart_f( void )
{
if( cls.state != ca_active || cls.legacymode )
return;
Voice_RecordStart();
}
/*
=================
S_VoiceRecordStop_f
=================
*/
void S_VoiceRecordStop_f( void )
{
if( cls.state != ca_active || !Voice_IsRecording() )
return;
CL_AddVoiceToDatagram();
Voice_RecordStop();
}
/*
================
S_Init
@@ -1894,11 +1954,12 @@ qboolean S_Init( void )
Cmd_AddCommand( "soundlist", S_SoundList_f, "display loaded sounds" );
Cmd_AddCommand( "s_info", S_SoundInfo_f, "print sound system information" );
Cmd_AddCommand( "s_fade", S_SoundFade_f, "fade all sounds then stop all" );
Cmd_AddCommand( "+voicerecord", Cmd_Null_f, "start voice recording (non-implemented)" );
Cmd_AddCommand( "-voicerecord", Cmd_Null_f, "stop voice recording (non-implemented)" );
Cmd_AddCommand( "+voicerecord", S_VoiceRecordStart_f, "start voice recording" );
Cmd_AddCommand( "-voicerecord", S_VoiceRecordStop_f, "stop voice recording" );
Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" );
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
dma.backendName = "None";
if( !SNDDMA_Init( ) )
{
Con_Printf( "Audio: sound system can't be initialized\n" );

View File

@@ -117,13 +117,6 @@ _inline void MIX_ActivatePaintbuffer( int ipaintbuffer )
paintbuffers[ipaintbuffer].factive = true;
}
// don't mix into this paintbuffer
_inline void MIX_DeactivatePaintbuffer( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
paintbuffers[ipaintbuffer].factive = false;
}
_inline void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
@@ -169,12 +162,6 @@ _inline void MIX_ResetPaintbufferFilterCounters( void )
paintbuffers[i].ifilter = FILTERTYPE_NONE;
}
_inline void MIX_ResetPaintbufferFilterCounter( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
paintbuffers[ipaintbuffer].ifilter = 0;
}
// return pointer to front paintbuffer pbuf, given index
_inline portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
{
@@ -619,7 +606,9 @@ void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate )
ch->pitch = VOX_ModifyPitch( ch, ch->basePitch * 0.01f );
else ch->pitch = ch->basePitch * 0.01f;
if( CL_GetEntityByIndex( ch->entnum ) && ( ch->entchannel == CHAN_VOICE ))
ch->pitch *= ( sys_timescale.value + 1 ) / 2;
if( CL_GetEntityByIndex( ch->entnum ) && ( ch->entchannel == CHAN_VOICE || ch->entchannel == CHAN_STREAM ))
{
if( pSource->width == 1 )
SND_MoveMouth8( ch, pSource, sampleCount );
@@ -895,43 +884,13 @@ void S_MixUpsample( int sampleCount, int filtertype )
ppaint->ifilter++;
}
void MIX_MixStreamBuffer( int end )
{
portable_samplepair_t *pbuf;
rawchan_t *ch;
pbuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
ch = S_FindRawChannel( S_RAW_SOUND_BACKGROUNDTRACK, false );
// clear the paint buffer
if( s_listener.paused || !ch || ch->s_rawend < paintedtime )
{
memset( pbuf, 0, (end - paintedtime) * sizeof( portable_samplepair_t ));
}
else
{
int i, stop;
// copy from the streaming sound source
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
for( i = paintedtime; i < stop; i++ )
{
pbuf[i-paintedtime].left = ( ch->rawsamples[i & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
pbuf[i-paintedtime].right = ( ch->rawsamples[i & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
}
for( ; i < end; i++ )
pbuf[i-paintedtime].left = pbuf[i-paintedtime].right = 0;
}
}
void MIX_MixRawSamplesBuffer( int end )
{
portable_samplepair_t *pbuf;
portable_samplepair_t *pbuf, *roombuf, *streambuf;
uint i, j, stop;
pbuf = MIX_GetCurrentPaintbufferPtr()->pbuf;
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
if( s_listener.paused ) return;
@@ -939,16 +898,19 @@ void MIX_MixRawSamplesBuffer( int end )
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
// copy from the streaming sound source
rawchan_t *ch = raw_channels[i];
rawchan_t *ch = raw_channels[i];
qboolean stream;
// background track should be mixing into another buffer
if( !ch || ch->entnum == S_RAW_SOUND_BACKGROUNDTRACK )
if( !ch )
continue;
// not audible
if( !ch->leftvol && !ch->rightvol )
continue;
stream = ch->entnum == S_RAW_SOUND_BACKGROUNDTRACK || CL_IsPlayerIndex( ch->entnum );
pbuf = stream ? streambuf : roombuf;
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
for( j = paintedtime; j < stop; j++ )
@@ -956,6 +918,9 @@ void MIX_MixRawSamplesBuffer( int end )
pbuf[j-paintedtime].left += ( ch->rawsamples[j & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
pbuf[j-paintedtime].right += ( ch->rawsamples[j & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
}
if( ch->entnum > 0 )
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
}
}
@@ -965,9 +930,6 @@ void MIX_MixRawSamplesBuffer( int end )
// caller also remixes all into final IPAINTBUFFER output.
void MIX_UpsampleAllPaintbuffers( int end, int count )
{
// process stream buffer
MIX_MixStreamBuffer( end );
// 11khz sounds are mixed into 3 buffers based on distance from listener, and facing direction
// These buffers are facing, facingaway, room
// These 3 mixed buffers are then each upsampled to 22khz.
@@ -1009,7 +971,6 @@ void MIX_UpsampleAllPaintbuffers( int end, int count )
#endif
// mix raw samples from the video streams
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
MIX_MixRawSamplesBuffer( end );
MIX_DeactivateAllPaintbuffers();

View File

@@ -24,17 +24,7 @@ void SND_InitMouth( int entnum, int entchannel )
{
if(( entchannel == CHAN_VOICE || entchannel == CHAN_STREAM ) && entnum > 0 )
{
cl_entity_t *clientEntity;
// init mouth movement vars
clientEntity = CL_GetEntityByIndex( entnum );
if( clientEntity )
{
clientEntity->mouth.mouthopen = 0;
clientEntity->mouth.sndcount = 0;
clientEntity->mouth.sndavg = 0;
}
SND_ForceInitMouth( entnum );
}
}
@@ -42,15 +32,7 @@ void SND_CloseMouth( channel_t *ch )
{
if( ch->entchannel == CHAN_VOICE || ch->entchannel == CHAN_STREAM )
{
cl_entity_t *clientEntity;
clientEntity = CL_GetEntityByIndex( ch->entnum );
if( clientEntity )
{
// shut mouth
clientEntity->mouth.mouthopen = 0;
}
SND_ForceCloseMouth( ch->entnum );
}
}
@@ -150,3 +132,68 @@ void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count )
pMouth->sndcount = 0;
}
}
void SND_ForceInitMouth( int entnum )
{
cl_entity_t *clientEntity;
clientEntity = CL_GetEntityByIndex( entnum );
if( clientEntity )
{
clientEntity->mouth.mouthopen = 0;
clientEntity->mouth.sndavg = 0;
clientEntity->mouth.sndcount = 0;
}
}
void SND_ForceCloseMouth( int entnum )
{
cl_entity_t *clientEntity;
clientEntity = CL_GetEntityByIndex( entnum );
if( clientEntity )
clientEntity->mouth.mouthopen = 0;
}
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count )
{
cl_entity_t *clientEntity;
mouth_t *pMouth = NULL;
int savg, data;
int scount = 0;
uint i;
clientEntity = CL_GetEntityByIndex( ch->entnum );
if( !clientEntity ) return;
pMouth = &clientEntity->mouth;
if( pData == NULL )
return;
i = 0;
scount = pMouth->sndcount;
savg = 0;
while ( i < count && scount < CAVGSAMPLES )
{
data = pData[i].left; // mono sound anyway
data = ( bound( -32767, data, 0x7ffe ) >> 8 );
savg += abs( data );
i += 80 + ( (byte)data & 0x1F );
scount++;
}
pMouth->sndavg += savg;
pMouth->sndcount = (byte)scount;
if ( pMouth->sndcount >= CAVGSAMPLES )
{
pMouth->mouthopen = pMouth->sndavg / CAVGSAMPLES;
pMouth->sndavg = 0;
pMouth->sndcount = 0;
}
}

View File

@@ -95,7 +95,7 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, int
else Q_strncpy( s_bgTrack.loopName, mainTrack, sizeof( s_bgTrack.loopName ));
// open stream
s_bgTrack.stream = FS_OpenStream( va( "media/%s", introTrack ));
s_bgTrack.stream = FS_OpenStream( introTrack );
Q_strncpy( s_bgTrack.current, introTrack, sizeof( s_bgTrack.current ));
memset( &musicfade, 0, sizeof( musicfade )); // clear any soundfade
s_bgTrack.source = cls.key_dest;
@@ -242,7 +242,7 @@ void S_StreamBackgroundTrack( void )
if( s_bgTrack.loopName[0] )
{
FS_FreeStream( s_bgTrack.stream );
s_bgTrack.stream = FS_OpenStream( va( "media/%s", s_bgTrack.loopName ));
s_bgTrack.stream = FS_OpenStream( s_bgTrack.loopName );
Q_strncpy( s_bgTrack.current, s_bgTrack.loopName, sizeof( s_bgTrack.current ));
if( !s_bgTrack.stream ) return;

View File

@@ -142,7 +142,7 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
if( !p )
{
Q_strcpy( szpath, "vox/" );
Q_strncpy( szpath, "vox/", nsize );
return psz;
}
@@ -176,6 +176,7 @@ static const char *VOX_LookupString( const char *pszin )
i = Q_atoi( pszin + 1 );
if(( sentenceEntry = Sequence_GetSentenceByIndex( i )))
return sentenceEntry->data;
return NULL;
}
else
{

View File

@@ -113,10 +113,11 @@ typedef struct snd_format_s
typedef struct
{
snd_format_t format;
int samples; // mono samples in buffer
int samplepos; // in mono samples
byte *buffer;
int samples; // mono samples in buffer
int samplepos; // in mono samples
byte *buffer;
qboolean initialized; // sound engine is active
const char *backendName;
} dma_t;
#include "vox.h"
@@ -202,7 +203,7 @@ typedef struct
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 16
#define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 8192
extern sound_t ambient_sfx[NUM_AMBIENTS];
@@ -271,11 +272,10 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
sfx_t *S_GetSfxByHandle( sound_t handle );
rawchan_t *S_FindRawChannel( int entnum, qboolean create );
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol );
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
void S_StopSound( int entnum, int channel, const char *soundname );
void S_UpdateFrame( struct ref_viewpass_s *rvp );
uint S_GetRawSamplesLength( int entnum );
void S_ClearRawChannel( int entnum );
void S_StopAllSounds( qboolean ambient );
void S_FreeSounds( void );
@@ -283,9 +283,12 @@ void S_FreeSounds( void );
// s_mouth.c
//
void SND_InitMouth( int entnum, int entchannel );
void SND_ForceInitMouth( int entnum );
void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count );
void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count );
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count );
void SND_CloseMouth( channel_t *ch );
void SND_ForceCloseMouth( int entnum );
//
// s_stream.c
@@ -301,6 +304,7 @@ void S_FadeMusicVolume( float fadePercent );
//
int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample );
int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample );
int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean use_loop );
int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int sampleCount, qboolean use_loop );
void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition );
void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition );

View File

@@ -218,6 +218,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
client_textmessage_t textMessages[MAX_MESSAGES];
int i, nameHeapSize, textHeapSize, messageSize, nameOffset;
int messageCount, lastNamePos;
size_t textHeapSizeRemaining;
lastNamePos = 0;
lineNumber = 0;
@@ -252,7 +253,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
Con_Reportf( "TextMessage: unexpected '}' found, line %d\n", lineNumber );
return;
}
Q_strcpy( currentName, trim );
Q_strncpy( currentName, trim, sizeof( currentName ));
break;
case MSGFILE_TEXT:
if( IsEndOfText( trim ))
@@ -266,7 +267,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
return;
}
Q_strcpy( nameHeap + lastNamePos, currentName );
Q_strncpy( nameHeap + lastNamePos, currentName, sizeof( nameHeap ) - lastNamePos );
// terminate text in-place in the memory file
// (it's temporary memory that will be deleted)
@@ -329,15 +330,20 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
// copy text & fixup pointers
textHeapSizeRemaining = textHeapSize;
pCurrentText = pNameHeap + nameHeapSize;
for( i = 0; i < messageCount; i++ )
{
size_t currentTextSize = Q_strlen( clgame.titles[i].pMessage ) + 1;
clgame.titles[i].pName = pNameHeap; // adjust name pointer (parallel buffer)
Q_strcpy( pCurrentText, clgame.titles[i].pMessage ); // copy text over
Q_strncpy( pCurrentText, clgame.titles[i].pMessage, textHeapSizeRemaining ); // copy text over
clgame.titles[i].pMessage = pCurrentText;
pNameHeap += Q_strlen( pNameHeap ) + 1;
pCurrentText += Q_strlen( pCurrentText ) + 1;
pCurrentText += currentTextSize;
textHeapSizeRemaining -= currentTextSize;
}
if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize ))

View File

@@ -23,54 +23,77 @@ GNU General Public License for more details.
#include "input.h"
#include "platform/platform.h"
static enum VGUI_KeyCode s_pVirtualKeyTrans[256];
static VGUI_DefaultCursor s_currentCursor;
static HINSTANCE s_pVGuiSupport; // vgui_support library
static convar_t *vgui_utf8 = NULL;
CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
void GAME_EXPORT *VGUI_EngineMalloc(size_t size)
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size );
static void GAME_EXPORT VGUI_GetMousePos( int *, int * );
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor );
static byte GAME_EXPORT VGUI_GetColor( int, int );
static int GAME_EXPORT VGUI_UtfProcessChar( int in );
static qboolean GAME_EXPORT VGUI_IsInGame( void );
static struct
{
qboolean initialized;
vgui_support_interface_t dllFuncs;
VGUI_DefaultCursor cursor;
HINSTANCE hInstance;
enum VGUI_KeyCode virtualKeyTrans[256];
} vgui =
{
false,
{ 0 }, // not initialized yet
-1
};
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size )
{
return Z_Malloc( size );
}
qboolean GAME_EXPORT VGUI_IsInGame( void )
static qboolean GAME_EXPORT VGUI_IsInGame( void )
{
return cls.state == ca_active && cls.key_dest == key_game;
}
void GAME_EXPORT VGUI_GetMousePos( int *_x, int *_y )
static void GAME_EXPORT VGUI_GetMousePos( int *_x, int *_y )
{
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
int x, y;
Platform_GetMousePos( &x, &y );
*_x = x / xscale, *_y = y / yscale;
*_x = x / xscale;
*_y = y / yscale;
}
void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor cursor )
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor cursor )
{
Platform_SetCursorType( cursor );
s_currentCursor = cursor;
if( vgui.cursor != cursor )
Platform_SetCursorType( cursor );
}
byte GAME_EXPORT VGUI_GetColor( int i, int j)
static byte GAME_EXPORT VGUI_GetColor( int i, int j )
{
return g_color_table[i][j];
}
// Define and initialize vgui API
int GAME_EXPORT VGUI_UtfProcessChar( int in )
static int GAME_EXPORT VGUI_UtfProcessChar( int in )
{
if( CVAR_TO_BOOL( vgui_utf8 ))
if( vgui_utf8.value )
return Con_UtfProcessCharForce( in );
else
return in;
return in;
}
vguiapi_t vgui =
qboolean VGui_IsActive( void )
{
return vgui.initialized;
}
static vgui_support_api_t gEngfuncs =
{
false, // Not initialized yet
NULL, // VGUI_DrawInit,
NULL, // VGUI_DrawShutdown,
NULL, // VGUI_SetupDrawingText,
@@ -88,28 +111,18 @@ vguiapi_t vgui =
VGUI_CursorSelect,
VGUI_GetColor,
VGUI_IsInGame,
NULL,
Key_EnableTextInput,
VGUI_GetMousePos,
VGUI_UtfProcessChar,
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
COM_LoadLibrary,
COM_FreeLibrary,
COM_GetProcAddress,
};
qboolean VGui_IsActive( void )
{
return vgui.initialized;
}
void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
static void VGui_FillAPIFromRef( vgui_support_api_t *to, const ref_interface_t *from )
{
to->DrawInit = from->VGUI_DrawInit;
to->DrawShutdown = from->VGUI_DrawShutdown;
@@ -126,141 +139,184 @@ void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
to->GenerateTexture = from->VGUI_GenerateTexture;
}
void VGui_RegisterCvars( void )
{
Cvar_RegisterVariable( &vgui_utf8 );
}
static HINSTANCE VGui_LoadSupportLibrary( void )
{
string vguiloader;
string vguilib;
HINSTANCE hInstance;
// HACKHACK: try to load path from custom path
// to support having different versions of VGUI
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ) && !COM_LoadLibrary( vguilib, false, false ))
{
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s", COM_GetLibraryError());
}
if( !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
{
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, sizeof( vguiloader ));
}
hInstance = COM_LoadLibrary( vguiloader, false, false );
if( !hInstance )
{
if( FS_FileExists( vguiloader, false ))
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
else Con_Reportf( "vgui_support: not found\n" );
}
return hInstance;
}
static qboolean VGui_ProbeNewAPI( HINSTANCE hInstance,
vgui_support_interface_t *iface, const vgui_support_api_t *api )
{
const int version = VGUI_SUPPORT_API_VERSION;
static vgui_support_api_t localapi;
VGUISUPPORTAPI F;
F = COM_GetProcAddress( hInstance, GET_VGUI_SUPPORT_API );
if( !F )
return false;
// keep local temporary copy, do not let vgui_support to mess up here
memcpy( &localapi, api, sizeof( localapi ));
if( F( version, iface, &localapi ) != version )
return false;
Con_Reportf( "vgui_support: initialized new API\n" );
return true;
}
static qboolean VGui_ProbeOldAPI( HINSTANCE hInstance,
vgui_support_interface_t *iface, const vgui_support_api_t *api,
qboolean client )
{
static legacy_vguiapi_t localapi;
LEGACY_VGUISUPPORTAPI F;
F = COM_GetProcAddress( hInstance, client ? LEGACY_CLIENT_GET_VGUI_SUPPORT_API : LEGACY_GET_VGUI_SUPPORT_API );
if( !F )
return false;
memset( &localapi, 0, sizeof( localapi ));
localapi.DrawInit = api->DrawInit;
localapi.DrawShutdown = api->DrawShutdown;
localapi.SetupDrawingText = api->SetupDrawingText;
localapi.SetupDrawingRect = api->SetupDrawingRect;
localapi.SetupDrawingImage = api->SetupDrawingImage;
localapi.BindTexture = api->BindTexture;
localapi.EnableTexture = api->EnableTexture;
localapi.CreateTexture = api->CreateTexture;
localapi.UploadTexture = api->UploadTexture;
localapi.UploadTextureBlock = api->UploadTextureBlock;
localapi.DrawQuad = api->DrawQuad;
localapi.GetTextureSizes = api->GetTextureSizes;
localapi.GenerateTexture = api->GenerateTexture;
localapi.EngineMalloc = api->EngineMalloc;
localapi.CursorSelect = api->CursorSelect;
localapi.GetColor = api->GetColor;
localapi.IsInGame = api->IsInGame;
localapi.EnableTextInput = api->EnableTextInput;
localapi.GetCursorPos = api->GetCursorPos;
localapi.ProcessUtfChar = api->ProcessUtfChar;
localapi.GetClipboardText = api->GetClipboardText;
localapi.SetClipboardText = api->SetClipboardText;
localapi.GetKeyModifiers = api->GetKeyModifiers;
F( &localapi );
localapi.initialized = true;
iface->Startup = localapi.Startup;
iface->Shutdown = localapi.Shutdown;
iface->GetPanel = localapi.GetPanel;
iface->Paint = localapi.Paint;
iface->Mouse = localapi.Mouse;
iface->Key = localapi.Key;
iface->MouseMove = localapi.MouseMove;
iface->TextInput = localapi.TextInput;
Con_Reportf( "vgui_support: initialized legacy API in %s module\n", client ? "client" : "support" );
return true;
}
qboolean VGui_LoadProgs( HINSTANCE hInstance )
{
LEGACY_VGUISUPPORTAPI F;
qboolean client = hInstance != NULL;
// not loading interface from client.dll, load vgui_support.dll instead
if( !client )
{
hInstance = vgui.hInstance = VGui_LoadSupportLibrary();
if( !hInstance )
return false;
}
// prepare api funcs
VGui_FillAPIFromRef( &gEngfuncs, &ref.dllFuncs );
// try new API first
if( !VGui_ProbeNewAPI( vgui.hInstance, &vgui.dllFuncs, &gEngfuncs ))
{
// try legacy API next
if( !VGui_ProbeOldAPI( vgui.hInstance, &vgui.dllFuncs, &gEngfuncs, client ))
{
Con_Reportf( S_ERROR "Failed to find VGUI support API entry point in %s module\n", client ? "client" : "support" );
return false;
}
}
vgui.initialized = true;
return true;
}
/*
================
VGui_Startup
Load vgui_support library and call VGui_Startup
================
*/
void VGui_Startup( const char *clientlib, int width, int height )
void VGui_Startup( HINSTANCE clientInstance, int width, int height )
{
static qboolean failed = false;
void (*F) ( vguiapi_t * );
char vguiloader[256];
char vguilib[256];
vguiloader[0] = vguilib[0] = '\0';
if( failed )
// vgui not initialized from both support and client modules, skip
if( !vgui.initialized )
return;
if( !vgui.initialized )
height = Q_max( 480, height );
if( width <= 640 ) width = 640;
else if( width <= 800 ) width = 800;
else if( width <= 1024 ) width = 1024;
else if( width <= 1152 ) width = 1152;
else if( width <= 1280 ) width = 1280;
else if( width <= 1600 ) width = 1600;
if( !clientInstance )
{
vgui_utf8 = Cvar_Get( "vgui_utf8", "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
VGui_FillAPIFromRef( &vgui, &ref.dllFuncs );
s_pVGuiSupport = COM_LoadLibrary( clientlib, false, false );
if( s_pVGuiSupport )
{
F = COM_GetProcAddress( s_pVGuiSupport, "InitVGUISupportAPI" );
if( F )
{
F( &vgui );
vgui.initialized = true;
Con_Reportf( "vgui_support: found internal client support\n" );
}
else
{
COM_FreeLibrary( s_pVGuiSupport );
}
}
if( !vgui.initialized )
{
// HACKHACK: load vgui with correct path first if specified.
// it will be reused while resolving vgui support and client deps
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ))
{
if( Q_strstr( vguilib, ".dll" ))
Q_strncpy( vguiloader, "vgui_support.dll", 256 );
else
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
if( !COM_LoadLibrary( vguilib, false, false ))
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s\n", COM_GetLibraryError() );
}
if( Q_strstr( clientlib, ".dll" ))
Q_strncpy( vguiloader, "vgui_support.dll", 256 );
if( !vguiloader[0] && !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
s_pVGuiSupport = COM_LoadLibrary( vguiloader, false, false );
if( !s_pVGuiSupport )
{
s_pVGuiSupport = COM_LoadLibrary( va( "../%s", vguiloader ), false, false );
}
if( !s_pVGuiSupport )
{
if( FS_FileExists( vguiloader, false ))
{
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
}
else
{
Con_Reportf( "vgui_support: not found\n" );
}
failed = true;
}
else
{
F = COM_GetProcAddress( s_pVGuiSupport, "InitAPI" );
if( F )
{
F( &vgui );
vgui.initialized = true;
}
else
{
Con_Reportf( S_ERROR "Failed to find vgui_support library entry point!\n" );
failed = true;
COM_FreeLibrary( s_pVGuiSupport );
}
}
}
if( vgui.dllFuncs.Startup )
vgui.dllFuncs.Startup( width, height );
}
if( height < 480 )
height = 480;
if( width <= 640 )
width = 640;
else if( width <= 800 )
width = 800;
else if( width <= 1024 )
width = 1024;
else if( width <= 1152 )
width = 1152;
else if( width <= 1280 )
width = 1280;
else if( width <= 1600 )
width = 1600;
#ifdef XASH_DLL_LOADER
else if ( Q_strstr( vguiloader, ".dll" ) )
width = 1600;
#endif
if( vgui.initialized )
else
{
//host.mouse_visible = true;
vgui.Startup( width, height );
}
else if ( COM_CheckString( clientlib ) )
{
failed = true;
if( vgui.dllFuncs.ClientStartup )
vgui.dllFuncs.ClientStartup( clientInstance, width, height );
}
}
/*
================
VGui_Shutdown
@@ -270,214 +326,223 @@ Unload vgui_support library and call VGui_Shutdown
*/
void VGui_Shutdown( void )
{
if( vgui.Shutdown )
vgui.Shutdown();
if( vgui.dllFuncs.Shutdown )
vgui.dllFuncs.Shutdown();
if( s_pVGuiSupport )
COM_FreeLibrary( s_pVGuiSupport );
s_pVGuiSupport = NULL;
if( vgui.hInstance )
COM_FreeLibrary( vgui.hInstance );
vgui.hInstance = NULL;
vgui.initialized = false;
}
void VGUI_InitKeyTranslationTable( void )
static void VGUI_InitKeyTranslationTable( void )
{
static qboolean bInitted = false;
static qboolean initialized = false;
if( bInitted )
return;
bInitted = true;
if( initialized ) return;
initialized = true;
// set virtual key translation table
memset( s_pVirtualKeyTrans, -1, sizeof( s_pVirtualKeyTrans ) );
memset( vgui.virtualKeyTrans, -1, sizeof( vgui.virtualKeyTrans ) );
s_pVirtualKeyTrans['0'] = KEY_0;
s_pVirtualKeyTrans['1'] = KEY_1;
s_pVirtualKeyTrans['2'] = KEY_2;
s_pVirtualKeyTrans['3'] = KEY_3;
s_pVirtualKeyTrans['4'] = KEY_4;
s_pVirtualKeyTrans['5'] = KEY_5;
s_pVirtualKeyTrans['6'] = KEY_6;
s_pVirtualKeyTrans['7'] = KEY_7;
s_pVirtualKeyTrans['8'] = KEY_8;
s_pVirtualKeyTrans['9'] = KEY_9;
s_pVirtualKeyTrans['A'] = s_pVirtualKeyTrans['a'] = KEY_A;
s_pVirtualKeyTrans['B'] = s_pVirtualKeyTrans['b'] = KEY_B;
s_pVirtualKeyTrans['C'] = s_pVirtualKeyTrans['c'] = KEY_C;
s_pVirtualKeyTrans['D'] = s_pVirtualKeyTrans['d'] = KEY_D;
s_pVirtualKeyTrans['E'] = s_pVirtualKeyTrans['e'] = KEY_E;
s_pVirtualKeyTrans['F'] = s_pVirtualKeyTrans['f'] = KEY_F;
s_pVirtualKeyTrans['G'] = s_pVirtualKeyTrans['g'] = KEY_G;
s_pVirtualKeyTrans['H'] = s_pVirtualKeyTrans['h'] = KEY_H;
s_pVirtualKeyTrans['I'] = s_pVirtualKeyTrans['i'] = KEY_I;
s_pVirtualKeyTrans['J'] = s_pVirtualKeyTrans['j'] = KEY_J;
s_pVirtualKeyTrans['K'] = s_pVirtualKeyTrans['k'] = KEY_K;
s_pVirtualKeyTrans['L'] = s_pVirtualKeyTrans['l'] = KEY_L;
s_pVirtualKeyTrans['M'] = s_pVirtualKeyTrans['m'] = KEY_M;
s_pVirtualKeyTrans['N'] = s_pVirtualKeyTrans['n'] = KEY_N;
s_pVirtualKeyTrans['O'] = s_pVirtualKeyTrans['o'] = KEY_O;
s_pVirtualKeyTrans['P'] = s_pVirtualKeyTrans['p'] = KEY_P;
s_pVirtualKeyTrans['Q'] = s_pVirtualKeyTrans['q'] = KEY_Q;
s_pVirtualKeyTrans['R'] = s_pVirtualKeyTrans['r'] = KEY_R;
s_pVirtualKeyTrans['S'] = s_pVirtualKeyTrans['s'] = KEY_S;
s_pVirtualKeyTrans['T'] = s_pVirtualKeyTrans['t'] = KEY_T;
s_pVirtualKeyTrans['U'] = s_pVirtualKeyTrans['u'] = KEY_U;
s_pVirtualKeyTrans['V'] = s_pVirtualKeyTrans['v'] = KEY_V;
s_pVirtualKeyTrans['W'] = s_pVirtualKeyTrans['w'] = KEY_W;
s_pVirtualKeyTrans['X'] = s_pVirtualKeyTrans['x'] = KEY_X;
s_pVirtualKeyTrans['Y'] = s_pVirtualKeyTrans['y'] = KEY_Y;
s_pVirtualKeyTrans['Z'] = s_pVirtualKeyTrans['z'] = KEY_Z;
// TODO: engine keys are not enough here!
// make crossplatform way to pass SDL keys here
s_pVirtualKeyTrans[K_KP_5 - 5] = KEY_PAD_0;
s_pVirtualKeyTrans[K_KP_5 - 4] = KEY_PAD_1;
s_pVirtualKeyTrans[K_KP_5 - 3] = KEY_PAD_2;
s_pVirtualKeyTrans[K_KP_5 - 2] = KEY_PAD_3;
s_pVirtualKeyTrans[K_KP_5 - 1] = KEY_PAD_4;
s_pVirtualKeyTrans[K_KP_5 - 0] = KEY_PAD_5;
s_pVirtualKeyTrans[K_KP_5 + 1] = KEY_PAD_6;
s_pVirtualKeyTrans[K_KP_5 + 2] = KEY_PAD_7;
s_pVirtualKeyTrans[K_KP_5 + 3] = KEY_PAD_8;
s_pVirtualKeyTrans[K_KP_5 + 4] = KEY_PAD_9;
s_pVirtualKeyTrans[K_KP_SLASH] = KEY_PAD_DIVIDE;
s_pVirtualKeyTrans['*'] = KEY_PAD_MULTIPLY;
s_pVirtualKeyTrans[K_KP_MINUS] = KEY_PAD_MINUS;
s_pVirtualKeyTrans[K_KP_PLUS] = KEY_PAD_PLUS;
s_pVirtualKeyTrans[K_KP_ENTER] = KEY_PAD_ENTER;
//s_pVirtualKeyTrans[K_KP_DECIMAL] = KEY_PAD_DECIMAL;
s_pVirtualKeyTrans['['] = KEY_LBRACKET;
s_pVirtualKeyTrans[']'] = KEY_RBRACKET;
s_pVirtualKeyTrans[';'] = KEY_SEMICOLON;
s_pVirtualKeyTrans['\''] = KEY_APOSTROPHE;
s_pVirtualKeyTrans['`'] = KEY_BACKQUOTE;
s_pVirtualKeyTrans[','] = KEY_COMMA;
s_pVirtualKeyTrans['.'] = KEY_PERIOD;
s_pVirtualKeyTrans[K_KP_SLASH] = KEY_SLASH;
s_pVirtualKeyTrans['\\'] = KEY_BACKSLASH;
s_pVirtualKeyTrans['-'] = KEY_MINUS;
s_pVirtualKeyTrans['='] = KEY_EQUAL;
s_pVirtualKeyTrans[K_ENTER] = KEY_ENTER;
s_pVirtualKeyTrans[K_SPACE] = KEY_SPACE;
s_pVirtualKeyTrans[K_BACKSPACE] = KEY_BACKSPACE;
s_pVirtualKeyTrans[K_TAB] = KEY_TAB;
s_pVirtualKeyTrans[K_CAPSLOCK] = KEY_CAPSLOCK;
s_pVirtualKeyTrans[K_KP_NUMLOCK] = KEY_NUMLOCK;
s_pVirtualKeyTrans[K_ESCAPE] = KEY_ESCAPE;
//s_pVirtualKeyTrans[K_KP_SCROLLLOCK] = KEY_SCROLLLOCK;
s_pVirtualKeyTrans[K_INS] = KEY_INSERT;
s_pVirtualKeyTrans[K_DEL] = KEY_DELETE;
s_pVirtualKeyTrans[K_HOME] = KEY_HOME;
s_pVirtualKeyTrans[K_END] = KEY_END;
s_pVirtualKeyTrans[K_PGUP] = KEY_PAGEUP;
s_pVirtualKeyTrans[K_PGDN] = KEY_PAGEDOWN;
s_pVirtualKeyTrans[K_PAUSE] = KEY_BREAK;
//s_pVirtualKeyTrans[K_SHIFT] = KEY_RSHIFT;
s_pVirtualKeyTrans[K_SHIFT] = KEY_LSHIFT; // SHIFT -> left SHIFT
//s_pVirtualKeyTrans[SDLK_RALT] = KEY_RALT;
s_pVirtualKeyTrans[K_ALT] = KEY_LALT; // ALT -> left ALT
//s_pVirtualKeyTrans[SDLK_RCTRL] = KEY_RCONTROL;
s_pVirtualKeyTrans[K_CTRL] = KEY_LCONTROL; // CTRL -> left CTRL
s_pVirtualKeyTrans[K_WIN] = KEY_LWIN;
//s_pVirtualKeyTrans[SDLK_APPLICATION] = KEY_RWIN;
//s_pVirtualKeyTrans[K_WIN] = KEY_APP;
s_pVirtualKeyTrans[K_UPARROW] = KEY_UP;
s_pVirtualKeyTrans[K_LEFTARROW] = KEY_LEFT;
s_pVirtualKeyTrans[K_DOWNARROW] = KEY_DOWN;
s_pVirtualKeyTrans[K_RIGHTARROW] = KEY_RIGHT;
s_pVirtualKeyTrans[K_F1] = KEY_F1;
s_pVirtualKeyTrans[K_F2] = KEY_F2;
s_pVirtualKeyTrans[K_F3] = KEY_F3;
s_pVirtualKeyTrans[K_F4] = KEY_F4;
s_pVirtualKeyTrans[K_F5] = KEY_F5;
s_pVirtualKeyTrans[K_F6] = KEY_F6;
s_pVirtualKeyTrans[K_F7] = KEY_F7;
s_pVirtualKeyTrans[K_F8] = KEY_F8;
s_pVirtualKeyTrans[K_F9] = KEY_F9;
s_pVirtualKeyTrans[K_F10] = KEY_F10;
s_pVirtualKeyTrans[K_F11] = KEY_F11;
s_pVirtualKeyTrans[K_F12] = KEY_F12;
vgui.virtualKeyTrans['0'] = KEY_0;
vgui.virtualKeyTrans['1'] = KEY_1;
vgui.virtualKeyTrans['2'] = KEY_2;
vgui.virtualKeyTrans['3'] = KEY_3;
vgui.virtualKeyTrans['4'] = KEY_4;
vgui.virtualKeyTrans['5'] = KEY_5;
vgui.virtualKeyTrans['6'] = KEY_6;
vgui.virtualKeyTrans['7'] = KEY_7;
vgui.virtualKeyTrans['8'] = KEY_8;
vgui.virtualKeyTrans['9'] = KEY_9;
vgui.virtualKeyTrans['A'] = vgui.virtualKeyTrans['a'] = KEY_A;
vgui.virtualKeyTrans['B'] = vgui.virtualKeyTrans['b'] = KEY_B;
vgui.virtualKeyTrans['C'] = vgui.virtualKeyTrans['c'] = KEY_C;
vgui.virtualKeyTrans['D'] = vgui.virtualKeyTrans['d'] = KEY_D;
vgui.virtualKeyTrans['E'] = vgui.virtualKeyTrans['e'] = KEY_E;
vgui.virtualKeyTrans['F'] = vgui.virtualKeyTrans['f'] = KEY_F;
vgui.virtualKeyTrans['G'] = vgui.virtualKeyTrans['g'] = KEY_G;
vgui.virtualKeyTrans['H'] = vgui.virtualKeyTrans['h'] = KEY_H;
vgui.virtualKeyTrans['I'] = vgui.virtualKeyTrans['i'] = KEY_I;
vgui.virtualKeyTrans['J'] = vgui.virtualKeyTrans['j'] = KEY_J;
vgui.virtualKeyTrans['K'] = vgui.virtualKeyTrans['k'] = KEY_K;
vgui.virtualKeyTrans['L'] = vgui.virtualKeyTrans['l'] = KEY_L;
vgui.virtualKeyTrans['M'] = vgui.virtualKeyTrans['m'] = KEY_M;
vgui.virtualKeyTrans['N'] = vgui.virtualKeyTrans['n'] = KEY_N;
vgui.virtualKeyTrans['O'] = vgui.virtualKeyTrans['o'] = KEY_O;
vgui.virtualKeyTrans['P'] = vgui.virtualKeyTrans['p'] = KEY_P;
vgui.virtualKeyTrans['Q'] = vgui.virtualKeyTrans['q'] = KEY_Q;
vgui.virtualKeyTrans['R'] = vgui.virtualKeyTrans['r'] = KEY_R;
vgui.virtualKeyTrans['S'] = vgui.virtualKeyTrans['s'] = KEY_S;
vgui.virtualKeyTrans['T'] = vgui.virtualKeyTrans['t'] = KEY_T;
vgui.virtualKeyTrans['U'] = vgui.virtualKeyTrans['u'] = KEY_U;
vgui.virtualKeyTrans['V'] = vgui.virtualKeyTrans['v'] = KEY_V;
vgui.virtualKeyTrans['W'] = vgui.virtualKeyTrans['w'] = KEY_W;
vgui.virtualKeyTrans['X'] = vgui.virtualKeyTrans['x'] = KEY_X;
vgui.virtualKeyTrans['Y'] = vgui.virtualKeyTrans['y'] = KEY_Y;
vgui.virtualKeyTrans['Z'] = vgui.virtualKeyTrans['z'] = KEY_Z;
vgui.virtualKeyTrans[K_KP_5 - 5] = KEY_PAD_0;
vgui.virtualKeyTrans[K_KP_5 - 4] = KEY_PAD_1;
vgui.virtualKeyTrans[K_KP_5 - 3] = KEY_PAD_2;
vgui.virtualKeyTrans[K_KP_5 - 2] = KEY_PAD_3;
vgui.virtualKeyTrans[K_KP_5 - 1] = KEY_PAD_4;
vgui.virtualKeyTrans[K_KP_5 - 0] = KEY_PAD_5;
vgui.virtualKeyTrans[K_KP_5 + 1] = KEY_PAD_6;
vgui.virtualKeyTrans[K_KP_5 + 2] = KEY_PAD_7;
vgui.virtualKeyTrans[K_KP_5 + 3] = KEY_PAD_8;
vgui.virtualKeyTrans[K_KP_5 + 4] = KEY_PAD_9;
vgui.virtualKeyTrans[K_KP_SLASH] = KEY_PAD_DIVIDE;
vgui.virtualKeyTrans['*'] = KEY_PAD_MULTIPLY;
vgui.virtualKeyTrans[K_KP_MINUS] = KEY_PAD_MINUS;
vgui.virtualKeyTrans[K_KP_PLUS] = KEY_PAD_PLUS;
vgui.virtualKeyTrans[K_KP_ENTER] = KEY_PAD_ENTER;
vgui.virtualKeyTrans[K_KP_NUMLOCK] = KEY_NUMLOCK;
vgui.virtualKeyTrans['['] = KEY_LBRACKET;
vgui.virtualKeyTrans[']'] = KEY_RBRACKET;
vgui.virtualKeyTrans[';'] = KEY_SEMICOLON;
vgui.virtualKeyTrans['`'] = KEY_BACKQUOTE;
vgui.virtualKeyTrans[','] = KEY_COMMA;
vgui.virtualKeyTrans['.'] = KEY_PERIOD;
vgui.virtualKeyTrans['-'] = KEY_MINUS;
vgui.virtualKeyTrans['='] = KEY_EQUAL;
vgui.virtualKeyTrans['/'] = KEY_SLASH;
vgui.virtualKeyTrans['\\'] = KEY_BACKSLASH;
vgui.virtualKeyTrans['\''] = KEY_APOSTROPHE;
vgui.virtualKeyTrans[K_TAB] = KEY_TAB;
vgui.virtualKeyTrans[K_ENTER] = KEY_ENTER;
vgui.virtualKeyTrans[K_SPACE] = KEY_SPACE;
vgui.virtualKeyTrans[K_CAPSLOCK] = KEY_CAPSLOCK;
vgui.virtualKeyTrans[K_BACKSPACE] = KEY_BACKSPACE;
vgui.virtualKeyTrans[K_ESCAPE] = KEY_ESCAPE;
vgui.virtualKeyTrans[K_INS] = KEY_INSERT;
vgui.virtualKeyTrans[K_DEL] = KEY_DELETE;
vgui.virtualKeyTrans[K_HOME] = KEY_HOME;
vgui.virtualKeyTrans[K_END] = KEY_END;
vgui.virtualKeyTrans[K_PGUP] = KEY_PAGEUP;
vgui.virtualKeyTrans[K_PGDN] = KEY_PAGEDOWN;
vgui.virtualKeyTrans[K_PAUSE] = KEY_BREAK;
vgui.virtualKeyTrans[K_SHIFT] = KEY_LSHIFT; // SHIFT -> left SHIFT
vgui.virtualKeyTrans[K_ALT] = KEY_LALT; // ALT -> left ALT
vgui.virtualKeyTrans[K_CTRL] = KEY_LCONTROL; // CTRL -> left CTRL
vgui.virtualKeyTrans[K_WIN] = KEY_LWIN;
vgui.virtualKeyTrans[K_UPARROW] = KEY_UP;
vgui.virtualKeyTrans[K_LEFTARROW] = KEY_LEFT;
vgui.virtualKeyTrans[K_DOWNARROW] = KEY_DOWN;
vgui.virtualKeyTrans[K_RIGHTARROW] = KEY_RIGHT;
vgui.virtualKeyTrans[K_F1] = KEY_F1;
vgui.virtualKeyTrans[K_F2] = KEY_F2;
vgui.virtualKeyTrans[K_F3] = KEY_F3;
vgui.virtualKeyTrans[K_F4] = KEY_F4;
vgui.virtualKeyTrans[K_F5] = KEY_F5;
vgui.virtualKeyTrans[K_F6] = KEY_F6;
vgui.virtualKeyTrans[K_F7] = KEY_F7;
vgui.virtualKeyTrans[K_F8] = KEY_F8;
vgui.virtualKeyTrans[K_F9] = KEY_F9;
vgui.virtualKeyTrans[K_F10] = KEY_F10;
vgui.virtualKeyTrans[K_F11] = KEY_F11;
vgui.virtualKeyTrans[K_F12] = KEY_F12;
}
enum VGUI_KeyCode VGUI_MapKey( int keyCode )
static enum VGUI_KeyCode VGUI_MapKey( int keyCode )
{
VGUI_InitKeyTranslationTable();
if( keyCode < 0 || keyCode >= (int)sizeof( s_pVirtualKeyTrans ) / (int)sizeof( s_pVirtualKeyTrans[0] ))
{
//Assert( false );
return (enum VGUI_KeyCode)-1;
}
else
{
return s_pVirtualKeyTrans[keyCode];
}
if( keyCode >= 0 && keyCode < ARRAYSIZE( vgui.virtualKeyTrans ))
return vgui.virtualKeyTrans[keyCode];
return (enum VGUI_KeyCode)-1;
}
void VGui_KeyEvent( int key, int down )
void VGui_MouseEvent( int key, int clicks )
{
if( !vgui.initialized )
enum VGUI_MouseAction mact;
enum VGUI_MouseCode code;
if( !vgui.dllFuncs.Mouse )
return;
switch( key )
{
case K_MOUSE1:
if( down && host.mouse_visible ) {
Key_EnableTextInput(true, false);
}
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_LEFT );
return;
case K_MOUSE2:
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_RIGHT );
return;
case K_MOUSE3:
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_MIDDLE );
return;
case K_MWHEELDOWN:
vgui.Mouse( MA_WHEEL, 1 );
return;
case K_MWHEELUP:
vgui.Mouse( MA_WHEEL, -1 );
return;
default:
break;
case K_MOUSE1: code = MOUSE_LEFT; break;
case K_MOUSE2: code = MOUSE_RIGHT; break;
case K_MOUSE3: code = MOUSE_MIDDLE; break;
default: return;
}
if( down == 2 )
vgui.Key( KA_TYPED, VGUI_MapKey( key ) );
if( clicks >= 2 )
mact = MA_DOUBLE;
else if( clicks == 1 )
mact = MA_PRESSED;
else
vgui.Key( down?KA_PRESSED:KA_RELEASED, VGUI_MapKey( key ) );
//Msg("VGui_KeyEvent %d %d %d\n", key, VGUI_MapKey( key ), down );
mact = MA_RELEASED;
vgui.dllFuncs.Mouse( mact, code );
}
void VGui_MWheelEvent( int y )
{
if( !vgui.dllFuncs.Mouse )
return;
vgui.dllFuncs.Mouse( MA_WHEEL, y );
}
void VGui_KeyEvent( int key, int down )
{
enum VGUI_KeyCode code;
if( !vgui.dllFuncs.Key )
return;
if(( code = VGUI_MapKey( key )) < 0 )
return;
if( down )
{
vgui.dllFuncs.Key( KA_PRESSED, code );
vgui.dllFuncs.Key( KA_TYPED, code );
}
else vgui.dllFuncs.Key( KA_RELEASED, code );
}
void VGui_MouseMove( int x, int y )
{
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
if( vgui.initialized )
vgui.MouseMove( x / xscale, y / yscale );
if( vgui.dllFuncs.MouseMove )
{
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
vgui.dllFuncs.MouseMove( x / xscale, y / yscale );
}
}
void VGui_Paint( void )
{
if( vgui.initialized )
vgui.Paint();
if( vgui.dllFuncs.Paint )
vgui.dllFuncs.Paint();
}
void VGui_RunFrame( void )
void VGui_UpdateInternalCursorState( VGUI_DefaultCursor cursorType )
{
//stub
vgui.cursor = cursorType;
}
void *GAME_EXPORT VGui_GetPanel( void )
{
if( vgui.initialized )
return vgui.GetPanel();
if( vgui.dllFuncs.GetPanel )
return vgui.dllFuncs.GetPanel();
return NULL;
}
void VGui_ReportTextInput( const char *text )
{
if ( vgui.initialized )
vgui.TextInput( text );
if( vgui.dllFuncs.TextInput )
vgui.dllFuncs.TextInput( text );
}

View File

@@ -16,25 +16,22 @@ GNU General Public License for more details.
#ifndef VGUI_DRAW_H
#define VGUI_DRAW_H
#ifdef __cplusplus
extern "C" {
#endif
#include "port.h"
//
// vgui_draw.c
//
void VGui_Startup( const char *clientlib, int width, int height );
void VGui_RegisterCvars( void );
qboolean VGui_LoadProgs( HINSTANCE hInstance );
void VGui_Startup( HINSTANCE clientInstance, int width, int height );
void VGui_Shutdown( void );
void VGui_Paint( void );
void VGui_RunFrame( void );
void VGui_MouseEvent( int key, int clicks );
void VGui_MWheelEvent( int y );
void VGui_KeyEvent( int key, int down );
void VGui_MouseMove( int x, int y );
qboolean VGui_IsActive( void );
void *VGui_GetPanel( void );
void VGui_ReportTextInput( const char *text );
#ifdef __cplusplus
}
#endif
#endif//VGUI_DRAW_H
void VGui_UpdateInternalCursorState( VGUI_DefaultCursor cursorType );
#endif // VGUI_DRAW_H

View File

@@ -21,7 +21,6 @@ GNU General Public License for more details.
#include "platform/platform.h"
#define WINDOW_NAME XASH_ENGINE_NAME " Window" // Half-Life
convar_t *vid_displayfrequency;
convar_t *vid_fullscreen;
convar_t *vid_mode;
convar_t *vid_brightness;
@@ -67,19 +66,30 @@ void VID_InitDefaultResolution( void )
R_SaveVideoMode
=================
*/
void R_SaveVideoMode( int w, int h , int render_w, int render_h )
void R_SaveVideoMode( int w, int h, int render_w, int render_h )
{
if( !w || !h || !render_w || !render_h )
{
host.renderinfo_changed = false;
return;
}
host.window_center_x = w / 2;
host.window_center_y = h / 2;
Cvar_SetValue( "width", w );
Cvar_SetValue( "height", h );
// immediately drop changed state or we may trigger
// video subsystem to reapply settings
host.renderinfo_changed = false;
if( refState.width == render_w && refState.height == render_h )
return;
refState.width = render_w;
refState.height = render_h;
host.renderinfo_changed = false;
// check for 4:3 or 5:4
if( render_w * 3 != render_h * 4 && render_w * 4 != render_h * 5 )
refState.wideScreen = true;
@@ -176,12 +186,11 @@ void VID_Init( void )
Cvar_Get( "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
Cvar_Get( "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
window_xpos = Cvar_Get( "_window_xpos", "130", FCVAR_RENDERINFO, "window position by horizontal" );
window_ypos = Cvar_Get( "_window_ypos", "48", FCVAR_RENDERINFO, "window position by vertical" );
window_xpos = Cvar_Get( "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
window_ypos = Cvar_Get( "_window_ypos", "-1", FCVAR_RENDERINFO, "window position by vertical" );
vid_gamma = Cvar_Get( "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
vid_brightness = Cvar_Get( "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen refresh rate" );
vid_fullscreen = Cvar_Get( "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable fullscreen mode" );
vid_mode = Cvar_Get( "vid_mode", "0", FCVAR_RENDERINFO, "current video mode index (used just for storage)" );
vid_highdpi = Cvar_Get( "vid_highdpi", "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );

View File

@@ -31,7 +31,6 @@ extern glwstate_t glw_state;
#define VID_MIN_WIDTH 320
extern convar_t *vid_fullscreen;
extern convar_t *vid_displayfrequency;
extern convar_t *vid_highdpi;
extern convar_t *vid_rotate;
extern convar_t *vid_scale;

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

@@ -0,0 +1,633 @@
/*
voice.c - voice chat implementation
Copyright (C) 2022 Velaron
Copyright (C) 2022 SNMetamorph
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#define CUSTOM_MODES 1 // required to correctly link with Opus Custom
#include <opus_custom.h>
#include "common.h"
#include "client.h"
#include "voice.h"
voice_state_t voice = { 0 };
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
/*
===============================================================================
OPUS INTEGRATION
===============================================================================
*/
/*
=========================
Voice_InitOpusDecoder
=========================
*/
static qboolean Voice_InitOpusDecoder( void )
{
int err;
voice.width = sizeof( opus_int16 );
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
if( !voice.custom_mode )
{
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
return false;
}
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.decoder )
{
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
return false;
}
return true;
}
/*
=========================
Voice_InitOpusEncoder
=========================
*/
static qboolean Voice_InitOpusEncoder( int quality )
{
int err;
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.encoder )
{
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
return false;
}
switch( quality )
{
case 1: // 6 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 6000 ));
break;
case 2: // 12 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 12000 ));
break;
case 4: // 64 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 64000 ));
break;
case 5: // 96 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 96000 ));
break;
default: // 36 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 36000 ));
break;
}
return true;
}
/*
=========================
Voice_ShutdownOpusDecoder
=========================
*/
static void Voice_ShutdownOpusDecoder( void )
{
if( voice.decoder )
{
opus_custom_decoder_destroy( voice.decoder );
voice.decoder = NULL;
}
}
/*
=========================
Voice_ShutdownOpusEncoder
=========================
*/
static void Voice_ShutdownOpusEncoder( void )
{
if( voice.encoder )
{
opus_custom_encoder_destroy( voice.encoder );
voice.encoder = NULL;
}
if( voice.custom_mode )
{
opus_custom_mode_destroy( voice.custom_mode );
voice.custom_mode = NULL;
}
}
/*
=========================
Voice_GetOpusCompressedData
=========================
*/
static uint Voice_GetOpusCompressedData( byte *out, uint maxsize, uint *frames )
{
uint ofs = 0, size = 0;
uint frame_size_bytes = voice.frame_size * voice.width;
if( voice.input_file )
{
uint numbytes;
double updateInterval, curtime = Sys_DoubleTime();
updateInterval = curtime - voice.start_time;
voice.start_time = curtime;
numbytes = updateInterval * voice.samplerate * voice.width * VOICE_PCM_CHANNELS;
numbytes = Q_min( numbytes, voice.input_file->size - voice.input_file_pos );
numbytes = Q_min( numbytes, sizeof( voice.input_buffer ) - voice.input_buffer_pos );
memcpy( voice.input_buffer + voice.input_buffer_pos, voice.input_file->buffer + voice.input_file_pos, numbytes );
voice.input_buffer_pos += numbytes;
voice.input_file_pos += numbytes;
}
if( !voice.input_file )
VoiceCapture_Lock( true );
for( ofs = 0; voice.input_buffer_pos - ofs >= frame_size_bytes && ofs <= voice.input_buffer_pos; ofs += frame_size_bytes )
{
int bytes;
#if 1
if( !voice.input_file )
{
// adjust gain before encoding, but only for input from voice
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size);
}
#endif
bytes = opus_custom_encode( voice.encoder, (const opus_int16 *)( voice.input_buffer + ofs ),
voice.frame_size, out + size + sizeof( uint16_t ), maxsize );
if( bytes > 0 )
{
// write compressed frame size
*((uint16_t *)&out[size]) = bytes;
size += bytes + sizeof( uint16_t );
maxsize -= bytes + sizeof( uint16_t );
(*frames)++;
}
else
{
Con_Printf( S_ERROR "%s: failed to encode frame: %s\n", __func__, opus_strerror( bytes ));
}
}
// did we compress anything? update counters
if( ofs )
{
fs_offset_t remaining = voice.input_buffer_pos - ofs;
// move remaining samples to the beginning of buffer
memmove( voice.input_buffer, voice.input_buffer + ofs, remaining );
voice.input_buffer_pos = remaining;
}
if( !voice.input_file )
VoiceCapture_Lock( false );
return size;
}
/*
===============================================================================
VOICE CHAT INTEGRATION
===============================================================================
*/
/*
=========================
Voice_ApplyGainAdjust
=========================
*/
static void Voice_ApplyGainAdjust( int16_t *samples, int count )
{
float gain, modifiedMax;
int average, adjustedSample, blockOffset = 0;
for( ;; )
{
int i, localMax = 0, localSum = 0;
int blockSize = Q_min( count - ( blockOffset + voice.autogain.block_size ), voice.autogain.block_size );
if( blockSize < 1 )
break;
for( i = 0; i < blockSize; ++i )
{
int sample = samples[blockOffset + i];
int absSample = abs( sample );
if( absSample > localMax )
localMax = absSample;
localSum += absSample;
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
adjustedSample = Q_min( SHRT_MAX, Q_max(( int )( sample * gain ), SHRT_MIN ));
samples[blockOffset + i] = adjustedSample;
}
if( blockOffset % voice.autogain.block_size == 0 )
{
average = localSum / blockSize;
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
voice.autogain.current_gain = voice.autogain.next_gain * voice_scale.value;
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * voice_scale.value;
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( voice.autogain.block_size - 1 );
}
blockOffset += blockSize;
}
}
/*
=========================
Voice_Status
Notify user dll aboit voice transmission
=========================
*/
static void Voice_Status( int entindex, qboolean bTalking )
{
if( cls.state == ca_active && clgame.dllFuncs.pfnVoiceStatus )
clgame.dllFuncs.pfnVoiceStatus( entindex, bTalking );
}
/*
=========================
Voice_StatusTimeout
Waits few milliseconds and if there was no
voice transmission, sends notification
=========================
*/
static void Voice_StatusTimeout( voice_status_t *status, int entindex, double frametime )
{
if( status->talking_ack )
{
status->talking_timeout += frametime;
if( status->talking_timeout > 0.2 )
{
status->talking_ack = false;
Voice_Status( entindex, false );
}
}
}
/*
=========================
Voice_StatusAck
Sends notification to user dll and
zeroes timeouts for this client
=========================
*/
void Voice_StatusAck( voice_status_t *status, int playerIndex )
{
if( !status->talking_ack )
Voice_Status( playerIndex, true );
status->talking_ack = true;
status->talking_timeout = 0.0;
}
/*
=========================
Voice_IsRecording
=========================
*/
qboolean Voice_IsRecording( void )
{
return voice.is_recording;
}
/*
=========================
Voice_RecordStop
=========================
*/
void Voice_RecordStop( void )
{
if( voice.input_file )
{
FS_FreeSound( voice.input_file );
voice.input_file = NULL;
}
VoiceCapture_Activate( false );
voice.is_recording = false;
Voice_Status( VOICE_LOCALCLIENT_INDEX, false );
voice.input_buffer_pos = 0;
memset( voice.input_buffer, 0, sizeof( voice.input_buffer ));
}
/*
=========================
Voice_RecordStart
=========================
*/
void Voice_RecordStart( void )
{
Voice_RecordStop();
if( voice_inputfromfile.value )
{
voice.input_file = FS_LoadSound( "voice_input.wav", NULL, 0 );
if( voice.input_file )
{
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
voice.input_file_pos = 0;
voice.start_time = Sys_DoubleTime();
voice.is_recording = true;
}
else
{
FS_FreeSound( voice.input_file );
voice.input_file = NULL;
}
}
if( !Voice_IsRecording() )
voice.is_recording = VoiceCapture_Activate( true );
if( Voice_IsRecording() )
Voice_Status( VOICE_LOCALCLIENT_INDEX, true );
}
/*
=========================
Voice_Disconnect
We're disconnected from server
stop recording and notify user dlls
=========================
*/
void Voice_Disconnect( void )
{
int i;
Voice_RecordStop();
if( voice.local.talking_ack )
{
Voice_Status( VOICE_LOOPBACK_INDEX, false );
voice.local.talking_ack = false;
}
for( i = 0; i < MAX_CLIENTS; i++ )
{
if( voice.players_status[i].talking_ack )
{
Voice_Status( i, false );
voice.players_status[i].talking_ack = false;
}
}
}
/*
=========================
Voice_StartChannel
Feed the decoded data to engine sound subsystem
=========================
*/
static void Voice_StartChannel( uint samples, byte *data, int entnum )
{
SND_ForceInitMouth( entnum );
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, 255 );
}
/*
=========================
Voice_AddIncomingData
Received encoded voice data, decode it
=========================
*/
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
{
int samples = 0;
int ofs = 0;
if( !voice.decoder )
return;
// decode frame by frame
for( ;; )
{
int frame_samples;
uint16_t compressed_size;
// no compressed size mark
if( ofs + sizeof( uint16_t ) > size )
break;
compressed_size = *(const uint16_t *)(data + ofs);
ofs += sizeof( uint16_t );
// no frame data
if( ofs + compressed_size > size )
break;
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size,
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
ofs += compressed_size;
samples += frame_samples;
}
if( samples > 0 )
Voice_StartChannel( samples, voice.decompress_buffer, ent );
}
/*
=========================
CL_AddVoiceToDatagram
Encode our voice data and send it to server
=========================
*/
void CL_AddVoiceToDatagram( void )
{
uint size, frames = 0;
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
return;
size = Voice_GetOpusCompressedData( voice.output_buffer, sizeof( voice.output_buffer ), &frames );
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
{
MSG_BeginClientCmd( &cls.datagram, clc_voicedata );
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
MSG_WriteByte( &cls.datagram, frames );
MSG_WriteShort( &cls.datagram, size );
MSG_WriteBytes( &cls.datagram, voice.output_buffer, size );
}
}
/*
=========================
Voice_RegisterCvars
Register voice related cvars and commands
=========================
*/
void Voice_RegisterCvars( void )
{
Cvar_RegisterVariable( &voice_enable );
Cvar_RegisterVariable( &voice_loopback );
Cvar_RegisterVariable( &voice_scale );
Cvar_RegisterVariable( &voice_avggain );
Cvar_RegisterVariable( &voice_maxgain );
Cvar_RegisterVariable( &voice_inputfromfile );
}
/*
=========================
Voice_Shutdown
Completely shutdown the voice subsystem
=========================
*/
static void Voice_Shutdown( void )
{
int i;
Voice_RecordStop();
Voice_ShutdownOpusEncoder();
Voice_ShutdownOpusDecoder();
VoiceCapture_Shutdown();
if( voice.local.talking_ack )
Voice_Status( VOICE_LOOPBACK_INDEX, false );
for( i = 0; i < MAX_CLIENTS; i++ )
{
if( voice.players_status[i].talking_ack )
Voice_Status( i, false );
}
memset( &voice, 0, sizeof( voice ));
}
/*
=========================
Voice_Idle
Run timeout for all clients
=========================
*/
void Voice_Idle( double frametime )
{
int i;
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
{
Voice_Shutdown();
return;
}
// update local player status first
Voice_StatusTimeout( &voice.local, VOICE_LOOPBACK_INDEX, frametime );
for( i = 0; i < MAX_CLIENTS; i++ )
Voice_StatusTimeout( &voice.players_status[i], i, frametime );
}
/*
=========================
Voice_Init
Initialize the voice subsystem
=========================
*/
qboolean Voice_Init( const char *pszCodecName, int quality )
{
if( !voice_enable.value )
return false;
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
return false;
}
// reinitialize only if codec parameters are different
if( Q_strcmp( voice.codec, pszCodecName ) && voice.quality != quality )
Voice_Shutdown();
voice.autogain.block_size = 128;
if( !Voice_InitOpusDecoder( ))
{
// no reason to init encoder and open audio device
// if we can't hear other players
Con_Printf( S_ERROR "Voice chat disabled.\n" );
Voice_Shutdown();
return false;
}
// we can hear others players, so it's fine to fail now
voice.initialized = true;
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
if( !Voice_InitOpusEncoder( quality ))
{
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
return false;
}
voice.quality = quality;
if( !VoiceCapture_Init( ))
Con_Printf( S_WARN "No microphone is available.\n" );
return true;
}

104
engine/client/voice.h Normal file
View File

@@ -0,0 +1,104 @@
/*
voice.h - voice chat implementation
Copyright (C) 2022 Velaron
Copyright (C) 2022 SNMetamorph
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef VOICE_H
#define VOICE_H
#include "common.h"
#include "protocol.h" // MAX_CLIENTS
#include "sound.h"
typedef struct OpusCustomEncoder OpusCustomEncoder;
typedef struct OpusCustomDecoder OpusCustomDecoder;
typedef struct OpusCustomMode OpusCustomMode;
#define VOICE_LOOPBACK_INDEX (-2)
#define VOICE_LOCALCLIENT_INDEX (-1)
#define VOICE_PCM_CHANNELS 1 // always mono
// never change these parameters when using opuscustom
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k
// must follow opus custom requirements
// also be divisible with MAX_RAW_SAMPLES
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024
#define VOICE_OPUS_CUSTOM_CODEC "opus_custom_44k_512"
// a1ba: do not change, we don't have any re-encoding support now
#define VOICE_DEFAULT_CODEC VOICE_OPUS_CUSTOM_CODEC
typedef struct voice_status_s
{
qboolean talking_ack;
double talking_timeout;
} voice_status_t;
typedef struct voice_state_s
{
string codec;
int quality;
qboolean initialized;
qboolean is_recording;
double start_time;
voice_status_t local;
voice_status_t players_status[MAX_CLIENTS];
// opus stuff
OpusCustomMode *custom_mode;
OpusCustomEncoder *encoder;
OpusCustomDecoder *decoder;
// audio info
uint width;
uint samplerate;
uint frame_size; // in samples
// buffers
byte input_buffer[MAX_RAW_SAMPLES];
byte output_buffer[MAX_RAW_SAMPLES];
byte decompress_buffer[MAX_RAW_SAMPLES];
fs_offset_t input_buffer_pos; // in bytes
// input from file
wavdata_t *input_file;
fs_offset_t input_file_pos; // in bytes
// automatic gain control
struct {
int block_size;
float current_gain;
float next_gain;
float gain_multiplier;
} autogain;
} voice_state_t;
extern voice_state_t voice;
void CL_AddVoiceToDatagram( void );
void Voice_RegisterCvars( void );
qboolean Voice_Init( const char *pszCodecName, int quality );
void Voice_Idle( double frametime );
qboolean Voice_IsRecording( void );
void Voice_RecordStop( void );
void Voice_RecordStart( void );
void Voice_Disconnect( void );
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames );
void Voice_StatusAck( voice_status_t *status, int playerIndex );
#endif // VOICE_H

View File

@@ -17,10 +17,20 @@ GNU General Public License for more details.
#include "base_cmd.h"
#include "cdll_int.h"
// TODO: use another hash function, as COM_HashKey depends on string length
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s
{
base_command_t *basecmd; // base command: cvar, alias or command
const char *name; // key for searching
base_command_type_e type; // type for faster searching
struct base_command_hashmap_s *next;
} base_command_hashmap_t;
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
#define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE )
/*
============
BaseCmd_FindInBucket
@@ -28,7 +38,7 @@ BaseCmd_FindInBucket
Find base command in bucket
============
*/
base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
{
base_command_hashmap_t *i = bucket;
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
@@ -44,9 +54,9 @@ BaseCmd_GetBucket
Get bucket which contain basecmd by given name
============
*/
base_command_hashmap_t *BaseCmd_GetBucket( const char *name )
static base_command_hashmap_t *BaseCmd_GetBucket( const char *name )
{
return hashed_cmds[ COM_HashKey( name, HASH_SIZE ) ];
return hashed_cmds[ BaseCmd_HashKey( name ) ];
}
/*
@@ -73,7 +83,7 @@ BaseCmd_Find
Find every type of base command and write into arguments
============
*/
void BaseCmd_FindAll(const char *name, base_command_t **cmd, base_command_t **alias, base_command_t **cvar)
void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **alias, base_command_t **cvar )
{
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
base_command_hashmap_t *i = base;
@@ -101,7 +111,6 @@ void BaseCmd_FindAll(const char *name, base_command_t **cmd, base_command_t **al
}
}
}
}
/*
@@ -113,41 +122,23 @@ Add new typed base command to hashmap
*/
void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const char *name )
{
uint hash = COM_HashKey( name, HASH_SIZE );
base_command_hashmap_t *elem;
base_command_hashmap_t *elem, *cur, *find;
uint hash = BaseCmd_HashKey( name );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) );
elem->basecmd = basecmd;
elem->type = type;
elem->name = name;
elem->next = hashed_cmds[hash];
hashed_cmds[hash] = elem;
}
/*
============
BaseCmd_Replace
// link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash];
find && Q_strcmp( find->name, elem->name ) < 0;
cur = find, find = find->next );
Used in case, when basecmd has been registered, but gamedll wants to register it's own
============
*/
qboolean BaseCmd_Replace( base_command_type_e type, base_command_t *basecmd, const char *name )
{
base_command_hashmap_t *i = BaseCmd_GetBucket( name );
if( cur ) cur->next = elem;
else hashed_cmds[hash] = elem;
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ) ; // filter out
i = i->next );
if( !i )
{
Con_Reportf( S_ERROR "BaseCmd_Replace: couldn't find %s\n", name);
return false;
}
i->basecmd = basecmd;
i->name = name; // may be freed after
return true;
elem->next = find;
}
/*
@@ -159,7 +150,7 @@ Remove base command from hashmap
*/
void BaseCmd_Remove( base_command_type_e type, const char *name )
{
uint hash = COM_HashKey( name, HASH_SIZE );
uint hash = BaseCmd_HashKey( name );
base_command_hashmap_t *i, *prev;
for( prev = NULL, i = hashed_cmds[hash]; i &&
@@ -221,23 +212,27 @@ void BaseCmd_Stats_f( void )
if( len > maxsize )
maxsize = len;
}
Con_Printf( "Base command stats:\n");
Con_Printf( "Bucket minimal length: %d\n", minsize );
Con_Printf( "Bucket maximum length: %d\n", maxsize );
Con_Printf( "Empty buckets: %d\n", empty );
Con_Printf( "min length: %d, max length: %d, empty: %d\n", minsize, maxsize, empty );
}
typedef struct
{
qboolean valid;
int lookups;
} basecmd_test_stats_t;
static void BaseCmd_CheckCvars( const char *key, const char *value, const void *unused, void *ptr )
{
base_command_t *v = BaseCmd_Find( HM_CVAR, key );
qboolean *invalid = ptr;
basecmd_test_stats_t *stats = ptr;
if( !v )
stats->lookups++;
if( !BaseCmd_Find( HM_CVAR, key ))
{
Con_Printf( "Cvar %s is missing in basecmd\n", key );
*invalid = true;
stats->valid = false;
}
}
@@ -250,38 +245,51 @@ testing order matches cbuf execute
*/
void BaseCmd_Test_f( void )
{
void *cmd;
cmdalias_t *a;
qboolean invalid = false;
basecmd_test_stats_t stats;
double start, end, dt;
int i;
// Cmd_LookupCmds don't allows to check alias, so just iterate
for( a = Cmd_AliasGetList(); a; a = a->next )
stats.valid = true;
stats.lookups = 0;
start = Sys_DoubleTime() * 1000;
for( i = 0; i < 1000; i++ )
{
base_command_t *v = BaseCmd_Find( HM_CMDALIAS, a->name );
cmdalias_t *a;
void *cmd;
if( !v )
// Cmd_LookupCmds don't allows to check alias, so just iterate
for( a = Cmd_AliasGetList(); a; a = a->next, stats.lookups++ )
{
Con_Printf( "Alias %s is missing in basecmd\n", a->name );
invalid = true;
if( !BaseCmd_Find( HM_CMDALIAS, a->name ))
{
Con_Printf( "Alias %s is missing in basecmd\n", a->name );
stats.valid = false;
}
}
for( cmd = Cmd_GetFirstFunctionHandle(); cmd;
cmd = Cmd_GetNextFunctionHandle( cmd ), stats.lookups++ )
{
if( !BaseCmd_Find( HM_CMD, Cmd_GetName( cmd )))
{
Con_Printf( "Command %s is missing in basecmd\n", Cmd_GetName( cmd ));
stats.valid = false;
}
}
Cvar_LookupVars( 0, NULL, &stats.valid, (setpair_t)BaseCmd_CheckCvars );
}
for( cmd = Cmd_GetFirstFunctionHandle(); cmd;
cmd = Cmd_GetNextFunctionHandle( cmd ) )
{
base_command_t *v = BaseCmd_Find( HM_CMD, Cmd_GetName( cmd ) );
end = Sys_DoubleTime() * 1000;
if( !v )
{
Con_Printf( "Command %s is missing in basecmd\n", Cmd_GetName( cmd ) );
invalid = true;
}
}
dt = end - start;
Cvar_LookupVars( 0, NULL, &invalid, (setpair_t)BaseCmd_CheckCvars );
if( !invalid )
{
if( !stats.valid )
Con_Printf( "BaseCmd is valid\n" );
}
Con_Printf( "Test took %.3f ms, %d lookups, %.3f us/lookup\n", dt, stats.lookups, dt / stats.lookups * 1000 );
BaseCmd_Stats_f();
}

View File

@@ -17,8 +17,6 @@ GNU General Public License for more details.
#ifndef BASE_CMD_H
#define BASE_CMD_H
// TODO: Find cases when command hashmap works incorrect
// and maybe disable it
#define XASH_HASHED_VARS
#ifdef XASH_HASHED_VARS
@@ -33,23 +31,13 @@ typedef enum base_command_type
typedef void base_command_t;
typedef struct base_command_hashmap_s
{
base_command_t *basecmd; // base command: cvar, alias or command
const char *name; // key for searching
base_command_type_e type; // type for faster searching
struct base_command_hashmap_s *next;
} base_command_hashmap_t;
void BaseCmd_Init( void );
base_command_hashmap_t *BaseCmd_GetBucket( const char *name );
base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name,
base_command_t **cmd, base_command_t **alias, base_command_t **cvar );
void BaseCmd_Insert ( base_command_type_e type, base_command_t *basecmd, const char *name );
qboolean BaseCmd_Replace( base_command_type_e type, base_command_t *basecmd, const char *name ); // only if same name
void BaseCmd_Remove ( base_command_type_e type, const char *name );
void BaseCmd_Stats_f( void ); // to be registered later
void BaseCmd_Test_f( void ); // to be registered later

View File

@@ -1,194 +0,0 @@
/*
build.c - returns a engine build number
Copyright (C) 2010 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
static const char *date = __DATE__ ;
static const char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static const char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// returns days since Apr 1 2015
int Q_buildnum( void )
{
int m = 0, d = 0, y = 0;
static int b = 0;
if( b != 0 ) return b;
for( m = 0; m < 11; m++ )
{
if( !Q_strnicmp( &date[0], mon[m], 3 ))
break;
d += mond[m];
}
d += Q_atoi( &date[4] ) - 1;
y = Q_atoi( &date[7] ) - 1900;
b = d + (int)((y - 1) * 365.25f );
if((( y % 4 ) == 0 ) && m > 1 )
{
b += 1;
}
b -= 41728; // Apr 1 2015
return b;
}
/*
=============
Q_buildnum_compat
Returns a Xash3D build number. This is left for compability with original Xash3D.
IMPORTANT: this value must be changed ONLY after updating to newer Xash3D
IMPORTANT: this value must be acquired through "build" cvar.
=============
*/
int Q_buildnum_compat( void )
{
// do not touch this! Only author of Xash3D can increase buildnumbers!
return 4529;
}
/*
============
Q_buildos
Returns current name of operating system. Without any spaces.
============
*/
const char *Q_buildos( void )
{
const char *osname;
#if XASH_MINGW
osname = "win32-mingw";
#elif XASH_WIN32
osname = "win32";
#elif XASH_ANDROID
osname = "android";
#elif XASH_LINUX
osname = "linux";
#elif XASH_APPLE
osname = "apple";
#elif XASH_FREEBSD
osname = "freebsd";
#elif XASH_NETBSD
osname = "netbsd";
#elif XASH_OPENBSD
osname = "openbsd";
#elif XASH_EMSCRIPTEN
osname = "emscripten";
#elif XASH_DOS4GW
osname = "DOS4GW";
#elif XASH_HAIKU
osname = "haiku";
#else
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
#endif
return osname;
}
/*
============
Q_buildarch
Returns current name of the architecture. Without any spaces.
============
*/
const char *Q_buildarch( void )
{
const char *archname;
#if XASH_AMD64
archname = "amd64";
#elif XASH_X86
archname = "i386";
#elif XASH_ARM && XASH_64BIT
archname = "arm64";
#elif XASH_ARM
archname = "armv"
#if XASH_ARM == 8
"8_32" // for those who (mis)using 32-bit OS on 64-bit CPU
#elif XASH_ARM == 7
"7"
#elif XASH_ARM == 6
"6"
#elif XASH_ARM == 5
"5"
#elif XASH_ARM == 4
"4"
#endif
#if XASH_ARM_HARDFP
"hf"
#else
"l"
#endif
;
#elif XASH_MIPS && XASH_BIG_ENDIAN
archname = "mips"
#if XASH_64BIT
"64"
#endif
#if XASH_LITTLE_ENDIAN
"el"
#endif
;
#elif XASH_RISCV
archname = "riscv"
#if XASH_64BIT
"64"
#else
"32"
#endif
#if XASH_RISCV_SINGLEFP
"d"
#elif XASH_RISCV_DOUBLEFP
"f"
#endif
;
#elif XASH_JS
archname = "javascript";
#elif XASH_E2K
archname = "e2k";
#else
#error "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug"
#endif
return archname;
}
/*
=============
Q_buildcommit
Returns a short hash of current commit in VCS as string.
XASH_BUILD_COMMIT must be passed in quotes
if XASH_BUILD_COMMIT is not defined,
Q_buildcommit will identify this build as "notset"
=============
*/
const char *Q_buildcommit( void )
{
#ifdef XASH_BUILD_COMMIT
return XASH_BUILD_COMMIT;
#else
return "notset";
#endif
}

View File

@@ -120,6 +120,18 @@ void Cbuf_AddText( const char *text )
Cbuf_AddTextToBuffer( &cmd_text, text );
}
void Cbuf_AddTextf( const char *fmt, ... )
{
va_list va;
char buf[MAX_VA_STRING];
va_start( va, fmt );
Q_vsnprintf( buf, sizeof( buf ), fmt, va );
va_end( va );
Cbuf_AddText( buf );
}
/*
============
Cbuf_AddFilteredText
@@ -647,7 +659,7 @@ void Cmd_TokenizeString( const char *text )
if( cmd_argc == 1 )
cmd_args = text;
text = _COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL );
text = COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL, NULL );
if( !text ) return;
@@ -984,7 +996,7 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
cmd_condlevel = 0;
// cvar value substitution
if( CVAR_TO_BOOL( cmd_scripting ))
if( CVAR_TO_BOOL( cmd_scripting ) && isPrivileged )
{
while( *text )
{
@@ -1150,13 +1162,13 @@ void Cmd_ForwardToServer( void )
str[0] = 0;
if( Q_stricmp( Cmd_Argv( 0 ), "cmd" ))
{
Q_strcat( str, Cmd_Argv( 0 ));
Q_strcat( str, " " );
Q_strncat( str, Cmd_Argv( 0 ), sizeof( str ));
Q_strncat( str, " ", sizeof( str ));
}
if( Cmd_Argc() > 1 )
Q_strcat( str, Cmd_Args( ));
else Q_strcat( str, "\n" );
Q_strncat( str, Cmd_Args( ), sizeof( str ));
else Q_strncat( str, "\n", sizeof( str ));
MSG_WriteString( &cls.netchan.message, str );
}
@@ -1171,17 +1183,21 @@ void Cmd_List_f( void )
{
cmd_t *cmd;
int i = 0;
const char *match;
size_t matchlen = 0;
const char *match = NULL;
if( Cmd_Argc() > 1 ) match = Cmd_Argv( 1 );
else match = NULL;
if( Cmd_Argc() > 1 )
{
match = Cmd_Argv( 1 );
matchlen = Q_strlen( match );
}
for( cmd = cmd_functions; cmd; cmd = cmd->next )
{
if( cmd->name[0] == '@' )
continue; // never show system cmds
if( match && !Q_stricmpext( match, cmd->name ))
if( match && !Q_strnicmpext( match, cmd->name, matchlen ))
continue;
Con_Printf( " %-*s ^3%s^7\n", 32, cmd->name, cmd->desc );
@@ -1250,21 +1266,21 @@ static void Cmd_Apropos_f( void )
cmdalias_t *alias;
const char *partial;
int count = 0;
qboolean ispattern;
char buf[MAX_VA_STRING];
if( Cmd_Argc() > 1 )
{
partial = Cmd_Args();
}
else
if( Cmd_Argc() < 2 )
{
Msg( "apropos what?\n" );
return;
}
ispattern = partial && Q_strpbrk( partial, "*?" );
if( !ispattern )
partial = va( "*%s*", partial );
partial = Cmd_Args();
if( !Q_strpbrk( partial, "*?" ))
{
Q_snprintf( buf, sizeof( buf ), "*%s*", partial );
partial = buf;
}
for( var = (convar_t*)Cvar_GetList(); var; var = var->next )
{
@@ -1391,8 +1407,8 @@ void Cmd_Init( void )
#endif // XASH_DEDICATED
Cmd_AddRestrictedCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" );
Cmd_AddRestrictedCommand( "unalias", Cmd_UnAlias_f, "remove a script function" );
Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" );
Cmd_AddCommand( "else", Cmd_Else_f, "invert condition bit" );
Cmd_AddRestrictedCommand( "if", Cmd_If_f, "compare and set condition bits" );
Cmd_AddRestrictedCommand( "else", Cmd_Else_f, "invert condition bit" );
#if defined(XASH_HASHED_VARS)
Cmd_AddCommand( "basecmd_stats", BaseCmd_Stats_f, "print info about basecmd usage" );

View File

@@ -21,6 +21,7 @@ GNU General Public License for more details.
#define S_WARN "^3Warning:^7 "
#define S_ERROR "^1Error:^7 "
#define S_USAGE "Usage: "
#define S_USAGE_INDENT " "
#define S_OPENGL_NOTE "^2OpenGL Note:^7 "
#define S_OPENGL_WARN "^3OpenGL Warning:^7 "
@@ -64,9 +65,7 @@ GNU General Public License for more details.
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
#define XASH_ENGINE_NAME "Xash3D FWGS"
// renderers order is important, software is always a last chance fallback
#define DEFAULT_RENDERERS { "gl", "gles1", "gles2", "gl4es", "soft" }
#define DEFAULT_RENDERERS_LEN 5
#define XASH_VERSION "0.20" // engine current version
#define XASH_COMPAT_VERSION "0.99" // version we are based on
#endif//COM_STRINGS_H

View File

@@ -151,6 +151,30 @@ int GAME_EXPORT COM_RandomLong( int lLow, int lHigh )
return lLow + (n % x);
}
/*
============
va
does a varargs printf into a temp buffer,
so I don't need to have varargs versions
of all text functions.
============
*/
char *va( const char *format, ... )
{
va_list argptr;
static char string[16][MAX_VA_STRING], *s;
static int stringindex = 0;
s = string[stringindex];
stringindex = (stringindex + 1) & 15;
va_start( argptr, format );
Q_vsnprintf( s, sizeof( string[0] ), format, argptr );
va_end( argptr );
return s;
}
/*
===============================================================================
@@ -529,7 +553,6 @@ This doesn't search in the pak file.
*/
int GAME_EXPORT COM_ExpandFilename( const char *fileName, char *nameOutBuffer, int nameOutBufferSize )
{
const char *path;
char result[MAX_SYSPATH];
if( !COM_CheckString( fileName ) || !nameOutBuffer || nameOutBufferSize <= 0 )
@@ -538,10 +561,8 @@ int GAME_EXPORT COM_ExpandFilename( const char *fileName, char *nameOutBuffer, i
// filename examples:
// media\sierra.avi - D:\Xash3D\valve\media\sierra.avi
// models\barney.mdl - D:\Xash3D\bshift\models\barney.mdl
if(( path = FS_GetDiskPath( fileName, false )) != NULL )
if( g_fsapi.GetFullDiskPath( result, sizeof( result ), fileName, false ))
{
Q_sprintf( result, "%s/%s", host.rootdir, path );
// check for enough room
if( Q_strlen( result ) > nameOutBufferSize )
return 0;
@@ -585,23 +606,6 @@ void COM_TrimSpace( const char *source, char *dest )
dest[length] = 0;
}
/*
============
COM_FixSlashes
Changes all '/' characters into '\' characters, in place.
============
*/
void COM_FixSlashes( char *pname )
{
while( *pname )
{
if( *pname == '\\' )
*pname = '/';
pname++;
}
}
/*
==================
COM_Nibble
@@ -893,9 +897,7 @@ cvar_t *pfnCvar_RegisterClientVariable( const char *szName, const char *szValue,
if( !Q_stricmp( szName, "motdfile" ))
flags |= FCVAR_PRIVILEGED;
if( FBitSet( flags, FCVAR_GLCONFIG ))
return (cvar_t *)Cvar_Get( szName, szValue, flags, va( CVAR_GLCONFIG_DESCRIPTION, szName ));
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( flags|FCVAR_CLIENTDLL ));
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL ));
}
/*
@@ -906,9 +908,7 @@ pfnCvar_RegisterVariable
*/
cvar_t *pfnCvar_RegisterGameUIVariable( const char *szName, const char *szValue, int flags )
{
if( FBitSet( flags, FCVAR_GLCONFIG ))
return (cvar_t *)Cvar_Get( szName, szValue, flags, va( CVAR_GLCONFIG_DESCRIPTION, szName ));
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( flags|FCVAR_GAMEUIDLL ));
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_GAMEUIDLL ));
}
/*
@@ -1003,7 +1003,7 @@ pfnGetGameDir
void GAME_EXPORT pfnGetGameDir( char *szGetGameDir )
{
if( !szGetGameDir ) return;
Q_strcpy( szGetGameDir, GI->gamefolder );
Q_strncpy( szGetGameDir, GI->gamefolder, sizeof( GI->gamefolder ));
}
qboolean COM_IsSafeFileToDownload( const char *filename )
@@ -1050,15 +1050,32 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
return true;
}
const char *COM_GetResourceTypeName( resourcetype_t restype )
{
switch( restype )
{
case t_decal: return "decal";
case t_eventscript: return "eventscript";
case t_generic: return "generic";
case t_model: return "model";
case t_skin: return "skin";
case t_sound: return "sound";
case t_world: return "world";
default: return "unknown";
}
}
char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline )
{
size_t size;
char *b;
if( !s ) return NULL;
if( !mempool ) mempool = host.mempool;
b = _Mem_Alloc( mempool, Q_strlen( s ) + 1, false, filename, fileline );
Q_strcpy( b, s );
size = Q_strlen( s ) + 1;
b = _Mem_Alloc( mempool, size, false, filename, fileline );
Q_strncpy( b, s, size );
return b;
}
@@ -1083,7 +1100,6 @@ void *GAME_EXPORT pfnSequenceGet( const char *fileName, const char *entryName )
{
Msg( "Sequence_Get: file %s, entry %s\n", fileName, entryName );
return Sequence_Get( fileName, entryName );
}
@@ -1182,22 +1198,22 @@ void Test_RunCommon( void )
Msg( "Checking COM_ParseFile...\n" );
file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "q" ) && len == 1);
file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "asdf" ) && len == 4);
file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "qwer" ) && len == -1);
file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "f \"f" ) && len == 4);
file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "meow" ) && len == -1);
file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL );
TASSERT( !Q_strcmp( buf, "bark" ) && len == 4);
}
#endif

View File

@@ -76,13 +76,6 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time
typedef struct
{
int numfilenames;
char **filenames;
char *filenamesbuffer;
} search_t;
enum
{
DEV_NONE = 0,
@@ -118,9 +111,8 @@ typedef enum
#include "cvar.h"
#include "con_nprint.h"
#include "crclib.h"
#define XASH_VERSION "0.20" // engine current version
#define XASH_COMPAT_VERSION "0.99" // version we are based on
#include "ref_api.h"
#include "fscallback.h"
// PERFORMANCE INFO
#define MIN_FPS 20.0f // host minimum fps value for maxfps.
@@ -150,18 +142,6 @@ typedef enum
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
#endif
// filesystem flags
#define FS_STATIC_PATH ( 1U << 0 ) // FS_ClearSearchPath will be ignore this path
#define FS_NOWRITE_PATH ( 1U << 1 ) // default behavior - last added gamedir set as writedir. This flag disables it
#define FS_GAMEDIR_PATH ( 1U << 2 ) // just a marker for gamedir path
#define FS_CUSTOM_PATH ( 1U << 3 ) // custom directory
#define FS_GAMERODIR_PATH ( 1U << 4 ) // caseinsensitive
#define FS_GAMEDIRONLY_SEARCH_FLAGS ( FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH )
#define GI SI.GameInfo
#define FS_Gamedir() SI.GameInfo->gamefolder
#define FS_Title() SI.GameInfo->title
#define GameState (&host.game)
#define FORCE_DRAW_VERSION_TIME 5.0f // draw version for 5 seconds
@@ -179,13 +159,13 @@ extern convar_t *scr_download;
extern convar_t *cmd_scripting;
extern convar_t *sv_maxclients;
extern convar_t *cl_allow_levelshots;
extern convar_t *vid_displayfrequency;
extern convar_t host_developer;
extern convar_t *host_limitlocal;
extern convar_t *host_framerate;
extern convar_t *host_maxfps;
extern convar_t sys_timescale;
extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password;
/*
==============================================================
@@ -202,61 +182,6 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts)
========================================================================
*/
typedef struct gameinfo_s
{
// filesystem info
char gamefolder[MAX_QPATH]; // used for change game '-game x'
char basedir[MAX_QPATH]; // base game directory (like 'id1' for Quake or 'valve' for Half-Life)
char falldir[MAX_QPATH]; // used as second basedir
char startmap[MAX_QPATH];// map to start singleplayer game
char trainmap[MAX_QPATH];// map to start hazard course (if specified)
char title[64]; // Game Main Title
float version; // game version (optional)
// .dll pathes
char dll_path[MAX_QPATH]; // e.g. "bin" or "cl_dlls"
char game_dll[MAX_QPATH]; // custom path for game.dll
// .ico path
char iconpath[MAX_QPATH]; // "game.ico" by default
// about mod info
string game_url; // link to a developer's site
string update_url; // link to updates page
char type[MAX_QPATH]; // single, toolkit, multiplayer etc
char date[MAX_QPATH];
size_t size;
int gamemode;
qboolean secure; // prevent to console acess
qboolean nomodels; // don't let player to choose model (use player.mdl always)
qboolean noskills; // disable skill menu selection
qboolean render_picbutton_text; // use font renderer to render WON buttons
char sp_entity[32]; // e.g. info_player_start
char mp_entity[32]; // e.g. info_player_deathmatch
char mp_filter[32]; // filtering multiplayer-maps
char ambientsound[NUM_AMBIENTS][MAX_QPATH]; // quake ambient sounds
int max_edicts; // min edicts is 600, max edicts is 8196
int max_tents; // min temp ents is 300, max is 2048
int max_beams; // min beams is 64, max beams is 512
int max_particles; // min particles is 4096, max particles is 32768
char game_dll_linux[64]; // custom path for game.dll
char game_dll_osx[64]; // custom path for game.dll
qboolean added;
} gameinfo_t;
typedef enum
{
GAME_NORMAL,
GAME_SINGLEPLAYER_ONLY,
GAME_MULTIPLAYER_ONLY
} gametype_t;
typedef struct sysinfo_s
{
string exeName; // exe.filename
@@ -264,9 +189,6 @@ typedef struct sysinfo_s
string basedirName; // name of base directory
string gamedll;
string clientlib;
gameinfo_t *GameInfo; // current GameInfo
gameinfo_t *games[MAX_MODS]; // environment games (founded at each engine start)
int numgames;
} sysinfo_t;
typedef enum
@@ -385,6 +307,16 @@ typedef struct
float scale; // curstate.scale
} tentlist_t;
typedef enum bugcomp_e
{
// default mode, we assume that user dlls are not relying on engine bugs
BUGCOMP_OFF,
// GoldSrc mode, user dlls are relying on GoldSrc specific bugs
// but fixing them may break regular Xash games
BUGCOMP_GOLDSRC,
} bugcomp_t;
typedef struct host_parm_s
{
HINSTANCE hInst;
@@ -426,14 +358,13 @@ typedef struct host_parm_s
qboolean allow_cheats; // this host will allow cheating
qboolean con_showalways; // show console always (developer and dedicated)
qboolean change_game; // initialize when game is changed
qboolean mouse_visible; // vgui override cursor control
qboolean mouse_visible; // vgui override cursor control (never change outside Platform_SetCursorType!)
qboolean shutdown_issued; // engine is shutting down
qboolean force_draw_version; // used when fraps is loaded
float force_draw_version_time;
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
qboolean apply_opengl_config;// when true apply only to opengl cvars and ignore all other commands
qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
int sv_cvars_restored; // count of restored server cvars
qboolean crashed; // set to true if crashed
qboolean daemonized;
qboolean enabledll;
@@ -459,6 +390,14 @@ typedef struct host_parm_s
struct decallist_s *decalList; // used for keep decals, when renderer is restarted or changed
int numdecals;
// bug compatibility level, for very "special" games
bugcomp_t bugcomp;
// measure time to first frame
double starttime;
// count of sleeps can be inserted between frames
double pureframetime;
} host_parm_t;
extern host_parm_t host;
@@ -473,12 +412,20 @@ extern sysinfo_t SI;
typedef void (*xcommand_t)( void );
//
// filesystem_engine.c
//
qboolean FS_LoadProgs( void );
void FS_Init( void );
void FS_Shutdown( void );
//
// cmd.c
//
void Cbuf_Init( void );
void Cbuf_Clear( void );
void Cbuf_AddText( const char *text );
void Cbuf_AddTextf( const char *text, ... ) _format( 1 );
void Cbuf_AddFilteredText( const char *text );
void Cbuf_InsertText( const char *text );
void Cbuf_ExecStuffCmds( void );
@@ -532,56 +479,6 @@ void Mem_PrintStats( void );
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
//
// filesystem.c
//
void FS_Init( void );
void FS_Path( void );
void FS_Rescan( void );
void FS_Shutdown( void );
void FS_ClearSearchPath( void );
void FS_AllowDirectPaths( qboolean enable );
void FS_AddGameDirectory( const char *dir, uint flags );
void FS_AddGameHierarchy( const char *dir, uint flags );
void FS_LoadGameInfo( const char *rootfolder );
const char *FS_GetDiskPath( const char *name, qboolean gamedironly );
byte *W_LoadLump( wfile_t *wad, const char *lumpname, size_t *lumpsizeptr, const char type );
void W_Close( wfile_t *wad );
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
qboolean CRC32_File( dword *crcvalue, const char *filename );
qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] );
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr );
qboolean FS_WriteFile( const char *filename, const void *data, fs_offset_t len );
qboolean COM_ParseVector( char **pfile, float *v, size_t size );
void COM_NormalizeAngles( vec3_t angles );
int COM_FileSize( const char *filename );
void COM_FixSlashes( char *pname );
void COM_FreeFile( void *buffer );
int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCompare );
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly );
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly );
fs_offset_t FS_Write( file_t *file, const void *data, size_t datasize );
fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize );
int FS_VPrintf( file_t *file, const char *format, va_list ap );
int FS_Seek( file_t *file, fs_offset_t offset, int whence );
int FS_Gets( file_t *file, byte *string, size_t bufsize );
int FS_Printf( file_t *file, const char *format, ... ) _format( 2 );
fs_offset_t FS_FileSize( const char *filename, qboolean gamedironly );
int FS_FileTime( const char *filename, qboolean gamedironly );
int FS_Print( file_t *file, const char *msg );
qboolean FS_Rename( const char *oldname, const char *newname );
int FS_FileExists( const char *filename, int gamedironly );
int FS_SetCurrentDirectory( const char *path );
qboolean FS_SysFileExists( const char *path, qboolean casesensitive );
qboolean FS_FileCopy( file_t *pOutput, file_t *pInput, int fileSize );
qboolean FS_Delete( const char *path );
int FS_UnGetc( file_t *file, byte c );
fs_offset_t FS_Tell( file_t *file );
qboolean FS_Eof( file_t *file );
int FS_Close( file_t *file );
int FS_Getc( file_t *file );
fs_offset_t FS_FileLength( file_t *f );
//
// imagelib
//
@@ -669,16 +566,7 @@ int FS_GetStreamPos( stream_t *stream );
void FS_FreeStream( stream_t *stream );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
uint Sound_GetApproxWavePlayLen( const char *filepath );
//
// build.c
//
int Q_buildnum( void );
int Q_buildnum_compat( void );
const char *Q_buildos( void );
const char *Q_buildarch( void );
const char *Q_buildcommit( void );
qboolean Sound_SupportedFileFormat( const char *fileext );
//
// host.c
@@ -699,7 +587,7 @@ void Host_WriteConfig( void );
qboolean Host_IsLocalGame( void );
qboolean Host_IsLocalClient( void );
void Host_ShutdownServer( void );
void Host_Error( const char *error, ... ) _format( 1 ) NORETURN;
void Host_Error( const char *error, ... ) _format( 1 );
void Host_PrintEngineFeatures( void );
void Host_Frame( float time );
void Host_InitDecals( void );
@@ -750,6 +638,7 @@ void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput );
int COM_SaveFile( const char *filename, const void *data, int len );
byte* COM_LoadFileForMe( const char *filename, int *pLength );
qboolean COM_IsSafeFileToDownload( const char *filename );
const char *COM_GetResourceTypeName( resourcetype_t restype );
cvar_t *pfnCVarGetPointer( const char *szVarName );
int pfnDrawConsoleString( int x, int y, char *string );
void pfnDrawSetTextColor( float r, float g, float b );
@@ -857,7 +746,6 @@ char *CL_Userinfo( void );
void CL_LegacyUpdateInfo( void );
void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
int CL_PointContents( const vec3_t point );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength );
int CL_GetDemoComment( const char *demoname, char *comment );
void COM_AddAppDirectoryToSearchPath( const char *pszBaseDir, const char *appName );
@@ -866,7 +754,6 @@ struct cmd_s *Cmd_GetFirstFunctionHandle( void );
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
struct cmdalias_s *Cmd_AliasGetList( void );
const char *Cmd_GetName( struct cmd_s *cmd );
struct pmtrace_s *PM_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe );
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
void SV_StartMusic( const char *curtrack, const char *looptrack, int position );
void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
@@ -879,7 +766,6 @@ void R_ClearAllDecals( void );
void CL_ClearStaticEntities( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
struct cl_entity_s *CL_GetEntityByIndex( int index );
struct player_info_s *CL_GetPlayerInfo( int playerIndex );
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
void CL_HudMessage( const char *pMessage );
const char *CL_MsgInfo( int cmd );
@@ -894,8 +780,6 @@ int SV_GetMaxClients( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsTimeDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean CL_IsBackgroundDemo( void );
qboolean CL_IsBackgroundMap( void );
qboolean SV_Initialized( void );
qboolean CL_LoadProgs( const char *name );
void CL_ProcessFile( qboolean successfully_received, const char *filename );
@@ -935,6 +819,7 @@ const char *Info_ValueForKey( const char *s, const char *key );
void Info_RemovePrefixedKeys( char *start, char prefix );
qboolean Info_RemoveKey( char *s, const char *key );
qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int maxsize );
qboolean Info_SetValueForKeyf( char *s, const char *key, int maxsize, const char *format, ... ) _format( 4 );
qboolean Info_SetValueForStarKey( char *s, const char *key, const char *value, int maxsize );
qboolean Info_IsValid( const char *s );
void Info_WriteVars( file_t *f );
@@ -955,6 +840,12 @@ void UI_SetActiveMenu( qboolean fActive );
void UI_ShowConnectionWarning( void );
void Cmd_Null_f( void );
void Rcon_Print( const char *pMsg );
qboolean COM_ParseVector( char **pfile, float *v, size_t size );
void COM_NormalizeAngles( vec3_t angles );
int COM_FileSize( const char *filename );
void COM_FreeFile( void *buffer );
int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCompare );
char *va( const char *format, ... ) _format( 1 );
// soundlib shared exports
qboolean S_Init( void );
@@ -967,7 +858,6 @@ void S_StopAllSounds( qboolean ambient );
// gamma routines
void BuildGammaTable( float gamma, float brightness );
byte LightToTexGamma( byte b );
byte TextureToGamma( byte b );
//
// identification.c
@@ -982,6 +872,11 @@ void GAME_EXPORT ID_SetCustomClientID( const char *id );
void NET_InitMasters( void );
void NET_SaveMasters( void );
qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data );
qboolean NET_IsMasterAdr( netadr_t adr );
void NET_MasterHeartbeat( void );
void NET_MasterClear( void );
void NET_MasterShutdown( void );
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat );
#ifdef REF_DLL
#error "common.h in ref_dll"

View File

@@ -80,8 +80,9 @@ int Cmd_ListMaps( search_t *t, char *lastmapname, size_t len )
if( f )
{
dheader_t *header;
dheader_t *header;
dextrahdr_t *hdrext;
dlump_t entities;
memset( buf, 0, sizeof( buf ));
FS_Read( f, buf, sizeof( buf ));
@@ -89,10 +90,10 @@ int Cmd_ListMaps( search_t *t, char *lastmapname, size_t len )
ver = header->version;
// check all the lumps and some other errors
if( Mod_TestBmodelLumps( t->filenames[i], buf, true ))
if( Mod_TestBmodelLumps( f, t->filenames[i], buf, true, &entities ))
{
lumpofs = header->lumps[LUMP_ENTITIES].fileofs;
lumplen = header->lumps[LUMP_ENTITIES].filelen;
lumpofs = entities.fileofs;
lumplen = entities.filelen;
ver = header->version;
}
@@ -100,8 +101,7 @@ int Cmd_ListMaps( search_t *t, char *lastmapname, size_t len )
if( hdrext->id == IDEXTRAHEADER ) version = hdrext->version;
Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename ));
COM_StripExtension( entfilename );
COM_DefaultExtension( entfilename, ".ent" );
COM_ReplaceExtension( entfilename, ".ent", sizeof( entfilename ));
ents = (char *)FS_LoadFile( entfilename, NULL, true );
if( !ents && lumplen >= 10 )
@@ -145,7 +145,7 @@ int Cmd_ListMaps( search_t *t, char *lastmapname, size_t len )
}
if( f ) FS_Close(f);
COM_FileBase( t->filenames[i], mapname );
COM_FileBase( t->filenames[i], mapname, sizeof( mapname ));
switch( ver )
{
@@ -193,7 +193,7 @@ qboolean Cmd_GetMapList( const char *s, char *completedname, int length )
t = FS_Search( va( "maps/%s*.bsp", s ), true, con_gamemaps->value );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -230,7 +230,7 @@ qboolean Cmd_GetDemoList( const char *s, char *completedname, int length )
t = FS_Search( va( "%s*.dem", s ), true, true );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -240,7 +240,7 @@ qboolean Cmd_GetDemoList( const char *s, char *completedname, int length )
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "dem" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
numdems++;
}
@@ -276,7 +276,7 @@ qboolean Cmd_GetMovieList( const char *s, char *completedname, int length )
t = FS_Search( va( "media/%s*.avi", s ), true, false );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -286,7 +286,7 @@ qboolean Cmd_GetMovieList( const char *s, char *completedname, int length )
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "avi" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
nummovies++;
}
@@ -323,7 +323,7 @@ qboolean Cmd_GetMusicList( const char *s, char *completedname, int length )
t = FS_Search( va( "media/%s*.*", s ), true, false );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -335,7 +335,7 @@ qboolean Cmd_GetMusicList( const char *s, char *completedname, int length )
if( Q_stricmp( ext, "wav" ) && Q_stricmp( ext, "mp3" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
numtracks++;
}
@@ -368,10 +368,10 @@ qboolean Cmd_GetSavesList( const char *s, char *completedname, int length )
string matchbuf;
int i, numsaves;
t = FS_Search( va( "%s%s*.sav", DEFAULT_SAVE_DIRECTORY, s ), true, true ); // lookup only in gamedir
t = FS_Search( va( DEFAULT_SAVE_DIRECTORY "%s*.sav", s ), true, true ); // lookup only in gamedir
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -381,7 +381,7 @@ qboolean Cmd_GetSavesList( const char *s, char *completedname, int length )
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "sav" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
numsaves++;
}
@@ -418,7 +418,7 @@ qboolean Cmd_GetConfigList( const char *s, char *completedname, int length )
t = FS_Search( va( "%s*.cfg", s ), true, false );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -428,7 +428,7 @@ qboolean Cmd_GetConfigList( const char *s, char *completedname, int length )
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "cfg" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
numconfigs++;
}
@@ -518,7 +518,7 @@ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
t = FS_Search( va( "%s/%s*.txt", clgame.itemspath, s ), true, false );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -528,7 +528,7 @@ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
numitems++;
}
@@ -570,7 +570,7 @@ qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
const char *keyname = Key_KeynumToString( i );
if(( *s == '*' ) || !Q_strnicmp( keyname, s, len))
Q_strcpy( keys[numkeys++], keyname );
Q_strncpy( keys[numkeys++], keyname, sizeof( keys[0] ));
}
if( !numkeys ) return false;
@@ -710,7 +710,7 @@ qboolean Cmd_GetCustomList( const char *s, char *completedname, int length )
t = FS_Search( va( "%s*.hpk", s ), true, false );
if( !t ) return false;
COM_FileBase( t->filenames[0], matchbuf );
COM_FileBase( t->filenames[0], matchbuf, sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true;
@@ -720,7 +720,7 @@ qboolean Cmd_GetCustomList( const char *s, char *completedname, int length )
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "hpk" ))
continue;
COM_FileBase( t->filenames[i], matchbuf );
COM_FileBase( t->filenames[i], matchbuf, sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
numitems++;
}
@@ -761,10 +761,10 @@ qboolean Cmd_GetGamesList( const char *s, char *completedname, int length )
// compare gamelist with current keyword
len = Q_strlen( s );
for( i = 0, numgamedirs = 0; i < SI.numgames; i++ )
for( i = 0, numgamedirs = 0; i < FI->numgames; i++ )
{
if(( *s == '*' ) || !Q_strnicmp( SI.games[i]->gamefolder, s, len))
Q_strcpy( gamedirs[numgamedirs++], SI.games[i]->gamefolder );
if(( *s == '*' ) || !Q_strnicmp( FI->games[i]->gamefolder, s, len))
Q_strncpy( gamedirs[numgamedirs++], FI->games[i]->gamefolder, sizeof( gamedirs[0] ));
}
if( !numgamedirs ) return false;
@@ -825,7 +825,7 @@ qboolean Cmd_GetCDList( const char *s, char *completedname, int length )
for( i = 0, numcdcommands = 0; i < 8; i++ )
{
if(( *s == '*' ) || !Q_strnicmp( cd_command[i], s, len))
Q_strcpy( cdcommands[numcdcommands++], cd_command[i] );
Q_strncpy( cdcommands[numcdcommands++], cd_command[i], sizeof( cdcommands[0] ));
}
if( !numcdcommands ) return false;
@@ -860,6 +860,7 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
byte buf[MAX_SYSPATH];
string mpfilter;
char *buffer;
size_t buffersize;
string result;
int i, size;
search_t *t;
@@ -882,7 +883,8 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
return false;
}
buffer = Mem_Calloc( host.mempool, t->numfilenames * 2 * sizeof( result ));
buffersize = t->numfilenames * 2 * sizeof( result );
buffer = Mem_Calloc( host.mempool, buffersize );
use_filter = COM_CheckStringEmpty( GI->mp_filter ) ? true : false;
for( i = 0; i < t->numfilenames; i++ )
@@ -898,31 +900,31 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
continue;
f = FS_Open( t->filenames[i], "rb", onlyingamedir );
COM_FileBase( t->filenames[i], mapname );
COM_FileBase( t->filenames[i], mapname, sizeof( mapname ));
if( f )
{
int num_spawnpoints = 0;
dheader_t *header;
dlump_t entities;
memset( buf, 0, MAX_SYSPATH );
FS_Read( f, buf, MAX_SYSPATH );
header = (dheader_t *)buf;
// check all the lumps and some other errors
if( !Mod_TestBmodelLumps( t->filenames[i], buf, true ))
if( !Mod_TestBmodelLumps( f, t->filenames[i], buf, true, &entities ))
{
FS_Close( f );
continue;
}
// after call Mod_TestBmodelLumps we gurantee what map is valid
lumpofs = header->lumps[LUMP_ENTITIES].fileofs;
lumplen = header->lumps[LUMP_ENTITIES].filelen;
lumpofs = entities.fileofs;
lumplen = entities.filelen;
Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename ));
COM_StripExtension( entfilename );
COM_DefaultExtension( entfilename, ".ent" );
COM_ReplaceExtension( entfilename, ".ent", sizeof( entfilename ));
ents = (char *)FS_LoadFile( entfilename, NULL, true );
if( !ents && lumplen >= 10 )
@@ -967,8 +969,8 @@ qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
if( num_spawnpoints )
{
// format: mapname "maptitle"\n
Q_sprintf( result, "%s \"%s\"\n", mapname, message );
Q_strcat( buffer, result ); // add new string
Q_snprintf( result, sizeof( result ), "%s \"%s\"\n", mapname, message );
Q_strncat( buffer, result, buffersize ); // add new string
}
}
}
@@ -1027,6 +1029,7 @@ autocomplete_list_t cmd_list[] =
{ "play", 1, Cmd_GetSoundList },
{ "map", 1, Cmd_GetMapList },
{ "cd", 1, Cmd_GetCDList },
{ "mp3", 1, Cmd_GetCDList },
{ NULL }, // termiantor
};
@@ -1039,10 +1042,14 @@ compare first argument with string
*/
static qboolean Cmd_CheckName( const char *name )
{
if( !Q_stricmp( Cmd_Argv( 0 ), name ))
const char *p = Cmd_Argv( 0 );
if( !Q_stricmp( p, name ))
return true;
if( !Q_stricmp( Cmd_Argv( 0 ), va( "\\%s", name )))
if( p[0] == '\\' && !Q_stricmp( &p[1], name ))
return true;
return false;
}
@@ -1324,8 +1331,9 @@ static void Cmd_WriteHelp(const char *name, const char *unused, const char *desc
{
int length;
if( !desc || !Q_strcmp( desc, "" ))
if( !COM_CheckString( desc ))
return; // ignore fantom cmds
if( name[0] == '+' || name[0] == '-' )
return; // key bindings
@@ -1354,7 +1362,6 @@ void Host_FinalizeConfig( file_t *f, const char *config )
FS_Close( f );
FS_Delete( backup );
FS_Rename( config, backup );
FS_Delete( config );
FS_Rename( newcfg, config );
}

View File

@@ -12,7 +12,9 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "common.h"
@@ -23,15 +25,16 @@ Sys_Crash
Crash handler, called from system
================
*/
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP || XASH_CRASHHANDLER == CRASHHANDLER_WIN32
#if XASH_WIN32
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP
#if DBGHELP
#pragma comment( lib, "dbghelp" )
#include <winnt.h>
#include <dbghelp.h>
#include <psapi.h>
#include <time.h>
#ifndef XASH_SDL
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
@@ -187,7 +190,65 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
SymCleanup( process );
}
#endif /* XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP */
static void Sys_GetProcessName( char *processName, size_t bufferSize )
{
char fullpath[MAX_PATH];
GetModuleBaseName( GetCurrentProcess(), NULL, fullpath, sizeof( fullpath ) - 1 );
COM_FileBase( fullpath, processName, bufferSize );
}
static void Sys_GetMinidumpFileName( const char *processName, char *mdmpFileName, size_t bufferSize )
{
time_t currentUtcTime = time( NULL );
struct tm *currentLocalTime = localtime( &currentUtcTime );
Q_snprintf( mdmpFileName, bufferSize, "%s_%s_crash_%d%.2d%.2d_%.2d%.2d%.2d.mdmp",
processName,
Q_buildcommit(),
currentLocalTime->tm_year + 1900,
currentLocalTime->tm_mon + 1,
currentLocalTime->tm_mday,
currentLocalTime->tm_hour,
currentLocalTime->tm_min,
currentLocalTime->tm_sec);
}
static qboolean Sys_WriteMinidump(PEXCEPTION_POINTERS exceptionInfo, MINIDUMP_TYPE minidumpType)
{
HRESULT errorCode;
string processName;
string mdmpFileName;
MINIDUMP_EXCEPTION_INFORMATION minidumpInfo;
Sys_GetProcessName( processName, sizeof( processName ));
Sys_GetMinidumpFileName( processName, mdmpFileName, sizeof( mdmpFileName ));
SetLastError( NOERROR );
HANDLE fileHandle = CreateFile(
mdmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
errorCode = HRESULT_FROM_WIN32( GetLastError( ));
if( !SUCCEEDED( errorCode )) {
CloseHandle( fileHandle );
return false;
}
minidumpInfo.ThreadId = GetCurrentThreadId();
minidumpInfo.ExceptionPointers = exceptionInfo;
minidumpInfo.ClientPointers = FALSE;
qboolean status = MiniDumpWriteDump(
GetCurrentProcess(), GetCurrentProcessId(), fileHandle,
minidumpType, &minidumpInfo, NULL, NULL);
CloseHandle( fileHandle );
return status;
}
#endif /* DBGHELP */
LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
@@ -198,7 +259,7 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
// check to avoid recursive call
host.crashed = true;
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP
#if DBGHELP
Sys_StackTrace( pInfo );
#else
Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
@@ -208,6 +269,26 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
CL_Crashed(); // tell client about crash
else host.status = HOST_CRASHED;
#if DBGHELP
if( Sys_CheckParm( "-minidumps" ))
{
int minidumpFlags = (
MiniDumpWithDataSegs |
MiniDumpWithCodeSegs |
MiniDumpWithHandleData |
MiniDumpWithFullMemory |
MiniDumpWithFullMemoryInfo |
MiniDumpWithIndirectlyReferencedMemory |
MiniDumpWithThreadInfo |
MiniDumpWithModuleHeaders);
if( !Sys_WriteMinidump( pInfo, (MINIDUMP_TYPE)minidumpFlags )) {
// fallback method, create minidump with minimal info in it
Sys_WriteMinidump( pInfo, MiniDumpWithDataSegs );
}
}
#endif
if( host_developer.value <= 0 )
{
// no reason to call debugger in release build - just exit
@@ -237,21 +318,21 @@ void Sys_RestoreCrashHandler( void )
if( oldFilter ) SetUnhandledExceptionFilter( oldFilter );
}
#elif XASH_CRASHHANDLER == CRASHHANDLER_UCONTEXT
#elif XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
// Posix signal handler
#include "library.h"
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
#define HAVE_UCONTEXT_H 1
#endif
#ifdef HAVE_UCONTEXT_H
#include <ucontext.h>
#endif
#include <signal.h>
#include <sys/mman.h>
#include "library.h"
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR "Stack dump:\n"
#define STACK_BACKTRACE_STR_LEN ( sizeof( STACK_BACKTRACE_STR ) - 1 )
#define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 )
#define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 ))
static struct sigaction oldFilter;
#ifdef XASH_DYNAMIC_DLADDR
static int d_dladdr( void *sym, Dl_info *info )
@@ -282,28 +363,18 @@ static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
if( dlinfo.dli_sname )
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
else
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
}
else
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
}
struct sigaction oldFilter;
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR "Stack dump:\n"
#define STACK_BACKTRACE_STR_LEN (sizeof( STACK_BACKTRACE_STR ) - 1)
#define STACK_DUMP_STR_LEN (sizeof( STACK_DUMP_STR ) - 1)
#define ALIGN( x, y ) (((uintptr_t) (x) + ((y)-1)) & ~((y)-1))
static void Sys_Crash( int signal, siginfo_t *si, void *context)
{
void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS!
char message[8192];
int len, logfd, i = 0;
size_t pagesize;
#if XASH_OPENBSD
struct sigcontext *ucontext = (struct sigcontext*)context;
@@ -358,10 +429,10 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
#endif
// safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: %s %s (build %i-%s, %s-%s)\n",
XASH_ENGINE_NAME, XASH_VERSION, Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
#if !XASH_BSD
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
@@ -380,6 +451,7 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
if( pc && bp && sp )
{
size_t pagesize = sysconf( _SC_PAGESIZE );
// try to print backtrace
write( STDERR_FILENO, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
write( logfd, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
@@ -447,7 +519,7 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
void Sys_SetupCrashHandler( void )
{
struct sigaction act;
struct sigaction act = { 0 };
act.sa_sigaction = Sys_Crash;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigaction( SIGSEGV, &act, &oldFilter );
@@ -464,7 +536,7 @@ void Sys_RestoreCrashHandler( void )
sigaction( SIGILL, &oldFilter, NULL );
}
#elif XASH_CRASHHANDLER == CRASHHANDLER_NULL
#else
void Sys_SetupCrashHandler( void )
{

View File

@@ -17,9 +17,23 @@ GNU General Public License for more details.
#include "custom.h"
#include "ref_common.h"
qboolean CustomDecal_Validate( void *raw, int nFileSize )
static rgbdata_t *CustomDecal_LoadImage( const char *path, void *raw, int size )
{
rgbdata_t *test = FS_LoadImage( "#logo.bmp", raw, nFileSize );
const char *testname;
// this way we limit file types
if( !Q_stricmp( COM_FileExtension( path ), "png" ))
testname = "#logo.png";
else testname = "#logo.bmp";
Image_SetForceFlags( IL_LOAD_PLAYER_DECAL );
return FS_LoadImage( testname, raw, size );
}
static qboolean CustomDecal_Validate( const char *path, void *raw, int nFileSize )
{
rgbdata_t *test = CustomDecal_LoadImage( path, raw, nFileSize );
if( test )
{
@@ -97,21 +111,25 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
{
pCust->resource.playernum = playernumber;
if( CustomDecal_Validate( pCust->pBuffer, pResource->nDownloadSize ))
if( CustomDecal_Validate( pResource->szFileName, pCust->pBuffer, pResource->nDownloadSize ))
{
if( !FBitSet( flags, FCUST_IGNOREINIT ))
{
if( pResource->nDownloadSize >= (1 * 1024) && pResource->nDownloadSize <= ( 16 * 1024 ))
if( pResource->nDownloadSize >= (1 * 1024) && pResource->nDownloadSize <= ( 128 * 1024 ))
{
pCust->bTranslated = true;
pCust->nUserData1 = 0;
pCust->nUserData2 = 1;
if( !FBitSet( flags, FCUST_WIPEDATA ))
pCust->pInfo = FS_LoadImage( "#logo.bmp", pCust->pBuffer, pCust->resource.nDownloadSize );
pCust->pInfo = CustomDecal_LoadImage( pResource->szFileName, pCust->pBuffer, pCust->resource.nDownloadSize );
else pCust->pInfo = NULL;
if( nLumps ) *nLumps = 1;
}
else
{
Con_Printf( S_WARN "Ignoring custom decal \"%s\": wrong size (%i bytes)\n", pResource->szFileName, pResource->nDownloadSize );
}
}
}
}

View File

@@ -21,6 +21,33 @@ GNU General Public License for more details.
convar_t *cvar_vars = NULL; // head of list
convar_t *cmd_scripting;
#ifdef HACKS_RELATED_HLMODS
typedef struct cvar_filter_quirks_s
{
const char *gamedir; // gamedir to enable for
const char *cvars; // list of cvars should be excluded from filter
} cvar_filter_quirks_t;
static cvar_filter_quirks_t cvar_filter_quirks[] =
{
// EXAMPLE:
//{
// "valve",
// "test;test1;test100"
//},
{
"ricochet",
"r_drawviewmodel",
},
{
"dod",
"cl_dodmusic" // Day of Defeat Beta 1.3 cvar
},
};
static cvar_filter_quirks_t *cvar_active_filter_quirks = NULL;
#endif
CVAR_DEFINE_AUTO( cl_filterstuffcmd, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "filter commands coming from server" );
/*
@@ -72,10 +99,16 @@ Cvar_BuildAutoDescription
build cvar auto description that based on the setup flags
============
*/
const char *Cvar_BuildAutoDescription( int flags )
const char *Cvar_BuildAutoDescription( const char *szName, int flags )
{
static char desc[256];
if( FBitSet( flags, FCVAR_GLCONFIG ))
{
Q_snprintf( desc, sizeof( desc ), CVAR_GLCONFIG_DESCRIPTION, szName );
return desc;
}
desc[0] = '\0';
if( FBitSet( flags, FCVAR_EXTDLL ))
@@ -220,6 +253,24 @@ const char *Cvar_ValidateString( convar_t *var, const char *value )
return pszValue;
}
/*
============
Cvar_ValidateVarName
============
*/
static qboolean Cvar_ValidateVarName( const char *s, qboolean isvalue )
{
if( !s )
return false;
if( Q_strchr( s, '\\' ) && !isvalue )
return false;
if( Q_strchr( s, '\"' ))
return false;
if( Q_strchr( s, ';' ) && !isvalue )
return false;
return true;
}
/*
============
Cvar_UnlinkVar
@@ -368,7 +419,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
// which executed from the config file. So we don't need to
// change value here: we *already* have actual value from config.
// in other cases we need to rewrite them
if( Q_strcmp( var->desc, "" ))
if( COM_CheckStringEmpty( var->desc ))
{
// directly set value
freestring( var->string );
@@ -428,6 +479,23 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
return var;
}
/*
============
Cvar_Getf
============
*/
convar_t *Cvar_Getf( const char *var_name, int flags, const char *description, const char *format, ... )
{
char value[MAX_VA_STRING];
va_list args;
va_start( args, format );
Q_vsnprintf( value, sizeof( value ), format, args );
va_end( args );
return Cvar_Get( var_name, value, flags, description );
}
/*
============
Cvar_RegisterVariable
@@ -495,6 +563,113 @@ void Cvar_RegisterVariable( convar_t *var )
#endif
}
/*
============
Cvar_Set2
============
*/
static convar_t *Cvar_Set2( const char *var_name, const char *value )
{
convar_t *var;
const char *pszValue;
qboolean dll_variable = false;
qboolean force = false;
if( !Cvar_ValidateVarName( var_name, false ))
{
Con_DPrintf( S_ERROR "Invalid cvar name string: %s\n", var_name );
return NULL;
}
var = Cvar_FindVar( var_name );
if( !var )
{
// if cvar not found, create it
return Cvar_Get( var_name, value, FCVAR_USER_CREATED, NULL );
}
else
{
if( !Cmd_CurrentCommandIsPrivileged( ))
{
if( FBitSet( var->flags, FCVAR_PRIVILEGED ))
{
Con_Printf( "%s is priveleged.\n", var->name );
return var;
}
if( cl_filterstuffcmd.value > 0.0f && FBitSet( var->flags, FCVAR_FILTERABLE ))
{
Con_Printf( "%s is filterable.\n", var->name );
return var;
}
}
}
// use this check to prevent acessing for unexisting fields
// for cvar_t: latched_string, description, etc
dll_variable = FBitSet( var->flags, FCVAR_EXTDLL );
// check value
if( !value )
{
if( !FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED ))
{
Con_Printf( "%s has no default value and can't be reset.\n", var->name );
return var;
}
if( dll_variable )
value = "0";
else
value = var->def_string; // reset to default value
}
if( !Q_strcmp( value, var->string ))
return var;
// any latched values not allowed for game cvars
if( dll_variable )
force = true;
if( !force )
{
if( FBitSet( var->flags, FCVAR_READ_ONLY ))
{
Con_Printf( "%s is read-only.\n", var->name );
return var;
}
if( FBitSet( var->flags, FCVAR_CHEAT ) && !host.allow_cheats )
{
Con_Printf( "%s is cheat protected.\n", var->name );
return var;
}
// just tell user about deferred changes
if( FBitSet( var->flags, FCVAR_LATCH ) && ( SV_Active() || CL_Active( )))
Con_Printf( "%s will be changed upon restarting.\n", var->name );
}
pszValue = Cvar_ValidateString( var, value );
// nothing to change
if( !Q_strcmp( pszValue, var->string ))
return var;
// fill it cls.userinfo, svs.serverinfo
if( !Cvar_UpdateInfo( var, pszValue, true ))
return var;
// and finally changed the cvar itself
freestring( var->string );
var->string = copystring( pszValue );
var->value = Q_atof( var->string );
// tell engine about changes
Cvar_Changed( var );
return var;
}
/*
============
Cvar_DirectSet
@@ -777,6 +952,39 @@ static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
if( cl_filterstuffcmd.value <= 0.0f )
return true;
#ifdef HACKS_RELATED_HLMODS
// check if game-specific filter exceptions should be applied
// TODO: for cmd exceptions, make generic function
if( cvar_active_filter_quirks )
{
const char *cur, *next;
cur = cvar_active_filter_quirks->cvars;
next = Q_strchr( cur, ';' );
// TODO: implement Q_strchrnul
while( cur && *cur )
{
size_t len = next ? next - cur : Q_strlen( cur );
// found, quit
if( !Q_strnicmp( cur, v->name, len ))
return true;
if( next )
{
cur = next + 1;
next = Q_strchr( cur, ';' );
}
else
{
// stop
cur = NULL;
}
}
}
#endif
if( FBitSet( v->flags, FCVAR_FILTERABLE ))
return false;
@@ -840,8 +1048,6 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged )
else
{
Cvar_DirectSet( v, Cmd_Argv( 1 ));
if( host.apply_game_config )
host.sv_cvars_restored++;
return true;
}
}
@@ -884,7 +1090,41 @@ void Cvar_Toggle_f( void )
v = !Cvar_VariableInteger( Cmd_Argv( 1 ));
Cvar_Set( Cmd_Argv( 1 ), va( "%i", v ));
Cvar_Set( Cmd_Argv( 1 ), v ? "1" : "0" );
}
/*
============
Cvar_Set_f
Allows setting and defining of arbitrary cvars from console, even if they
weren't declared in C code.
============
*/
void Cvar_Set_f( void )
{
int i, c, l = 0, len;
char combined[MAX_CMD_TOKENS];
c = Cmd_Argc();
if( c < 3 )
{
Msg( S_USAGE "set <variable> <value>\n" );
return;
}
combined[0] = 0;
for( i = 2; i < c; i++ )
{
len = Q_strlen( Cmd_Argv(i) + 1 );
if( l + len >= MAX_CMD_TOKENS - 2 )
break;
Q_strncat( combined, Cmd_Argv( i ), sizeof( combined ));
if( i != c-1 ) Q_strncat( combined, " ", sizeof( combined ));
l += len;
}
Cvar_Set2( Cmd_Argv( 1 ), combined );
}
/*
@@ -932,27 +1172,32 @@ void Cvar_List_f( void )
{
convar_t *var;
const char *match = NULL;
char *value;
int count = 0;
size_t matchlen = 0;
if( Cmd_Argc() > 1 )
{
match = Cmd_Argv( 1 );
matchlen = Q_strlen( match );
}
for( var = cvar_vars; var; var = var->next )
{
char value[MAX_VA_STRING];
if( var->name[0] == '@' )
continue; // never shows system cvars
if( match && !Q_stricmpext( match, var->name ))
if( match && !Q_strnicmpext( match, var->name, matchlen ))
continue;
if( Q_colorstr( var->string ))
value = va( "\"%s\"", var->string );
else value = va( "\"^2%s^7\"", var->string );
Q_snprintf( value, sizeof( value ), "\"%s\"", var->string );
else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string );
if( FBitSet( var->flags, FCVAR_EXTENDED|FCVAR_ALLOCATED ))
Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, var->desc );
else Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, Cvar_BuildAutoDescription( var->flags ));
else Con_Printf( " %-*s %s ^3%s^7\n", 32, var->name, value, Cvar_BuildAutoDescription( var->name, var->flags ));
count++;
}
@@ -994,16 +1239,37 @@ Reads in all archived cvars
void Cvar_Init( void )
{
cvar_vars = NULL;
cvar_active_filter_quirks = NULL;
cmd_scripting = Cvar_Get( "cmd_scripting", "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" );
Cvar_RegisterVariable (&host_developer); // early registering for dev
Cvar_RegisterVariable( &host_developer ); // early registering for dev
Cvar_RegisterVariable( &cl_filterstuffcmd );
Cmd_AddRestrictedCommand( "setgl", Cvar_SetGL_f, "change the value of a opengl variable" ); // OBSOLETE
Cmd_AddRestrictedCommand( "toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" );
Cmd_AddRestrictedCommand( "reset", Cvar_Reset_f, "reset any type variable to initial value" );
Cmd_AddCommand( "set", Cvar_Set_f, "create or change the value of a console variable" );
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
}
/*
============
Cvar_PostFSInit
============
*/
void Cvar_PostFSInit( void )
{
int i;
for( i = 0; i < ARRAYSIZE( cvar_filter_quirks ); i++ )
{
if( !Q_stricmp( cvar_filter_quirks[i].gamedir, GI->gamefolder ))
{
cvar_active_filter_quirks = &cvar_filter_quirks[i];
break;
}
}
}
#if XASH_ENGINE_TESTS
#include "tests.h"

View File

@@ -48,6 +48,7 @@ typedef struct convar_s
#define FCVAR_VIDRESTART (1<<20) // recreate the window is cvar with this flag was changed
#define FCVAR_TEMPORARY (1<<21) // these cvars holds their values and can be unlink in any time
#define FCVAR_MOVEVARS (1<<22) // this cvar is a part of movevars_t struct that shared between client and server
#define FCVAR_USER_CREATED (1<<23) // created by a set command (dll's used)
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
@@ -62,12 +63,13 @@ cvar_t *Cvar_GetList( void );
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
void Cvar_RegisterVariable( convar_t *var );
convar_t *Cvar_Get( const char *var_name, const char *value, int flags, const char *description );
convar_t *Cvar_Getf( const char *var_name, int flags, const char *description, const char *format, ... ) _format( 4 );
void Cvar_LookupVars( int checkbit, void *buffer, void *ptr, setpair_t callback );
void Cvar_FullSet( const char *var_name, const char *value, int flags );
void Cvar_DirectSet( convar_t *var, const char *value );
void Cvar_Set( const char *var_name, const char *value );
void Cvar_SetValue( const char *var_name, float value );
const char *Cvar_BuildAutoDescription( int flags );
const char *Cvar_BuildAutoDescription( const char *szName, int flags );
float Cvar_VariableValue( const char *var_name );
int Cvar_VariableInteger( const char *var_name );
const char *Cvar_VariableString( const char *var_name );
@@ -77,6 +79,7 @@ void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void );
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void );
void Cvar_PostFSInit( void );
void Cvar_Unlink( int group );
#endif//CVAR_H

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