Compare commits

...

173 Commits

Author SHA1 Message Date
Alibek Omarov
98acbbad01 engine: rework how HTTP finite-machine works, use function pointers instead of enum. Preliminary chunked transfer and compression support. 2024-10-28 02:40:18 +03:00
Alibek Omarov
eb72b6baee ref: gl: fix r_shadows and gl_vbo registration order. It must be registered before reading renderer config 2024-10-28 02:10:24 +03:00
Alibek Omarov
422addcbb6 public: make Q_atoi_hex public, check for 0x prefix 2024-10-28 02:09:05 +03:00
Alibek Omarov
4a58be2aa0 ref: gl: deregister timerefresh command in renderer, as it's renderer-specific 2024-10-28 01:59:39 +03:00
Alibek Omarov
562b54839c engine: client: console: fix printing multiline messages with CRLF, like HTTP headers 2024-10-28 01:58:47 +03:00
Alibek Omarov
639eaa9416 engine: split HTTP client into a separate file 2024-10-27 17:07:35 +03:00
Alibek Omarov
6c6cb65b30 mainui: update 2024-10-27 14:33:27 +03:00
Alibek Omarov
8ea8437e19 3rdparty: opus: downgrade to 1.4.0 2024-10-27 14:32:43 +03:00
Alibek Omarov
2656eb1aeb engine: fix A2S_GOLDSRC_INFO, it must always include Source Engine Query and a null terminator 2024-10-26 20:24:31 +03:00
Alibek Omarov
fa1e92b127 engine: request file from server if HTTP locations failed 2024-10-26 20:24:31 +03:00
Alibek Omarov
cff8ee13e6 engine: rcon refactoring. Use sizebuf_t to concatenate commands. Only call redirect when we're executing command. 2024-10-26 19:37:30 +03:00
Alibek Omarov
3956e3863e engine: make Netchan_TransmitBits accept const data 2024-10-26 19:19:37 +03:00
Alibek Omarov
9600218757 engine: client: send tempdecal.wad to GoldSrc servers 2024-10-26 19:16:59 +03:00
Alibek Omarov
2db7cb0d64 engine: client: when validating, we're supposed to send move and delta commands 2024-10-26 19:12:52 +03:00
Alibek Omarov
267a70d621 engine: common: don't print svc/clc_nop with net_recv/send_debug 2024-10-26 05:18:09 +03:00
Alibek Omarov
667bedab82 engine: client: allow reading upper directories for clc_fileconsistency. Initialize md5 digest, add note about servers relying on uninitialized md5 value in some cases. 2024-10-26 05:17:24 +03:00
Alibek Omarov
49990a0859 mainui: update 2024-10-26 05:15:55 +03:00
Alibek Omarov
f7c4cd9398 engine: client: allow case-insensitive goldsrc proto argument in connect and queryserver commands 2024-10-26 05:15:46 +03:00
Alibek Omarov
cd4f4d5ad4 engine: common: fix hpkextract command 2024-10-26 05:15:09 +03:00
Alibek Omarov
fe429fe213 engine: common: net_ws: fix HTTP request when server have custom port and/or doesn't have slash at the end of URL. Set Accept: */* just in case. 2024-10-26 05:14:51 +03:00
Alibek Omarov
0a24ca3fe2 engine: client: fix svc_updateuserinfo for inactive player on GoldSrc servers 2024-10-26 05:13:22 +03:00
Alibek Omarov
8c93a0d247 engine: client: allow playing back demos recorded on GoldSrc servers 2024-10-26 05:12:11 +03:00
Alibek Omarov
5c75dda864 mainui: update 2024-10-26 02:42:30 +03:00
Alibek Omarov
55bdded6a4 engine: add pfnIsCvarReadOnly to mainui API 2024-10-25 05:09:02 +03:00
Alibek Omarov
25b2c0f7e3 ref: gl: use FCVAR_GLCONFIG on VBO and detail textures cvars, so it always gets saved to opengl.cfg 2024-10-24 23:31:16 +03:00
Alibek Omarov
ed522852cf mainui: update 2024-10-24 23:30:23 +03:00
Alibek Omarov
224e42d345 engine: platform: android: make dlsym-weak C++ again (because of struct soinfo definition). Reformat linker.h file as well. 2024-10-24 17:54:09 +03:00
Alibek Omarov
128a1f59a9 engine: cleanup XASH_64BIT usage. Always use it from build.h 2024-10-24 16:39:09 +03:00
Alibek Omarov
40ffde0439 3rdparty: opus: update to 1.5.2 2024-10-24 15:51:41 +03:00
Alibek Omarov
ec5578a437 ref: gl: vgl_shim: remove -fno-PIC to properly link it with shared library 2024-10-24 15:47:06 +03:00
Alibek Omarov
1cf40a2d17 engine: wscript: remove useless globs 2024-10-24 15:46:33 +03:00
Alibek Omarov
958ea0ac1d scripts: gha: temporarily enable verbose build output for PSVita 2024-10-24 02:05:47 +03:00
Alibek Omarov
a9fdae28b2 engine: platform: android: reformat dlsym-weak and make it C only 2024-10-24 02:04:52 +03:00
Alibek Omarov
3d9eb869b0 ci: fix netbsd bzip2 package name 2024-10-24 00:57:18 +03:00
Alibek Omarov
8162c6d42f scripts: waifulib: xshlib: prepend xshlib so it's always first 2024-10-24 00:46:43 +03:00
Alibek Omarov
48a9f17222 filesystem: only export GetFSAPI, CreateInterface is useless with static linking (and should be implemented differently) 2024-10-24 00:40:47 +03:00
Alibek Omarov
e381d04094 ref: simplify wscripts, remove gl2_shim unused wscript, fix non-existent export in exports.txt 2024-10-24 00:40:12 +03:00
Alibek Omarov
0e79326571 waf: upgrade to latest, fix for api changes 2024-10-24 00:37:05 +03:00
Alibek Omarov
f7eb8cd913 engine: wscript: ensure we always add needed features when mixing C and C++ objects. Simplify bld call for all platforms 2024-10-23 23:22:23 +03:00
Alibek Omarov
a15c1f99b2 wscript: remove useless features 2024-10-23 23:20:47 +03:00
Alibek Omarov
ba2191172d ci: add bzip2 for sourcehut CI 2024-10-23 20:25:26 +03:00
Alibek Omarov
6ab2c9dbbf engine: client: fix out of bounds access with some ticket generators
* Update MultiEmulator submodule
2024-10-22 02:13:36 +03:00
Alibek Omarov
7da460d4b1 public: bump miniz to latest release 2024-10-21 21:22:50 +03:00
Alibek Omarov
ffe7b1f4a1 3rdparty: MultiEmulator: move it to submodule 2024-10-21 14:08:16 +03:00
Alibek Omarov
6a1f502d25 3rdparty: MultiEmulator: remove unused code 2024-10-21 06:30:53 +03:00
Alibek Omarov
434359ea01 3rdparty: update mainui and extras 2024-10-21 06:19:11 +03:00
Alibek Omarov
ae2ad6ddf2 3rdparty: add MultiEmulator by 2010kohtep
* patched to be portable, turned into a static library
* integrated to the engine
2024-10-21 06:19:11 +03:00
Alibek Omarov
ec11683dc5 engine: client: minor fix, reference cl_allowdownload cvar actual name 2024-10-21 04:49:25 +03:00
Alibek Omarov
47318b0c14 engine: server: minor fix, use __func__ instead of the function name in debug message 2024-10-21 02:32:07 +03:00
Alibek Omarov
60d6214ad7 engine: client: implement parsing GoldSrc server query response for mainui_cpp 2024-10-21 02:31:45 +03:00
Alibek Omarov
a3e26a21a7 engine: common: net_chan: as we expect pfnBlockSize to be always set, use it to determine if netchan was initialized or not 2024-10-21 02:30:49 +03:00
Alibek Omarov
d0f3a6f74b engine: client: add command queryserver for mainui to query a specific address. Make server querying commands restricted 2024-10-20 02:22:09 +03:00
Alibek Omarov
fee236a050 engine: common: net_ws: make NET_IsLocalAddress inline 2024-10-19 14:08:27 +03:00
Alibek Omarov
e3e4bcc015 engine: global refactoring of connectionless packets, now they can be customized from single protocol.h header 2024-10-19 14:05:00 +03:00
Alibek Omarov
2d546ccbf7 engine: implement CL_MsgInfo for dedicated server 2024-10-18 03:13:43 +03:00
Alibek Omarov
b41804bb5b mainui: update 2024-10-17 14:56:38 +03:00
Alibek Omarov
47a04df189 wscript: try to fix Windows XP compatibility on 32-bit binaries 2024-10-17 14:56:10 +03:00
Alibek Omarov
2efedaf46c pm_shared: mark PM_TraceSurface call in PMove API as Xash3D specific 2024-10-17 03:36:29 +03:00
Alibek Omarov
49e43c830b engine: client: fix formatting error in CL_ParseExtraInfo 2024-10-16 22:29:21 +03:00
Alibek Omarov
763e101208 ref: preserve aspect ratio when saving level and save shots 2024-10-16 21:35:52 +03:00
Alibek Omarov
e39a62b1fd mainui: update 2024-10-16 08:33:44 +03:00
Alibek Omarov
da76abda75 engine: even more refactorings to avoid global cls.legacymode usage, now with GoldSrc server autodetection 2024-10-16 07:31:27 +03:00
Alibek Omarov
829d7d0a7e engine: client: CL_SendConnectPacket refactoring 2024-10-16 07:02:23 +03:00
Alibek Omarov
9f6372b305 engine: client: implement GoldSrc fragment size limits 2024-10-16 07:00:10 +03:00
Alibek Omarov
12edd782c6 engine: common: net_chan: always rely on pfnBlockSize being non-null 2024-10-16 06:59:33 +03:00
Alibek Omarov
0b59fa9416 engine: swap Cvar_VariableInteger and simple integer checks for performance 2024-10-16 06:57:46 +03:00
Alibek Omarov
cc0f12ed26 engine: client: add stubs for richpresence commands added in HL25 2024-10-16 05:57:32 +03:00
Alibek Omarov
f42553d0e1 readme: install 32-bit deps on Ubuntu with aptitude, as it's less prone to fuck up entire system (remove random packages, bootloader, etc...) [skip ci] 2024-10-16 00:32:23 +03:00
Alibek Omarov
e7564420c9 engine: fix some ubsan warnings (alignment, integer limits...) 2024-10-16 00:32:22 +03:00
Alibek Omarov
e81a0ded11 engine: client: fix sendres message for GoldSrc protocol 2024-10-16 00:32:22 +03:00
Alibek Omarov
a32c702dbd engine: client: avoid useless check on empty clc_resourcelist, which will never be false 2024-10-15 06:15:22 +03:00
Alibek Omarov
23a5ed71de engine: easier MSG_EndBitWriting byte padding 2024-10-15 06:14:37 +03:00
Alibek Omarov
245dc97cfb engine: semi-correct printing GoldSrc client messages 2024-10-15 06:12:31 +03:00
Alibek Omarov
ece204c30f engine: common: add cvars net_send_debug and net_recv_debug to print server/client messages to console 2024-10-15 06:11:57 +03:00
Alibek Omarov
1bd59096fd engine: client: implement miscellaneous, often unused, GoldSrc protocol messages 2024-10-15 06:10:25 +03:00
Alibek Omarov
0b02c2c6a7 engine: client: fix disconnect on GoldSrc servers 2024-10-15 06:08:21 +03:00
Alibek Omarov
6a61a499e9 engine: client: don't send useless/empty clc_move commands while we're connecting to server 2024-10-15 06:07:57 +03:00
Alibek Omarov
6b1c283082 engine: client: fix svc_event parsing 2024-10-15 06:07:06 +03:00
Alibek Omarov
5402a9611e engine: common: fix discarded const qualifier 2024-10-14 19:41:36 +03:00
Alibek Omarov
43e06ccd45 engine: common: make some simple functions inlined 2024-10-14 19:20:47 +03:00
Alibek Omarov
f52c825bf5 engine: make some global variables static and const, make even more functions static if possible 2024-10-14 19:19:46 +03:00
Alibek Omarov
bf8b709372 engine: move pm_debug particle functions to client, as they are never used on server 2024-10-14 19:11:26 +03:00
Alibek Omarov
fdf82e5270 engine: client: cleanup tent and efx code, make global variables static, remove unused functions 2024-10-14 18:08:01 +03:00
Alibek Omarov
0224a1b66b engine: client: better debug messages for GoldSrc entities packet parsing 2024-10-14 17:59:17 +03:00
Alibek Omarov
505ad6d69b engine: server: reinitalize delta in case if delta was shutdown by client and some tables were omitted (movevars after using GoldSrc server) 2024-10-14 06:56:17 +03:00
Alibek Omarov
5bcd573821 engine: remove goldsrc meta delta table reinitialization 2024-10-14 06:54:41 +03:00
Alibek Omarov
c5a291d9c7 engine: minor refactoring 2024-10-14 05:17:21 +03:00
Alibek Omarov
232a8c1148 engine: common: net_ws: don't expect more than 5 splits for GoldSrc protocol 2024-10-14 05:17:03 +03:00
Alibek Omarov
663f6eaf5c ref: turn r_shadows into extended convar_t 2024-10-14 04:18:35 +03:00
Alibek Omarov
9d3210259c ref: set hullcolor (used by r_drawentities) as const 2024-10-14 04:15:48 +03:00
Alibek Omarov
4ec6c2f7cf engine: client: support vox sentence that starts with leading slash 2024-10-14 04:13:10 +03:00
Alibek Omarov
8452bec877 engine: client: reduce reads of cls.legacymode 2024-10-14 04:13:10 +03:00
Alibek Omarov
0d4296e0e1 engine: client: explicitly pass protocol to svc_time parser 2024-10-14 04:13:10 +03:00
Alibek Omarov
2b85da3bc9 engine: client: fix parsing svc_setpause and svc_goldsrc_timescale for GoldSrc protocol 2024-10-14 04:13:10 +03:00
Alibek Omarov
17f194b9a3 engine: client: consolidate usermsg registering and parsing for multiple protocols 2024-10-14 04:13:10 +03:00
Alibek Omarov
ff47fbaedc engine: client: another fix baselines and entities parsing for GoldSrc, ensure we always call MSG_EndBitWriting 2024-10-14 04:13:10 +03:00
Alibek Omarov
87c88f7463 engine: client: fix svc_particles parsing on GoldSrc protocol 2024-10-14 04:13:10 +03:00
Alibek Omarov
60fd5f7ab8 engine: client: stub svc_restoresound for legacy protocol, it's only used during save restore which is unuseful for us
* Set sequence flag for restored sound, even though we don't support sequences anymore.
2024-10-14 04:13:10 +03:00
Alibek Omarov
5ceab059dc engine: client: add function for parsing common protocol messages, which structure is enforced by server DLL compatibility 2024-10-14 04:13:10 +03:00
Alibek Omarov
67c898f9ad engine: client: improve server data parsing for GoldSrc, restore nick name and remove unuseful userinfo keys before connection 2024-10-14 04:13:10 +03:00
Alibek Omarov
d903187eea public: make crc value init functions inline, move hex2char/ex2string to crclib and make them private to it 2024-10-14 04:13:10 +03:00
54ac
653f0841e4 ref: gl: restore r_shadows (#1843) 2024-10-13 17:15:29 +03:00
Alibek Omarov
10bfadb556 engine: client: support svc_disconnect reason messages for GoldSrc protocol 2024-10-11 20:58:46 +03:00
Alibek Omarov
0b2cc066dd engine: fix signed integers encoding with alternate format for GoldSrc protocol 2024-10-11 20:36:09 +03:00
Alibek Omarov
60ab13d216 engine: client: always add [Xash3D] to the nickname on GoldSrc servers 2024-10-11 19:32:16 +03:00
Alibek Omarov
f90c658567 engine: client: skip voice data for GoldSrc protocol to avoid svc_bad 2024-10-11 19:31:41 +03:00
Alibek Omarov
0c54895877 engine: client: add unmunge function for consistency info for GoldSrc protocol 2024-10-11 18:41:17 +03:00
Alibek Omarov
4eb54328f8 engine: client: various connection setup fixes for GoldSrc proto
* always add "steam" to getchallenge message
* cdkey md5 should be sent with lowercase
* strip null terminator from connect message
2024-10-11 18:41:16 +03:00
Alibek Omarov
b1189db9c5 engine: client: avoid clc_move spam when we're connected but not spawned yet 2024-10-11 00:08:21 +03:00
Alibek Omarov
869578f1ba engine: client: lie about sv_version for GoldSrc protocol 2024-10-11 00:08:21 +03:00
Alibek Omarov
3320f776ce engine: client: implement correct clc_fileconsistency response for GoldSrc 2024-10-11 00:08:21 +03:00
Alibek Omarov
1d64635783 engine: correctly check for cls.legacymode, as it's not a boolean anymore 2024-10-11 00:08:21 +03:00
Alibek Omarov
bbb076c0d4 engine: client: voice: don't print about unsupported codec with empty string name 2024-10-10 23:40:23 +03:00
Alibek Omarov
fe2a4d0428 engine: common: net_encode: remove DT_SIGNED_GS flag just in case 2024-10-10 23:40:23 +03:00
Alibek Omarov
6bdc1941e6 engine: common: netchan: only compress with BZip2 when it's efficient 2024-10-10 23:40:23 +03:00
Alibek Omarov
9188905145 engine: client: fix map CRC match with GoldSrc protocol 2024-10-10 23:40:23 +03:00
Alibek Omarov
3f2fbb10d8 engine: client: only send continueloading for legacy protocol 2024-10-10 23:40:23 +03:00
Alibek Omarov
9c97235fe8 engine: client: implement GoldSrc connectionless print message 2024-10-10 23:40:23 +03:00
Alibek Omarov
70a13b47db engine: client: implement randomized cdkey for GoldSrc protocol 2024-10-10 23:40:22 +03:00
Alibek Omarov
18afaf0eaf engine: client: more accurate clc_move for GoldSrc protocol 2024-10-10 23:38:55 +03:00
Alibek Omarov
8b8c3d8116 scripts: waifulib: xcompile: define WebAssembly target as DEST_OS wasi 2024-10-10 16:13:54 +03:00
Alibek Omarov
514fc9fe43 public: reserve identifier for WebAssembly port 2024-10-10 16:13:20 +03:00
Alibek Omarov
5d8923d69c scripts: waifulib: sdl2: fix build on macOS 2024-10-10 15:44:32 +03:00
Alibek Omarov
5db880af57 engine: wscript: add an ability to build with SDL3 2024-10-10 06:13:56 +03:00
Alibek Omarov
c05db9ce58 waf: upgrade waifu to latest master 2024-10-10 06:13:32 +03:00
Alibek Omarov
04079abe00 scripts: waifulib: re-export sdl2.py from waifu repository, add sdl3 compatibility 2024-10-10 06:13:23 +03:00
Alibek Omarov
8054b69f73 readme: add GoldSrc protocol support, add RedHat/Fedora build instructions, better wording [skip ci] 2024-10-10 01:58:56 +03:00
SNMetamorph
b5ee777466 Documentation: added article about GoldSrc network protocol support 2024-10-10 01:52:44 +03:00
Alibek Omarov
96f3061709 ref: gl: show texture size in memory, skip empty pages, skip empty 0-th texture 2024-10-09 02:44:26 +03:00
Alibek Omarov
420c5a4ff3 ref: gl: set numeric value for wrappers macros, similar to build.h macros 2024-10-09 02:01:10 +03:00
Alibek Omarov
e8f6476e8c ref: gl: patch to compile with nanogl (nanogl doesn't impement glTexCoord3f) 2024-10-09 00:31:05 +03:00
Alibek Omarov
65ec35b732 engine: client: fix bug in temp entity parsing caused by find and replace 2024-10-08 23:02:02 +03:00
Alibek Omarov
8d731b5d15 engine: common: fix for dedicated again 2024-10-08 16:41:25 +03:00
Alibek Omarov
38c0dc4551 3rdparty: bzip2: properly use stdio-free version, don't include tests and utils to the build 2024-10-08 15:39:56 +03:00
Alibek Omarov
4d8cb0469f scripts: gha: build Linux binaries with bundled deps, to avoid external dependency on libbz2 2024-10-08 13:09:34 +03:00
Alibek Omarov
62cb8f5ba6 3rdparty: bzip2: forgot to add actual bz_version.h file 2024-10-08 13:07:42 +03:00
Alibek Omarov
97c75d96d5 3rdparty: bzip2: build with BZ_NO_STDIO 2024-10-08 13:06:02 +03:00
Alibek Omarov
f5ae806b31 ref: gl: add r_showtextures implementation by ncuxonaT
Main changes made by me besides engine differences:
* Text color changed to pure white for better readability
* An attempt to draw texture name in full size
2024-10-08 12:56:07 +03:00
Alibek Omarov
482dc3a5a5 engine: client: fix joining current protocol servers 2024-10-08 12:43:29 +03:00
Alibek Omarov
a8539ac004 3rdparty: bzip2: add pre-generated bz_version.h header as some generators (like cmake.py) don't understand subst yet 2024-10-08 12:27:41 +03:00
Alibek Omarov
9970c56218 engine: common: disable bzip2 for dedicated server, it's not used there 2024-10-08 12:14:37 +03:00
Alibek Omarov
480218412a engine: client: remove voidptr hack from IN_EngineAppendMove, just use usercmd_t directly 2024-10-08 04:07:03 +03:00
Alibek Omarov
6ae09d2866 engine: client: support GoldSrc signon and refactor parsing delta entities for current and legacy protocols 2024-10-08 04:07:03 +03:00
Alibek Omarov
609680b328 engine: client: support parsing GoldSrc event messages 2024-10-08 04:07:03 +03:00
Alibek Omarov
ccbe370c8e engine: client: add support for parsing GoldSrc messages 2024-10-08 04:07:03 +03:00
Alibek Omarov
9706e47643 engine: client: refactor and implement GoldSrc-specific parsing bits in common message parsing code 2024-10-08 03:28:02 +03:00
Alibek Omarov
d98361f782 engine: client: add support for parsing GoldSrc svc_temp_entity 2024-10-08 03:28:02 +03:00
Alibek Omarov
ba7c789ec9 engine: common: add GoldSrc delta support 2024-10-08 03:28:02 +03:00
Alibek Omarov
d128997d40 engine: common: add GoldSrc bitbuf operations, add support for GoldSrc signed integers 2024-10-08 03:28:02 +03:00
Alibek Omarov
61342547ce engine: common: add support for GoldSrc split packet 2024-10-08 03:28:02 +03:00
Alibek Omarov
c1a5f173b8 engine: common: add GoldSrc netchan support 2024-10-08 03:28:02 +03:00
Alibek Omarov
f5c5b7b2c8 engine: common: add buffer munge functions 2024-10-08 03:28:02 +03:00
Alibek Omarov
057b47555d 3rdparty: bzip2: add wscript for bzip2, check for system-wide bzip2, add readme note 2024-10-08 03:28:02 +03:00
Alibek Omarov
43299f6747 3rdparty: add bzip2 submodule 2024-10-08 03:28:02 +03:00
Alibek Omarov
03bf6cb719 engine: client: get rid of PROTOCOL_GOLDSRC_VERSION, as connprotocol_t enum does it's job 2024-10-08 03:27:32 +03:00
Alibek Omarov
3a1bb12830 engine: client: rename CL_LegacyMode to CL_Protocol 2024-10-08 03:27:09 +03:00
Alibek Omarov
5efa68757e engine: remove unused svc_deltapacketbones 2024-10-08 03:27:09 +03:00
Alibek Omarov
afaf5bf3ea engine: improve security a little bit by properly checking customization files starting with \!MD5
Implement basic test for COM_IsSafeFileToDownload

Move COM_ParseFileSafe test to libpublic
2024-10-08 03:22:53 +03:00
SNMetamorph
50c805826f engine: implemented handling SIGTERM signal for proper stopping dedicated server 2024-10-08 01:05:26 +03:00
Alibek Omarov
35ae9f4a64 engine: client: don't save thirdperson value, it's not used anywhere 2024-10-07 21:00:16 +03:00
Alibek Omarov
d7d96c02a2 engine: client: implement cvar showpause for GoldSrc compatibility 2024-10-07 20:59:44 +03:00
Alibek Omarov
dd03723144 readme: add libopus-dev to dependencies list on Debian/Ubuntu 2024-10-07 18:09:32 +03:00
xiaodo
26f07196ea engine: Format Codes. 2024-10-07 17:22:27 +03:00
xiaodo
8c291fdfe3 engine: fix CenterPrint Wrong Y Position. 2024-10-07 17:22:27 +03:00
xiaodoxd
d1e118f07c Fix CenterPrint Wrong X Position 2024-10-07 17:22:27 +03:00
Alibek Omarov
6c531c14e6 engine: common: cvar: compatibility hack for mods that depend on HL25 widescreen FOV
Fixes Natural Selection 3.3 beta 9.
2024-10-04 19:09:43 +03:00
Alibek Omarov
433213c915 engine: server: fix cvar description for mp_footsteps 2024-10-04 19:07:44 +03:00
Alibek Omarov
ab0c0b18c2 engine: server: remove limit on sv_zmax value as it breaks Natural Selection mod 2024-10-04 19:07:08 +03:00
Alibek Omarov
29fd5f9fbe engine: server: remove FCVAR_SERVER flag from sv_zmax
The problem is that FCVAR_SERVER flagged cvars get saved to listenserver.cfg.

The game code usually sets sv_zmax value to worldspawn parameters and
listenserver.cfg gets generated before server DLL gets initialized.
2024-10-04 19:04:34 +03:00
Alibek Omarov
882d8afc93 engine: server: stub SV_RestartDecals for dedicated server 2024-10-04 01:28:22 +03:00
Alibek Omarov
e11635d15c engine: server: slight refactoring, hide client calls under XASH_DEDICATED, remove useless dedicated stub 2024-10-04 01:22:59 +03:00
Alibek Omarov
5d79d93aac engine: server: use safe cvar unlinking for mods that deallocate cvars (like HL Unified SDK) 2024-10-03 15:32:14 +03:00
Alibek Omarov
7ccf651fd0 engine: cvar: implement safer cvar unlinking in case when game deallocates cvar 2024-10-03 15:32:14 +03:00
140 changed files with 14379 additions and 6413 deletions

View File

@@ -5,6 +5,7 @@ packages:
- freetype-dev
- fontconfig-dev
- opus-dev
- bzip2-dev
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:

View File

@@ -7,6 +7,7 @@ packages:
- libfreetype-dev
- libfontconfig-dev
- libopus-dev
- libbz2-dev
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:

View File

@@ -6,6 +6,7 @@ packages:
- libfreetype-dev
- libfontconfig-dev
- libopus-dev
- libbz2-dev
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:

View File

@@ -6,6 +6,7 @@ packages:
- print/freetype2
- x11-fonts/fontconfig
- audio/opus
- archivers/bzip2
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:

View File

@@ -6,6 +6,7 @@ packages:
- fontconfig
- libopus
- pkgconf
- bzip2
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:

View File

@@ -3,6 +3,7 @@ packages:
- python3
- sdl2
- opus
- bzip2
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:

3
.gitignore vendored
View File

@@ -342,3 +342,6 @@ enc_temp_folder/
# KDevelop4
*.kdev4
# ccls langauge server
.ccls-*

6
.gitmodules vendored
View File

@@ -19,3 +19,9 @@
[submodule "3rdparty/xash-extras"]
path = 3rdparty/extras/xash-extras
url = https://github.com/FWGS/xash-extras
[submodule "3rdparty/bzip2/bzip2"]
path = 3rdparty/bzip2/bzip2
url = https://gitlab.com/bzip2/bzip2
[submodule "3rdparty/MultiEmulator"]
path = 3rdparty/MultiEmulator
url = https://github.com/FWGS/MultiEmulator

1
3rdparty/MultiEmulator vendored Submodule

Submodule 3rdparty/MultiEmulator added at 2f3c3a40cd

1
3rdparty/bzip2/bz_version.h vendored Normal file
View File

@@ -0,0 +1 @@
#define BZ_VERSION "1.1.0-fwgs"

1
3rdparty/bzip2/bzip2 vendored Submodule

Submodule 3rdparty/bzip2/bzip2 added at 66c46b8c94

34
3rdparty/bzip2/wscript vendored Normal file
View File

@@ -0,0 +1,34 @@
#! /usr/bin/env python
# encoding: utf-8
def options(opt):
pass
def configure(conf):
conf.define('_GNU_SOURCE', 1)
conf.define('BZ_NO_STDIO', 1)
if conf.env.DEST_OS == 'win32':
conf.define('BZ_LCCWIN32', 1)
else:
conf.define('BZ_UNIX', 1)
def build(bld):
# doesn't work with CMake generator
# bld(
# features = 'subst',
# source = 'bzip2/bz_version.h.in',
# target = 'bz_version.h',
# BZ_VERSION='1.1.0-fwgs'
# )
bz_sources = ['bzip2/blocksort.c', 'bzip2/huffman.c', 'bzip2/crctable.c', 'bzip2/randtable.c', 'bzip2/compress.c', 'bzip2/decompress.c', 'bzip2/bzlib.c']
bld.stlib(
source = bz_sources,
target = 'bzip2',
# use = 'bz_version.h',
includes = ['.', 'bzip2/'],
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = ['bzip2/']
)

View File

@@ -16,7 +16,6 @@ def build(bld):
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', 'NO_LOADER', 'STATICLIB'],
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],

View File

@@ -27,7 +27,7 @@ def build(bld):
'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']
defines = ['USE_ALLOCA', 'OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.4.0"', 'CUSTOM_MODES']
bld.stlib(
source = sources,

View File

@@ -0,0 +1,14 @@
# Support for GoldSrc network protocol
This feature is still work-in-progress, but for now it's available for all users, and we appreciate any bug-reports and contributions around it.
For connecting to GoldSrc-based servers, use this command:
```
connect ip:port gs
```
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should accept HLTV connections.
Without this requirement, you will just get "Steam validation rejected" error on connecting.
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
In case of ReHLDS with Reunion plugin, by default it rejects HLTV clients. But connections from HLTV can be easily enabled in `reunion.cfg` file.

View File

@@ -11,12 +11,12 @@ Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://ww
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
## Fork features
* Steam Half-Life (HLSDK 2.4) support.
* Steam Half-Life (HLSDK 2.5) support.
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
* Better multiplayer support: multiple master servers, headless dedicated server, voice chat and IPv6 support.
* Better multiplayer: multiple master servers, headless dedicated server, voice chat, [GoldSrc protocol support](Documentation/goldsrc-protocol-support.md) and IPv6 support.
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
* Mobility API: better game integration on mobile devices (vibration, touch controls)
* Mobility API: better game integration on mobile devices (vibration, touch controls).
* Different input methods: touch and gamepad in addition to mouse & keyboard.
* TrueType font rendering, as a part of mainui_cpp.
* External VGUI support module.
@@ -35,17 +35,16 @@ You still needed to copy `valve` directory as all game resources located there.
For additional info, run Xash3D with `-help` command line key.
## Contributing
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html
* Issues are accepted in both English and Russian
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html.
* Issues are accepted in both English and Russian.
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read https://waf.io/book/
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
### Prerequisites
If your CPU is x86 compatible and you're on Windows or Linux, 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!
@@ -62,31 +61,40 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
#### GNU/Linux
##### Debian/Ubuntu
* Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this
* Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
`$ sudo dpkg --add-architecture i386`
* Install development tools
* For 32-bit engine on amd64: \
`$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386`
* For everything else: \
`$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev`
* Clone this repostory:
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
##### RedHat/Fedora
* Only for 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
### Building
#### Windows (Visual Studio)
0) Open command line
0) Open command line.
1) Navigate to `xash3d-fwgs` directory.
2) Carefully examine which build options are available: `waf --help`
3) Configure build: `waf configure -T release --sdl2=c:/path/to/SDL2`
4) Compile: `waf build`
5) Install: `waf install --destdir=c:/path/to/any/output/directory`
2) (optional) Examine which build options are available: `waf --help`.
3) Configure build: `waf configure --sdl2=c:/path/to/SDL2`.
4) Compile: `waf build`.
5) Install: `waf install --destdir=c:/path/to/any/output/directory`.
#### Linux
If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig` prior to running configure.
If compiling 32-bit on amd64, make sure `PKG_CONFIG_PATH` from the previous step is set correctly, prior to running configure.
0) Examine which build options are available: `./waf --help`
1) Configure build: `./waf configure -T release`
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
2) Compile: `./waf build`
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
0) (optional) Examine which build options are available: `./waf --help`.
1) Configure build: `./waf configure` (you need to pass `-8` to compile 64-bit engine on 64-bit x86 processor).
2) Compile: `./waf build`.
3) Install: `./waf install --destdir=/path/to/any/output/directory`.

View File

@@ -146,7 +146,7 @@ void CL_PlayCDTrack_f( void )
if( paused ) Con_Printf( "Paused %s track %u\n", looped ? "looping" : "playing", track );
else Con_Printf( "Currently %s track %u\n", looped ? "looping" : "playing", track );
}
Con_Printf( "Volume is %f\n", Cvar_VariableValue( "MP3Volume" ));
Con_Printf( "Volume is %f\n", s_musicvolume.value );
return;
}
else Con_Printf( "%s: unknown command %s\n", Cmd_Argv( 0 ), command );

View File

@@ -50,7 +50,7 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
if( !cl_allow_download.value )
{
Con_Reportf( "Download refused, cl_allow_download is 0\n" );
Con_Reportf( "Download refused, cl_allowdownload is 0\n" );
return true;
}
@@ -74,7 +74,7 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
if( cl.http_download )
{
HTTP_AddDownload( filepath, pResource->nDownloadSize, true );
HTTP_AddDownload( filepath, pResource->nDownloadSize, true, pResource );
}
else
{

View File

@@ -40,6 +40,8 @@ GNU General Public License for more details.
#define IDEMOHEADER (('M'<<24)+('E'<<16)+('D'<<8)+'I') // little-endian "IDEM"
#define DEMO_PROTOCOL 3
#define PROTOCOL_GOLDSRC_VERSION_DEMO (PROTOCOL_GOLDSRC_VERSION | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
const char *demo_cmd[dem_lastcmd+1] =
{
"dem_unknown",
@@ -120,7 +122,7 @@ static int CL_GetDemoNetProtocol( connprotocol_t proto )
case PROTO_QUAKE:
return PROTOCOL_VERSION_QUAKE;
case PROTO_GOLDSRC:
return PROTOCOL_GOLDSRC_VERSION;
return PROTOCOL_GOLDSRC_VERSION_DEMO;
}
return PROTOCOL_VERSION;
@@ -136,7 +138,7 @@ static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
return PROTO_LEGACY;
case PROTOCOL_VERSION_QUAKE:
return PROTO_QUAKE;
case PROTOCOL_GOLDSRC_VERSION:
case PROTOCOL_GOLDSRC_VERSION_DEMO:
return PROTO_GOLDSRC;
}
@@ -283,7 +285,7 @@ void CL_WriteDemoUserCmd( int cmdnumber )
// write usercmd_t
MSG_Init( &buf, "UserCmd", data, sizeof( data ));
CL_WriteUsercmd( &buf, -1, cmdnumber ); // always no delta
CL_WriteUsercmd( PROTO_CURRENT, &buf, -1, cmdnumber ); // always no delta, always in current protocol
bytes = MSG_GetNumBytesWritten( &buf );
@@ -706,7 +708,7 @@ static void CL_DemoStartPlayback( int mode )
demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
CL_SetupNetchanForProtocol( cls.legacymode );
memset( demo.cmds, 0, sizeof( demo.cmds ));
demo.angle_position = 1;
@@ -1468,7 +1470,7 @@ static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, fi
return false;
}
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION )
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION && hdr->net_protocol != PROTOCOL_GOLDSRC_VERSION_DEMO )
{
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );

View File

@@ -25,13 +25,16 @@ static CVAR_DEFINE_AUTO( tracerspeed, "6000", 0, "tracer speed" );
static CVAR_DEFINE_AUTO( tracerlength, "0.8", 0, "tracer length factor" );
static CVAR_DEFINE_AUTO( traceroffset, "30", 0, "tracer starting offset" );
particle_t *cl_active_particles;
particle_t *cl_active_tracers;
particle_t *cl_free_particles;
particle_t *cl_particles = NULL; // particle pool
static particle_t *cl_active_particles;
static particle_t *cl_active_tracers;
static particle_t *cl_free_particles;
static particle_t *cl_particles = NULL; // particle pool
static vec3_t cl_avelocities[NUMVERTEXNORMALS];
static float cl_lasttimewarn = 0.0f;
// expand debugging BBOX particle hulls by this many units.
#define BOX_GAP 0.0f
/*
================
R_LookupColor
@@ -262,9 +265,9 @@ VIEWBEAMS MANAGEMENT
==============================================================
*/
BEAM *cl_active_beams;
BEAM *cl_free_beams;
BEAM *cl_viewbeams = NULL; // beams pool
static BEAM *cl_active_beams;
static BEAM *cl_free_beams;
static BEAM *cl_viewbeams = NULL; // beams pool
/*
@@ -1601,6 +1604,73 @@ void GAME_EXPORT R_RocketTrail( vec3_t start, vec3_t end, int type )
}
}
/*
===============
PM_ParticleLine
draw line from particles
================
*/
static void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel )
{
float len, curdist;
vec3_t diff, pos;
// determine distance
VectorSubtract( end, start, diff );
len = VectorNormalizeLength( diff );
curdist = 0;
while( curdist <= len )
{
VectorMA( start, curdist, diff, pos );
CL_Particle( pos, pcolor, life, 0, zvel );
curdist += 2.0f;
}
}
/*
================
PM_DrawRectangle
================
*/
static void PM_DrawRectangle( const vec3_t tl, const vec3_t bl, const vec3_t tr, const vec3_t br, int pcolor, float life )
{
PM_ParticleLine( tl, bl, pcolor, life, 0 );
PM_ParticleLine( bl, br, pcolor, life, 0 );
PM_ParticleLine( br, tr, pcolor, life, 0 );
PM_ParticleLine( tr, tl, pcolor, life, 0 );
}
/*
================
PM_DrawBBox
================
*/
static void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life )
{
vec3_t p[8], tmp;
float gap = BOX_GAP;
int i;
for( i = 0; i < 8; i++ )
{
tmp[0] = (i & 1) ? mins[0] - gap : maxs[0] + gap;
tmp[1] = (i & 2) ? mins[1] - gap : maxs[1] + gap ;
tmp[2] = (i & 4) ? mins[2] - gap : maxs[2] + gap ;
VectorAdd( tmp, origin, tmp );
VectorCopy( tmp, p[i] );
}
for( i = 0; i < 6; i++ )
{
PM_DrawRectangle( p[boxpnt[i][1]], p[boxpnt[i][0]], p[boxpnt[i][2]], p[boxpnt[i][3]], pcolor, life );
}
}
/*
================
R_ParticleLine
@@ -1764,25 +1834,6 @@ void GAME_EXPORT R_StreakSplash( const vec3_t pos, const vec3_t dir, int color,
}
}
/*
===============
R_DebugParticle
just for debug purposes
===============
*/
void R_DebugParticle( const vec3_t pos, byte r, byte g, byte b )
{
particle_t *p;
p = R_AllocParticle( NULL );
if( !p ) return;
VectorCopy( pos, p->org );
p->color = R_LookupColor( r, g, b );
p->die = cl.time + 0.01f;
}
/*
===============
CL_Particle

View File

@@ -380,7 +380,7 @@ CL_ParseReliableEvent
=============
*/
void CL_ParseReliableEvent( sizebuf_t *msg )
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
{
int event_index;
event_args_t nullargs, args;
@@ -390,11 +390,19 @@ void CL_ParseReliableEvent( sizebuf_t *msg )
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
// reliable events not use delta-compression just null-compression
MSG_ReadDeltaEvent( msg, &nullargs, &args );
if( proto == PROTO_GOLDSRC )
{
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
}
else
{
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
if( args.entindex > 0 && args.entindex <= cl.maxclients )
args.angles[PITCH] *= -3.0f;
@@ -409,33 +417,42 @@ CL_ParseEvent
=============
*/
void CL_ParseEvent( sizebuf_t *msg )
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
{
int event_index;
int i, num_events;
int packet_index;
event_args_t nullargs, args;
const event_args_t nullargs = { 0 };
event_args_t args = { 0 };
entity_state_t *state;
float delay;
memset( &nullargs, 0, sizeof( nullargs ));
memset( &args, 0, sizeof( args ));
int entity_bits;
num_events = MSG_ReadUBitLong( msg, 5 );
if( proto == PROTO_GOLDSRC )
entity_bits = MAX_GOLDSRC_ENTITY_BITS;
else if( proto == PROTO_LEGACY )
entity_bits = MAX_LEGACY_ENTITY_BITS;
else entity_bits = MAX_ENTITY_BITS;
// parse events queue
for( i = 0 ; i < num_events; i++ )
{
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( MSG_ReadOneBit( msg ))
packet_index = MSG_ReadUBitLong( msg, cls.legacymode ? MAX_LEGACY_ENTITY_BITS : MAX_ENTITY_BITS );
else packet_index = -1;
if( MSG_ReadOneBit( msg ))
{
MSG_ReadDeltaEvent( msg, &nullargs, &args );
packet_index = MSG_ReadUBitLong( msg, entity_bits );
if( MSG_ReadOneBit( msg ))
{
if( proto == PROTO_GOLDSRC )
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
else MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
}
else packet_index = -1;
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);

View File

@@ -174,7 +174,7 @@ static qboolean CL_EntityCustomLerp( cl_entity_t *e )
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
case MOVETYPE_TOSS:
if( cls.legacymode && e->model && e->model->type == mod_studio )
if( cls.legacymode == PROTO_LEGACY && e->model && e->model->type == mod_studio )
return false;
}
@@ -669,9 +669,9 @@ FRAME PARSING
=========================================================================
*/
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum )
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum, connprotocol_t proto )
{
if( cls.legacymode )
if( proto == PROTO_LEGACY )
{
*newnum = MSG_ReadWord( msg );
if( *newnum == 0 )
@@ -694,7 +694,7 @@ CL_FlushEntityPacket
Read and ignore whole entity packet.
=================
*/
static void CL_FlushEntityPacket( sizebuf_t *msg )
static void CL_FlushEntityPacket( sizebuf_t *msg, connprotocol_t proto )
{
int newnum;
entity_state_t from, to;
@@ -707,7 +707,7 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
// read it all, but ignore it
while( 1 )
{
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
break; // done
if( MSG_CheckOverflow( msg ))
@@ -717,6 +717,47 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
}
}
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe )
{
int subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
if( subtracted == 0 )
{
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
return false;
}
if( subtracted >= CL_UPDATE_MASK )
{
// we can't use this, it is too old
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
return false;
}
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
{
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
return false;
}
return true;
}
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent )
{
if( !oldframe )
{
*oldent = NULL;
return MAX_ENTNUMBER;
}
if( oldindex >= oldframe->num_entities )
return MAX_ENTNUMBER;
*oldent = &cls.packet_entities[(oldframe->first_entity + oldindex) % cls.num_client_entities];
return (*oldent)->number;
}
/*
=================
CL_DeltaEntity
@@ -787,7 +828,7 @@ An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto )
{
frame_t *newframe, *oldframe;
int oldindex, newnum, oldnum;
@@ -803,7 +844,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
CL_WriteDemoJumpTime();
// sentinel count. save it for debug checking
if( cls.legacymode )
if( proto == PROTO_LEGACY )
count = MSG_ReadWord( msg );
else count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1;
@@ -817,32 +858,12 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
if( delta )
{
int subtracted;
oldpacket = MSG_ReadByte( msg );
subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
if( subtracted == 0 )
{
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
if( subtracted >= CL_UPDATE_MASK )
{
// we can't use this, it is too old
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
uint oldpacket = MSG_ReadByte( msg );
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
{
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
CL_FlushEntityPacket( msg );
CL_FlushEntityPacket( msg, proto );
return playerbytes;
}
}
@@ -860,27 +881,11 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
oldent = NULL;
oldindex = 0;
if( !oldframe )
{
oldnum = MAX_ENTNUMBER;
}
else
{
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
}
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
while( 1 )
{
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
break; // done
if( MSG_CheckOverflow( msg ))
@@ -892,17 +897,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
{
// one or more entities from the old packet are unchanged
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
if( oldnum == newnum )
@@ -911,17 +906,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
bufStart = MSG_GetNumBytesRead( msg );
CL_DeltaEntity( msg, newframe, newnum, oldent, true );
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufStart;
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
continue;
}
@@ -940,17 +925,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
{
// one or more entities from the old packet are unchanged
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
if( newframe->num_entities != count && newframe->num_entities != 0 )
@@ -972,7 +947,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
cls.signon = SIGNONS;
// Clear loading plaque.
CL_SignonReply ();
CL_SignonReply( proto );
}
return playerbytes;
@@ -1290,7 +1265,7 @@ static void CL_LinkPacketEntities( frame_t *frame )
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
else if( cls.legacymode && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
else if( cls.legacymode == PROTO_LEGACY && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
{
if( !CL_InterpolateModel( ent ))
continue;

View File

@@ -34,10 +34,10 @@ GNU General Public License for more details.
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
#define TEXT_MSGNAME "TextMessage%i"
char cl_textbuffer[MAX_TEXTCHANNELS][2048];
client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
static char cl_textbuffer[MAX_TEXTCHANNELS][2048];
static client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
static dllfunc_t cdll_exports[] =
static const dllfunc_t cdll_exports[] =
{
{ "Initialize", (void **)&clgame.dllFuncs.pfnInitialize },
{ "HUD_VidInit", (void **)&clgame.dllFuncs.pfnVidInit },
@@ -80,7 +80,7 @@ static dllfunc_t cdll_exports[] =
};
// optional exports
static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
static const dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
{
{ "HUD_GetStudioModelInterface", (void **)&clgame.dllFuncs.pfnGetStudioModelInterface },
{ "HUD_DirectorMessage", (void **)&clgame.dllFuncs.pfnDirectorMessage },
@@ -140,11 +140,7 @@ returns true if thirdperson is enabled
*/
qboolean CL_IsThirdPerson( void )
{
cl.local.thirdperson = clgame.dllFuncs.CL_IsThirdPerson();
if( cl.local.thirdperson )
return true;
return false;
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false;
}
/*
@@ -252,18 +248,18 @@ static int CL_AdjustXPos( float x, int width, int totalWidth )
if( x == -1 )
{
xPos = ( refState.width - width ) * 0.5f;
xPos = ( clgame.scrInfo.iWidth - width ) * 0.5f;
}
else
{
if ( x < 0 )
xPos = (1.0f + x) * refState.width - totalWidth; // Alight right
xPos = (1.0f + x) * clgame.scrInfo.iWidth - totalWidth; // Alight right
else // align left
xPos = x * refState.width;
xPos = x * clgame.scrInfo.iWidth;
}
if( xPos + width > refState.width )
xPos = refState.width - width;
if( xPos + width > clgame.scrInfo.iWidth )
xPos = clgame.scrInfo.iWidth - width;
else if( xPos < 0 )
xPos = 0;
@@ -283,19 +279,19 @@ static int CL_AdjustYPos( float y, int height )
if( y == -1 ) // centered?
{
yPos = ( refState.height - height ) * 0.5f;
yPos = ( clgame.scrInfo.iHeight - height ) * 0.5f;
}
else
{
// Alight bottom?
if( y < 0 )
yPos = (1.0f + y) * refState.height - height; // Alight bottom
yPos = (1.0f + y) * clgame.scrInfo.iHeight - height; // Alight bottom
else // align top
yPos = y * refState.height;
yPos = y * clgame.scrInfo.iHeight;
}
if( yPos + height > refState.height )
yPos = refState.height - height;
if( yPos + height > clgame.scrInfo.iHeight )
yPos = clgame.scrInfo.iHeight - height;
else if( yPos < 0 )
yPos = 0;
@@ -1019,7 +1015,8 @@ void CL_DrawHUD( int state )
CL_DrawCrosshair ();
CL_DrawCenterPrint ();
clgame.dllFuncs.pfnRedraw( cl.time, cl.intermission );
CL_DrawLoadingOrPaused( cls.pauseIcon );
if( showpause.value )
CL_DrawLoadingOrPaused( cls.pauseIcon );
break;
case CL_LOADING:
CL_DrawLoadingOrPaused( cls.loadingBar );
@@ -3488,7 +3485,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
nr->flags = flags;
// local servers request
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, A2A_NETINFO" %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
}
/*

View File

@@ -1303,6 +1303,16 @@ static gameinfo2_t *pfnGetModInfo( int gi_version, int i )
return &gameui.modsInfo[i];
}
static int pfnIsCvarReadOnly( const char *name )
{
convar_t *cv = Cvar_FindVar( name );
if( !cv )
return -1;
return FBitSet( cv->flags, FCVAR_READ_ONLY ) ? 1 : 0;
}
static ui_extendedfuncs_t gExtendedfuncs =
{
pfnEnableTextInput,
@@ -1318,6 +1328,7 @@ static ui_extendedfuncs_t gExtendedfuncs =
&gNetApi,
pfnGetGameInfo,
pfnGetModInfo,
pfnIsCvarReadOnly,
};
void UI_UnloadProgs( void )

File diff suppressed because it is too large Load Diff

View File

@@ -63,9 +63,9 @@ static byte netcolors[NETGRAPH_NET_COLORS+NETGRAPH_LERP_HEIGHT][4] =
// other will be generated through NetGraph_InitColors()
};
static byte sendcolor[4] = { 88, 29, 130, 255 };
static byte holdcolor[4] = { 255, 0, 0, 200 };
static byte extrap_base_color[4] = { 255, 255, 255, 255 };
static const byte sendcolor[4] = { 88, 29, 130, 255 };
static const byte holdcolor[4] = { 255, 0, 0, 200 };
static const byte extrap_base_color[4] = { 255, 255, 255, 255 };
static netbandwidthgraph_t netstat_graph[NET_TIMINGS];
static float packet_loss;
static float packet_choke;
@@ -79,7 +79,7 @@ NetGraph_DrawRect
NetGraph_FillRGBA shortcut
==========
*/
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
static void NetGraph_DrawRect( const wrect_t *rect, const byte colors[4] )
{
ref.dllFuncs.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad

File diff suppressed because it is too large Load Diff

View File

@@ -137,12 +137,7 @@ static void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
//if( FBitSet( flags, SND_SEQUENCE ))
//Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound + MAX_SOUNDS );
//else
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
@@ -269,7 +264,7 @@ static void CL_LegacyParseResourceList( sizebuf_t *msg )
if( !cl_allow_download.value )
{
Con_DPrintf( "Refusing new resource, cl_allow_download set to 0\n" );
Con_DPrintf( "Refusing new resource, cl_allowdownload set to 0\n" );
reslist.rescount = 0;
}
@@ -300,7 +295,7 @@ static void CL_LegacyParseResourceList( sizebuf_t *msg )
continue; // already exists
host.downloadcount++;
HTTP_AddDownload( path, -1, true );
HTTP_AddDownload( path, -1, true, NULL );
}
if( !host.downloadcount )
@@ -320,7 +315,7 @@ dispatch messages
void CL_ParseLegacyServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd, param1, param2;
int cmd;
int old_background;
const char *s;
@@ -345,6 +340,9 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_LEGACY, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
@@ -359,7 +357,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
Host_AbortCurrentFrame ();
break;
case svc_legacy_event:
CL_ParseEvent( msg );
CL_ParseEvent( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_changing:
@@ -421,7 +419,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
break;
case svc_time:
CL_ParseServerTime( msg );
CL_ParseServerTime( msg, PROTO_LEGACY );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
@@ -446,19 +444,19 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, true );
CL_ParseServerData( msg, PROTO_LEGACY );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg );
CL_ParseLightStyle( msg, PROTO_LEGACY );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, true );
CL_UpdateUserinfo( msg, PROTO_LEGACY );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
case svc_clientdata:
CL_ParseClientData( msg );
CL_ParseClientData( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resource:
@@ -468,82 +466,58 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
CL_UpdateUserPings( msg );
break;
case svc_particle:
CL_ParseParticles( msg );
CL_ParseParticles( msg, PROTO_LEGACY );
break;
case svc_restoresound:
CL_ParseRestoreSoundPacket( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
Con_Printf( S_ERROR "%s: svc_restoresound: implement me!\n", __func__ );
break;
case svc_spawnstatic:
CL_LegacyParseStaticEntity( msg );
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg );
CL_ParseReliableEvent( msg, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_ParseBaseline( msg, true );
break;
case svc_temp_entity:
CL_ParseTempEntity( msg );
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
CL_ParseBaseline( msg, PROTO_LEGACY );
break;
case svc_setpause:
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg );
CL_ParseSignon( msg, PROTO_LEGACY );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_legacy_modelindex:
CL_LegacyPrecacheModel( msg );
break;
case svc_legacy_soundindex:
CL_LegacyPrecacheSound( msg );
break;
case svc_cdtrack:
param1 = MSG_ReadByte( msg );
param1 = bound( 1, param1, MAX_CDTRACKS ); // tracknum
param2 = MSG_ReadByte( msg );
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_legacy_eventindex:
CL_LegacyPrecacheEvent(msg);
break;
case svc_weaponanim:
param1 = MSG_ReadByte( msg ); // iAnim
param2 = MSG_ReadByte( msg ); // body
CL_WeaponAnim( param1, param2 );
break;
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_roomtype:
param1 = MSG_ReadShort( msg );
Cvar_SetValue( "room_type", param1 );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg );
CL_RegisterUserMessage( msg, PROTO_LEGACY );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false );
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntities( msg, true );
playerbytes = CL_ParsePacketEntities( msg, true, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
@@ -590,9 +564,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_director:
CL_ParseDirector( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
@@ -603,7 +574,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
CL_ParseCvarValue( msg, true, PROTO_LEGACY );
break;
default:
CL_ParseUserMessage( msg, cmd );
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
@@ -615,7 +586,7 @@ void CL_LegacyPrecache_f( void )
int spawncount, i;
model_t *mod;
if( !cls.legacymode )
if( cls.legacymode != PROTO_LEGACY )
return;
spawncount = Q_atoi( Cmd_Argv( 1 ));
@@ -658,8 +629,3 @@ void CL_LegacyPrecache_f( void )
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS - 1;
}
qboolean CL_LegacyMode( void )
{
return cls.legacymode == PROTO_LEGACY;
}

762
engine/client/cl_parse_gs.c Normal file
View File

@@ -0,0 +1,762 @@
/*
cl_parse.c - parse a message received from the server (GoldSrc 48 protocol)
Copyright (C) 2008 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"
#include "client.h"
#include "net_encode.h"
#include "particledef.h"
#include "cl_tent.h"
#include "shake.h"
#include "hltv.h"
#include "input.h"
#include "server.h"
static void CL_ParseExtraInfo( sizebuf_t *msg )
{
string clientfallback;
Q_strncpy( clientfallback, MSG_ReadString( msg ), sizeof( clientfallback ));
if( COM_CheckStringEmpty( clientfallback ))
Con_Reportf( S_ERROR "%s: TODO: add fallback directory %s!\n", __func__, clientfallback );
if( MSG_ReadByte( msg ))
{
Cvar_FullSet( "sv_cheats", "1", FCVAR_READ_ONLY | FCVAR_SERVER );
}
else
{
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
}
}
static void CL_ParseNewMovevars( sizebuf_t *msg )
{
Delta_InitClient(); // finalize client delta's
clgame.movevars.gravity = MSG_ReadFloat( msg );
clgame.movevars.stopspeed = MSG_ReadFloat( msg );
clgame.movevars.maxspeed = MSG_ReadFloat( msg );
clgame.movevars.spectatormaxspeed = MSG_ReadFloat( msg );
clgame.movevars.accelerate = MSG_ReadFloat( msg );
clgame.movevars.airaccelerate = MSG_ReadFloat( msg );
clgame.movevars.wateraccelerate = MSG_ReadFloat( msg );
clgame.movevars.friction = MSG_ReadFloat( msg );
clgame.movevars.edgefriction = MSG_ReadFloat( msg );
clgame.movevars.waterfriction = MSG_ReadFloat( msg );
clgame.movevars.entgravity = MSG_ReadFloat( msg );
clgame.movevars.bounce = MSG_ReadFloat( msg );
clgame.movevars.stepsize = MSG_ReadFloat( msg );
clgame.movevars.maxvelocity = MSG_ReadFloat( msg );
clgame.movevars.zmax = MSG_ReadFloat( msg );
clgame.movevars.waveHeight = MSG_ReadFloat( msg );
clgame.movevars.footsteps = MSG_ReadByte( msg );
clgame.movevars.rollangle = MSG_ReadFloat( msg );
clgame.movevars.rollspeed = MSG_ReadFloat( msg );
clgame.movevars.skycolor_r = MSG_ReadFloat( msg );
clgame.movevars.skycolor_g = MSG_ReadFloat( msg );
clgame.movevars.skycolor_b = MSG_ReadFloat( msg );
clgame.movevars.skyvec_x = MSG_ReadFloat( msg );
clgame.movevars.skyvec_y = MSG_ReadFloat( msg );
clgame.movevars.skyvec_z = MSG_ReadFloat( msg );
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
// water alpha is not allowed
if( !FBitSet( world.flags, FWORLD_WATERALPHA ))
clgame.movevars.wateralpha = 1.0f;
// update sky if changed
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
R_SetupSky( clgame.movevars.skyName );
clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual!
clgame.oldmovevars.features = clgame.movevars.features = host.features;
}
typedef struct delta_header_t
{
qboolean remove : 1;
qboolean custom : 1;
qboolean instanced : 1;
uint instanced_baseline_index : 6;
uint offset : 6;
} delta_header_t;
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
{
int entnum = oldnum;
memset( hdr, 0, sizeof( *hdr ));
if( !delta )
{
// if we have one bit set, then it's a next entity in line
// if we have next bit NON set, then it's a one of next 64 entities
// if not, it's a new entity
if( MSG_ReadOneBit( msg ))
entnum++;
else if( MSG_ReadOneBit( msg ) == 0 )
entnum += MSG_ReadUBitLong( msg, 6 );
else
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
}
else
{
// does this packet encode entity deletion?
hdr->remove = MSG_ReadOneBit( msg );
// same logic as above
if( MSG_ReadOneBit( msg ) == 0 )
entnum += MSG_ReadUBitLong( msg, 6 );
else entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
}
// if we are not removing this entity
if( !hdr->remove )
{
hdr->custom = MSG_ReadOneBit( msg );
// do we got instanced baselines in svc_spawnbaselines?
if( cl.instanced_baseline_count )
{
hdr->instanced = MSG_ReadOneBit( msg );
if( hdr->instanced )
hdr->instanced_baseline_index = MSG_ReadUBitLong( msg, 6 );
}
if( !delta && !hdr->instanced )
{
if( MSG_ReadOneBit( msg ))
hdr->offset = MSG_ReadUBitLong( msg, 6 );
}
}
return entnum;
}
static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
{
if( hdr->custom )
return DT_CUSTOM_ENTITY_STATE_T;
if( CL_IsPlayerIndex( entnum ))
return DT_ENTITY_STATE_PLAYER_T;
return DT_ENTITY_STATE_T;
}
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{
frame->valid = false;
cl.validsequence = 0; // can't render a frame
// read it all but ignore it
while( 1 )
{
int num = 0;
entity_state_t from = { 0 }, to;
delta_header_t hdr;
if( MSG_ReadWord( msg ) != 0 )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
if( hdr.remove )
continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
}
}
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
{
cl_entity_t *ent;
entity_state_t *to;
qboolean newent = from == NULL;
int pack = frame->num_entities;
qboolean has_update = msg != NULL;
// alloc next slot to store update
to = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
return;
}
ent = CL_EDICT_NUM( newnum );
if( hdr->remove )
{
if( !newent )
CL_KillDeadBeams( ent );
else
Con_Printf( S_WARN "%s: entity remove on non-delta update (%d)\n", __func__, newnum );
return;
}
ent->index = newnum; // enumerate entity index
if( newent )
{
if( hdr->instanced )
from = &cl.instanced_baseline[hdr->instanced_baseline_index];
else if( hdr->offset != 0 )
from = &cls.packet_entities[(cls.next_client_entities - hdr->offset) % cls.num_client_entities];
else
from = &ent->baseline;
}
if( has_update )
Delta_ReadGSFields( msg, CL_GetEntityDelta( hdr, newnum ), from, to, cl.mtime[0] );
else memcpy( to, from, sizeof( entity_state_t ));
to->entityType = hdr->custom ? ENTITY_BEAM : ENTITY_NORMAL;
to->number = newnum;
if( newent )
{
// interpolation must be reset
SETVISBIT( frame->flags, pack );
// release beams from previous entity
CL_KillDeadBeams( ent );
}
// add entity to packet
cls.next_client_entities++;
frame->num_entities++;
}
static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *from )
{
delta_header_t fakehdr =
{
.custom = FBitSet( from->entityType, ENTITY_BEAM ) == ENTITY_BEAM,
};
CL_DeltaEntityGS( &fakehdr, NULL, frame, num, from );
}
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{
frame_t *frame, *oldframe;
int oldindex, newnum, oldnum, numbase = 0;
entity_state_t *oldent;
int count;
int playerbytes = 0;
// save first uncompressed packet as timestamp
if( cls.changelevel && !delta && cls.demorecording )
CL_WriteDemoJumpTime();
count = MSG_ReadWord( msg );
frame = &cl.frames[cl.parsecountmod];
memset( frame->flags, 0, sizeof( frame->flags ));
frame->first_entity = cls.next_client_entities;
frame->num_entities = 0;
frame->valid = true;
if( delta )
{
uint oldpacket = MSG_ReadByte( msg );
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
{
MSG_StartBitWriting( msg );
CL_FlushEntityPacketGS( frame, msg );
MSG_EndBitWriting( msg );
return playerbytes;
}
}
else
{
oldframe = NULL;
cl.send_reply = true;
cls.demowaiting = false;
}
cl.validsequence = cls.netchan.incoming_sequence;
MSG_StartBitWriting( msg );
oldent = NULL;
oldindex = 0;
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
// read it all but ignore it
while( 1 )
{
int bufstart;
qboolean player;
delta_header_t hdr;
int val = MSG_ReadWord( msg );
if( val )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
numbase = newnum = CL_ParseDeltaHeader( msg, delta, numbase, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
while( oldnum < newnum )
{
if( !delta )
Con_Printf( S_WARN "%s: old frame copy on non-delta update (%d < %d)\n", __func__, oldnum, newnum );
// one or more entities from the old packet are unchanged
CL_CopyPacketEntity( frame, oldnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
bufstart = MSG_GetNumBytesRead( msg );
if( oldnum == newnum )
{
if( !delta )
Con_Printf( S_WARN "%s: delta entity on non-delta update (%d)\n", __func__, oldnum );
// from delta
CL_DeltaEntityGS( &hdr, msg, frame, newnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
else if( oldnum > newnum )
{
// from baseline
CL_DeltaEntityGS( &hdr, msg, frame, newnum, NULL );
}
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
}
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
// any remaining entities in the old frame are copied over
while( oldnum != MAX_ENTNUMBER )
{
// one or more entities from the old packet are unchanged
CL_CopyPacketEntity( frame, oldnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
MSG_EndBitWriting( msg );
if( frame->num_entities != count )
Con_Reportf( S_WARN "CL_Parse%sPacketEntitiesGS: (%i should be %i)\n", delta ? "Delta" : "", frame->num_entities, count );
if( !frame->valid )
return playerbytes;
CL_ProcessPacket( frame );
CL_SetSolidEntities();
// first update, received world, remove loading plaque
if( cls.signon == ( SIGNONS - 1 ))
{
cls.signon = SIGNONS;
CL_SignonReply( PROTO_GOLDSRC );
}
return playerbytes;
}
static float MSG_ReadGSBitCoord( sizebuf_t *sb )
{
float value = 0;
int ival, fval;
ival = MSG_ReadOneBit( sb );
fval = MSG_ReadOneBit( sb );
if( ival || fval )
{
int sign = MSG_ReadOneBit( sb );
if( ival )
ival = MSG_ReadUBitLong( sb, 12 );
if( fval )
fval = MSG_ReadUBitLong( sb, 3 );
value = (float)( fval / 8.0 + ival );
if( sign )
value = -value;
}
return value;
}
static void MSG_ReadGSBitVec3Coord( sizebuf_t *sb, vec3_t fa )
{
qboolean x, y, z;
VectorClear( fa );
x = MSG_ReadOneBit( sb );
y = MSG_ReadOneBit( sb );
z = MSG_ReadOneBit( sb );
if( x )
fa[0] = MSG_ReadGSBitCoord( sb );
if( y )
fa[1] = MSG_ReadGSBitCoord( sb );
if( z )
fa[2] = MSG_ReadGSBitCoord( sb );
}
static void CL_ParseSoundPacketGS( sizebuf_t *msg )
{
vec3_t pos;
int chan, sound;
float volume, attn;
int flags, pitch, entnum;
sound_t handle = 0;
MSG_StartBitWriting( msg );
flags = MSG_ReadUBitLong( msg, 9 );
if( FBitSet( flags, SND_VOLUME ))
volume = (float)MSG_ReadByte( msg ) / 255.0f;
else volume = VOL_NORM;
if( FBitSet( flags, SND_ATTENUATION ))
attn = (float)MSG_ReadByte( msg ) / 64.0f;
else attn = ATTN_NONE;
chan = MSG_ReadUBitLong( msg, 3 );
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
if( FBitSet( flags, SND_LEGACY_LARGE_INDEX ))
sound = MSG_ReadWord( msg );
else sound = MSG_ReadByte( msg );
MSG_ReadGSBitVec3Coord( msg, pos );
if( FBitSet( flags, SND_PITCH ))
pitch = MSG_ReadByte( msg );
else pitch = PITCH_NORM;
MSG_EndBitWriting( msg );
ClearBits( flags, SND_LEGACY_LARGE_INDEX );
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
if( !cl.audio_prepped )
return; // too early
// g-cont. sound and ambient sound have only difference with channel
if( chan == CHAN_STATIC )
{
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
else
{
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
}
}
static void CL_ParseSpawnStaticSound( sizebuf_t *msg )
{
vec3_t pos;
int handle, entnum, pitch, flags;
float volume, attn;
MSG_ReadVec3Coord( msg, pos );
handle = MSG_ReadShort( msg );
volume = MSG_ReadByte( msg ) * ( 1.0f / 255.0f );
attn = MSG_ReadByte( msg ) * ( 1.0f / 64.0f );
entnum = MSG_ReadShort( msg );
pitch = MSG_ReadByte( msg );
flags = MSG_ReadByte( msg );
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
/*
=====================================================================
ACTION MESSAGES
=====================================================================
*/
/*
=====================
CL_ParseGoldSrcServerMessage
dispatch messages
=====================
*/
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd, param1;
const char *s;
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "CL_ParseServerMessage: overflow!\n" );
return;
}
// mark start position
bufStart = MSG_GetNumBytesRead( msg );
// end of message (align bits)
if( MSG_GetNumBitsLeft( msg ) < 8 )
break;
cmd = MSG_ReadServerCmd( msg );
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
case svc_spawnstatic:
case svc_goldsrc_damage:
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
break;
case svc_disconnect:
s = MSG_ReadString( msg );
if( COM_CheckStringEmpty( s ))
Con_Printf( "Server issued disconnect. Reason: %s\n", s );
CL_Drop ();
Host_AbortCurrentFrame ();
break;
case svc_event:
MSG_StartBitWriting( msg );
CL_ParseEvent( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_goldsrc_version:
param1 = MSG_ReadLong( msg );
if( param1 != PROTOCOL_GOLDSRC_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", param1, PROTOCOL_GOLDSRC_VERSION );
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseSoundPacketGS( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_GOLDSRC );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
s = MSG_ReadString( msg );
if( cl_trace_stufftext.value )
{
size_t len = Q_strlen( s );
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
}
#ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_goldsrc_serverinfo:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_GOLDSRC );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_GOLDSRC );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
break;
case svc_goldsrc_deltadescription:
Delta_ParseTableField_GS( msg );
break;
case svc_clientdata:
MSG_StartBitWriting( msg );
CL_ParseClientData( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_goldsrc_stopsound:
param1 = MSG_ReadWord( msg );
S_StopSound( param1 >> 3, param1 & 7, NULL );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_pings:
MSG_StartBitWriting( msg );
CL_UpdateUserPings( msg );
MSG_EndBitWriting( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_GOLDSRC );
break;
case svc_event_reliable:
MSG_StartBitWriting( msg );
CL_ParseReliableEvent( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
MSG_StartBitWriting( msg );
CL_ParseBaseline( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
break;
case svc_setpause:
cl.paused = ( MSG_ReadByte( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_GOLDSRC );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_goldsrc_spawnstaticsound:
CL_ParseSpawnStaticSound( msg );
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_goldsrc_decalname:
param1 = MSG_ReadByte( msg );
s = MSG_ReadString( msg );
Q_strncpy( host.draw_decals[param1], s, sizeof( host.draw_decals[param1] ));
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_goldsrc_newusermsg:
CL_RegisterUserMessage( msg, PROTO_GOLDSRC );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, true );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
MSG_StartBitWriting( msg );
CL_ParseResourceList( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
break;
case svc_goldsrc_newmovevars:
CL_ParseNewMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, PROTO_GOLDSRC );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_goldsrc_sendextrainfo:
CL_ParseExtraInfo( msg );
break;
case svc_goldsrc_timescale:
// we can set sys_timescale to anything we want but in GoldSrc it's locked for
// HLTV and demoplayback. Do we really want to have it then if both are out of scope?
Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ );
MSG_ReadFloat( msg );
break;
case svc_goldsrc_sendcvarvalue:
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
break;
case svc_goldsrc_sendcvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
}
}

View File

@@ -59,7 +59,7 @@ void GAME_EXPORT CL_PopPMStates( void )
CL_IsPredicted
===============
*/
qboolean CL_IsPredicted( void )
static qboolean CL_IsPredicted( void )
{
if( cl_nopred.value || cl.intermission )
return false;

View File

@@ -431,7 +431,7 @@ static void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits )
cls.signon = SIGNONS;
// Clear loading plaque.
CL_SignonReply ();
CL_SignonReply( PROTO_QUAKE );
}
// alloc next slot to store update
@@ -626,7 +626,7 @@ CL_ParseStaticEntity
===================
*/
static void CL_ParseStaticEntity( sizebuf_t *msg )
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
{
entity_state_t state;
cl_entity_t *ent;
@@ -950,7 +950,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
break;
case svc_time:
Cbuf_AddText( "\n" ); // new frame was started
CL_ParseServerTime( msg );
CL_ParseServerTime( msg, PROTO_QUAKE );
break;
case svc_print:
str = MSG_ReadString( msg );
@@ -1006,7 +1006,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
CL_ParseQuakeDamage( msg );
break;
case svc_spawnstatic:
CL_ParseStaticEntity( msg );
CL_ParseQuakeStaticEntity( msg );
break;
case svc_spawnbinary:
// never used in Quake

View File

@@ -853,7 +853,6 @@ void SCR_Shutdown( void )
{
if( !scr_init ) return;
Cmd_RemoveCommand( "timerefresh" );
Cmd_RemoveCommand( "skyname" );
Cmd_RemoveCommand( "viewpos" );
UI_SetActiveMenu( false );

View File

@@ -35,17 +35,17 @@ TEMPENTS MANAGEMENT
#define SHARD_VOLUME 12.0f // on shard ever n^3 units
#define MAX_MUZZLEFLASH 3
TEMPENTITY *cl_active_tents;
TEMPENTITY *cl_free_tents;
TEMPENTITY *cl_tempents = NULL; // entities pool
static TEMPENTITY *cl_active_tents;
static TEMPENTITY *cl_free_tents;
static TEMPENTITY *cl_tempents = NULL; // entities pool
model_t *cl_sprite_muzzleflash[MAX_MUZZLEFLASH]; // muzzle flashes
model_t *cl_sprite_dot = NULL;
model_t *cl_sprite_ricochet = NULL;
model_t *cl_sprite_shell = NULL;
model_t *cl_sprite_glow = NULL;
static model_t *cl_sprite_muzzleflash[MAX_MUZZLEFLASH]; // muzzle flashes
static model_t *cl_sprite_ricochet = NULL;
static model_t *cl_sprite_glow = NULL;
model_t *cl_sprite_dot = NULL;
model_t *cl_sprite_shell = NULL;
const char *cl_default_sprites[] =
static const char *const cl_default_sprites[] =
{
// built-in sprites
"sprites/muzzleflash1.spr",
@@ -169,29 +169,13 @@ void CL_AddClientResources( void )
#endif
}
/*
================
CL_InitTempents
================
*/
void CL_InitTempEnts( void )
{
cl_tempents = Mem_Calloc( cls.mempool, sizeof( TEMPENTITY ) * GI->max_tents );
CL_ClearTempEnts();
// load tempent sprites (glowshell, muzzleflashes etc)
CL_LoadClientSprites ();
}
/*
================
CL_ClearTempEnts
================
*/
void CL_ClearTempEnts( void )
static void CL_ClearTempEnts( void )
{
int i;
@@ -208,6 +192,21 @@ void CL_ClearTempEnts( void )
cl_active_tents = NULL;
}
/*
================
CL_InitTempents
================
*/
void CL_InitTempEnts( void )
{
cl_tempents = Mem_Calloc( cls.mempool, sizeof( TEMPENTITY ) * GI->max_tents );
CL_ClearTempEnts();
// load tempent sprites (glowshell, muzzleflashes etc)
CL_LoadClientSprites ();
}
/*
================
CL_FreeTempEnts
@@ -444,11 +443,16 @@ alloc normal\low priority tempentity
*/
TEMPENTITY *CL_TempEntAlloc( const vec3_t org, model_t *pmodel )
{
static float cl_lasttimewarn;
TEMPENTITY *pTemp;
if( !cl_free_tents )
{
Con_DPrintf( "Overflow %d temporary ents!\n", GI->max_tents );
if( cl_lasttimewarn < host.realtime )
{
Con_DPrintf( "Overflow %d temporary ents!\n", GI->max_tents );
cl_lasttimewarn = host.realtime + 1.0f;
}
return NULL;
}
@@ -1892,13 +1896,13 @@ CL_ParseTempEntity
handle temp-entity messages
==============
*/
void CL_ParseTempEntity( sizebuf_t *msg )
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto )
{
sizebuf_t buf;
byte pbuf[2048];
sizebuf_t buf, *pbuf;
byte msg_data[2048];
int iSize;
int type, color, count, flags;
int decalIndex, modelIndex, entityIndex;
int decalIndex = 0, modelIndex = 0, entityIndex = 0;
float scale, life, frameRate, vel, random;
float brightness, r, g, b;
vec3_t pos, pos2, ang;
@@ -1909,23 +1913,30 @@ void CL_ParseTempEntity( sizebuf_t *msg )
sound_t hSound;
const char *name;
if( cls.legacymode )
iSize = MSG_ReadByte( msg );
else iSize = MSG_ReadWord( msg );
if( proto != PROTO_GOLDSRC )
{
if( proto == PROTO_LEGACY )
iSize = MSG_ReadByte( msg );
else iSize = MSG_ReadWord( msg );
decalIndex = modelIndex = entityIndex = 0;
// this will probably be fatal anyway
if( iSize > sizeof( msg_data ))
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
// this will probably be fatal anyway
if( iSize > sizeof( pbuf ))
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
// parse user message into buffer
MSG_ReadBytes( msg, msg_data, iSize );
// parse user message into buffer
MSG_ReadBytes( msg, pbuf, iSize );
// init a safe tempbuffer
MSG_Init( &buf, "TempEntity", msg_data, iSize );
// init a safe tempbuffer
MSG_Init( &buf, "TempEntity", pbuf, iSize );
pbuf = &buf;
}
else
{
pbuf = msg;
}
type = MSG_ReadByte( &buf );
type = MSG_ReadByte( pbuf );
switch( type )
{
@@ -1942,29 +1953,29 @@ void CL_ParseTempEntity( sizebuf_t *msg )
case TE_BEAMRING:
case TE_BEAMHOSE:
case TE_KILLBEAM:
CL_ParseViewBeam( &buf, type );
CL_ParseViewBeam( pbuf, type );
break;
case TE_GUNSHOT:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
R_RicochetSound( pos );
R_RunParticleEffect( pos, vec3_origin, 0, 20 );
break;
case TE_EXPLOSION:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
frameRate = MSG_ReadByte( &buf );
flags = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
frameRate = MSG_ReadByte( pbuf );
flags = MSG_ReadByte( pbuf );
R_Explosion( pos, modelIndex, scale, frameRate, flags );
break;
case TE_TAREXPLOSION:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
R_BlobExplosion( pos );
if(( name = SoundList_Get( Explode, 0 )))
@@ -1974,48 +1985,48 @@ void CL_ParseTempEntity( sizebuf_t *msg )
}
break;
case TE_SMOKE:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
frameRate = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
frameRate = MSG_ReadByte( pbuf );
pTemp = R_DefaultSprite( pos, modelIndex, frameRate );
R_Sprite_Smoke( pTemp, scale );
break;
case TE_TRACER:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
R_TracerEffect( pos, pos2 );
break;
case TE_SPARKS:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
R_SparkShower( pos );
break;
case TE_LAVASPLASH:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
R_LavaSplash( pos );
break;
case TE_TELEPORT:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
R_TeleportSplash( pos );
break;
case TE_EXPLOSION2:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
color = MSG_ReadByte( &buf );
count = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
color = MSG_ReadByte( pbuf );
count = MSG_ReadByte( pbuf );
R_ParticleExplosion2( pos, color, count );
dl = CL_AllocDlight( 0 );
@@ -2035,25 +2046,25 @@ void CL_ParseTempEntity( sizebuf_t *msg )
case TE_WORLDDECAL:
case TE_WORLDDECALHIGH:
case TE_DECALHIGH:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
if( type == TE_BSPDECAL )
{
decalIndex = MSG_ReadShort( &buf );
entityIndex = MSG_ReadShort( &buf );
decalIndex = MSG_ReadShort( pbuf );
entityIndex = MSG_ReadShort( pbuf );
if( entityIndex )
modelIndex = MSG_ReadShort( &buf );
modelIndex = MSG_ReadShort( pbuf );
else modelIndex = 0;
}
else
{
decalIndex = MSG_ReadByte( &buf );
decalIndex = MSG_ReadByte( pbuf );
if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH )
decalIndex += 256;
if( type == TE_DECALHIGH || type == TE_DECAL )
entityIndex = MSG_ReadShort( &buf );
entityIndex = MSG_ReadShort( pbuf );
else entityIndex = 0;
pEnt = CL_GetEntityByIndex( entityIndex );
@@ -2062,197 +2073,197 @@ void CL_ParseTempEntity( sizebuf_t *msg )
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, pos, type == TE_BSPDECAL ? FDECAL_PERMANENT : 0 );
break;
case TE_IMPLOSION:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
scale = MSG_ReadByte( &buf );
count = MSG_ReadByte( &buf );
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
scale = MSG_ReadByte( pbuf );
count = MSG_ReadByte( pbuf );
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_Implosion( pos, scale, count, life );
break;
case TE_SPRITETRAIL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf );
life = (float)MSG_ReadByte( &buf ) * 0.1f;
scale = (float)MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadByte( pbuf );
life = (float)MSG_ReadByte( pbuf ) * 0.1f;
scale = (float)MSG_ReadByte( pbuf );
if( !scale ) scale = 1.0f;
else scale *= 0.1f;
vel = (float)MSG_ReadByte( &buf ) * 10;
random = (float)MSG_ReadByte( &buf ) * 10;
vel = (float)MSG_ReadByte( pbuf ) * 10;
random = (float)MSG_ReadByte( pbuf ) * 10;
R_Sprite_Trail( type, pos, pos2, modelIndex, count, life, scale, random, 255, vel );
break;
case TE_SPRITE:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
scale = (float)MSG_ReadByte( &buf ) * 0.1f;
brightness = (float)MSG_ReadByte( &buf ) / 255.0f;
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
scale = (float)MSG_ReadByte( pbuf ) * 0.1f;
brightness = (float)MSG_ReadByte( pbuf ) / 255.0f;
R_TempSprite( pos, vec3_origin, scale, modelIndex,
kRenderTransAdd, kRenderFxNone, brightness, 0.0, FTENT_SPRANIMATE );
break;
case TE_GLOWSPRITE:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
life = (float)MSG_ReadByte( &buf ) * 0.1f;
scale = (float)MSG_ReadByte( &buf ) * 0.1f;
brightness = (float)MSG_ReadByte( &buf ) / 255.0f;
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
life = (float)MSG_ReadByte( pbuf ) * 0.1f;
scale = (float)MSG_ReadByte( pbuf ) * 0.1f;
brightness = (float)MSG_ReadByte( pbuf ) / 255.0f;
R_TempSprite( pos, vec3_origin, scale, modelIndex,
kRenderGlow, kRenderFxNoDissipation, brightness, life, FTENT_FADEOUT );
break;
case TE_STREAK_SPLASH:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
color = MSG_ReadByte( &buf );
count = MSG_ReadShort( &buf );
vel = (float)MSG_ReadShort( &buf );
random = (float)MSG_ReadShort( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
color = MSG_ReadByte( pbuf );
count = MSG_ReadShort( pbuf );
vel = (float)MSG_ReadShort( pbuf );
random = (float)MSG_ReadShort( pbuf );
R_StreakSplash( pos, pos2, color, count, vel, -random, random );
break;
case TE_DLIGHT:
dl = CL_AllocDlight( 0 );
dl->origin[0] = MSG_ReadCoord( &buf );
dl->origin[1] = MSG_ReadCoord( &buf );
dl->origin[2] = MSG_ReadCoord( &buf );
dl->radius = (float)(MSG_ReadByte( &buf ) * 10.0f);
dl->color.r = MSG_ReadByte( &buf );
dl->color.g = MSG_ReadByte( &buf );
dl->color.b = MSG_ReadByte( &buf );
dl->die = cl.time + (float)(MSG_ReadByte( &buf ) * 0.1f);
dl->decay = (float)(MSG_ReadByte( &buf ) * 10.0f);
dl->origin[0] = MSG_ReadCoord( pbuf );
dl->origin[1] = MSG_ReadCoord( pbuf );
dl->origin[2] = MSG_ReadCoord( pbuf );
dl->radius = (float)(MSG_ReadByte( pbuf ) * 10.0f);
dl->color.r = MSG_ReadByte( pbuf );
dl->color.g = MSG_ReadByte( pbuf );
dl->color.b = MSG_ReadByte( pbuf );
dl->die = cl.time + (float)(MSG_ReadByte( pbuf ) * 0.1f);
dl->decay = (float)(MSG_ReadByte( pbuf ) * 10.0f);
break;
case TE_ELIGHT:
dl = CL_AllocElight( MSG_ReadShort( &buf ));
dl->origin[0] = MSG_ReadCoord( &buf );
dl->origin[1] = MSG_ReadCoord( &buf );
dl->origin[2] = MSG_ReadCoord( &buf );
dl->radius = MSG_ReadCoord( &buf );
dl->color.r = MSG_ReadByte( &buf );
dl->color.g = MSG_ReadByte( &buf );
dl->color.b = MSG_ReadByte( &buf );
life = (float)MSG_ReadByte( &buf ) * 0.1f;
dl = CL_AllocElight( MSG_ReadShort( pbuf ));
dl->origin[0] = MSG_ReadCoord( pbuf );
dl->origin[1] = MSG_ReadCoord( pbuf );
dl->origin[2] = MSG_ReadCoord( pbuf );
dl->radius = MSG_ReadCoord( pbuf );
dl->color.r = MSG_ReadByte( pbuf );
dl->color.g = MSG_ReadByte( pbuf );
dl->color.b = MSG_ReadByte( pbuf );
life = (float)MSG_ReadByte( pbuf ) * 0.1f;
dl->die = cl.time + life;
dl->decay = MSG_ReadCoord( &buf );
dl->decay = MSG_ReadCoord( pbuf );
if( life != 0 ) dl->decay /= life;
break;
case TE_TEXTMESSAGE:
CL_ParseTextMessage( &buf );
CL_ParseTextMessage( pbuf );
break;
case TE_LINE:
case TE_BOX:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
life = (float)(MSG_ReadShort( &buf ) * 0.1f);
r = MSG_ReadByte( &buf );
g = MSG_ReadByte( &buf );
b = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
life = (float)(MSG_ReadShort( pbuf ) * 0.1f);
r = MSG_ReadByte( pbuf );
g = MSG_ReadByte( pbuf );
b = MSG_ReadByte( pbuf );
if( type == TE_LINE ) R_ParticleLine( pos, pos2, r, g, b, life );
else R_ParticleBox( pos, pos2, r, g, b, life );
break;
case TE_LARGEFUNNEL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
flags = MSG_ReadShort( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
flags = MSG_ReadShort( pbuf );
R_LargeFunnel( pos, flags );
R_FunnelSprite( pos, modelIndex, flags );
break;
case TE_BLOODSTREAM:
case TE_BLOOD:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
color = MSG_ReadByte( &buf );
count = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
color = MSG_ReadByte( pbuf );
count = MSG_ReadByte( pbuf );
if( type == TE_BLOOD ) R_Blood( pos, pos2, color, count );
else R_BloodStream( pos, pos2, color, count );
break;
case TE_SHOWLINE:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
R_ShowLine( pos, pos2 );
break;
case TE_FIZZ:
entityIndex = MSG_ReadShort( &buf );
modelIndex = MSG_ReadShort( &buf );
scale = MSG_ReadByte( &buf ); // same as density
entityIndex = MSG_ReadShort( pbuf );
modelIndex = MSG_ReadShort( pbuf );
scale = MSG_ReadByte( pbuf ); // same as density
pEnt = CL_GetEntityByIndex( entityIndex );
R_FizzEffect( pEnt, modelIndex, scale );
break;
case TE_MODEL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
ang[0] = 0.0f;
ang[1] = MSG_ReadAngle( &buf ); // yaw angle
ang[1] = MSG_ReadAngle( pbuf ); // yaw angle
ang[2] = 0.0f;
modelIndex = MSG_ReadShort( &buf );
flags = MSG_ReadByte( &buf ); // sound flags
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
modelIndex = MSG_ReadShort( pbuf );
flags = MSG_ReadByte( pbuf ); // sound flags
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_TempModel( pos, pos2, ang, life, modelIndex, flags );
break;
case TE_EXPLODEMODEL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
vel = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadShort( &buf );
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
vel = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadShort( pbuf );
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_TempSphereModel( pos, vel, life, count, modelIndex );
break;
case TE_BREAKMODEL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
ang[0] = MSG_ReadCoord( &buf );
ang[1] = MSG_ReadCoord( &buf );
ang[2] = MSG_ReadCoord( &buf );
random = (float)MSG_ReadByte( &buf ) * 10.0f;
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf );
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
flags = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
ang[0] = MSG_ReadCoord( pbuf );
ang[1] = MSG_ReadCoord( pbuf );
ang[2] = MSG_ReadCoord( pbuf );
random = (float)MSG_ReadByte( pbuf ) * 10.0f;
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadByte( pbuf );
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
flags = MSG_ReadByte( pbuf );
R_BreakModel( pos, pos2, ang, random, life, count, modelIndex, (char)flags );
break;
case TE_GUNSHOTDECAL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
entityIndex = MSG_ReadShort( &buf );
decalIndex = MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
entityIndex = MSG_ReadShort( pbuf );
decalIndex = MSG_ReadByte( pbuf );
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
R_BulletImpactParticles( pos );
flags = COM_RandomLong( 0, 0x7fff );
@@ -2261,139 +2272,139 @@ void CL_ParseTempEntity( sizebuf_t *msg )
break;
case TE_SPRAY:
case TE_SPRITE_SPRAY:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf );
vel = (float)MSG_ReadByte( &buf );
random = (float)MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadByte( pbuf );
vel = (float)MSG_ReadByte( pbuf );
random = (float)MSG_ReadByte( pbuf );
if( type == TE_SPRAY )
{
flags = MSG_ReadByte( &buf ); // rendermode
flags = MSG_ReadByte( pbuf ); // rendermode
R_Spray( pos, pos2, modelIndex, count, vel, random, flags );
}
else R_Sprite_Spray( pos, pos2, modelIndex, count, vel * 2.0f, random );
break;
case TE_ARMOR_RICOCHET:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_RicochetSprite( pos, cl_sprite_ricochet, 0.1f, scale );
R_RicochetSound( pos );
break;
case TE_PLAYERDECAL:
color = MSG_ReadByte( &buf ) - 1; // playernum
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
entityIndex = MSG_ReadShort( &buf );
decalIndex = MSG_ReadByte( &buf );
color = MSG_ReadByte( pbuf ) - 1; // playernum
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
entityIndex = MSG_ReadShort( pbuf );
decalIndex = MSG_ReadByte( pbuf );
CL_PlayerDecal( color, decalIndex, entityIndex, pos );
break;
case TE_BUBBLES:
case TE_BUBBLETRAIL:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
scale = MSG_ReadCoord( &buf ); // water height
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf );
vel = MSG_ReadCoord( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
scale = MSG_ReadCoord( pbuf ); // water height
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadByte( pbuf );
vel = MSG_ReadCoord( pbuf );
if( type == TE_BUBBLES ) R_Bubbles( pos, pos2, scale, modelIndex, count, vel );
else R_BubbleTrail( pos, pos2, scale, modelIndex, count, vel );
break;
case TE_BLOODSPRITE:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf ); // sprite #1
decalIndex = MSG_ReadShort( &buf ); // sprite #2
color = MSG_ReadByte( &buf );
scale = (float)MSG_ReadByte( &buf );
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf ); // sprite #1
decalIndex = MSG_ReadShort( pbuf ); // sprite #2
color = MSG_ReadByte( pbuf );
scale = (float)MSG_ReadByte( pbuf );
R_BloodSprite( pos, color, modelIndex, decalIndex, scale );
break;
case TE_PROJECTILE:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf );
life = MSG_ReadByte( &buf );
color = MSG_ReadByte( &buf ); // playernum
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
modelIndex = MSG_ReadShort( pbuf );
life = MSG_ReadByte( pbuf );
color = MSG_ReadByte( pbuf ); // playernum
R_Projectile( pos, pos2, modelIndex, life, color, NULL );
break;
case TE_PLAYERSPRITES:
color = MSG_ReadShort( &buf ); // entitynum
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf );
random = (float)MSG_ReadByte( &buf );
color = MSG_ReadShort( pbuf ); // entitynum
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadByte( pbuf );
random = (float)MSG_ReadByte( pbuf );
R_PlayerSprites( color, modelIndex, count, random );
break;
case TE_PARTICLEBURST:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
scale = (float)MSG_ReadShort( &buf );
color = MSG_ReadByte( &buf );
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
scale = (float)MSG_ReadShort( pbuf );
color = MSG_ReadByte( pbuf );
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_ParticleBurst( pos, scale, color, life );
break;
case TE_FIREFIELD:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
scale = (float)MSG_ReadShort( &buf );
modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf );
flags = MSG_ReadByte( &buf );
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
scale = (float)MSG_ReadShort( pbuf );
modelIndex = MSG_ReadShort( pbuf );
count = MSG_ReadByte( pbuf );
flags = MSG_ReadByte( pbuf );
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_FireField( pos, scale, modelIndex, count, flags, life );
break;
case TE_PLAYERATTACHMENT:
color = MSG_ReadByte( &buf ); // playernum
scale = MSG_ReadCoord( &buf ); // height
modelIndex = MSG_ReadShort( &buf );
life = (float)(MSG_ReadShort( &buf ) * 0.1f);
color = MSG_ReadByte( pbuf ); // playernum
scale = MSG_ReadCoord( pbuf ); // height
modelIndex = MSG_ReadShort( pbuf );
life = (float)(MSG_ReadShort( pbuf ) * 0.1f);
R_AttachTentToPlayer( color, modelIndex, scale, life );
break;
case TE_KILLPLAYERATTACHMENTS:
color = MSG_ReadByte( &buf ); // playernum
color = MSG_ReadByte( pbuf ); // playernum
R_KillAttachedTents( color );
break;
case TE_MULTIGUNSHOT:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf ) * 0.1f;
pos2[1] = MSG_ReadCoord( &buf ) * 0.1f;
pos2[2] = MSG_ReadCoord( &buf ) * 0.1f;
ang[0] = MSG_ReadCoord( &buf ) * 0.01f;
ang[1] = MSG_ReadCoord( &buf ) * 0.01f;
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf ) * 0.1f;
pos2[1] = MSG_ReadCoord( pbuf ) * 0.1f;
pos2[2] = MSG_ReadCoord( pbuf ) * 0.1f;
ang[0] = MSG_ReadCoord( pbuf ) * 0.01f;
ang[1] = MSG_ReadCoord( pbuf ) * 0.01f;
ang[2] = 0.0f;
count = MSG_ReadByte( &buf );
decalIndices[0] = MSG_ReadByte( &buf );
count = MSG_ReadByte( pbuf );
decalIndices[0] = MSG_ReadByte( pbuf );
R_MultiGunshot( pos, pos2, ang, count, 1, decalIndices );
break;
case TE_USERTRACER:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
pos2[0] = MSG_ReadCoord( &buf );
pos2[1] = MSG_ReadCoord( &buf );
pos2[2] = MSG_ReadCoord( &buf );
life = (float)(MSG_ReadByte( &buf ) * 0.1f);
color = MSG_ReadByte( &buf );
scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
pos[0] = MSG_ReadCoord( pbuf );
pos[1] = MSG_ReadCoord( pbuf );
pos[2] = MSG_ReadCoord( pbuf );
pos2[0] = MSG_ReadCoord( pbuf );
pos2[1] = MSG_ReadCoord( pbuf );
pos2[2] = MSG_ReadCoord( pbuf );
life = (float)(MSG_ReadByte( pbuf ) * 0.1f);
color = MSG_ReadByte( pbuf );
scale = (float)(MSG_ReadByte( pbuf ) * 0.1f);
R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL );
break;
default:
@@ -2402,7 +2413,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
}
// throw warning
if( MSG_CheckOverflow( &buf ))
if( MSG_CheckOverflow( pbuf ))
Con_DPrintf( S_WARN "%s: overflow TE message %i\n", __func__, type );
}

View File

@@ -77,7 +77,6 @@ void R_MultiGunshot( const vec3_t org, const vec3_t dir, const vec3_t noise, int
void R_FireField( float *org, int radius, int modelIndex, int count, int flags, float life );
void R_PlayerSprites( int client, int modelIndex, int count, int size );
void R_Sprite_WallPuff( struct tempent_s *pTemp, float scale );
void R_DebugParticle( const vec3_t pos, byte r, byte g, byte b );
void R_RicochetSound( const vec3_t pos );
struct dlight_s *CL_AllocDlight( int key );
struct dlight_s *CL_AllocElight( int key );

View File

@@ -129,7 +129,6 @@ typedef struct
// misc local info
qboolean repredicting; // repredicting in progress
qboolean thirdperson;
qboolean apply_effects; // local player will not added but we should apply their effects: flashlight etc
float idealpitch;
int viewmodel;
@@ -278,6 +277,8 @@ typedef struct
int lostpackets; // count lost packets and show dialog in menu
double frametime_remainder;
uint worldmapCRC;
} client_t;
/*
@@ -309,14 +310,6 @@ typedef enum
CL_CHANGELEVEL, // draw 'loading' during changelevel
} scrstate_t;
typedef enum
{
PROTO_CURRENT = 0, // Xash3D 49
PROTO_LEGACY = 1, // Xash3D 48
PROTO_QUAKE = 2, // Quake 15
PROTO_GOLDSRC = 3, // GoldSrc 48
} connprotocol_t;
typedef struct
{
char name[32];
@@ -567,7 +560,6 @@ typedef struct
byte datagram_buf[MAX_DATAGRAM];
netchan_t netchan;
int challenge; // from the server to use for connecting
float packet_loss;
double packet_loss_recalc_time;
@@ -660,6 +652,7 @@ extern gameui_static_t gameui;
//
// cvars
//
extern convar_t showpause;
extern convar_t mp_decals;
extern convar_t cl_logomaxdim;
extern convar_t cl_allow_download;
@@ -754,13 +747,13 @@ void CL_Particle( const vec3_t org, int color, float life, int zpos, int zvel );
void CL_Init( void );
void CL_Disconnect_f( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename );
void CL_WriteUsercmd( sizebuf_t *msg, int from, int to );
int CL_GetFragmentSize( void *unused , fragsize_t mode );
void CL_WriteUsercmd( connprotocol_t proto, sizebuf_t *msg, int from, int to );
void CL_SetupNetchanForProtocol( connprotocol_t proto );
qboolean CL_PrecacheResources( void );
void CL_SetupOverviewParams( void );
void CL_UpdateFrameLerp( void );
int CL_IsDevOverviewMode( void );
void CL_SignonReply( void );
void CL_SignonReply( connprotocol_t proto );
void CL_ClearState( void );
//
@@ -790,8 +783,8 @@ int CL_GetDemoComment( const char *demoname, char *comment );
//
// cl_events.c
//
void CL_ParseEvent( sizebuf_t *msg );
void CL_ParseReliableEvent( sizebuf_t *msg );
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto );
void CL_SetEventIndex( const char *szEvName, int ev_index );
void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
@@ -868,20 +861,21 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
// cl_parse.c
//
void CL_ParseSetAngle( sizebuf_t *msg );
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy );
void CL_ParseLightStyle( sizebuf_t *msg );
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy );
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResource( sizebuf_t *msg );
void CL_ParseClientData( sizebuf_t *msg );
void CL_ParseClientData( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserPings( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseRestoreSoundPacket( sizebuf_t *msg );
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy );
void CL_ParseSignon( sizebuf_t *msg );
void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseRestore( sizebuf_t *msg );
void CL_ParseStaticDecal( sizebuf_t *msg );
void CL_ParseAddAngle( sizebuf_t *msg );
void CL_RegisterUserMessage( sizebuf_t *msg );
void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResourceList( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseMovevars( sizebuf_t *msg );
void CL_ParseResourceRequest( sizebuf_t *msg );
void CL_ParseCustomization( sizebuf_t *msg );
@@ -890,18 +884,22 @@ void CL_ParseSoundFade( sizebuf_t *msg );
void CL_ParseFileTransferFailed( sizebuf_t *msg );
void CL_ParseHLTV( sizebuf_t *msg );
void CL_ParseDirector( sizebuf_t *msg );
void CL_ParseVoiceInit( sizebuf_t *msg );
void CL_ParseVoiceData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResLocation( sizebuf_t *msg );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
void CL_ParseServerMessage( sizebuf_t *msg );
void CL_ParseTempEntity( sizebuf_t *msg );
qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset );
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto );
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
qboolean CL_RequestMissingResources( void );
void CL_RegisterResources ( sizebuf_t *msg );
void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseViewEntity( sizebuf_t *msg );
void CL_ParseServerTime( sizebuf_t *msg );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
void CL_ParseServerTime( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num, connprotocol_t proto );
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
void CL_ParseTextMessage( sizebuf_t *msg );
void CL_ParseExec( sizebuf_t *msg );
void CL_BatchResourceRequest( qboolean initialize );
int CL_EstimateNeededResources( void );
@@ -911,6 +909,11 @@ int CL_EstimateNeededResources( void );
void CL_ParseLegacyServerMessage( sizebuf_t *msg );
void CL_LegacyPrecache_f( void );
//
// cl_parse_gs.c
//
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg );
//
// cl_scrn.c
//
@@ -952,7 +955,6 @@ void CL_SetSolidPlayers( int playernum );
void CL_InitClientMove( void );
void CL_PredictMovement( qboolean repredicting );
void CL_CheckPredictionError( void );
qboolean CL_IsPredicted( void );
int CL_WaterEntity( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
pmtrace_t *CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
@@ -975,7 +977,9 @@ void CL_ParseQuakeMessage( sizebuf_t *msg );
//
struct channel_s;
struct rawchan_s;
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta );
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe );
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent );
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto );
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType );
void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset );
qboolean CL_GetEntitySpatialization( struct channel_s *ch );
@@ -1025,7 +1029,6 @@ void CL_InitParticles( void );
void CL_ClearParticles( void );
void CL_FreeParticles( void );
void CL_InitTempEnts( void );
void CL_ClearTempEnts( void );
void CL_FreeTempEnts( void );
void CL_TempEntUpdate( void );
void CL_InitViewBeams( void );

View File

@@ -875,7 +875,6 @@ void Con_Print( const char *txt )
Con_DeleteLastLine();
cr_pending = 0;
}
c = *txt;
switch( c )
@@ -883,10 +882,13 @@ void Con_Print( const char *txt )
case '\0':
break;
case '\r':
Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length;
cr_pending = 1;
bufpos = 0;
if( txt[1] != '\n' )
{
Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length;
cr_pending = 1;
bufpos = 0;
}
break;
case '\n':
Con_AddLine( buf, bufpos, true );
@@ -894,6 +896,7 @@ void Con_Print( const char *txt )
bufpos = 0;
break;
default:
buf[bufpos++] = c | mask;
if(( bufpos >= sizeof( buf ) - 1 ) || bufpos >= ( con.linewidth - 1 ))
{
@@ -1941,7 +1944,7 @@ void Con_DrawConsole( void )
{
if( !cl_allow_levelshots.value && !cls.timedemo )
{
if(( Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) && cls.key_dest != key_console )
if( cls.key_dest != key_console && ( Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )))
con.vislines = con.showlines = 0;
else con.vislines = con.showlines = refState.height;
}

View File

@@ -569,10 +569,9 @@ IN_EngineAppendMove
Called from cl_main.c after generating command in client
================
*/
void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active )
{
float forward, side, pitch, yaw;
usercmd_t *cmd = cmd1;
if( clgame.dllFuncs.pfnLookEvent )
return;

View File

@@ -25,6 +25,7 @@ INPUT
*/
#include "keydefs.h"
#include "usercmd.h"
//
// input.c
@@ -43,7 +44,7 @@ void IN_ToggleClientMouse( int newstate, int oldstate );
uint IN_CollectInputDevices( void );
void IN_LockInputDevices( qboolean lock );
void IN_EngineAppendMove( float frametime, void *cmd, qboolean active );
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
extern convar_t m_yaw;
extern convar_t m_pitch;

View File

@@ -1894,7 +1894,7 @@ S_VoiceRecordStart_f
*/
static void S_VoiceRecordStart_f( void )
{
if( cls.state != ca_active || cls.legacymode )
if( cls.state != ca_active )
return;
Voice_RecordStart();

View File

@@ -248,6 +248,12 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
const char *p;
int len;
// HACKHACK: some modders send strings like "/fvox/_period four"
// which should get parsed as "_period four" said by fvox
// it might be incorrect but ignore first slash here for now
if( psz[0] == '/' )
psz++;
// search / backwards
p = Q_strrchr( psz, '/' );
@@ -595,8 +601,8 @@ static void Test_VOX_GetDirectory( void )
{
"", "", "vox/",
"bark bark", "bark bark", "vox/",
"barney/meow", "meow", "barney/"
"barney/meow", "meow", "barney/",
"/fvox/_period", "_period", "fvox/",
};
int i;

View File

@@ -396,6 +396,9 @@ void Voice_RecordStart( void )
{
Voice_RecordStop();
if( !voice.initialized )
return;
if( voice_inputfromfile.value )
{
voice.input_file = FS_LoadSound( "voice_input.wav", NULL, 0 );
@@ -415,7 +418,7 @@ void Voice_RecordStart( void )
}
}
if( !Voice_IsRecording() )
if( !Voice_IsRecording( ) && voice.device_opened )
voice.is_recording = VoiceCapture_Activate( true );
if( Voice_IsRecording() )
@@ -627,7 +630,8 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
{
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
if( COM_CheckStringEmpty( pszCodecName ))
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
// reset saved codec name, we won't enable voice for this connection
voice_codec_init[0] = 0;

View File

@@ -25,7 +25,7 @@ typedef enum
T_COUNT
} cvartype_t;
const char *cvartypes[] = { NULL, "BOOL", "NUMBER", "LIST", "STRING" };
static const char *const cvartypes[] = { NULL, "BOOL", "NUMBER", "LIST", "STRING" };
typedef struct parserstate_s
{

View File

@@ -24,18 +24,27 @@ GNU General Public License for more details.
typedef struct
{
byte *data;
int cursize;
int maxsize;
byte *const data;
const int maxsize;
int cursize;
} cmdbuf_t;
qboolean cmd_wait;
cmdbuf_t cmd_text, filteredcmd_text;
byte cmd_text_buf[MAX_CMD_BUFFER];
byte filteredcmd_text_buf[MAX_CMD_BUFFER];
cmdalias_t *cmd_alias;
uint cmd_condition;
int cmd_condlevel;
static qboolean cmd_wait;
static byte cmd_text_buf[MAX_CMD_BUFFER];
static byte filteredcmd_text_buf[MAX_CMD_BUFFER];
static cmdbuf_t cmd_text =
{
.data = cmd_text_buf,
.maxsize = ARRAYSIZE( cmd_text_buf ),
};
static cmdbuf_t filteredcmd_text =
{
.data = filteredcmd_text_buf,
.maxsize = ARRAYSIZE( filteredcmd_text_buf ),
};
static cmdalias_t *cmd_alias;
static uint cmd_condition;
static int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
@@ -48,20 +57,6 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
=============================================================================
*/
/*
============
Cbuf_Init
============
*/
static void Cbuf_Init( void )
{
cmd_text.data = cmd_text_buf;
filteredcmd_text.data = filteredcmd_text_buf;
filteredcmd_text.maxsize = cmd_text.maxsize = MAX_CMD_BUFFER;
filteredcmd_text.cursize = cmd_text.cursize = 0;
}
/*
============
Cbuf_Clear
@@ -1219,13 +1214,13 @@ void Cmd_Unlink( int group )
cmd_t **prev;
int count = 0;
if( Cvar_VariableInteger( "host_gameloaded" ) && FBitSet( group, CMD_SERVERDLL ))
if( FBitSet( group, CMD_SERVERDLL ) && Cvar_VariableInteger( "host_gameloaded" ))
return;
if( Cvar_VariableInteger( "host_clientloaded" ) && FBitSet( group, CMD_CLIENTDLL ))
if( FBitSet( group, CMD_CLIENTDLL ) && Cvar_VariableInteger( "host_clientloaded" ))
return;
if( Cvar_VariableInteger( "host_gameuiloaded" ) && FBitSet( group, CMD_GAMEUIDLL ))
if( FBitSet( group, CMD_GAMEUIDLL ) && Cvar_VariableInteger( "host_gameuiloaded" ))
return;
prev = &cmd_functions;
@@ -1387,8 +1382,6 @@ Cmd_Init
*/
void Cmd_Init( void )
{
Cbuf_Init();
cmd_functions = NULL;
cmd_condition = 0;
cmd_alias = NULL;

View File

@@ -23,7 +23,7 @@ GNU General Public License for more details.
#include "client.h"
#include "library.h"
static const char *file_exts[] =
static const char *const file_exts[] =
{
// ban text files that don't make sense as resource
"cfg", "lst", "ini", "log",
@@ -759,25 +759,6 @@ void GAME_EXPORT COM_FreeFile( void *buffer )
free( buffer );
}
/*
=============
COM_NormalizeAngles
=============
*/
void COM_NormalizeAngles( vec3_t angles )
{
int i;
for( i = 0; i < 3; i++ )
{
if( angles[i] > 180.0f )
angles[i] -= 360.0f;
else if( angles[i] < -180.0f )
angles[i] += 360.0f;
}
}
/*
=============
pfnGetModelType
@@ -843,7 +824,7 @@ int GAME_EXPORT COM_CompareFileTime( const char *filename1, const char *filename
if( ft1 == -1 || ft2 == -1 )
return bRet;
*iCompare = Host_CompareFileTime( ft1, ft2 );
*iCompare = ft1 < ft2 ? -1 : ( ft1 > ft2 ? 1 : 0 );
bRet = 1;
}
@@ -898,18 +879,40 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
char lwrfilename[4096];
const char *first, *last;
const char *ext;
size_t len;
int i;
if( !COM_CheckString( filename ))
return false;
ext = COM_FileExtension( lwrfilename );
ext = COM_FileExtension( filename );
len = Q_strlen( filename );
// only allow extensionless files that start with !MD5
if( !Q_strncmp( filename, "!MD5", 4 ) && ext[0] == 0 )
if( !Q_strncmp( filename, "!MD5", 4 ))
{
if( COM_CheckStringEmpty( ext ))
return false;
len = Q_strlen( filename );
if( len != 36 )
return false;
for( i = 4; i < len; i++ )
{
if(( filename[i] >= '0' && filename[i] <= '9' ) ||
( filename[i] >= 'A' && filename[i] <= 'F' ))
continue;
return false;
}
return true;
}
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
ext = COM_FileExtension( lwrfilename );
if( Q_strpbrk( lwrfilename, "\\:~" ) || Q_strstr( lwrfilename, ".." ) )
return false;
@@ -1042,28 +1045,13 @@ void GAME_EXPORT pfnResetTutorMessageDecayData( void )
void Test_RunCommon( void )
{
char *file = (char *)"q asdf \"qwerty\" \"f \\\"f\" meowmeow\n// comment \"stuff ignored\"\nbark";
int len;
char buf[5];
Msg( "Checking COM_IsSafeFileToDownload...\n" );
Msg( "Checking COM_ParseFile...\n" );
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, NULL );
TASSERT( !Q_strcmp( buf, "asdf" ) && len == 4);
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, NULL );
TASSERT( !Q_strcmp( buf, "f \"f" ) && len == 4);
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, NULL );
TASSERT( !Q_strcmp( buf, "bark" ) && len == 4);
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302BC732" ), true );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD56f1ffd8c96bd64c9c27955309f6ecfe6" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302B.exe" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5/../../valve/resource/GameMenu.res" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "not-a-virus-trust-me.bat" ), false );
TASSERT_EQi( COM_IsSafeFileToDownload( "a-texture.png" ), true );
}
#endif

View File

@@ -168,6 +168,7 @@ extern convar_t sys_timescale;
extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password;
extern convar_t hpk_custom_file;
extern convar_t con_gamemaps;
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
@@ -528,7 +529,6 @@ typedef void( *pfnChangeGame )( const char *progname );
qboolean Host_IsQuakeCompatible( void );
void EXPORT Host_Shutdown( void );
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func );
int Host_CompareFileTime( int ft1, int ft2 );
void Host_EndGame( qboolean abort, const char *message, ... ) _format( 2 );
void Host_AbortCurrentFrame( void ) NORETURN;
void Host_WriteServerConfig( const char *name );
@@ -537,7 +537,7 @@ void Host_WriteVideoConfig( void );
void Host_WriteConfig( void );
void Host_ShutdownServer( void );
void Host_Error( const char *error, ... ) _format( 1 );
void Host_ValidateEngineFeatures( uint32_t features );
void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features );
void Host_Frame( double time );
void Host_Credits( void );
@@ -670,6 +670,15 @@ void HPAK_FlushHostQueue( void );
#define INPUT_DEVICE_JOYSTICK (1<<2)
#define INPUT_DEVICE_VR (1<<3)
typedef enum connprotocol_e
{
PROTO_CURRENT = 0, // Xash3D 49
PROTO_LEGACY, // Xash3D 48
PROTO_QUAKE, // Quake 15
PROTO_GOLDSRC, // GoldSrc 48
} connprotocol_t;
// shared calls
struct physent_s;
struct sv_client_s;
@@ -680,7 +689,6 @@ qboolean CL_IsThirdPerson( void );
qboolean CL_IsIntermission( void );
qboolean CL_Initialized( void );
char *CL_Userinfo( void );
void CL_LegacyUpdateInfo( void );
void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
@@ -761,13 +769,34 @@ void UI_ShowConnectionWarning( void );
void Cmd_Null_f( void );
void Rcon_Print( host_redirect_t *rd, 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 );
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer );
static inline void COM_NormalizeAngles( vec3_t angles )
{
int i;
for( i = 0; i < 3; i++ )
{
if( angles[i] > 180.0f )
angles[i] -= 360.0f;
else if( angles[i] < -180.0f )
angles[i] += 360.0f;
}
}
#if !XASH_DEDICATED
connprotocol_t CL_Protocol( void );
#else
static inline connprotocol_t CL_Protocol( void )
{
return PROTO_CURRENT;
}
#endif
static inline qboolean Host_IsLocalGame( void )
{
if( SV_Active( ))
@@ -817,6 +846,16 @@ void NET_MasterClear( void );
void NET_MasterShutdown( void );
qboolean NET_GetMaster( netadr_t from, uint *challenge, double *last_heartbeat );
//
// munge.c
//
void COM_Munge( byte *data, size_t len, int seq );
void COM_UnMunge( byte *data, size_t len, int seq );
void COM_Munge2( byte *data, size_t len, int seq );
void COM_UnMunge2( byte *data, size_t len, int seq );
void COM_Munge3( byte *data, size_t len, int seq );
void COM_UnMunge3( byte *data, size_t len, int seq );
//
// sounds.c
//

View File

@@ -18,8 +18,6 @@ GNU General Public License for more details.
#include "const.h"
#include "kbutton.h"
extern convar_t con_gamemaps;
#define CON_MAXCMDS 4096 // auto-complete intermediate list
typedef struct autocomplete_list_s
@@ -1012,7 +1010,7 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
return Cmd_CheckMapsList_R( fRefresh, true );
}
autocomplete_list_t cmd_list[] =
static const autocomplete_list_t cmd_list[] =
{
{ "map_background", 1, Cmd_GetMapList },
{ "changelevel2", 1, Cmd_GetMapList },
@@ -1075,7 +1073,7 @@ for various cmds
*/
static qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize )
{
autocomplete_list_t *list;
const autocomplete_list_t *list;
for( list = cmd_list; list->name; list++ )
{

View File

@@ -18,17 +18,17 @@ GNU General Public License for more details.
#include "base_cmd.h"
#include "eiface.h" // ARRAYSIZE
convar_t *cvar_vars = NULL; // head of list
static convar_t *cvar_vars = NULL; // head of list
CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" );
#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[] =
#ifdef HACKS_RELATED_HLMODS
static const cvar_filter_quirks_t cvar_filter_quirks[] =
{
// EXAMPLE:
//{
@@ -44,10 +44,10 @@ static cvar_filter_quirks_t cvar_filter_quirks[] =
"cl_dodmusic" // Day of Defeat Beta 1.3 cvar
},
};
static cvar_filter_quirks_t *cvar_active_filter_quirks = NULL;
#endif
static const cvar_filter_quirks_t *cvar_active_filter_quirks = NULL;
CVAR_DEFINE_AUTO( cl_filterstuffcmd, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "filter commands coming from server" );
/*
@@ -70,15 +70,14 @@ find the specified variable by name
*/
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
{
// TODO: ignore group for cvar
#if defined(XASH_HASHED_VARS)
return (convar_t *)BaseCmd_Find( HM_CVAR, var_name );
#else
convar_t *var;
convar_t *var;
if( !var_name )
return NULL;
#if defined(XASH_HASHED_VARS) // TODO: ignore_group
var = BaseCmd_Find( HM_CVAR, var_name );
#else
for( var = cvar_vars; var; var = var->next )
{
if( ignore_group && FBitSet( ignore_group, var->flags ))
@@ -87,9 +86,13 @@ convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group )
if( !Q_stricmp( var_name, var->name ))
return var;
}
return NULL;
#endif
// HACKHACK: HL25 compatibility
if( !var && !Q_stricmp( var_name, "gl_widescreen_yfov" ))
var = Cvar_FindVarExt( "r_adjust_fov", ignore_group );
return var;
}
/*
@@ -272,6 +275,15 @@ static qboolean Cvar_ValidateVarName( const char *s, qboolean isvalue )
return true;
}
static void Cvar_Free( convar_t *var )
{
freestring( var->name );
freestring( var->string );
freestring( var->def_string );
freestring( var->desc );
Mem_Free( var );
}
/*
============
Cvar_UnlinkVar
@@ -311,17 +323,13 @@ static int Cvar_UnlinkVar( const char *var_name, int group )
#endif
// unlink variable from list
freestring( var->string );
*prev = var->next;
// only allocated cvars can throw these fields
if( FBitSet( var->flags, FCVAR_ALLOCATED ))
{
freestring( var->name );
freestring( var->def_string );
freestring( var->desc );
Mem_Free( var );
}
Cvar_Free( var );
else
freestring( var->string );
count++;
}
@@ -610,7 +618,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
return Cvar_Get( var_name, value, FCVAR_USER_CREATED, NULL );
}
else
{
{
if( !Cmd_CurrentCommandIsPrivileged( ))
{
if( FBitSet( var->flags, FCVAR_PRIVILEGED ))
@@ -966,7 +974,6 @@ 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 )
@@ -997,7 +1004,6 @@ static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
}
}
}
#endif
if( FBitSet( v->flags, FCVAR_FILTERABLE ))
return false;
@@ -1217,6 +1223,20 @@ static void Cvar_List_f( void )
Con_Printf( "\n%i cvars\n", count );
}
static qboolean Cvar_ValidateUnlinkGroup( int group )
{
if( FBitSet( group, FCVAR_EXTDLL ) && !Cvar_VariableInteger( "host_gameloaded" ))
return false;
if( FBitSet( group, FCVAR_CLIENTDLL ) && !Cvar_VariableInteger( "host_clientloaded" ))
return false;
if( FBitSet( group, FCVAR_GAMEUIDLL ) && !Cvar_VariableInteger( "host_gameuiloaded" ))
return false;
return true;
}
/*
============
Cvar_Unlink
@@ -1228,19 +1248,95 @@ void Cvar_Unlink( int group )
{
int count;
if( Cvar_VariableInteger( "host_gameloaded" ) && FBitSet( group, FCVAR_EXTDLL ))
return;
if( Cvar_VariableInteger( "host_clientloaded" ) && FBitSet( group, FCVAR_CLIENTDLL ))
return;
if( Cvar_VariableInteger( "host_gameuiloaded" ) && FBitSet( group, FCVAR_GAMEUIDLL ))
if( !Cvar_ValidateUnlinkGroup( group ))
return;
count = Cvar_UnlinkVar( NULL, group );
Con_Reportf( "unlink %i cvars\n", count );
}
pending_cvar_t *Cvar_PrepareToUnlink( int group )
{
pending_cvar_t *list = NULL;
pending_cvar_t *tail = NULL;
convar_t *cv;
for( cv = cvar_vars; cv != NULL; cv = cv->next )
{
size_t namelen;
pending_cvar_t *p;
if( !FBitSet( cv->flags, group ))
continue;
namelen = Q_strlen( cv->name ) + 1;
p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
p->next = NULL;
p->cv_cur = cv;
p->cv_next = cv->next;
p->cv_allocated = FBitSet( cv->flags, FCVAR_ALLOCATED ) ? true : false;
Q_strncpy( p->cv_name, cv->name, namelen );
if( list == NULL )
list = p;
else
tail->next = p;
tail = p;
}
return list;
}
void Cvar_UnlinkPendingCvars( pending_cvar_t *list )
{
int count = 0;
while( list != NULL )
{
pending_cvar_t *next = list->next;
convar_t *cv_prev, *cv;
for( cv_prev = NULL, cv = cvar_vars; cv != NULL; cv_prev = cv, cv = cv->next )
{
if( cv == list->cv_cur )
break;
}
if( cv == NULL )
{
Con_Reportf( "%s: can't find %s in variable list\n", __func__, list->cv_name );
Mem_Free( list );
list = next;
continue;
}
// unlink cvar from list
BaseCmd_Remove( HM_CVAR, list->cv_name );
if( cv_prev != NULL )
cv_prev->next = list->cv_next;
else cvar_vars = list->cv_next;
if( list->cv_allocated )
Cvar_Free( list->cv_cur );
else
{
// TODO: can't free cvar string here because
// it's not safe to access cv_cur and
// can't save string pointer because it could've been changed
// and pointer to it is already lost
// freestring( list->cv_string );
}
// now free pending cvar
Mem_Free( list );
list = next;
count++;
}
Con_Reportf( "unlink %i cvars\n", count );
}
/*
============
Cvar_Init

View File

@@ -18,6 +18,18 @@ GNU General Public License for more details.
#include "cvardef.h"
// As some mods dynamically allocate cvars and free them without notifying the engine
// let's construct a list of cvars that must be removed
typedef struct pending_cvar_s
{
struct pending_cvar_s *next;
convar_t *cv_cur; // preserve the data that might get freed
convar_t *cv_next;
qboolean cv_allocated; // if it's allocated by us, it's safe to access cv_cur
char cv_name[];
} pending_cvar_t;
cvar_t *Cvar_GetList( void );
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
@@ -43,4 +55,7 @@ void Cvar_Init( void );
void Cvar_PostFSInit( void );
void Cvar_Unlink( int group );
pending_cvar_t *Cvar_PrepareToUnlink( int group );
void Cvar_UnlinkPendingCvars( pending_cvar_t *pending_cvars );
#endif//CVAR_H

View File

@@ -16,12 +16,37 @@ GNU General Public License for more details.
#include "common.h"
#include "xash3d_mathlib.h"
#include "ref_api.h"
#include "server.h"
ref_globals_t refState;
void CL_ProcessFile( qboolean successfully_received, const char *filename )
const char *CL_MsgInfo( int cmd )
{
static string sz;
Q_strncpy( sz, "???", sizeof( sz ));
if( cmd >= 0 && cmd <= svc_lastmsg )
{
// get engine message name
const char *svc_string = svc_strings[cmd];
Q_strncpy( sz, svc_string, sizeof( sz ));
}
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
{
int i;
for( i = 0; i < MAX_USER_MESSAGES; i++ )
{
if( svgame.msg[i].number == cmd )
{
Q_strncpy( sz, svgame.msg[i].name, sizeof( sz ));
break;
}
}
}
return sz;
}
int GAME_EXPORT CL_Active( void )
@@ -134,11 +159,6 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
}
int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
{
return 0;
}
int GAME_EXPORT CL_GetMaxClients( void )
{
return 0;

View File

@@ -40,7 +40,7 @@ GNU General Public License for more details.
#include "render_api.h" // decallist_t
#include "tests.h"
pfnChangeGame pChangeGame = NULL;
static pfnChangeGame pChangeGame = NULL;
host_parm_t host; // host parms
#ifdef XASH_ENGINE_TESTS
@@ -49,8 +49,8 @@ struct tests_stats_s tests_stats;
CVAR_DEFINE( host_developer, "developer", "0", FCVAR_FILTERABLE, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_timescale, "1.0", FCVAR_FILTERABLE, "scale frame time" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", FCVAR_SERVER, "framerate in dedicated mode" );
static CVAR_DEFINE_AUTO( sys_ticrate, "100", FCVAR_SERVER, "framerate in dedicated mode" );
static CVAR_DEFINE_AUTO( host_serverstate, "0", FCVAR_READ_ONLY, "displays current server state" );
static CVAR_DEFINE_AUTO( host_gameloaded, "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );
static CVAR_DEFINE_AUTO( host_clientloaded, "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" );
@@ -69,14 +69,14 @@ typedef struct feature_message_s
const char *arg;
} feature_message_t;
static feature_message_t bugcomp_features[] =
static const feature_message_t bugcomp_features[] =
{
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" },
{ BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG, "GoldSrc Message Rewrite Facility", "gsmrf" },
{ BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE, "spatialize sounds with zero attenuation", "sp_attn_none" },
};
static feature_message_t engine_features[] =
static const feature_message_t engine_features[] =
{
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
@@ -200,19 +200,6 @@ static void Sys_PrintUsage( const char *exename )
Sys_Quit();
}
int Host_CompareFileTime( int ft1, int ft2 )
{
if( ft1 < ft2 )
{
return -1;
}
else if( ft1 > ft2 )
{
return 1;
}
return 0;
}
void Host_ShutdownServer( void )
{
SV_Shutdown( "Server was killed\n" );
@@ -223,7 +210,7 @@ void Host_ShutdownServer( void )
Host_PrintEngineFeatures
================
*/
static void Host_PrintFeatures( uint32_t flags, const char *s, feature_message_t *features, size_t size )
static void Host_PrintFeatures( uint32_t flags, const char *s, const feature_message_t *features, size_t size )
{
size_t i;
@@ -241,15 +228,8 @@ Host_ValidateEngineFeatures
validate features bits and set host.features
==============
*/
void Host_ValidateEngineFeatures( uint32_t features )
void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features )
{
uint32_t mask = ENGINE_FEATURES_MASK;
#if !XASH_DEDICATED
if( !Host_IsDedicated( ) && cls.legacymode )
mask = ENGINE_LEGACY_FEATURES_MASK;
#endif
// don't allow unsupported bits
features &= mask;
@@ -1072,6 +1052,9 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
Host_RunTests( 0 );
#endif
#if XASH_DEDICATED
Platform_SetupSigtermHandling();
#endif
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
FS_Init( basedir );

View File

@@ -1055,7 +1055,7 @@ static void HPAK_Extract_f( void )
FS_Seek( f, entry->filepos, SEEK_SET );
FS_Read( f, pData, nDataSize );
Q_snprintf( szFileOut, sizeof( szFileOut ), "hpklmps\\lmp%04i.bmp", nCurrent );
Q_snprintf( szFileOut, sizeof( szFileOut ), "hpklmps/lmp%04i.bmp", nCurrent );
FS_WriteFile( szFileOut, pData, nDataSize );
if( pData ) Mem_Free( pData );
}

View File

@@ -198,7 +198,7 @@ static mlumpinfo_t srclumps[HEADER_LUMPS] =
{ LUMP_MODELS, 1, MAX_MAP_MODELS, sizeof( dmodel_t ), -1, "models", CHECK_OVERFLOW, (const void **)&srcmodel.submodels, &srcmodel.numsubmodels },
};
static mlumpinfo_t extlumps[EXTRA_LUMPS] =
static const mlumpinfo_t extlumps[EXTRA_LUMPS] =
{
{ LUMP_LIGHTVECS, 0, MAX_MAP_LIGHTING, sizeof( byte ), -1, "deluxmaps", USE_EXTRAHEADER, (const void **)&srcmodel.deluxdata, &srcmodel.deluxdatasize },
{ LUMP_FACEINFO, 0, MAX_MAP_FACEINFO, sizeof( dfaceinfo_t ), -1, "faceinfos", CHECK_OVERFLOW|USE_EXTRAHEADER, (const void **)&srcmodel.faceinfo, &srcmodel.numfaceinfo },
@@ -347,7 +347,7 @@ Mod_LoadLump
generic loader
=================
*/
static void Mod_LoadLump( const byte *in, mlumpinfo_t *info, mlumpstat_t *stat, int flags )
static void Mod_LoadLump( const byte *in, const mlumpinfo_t *info, mlumpstat_t *stat, int flags )
{
int version = ((dheader_t *)in)->version;
size_t numelems, real_entrysize;

161
engine/common/munge.c Normal file
View File

@@ -0,0 +1,161 @@
/*
munge.c - protocol mangling for GoldSrc
Copyright (C) ReHLDS developers
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"
static const byte mungify_table[] =
{
0x7A, 0x64, 0x05, 0xF1, 0x1B, 0x9B, 0xA0, 0xB5,
0xCA, 0xED, 0x61, 0x0D, 0x4A, 0xDF, 0x8E, 0xC7,
};
static const byte mungify_table2[] =
{
0x05, 0x61, 0x7A, 0xED, 0x1B, 0xCA, 0x0D, 0x9B,
0x4A, 0xF1, 0x64, 0xC7, 0xB5, 0x8E, 0xDF, 0xA0,
};
static const byte mungify_table3[] =
{
0x20, 0x07, 0x13, 0x61, 0x03, 0x45, 0x17, 0x72,
0x0A, 0x2D, 0x48, 0x0C, 0x4A, 0x12, 0xA9, 0xB5,
};
static uint COM_SwapLong( uint c )
{
return ((( c >> 0 ) & 0xFF) << 24 ) +
((( c >> 8 ) & 0xFF) << 16 ) +
((( c >> 16 ) & 0xFF) << 8 ) +
((( c >> 24 ) & 0xFF) << 0 );
}
static void COM_GenericMunge( byte *data, const size_t len, const int seq, const byte *table, const qboolean reverse )
{
const size_t mungelen = len / 4;
int i;
for( i = 0; i < mungelen; i++ )
{
uint32_t c;
void *pc = &data[i * 4];
byte *p;
int j;
memcpy( &c, pc, sizeof( c ));
c ^= seq;
if( !reverse )
c = COM_SwapLong( c );
p = (byte *)&c;
for( j = 0; j < 4; j++ )
*p++ ^= (0xa5 | (j << j) | j | table[(i + j) & 0x0f]);
if( reverse )
c = COM_SwapLong( c );
c ^= ~seq;
memcpy( pc, &c, sizeof( c ));
}
}
// Anti-proxy/aimbot obfuscation code
// COM_UnMunge should reversably fixup the data
void COM_Munge( byte *data, size_t len, int seq )
{
COM_GenericMunge( data, len, seq, mungify_table, false );
}
void COM_UnMunge( byte *data, size_t len, int seq )
{
COM_GenericMunge( data, len, seq, mungify_table, true );
}
void COM_Munge2( byte *data, size_t len, int seq )
{
COM_GenericMunge( data, len, seq, mungify_table2, false );
}
void COM_UnMunge2( byte *data, size_t len, int seq )
{
COM_GenericMunge( data, len, seq, mungify_table2, true );
}
void COM_Munge3( byte *data, size_t len, int seq )
{
COM_GenericMunge( data, len, seq, mungify_table3, false );
}
void COM_UnMunge3( byte *data, size_t len, int seq )
{
COM_GenericMunge( data, len, seq, mungify_table3, true );
}
#if XASH_ENGINE_TESTS
#include "tests.h"
void Test_RunMunge( void )
{
const char *msg = "0123456789qwertyuiopasdfghjklzxcvbnmaa";
const char *expected[][3] =
{
{
"\x33\x2a\x61\x30\x2d\x6e\x35\x74\x2d\x79\x79\x78\x73\x34\x32\x25\x30\x2f\x39\x35\x26\x3c\x33\x61\x31\x22\x78\x67\x29\x68\x6a\x6c\x7d\x7e\x72\x36\x61\x61",
"\x69\x2a\x31\x30\x2d\x36\x25\x74\x77\x61\x79\x38\x6b\x34\x62\x25\x30\x7f\x39\x35\x76\x34\x33\x61\x39\x2a\x78\x67\x23\x68\x7a\x6c\x7d\x66\x72\x76\x61\x61",
"\x69\x6a\x71\x30\x6f\x7e\x25\x74\x3f\x69\x69\x38\x63\x2c\x62\x25\x28\x77\x29\x75\x7c\x2c\x73\x21\x23\x62\x38\x27\x6b\x28\x2a\x6c\x3d\x3e\x72\x36\x61\x61",
}, {
"\x32\x2a\x61\x31\x2c\x6e\x35\x75\x2c\x79\x79\x79\x72\x34\x32\x24\x31\x2f\x39\x34\x27\x3c\x33\x60\x30\x22\x78\x66\x28\x68\x6a\x6d\x7c\x7e\x72\x37\x61\x61",
"\x68\x2a\x31\x31\x2c\x36\x25\x75\x76\x61\x79\x39\x6a\x34\x62\x24\x31\x7f\x39\x34\x77\x34\x33\x60\x38\x2a\x78\x66\x22\x68\x7a\x6d\x7c\x66\x72\x77\x61\x61",
"\x68\x6a\x71\x31\x6e\x7e\x25\x75\x3e\x69\x69\x39\x62\x2c\x62\x24\x29\x77\x29\x74\x7d\x2c\x73\x20\x22\x62\x38\x26\x6a\x28\x2a\x6d\x3c\x3e\x72\x37\x61\x61",
}
};
string buf;
size_t msglen = Q_strlen( msg ) + 1;
int i;
Q_strncpy( buf, msg, msglen );
for( i = 0; i < 0xFF; i++ )
{
COM_Munge( buf, msglen, i );
if( i < sizeof( expected ) / sizeof( expected[0] ))
{
//for( int j = 0; j < msglen; j++ )
// printf( "\\x%02x", buf[j] );
//printf( "\n" );
TASSERT( !memcmp( buf, expected[i][0], msglen ));
}
COM_UnMunge( buf, msglen, i );
TASSERT( !Q_strcmp( buf, msg ));
COM_Munge2( buf, msglen, i );
if( i < sizeof( expected ) / sizeof( expected[0] ))
{
TASSERT( !memcmp( buf, expected[i][1], msglen ));
}
COM_UnMunge2( buf, msglen, i );
TASSERT( !Q_strcmp( buf, msg ));
COM_Munge3( buf, msglen, i );
if( i < sizeof( expected ) / sizeof( expected[0] ))
{
TASSERT( !memcmp( buf, expected[i][2], msglen ));
}
COM_UnMunge3( buf, msglen, i );
TASSERT( !Q_strcmp( buf, msg ));
}
}
#endif

View File

@@ -17,15 +17,13 @@ GNU General Public License for more details.
#include "protocol.h"
#include "net_buffer.h"
#include "xash3d_mathlib.h"
//#define DEBUG_NET_MESSAGES_SEND
//#define DEBUG_NET_MESSAGES_READ
// precalculated bit masks for WriteUBitLong.
// Using these tables instead of doing the calculations
// gives a 33% speedup in WriteUBitLong.
static uint32_t BitWriteMasks[32][33];
static uint32_t ExtraMasks[32];
const char *svc_strings[svc_lastmsg+1] =
const char *const svc_strings[svc_lastmsg+1] =
{
"svc_bad",
"svc_nop",
@@ -81,7 +79,7 @@ const char *svc_strings[svc_lastmsg+1] =
"svc_director",
"svc_voiceinit",
"svc_voicedata",
"svc_deltapacketbones",
"svc_unused54",
"svc_unused55",
"svc_resourcelocation",
"svc_querycvarvalue",
@@ -89,7 +87,7 @@ const char *svc_strings[svc_lastmsg+1] =
"svc_exec",
};
const char *svc_legacy_strings[svc_lastmsg+1] =
const char *const svc_legacy_strings[svc_lastmsg+1] =
{
[svc_legacy_changing] = "svc_legacy_changing",
[svc_legacy_ambientsound] = "svc_legacy_ambientsound",
@@ -100,7 +98,7 @@ const char *svc_legacy_strings[svc_lastmsg+1] =
[svc_legacy_chokecount] = "svc_legacy_chokecount",
};
const char *svc_goldsrc_strings[svc_lastmsg+1] =
const char *const svc_goldsrc_strings[svc_lastmsg+1] =
{
[svc_goldsrc_version] = "svc_goldsrc_version",
[svc_goldsrc_serverinfo] = "svc_goldsrc_serverinfo",
@@ -119,7 +117,7 @@ const char *svc_goldsrc_strings[svc_lastmsg+1] =
[svc_goldsrc_sendcvarvalue2] = "svc_goldsrc_sendcvarvalue2",
};
const char *svc_quake_strings[svc_lastmsg+1] =
const char *const svc_quake_strings[svc_lastmsg+1] =
{
[svc_updatestat] = "svc_quake_updatestat",
[svc_version] = "svc_quake_version",
@@ -213,17 +211,23 @@ void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits )
// do we have a valid # of bits to encode with?
Assert( numbits >= 1 && numbits <= 32 );
// NOTE: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
// (Some old code writes direct integers right into the buffer).
if( data < 0 )
if( sb->iAlternateSign )
{
MSG_WriteUBitLong( sb, (uint)( 0x80000000 + data ), numbits - 1 );
MSG_WriteOneBit( sb, 1 );
MSG_WriteOneBit( sb, data < 0 ? 1 : 0 );
MSG_WriteUBitLong( sb, (uint)abs( data ), numbits - 1 );
}
else
{
MSG_WriteUBitLong( sb, (uint)data, numbits - 1 );
MSG_WriteOneBit( sb, 0 );
if( data < 0 )
{
MSG_WriteUBitLong( sb, (uint)( 0x80000000 + data ), numbits - 1 );
MSG_WriteOneBit( sb, 1 );
}
else
{
MSG_WriteUBitLong( sb, (uint)data, numbits - 1 );
MSG_WriteOneBit( sb, 0 );
}
}
}
@@ -317,28 +321,30 @@ void MSG_WriteVec3Angles( sizebuf_t *sb, const float *fa )
void MSG_WriteCmdExt( sizebuf_t *sb, int cmd, netsrc_t type, const char *name )
{
#ifdef DEBUG_NET_MESSAGES_SEND
if( name != NULL )
if( unlikely( net_send_debug.value ))
{
// get custom name
Con_Printf( "^1sv^7 write: %s\n", name );
}
else if( type == NS_SERVER )
{
if( cmd >= 0 && cmd <= svc_lastmsg )
if( name != NULL )
{
// get engine message name
Con_Printf( "^1sv^7 write: %s\n", svc_strings[cmd] );
// get custom name
Con_Printf( "^1sv^7 (%d) write: %s\n", sb->iCurBit, name );
}
else if( type == NS_SERVER )
{
if( cmd >= 0 && cmd <= svc_lastmsg )
{
// get engine message name
Con_Printf( "^1sv^7 (%d) write: %s\n", sb->iCurBit, svc_strings[cmd] );
}
}
else if( type == NS_CLIENT )
{
if( cmd >= 0 && cmd <= clc_lastmsg && cmd != clc_nop )
{
Con_Printf( "^1cl^7 (%d) write: %s\n", sb->iCurBit, clc_strings[cmd] );
}
}
}
else if( type == NS_CLIENT )
{
if( cmd >= 0 && cmd <= clc_lastmsg )
{
Con_Printf( "^1cl^7 write: %s\n", clc_strings[cmd] );
}
}
#endif
MSG_WriteUBitLong( sb, cmd, sizeof( uint8_t ) << 3 );
}
@@ -533,12 +539,22 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
{
int r, sign;
r = MSG_ReadUBitLong( sb, numbits - 1 );
if( sb->iAlternateSign )
{
sign = MSG_ReadOneBit( sb );
r = MSG_ReadUBitLong( sb, numbits - 1 );
// NOTE: it does this wierdness here so it's bit-compatible with regular integer data in the buffer.
// (Some old code writes direct integers right into the buffer).
sign = MSG_ReadOneBit( sb );
if( sign ) r = -( BIT( numbits - 1 ) - r );
if( sign )
r = -r;
}
else
{
r = MSG_ReadUBitLong( sb, numbits - 1 );
sign = MSG_ReadOneBit( sb );
if( sign )
r = -( BIT( numbits - 1 ) - r );
}
return r;
}
@@ -554,22 +570,31 @@ int MSG_ReadCmd( sizebuf_t *sb, netsrc_t type )
{
int cmd = MSG_ReadUBitLong( sb, sizeof( uint8_t ) << 3 );
#ifdef DEBUG_NET_MESSAGES_READ
if( type == NS_SERVER )
if( unlikely( net_recv_debug.value ))
{
Con_Printf( "^1cl^7 read: %s\n", CL_MsgInfo( cmd ));
if( type == NS_SERVER )
{
if( cmd != svc_nop )
Con_Printf( "^1cl^7 read: %s\n", CL_MsgInfo( cmd ));
}
else if( cmd >= 0 && cmd <= clc_lastmsg )
{
Con_Printf( "^1sv^7 read: %s\n", clc_strings[cmd] );
}
}
else if( cmd >= 0 && cmd <= clc_lastmsg )
{
Con_Printf( "^1sv^7 read: %s\n", clc_strings[cmd] );
}
#endif
return cmd;
}
int MSG_ReadChar( sizebuf_t *sb )
{
return MSG_ReadSBitLong( sb, sizeof( int8_t ) << 3 );
int alt = sb->iAlternateSign, ret;
sb->iAlternateSign = 0;
ret = MSG_ReadSBitLong( sb, sizeof( int8_t ) << 3 );
sb->iAlternateSign = alt;
return ret;
}
int MSG_ReadByte( sizebuf_t *sb )
@@ -579,7 +604,13 @@ int MSG_ReadByte( sizebuf_t *sb )
int MSG_ReadShort( sizebuf_t *sb )
{
return MSG_ReadSBitLong( sb, sizeof( int16_t ) << 3 );
int alt = sb->iAlternateSign, ret;
sb->iAlternateSign = 0;
ret = MSG_ReadSBitLong( sb, sizeof( int16_t ) << 3 );
sb->iAlternateSign = alt;
return ret;
}
int MSG_ReadWord( sizebuf_t *sb )
@@ -611,7 +642,13 @@ void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa )
int MSG_ReadLong( sizebuf_t *sb )
{
return MSG_ReadSBitLong( sb, sizeof( int32_t ) << 3 );
int alt = sb->iAlternateSign, ret;
sb->iAlternateSign = 0;
ret = MSG_ReadSBitLong( sb, sizeof( int32_t ) << 3 );
sb->iAlternateSign = alt;
return ret;
}
uint MSG_ReadDword( sizebuf_t *sb )

View File

@@ -42,6 +42,9 @@ struct sizebuf_s
int iCurBit;
int nDataBits;
const char *pDebugName; // buffer name (pointer to const name)
// to support GoldSrc broken signed integers
int iAlternateSign;
};
#define MSG_StartReading MSG_StartWriting
@@ -71,6 +74,7 @@ static inline void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pDa
sb->nDataBits = nBits;
sb->pDebugName = pDebugName;
sb->iAlternateSign = 0;
}
static inline void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits )
@@ -169,6 +173,26 @@ static inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
return sb->bOverflow;
}
static inline void MSG_EndBitWriting( sizebuf_t *sb )
{
sb->iAlternateSign--;
if( sb->iAlternateSign < 0 )
{
Con_Printf( "%s: non-even MSG_Start/EndBitWriting\n", __func__ );
sb->iAlternateSign = 0;
}
// we have native bit ops here, just pad to closest byte
if(( sb->iCurBit & 7 ) != 0 )
MSG_SeekToBit( sb, 8 - ( sb->iCurBit & 7 ), SEEK_CUR );
}
static inline void MSG_StartBitWriting( sizebuf_t *sb )
{
sb->iAlternateSign++;
}
void MSG_InitMasks( void ); // called once at startup engine
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );

View File

@@ -18,6 +18,9 @@ GNU General Public License for more details.
#include "xash3d_mathlib.h"
#include "net_encode.h"
#include "protocol.h"
#if !XASH_DEDICATED
#include <bzlib.h>
#endif // !XASH_DEDICATED
#define MAKE_FRAGID( id, count ) ((( id & 0xffff ) << 16 ) | ( count & 0xffff ))
#define FRAG_GETID( fragid ) (( fragid >> 16 ) & 0xffff )
@@ -84,10 +87,12 @@ such as during the connection stage while waiting for the client to load,
then a packet only needs to be delivered if there is something in the
unacknowledged reliable
*/
CVAR_DEFINE_AUTO( net_showpackets, "0", 0, "show network packets" );
CVAR_DEFINE_AUTO( net_showpackets, "0", FCVAR_PRIVILEGED, "show network packets" );
static CVAR_DEFINE_AUTO( net_chokeloop, "0", 0, "apply bandwidth choke to loopback packets" );
static CVAR_DEFINE_AUTO( net_showdrop, "0", 0, "show packets that are dropped" );
static CVAR_DEFINE_AUTO( net_qport, "0", FCVAR_READ_ONLY, "current quake netport" );
CVAR_DEFINE_AUTO( net_send_debug, "0", FCVAR_PRIVILEGED, "enable debugging output for outgoing messages" );
CVAR_DEFINE_AUTO( net_recv_debug, "0", FCVAR_PRIVILEGED, "enable debugging output for incoming messages" );
int net_drop;
netadr_t net_from;
@@ -95,12 +100,58 @@ sizebuf_t net_message;
static poolhandle_t net_mempool;
byte net_message_buffer[NET_MAX_MESSAGE];
const char *ns_strings[NS_COUNT] =
static const char *const ns_strings[NS_COUNT] =
{
"Client",
"Server",
};
#if !XASH_DEDICATED
void bz_internal_error( int errcode );
void bz_internal_error( int errcode )
{
Con_Printf( S_ERROR "bzip2/libbzip2: internal error number %d.\n"
"This is a bug in bzip2/libbzip2, %s.\n"
"Please report it at: https://gitlab.com/bzip2/bzip2/-/issues\n"
"If this happened when you were using some program which uses\n"
"libbzip2 as a component, you should also report this bug to\n"
"the author(s) of that program.\n"
"Please make an effort to report this bug;\n"
"timely and accurate bug reports eventually lead to higher\n"
"quality software. Thanks.\n\n",
errcode, BZ2_bzlibVersion( ));
if (errcode == 1007) {
Con_Printf(
"\n*** A special note about internal error number 1007 ***\n"
"\n"
"Experience suggests that a common cause of i.e. 1007\n"
"is unreliable memory or other hardware. The 1007 assertion\n"
"just happens to cross-check the results of huge numbers of\n"
"memory reads/writes, and so acts (unintendedly) as a stress\n"
"test of your memory system.\n"
"\n"
"I suggest the following: try compressing the file again,\n"
"possibly monitoring progress in detail with the -vv flag.\n"
"\n"
"* If the error cannot be reproduced, and/or happens at different\n"
" points in compression, you may have a flaky memory system.\n"
" Try a memory-test program. I have used Memtest86\n"
" (www.memtest86.com). At the time of writing it is free (GPLd).\n"
" Memtest86 tests memory much more thorougly than your BIOSs\n"
" power-on test, and may find failures that the BIOS doesn't.\n"
"\n"
"* If the error can be repeatably reproduced, this is a bug in\n"
" bzip2, and I would very much like to hear about it. Please\n"
" let me know, and, ideally, save a copy of the file causing the\n"
" problem -- without which I will be unable to investigate it.\n"
"\n"
);
}
Sys_Error( "bzip2/libbzip2: internal error number %d\n", errcode );
}
#endif // XASH_DEDICATED
/*
=================================
@@ -216,6 +267,8 @@ void Netchan_Init( void )
Cvar_RegisterVariable( &net_chokeloop );
Cvar_RegisterVariable( &net_showdrop );
Cvar_RegisterVariable( &net_qport );
Cvar_RegisterVariable( &net_send_debug );
Cvar_RegisterVariable( &net_recv_debug );
Cvar_FullSet( net_qport.name, buf, net_qport.flags );
net_mempool = Mem_AllocPool( "Network Pool" );
@@ -265,12 +318,18 @@ Netchan_Setup
called to open a channel to a remote system
==============
*/
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ))
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ), uint flags )
{
Netchan_Clear( chan );
memset( chan, 0, sizeof( *chan ));
if( pfnBlockSize == NULL )
{
Host_Error( "%s: pfnBlockSize == NULL", __func__ );
return;
}
chan->sock = sock;
chan->remote_address = adr;
chan->last_received = host.realtime;
@@ -281,6 +340,10 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
chan->qport = qport;
chan->client = client;
chan->pfnBlockSize = pfnBlockSize;
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false;
chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false;
chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false;
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
}
@@ -457,7 +520,7 @@ Netchan_OutOfBand
Sends an out-of-band datagram
================
*/
void Netchan_OutOfBand( int net_socket, netadr_t adr, int len, byte *data )
void Netchan_OutOfBand( int net_socket, netadr_t adr, int len, const byte *data )
{
byte buf[MAX_PRINT_MSG + 4] = { 0xff, 0xff, 0xff, 0xff };
@@ -681,21 +744,39 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
if( MSG_GetNumBytesWritten( msg ) == 0 )
return;
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
wait = (fragbufwaiting_t *)Mem_Calloc( net_mempool, sizeof( fragbufwaiting_t ));
if( !LZSS_IsCompressed( MSG_GetData( msg )))
if( chan->use_bz2 && memcmp( MSG_GetData( msg ), "BZ2", 4 ))
{
uint uCompressedSize = 0;
uint uSourceSize = MSG_GetNumBytesWritten( msg );
byte *pbOut = LZSS_Compress( msg->pData, uSourceSize, &uCompressedSize );
#if !XASH_DEDICATED
byte pbOut[0x10000];
uint uSourceSize = MSG_GetNumBytesWritten( msg );
uint uCompressedSize = MSG_GetNumBytesWritten( msg ) - 4;
if( !BZ2_bzBuffToBuffCompress( pbOut, &uCompressedSize, MSG_GetData( msg ), uSourceSize, 9, 0, 30 ))
{
if( uCompressedSize < uSourceSize )
{
Con_Reportf( "Compressing split packet with BZip2 (%d -> %d bytes)\n", uSourceSize, uCompressedSize );
memcpy( msg->pData, "BZ2", 4 );
memcpy( msg->pData + 4, pbOut, uCompressedSize );
MSG_SeekToBit( msg, uCompressedSize << 3, SEEK_SET );
}
}
#else
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif
}
else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg )))
{
uint uCompressedSize = 0;
uint uSourceSize = MSG_GetNumBytesWritten( msg );
byte *pbOut = LZSS_Compress( msg->pData, uSourceSize, &uCompressedSize );
if( pbOut && uCompressedSize > 0 && uCompressedSize < uSourceSize )
{
Con_Reportf( "Compressing split packet (%d -> %d bytes)\n", uSourceSize, uCompressedSize );
Con_Reportf( "Compressing split packet with LZSS (%d -> %d bytes)\n", uSourceSize, uCompressedSize );
memcpy( msg->pData, pbOut, uCompressedSize );
MSG_SeekToBit( msg, uCompressedSize << 3, SEEK_SET );
}
@@ -842,9 +923,7 @@ void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, const char *filenam
if( !size ) return;
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
if( !LZSS_IsCompressed( pbuf ))
{
@@ -940,16 +1019,14 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename )
Con_Printf( S_WARN "Unable to transfer %s due to path length overflow\n", filename );
return 0;
}
if(( filesize = FS_FileSize( filename, false )) <= 0 )
{
Con_Printf( S_WARN "Unable to open %s for transfer\n", filename );
return 0;
}
if( chan->pfnBlockSize != NULL )
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
else chunksize = FRAGMENT_MAX_SIZE; // fallback
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
Q_snprintf( compressedfilename, sizeof( compressedfilename ), "%s.ztmp", filename );
compressedFileTime = FS_FileTime( compressedfilename, false );
@@ -1098,7 +1175,20 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
p = n;
}
if( LZSS_IsCompressed( MSG_GetData( msg )))
if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ) )
{
#if !XASH_DEDICATED
byte buf[0x10000];
uint uDecompressedLen = sizeof( buf );
BZ2_bzBuffToBuffDecompress( buf, &uDecompressedLen, MSG_GetData( msg ) + 4, MSG_GetNumBytesWritten( msg ) - 4, 1, 0 );
memcpy( msg->pData, buf, uDecompressedLen );
size = uDecompressedLen;
#else
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif
}
else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg )))
{
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ));
byte buf[NET_MAX_MESSAGE];
@@ -1135,7 +1225,8 @@ Netchan_CopyFileFragments
*/
qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
{
char filename[MAX_OSPATH];
char filename[MAX_OSPATH], compressor[32];
uint uncompressedSize;
int nsize, pos;
byte *buffer;
fragbuf_t *p, *n;
@@ -1158,6 +1249,12 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
MSG_Clear( msg );
Q_strncpy( filename, MSG_ReadString( msg ), sizeof( filename ));
compressor[0] = 0;
if( chan->gs_netchan )
{
Q_strncpy( compressor, MSG_ReadString( msg ), sizeof( compressor ));
uncompressedSize = MSG_ReadLong( msg );
}
if( !COM_CheckString( filename ))
{
@@ -1228,10 +1325,26 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
p = n;
}
if( LZSS_IsCompressed( buffer ))
if( chan->gs_netchan && chan->use_bz2 && !Q_stricmp( compressor, "bz2" ))
{
uint uncompressedSize = LZSS_GetActualSize( buffer ) + 1;
byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize );
#if !XASH_DEDICATED
byte *uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize );
Con_DPrintf( "Decompressing file %s (%d -> %d bytes)\n", filename, nsize, uncompressedSize );
BZ2_bzBuffToBuffDecompress( uncompressedBuffer, &uncompressedSize, buffer, nsize, 1, 0 );
Mem_Free( buffer );
nsize = uncompressedSize;
buffer = uncompressedBuffer;
#else
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif
}
else if( LZSS_IsCompressed( buffer ))
{
byte *uncompressedBuffer;
uncompressedSize = LZSS_GetActualSize( buffer ) + 1;
uncompressedBuffer = Mem_Calloc( net_mempool, uncompressedSize );
nsize = LZSS_Decompress( buffer, uncompressedBuffer );
Mem_Free( buffer );
@@ -1391,7 +1504,7 @@ transmition / retransmition of the reliable messages.
A 0 length will still generate a packet and deal with the reliable messages.
================
*/
void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
void Netchan_TransmitBits( netchan_t *chan, int length, const byte *data )
{
byte send_buf[NET_MAX_MESSAGE];
qboolean send_reliable_fragment;
@@ -1408,6 +1521,9 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
return;
}
if( chan->pfnBlockSize == NULL ) // not initialized
return;
// if the remote side dropped the last reliable message, resend it
send_reliable = false;
@@ -1446,12 +1562,9 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// stall reliable payloads if sending from frag buffer
if( send_from_regular && ( send_from_frag[FRAG_NORMAL_STREAM] ))
{
int maxsize = MAX_RELIABLE_PAYLOAD;
int maxsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
send_from_regular = false;
if( chan->pfnBlockSize )
maxsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
if( maxsize == 0 )
maxsize = MAX_RELIABLE_PAYLOAD;
@@ -1593,7 +1706,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
MSG_WriteLong( &send, w2 );
// send the qport if we are a client
if( chan->sock == NS_CLIENT )
if( chan->sock == NS_CLIENT && !chan->gs_netchan )
{
MSG_WriteWord( &send, (int)net_qport.value );
}
@@ -1606,8 +1719,16 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
{
MSG_WriteByte( &send, 1 );
MSG_WriteLong( &send, chan->reliable_fragid[i] );
MSG_WriteLong( &send, chan->frag_startpos[i] );
MSG_WriteLong( &send, chan->frag_length[i] );
if( chan->gs_netchan )
{
MSG_WriteShort( &send, chan->frag_startpos[i] >> 3 );
MSG_WriteShort( &send, chan->frag_length[i] >> 3 );
}
else
{
MSG_WriteLong( &send, chan->frag_startpos[i] );
MSG_WriteLong( &send, chan->frag_length[i] );
}
}
else
{
@@ -1625,9 +1746,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
if( length )
{
int maxsize = NET_MAX_MESSAGE;
if( chan->pfnBlockSize )
maxsize = chan->pfnBlockSize( chan->client, FRAGSIZE_UNRELIABLE );
int maxsize = chan->pfnBlockSize( chan->client, FRAGSIZE_UNRELIABLE );
if( (( MSG_GetNumBytesWritten( &send ) + length ) >> 3) <= maxsize )
MSG_WriteBits( &send, data, length );
@@ -1661,9 +1780,11 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// send the datagram
if( !CL_IsPlaybackDemo( ))
{
int splitsize = 0;
if( chan->pfnBlockSize )
splitsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
int splitsize = chan->pfnBlockSize( chan->client, FRAGSIZE_SPLIT );
if( chan->use_munge )
COM_Munge2( send.pData + 8, MSG_GetNumBytesWritten( &send ) - 8, (byte)( chan->outgoing_sequence - 1 ));
NET_SendPacketEx( chan->sock, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), chan->remote_address, splitsize );
}
@@ -1712,6 +1833,9 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
sequence = MSG_ReadLong( msg );
sequence_ack = MSG_ReadLong( msg );
if( chan->use_munge )
COM_UnMunge2( msg->pData + 8, ( msg->nDataBits >> 3 ) - 8, sequence & 0xFF );
// read the qport if we are a server
if( chan->sock == NS_SERVER )
qport = MSG_ReadShort( msg );
@@ -1729,8 +1853,16 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg )
{
frag_message[i] = true;
fragid[i] = MSG_ReadLong( msg );
frag_offset[i] = MSG_ReadLong( msg );
frag_length[i] = MSG_ReadLong( msg );
if( chan->gs_netchan )
{
frag_offset[i] = MSG_ReadShort( msg ) << 3;
frag_length[i] = MSG_ReadShort( msg ) << 3;
}
else
{
frag_offset[i] = MSG_ReadLong( msg );
frag_length[i] = MSG_ReadLong( msg );
}
}
}

View File

@@ -37,6 +37,7 @@ GNU General Public License for more details.
#define DT_TIMEWINDOW_BIG BIT( 6 ) // and re-encoded on the client relative to the client's clock
#define DT_STRING BIT( 7 ) // A null terminated string, sent as 8 byte chars
#define DT_SIGNED BIT( 8 ) // sign modificator
#define DT_SIGNED_GS BIT( 31 ) // GoldSrc-specific sign modificator
#define NUM_FIELDS( x ) ((sizeof( x ) / sizeof( x[0] )) - 1)
@@ -47,6 +48,7 @@ GNU General Public License for more details.
#define PHYS_DEF( x ) #x, offsetof( movevars_t, x ), sizeof( ((movevars_t *)0)->x )
#define CLDT_DEF( x ) #x, offsetof( clientdata_t, x ), sizeof( ((clientdata_t *)0)->x )
#define WPDT_DEF( x ) #x, offsetof( weapon_data_t, x ), sizeof( ((weapon_data_t *)0)->x )
#define DESC_DEF( x ) #x, offsetof( goldsrc_delta_t, x ), sizeof( ((goldsrc_delta_t *)0)->x )
static qboolean delta_init = false;
@@ -315,6 +317,18 @@ static const delta_field_t ent_fields[] =
{ NULL },
};
static const delta_field_t meta_fields[] =
{
{ DESC_DEF( fieldType ), },
{ DESC_DEF( fieldName ), },
{ DESC_DEF( fieldOffset ), },
{ DESC_DEF( fieldSize ), },
{ DESC_DEF( significant_bits ), },
{ DESC_DEF( premultiply ), },
{ DESC_DEF( postmultiply ), },
{ NULL },
};
#if XASH_ENGINE_TESTS
typedef struct delta_test_struct_t
{
@@ -352,22 +366,6 @@ static const delta_field_t test_fields[] =
};
#endif
enum
{
DT_EVENT_T = 0,
DT_MOVEVARS_T,
DT_USERCMD_T,
DT_CLIENTDATA_T,
DT_WEAPONDATA_T,
DT_ENTITY_STATE_T,
DT_ENTITY_STATE_PLAYER_T,
DT_CUSTOM_ENTITY_STATE_T,
#if XASH_ENGINE_TESTS
DT_DELTA_TEST_STRUCT_T,
#endif
DT_STRUCT_COUNT
};
static delta_info_t dt_info[] =
{
[DT_EVENT_T] = { "event_t", ev_fields, NUM_FIELDS( ev_fields ) },
@@ -375,7 +373,7 @@ static delta_info_t dt_info[] =
[DT_USERCMD_T] = { "usercmd_t", cmd_fields, NUM_FIELDS( cmd_fields ) },
[DT_CLIENTDATA_T] = { "clientdata_t", cd_fields, NUM_FIELDS( cd_fields ) },
[DT_WEAPONDATA_T] = { "weapon_data_t", wd_fields, NUM_FIELDS( wd_fields ) },
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
#if XASH_ENGINE_TESTS
@@ -384,6 +382,68 @@ static delta_info_t dt_info[] =
[DT_STRUCT_COUNT] = { NULL },
};
// meta description is special, it cannot be overriden
static const delta_info_t dt_goldsrc_meta =
{
.pName = "goldsrc_delta_t",
.pInfo = meta_fields,
.maxFields = NUM_FIELDS( meta_fields ),
.numFields = NUM_FIELDS( meta_fields ),
.pFields = (delta_t[NUM_FIELDS( meta_fields )])
{
{
DESC_DEF( fieldType ),
.flags = DT_INTEGER,
.multiplier = 1.0f,
.post_multiplier = 1.0f,
.bits = 32,
},
{
DESC_DEF( fieldName ),
.flags = DT_STRING,
.multiplier = 1.0f,
.post_multiplier = 1.0f,
.bits = 1,
},
{
DESC_DEF( fieldOffset ),
.flags = DT_INTEGER,
.multiplier = 1.0f,
.post_multiplier = 1.0f,
.bits = 16,
},
{
DESC_DEF( fieldSize ),
.flags = DT_INTEGER,
.multiplier = 1.0f,
.post_multiplier = 1.0f,
.bits = 8,
},
{
DESC_DEF( significant_bits ),
.flags = DT_INTEGER,
.multiplier = 1.0f,
.post_multiplier = 1.0f,
.bits = 8,
},
{
DESC_DEF( premultiply ),
.flags = DT_FLOAT,
.multiplier = 4000.0f,
.post_multiplier = 1.0f,
.bits = 32,
},
{
DESC_DEF( postmultiply ),
.flags = DT_FLOAT,
.multiplier = 4000.0f,
.post_multiplier = 1.0f,
.bits = 32,
},
},
.bInitialized = true
};
static delta_info_t *Delta_FindStruct( const char *name )
{
int i;
@@ -493,7 +553,7 @@ static qboolean Delta_AddField( delta_info_t *dt, const char *pName, int flags,
int i;
// check for coexisting field
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
for( i = 0, pField = dt->pFields; i < dt->numFields && pField; i++, pField++ )
{
if( !Q_strcmp( pField->name, pName ))
{
@@ -1166,7 +1226,7 @@ write fields by offsets
assume from and to is valid
=====================
*/
static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, const void *from, const void *to, double timebase )
static void Delta_WriteField_( sizebuf_t *msg, delta_t *pField, const void *from, const void *to, double timebase )
{
int signbit = FBitSet( pField->flags, DT_SIGNED ) ? 1 : 0;
float flValue, flAngle;
@@ -1174,14 +1234,6 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, const void *f
int dt;
const char *pStr;
if( Delta_CompareField( pField, from, to ))
{
MSG_WriteOneBit( msg, 0 ); // unchanged
return false;
}
MSG_WriteOneBit( msg, 1 ); // changed
if( pField->flags & DT_BYTE )
{
if( signbit )
@@ -1255,6 +1307,20 @@ static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, const void *f
pStr = (char *)((byte *)to + pField->offset );
MSG_WriteString( msg, pStr );
}
}
static qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, const void *from, const void *to, double timebase )
{
if( Delta_CompareField( pField, from, to ))
{
MSG_WriteOneBit( msg, 0 ); // unchanged
return false;
}
MSG_WriteOneBit( msg, 1 ); // changed
Delta_WriteField_( msg, pField, from, to, timebase );
return true;
}
@@ -1313,7 +1379,7 @@ read fields by offsets
assume 'from' and 'to' is valid
=====================
*/
static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, const void *from, void *to, double timebase )
static void Delta_ReadField_( sizebuf_t *msg, delta_t *pField, void *to, double timebase )
{
qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false;
float flValue, flAngle, flTime;
@@ -1321,12 +1387,6 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, const void *fr
const char *pStr;
char *pOut;
if( !MSG_ReadOneBit( msg ) )
{
Delta_CopyField( pField, from, to, timebase );
return false;
}
Assert( pField->multiplier != 0.0f );
if( pField->flags & DT_BYTE )
@@ -1410,9 +1470,85 @@ static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, const void *fr
pOut = (char *)((byte *)to + pField->offset );
Q_strncpy( pOut, pStr, pField->size );
}
}
static qboolean Delta_ReadField( sizebuf_t *msg, delta_t *pField, const void *from, void *to, double timebase )
{
if( !MSG_ReadOneBit( msg ))
{
Delta_CopyField( pField, from, to, timebase );
return false;
}
Delta_ReadField_( msg, pField, to, timebase );
return true;
}
static void Delta_ParseGSFields( sizebuf_t *msg, const delta_info_t *dt, const void *from, void *to, double timebase )
{
uint8_t bits[8] = { 0 };
delta_t *pField;
byte c;
int i;
c = MSG_ReadUBitLong( msg, 3 );
for( i = 0; i < c; i++ )
bits[i] = MSG_ReadByte( msg );
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
{
int b = i >> 3;
int n = 1 << ( i & 7 );
if( FBitSet( bits[b], n ))
Delta_ReadField_( msg, pField, to, timebase );
else Delta_CopyField( pField, from, to, timebase );
}
}
void Delta_ReadGSFields( sizebuf_t *msg, int index, const void *from, void *to, double timebase )
{
const delta_info_t *dt = Delta_FindStructByIndex( index );
Delta_ParseGSFields( msg, dt, from, to, timebase );
}
void Delta_WriteGSFields( sizebuf_t *msg, int index, const void *from, const void *to, double timebase )
{
delta_info_t *dt = Delta_FindStructByIndex( index );
delta_t *pField;
uint8_t bits[8] = { 0 };
uint c = 0;
int i;
Delta_CustomEncode( dt, from, to );
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
{
if( !Delta_CompareField( pField, from, to ))
{
int b = i >> 3;
int n = 1 << ( i & 7 );
SetBits( bits[b], n );
c = b + 1;
}
}
MSG_WriteUBitLong( msg, c, 3 );
for( i = 0; i < c; i++ )
MSG_WriteByte( msg, bits[i] );
for( i = 0, pField = dt->pFields; i < dt->numFields; i++, pField++ )
{
int b = i >> 3;
int n = 1 << ( i & 7 );
if( FBitSet( bits[b], n ))
Delta_WriteField_( msg, pField, from, to, timebase );
}
}
/*
=============================================================================
@@ -1882,7 +2018,10 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const entity_state_t *from, entity
int baseline_offset = 0;
if( number < 0 || number >= clgame.maxEntities )
Host_Error( "%s: bad delta entity number: %i\n", __func__, number );
{
Con_Printf( S_ERROR "%s: bad delta entity number: %i\n", __func__, number );
return false;
}
fRemoveType = MSG_ReadUBitLong( msg, 2 );
@@ -1904,7 +2043,8 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const entity_state_t *from, entity
return false;
}
Host_Error( "%s: unknown update type %i\n", __func__, fRemoveType );
Con_Printf( S_ERROR "%s: unknown update type %i\n", __func__, fRemoveType );
return false;
}
if( !cls.legacymode )
@@ -1952,7 +2092,11 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const entity_state_t *from, entity
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
}
Assert( dt && dt->bInitialized );
if( !dt || !dt->bInitialized )
{
Con_Printf( S_ERROR "%s: broken delta\n", __func__ );
return true;
}
pField = dt->pFields;
Assert( pField != NULL );
@@ -1967,6 +2111,44 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const entity_state_t *from, entity
return true;
}
void Delta_ParseTableField_GS( sizebuf_t *msg )
{
const char *s = MSG_ReadString( msg );
delta_info_t *dt = Delta_FindStruct( s );
goldsrc_delta_t null = { 0 };
int i, num_fields;
// delta encoders it's already initialized on this machine (local game)
if( delta_init )
Delta_Shutdown();
if( !dt )
Host_Error( "%s: not initialized", __func__ );
num_fields = MSG_ReadShort( msg );
if( num_fields > dt->maxFields )
Host_Error( "%s: numFields > maxFields", __func__ );
MSG_StartBitWriting( msg );
for( i = 0; i < num_fields; i++ )
{
goldsrc_delta_t to;
Delta_ParseGSFields( msg, &dt_goldsrc_meta, &null, &to, 0.0f );
// patch our DT_SIGNED flag
if( FBitSet( to.fieldType, DT_SIGNED_GS ))
{
ClearBits( to.fieldType, DT_SIGNED_GS );
SetBits( to.fieldType, DT_SIGNED );
}
Delta_AddField( dt, to.fieldName, to.fieldType, to.significant_bits, to.premultiply, to.postmultiply );
}
MSG_EndBitWriting( msg );
}
/*
==================
Delta_WriteDescriptionToClient

View File

@@ -33,6 +33,22 @@ enum
DELTA_STATIC,
};
enum
{
DT_EVENT_T = 0,
DT_MOVEVARS_T,
DT_USERCMD_T,
DT_CLIENTDATA_T,
DT_WEAPONDATA_T,
DT_ENTITY_STATE_T,
DT_ENTITY_STATE_PLAYER_T,
DT_CUSTOM_ENTITY_STATE_T,
#if XASH_ENGINE_TESTS
DT_DELTA_TEST_STRUCT_T,
#endif
DT_STRUCT_COUNT
};
// struct info (filled by engine)
typedef struct
{
@@ -54,6 +70,17 @@ struct delta_s
qboolean bInactive; // unsetted by user request
};
typedef struct goldsrc_delta_s
{
int fieldType;
char fieldName[32];
int fieldOffset;
short fieldSize;
int significant_bits;
float premultiply;
float postmultiply;
} goldsrc_delta_t;
typedef void (*pfnDeltaEncode)( struct delta_s *pFields, const byte *from, const byte *to );
typedef struct
@@ -87,6 +114,7 @@ void Delta_UnsetFieldByIndex( delta_t *pFields, int fieldNumber );
// send table over network
void Delta_WriteDescriptionToClient( sizebuf_t *msg );
void Delta_ParseTableField( sizebuf_t *msg );
void Delta_ParseTableField_GS( sizebuf_t *msg );
// encode routines
@@ -109,5 +137,7 @@ void MSG_ReadWeaponData( sizebuf_t *msg, const struct weapon_data_s *from, struc
void MSG_WriteDeltaEntity( const struct entity_state_s *from, const struct entity_state_s *to, sizebuf_t *msg, qboolean force, int type, double timebase, int ofs );
qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, const struct entity_state_s *from, struct entity_state_s *to, int num, int type, double timebase );
int Delta_TestBaseline( const struct entity_state_s *from, const struct entity_state_s *to, qboolean player, double timebase );
void Delta_ReadGSFields( sizebuf_t *msg, int index, const void *from, void *to, double timebase );
void Delta_WriteGSFields( sizebuf_t *msg, int index, const void *from, const void *to, double timebase );
#endif//NET_ENCODE_H

1188
engine/common/net_http.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -50,8 +50,10 @@ typedef enum
#include "netadr.h"
extern convar_t net_showpackets;
extern convar_t net_clockwindow;
extern convar_t net_showpackets;
extern convar_t net_clockwindow;
extern convar_t net_send_debug;
extern convar_t net_recv_debug;
void NET_Init( void );
void NET_Shutdown( void );
@@ -59,7 +61,6 @@ void NET_Sleep( int msec );
qboolean NET_IsActive( void );
qboolean NET_IsConfigured( void );
void NET_Config( qboolean net_enable, qboolean changeport );
qboolean NET_IsLocalAddress( netadr_t adr );
const char *NET_AdrToString( const netadr_t a );
const char *NET_BaseAdrToString( const netadr_t a );
qboolean NET_IsReservedAdr( netadr_t a );
@@ -77,13 +78,17 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 );
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
static inline qboolean NET_IsLocalAddress( netadr_t adr )
{
return adr.type == NA_LOOPBACK ? true : false;
}
#if !XASH_DEDICATED
qboolean CL_LegacyMode( void );
int CL_GetSplitSize( void );
#endif
void HTTP_AddCustomServer( const char *url );
void HTTP_AddDownload( const char *path, int size, qboolean process );
void HTTP_AddDownload( const char *path, int size, qboolean process, resource_t *res );
void HTTP_ClearCustomServers( void );
void HTTP_Shutdown( void );
void HTTP_ResetProcessState( void );

View File

@@ -0,0 +1,103 @@
/*
net_ws_private.h - networking private definitions
Copyright (C) 2024 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 "net_ws.h"
#if XASH_NO_NETWORK
#include "platform/stub/net_stub.h"
#elif XASH_WIN32
#include "platform/win32/net.h"
#elif XASH_PSVITA
#include "platform/psvita/net_psvita.h"
static const struct in6_addr in6addr_any;
#else
#include "platform/posix/net.h"
#endif
//
// net_ws.c
//
static inline const char *NET_ErrorString( void )
{
#if XASH_WIN32
int err = WSAGetLastError();
switch( err )
{
case WSAEINTR: return "WSAEINTR";
case WSAEBADF: return "WSAEBADF";
case WSAEACCES: return "WSAEACCES";
case WSAEFAULT: return "WSAEFAULT";
case WSAEINVAL: return "WSAEINVAL";
case WSAEMFILE: return "WSAEMFILE";
case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
case WSAEINPROGRESS: return "WSAEINPROGRESS";
case WSAEALREADY: return "WSAEALREADY";
case WSAENOTSOCK: return "WSAENOTSOCK";
case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
case WSAEMSGSIZE: return "WSAEMSGSIZE";
case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
case WSAEADDRINUSE: return "WSAEADDRINUSE";
case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
case WSAENETDOWN: return "WSAENETDOWN";
case WSAENETUNREACH: return "WSAENETUNREACH";
case WSAENETRESET: return "WSAENETRESET";
case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
case WSAECONNRESET: return "WSAECONNRESET";
case WSAENOBUFS: return "WSAENOBUFS";
case WSAEISCONN: return "WSAEISCONN";
case WSAENOTCONN: return "WSAENOTCONN";
case WSAESHUTDOWN: return "WSAESHUTDOWN";
case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
case WSAETIMEDOUT: return "WSAETIMEDOUT";
case WSAECONNREFUSED: return "WSAECONNREFUSED";
case WSAELOOP: return "WSAELOOP";
case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
case WSAEDISCON: return "WSAEDISCON";
case WSASYSNOTREADY: return "WSASYSNOTREADY";
case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
case WSANOTINITIALISED: return "WSANOTINITIALISED";
case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
case WSATRY_AGAIN: return "WSATRY_AGAIN";
case WSANO_RECOVERY: return "WSANO_RECOVERY";
case WSANO_DATA: return "WSANO_DATA";
}
return "NO ERROR";
#else
return strerror( errno );
#endif
}
static inline socklen_t NET_SockAddrLen( const struct sockaddr_storage *addr )
{
switch ( addr->ss_family )
{
case AF_INET:
return sizeof( struct sockaddr_in );
case AF_INET6:
return sizeof( struct sockaddr_in6 );
default:
return sizeof( *addr ); // what the fuck is this?
}
}
net_gai_state_t NET_StringToSockaddr( const char *s, struct sockaddr_storage *sadr, qboolean nonblocking, int family );

View File

@@ -208,6 +208,14 @@ typedef enum fragsize_e
FRAGSIZE_UNRELIABLE
} fragsize_t;
typedef enum netchan_flags_e
{
NETCHAN_USE_LEGACY_SPLIT = BIT( 0 ),
NETCHAN_USE_MUNGE = BIT( 1 ),
NETCHAN_USE_BZIP2 = BIT( 2 ),
NETCHAN_GOLDSRC = BIT( 3 ),
} netchan_flags_t;
// Network Connection Channel
typedef struct netchan_s
{
@@ -270,10 +278,14 @@ typedef struct netchan_s
// added for net_speeds
size_t total_sended;
size_t total_received;
qboolean split;
unsigned int maxpacket;
unsigned int splitid;
netsplit_t netsplit;
netsplit_t netsplit;
qboolean split;
qboolean use_munge;
qboolean use_bz2;
qboolean gs_netchan;
} netchan_t;
extern netadr_t net_from;
@@ -287,14 +299,14 @@ extern int net_drop;
void Netchan_Init( void );
void Netchan_Shutdown( void );
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ) );
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, void *client, int (*pfnBlockSize)(void *, fragsize_t mode ), uint flags );
void Netchan_CreateFileFragmentsFromBuffer( netchan_t *chan, const char *filename, byte *pbuf, int size );
qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *length );
qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg );
void Netchan_CreateFragments( netchan_t *chan, sizebuf_t *msg );
int Netchan_CreateFileFragments( netchan_t *chan, const char *filename );
void Netchan_TransmitBits( netchan_t *chan, int lengthInBits, byte *data );
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data );
void Netchan_TransmitBits( netchan_t *chan, int lengthInBits, const byte *data );
void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, const byte *data );
void Netchan_OutOfBandPrint( int net_socket, netadr_t adr, const char *format, ... ) _format( 3 );
qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg );
void Netchan_UpdateProgress( netchan_t *chan );

View File

@@ -1,95 +0,0 @@
/*
pm_debug.c - player move debugging code
Copyright (C) 2017 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"
#include "xash3d_mathlib.h"
#include "pm_local.h"
#if !XASH_DEDICATED
#include "client.h" // CL_Particle
#endif
// expand debugging BBOX particle hulls by this many units.
#define BOX_GAP 0.0f
/*
===============
PM_ParticleLine
draw line from particles
================
*/
void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel )
{
#if !XASH_DEDICATED
float len, curdist;
vec3_t diff, pos;
// determine distance
VectorSubtract( end, start, diff );
len = VectorNormalizeLength( diff );
curdist = 0;
while( curdist <= len )
{
VectorMA( start, curdist, diff, pos );
CL_Particle( pos, pcolor, life, 0, zvel );
curdist += 2.0f;
}
#endif // XASH_DEDICATED
}
/*
================
PM_DrawRectangle
================
*/
static void PM_DrawRectangle( const vec3_t tl, const vec3_t bl, const vec3_t tr, const vec3_t br, int pcolor, float life )
{
PM_ParticleLine( tl, bl, pcolor, life, 0 );
PM_ParticleLine( bl, br, pcolor, life, 0 );
PM_ParticleLine( br, tr, pcolor, life, 0 );
PM_ParticleLine( tr, tl, pcolor, life, 0 );
}
/*
================
PM_DrawBBox
================
*/
void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life )
{
#if !XASH_DEDICATED
vec3_t p[8], tmp;
float gap = BOX_GAP;
int i;
for( i = 0; i < 8; i++ )
{
tmp[0] = (i & 1) ? mins[0] - gap : maxs[0] + gap;
tmp[1] = (i & 2) ? mins[1] - gap : maxs[1] + gap ;
tmp[2] = (i & 4) ? mins[2] - gap : maxs[2] + gap ;
VectorAdd( tmp, origin, tmp );
VectorCopy( tmp, p[i] );
}
for( i = 0; i < 6; i++ )
{
PM_DrawRectangle( p[boxpnt[i][1]], p[boxpnt[i][0]], p[boxpnt[i][2]], p[boxpnt[i][3]], pcolor, life );
}
#endif // XASH_DEDICATED
}

View File

@@ -20,17 +20,10 @@ GNU General Public License for more details.
typedef int (*pfnIgnore)( physent_t *pe ); // custom trace filter
//
// pm_debug.c
//
void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel );
void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life );
//
// pm_trace.c
//
void Pmove_Init( void );
void PM_ClearPhysEnts( playermove_t *pmove );
void PM_InitBoxHull( void );
hull_t *PM_HullForBsp( physent_t *pe, playermove_t *pmove, float *offset );
qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace );
@@ -46,7 +39,29 @@ struct msurface_s *PM_TraceSurfacePmove( playermove_t *pmove, int ground, float
const char *PM_TraceTexture( playermove_t *pmove, int ground, float *vstart, float *vend );
int PM_PointContentsPmove( playermove_t *pmove, const float *p, int *truecontents );
void PM_StuckTouch( playermove_t *pmove, int hitent, pmtrace_t *tr );
void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent );
static inline void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent )
{
out->allsolid = in->allsolid;
out->startsolid = in->startsolid;
out->inopen = in->inopen;
out->inwater = in->inwater;
out->fraction = in->fraction;
out->plane.dist = in->plane.dist;
out->hitgroup = in->hitgroup;
out->ent = ent;
VectorCopy( in->endpos, out->endpos );
VectorCopy( in->plane.normal, out->plane.normal );
}
static inline void PM_ClearPhysEnts( playermove_t *pmove )
{
pmove->nummoveent = 0;
pmove->numphysent = 0;
pmove->numvisent = 0;
pmove->numtouch = 0;
}
static inline void PM_InitTrace( trace_t *trace, const vec3_t end )
{

View File

@@ -55,14 +55,6 @@ void Pmove_Init( void )
memcpy( host.player_maxs, pm_hullmaxs, sizeof( pm_hullmaxs ));
}
void PM_ClearPhysEnts( playermove_t *pmove )
{
pmove->nummoveent = 0;
pmove->numphysent = 0;
pmove->numvisent = 0;
pmove->numtouch = 0;
}
/*
===================
PM_InitBoxHull
@@ -117,21 +109,6 @@ static hull_t *PM_HullForBox( const vec3_t mins, const vec3_t maxs )
return &pm_boxhull;
}
void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent )
{
out->allsolid = in->allsolid;
out->startsolid = in->startsolid;
out->inopen = in->inopen;
out->inwater = in->inwater;
out->fraction = in->fraction;
out->plane.dist = in->plane.dist;
out->hitgroup = in->hitgroup;
out->ent = ent;
VectorCopy( in->endpos, out->endpos );
VectorCopy( in->plane.normal, out->plane.normal );
}
/*
==================
PM_HullPointContents

View File

@@ -73,7 +73,7 @@ GNU General Public License for more details.
#define svc_director 51 // <variable sized>
#define svc_voiceinit 52 // <see code>
#define svc_voicedata 53 // [byte][short][...]
#define svc_deltapacketbones 54 // [short][byte][...]
// reserved
// reserved
#define svc_resourcelocation 56 // [string]
#define svc_querycvarvalue 57 // [string]
@@ -93,7 +93,7 @@ GNU General Public License for more details.
#define clc_voicedata 8
#define clc_requestcvarvalue 9
#define clc_requestcvarvalue2 10
#define clc_lastmsg 10 // end client messages
#define clc_lastmsg 11 // end client messages (11 is GoldSrc message)
#define MAX_VISIBLE_PACKET_BITS 11 // 2048 visible entities per frame (hl1 has 256)
#define MAX_VISIBLE_PACKET (1<<MAX_VISIBLE_PACKET_BITS)
@@ -277,11 +277,11 @@ GNU General Public License for more details.
#define SU_ARMOR (1<<13)
#define SU_WEAPON (1<<14)
extern const char *svc_strings[svc_lastmsg+1];
extern const char *svc_legacy_strings[svc_lastmsg+1];
extern const char *svc_quake_strings[svc_lastmsg+1];
extern const char *svc_goldsrc_strings[svc_lastmsg+1];
extern const char *clc_strings[clc_lastmsg+1];
extern const char *const svc_strings[svc_lastmsg+1];
extern const char *const svc_legacy_strings[svc_lastmsg+1];
extern const char *const svc_quake_strings[svc_lastmsg+1];
extern const char *const svc_goldsrc_strings[svc_lastmsg+1];
extern const char *const clc_strings[clc_lastmsg+1];
// FWGS extensions
#define NET_EXT_SPLITSIZE (1U<<0) // set splitsize by cl_dlmax
@@ -320,8 +320,7 @@ extern const char *clc_strings[clc_lastmsg+1];
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter
// GoldSrc protocol definitions
#define PROTOCOL_GOLDSRC_VERSION_REAL 48
#define PROTOCOL_GOLDSRC_VERSION (PROTOCOL_GOLDSRC_VERSION_REAL | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
#define PROTOCOL_GOLDSRC_VERSION 48
#define svc_goldsrc_version svc_changing
#define svc_goldsrc_serverinfo svc_serverdata
@@ -342,17 +341,66 @@ extern const char *clc_strings[clc_lastmsg+1];
#define clc_goldsrc_hltv clc_requestcvarvalue // 9
#define clc_goldsrc_requestcvarvalue clc_requestcvarvalue2 // 10
#define clc_goldsrc_requestcvarvalue2 11
#define clc_goldsrc_lastmsg 12
#define S2C_REJECT_BADPASSWORD '8'
#define S2C_REJECT '9'
#define S2C_CHALLENGE "A00000000"
#define S2C_CONNECTION "B"
#define clc_goldsrc_lastmsg 11
#define MAX_GOLDSRC_BACKUP_CMDS 8
#define MAX_GOLDSRC_TOTAL_CMDS 16
#define MAX_GOLDSRC_MODEL_BITS 10
#define MAX_GOLDSRC_RESOURCE_BITS 12
#define MAX_GOLDSRC_ENTITY_BITS 11
// #define MAX_GOLDSRC_EDICTS BIT( MAX_ENTITY_BITS )
#define MAX_GOLDSRC_EDICTS ( BIT( MAX_ENTITY_BITS ) + ( MAX_CLIENTS * 15 ))
#define LAST_GOLDSRC_EDICT ( BIT( MAX_ENTITY_BITS ) - 1 )
// from any to any (must be handled on both server and client)
#define A2A_PING "ping" // reply with A2A_ACK
#define A2A_ACK "ack" // no-op
#define A2A_INFO "info" // different format for client and server, see code
#define A2A_NETINFO "netinfo" // different format for client and server, see code
#define A2A_GOLDSRC_PING "i" // reply with A2A_GOLDSRC_ACK
#define A2A_GOLDSRC_ACK "j" // no-op
// from any to server
#define A2S_GOLDSRC_INFO "TSource Engine Query"
#define A2S_GOLDSRC_RULES 'V'
#define A2S_GOLDSRC_PLAYERS 'U'
// from server to any
#define S2A_GOLDSRC_INFO 'I'
#define S2A_GOLDSRC_RULES 'E'
#define S2A_GOLDSRC_PLAYERS 'D'
// from master to server
#define M2S_CHALLENGE "s"
#define M2S_NAT_CONNECT "c"
// from server to master
#define S2M_INFO "0\n"
// from client to server
#define C2S_BANDWIDTHTEST "bandwidth"
#define C2S_GETCHALLENGE "getchallenge"
#define C2S_CONNECT "connect"
#define C2S_RCON "rcon"
// from server to client
#define S2C_BANDWIDTHTEST "testpacket"
#define S2C_CHALLENGE "challenge"
#define S2C_CONNECTION "client_connect"
#define S2C_ERRORMSG "errormsg"
#define S2C_REJECT "disconnect"
#define S2C_GOLDSRC_REJECT_BADPASSWORD '8'
#define S2C_GOLDSRC_REJECT '9'
#define S2C_GOLDSRC_CHALLENGE "A00000000"
#define S2C_GOLDSRC_CONNECTION "B"
// from any to client
#define A2C_PRINT "print"
#define A2C_GOLDSRC_PRINT 'l'
// from master to client
#define M2A_SERVERSLIST "f"
#endif//NET_PROTOCOL_H

View File

@@ -21,7 +21,7 @@ enum soundlst_type_e
SoundList_List
};
static const char *soundlst_groups[SoundList_Groups] =
static const char *const soundlst_groups[SoundList_Groups] =
{
"BouncePlayerShell",
"BounceWeaponShell",
@@ -46,7 +46,7 @@ typedef struct soundlst_s
int max; // the string count if type is group
} soundlst_t;
soundlst_t soundlst[SoundList_Groups];
static soundlst_t soundlst[SoundList_Groups];
static void SoundList_Print_f( void );
static void SoundList_Free( soundlst_t *lst )

View File

@@ -41,6 +41,7 @@ void Test_RunIPFilter( void );
void Test_RunGamma( void );
void Test_RunDelta( void );
void Test_RunBuffer( void );
void Test_RunMunge( void );
#define TEST_LIST_0 \
Test_RunLibCommon(); \
@@ -49,7 +50,8 @@ void Test_RunBuffer( void );
Test_RunCvar(); \
Test_RunIPFilter(); \
Test_RunBuffer(); \
Test_RunDelta();
Test_RunDelta(); \
Test_RunMunge();
#define TEST_LIST_0_CLIENT \
Test_RunCon(); \

View File

@@ -20,47 +20,6 @@ GNU General Public License for more details.
#include "xash3d_mathlib.h"
#include "studio.h"
/*
==================
World_MoveBounds
==================
*/
void World_MoveBounds( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, vec3_t boxmins, vec3_t boxmaxs )
{
int i;
for( i = 0; i < 3; i++ )
{
if( end[i] > start[i] )
{
boxmins[i] = start[i] + mins[i] - 1.0f;
boxmaxs[i] = end[i] + maxs[i] + 1.0f;
}
else
{
boxmins[i] = end[i] + mins[i] - 1.0f;
boxmaxs[i] = start[i] + maxs[i] + 1.0f;
}
}
}
trace_t World_CombineTraces( trace_t *cliptrace, trace_t *trace, edict_t *touch )
{
if( trace->allsolid || trace->startsolid || trace->fraction < cliptrace->fraction )
{
trace->ent = touch;
if( cliptrace->startsolid )
{
*cliptrace = *trace;
cliptrace->startsolid = true;
}
else *cliptrace = *trace;
}
return *cliptrace;
}
/*
==================
World_TransformAABB
@@ -107,31 +66,3 @@ void World_TransformAABB( matrix4x4 transform, const vec3_t mins, const vec3_t m
}
}
}
/*
==================
RankForContents
Used for determine contents priority
==================
*/
int RankForContents( int contents )
{
switch( contents )
{
case CONTENTS_EMPTY: return 0;
case CONTENTS_WATER: return 1;
case CONTENTS_TRANSLUCENT: return 2;
case CONTENTS_CURRENT_0: return 3;
case CONTENTS_CURRENT_90: return 4;
case CONTENTS_CURRENT_180: return 5;
case CONTENTS_CURRENT_270: return 6;
case CONTENTS_CURRENT_UP: return 7;
case CONTENTS_CURRENT_DOWN: return 8;
case CONTENTS_SLIME: return 9;
case CONTENTS_LAVA: return 10;
case CONTENTS_SKY: return 11;
case CONTENTS_SOLID: return 12;
default: return 13; // any user contents has more priority than default
}
}

View File

@@ -36,10 +36,71 @@ ENTITY AREA CHECKING
#include "lightstyle.h"
// trace common
void World_MoveBounds( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, vec3_t boxmins, vec3_t boxmaxs );
static inline void World_MoveBounds( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, vec3_t boxmins, vec3_t boxmaxs )
{
int i;
for( i = 0; i < 3; i++ )
{
if( end[i] > start[i] )
{
boxmins[i] = start[i] + mins[i] - 1.0f;
boxmaxs[i] = end[i] + maxs[i] + 1.0f;
}
else
{
boxmins[i] = end[i] + mins[i] - 1.0f;
boxmaxs[i] = start[i] + maxs[i] + 1.0f;
}
}
}
static inline trace_t World_CombineTraces( trace_t *cliptrace, trace_t *trace, edict_t *touch )
{
if( trace->allsolid || trace->startsolid || trace->fraction < cliptrace->fraction )
{
trace->ent = touch;
if( cliptrace->startsolid )
{
*cliptrace = *trace;
cliptrace->startsolid = true;
}
else *cliptrace = *trace;
}
return *cliptrace;
}
/*
==================
RankForContents
Used for determine contents priority
==================
*/
static inline int RankForContents( int contents )
{
switch( contents )
{
case CONTENTS_EMPTY: return 0;
case CONTENTS_WATER: return 1;
case CONTENTS_TRANSLUCENT: return 2;
case CONTENTS_CURRENT_0: return 3;
case CONTENTS_CURRENT_90: return 4;
case CONTENTS_CURRENT_180: return 5;
case CONTENTS_CURRENT_270: return 6;
case CONTENTS_CURRENT_UP: return 7;
case CONTENTS_CURRENT_DOWN: return 8;
case CONTENTS_SLIME: return 9;
case CONTENTS_LAVA: return 10;
case CONTENTS_SKY: return 11;
case CONTENTS_SOLID: return 12;
default: return 13; // any user contents has more priority than default
}
}
void World_TransformAABB( matrix4x4 transform, const vec3_t mins, const vec3_t maxs, vec3_t outmins, vec3_t outmaxs );
trace_t World_CombineTraces( trace_t *cliptrace, trace_t *trace, edict_t *touch );
int RankForContents( int contents );
#define check_angles( x ) ( (int)x == 90 || (int)x == 180 || (int)x == 270 || (int)x == -90 || (int)x == -180 || (int)x == -270 )

View File

@@ -64,6 +64,7 @@ typedef enum
force_exactfile, // File on client must exactly match server's file
force_model_samebounds, // For model files only, the geometry must fit in the same bbox
force_model_specifybounds, // For model files only, the geometry must fit in the specified bbox
force_model_specifybounds_if_avail,
} FORCE_TYPE;
// Returned by TraceLine

View File

@@ -222,6 +222,10 @@ typedef struct ui_extendedfuncs_s {
// new mods info
gameinfo2_t *(*pfnGetGameInfo)( int gi_version ); // might return NULL if gi_version is unsupported
gameinfo2_t *(*pfnGetModInfo)( int gi_version, int mod_index ); // continiously call it until it returns null
// returns 1 if cvar has read-only flag
// or -1 if cvar not found
int (*pfnIsCvarReadOnly)( const char *name );
} ui_extendedfuncs_t;
// deprecated export from old engine

View File

@@ -26,47 +26,56 @@
* SUCH DAMAGE.
*/
#if defined __ANDROID__ && !defined XASH_64BIT
#include "build.h"
#if XASH_ANDROID && !XASH_64BIT
#include <string.h>
#include <android/log.h>
#include "linker.h"
static Elf_Sym* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
Elf_Sym* symtab = si->symtab;
const char* strtab = si->strtab;
static Elf_Sym *soinfo_elf_lookup( const soinfo *si, unsigned hash, const char *name )
{
const Elf_Sym *symtab = si->symtab;
const char *strtab = si->strtab;
unsigned n;
if( si->nbucket == 0 )
return NULL;
for (unsigned n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]) {
Elf_Sym* s = symtab + n;
if (strcmp(strtab + s->st_name, name)) continue;
for( n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n] )
{
const Elf_Sym *s = symtab + n;
/* only concern ourselves with global and weak symbol definitions */
switch (ELF_ST_BIND(s->st_info)) {
case STB_GLOBAL:
case STB_WEAK:
if (s->st_shndx == SHN_UNDEF) {
continue;
}
return s;
}
}
if( strcmp( strtab + s->st_name, name ))
continue;
return NULL;
/* only concern ourselves with global and weak symbol definitions */
switch( ELF_ST_BIND( s->st_info ))
{
case STB_GLOBAL:
case STB_WEAK:
if( s->st_shndx == SHN_UNDEF )
continue;
return s;
}
}
return NULL;
}
static unsigned elfhash(const char* _name) {
const unsigned char* name = (const unsigned char*) _name;
unsigned h = 0, g;
static unsigned elfhash( const unsigned char *name )
{
unsigned h = 0;
while(*name) {
h = (h << 4) + *name++;
g = h & 0xf0000000;
h ^= g;
h ^= g >> 24;
}
return h;
while( *name )
{
unsigned g;
h = ( h << 4 ) + *name++;
g = h & 0xf0000000;
h ^= g;
h ^= g >> 24;
}
return h;
}
/* This is used by dlsym(3). It performs symbol lookup only within the
@@ -78,21 +87,20 @@ static unsigned elfhash(const char* _name) {
Binary Interface) where in Chapter 5 it discuss resolving "Shared
Object Dependencies" in breadth first search order.
*/
static Elf_Sym* dlsym_handle_lookup(soinfo* si, const char* name) {
return soinfo_elf_lookup(si, elfhash(name), name);
static Elf_Sym *dlsym_handle_lookup( const soinfo *si, const char *name )
{
return soinfo_elf_lookup( si, elfhash((const unsigned char *)name ), name );
}
extern "C" void* dlsym_weak(void* handle, const char* symbol) {
extern "C" void *dlsym_weak( void *handle, const char *symbol )
{
soinfo *found = (soinfo *)handle;
Elf_Sym *sym = dlsym_handle_lookup( found, symbol );
soinfo* found = NULL;
Elf_Sym* sym = NULL;
found = reinterpret_cast<soinfo*>(handle);
sym = dlsym_handle_lookup(found, symbol);
if( sym != NULL )
return (void *)( sym->st_value + found->base /*load_bias*/ );
if (sym != NULL) {
return reinterpret_cast<void*>(sym->st_value + found->base/*load_bias*/);
}
__android_log_print(ANDROID_LOG_ERROR, "dlsym-weak", "Failed when looking up %s\n", symbol);
return NULL;
__android_log_print( ANDROID_LOG_ERROR, "dlsym-weak", "Failed when looking up %s\n", symbol );
return NULL;
}
#endif
#endif // XASH_ANDROID && !XASH_64BIT

View File

@@ -28,7 +28,6 @@
#ifndef _LINKER_H_
#define _LINKER_H_
#ifdef __ANDROID__
#include <unistd.h>
#include <sys/types.h>
@@ -39,163 +38,153 @@
// a1ba: we don't really need custom linker on Android 64, because
// it's only intended to workaround bug which persist on Android < 4.4
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_RelA Elf32_Rela
#define Elf_Dyn Elf32_Dyn
#define Elf_Half Elf32_Half
#define Elf_Word Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Addr Elf32_Addr
#define Elf_Off Elf32_Off
#define Elf_Nhdr Elf32_Nhdr
#define Elf_Note Elf32_Note
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_RelA Elf32_Rela
#define Elf_Dyn Elf32_Dyn
#define Elf_Half Elf32_Half
#define Elf_Word Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Addr Elf32_Addr
#define Elf_Off Elf32_Off
#define Elf_Nhdr Elf32_Nhdr
#define Elf_Note Elf32_Note
// Returns the address of the page containing address 'x'.
#define PAGE_START(x) ((x) & PAGE_MASK)
#define PAGE_START( x ) (( x )&PAGE_MASK )
// Returns the offset of address 'x' in its page.
#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
#define PAGE_OFFSET( x ) (( x ) & ~PAGE_MASK )
// Returns the address of the next page after address 'x', unless 'x' is
// itself at the start of a page.
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
#define PAGE_END( x ) PAGE_START(( x ) + ( PAGE_SIZE - 1 ))
// Magic shared structures that GDB knows about.
struct link_map_t {
uintptr_t l_addr;
char* l_name;
uintptr_t l_ld;
link_map_t* l_next;
link_map_t* l_prev;
uintptr_t l_addr;
char *l_name;
uintptr_t l_ld;
link_map_t *l_next;
link_map_t *l_prev;
};
// Values for r_debug->state
enum {
RT_CONSISTENT,
RT_ADD,
RT_DELETE
RT_CONSISTENT,
RT_ADD,
RT_DELETE
};
#if 0
struct r_debug {
int32_t r_version;
link_map_t* r_map;
void (*r_brk)(void);
int32_t r_state;
uintptr_t r_ldbase;
};
#endif
#define FLAG_LINKED 0x00000001
#define FLAG_EXE 0x00000004 // The main executable
#define FLAG_LINKER 0x00000010 // The linker itself
#define FLAG_LINKED 0x00000001
#define FLAG_EXE 0x00000004 // The main executable
#define FLAG_LINKER 0x00000010 // The linker itself
#define SOINFO_NAME_LEN 128
typedef void (*linker_function_t)();
// Android uses REL for 32-bit but only uses RELA for 64-bit.
#if defined(__LP64__)
#if defined( __LP64__ )
#define USE_RELA 1
#endif
struct soinfo {
public:
char name[SOINFO_NAME_LEN];
const Elf_Phdr* phdr;
size_t phnum;
Elf_Addr entry;
Elf_Addr base;
unsigned size;
public:
char name[SOINFO_NAME_LEN];
const Elf_Phdr *phdr;
size_t phnum;
Elf_Addr entry;
Elf_Addr base;
unsigned size;
#ifndef __LP64__
uint32_t unused1; // DO NOT USE, maintained for compatibility.
uint32_t unused1; // DO NOT USE, maintained for compatibility.
#endif
Elf_Dyn* dynamic;
Elf_Dyn *dynamic;
#ifndef __LP64__
uint32_t unused2; // DO NOT USE, maintained for compatibility
uint32_t unused3; // DO NOT USE, maintained for compatibility
uint32_t unused2; // DO NOT USE, maintained for compatibility
uint32_t unused3; // DO NOT USE, maintained for compatibility
#endif
soinfo* next;
unsigned flags;
soinfo *next;
unsigned flags;
const char* strtab;
Elf_Sym* symtab;
const char *strtab;
Elf_Sym *symtab;
size_t nbucket;
size_t nchain;
unsigned* bucket;
unsigned* chain;
size_t nbucket;
size_t nchain;
unsigned *bucket;
unsigned *chain;
#if !defined(__LP64__)
// This is only used by 32-bit MIPS, but needs to be here for
// all 32-bit architectures to preserve binary compatibility.
unsigned* plt_got;
#if !defined( __LP64__ )
// This is only used by 32-bit MIPS, but needs to be here for
// all 32-bit architectures to preserve binary compatibility.
unsigned *plt_got;
#endif
#if defined(USE_RELA)
Elf_RelA* plt_rela;
size_t plt_rela_count;
#if defined( USE_RELA )
Elf_RelA *plt_rela;
size_t plt_rela_count;
Elf_RelA* rela;
size_t rela_count;
Elf_RelA *rela;
size_t rela_count;
#else
Elf_Rel* plt_rel;
size_t plt_rel_count;
Elf_Rel *plt_rel;
size_t plt_rel_count;
Elf_Rel* rel;
size_t rel_count;
Elf_Rel *rel;
size_t rel_count;
#endif
linker_function_t* preinit_array;
size_t preinit_array_count;
linker_function_t *preinit_array;
size_t preinit_array_count;
linker_function_t* init_array;
size_t init_array_count;
linker_function_t* fini_array;
size_t fini_array_count;
linker_function_t *init_array;
size_t init_array_count;
linker_function_t *fini_array;
size_t fini_array_count;
linker_function_t init_func;
linker_function_t fini_func;
linker_function_t init_func;
linker_function_t fini_func;
#if defined(__arm__)
// ARM EABI section used for stack unwinding.
unsigned* ARM_exidx;
size_t ARM_exidx_count;
#elif defined(__mips__)
unsigned mips_symtabno;
unsigned mips_local_gotno;
unsigned mips_gotsym;
#if defined( __arm__ )
// ARM EABI section used for stack unwinding.
unsigned *ARM_exidx;
size_t ARM_exidx_count;
#elif defined( __mips__ )
unsigned mips_symtabno;
unsigned mips_local_gotno;
unsigned mips_gotsym;
#endif
size_t ref_count;
link_map_t link_map;
size_t ref_count;
link_map_t link_map;
bool constructors_called;
bool constructors_called;
// When you read a virtual address from the ELF file, add this
// value to get the corresponding address in the process' address space.
Elf_Addr load_bias;
// When you read a virtual address from the ELF file, add this
// value to get the corresponding address in the process' address space.
Elf_Addr load_bias;
#if !defined(__LP64__)
bool has_text_relocations;
#if !defined( __LP64__ )
bool has_text_relocations;
#endif
bool has_DT_SYMBOLIC;
bool has_DT_SYMBOLIC;
void CallConstructors();
void CallDestructors();
void CallPreInitConstructors();
void CallConstructors();
void CallDestructors();
void CallPreInitConstructors();
private:
void CallArray(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
void CallFunction(const char* function_name, linker_function_t function);
private:
void CallArray( const char *array_name, linker_function_t *functions, size_t count, bool reverse );
void CallFunction( const char *function_name, linker_function_t function );
};
#endif
#endif

View File

@@ -51,6 +51,7 @@ void IOS_LaunchDialog( void );
#if XASH_POSIX
void Posix_Daemonize( void );
void Posix_SetupSigtermHandling( void );
#endif
#if XASH_SDL
@@ -156,6 +157,13 @@ static inline qboolean Sys_DebuggerPresent( void )
#endif
}
static inline void Platform_SetupSigtermHandling( void )
{
#if XASH_POSIX
Posix_SetupSigtermHandling( );
#endif
}
/*
==============================================================================

View File

@@ -18,6 +18,7 @@ GNU General Public License for more details.
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include "platform/platform.h"
#include "menu_int.h"
@@ -145,6 +146,21 @@ void Posix_Daemonize( void )
}
static void Posix_SigtermCallback( int signal )
{
Sys_Quit();
}
void Posix_SetupSigtermHandling( void )
{
#if !XASH_PSVITA
struct sigaction act = { 0 };
act.sa_handler = Posix_SigtermCallback;
act.sa_flags = 0;
sigaction( SIGTERM, &act, NULL );
#endif
}
#if XASH_TIMER == TIMER_POSIX
double Platform_DoubleTime( void )
{

View File

@@ -674,7 +674,7 @@ static void VID_SetWindowIcon( SDL_Window *hWnd )
if( ico && WIN_SetWindowIcon( ico ))
return;
}
#endif // _WIN32 && !XASH_64BIT
#endif // XASH_WIN32
Q_strncpy( iconpath, GI->iconpath, sizeof( iconpath ));
COM_ReplaceExtension( iconpath, ".tga", sizeof( iconpath ));

View File

@@ -61,8 +61,6 @@ GNU General Public License for more details.
#define FCONTEXT_CORE_PROFILE BIT( 0 )
#define FCONTEXT_DEBUG_ARB BIT( 1 )
#define FCVAR_READ_ONLY (1<<17) // cannot be set by user at all, and can't be requested by CvarGetPointer from game dlls
// screenshot types
#define VID_SCREENSHOT 0
#define VID_LEVELSHOT 1

View File

@@ -683,6 +683,6 @@ int SV_LightForEntity( edict_t *pEdict );
//
// sv_query.c
//
qboolean SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from );
void SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from );
#endif//SERVER_H

View File

@@ -19,7 +19,7 @@ GNU General Public License for more details.
#include "net_encode.h"
#include "net_api.h"
const char *clc_strings[clc_lastmsg+1] =
const char *const clc_strings[clc_lastmsg+1] =
{
"clc_bad",
"clc_nop",
@@ -27,11 +27,12 @@ const char *clc_strings[clc_lastmsg+1] =
"clc_stringcmd",
"clc_delta",
"clc_resourcelist",
"clc_unused6",
"clc_legacy_userinfo",
"clc_fileconsistency",
"clc_voicedata",
"clc_cvarvalue",
"clc_cvarvalue2",
"clc_cvarvalue/clc_goldsrc_hltv",
"clc_cvarvalue2/clc_goldsrc_requestcvarvalue",
"clc_goldsrc_requestcvarvalue2",
};
typedef struct ucmd_s
@@ -130,7 +131,7 @@ static void SV_GetChallenge( netadr_t from )
}
// send it back
Netchan_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "challenge %i", svs.challenges[i].challenge );
Netchan_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, S2C_CHALLENGE" %i", svs.challenges[i].challenge );
}
static int SV_GetFragmentSize( void *pcl, fragsize_t mode )
@@ -193,9 +194,9 @@ void SV_RejectConnection( netadr_t from, const char *fmt, ... )
va_end( argptr );
Con_Reportf( "%s connection refused. Reason: %s\n", NET_AdrToString( from ), text );
Netchan_OutOfBandPrint( NS_SERVER, from, "errormsg\n^1Server was reject the connection:^7 %s", text );
Netchan_OutOfBandPrint( NS_SERVER, from, "print\n^1Server was reject the connection:^7 %s", text );
Netchan_OutOfBandPrint( NS_SERVER, from, "disconnect\n" );
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_ERRORMSG"\n^1Server was reject the connection:^7 %s", text );
Netchan_OutOfBandPrint( NS_SERVER, from, A2C_PRINT"\n^1Server was reject the connection:^7 %s", text );
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_REJECT"\n" );
}
/*
@@ -444,7 +445,7 @@ static void SV_ConnectClient( netadr_t from )
newcl->listeners = -1;
// initailize netchan
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize );
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, 0 );
MSG_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf
Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 );
@@ -455,7 +456,7 @@ static void SV_ConnectClient( netadr_t from )
Info_SetValueForKeyf( protinfo, "ext", sizeof( protinfo ), "%d", newcl->extensions );
// send the connect packet to the client
Netchan_OutOfBandPrint( NS_SERVER, from, "client_connect %s", protinfo );
Netchan_OutOfBandPrint( NS_SERVER, from, S2C_CONNECTION" %s", protinfo );
newcl->upstate = us_inactive;
newcl->connection_started = host.realtime;
@@ -603,7 +604,7 @@ void SV_KickPlayer( sv_client_t *cl, const char *fmt, ... )
SV_BroadcastPrintf( cl, "%s was kicked with message: \"%s\"\n", cl->name, buf );
SV_ClientPrintf( cl, "You were kicked from the game with message: \"%s\"\n", buf );
if( cl->useragent[0] )
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, "errormsg\nKicked with message:\n%s\n", buf );
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, S2C_ERRORMSG"\nKicked with message:\n%s\n", buf );
}
else
{
@@ -611,7 +612,7 @@ void SV_KickPlayer( sv_client_t *cl, const char *fmt, ... )
SV_BroadcastPrintf( cl, "%s was kicked\n", cl->name );
SV_ClientPrintf( cl, "You were kicked from the game\n" );
if( cl->useragent[0] )
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, "errormsg\nYou were kicked from the game\n" );
Netchan_OutOfBandPrint( NS_SERVER, cl->netchan.remote_address, S2C_ERRORMSG"\nYou were kicked from the game\n" );
}
SV_DropClient( cl, false );
@@ -713,20 +714,18 @@ static void SV_BeginRedirect( host_redirect_t *rd, netadr_t adr, rdtype_t target
static void SV_FlushRedirect( netadr_t adr, int dest, char *buf )
{
if( sv.current_client && FBitSet( sv.current_client->flags, FCL_FAKECLIENT ))
return;
switch( dest )
{
case RD_PACKET:
Netchan_OutOfBandPrint( NS_SERVER, adr, "print\n%s", buf );
Netchan_OutOfBandPrint( NS_SERVER, adr, A2C_PRINT"\n%s", buf );
break;
case RD_CLIENT:
if( !sv.current_client ) return; // client not set
if( !sv.current_client || !FBitSet( sv.current_client->flags, FCL_FAKECLIENT ))
return; // client not set
MSG_BeginServerCmd( &sv.current_client->netchan.message, svc_print );
MSG_WriteString( &sv.current_client->netchan.message, buf );
break;
case RD_NONE:
default:
Con_Printf( S_ERROR "%s: %s: invalid destination\n", __func__, NET_AdrToString( adr ));
break;
}
@@ -952,14 +951,30 @@ static void SV_Info( netadr_t from, int protocolVersion )
if( remaining < 0 )
{
// should never happen?
Con_Printf( S_ERROR "SV_Info: infostring overflow!\n" );
Con_Printf( S_ERROR "%s: infostring overflow!\n", __func__ );
return;
}
Q_strncpy( temp, hostname.string, remaining );
Info_SetValueForKey( s, "host", temp, sizeof( s ));
}
Netchan_OutOfBandPrint( NS_SERVER, from, "info\n%s", s );
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_INFO"\n%s", s );
}
static void SV_ConnectNatClient( netadr_t from )
{
netadr_t to;
if( !sv_nat.value || !NET_IsMasterAdr( from ))
return;
if( !NET_StringToAdr( Cmd_Argv( 1 ), &to ))
return;
if( NET_IsReservedAdr( to ))
return;
SV_Info( to, PROTOCOL_VERSION );
}
/*
@@ -993,7 +1008,7 @@ static void SV_BuildNetAnswer( netadr_t from )
{
// send error unsupported protocol
Info_SetValueForKey( string, "neterror", "protocol", sizeof( string ));
Netchan_OutOfBandPrint( NS_SERVER, from, "netinfo %i %i %s\n", context, type, string );
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_NETINFO" %i %i %s\n", context, type, string );
return;
}
@@ -1064,19 +1079,7 @@ static void SV_BuildNetAnswer( netadr_t from )
break;
}
Netchan_OutOfBandPrint( NS_SERVER, from, "netinfo %i %i %s\n", context, type, string );
}
/*
================
SV_Ping
Just responds with an acknowledgement
================
*/
static void SV_Ping( netadr_t from )
{
Netchan_OutOfBandPrint( NS_SERVER, from, "ack" );
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_NETINFO" %i %i %s\n", context, type, string );
}
/*
@@ -1104,10 +1107,7 @@ Redirect all printfs
*/
void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
{
static char outputbuf[2048];
const char *adr;
char remaining[1024];
char *p = remaining;
int i;
if( !rcon_enable.value || !COM_CheckStringEmpty( rcon_password.string ))
@@ -1120,7 +1120,9 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
if( Rcon_Validate( ))
{
SV_BeginRedirect( &host.rd, from, RD_PACKET, outputbuf, sizeof( outputbuf ) - 16, SV_FlushRedirect );
static char outputbuf[2048];
char remaining[1024];
char *p = remaining;
remaining[0] = 0;
for( i = 2; i < Cmd_Argc(); i++ )
@@ -1129,8 +1131,9 @@ void SV_RemoteCommand( netadr_t from, sizebuf_t *msg )
p += Q_strncpy( p, Cmd_Argv( i ), sizeof( remaining ) - ( p - remaining ));
p += Q_strncpy( p, "\" ", sizeof( remaining ) - ( p - remaining ));
}
Cmd_ExecuteString( remaining );
SV_BeginRedirect( &host.rd, from, RD_PACKET, outputbuf, sizeof( outputbuf ) - 16, SV_FlushRedirect );
Cmd_ExecuteString( remaining );
SV_EndRedirect( &host.rd );
}
else Con_Printf( S_ERROR "Bad rcon_password.\n" );
@@ -1342,9 +1345,8 @@ otherwise see code SV_UpdateMovevars()
*/
void SV_FullUpdateMovevars( sv_client_t *cl, sizebuf_t *msg )
{
movevars_t nullmovevars;
const movevars_t nullmovevars = { 0 };
memset( &nullmovevars, 0, sizeof( nullmovevars ));
MSG_WriteDeltaMovevars( msg, &nullmovevars, &svgame.movevars );
}
@@ -1992,7 +1994,7 @@ static qboolean SV_Noclip_f( sv_client_t *cl )
{
edict_t *pEntity = cl->edict;
if( !Cvar_VariableInteger( "sv_cheats" ) || sv.background )
if( sv.background || !Cvar_VariableInteger( "sv_cheats" ))
return true;
if( pEntity->v.movetype != MOVETYPE_NOCLIP )
@@ -2018,7 +2020,7 @@ static qboolean SV_Godmode_f( sv_client_t *cl )
{
edict_t *pEntity = cl->edict;
if( !Cvar_VariableInteger( "sv_cheats" ) || sv.background )
if( sv.background || !Cvar_VariableInteger( "sv_cheats" ))
return true;
pEntity->v.flags = pEntity->v.flags ^ FL_GODMODE;
@@ -2039,7 +2041,7 @@ static qboolean SV_Notarget_f( sv_client_t *cl )
{
edict_t *pEntity = cl->edict;
if( !Cvar_VariableInteger( "sv_cheats" ) || sv.background )
if( sv.background || !Cvar_VariableInteger( "sv_cheats" ))
return true;
pEntity->v.flags = pEntity->v.flags ^ FL_NOTARGET;
@@ -3036,7 +3038,7 @@ static qboolean SV_EntGetVars_f( sv_client_t *cl )
return true;
}
ucmd_t ucmds[] =
static const ucmd_t ucmds[] =
{
{ "new", SV_New_f },
{ "god", SV_Godmode_f },
@@ -3056,7 +3058,7 @@ ucmd_t ucmds[] =
{ NULL, NULL }
};
ucmd_t enttoolscmds[] =
static const ucmd_t enttoolscmds[] =
{
{ "ent_list", SV_EntList_f },
{ "ent_info", SV_EntInfo_f },
@@ -3073,7 +3075,7 @@ SV_ExecuteUserCommand
*/
static void SV_ExecuteClientCommand( sv_client_t *cl, const char *s )
{
ucmd_t *u;
const ucmd_t *u;
Cmd_TokenizeString( s );
@@ -3148,17 +3150,14 @@ connectionless packets.
*/
void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
{
char *args;
const char *pcmd;
char buf[MAX_SYSPATH];
int len = sizeof( buf );
const char *pcmd, *args;
// prevent flooding from banned address
if( SV_CheckIP( &from ) )
if( SV_CheckIP( &from ))
return;
MSG_Clear( msg );
MSG_ReadLong( msg );// skip the -1 marker
MSG_SeekToBit( msg, sizeof( uint32_t ) << 3, SEEK_CUR ); // skip the -1 marker
args = MSG_ReadStringLine( msg );
Cmd_TokenizeString( args );
@@ -3168,29 +3167,79 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
if( sv_log_outofband.value )
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), pcmd );
if( !Q_strcmp( pcmd, "ping" )) SV_Ping( from );
else if( !Q_strcmp( pcmd, "ack" )) SV_Ack( from );
else if( !Q_strcmp( pcmd, "info" )) SV_Info( from, Q_atoi( Cmd_Argv( 1 )));
else if( !Q_strcmp( pcmd, "bandwidth" )) SV_TestBandWidth( from );
else if( !Q_strcmp( pcmd, "getchallenge" )) SV_GetChallenge( from );
else if( !Q_strcmp( pcmd, "connect" )) SV_ConnectClient( from );
else if( !Q_strcmp( pcmd, "rcon" )) SV_RemoteCommand( from, msg );
else if( !Q_strcmp( pcmd, "netinfo" )) SV_BuildNetAnswer( from );
else if( !Q_strcmp( pcmd, "s" )) SV_AddToMaster( from, msg );
else if( !Q_strcmp( pcmd, "i" )) NET_SendPacket( NS_SERVER, 5, "\xFF\xFF\xFF\xFFj", from ); // A2A_PING
else if( SV_SourceQuery_HandleConnnectionlessPacket( pcmd, from )) { } // function handles replies
else if( !Q_strcmp( pcmd, "c" ) && sv_nat.value && NET_IsMasterAdr( from ))
if( !svs.initialized )
{
netadr_t to;
if( NET_StringToAdr( Cmd_Argv( 1 ), &to ) && !NET_IsReservedAdr( to ))
SV_Info( to, PROTOCOL_VERSION );
// only process rcon if server not initialized
if( !Q_strcmp( pcmd, C2S_RCON ))
SV_RemoteCommand( net_from, &net_message );
return;
}
else if( svgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
if( !Q_strcmp( pcmd, A2S_GOLDSRC_INFO ) || pcmd[0] == A2S_GOLDSRC_PLAYERS || pcmd[0] == A2S_GOLDSRC_RULES )
{
// user out of band message (must be handled in CL_ConnectionlessPacket)
if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, (byte*)buf );
SV_SourceQuery_HandleConnnectionlessPacket( pcmd, from );
}
else if( !Q_strcmp( pcmd, A2A_NETINFO ))
{
SV_BuildNetAnswer( from );
}
else if( !Q_strcmp( pcmd, A2A_INFO ))
{
SV_Info( from, Q_atoi( Cmd_Argv( 1 )));
}
else if( !Q_strcmp( pcmd, M2S_CHALLENGE ))
{
SV_AddToMaster( from, msg );
}
else if( !Q_strcmp( pcmd, M2S_NAT_CONNECT ))
{
SV_ConnectNatClient( from );
}
else if( !Q_strcmp( pcmd, C2S_BANDWIDTHTEST ))
{
SV_TestBandWidth( from );
}
else if( !Q_strcmp( pcmd, C2S_GETCHALLENGE ))
{
SV_GetChallenge( from );
}
else if( !Q_strcmp( pcmd, C2S_CONNECT ))
{
SV_ConnectClient( from );
}
else if( !Q_strcmp( pcmd, A2A_PING ))
{
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_ACK );
}
else if( !Q_strcmp( pcmd, A2A_GOLDSRC_PING ))
{
Netchan_OutOfBandPrint( NS_SERVER, from, A2A_GOLDSRC_ACK );
}
else if( !Q_strcmp( pcmd, C2S_RCON ))
{
SV_RemoteCommand( from, msg );
}
else if( !Q_strcmp( pcmd, A2A_ACK ) || !Q_strcmp( pcmd, A2A_GOLDSRC_ACK ))
{
SV_Ack( from );
}
else
{
char buf[MAX_SYSPATH];
int len = sizeof( buf );
if( svgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
{
// user out of band message (must be handled in CL_ConnectionlessPacket)
if( len > 0 )
Netchan_OutOfBand( NS_SERVER, from, len, (byte*)buf );
}
else
{
Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
}
}
else Con_DPrintf( S_ERROR "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args );
}
/*

View File

@@ -16,8 +16,6 @@ GNU General Public License for more details.
#include "common.h"
#include "server.h"
extern convar_t con_gamemaps;
/*
=================
SV_ClientPrintf

View File

@@ -25,8 +25,8 @@ typedef struct
byte sended[MAX_EDICTS_BYTES];
} sv_ents_t;
int c_fullsend; // just a debug counter
int c_notsend;
static int c_fullsend; // just a debug counter
static int c_notsend;
/*
=======================

View File

@@ -24,8 +24,6 @@ GNU General Public License for more details.
#include "render_api.h" // modelstate_t
#include "ref_common.h" // decals
#define ENTVARS_COUNT ARRAYSIZE( gEntvarsDescription )
// GameAPI functions declarations
static int GAME_EXPORT pfnModelIndex( const char *m );
@@ -83,7 +81,7 @@ EntvarsDescription
entavrs table for FindEntityByString
=============
*/
static TYPEDESCRIPTION gEntvarsDescription[] =
static const TYPEDESCRIPTION gEntvarsDescription[] =
{
DEFINE_ENTITY_FIELD( classname, FIELD_STRING ),
DEFINE_ENTITY_FIELD( globalname, FIELD_STRING ),
@@ -100,20 +98,6 @@ static TYPEDESCRIPTION gEntvarsDescription[] =
DEFINE_ENTITY_FIELD( noise3, FIELD_SOUNDNAME ),
};
/*
=============
SV_GetEntvarsDescription
entavrs table for FindEntityByString
=============
*/
static TYPEDESCRIPTION *SV_GetEntvarsDescirption( int number )
{
if( number < 0 || number >= ENTVARS_COUNT )
return NULL;
return &gEntvarsDescription[number];
}
/*
=============
SV_SysError
@@ -643,12 +627,16 @@ Write ambient sounds into demo
*/
void SV_RestartAmbientSounds( void )
{
// TODO: we don't know sounds state on remote server
// as it's used only for demos, maybe this could be implemented on client side?
#if !XASH_DEDICATED
soundlist_t soundInfo[256];
string curtrack, looptrack;
int i, nSounds;
int position;
if( !SV_Active( )) return;
if( !SV_Active( ) || Host_IsDedicated( ))
return;
nSounds = S_GetCurrentStaticSounds( soundInfo, 256 );
@@ -663,13 +651,12 @@ void SV_RestartAmbientSounds( void )
SV_StartSound( SV_PEntityOfEntIndex( si->entnum, true ), CHAN_STATIC, si->name, si->volume, si->attenuation, 0, si->pitch );
}
#if !XASH_DEDICATED // TODO: ???
// restart soundtrack
if( S_StreamGetCurrentState( curtrack, sizeof( curtrack ), looptrack, sizeof( looptrack ), &position ))
{
SV_StartMusic( curtrack, looptrack, position );
}
#endif
#endif // !XASH_DEDICATED
}
/*
@@ -681,31 +668,25 @@ Write all the decals into demo
*/
void SV_RestartDecals( void )
{
// TODO: similar to SV_RestartAmbientSounds, this is only used for demo recording
// and better be reimplemented on client side
#if !XASH_DEDICATED
decallist_t *list;
int decalIndex;
int modelIndex;
sizebuf_t *msg;
int i, numdecals;
if( !SV_Active( )) return;
if( !SV_Active( ) || Host_IsDedicated( ))
return;
// g-cont. add space for studiodecals if present
list = (decallist_t *)Z_Calloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
#if !XASH_DEDICATED
if( !Host_IsDedicated() )
{
numdecals = ref.dllFuncs.R_CreateDecalList( list );
numdecals = ref.dllFuncs.R_CreateDecalList( list );
// remove decals from map
ref.dllFuncs.R_ClearAllDecals();
}
else
#endif // XASH_DEDICATED
{
// we probably running a dedicated server
numdecals = 0;
}
// remove decals from map
ref.dllFuncs.R_ClearAllDecals();
// write decals into reliable datagram
msg = SV_GetReliableDatagram();
@@ -728,6 +709,7 @@ void SV_RestartDecals( void )
}
Z_Free( list );
#endif // !XASH_DEDICATED
}
/*
@@ -1508,8 +1490,8 @@ SV_FindEntityByString
*/
static edict_t *GAME_EXPORT SV_FindEntityByString( edict_t *pStartEdict, const char *pszField, const char *pszValue )
{
int index = 0, e = 0;
TYPEDESCRIPTION *desc = NULL;
int i = 0, e = 0;
const TYPEDESCRIPTION *desc = NULL;
edict_t *ed;
const char *t;
@@ -1518,10 +1500,13 @@ static edict_t *GAME_EXPORT SV_FindEntityByString( edict_t *pStartEdict, const c
if( pStartEdict ) e = NUM_FOR_EDICT( pStartEdict );
while(( desc = SV_GetEntvarsDescirption( index++ )) != NULL )
for( i = 0; i < ARRAYSIZE( gEntvarsDescription ); i++ )
{
if( !Q_strcmp( pszField, desc->fieldName ))
if( !Q_strcmp( pszField, gEntvarsDescription[i].fieldName ))
{
desc = &gEntvarsDescription[i];
break;
}
}
if( desc == NULL )
@@ -3000,24 +2985,22 @@ static void *GAME_EXPORT pfnPvEntPrivateData( edict_t *pEdict )
}
#ifdef XASH_64BIT
static struct str64_s
{
size_t maxstringarray;
qboolean allowdup;
qboolean dynamic;
char *staticstringarray;
char *pstringarray;
char *pstringarraystatic;
char *pstringbase;
char *poldstringbase;
char *plast;
qboolean dynamic;
size_t maxalloc;
size_t numdups;
size_t numoverflows;
size_t totalalloc;
} str64;
#endif
/*
==================
@@ -3028,7 +3011,7 @@ Free strings on server stop. Reset string pointer on 64 bits
*/
void SV_EmptyStringPool( void )
{
#ifdef XASH_64BIT
#if XASH_64BIT
if( str64.dynamic ) // switch only after array fill (more space for multiplayer games)
str64.pstringbase = str64.pstringarray;
else
@@ -3036,9 +3019,9 @@ void SV_EmptyStringPool( void )
str64.pstringbase = str64.poldstringbase = str64.pstringarraystatic;
str64.plast = str64.pstringbase + 1;
}
#else
#else // !XASH_64BIT
Mem_EmptyPool( svgame.stringspool );
#endif
#endif // !XASH_64BIT
}
/*
@@ -3052,7 +3035,7 @@ this helps not to lose strings that belongs to static game part
*/
void SV_SetStringArrayMode( qboolean dynamic )
{
#ifdef XASH_64BIT
#if XASH_64BIT
Con_Reportf( "%s(%d) %d\n", __func__, dynamic, str64.dynamic );
if( dynamic == str64.dynamic )
@@ -3061,11 +3044,11 @@ void SV_SetStringArrayMode( qboolean dynamic )
str64.dynamic = dynamic;
SV_EmptyStringPool();
#endif
#endif // !XASH_64BIT
}
#if XASH_AMD64 && XASH_LINUX && !XASH_ANDROID
#define USE_MMAP
#define USE_MMAP 1
#include <sys/mman.h>
#endif
@@ -3081,7 +3064,7 @@ this case need patched game dll with MAKE_STRING checking ptrdiff size
*/
static void SV_AllocStringPool( void )
{
#ifdef XASH_64BIT
#if XASH_64BIT
void *ptr = NULL;
string lenstr;
@@ -3096,7 +3079,7 @@ static void SV_AllocStringPool( void )
if( Sys_CheckParm( "-str64dup" ) )
str64.allowdup = true;
#ifdef USE_MMAP
#if USE_MMAP
{
uint flags;
size_t pagesize = sysconf( _SC_PAGESIZE );
@@ -3150,35 +3133,37 @@ static void SV_AllocStringPool( void )
ptr = str64.staticstringarray = Mem_Calloc( host.mempool, str64.maxstringarray * 2 );
}
}
#else
#else // !USE_MMAP
ptr = str64.staticstringarray = Mem_Calloc( host.mempool, str64.maxstringarray * 2 );
#endif
#endif // !USE_MMAP
str64.pstringarray = ptr;
str64.pstringarraystatic = (byte*)ptr + str64.maxstringarray;
str64.pstringbase = str64.poldstringbase = ptr;
str64.plast = (byte*)ptr + 1;
svgame.globals->pStringBase = ptr;
#else
#else // !XASH_64BIT
svgame.stringspool = Mem_AllocPool( "Server Strings" );
svgame.globals->pStringBase = "";
#endif
#endif // !XASH_64BIT
}
static void SV_FreeStringPool( void )
{
#ifdef XASH_64BIT
#if XASH_64BIT
Con_Reportf( "%s()\n", __func__ );
#ifdef USE_MMAP
#if USE_MMAP
if( str64.pstringarray != str64.staticstringarray )
munmap( str64.pstringarray, (str64.maxstringarray * 2) & ~(sysconf( _SC_PAGESIZE ) - 1) );
else
#endif
#endif // USE_MMAP
{
Mem_Free( str64.staticstringarray );
#else
}
#else // !XASH_64BIT
Mem_FreePool( &svgame.stringspool );
#endif
#endif // !XASH_64BIT
}
/*
@@ -3249,9 +3234,7 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
{
char *newString = NULL;
uint len;
#ifdef XASH_64BIT
int cmp;
#endif
if( svgame.physFuncs.pfnAllocString != NULL )
{
@@ -3267,7 +3250,7 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
return i;
}
#ifdef XASH_64BIT
#if XASH_64BIT
cmp = 1;
if( !str64.allowdup )
@@ -3305,18 +3288,18 @@ string_t GAME_EXPORT SV_AllocString( const char *szValue )
str64.maxalloc = newString - str64.pstringarray;
return newString - svgame.globals->pStringBase;
#else
#else // !XASH_64BIT
len = SV_ProcessString( NULL, szValue );
newString = Mem_Malloc( svgame.stringspool, len );
SV_ProcessString( newString, szValue );
return newString - svgame.globals->pStringBase;
#endif
#endif // !XASH_64BIT
}
void SV_PrintStr64Stats_f( void )
{
#ifdef XASH_64BIT
#if XASH_64BIT
Con_Printf( "====================\n" );
Con_Printf( "64 bit string pool statistics\n" );
Con_Printf( "====================\n" );
@@ -3325,9 +3308,9 @@ void SV_PrintStr64Stats_f( void )
Con_Printf( "maximum array usage: %lu\n", str64.maxalloc );
Con_Printf( "overflow counter: %lu\n", str64.numoverflows );
Con_Printf( "dup string counter: %lu\n", str64.numdups );
#else
#else // !XASH_64BIT
Con_Printf( "Not implemented\n" );
#endif
#endif // !XASH_64BIT
}
/*
@@ -3341,7 +3324,7 @@ string_t SV_MakeString( const char *szValue )
{
if( svgame.physFuncs.pfnMakeString != NULL )
return svgame.physFuncs.pfnMakeString( szValue );
#ifdef XASH_64BIT
#if XASH_64BIT
{
long long ptrdiff = szValue - svgame.globals->pStringBase;
if( ptrdiff > INT_MAX || ptrdiff < INT_MIN )
@@ -3349,9 +3332,9 @@ string_t SV_MakeString( const char *szValue )
else
return (int)ptrdiff;
}
#else
#else // !XASH_64BIT
return szValue - svgame.globals->pStringBase;
#endif
#endif // !XASH_64BIT
}
/*
@@ -5115,6 +5098,8 @@ void SV_SpawnEntities( const char *mapname )
void SV_UnloadProgs( void )
{
pending_cvar_t *pending_cvars_list;
if( !svgame.hInstance )
return;
@@ -5124,6 +5109,8 @@ void SV_UnloadProgs( void )
/// SV_UnloadProgs will be disabled
//Mod_ClearUserData ();
pending_cvars_list = Cvar_PrepareToUnlink( FCVAR_EXTDLL );
if( svgame.dllFuncs2.pfnGameShutdown != NULL )
svgame.dllFuncs2.pfnGameShutdown ();
@@ -5141,7 +5128,7 @@ void SV_UnloadProgs( void )
// must unlink all game cvars,
// before pointers on them will be lost...
Cvar_Unlink( FCVAR_EXTDLL );
Cvar_UnlinkPendingCvars( pending_cvars_list );
Cmd_Unlink( CMD_SERVERDLL );
SV_FreeStringPool();

View File

@@ -973,7 +973,7 @@ static void SV_GenerateTestPacket( void )
// write packet base data
MSG_Init( &svs.testpacket, "BandWidthTest", svs.testpacket_buf, maxsize );
MSG_WriteLong( &svs.testpacket, -1 );
MSG_WriteString( &svs.testpacket, "testpacket" );
MSG_WriteString( &svs.testpacket, S2C_BANDWIDTHTEST );
svs.testpacket_crcpos = svs.testpacket.pData + MSG_GetNumBytesWritten( &svs.testpacket );
MSG_WriteDword( &svs.testpacket, 0 ); // to be changed by crc
@@ -1028,6 +1028,8 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
if( !SV_InitGame( ))
return false;
Delta_Init(); // re-initialize delta
// unlock sv_cheats in local game
ClearBits( sv_cheats.flags, FCVAR_READ_ONLY );

View File

@@ -92,9 +92,9 @@ static CVAR_DEFINE_AUTO( sv_waterfriction, "1", FCVAR_SERVER|FCVAR_MOVEVARS, "ho
static CVAR_DEFINE_AUTO( sv_bounce, "1", FCVAR_SERVER|FCVAR_MOVEVARS, "bounce factor for entities with MOVETYPE_BOUNCE" );
static CVAR_DEFINE_AUTO( sv_stepsize, "18", FCVAR_SERVER|FCVAR_MOVEVARS, "how high you and NPS's can step up" );
CVAR_DEFINE_AUTO( sv_maxvelocity, "2000", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "max velocity for all things in the world" );
static CVAR_DEFINE_AUTO( sv_zmax, "4096", FCVAR_SERVER|FCVAR_MOVEVARS|FCVAR_SPONLY, "maximum viewable distance" );
static CVAR_DEFINE_AUTO( sv_zmax, "4096", FCVAR_MOVEVARS|FCVAR_SPONLY, "maximum viewable distance" );
CVAR_DEFINE_AUTO( sv_wateramp, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "world waveheight factor" );
static CVAR_DEFINE( sv_footsteps, "mp_footsteps", "1", FCVAR_SERVER|FCVAR_MOVEVARS, "world gravity value" );
static CVAR_DEFINE( sv_footsteps, "mp_footsteps", "1", FCVAR_SERVER|FCVAR_MOVEVARS, "play foot steps for players" );
CVAR_DEFINE_AUTO( sv_skyname, "desert", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "skybox name (can be dynamically changed in-game)" );
static CVAR_DEFINE_AUTO( sv_rollangle, "0", FCVAR_MOVEVARS|FCVAR_UNLOGGED|FCVAR_ARCHIVE, "how much to tilt the view when strafing" );
static CVAR_DEFINE_AUTO( sv_rollspeed, "200", FCVAR_MOVEVARS|FCVAR_UNLOGGED, "how much strafing is necessary to tilt the view" );
@@ -189,6 +189,9 @@ void SV_UpdateMovevars( qboolean initialize )
if( !initialize && !host.movevars_changed )
return;
// NOTE: this breaks Natural Selection mod on ns_machina map that uses model as sky
// it sets the value to 4000000 that even exceeds the coord limit
#if 0
// check range
if( sv_zmax.value < 256.0f ) Cvar_SetValue( "sv_zmax", 256.0f );
@@ -203,6 +206,7 @@ void SV_UpdateMovevars( qboolean initialize )
if( sv_zmax.value > 32767.0f )
Cvar_SetValue( "sv_zmax", 32767.0f );
}
#endif
svgame.movevars.gravity = sv_gravity.value;
svgame.movevars.stopspeed = sv_stopspeed.value;
@@ -385,23 +389,7 @@ static void SV_ReadPackets( void )
// check for connectionless packet (0xffffffff) first
if( MSG_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 )
{
if( !svs.initialized )
{
char *args;
const char *c;
MSG_Clear( &net_message );
MSG_ReadLong( &net_message );// skip the -1 marker
args = MSG_ReadStringLine( &net_message );
Cmd_TokenizeString( args );
c = Cmd_Argv( 0 );
if( !Q_strcmp( c, "rcon" ))
SV_RemoteCommand( net_from, &net_message );
}
else SV_ConnectionlessPacket( net_from, &net_message );
SV_ConnectionlessPacket( net_from, &net_message );
continue;
}
@@ -726,7 +714,7 @@ Master will validate challenge and this server to public list
void SV_AddToMaster( netadr_t from, sizebuf_t *msg )
{
uint challenge, challenge2, heartbeat_challenge;
char s[MAX_INFO_STRING] = "0\n"; // skip 2 bytes of header
char s[MAX_INFO_STRING] = S2M_INFO; // skip 2 bytes of header
int clients, bots;
double last_heartbeat;
const int len = sizeof( s );

View File

@@ -2146,18 +2146,18 @@ qboolean SV_InitPhysicsAPI( void )
if( svgame.physFuncs.SV_CheckFeatures != NULL )
{
// grab common engine features (it will be shared across the network)
Host_ValidateEngineFeatures( svgame.physFuncs.SV_CheckFeatures( ));
Host_ValidateEngineFeatures( ENGINE_FEATURES_MASK, svgame.physFuncs.SV_CheckFeatures( ));
}
return true;
}
// make sure what physic functions is cleared
memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs ));
Host_ValidateEngineFeatures( 0 );
Host_ValidateEngineFeatures( ENGINE_FEATURES_MASK, 0 );
return false; // just tell user about problems
}
// physic interface is missed
Host_ValidateEngineFeatures( 0 );
Host_ValidateEngineFeatures( ENGINE_FEATURES_MASK, 0 );
return true;
}

View File

@@ -16,15 +16,6 @@ GNU General Public License for more details.
#include "common.h"
#include "server.h"
#define SOURCE_QUERY_DETAILS 'T'
#define SOURCE_QUERY_DETAILS_RESPONSE 'I'
#define SOURCE_QUERY_RULES 'V'
#define SOURCE_QUERY_RULES_RESPONSE 'E'
#define SOURCE_QUERY_PLAYERS 'U'
#define SOURCE_QUERY_PLAYERS_RESPONSE 'D'
/*
==================
SV_SourceQuery_Details
@@ -41,7 +32,8 @@ static void SV_SourceQuery_Details( netadr_t from )
MSG_Init( &buf, "TSourceEngineQuery", answer, sizeof( answer ));
MSG_WriteByte( &buf, SOURCE_QUERY_DETAILS_RESPONSE );
MSG_WriteDword( &buf, 0xFFFFFFFFU );
MSG_WriteByte( &buf, S2A_GOLDSRC_INFO );
MSG_WriteByte( &buf, PROTOCOL_VERSION );
MSG_WriteString( &buf, hostname.string );
@@ -69,7 +61,7 @@ static void SV_SourceQuery_Details( netadr_t from )
MSG_WriteByte( &buf, GI->secure );
MSG_WriteString( &buf, XASH_VERSION );
Netchan_OutOfBand( NS_SERVER, from, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ));
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &buf ), MSG_GetData( &buf ), from );
}
/*
@@ -87,7 +79,8 @@ static void SV_SourceQuery_Rules( netadr_t from )
MSG_Init( &buf, "TSourceEngineQueryRules", answer, sizeof( answer ));
MSG_WriteByte( &buf, SOURCE_QUERY_RULES_RESPONSE );
MSG_WriteDword( &buf, 0xFFFFFFFFU );
MSG_WriteByte( &buf, S2A_GOLDSRC_RULES );
pos = MSG_GetNumBitsWritten( &buf );
MSG_WriteShort( &buf, 0 );
@@ -117,7 +110,7 @@ static void SV_SourceQuery_Rules( netadr_t from )
MSG_SeekToBit( &buf, pos, SEEK_SET );
MSG_WriteShort( &buf, cvar_count );
Netchan_OutOfBand( NS_SERVER, from, total, MSG_GetData( &buf ));
NET_SendPacket( NS_SERVER, total, MSG_GetData( &buf ), from );
}
}
@@ -139,7 +132,8 @@ static void SV_SourceQuery_Players( netadr_t from )
MSG_Init( &buf, "TSourceEngineQueryPlayers", answer, sizeof( answer ));
MSG_WriteByte( &buf, SOURCE_QUERY_PLAYERS_RESPONSE );
MSG_WriteDword( &buf, 0xFFFFFFFFU );
MSG_WriteByte( &buf, S2A_GOLDSRC_PLAYERS );
pos = MSG_GetNumBitsWritten( &buf );
MSG_WriteByte( &buf, 0 );
@@ -168,7 +162,7 @@ static void SV_SourceQuery_Players( netadr_t from )
MSG_SeekToBit( &buf, pos, SEEK_SET );
MSG_WriteByte( &buf, count );
Netchan_OutOfBand( NS_SERVER, from, total, MSG_GetData( &buf ));
NET_SendPacket( NS_SERVER, total, MSG_GetData( &buf ), from );
}
}
@@ -177,24 +171,19 @@ static void SV_SourceQuery_Players( netadr_t from )
SV_SourceQuery_HandleConnnectionlessPacket
==================
*/
qboolean SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from )
void SV_SourceQuery_HandleConnnectionlessPacket( const char *c, netadr_t from )
{
switch( c[0] )
if( !Q_strcmp( c, A2S_GOLDSRC_INFO ))
{
case SOURCE_QUERY_DETAILS:
SV_SourceQuery_Details( from );
return true;
case SOURCE_QUERY_RULES:
SV_SourceQuery_Rules( from );
return true;
case SOURCE_QUERY_PLAYERS:
SV_SourceQuery_Players( from );
return true;
default:
return false;
}
return false;
else switch( c[0] )
{
case A2S_GOLDSRC_RULES:
SV_SourceQuery_Rules( from );
break;
case A2S_GOLDSRC_PLAYERS:
SV_SourceQuery_Players( from );
break;
}
}

View File

@@ -82,7 +82,7 @@ typedef struct
float time;
} SAVE_LIGHTSTYLE;
void (__cdecl *pfnSaveGameComment)( char *buffer, int max_length ) = NULL;
static void (__cdecl *pfnSaveGameComment)( char *buffer, int max_length ) = NULL;
static TYPEDESCRIPTION gGameHeader[] =
{
@@ -218,7 +218,7 @@ static TYPEDESCRIPTION gTempEntvars[] =
DEFINE_ENTITY_GLOBAL_FIELD( globalname, FIELD_STRING ),
};
struct
static const struct
{
const char *mapname;
const char *titlename;
@@ -1170,41 +1170,36 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
char name[MAX_QPATH];
int i, id, version;
char *pTokenData;
decallist_t *decalList;
SAVE_CLIENT header;
decallist_t *decalList = NULL;
SAVE_CLIENT header = { 0 };
file_t *pFile;
// clearing the saving buffer to reuse
SaveClear( pSaveData );
memset( &header, 0, sizeof( header ));
// g-cont. add space for studiodecals if present
decalList = (decallist_t *)Z_Calloc( sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
header.entityCount = sv.num_static_entities;
// initialize client header
#if !XASH_DEDICATED
if( !Host_IsDedicated() )
if( !Host_IsDedicated( ))
{
header.decalCount = ref.dllFuncs.R_CreateDecalList( decalList );
}
else
#endif // XASH_DEDICATED
{
// we probably running a dedicated server
header.decalCount = 0;
}
header.entityCount = sv.num_static_entities;
// g-cont. add space for studiodecals if present
decalList = (decallist_t *)Mem_Calloc( host.mempool, sizeof( decallist_t ) * MAX_RENDER_DECALS * 2 );
if( !changelevel )
{
// sounds won't going across transition
header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS );
#if !XASH_DEDICATED
// music not reqiured to save position: it's just continue playing on a next level
S_StreamGetCurrentState( header.introTrack, sizeof( header.introTrack ), header.mainTrack, sizeof( header.mainTrack ), &header.trackPosition );
#endif
header.decalCount = ref.dllFuncs.R_CreateDecalList( decalList );
if( !changelevel ) // sounds won't going across transition
{
header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS );
// music not reqiured to save position: it's just continue playing on a next level
S_StreamGetCurrentState(
header.introTrack, sizeof( header.introTrack ),
header.mainTrack, sizeof( header.mainTrack ),
&header.trackPosition );
}
}
#endif // XASH_DEDICATED
// save viewentity to allow camera works after save\restore
if( SV_IsValidEdict( cl->pViewEntity ) && cl->pViewEntity != cl->edict )
@@ -1217,7 +1212,7 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "ClientHeader", &header, gSaveClient, ARRAYSIZE( gSaveClient ));
// store decals
for( i = 0; i < header.decalCount; i++ )
for( i = 0; decalList != NULL && i < header.decalCount; i++ )
{
// NOTE: apply landmark offset only for brush entities without origin brushes
if( pSaveData->fUseLandmark && FBitSet( decalList[i].flags, FDECAL_USE_LANDMARK ))
@@ -1225,7 +1220,9 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "DECALLIST", &decalList[i], gDecalEntry, ARRAYSIZE( gDecalEntry ));
}
Z_Free( decalList );
if( decalList )
Mem_Free( decalList );
// write client entities
for( i = 0; i < header.entityCount; i++ )
@@ -2188,6 +2185,19 @@ qboolean SV_SaveGame( const char *pName )
return SaveGameSlot( savename, comment );
}
static int SV_CompareFileTime( int ft1, int ft2 )
{
if( ft1 < ft2 )
{
return -1;
}
else if( ft1 > ft2 )
{
return 1;
}
return 0;
}
/*
==================
SV_GetLatestSave
@@ -2213,7 +2223,7 @@ const char *SV_GetLatestSave( void )
if( ft > 0 )
{
// should we use the matched?
if( !found || Host_CompareFileTime( newest, ft ) < 0 )
if( !found || SV_CompareFileTime( newest, ft ) < 0 )
{
Q_strncpy( savename, t->filenames[i], sizeof( savename ));
newest = ft;

View File

@@ -80,14 +80,24 @@ def configure(conf):
conf.env.HAVE_SDL2 = True
else:
conf.load('sdl2')
if not conf.env.HAVE_SDL2:
conf.fatal('SDL2 not available! If you want to build dedicated server, specify --dedicated')
conf.define('XASH_SDL', 2)
if conf.options.SDL3:
if not conf.env.HAVE_SDL3:
conf.fatal('SDL3 not available! If you want to build dedicated server, specify --dedicated')
conf.define('XASH_SDL', 3)
else:
if not conf.env.HAVE_SDL2:
conf.fatal('SDL2 not available! If you want to build dedicated server, specify --dedicated')
conf.define('XASH_SDL', 2)
if conf.env.DEST_OS == 'haiku':
conf.env.LIB_HAIKU = ['network']
conf.env.LIBPATH_HAIKU = ['/boot/system/lib']
if conf.env.DEST_OS == 'wasi':
conf.options.NO_ASYNC_RESOLVE = True
conf.env.append_unique('CFLAGS', '-mllvm')
conf.env.append_unique('CFLAGS', '-wasm-enable-sjlj')
if conf.options.STATIC:
conf.env.STATIC = True
conf.define('XASH_NO_LIBDL',1)
@@ -118,7 +128,6 @@ def configure(conf):
conf.define_cond('XASH_ENABLE_MAIN', conf.env.DISABLE_LAUNCHER)
conf.define_cond('XASH_NO_ASYNC_NS_RESOLVE', conf.options.NO_ASYNC_RESOLVE)
conf.define_cond('SUPPORT_BSP2_FORMAT', conf.options.SUPPORT_BSP2_FORMAT)
conf.define_cond('XASH_64BIT', conf.env.DEST_SIZEOF_VOID_P != 4)
conf.define_cond('DBGHELP', conf.env.DEST_OS == 'win32')
conf.define_cond('PSAPI_VERSION', conf.env.DEST_OS == 'win32') # will be defined as 1
@@ -172,13 +181,12 @@ def build(bld):
source += bld.path.ant_glob(['platform/misc/lib_static.c'])
is_cxx_link = True
if bld.env.HAVE_SDL2:
libs.append('SDL2')
if bld.env.HAVE_SDL2 or bld.env.HAVE_SDL3:
libs.append('SDL3' if bld.env.HAVE_SDL3 else 'SDL2')
source += bld.path.ant_glob(['platform/sdl/*.c'])
if bld.env.MAGX:
libs.append('MAGX')
source += bld.path.ant_glob(['platform/magx/*.cpp'])
is_cxx_link = True
if bld.env.DEST_OS == 'android':
@@ -222,43 +230,44 @@ def build(bld):
'client/*.c',
'client/vgui/*.c',
'client/avi/*.c'])
libs += ['opus']
is_cxx_link = True
libs += ['opus', 'bzip2', 'MultiEmulator']
includes = ['server', 'client', 'client/vgui' ]
rpath = bld.env.DEFAULT_RPATH
# Switch and PSVita have custom parameters
if bld.env.DEST_OS in ['nswitch', 'psvita']:
bld(source = source,
target = 'xash',
features = 'c cxxprogram',
includes = includes,
use = libs,
install_path = None,
nro_install_path = bld.env.BINDIR,
nacp = 'platform/nswitch/xash3d-fwgs.nacp',
icon = 'platform/nswitch/icon.jpg',
sce_sys = 'platform/psvita/sce_sys',
title_id = 'XASH10000',
app_name = 'xash3d-fwgs'
)
else:
# always build as shared library on Android
if bld.env.DISABLE_LAUNCHER and bld.env.DEST_OS != "android":
install_path = bld.env.BINDIR
program = 'cxxprogram' if is_cxx_link else 'cprogram'
if bld.env.STATIC:
program += '_static'
features = ['c', program]
rpath = None
install_path = None
features = 'cxx c cxxprogram cprogram'
# Always build as shared library on Android
elif bld.env.DISABLE_LAUNCHER and bld.env.DEST_OS != 'android':
install_path = bld.env.BINDIR
if bld.env.STATIC:
features = 'cxx c cxxprogram_static cprogram_static'
elif is_cxx_link:
features = 'cxx c cxxprogram cprogram'
else:
install_path = bld.env.LIBDIR
features = ['c', 'cxxshlib' if is_cxx_link else 'cshlib']
features = 'c cprogram'
else:
install_path = bld.env.LIBDIR
if is_cxx_link:
features = 'cxx c cxxshlib cshlib'
else:
features = 'c cshlib'
bld(source = source,
target = 'xash',
features = features,
includes = includes,
use = libs,
install_path = install_path,
subsystem = bld.env.MSVC_SUBSYSTEM,
rpath = bld.env.DEFAULT_RPATH,
)
bld(source = source,
target = 'xash',
features = features,
includes = 'server client client/vgui',
use = libs,
install_path = install_path,
nro_install_path = bld.env.BINDIR,
nacp = 'platform/nswitch/xash3d-fwgs.nacp',
icon = 'platform/nswitch/icon.jpg',
sce_sys = 'platform/psvita/sce_sys',
title_id = 'XASH10000',
app_name = 'xash3d-fwgs',
subsystem = bld.env.MSVC_SUBSYSTEM,
rpath = rpath,
)

1
filesystem/exports.txt Normal file
View File

@@ -0,0 +1 @@
GetFSAPI

View File

@@ -25,7 +25,7 @@ def build(bld):
libs += [ 'public', 'ANDROID' ]
bld.shlib(target = 'filesystem_stdio',
features = 'cxx seq',
features = 'seq',
source = bld.path.ant_glob(['*.c', '*.cpp']),
use = libs,
install_path = bld.env.LIBDIR,

View File

@@ -30,9 +30,8 @@ def build(bld):
if bld.env.DEST_OS == 'linux':
bld.env.LDFLAGS += ['-Wl,--no-as-needed', '-lm']
bld(source = source,
bld.program(source = source,
target = 'xash3d', # hl.exe
features = 'c cxx cxxprogram',
use = 'sdk_includes DL USER32 SHELL32 werror',
rpath = bld.env.DEFAULT_RPATH,
install_path = bld.env.BINDIR,

View File

@@ -216,6 +216,7 @@ typedef struct playermove_s
pmtrace_t (*PM_PlayerTraceEx) (float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ));
int (*PM_TestPlayerPositionEx) (float *pos, pmtrace_t *ptrace, int (*pfnIgnore)( physent_t *pe ));
struct pmtrace_s *(*PM_TraceLineEx)( float *start, float *end, int flags, int usehulll, int (*pfnIgnore)( physent_t *pe ));
struct msurface_s *(*PM_TraceSurface)( int ground, float *vstart, float *vend );
struct msurface_s *(*PM_TraceSurface)( int ground, float *vstart, float *vend ); // Xash3D-specific
} playermove_t;
#endif//PM_DEFS_H

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