mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
484 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68f1a8bdc2 | ||
|
|
da1669ddf7 | ||
|
|
67af41cce8 | ||
|
|
e2c96e62e1 | ||
|
|
2ecae442fc | ||
|
|
a1060b0eb5 | ||
|
|
ddd8de888f | ||
|
|
a758dffbc1 | ||
|
|
87775faeca | ||
|
|
ef0fc46ed8 | ||
|
|
138b4fa247 | ||
|
|
47d1f3459c | ||
|
|
4712aae834 | ||
|
|
2900ee1cde | ||
|
|
c6c4178dd2 | ||
|
|
a3ce0e6b1b | ||
|
|
0b1ad3b7f0 | ||
|
|
37fb46f092 | ||
|
|
bc8bf9a9fb | ||
|
|
9e28c98911 | ||
|
|
0a1269d52d | ||
|
|
2e5bc31c9e | ||
|
|
1b335fd945 | ||
|
|
0c8b2d007a | ||
|
|
9ee1b32e2d | ||
|
|
953ad98a16 | ||
|
|
1357057bd8 | ||
|
|
35c9323de6 | ||
|
|
13a0afef06 | ||
|
|
c7ad8e4bf6 | ||
|
|
f1754bdd5f | ||
|
|
c462a1c500 | ||
|
|
0bba184994 | ||
|
|
178602ea1f | ||
|
|
2eb8f88a20 | ||
|
|
96d11df06c | ||
|
|
950d210ec5 | ||
|
|
55c1bddac5 | ||
|
|
ac50c762d7 | ||
|
|
5c2ab150b3 | ||
|
|
0870536405 | ||
|
|
b47ede477a | ||
|
|
eef5cc17b3 | ||
|
|
ad2191333d | ||
|
|
a85cac497d | ||
|
|
e0c69d7df5 | ||
|
|
ff3d91ceb4 | ||
|
|
5777431577 | ||
|
|
cd86f80203 | ||
|
|
8c885d3f37 | ||
|
|
dddb46a6d0 | ||
|
|
6b0f378c5b | ||
|
|
9dd7f37d42 | ||
|
|
9f10fb6472 | ||
|
|
64dbccb9bd | ||
|
|
9a432a5a13 | ||
|
|
842e494fa6 | ||
|
|
7fc9ee154a | ||
|
|
5f84010c2a | ||
|
|
3dcd6cb80b | ||
|
|
79e94bf766 | ||
|
|
3de370f3d5 | ||
|
|
c84d2f4624 | ||
|
|
380a9f7a6f | ||
|
|
a6c7b67d0d | ||
|
|
c13c1f2577 | ||
|
|
151405618f | ||
|
|
70e11cc309 | ||
|
|
7619824d80 | ||
|
|
f3d181b5ee | ||
|
|
55055a70f0 | ||
|
|
22d3ba674e | ||
|
|
ac487a2133 | ||
|
|
4da3a14adc | ||
|
|
69ec810ed0 | ||
|
|
2df01316ce | ||
|
|
3a67aefee2 | ||
|
|
d114dffcb4 | ||
|
|
7bb5d9a67a | ||
|
|
a6b1e57ae1 | ||
|
|
c70c13eb5c | ||
|
|
d905ea354e | ||
|
|
99cec81894 | ||
|
|
5d5bccf1bb | ||
|
|
6fcf0a77af | ||
|
|
e7477c0abf | ||
|
|
85540855c3 | ||
|
|
2dc220b42f | ||
|
|
2d6cadbf1b | ||
|
|
340871e03a | ||
|
|
e222a74960 | ||
|
|
ab499d5095 | ||
|
|
a5f7027229 | ||
|
|
bf5cf897e2 | ||
|
|
d33c1af549 | ||
|
|
677464d04d | ||
|
|
d2d6ed8bd4 | ||
|
|
bd2a44dbdd | ||
|
|
e9ee4beb9f | ||
|
|
3b3f057f6f | ||
|
|
a9dec51e59 | ||
|
|
257312ad7c | ||
|
|
6ee8a2dfa7 | ||
|
|
75c5e9cfa7 | ||
|
|
1a94f2b585 | ||
|
|
f0b4c42c68 | ||
|
|
9be061735f | ||
|
|
6bfa525080 | ||
|
|
8fcaf18897 | ||
|
|
f558cde266 | ||
|
|
b508a33f5d | ||
|
|
b4db99006b | ||
|
|
8994f079a5 | ||
|
|
b2d184cfa5 | ||
|
|
92dc92379f | ||
|
|
2a6862ceb9 | ||
|
|
4c569e1d5f | ||
|
|
4420ffd49e | ||
|
|
fb7f57cf6a | ||
|
|
8be3bdac5d | ||
|
|
2785376bd3 | ||
|
|
d6e77e531d | ||
|
|
e686b1410d | ||
|
|
2c23a1e0a0 | ||
|
|
47eb9e8c8f | ||
|
|
712b354421 | ||
|
|
18ef4922de | ||
|
|
274f9d5846 | ||
|
|
f6fa085fe4 | ||
|
|
9ab0f04ba5 | ||
|
|
fb7854f1ef | ||
|
|
1086c31503 | ||
|
|
3a47248a09 | ||
|
|
71a333261b | ||
|
|
5ea2e295c1 | ||
|
|
1fc7547a53 | ||
|
|
a7d63649f8 | ||
|
|
2f26fcdc2a | ||
|
|
107d4cdd61 | ||
|
|
52f9aad4d0 | ||
|
|
7bb5175084 | ||
|
|
dd570b616b | ||
|
|
943a30af04 | ||
|
|
eabed60e56 | ||
|
|
f793413a79 | ||
|
|
f4a3b8571d | ||
|
|
da6586b847 | ||
|
|
4a5f34089d | ||
|
|
90da9659d1 | ||
|
|
2e30acf611 | ||
|
|
5554d13f7f | ||
|
|
a5ef33b302 | ||
|
|
9a2588f7eb | ||
|
|
cac5852e68 | ||
|
|
d52d50e283 | ||
|
|
6911da8581 | ||
|
|
e70f9a67b8 | ||
|
|
173aa7333a | ||
|
|
2396b2d4db | ||
|
|
6120c0daec | ||
|
|
790f9bde54 | ||
|
|
7a469fb481 | ||
|
|
d4a2011a59 | ||
|
|
9165832caf | ||
|
|
d274a5c13c | ||
|
|
e6bd15c68b | ||
|
|
38bef99f98 | ||
|
|
95ff9e7165 | ||
|
|
2fddbdddee | ||
|
|
465e812ed9 | ||
|
|
3b1fb79a85 | ||
|
|
0f8f35b415 | ||
|
|
a133b1c2a9 | ||
|
|
fa74acb5f0 | ||
|
|
836b4c358f | ||
|
|
982e32d108 | ||
|
|
024a335505 | ||
|
|
963cbf61e4 | ||
|
|
6d98d2c7c3 | ||
|
|
64726f13e1 | ||
|
|
85dfaaa2c2 | ||
|
|
42a915b04a | ||
|
|
42a8aa6c66 | ||
|
|
56464d3291 | ||
|
|
aed96ee753 | ||
|
|
a937320c65 | ||
|
|
a81a0cb059 | ||
|
|
5af9511505 | ||
|
|
14ae9b312d | ||
|
|
2d3e5c2e0b | ||
|
|
17950fec3e | ||
|
|
2009140da8 | ||
|
|
2a394eee62 | ||
|
|
09a7585643 | ||
|
|
a09084ceba | ||
|
|
147e5dceff | ||
|
|
3510afd30b | ||
|
|
d3586c2143 | ||
|
|
56ba2325c1 | ||
|
|
b77a4ed3a1 | ||
|
|
9b86c3127a | ||
|
|
0da7ffe45f | ||
|
|
30b78d9559 | ||
|
|
c16abc0b85 | ||
|
|
708c691cdb | ||
|
|
31c20ac4d8 | ||
|
|
1458014a29 | ||
|
|
1c84a5c8ad | ||
|
|
6728b843f7 | ||
|
|
1b55104d51 | ||
|
|
76978bfd47 | ||
|
|
6ff3231dab | ||
|
|
64716e6b42 | ||
|
|
a1191eb4ab | ||
|
|
166bed732e | ||
|
|
02cb12e4b4 | ||
|
|
159467ad44 | ||
|
|
2a006086c5 | ||
|
|
e0dc1eec93 | ||
|
|
ab130ee92c | ||
|
|
dabbe09918 | ||
|
|
296a7ac11d | ||
|
|
6bbf08893e | ||
|
|
f8b958738a | ||
|
|
1b4427f13f | ||
|
|
e55577fd26 | ||
|
|
c42960ec2a | ||
|
|
c033d4b65c | ||
|
|
dc6f03b4e4 | ||
|
|
b6967a432a | ||
|
|
7d0467863c | ||
|
|
a0b72d3995 | ||
|
|
5fe4b867f3 | ||
|
|
40af058406 | ||
|
|
b4376a6a8c | ||
|
|
457422c679 | ||
|
|
080eba948f | ||
|
|
eff86defd9 | ||
|
|
fcb463d400 | ||
|
|
efee8149e2 | ||
|
|
bc32f37fce | ||
|
|
58bfa247a4 | ||
|
|
59b9b31604 | ||
|
|
844af709c0 | ||
|
|
bb6e2d6885 | ||
|
|
6243dc7913 | ||
|
|
45c4362ae6 | ||
|
|
a0230b7e00 | ||
|
|
768755c31a | ||
|
|
3088c7f198 | ||
|
|
c8469071bf | ||
|
|
115fc301b5 | ||
|
|
bc449b8e95 | ||
|
|
74bbc0fe7e | ||
|
|
c73fa3d7a6 | ||
|
|
5694610478 | ||
|
|
ec107dfba5 | ||
|
|
64aa476330 | ||
|
|
42f6719e8d | ||
|
|
244b9dc02b | ||
|
|
fe3644a417 | ||
|
|
e18b61e041 | ||
|
|
d054782693 | ||
|
|
d56e53a347 | ||
|
|
3503c721ac | ||
|
|
0fab5f07d0 | ||
|
|
b0d12f8bf9 | ||
|
|
9fe58aaabc | ||
|
|
03c8ea14cc | ||
|
|
260edc2a08 | ||
|
|
b41591a527 | ||
|
|
4e9481451b | ||
|
|
95b48da37d | ||
|
|
1b36785177 | ||
|
|
8bc76e3d58 | ||
|
|
1a5e2b907d | ||
|
|
3717e5c2e0 | ||
|
|
33a1416199 | ||
|
|
ff4221fbe7 | ||
|
|
486bca82e8 | ||
|
|
611d07fc16 | ||
|
|
f7e12586cf | ||
|
|
f62aa051c8 | ||
|
|
2b6b898102 | ||
|
|
1dd0444531 | ||
|
|
ba9eb01c1f | ||
|
|
73a8144e75 | ||
|
|
6aef422de6 | ||
|
|
5f4b8b60cb | ||
|
|
3256236ba2 | ||
|
|
b102727320 | ||
|
|
3434005e66 | ||
|
|
b3026a7991 | ||
|
|
0a051832a8 | ||
|
|
2dbafbda02 | ||
|
|
240b6fb6f2 | ||
|
|
4163d3655a | ||
|
|
2c7bf49fc9 | ||
|
|
739592e50d | ||
|
|
393e31e509 | ||
|
|
a1dceacc8f | ||
|
|
cf26c87872 | ||
|
|
21195b3491 | ||
|
|
3f66f6a6a5 | ||
|
|
daae4f2f80 | ||
|
|
4e2708c1ac | ||
|
|
d57d8e0d5d | ||
|
|
9577a6af21 | ||
|
|
107a6aed01 | ||
|
|
2c2045d413 | ||
|
|
30fe471d2b | ||
|
|
5ab6979633 | ||
|
|
ec5e9cb6e3 | ||
|
|
f4b4546197 | ||
|
|
f047749e61 | ||
|
|
87840ce91d | ||
|
|
bf31e9f634 | ||
|
|
f86d84daed | ||
|
|
41ed920d35 | ||
|
|
df23ddb545 | ||
|
|
767556ccad | ||
|
|
f9dab2ad19 | ||
|
|
66cb3a6120 | ||
|
|
7672a370da | ||
|
|
870e47ed03 | ||
|
|
32d4bdb80f | ||
|
|
929dfd2c71 | ||
|
|
f437af6451 | ||
|
|
413a0fb2e5 | ||
|
|
793adadb06 | ||
|
|
999b43b89f | ||
|
|
bd60c88c7d | ||
|
|
23b9a2eddf | ||
|
|
0b57d97c8c | ||
|
|
6255293dd4 | ||
|
|
04136d95a3 | ||
|
|
40aa29e42a | ||
|
|
a709f30da9 | ||
|
|
0796c14e79 | ||
|
|
a9c0a4be23 | ||
|
|
3e1209d3a4 | ||
|
|
caf14c1b7c | ||
|
|
27f7d2c8d2 | ||
|
|
8ee430eda2 | ||
|
|
484e4cb225 | ||
|
|
b080ad9954 | ||
|
|
f6625d9188 | ||
|
|
1eb2816bc4 | ||
|
|
077be5aaf3 | ||
|
|
d59875f114 | ||
|
|
e89191ed39 | ||
|
|
ea21438637 | ||
|
|
0d2e8333e8 | ||
|
|
338399e622 | ||
|
|
27cab8aad5 | ||
|
|
1545a49b4c | ||
|
|
3ca15250e8 | ||
|
|
6cbac51731 | ||
|
|
e310c666b1 | ||
|
|
677b0170aa | ||
|
|
9150b770e4 | ||
|
|
2ad6511c31 | ||
|
|
0848f28d83 | ||
|
|
5d9bc950ce | ||
|
|
714da79395 | ||
|
|
823fe9ebbd | ||
|
|
4bf72b5383 | ||
|
|
51945f002b | ||
|
|
bcca9387de | ||
|
|
b8417fa46d | ||
|
|
85b0699288 | ||
|
|
6c03fb0226 | ||
|
|
a084dea07c | ||
|
|
2e0fc3e4c1 | ||
|
|
24f4d410ce | ||
|
|
052e0445ab | ||
|
|
758c908d5a | ||
|
|
3917c2589d | ||
|
|
f4a77308ec | ||
|
|
103b9724f9 | ||
|
|
75a315ecf0 | ||
|
|
63b3b9ef6d | ||
|
|
a6c2cfe89b | ||
|
|
5120657386 | ||
|
|
e754de46d1 | ||
|
|
5d718aa0d6 | ||
|
|
55fcbc8880 | ||
|
|
e19aa001b2 | ||
|
|
b447ea9c18 | ||
|
|
13274655d4 | ||
|
|
3723ac60ef | ||
|
|
da578f47f1 | ||
|
|
433e7de686 | ||
|
|
e18e9ae2ea | ||
|
|
27d5123a61 | ||
|
|
89b9f9ffe2 | ||
|
|
a17b8aaa13 | ||
|
|
e210969612 | ||
|
|
1208356b92 | ||
|
|
d7cd74fe2f | ||
|
|
31b63e9939 | ||
|
|
b99c2c2df1 | ||
|
|
94d3eff9ce | ||
|
|
b78e9961c6 | ||
|
|
b0704ca5d6 | ||
|
|
31c0934108 | ||
|
|
37083c8aef | ||
|
|
af23b0c67b | ||
|
|
a9e83fb9cf | ||
|
|
51126e1691 | ||
|
|
dd410a2de5 | ||
|
|
7ccb0b5c02 | ||
|
|
7f3e62e456 | ||
|
|
fcfc29d7ea | ||
|
|
2f3429a144 | ||
|
|
20782693f4 | ||
|
|
0cfb354374 | ||
|
|
9be5b7c6c9 | ||
|
|
e7653d2ea6 | ||
|
|
1494887e29 | ||
|
|
42dab2b1a5 | ||
|
|
36a0c1fb17 | ||
|
|
60c6767337 | ||
|
|
75451cc7fa | ||
|
|
db10035d9d | ||
|
|
de21d845ec | ||
|
|
320f8466e6 | ||
|
|
f3208e95b2 | ||
|
|
ea34bc8652 | ||
|
|
3daf014af8 | ||
|
|
ca9d3d262a | ||
|
|
a08f5e439d | ||
|
|
8f6771dff4 | ||
|
|
cd47c6b5b3 | ||
|
|
1f4f3d7fda | ||
|
|
e81b5144b3 | ||
|
|
9ec1caed53 | ||
|
|
ca3b4a9d7f | ||
|
|
87ac217887 | ||
|
|
213650db8f | ||
|
|
ac46164a6e | ||
|
|
6d12d84e94 | ||
|
|
2a18cde60c | ||
|
|
35783bcec2 | ||
|
|
1677835b45 | ||
|
|
2f2780cb1b | ||
|
|
95b134b5a6 | ||
|
|
f60e856f35 | ||
|
|
2ec0d25d85 | ||
|
|
fcd0982524 | ||
|
|
6881ee742d | ||
|
|
f070bbef3c | ||
|
|
dd8c66d90e | ||
|
|
f995d055b5 | ||
|
|
fed65dd497 | ||
|
|
c896425ad9 | ||
|
|
4107bd4e0f | ||
|
|
156b2b2b10 | ||
|
|
13a063bf7d | ||
|
|
ef786b7d79 | ||
|
|
5c0c1b1226 | ||
|
|
d041b2aa27 | ||
|
|
f6d489e038 | ||
|
|
d34fedea69 | ||
|
|
80b3f90091 | ||
|
|
2a4fafc3f9 | ||
|
|
9b3ccf5f04 | ||
|
|
f59ac2360a | ||
|
|
ff21fb42e6 | ||
|
|
288cac69de | ||
|
|
2640b6d869 | ||
|
|
d8910b0e38 | ||
|
|
049bed555e | ||
|
|
fe5944720b | ||
|
|
665c46b281 | ||
|
|
975ab6785e | ||
|
|
6fa4dbfba2 | ||
|
|
0506a1dfce | ||
|
|
908a9930e6 | ||
|
|
7d7e72196b | ||
|
|
7cc67157e5 | ||
|
|
b7ff9c7a24 | ||
|
|
aab1fa1ba2 | ||
|
|
effeba2f44 |
27
.cirrus.yml
27
.cirrus.yml
@@ -1,32 +1,7 @@
|
||||
task:
|
||||
# Seems packages for it were removed from the mirrors
|
||||
# name: freebsd-12-amd64
|
||||
# freebsd_instance:
|
||||
# image_family: freebsd-12-4
|
||||
# setup_script:
|
||||
# - pkg update
|
||||
# - pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
# - git submodule update --init --recursive
|
||||
# test_script:
|
||||
# - ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
# - ./scripts/cirrus/build_freebsd.sh full
|
||||
|
||||
task:
|
||||
name: freebsd-13-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-2
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
- ./scripts/cirrus/build_freebsd.sh full
|
||||
|
||||
task:
|
||||
name: freebsd-14-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-0-snap
|
||||
image_family: freebsd-14-0
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
|
||||
360
.editorconfig
360
.editorconfig
@@ -1,9 +1,365 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
# this file is just a suggestion, you might follow it, you might not
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = latin1
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
|
||||
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
|
||||
|
||||
# Visual C++ Formatting settings
|
||||
cpp_indent_braces = false
|
||||
cpp_indent_multi_line_relative_to = innermost_parenthesis
|
||||
cpp_indent_within_parentheses = indent
|
||||
cpp_indent_preserve_within_parentheses = true
|
||||
cpp_indent_case_contents = true
|
||||
cpp_indent_case_labels = false
|
||||
cpp_indent_case_contents_when_block = false
|
||||
cpp_indent_lambda_braces_when_parameter = true
|
||||
cpp_indent_goto_labels = one_left
|
||||
cpp_indent_preprocessor = leftmost_column
|
||||
cpp_indent_access_specifiers = false
|
||||
cpp_indent_namespace_contents = true
|
||||
cpp_indent_preserve_comments = false
|
||||
cpp_new_line_before_open_brace_namespace = new_line
|
||||
cpp_new_line_before_open_brace_type = new_line
|
||||
cpp_new_line_before_open_brace_function = new_line
|
||||
cpp_new_line_before_open_brace_block = new_line
|
||||
cpp_new_line_before_open_brace_lambda = new_line
|
||||
cpp_new_line_scope_braces_on_separate_lines = true
|
||||
cpp_new_line_close_brace_same_line_empty_type = false
|
||||
cpp_new_line_close_brace_same_line_empty_function = false
|
||||
cpp_new_line_before_catch = true
|
||||
cpp_new_line_before_else = true
|
||||
cpp_new_line_before_while_in_do_while = false
|
||||
cpp_space_before_function_open_parenthesis = remove
|
||||
cpp_space_within_parameter_list_parentheses = true
|
||||
cpp_space_between_empty_parameter_list_parentheses = true
|
||||
cpp_space_after_keywords_in_control_flow_statements = false
|
||||
cpp_space_within_control_flow_statement_parentheses = true
|
||||
cpp_space_before_lambda_open_parenthesis = false
|
||||
cpp_space_within_cast_parentheses = false
|
||||
cpp_space_after_cast_close_parenthesis = false
|
||||
cpp_space_within_expression_parentheses = true
|
||||
cpp_space_before_block_open_brace = true
|
||||
cpp_space_between_empty_braces = true
|
||||
cpp_space_before_initializer_list_open_brace = false
|
||||
cpp_space_within_initializer_list_braces = true
|
||||
cpp_space_preserve_in_initializer_list = true
|
||||
cpp_space_before_open_square_bracket = false
|
||||
cpp_space_within_square_brackets = false
|
||||
cpp_space_before_empty_square_brackets = false
|
||||
cpp_space_between_empty_square_brackets = false
|
||||
cpp_space_group_square_brackets = true
|
||||
cpp_space_within_lambda_brackets = false
|
||||
cpp_space_between_empty_lambda_brackets = false
|
||||
cpp_space_before_comma = false
|
||||
cpp_space_after_comma = true
|
||||
cpp_space_remove_around_member_operators = true
|
||||
cpp_space_before_inheritance_colon = true
|
||||
cpp_space_before_constructor_colon = true
|
||||
cpp_space_remove_before_semicolon = true
|
||||
cpp_space_after_semicolon = true
|
||||
cpp_space_remove_around_unary_operator = true
|
||||
cpp_space_around_binary_operator = insert
|
||||
cpp_space_around_assignment_operator = insert
|
||||
cpp_space_pointer_reference_alignment = right
|
||||
cpp_space_around_ternary_operator = insert
|
||||
cpp_use_unreal_engine_macro_formatting = true
|
||||
cpp_wrap_preserve_blocks = one_liners
|
||||
|
||||
# IDEA settings
|
||||
ij_c_add_brief_tag = false
|
||||
ij_c_add_getter_prefix = true
|
||||
ij_c_add_setter_prefix = true
|
||||
ij_c_align_dictionary_pair_values = false
|
||||
ij_c_align_group_field_declarations = false
|
||||
ij_c_align_init_list_in_columns = true
|
||||
ij_c_align_multiline_array_initializer_expression = false
|
||||
ij_c_align_multiline_assignment = false
|
||||
ij_c_align_multiline_binary_operation = false
|
||||
ij_c_align_multiline_chained_methods = false
|
||||
ij_c_align_multiline_for = true
|
||||
ij_c_align_multiline_ternary_operation = false
|
||||
ij_c_array_initializer_comma_on_next_line = false
|
||||
ij_c_array_initializer_new_line_after_left_brace = false
|
||||
ij_c_array_initializer_right_brace_on_new_line = false
|
||||
ij_c_array_initializer_wrap = off
|
||||
ij_c_assignment_wrap = off
|
||||
ij_c_binary_operation_sign_on_next_line = false
|
||||
ij_c_binary_operation_wrap = off
|
||||
ij_c_blank_lines_after_class_header = 0
|
||||
ij_c_blank_lines_after_imports = 1
|
||||
ij_c_blank_lines_around_class = 1
|
||||
ij_c_blank_lines_around_field = 0
|
||||
ij_c_blank_lines_around_field_in_interface = 0
|
||||
ij_c_blank_lines_around_method = 1
|
||||
ij_c_blank_lines_around_method_in_interface = 1
|
||||
ij_c_blank_lines_around_namespace = 0
|
||||
ij_c_blank_lines_around_properties_in_declaration = 0
|
||||
ij_c_blank_lines_around_properties_in_interface = 0
|
||||
ij_c_blank_lines_before_imports = 1
|
||||
ij_c_blank_lines_before_method_body = 0
|
||||
ij_c_block_brace_placement = next_line
|
||||
ij_c_block_brace_style = next_line
|
||||
ij_c_block_comment_at_first_column = true
|
||||
ij_c_catch_on_new_line = false
|
||||
ij_c_class_brace_style = next_line
|
||||
ij_c_class_constructor_init_list_align_multiline = true
|
||||
ij_c_class_constructor_init_list_comma_on_next_line = false
|
||||
ij_c_class_constructor_init_list_new_line_after_colon = never
|
||||
ij_c_class_constructor_init_list_new_line_before_colon = if_long
|
||||
ij_c_class_constructor_init_list_wrap = normal
|
||||
ij_c_copy_is_deep = false
|
||||
ij_c_create_interface_for_categories = true
|
||||
ij_c_declare_generated_methods = true
|
||||
ij_c_description_include_member_names = true
|
||||
ij_c_discharged_short_ternary_operator = false
|
||||
ij_c_do_not_add_breaks = false
|
||||
ij_c_do_while_brace_force = never
|
||||
ij_c_else_on_new_line = false
|
||||
ij_c_enum_constants_comma_on_next_line = false
|
||||
ij_c_enum_constants_wrap = off
|
||||
ij_c_for_brace_force = never
|
||||
ij_c_for_statement_new_line_after_left_paren = false
|
||||
ij_c_for_statement_right_paren_on_new_line = false
|
||||
ij_c_for_statement_wrap = off
|
||||
ij_c_function_brace_placement = next_line
|
||||
ij_c_function_call_arguments_align_multiline = true
|
||||
ij_c_function_call_arguments_align_multiline_pars = false
|
||||
ij_c_function_call_arguments_comma_on_next_line = false
|
||||
ij_c_function_call_arguments_new_line_after_lpar = false
|
||||
ij_c_function_call_arguments_new_line_before_rpar = false
|
||||
ij_c_function_call_arguments_wrap = normal
|
||||
ij_c_function_non_top_after_return_type_wrap = normal
|
||||
ij_c_function_parameters_align_multiline = true
|
||||
ij_c_function_parameters_align_multiline_pars = false
|
||||
ij_c_function_parameters_comma_on_next_line = false
|
||||
ij_c_function_parameters_new_line_after_lpar = false
|
||||
ij_c_function_parameters_new_line_before_rpar = false
|
||||
ij_c_function_parameters_wrap = normal
|
||||
ij_c_function_top_after_return_type_wrap = normal
|
||||
ij_c_generate_additional_eq_operators = true
|
||||
ij_c_generate_additional_rel_operators = true
|
||||
ij_c_generate_class_constructor = true
|
||||
ij_c_generate_comparison_operators_use_std_tie = false
|
||||
ij_c_generate_instance_variables_for_properties = ask
|
||||
ij_c_generate_operators_as_members = true
|
||||
ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT}
|
||||
ij_c_if_brace_force = never
|
||||
ij_c_in_line_short_ternary_operator = true
|
||||
ij_c_indent_block_comment = true
|
||||
ij_c_indent_c_struct_members = 4
|
||||
ij_c_indent_case_from_switch = true
|
||||
ij_c_indent_class_members = 4
|
||||
ij_c_indent_directive_as_code = false
|
||||
ij_c_indent_implementation_members = 0
|
||||
ij_c_indent_inside_code_block = 4
|
||||
ij_c_indent_interface_members = 0
|
||||
ij_c_indent_interface_members_except_ivars_block = false
|
||||
ij_c_indent_namespace_members = 4
|
||||
ij_c_indent_preprocessor_directive = 0
|
||||
ij_c_indent_visibility_keywords = 0
|
||||
ij_c_insert_override = true
|
||||
ij_c_insert_virtual_with_override = false
|
||||
ij_c_introduce_auto_consts = false
|
||||
ij_c_introduce_auto_vars = false
|
||||
ij_c_introduce_const_params = false
|
||||
ij_c_introduce_const_vars = false
|
||||
ij_c_introduce_constexpr_consts = false
|
||||
ij_c_introduce_generate_property = false
|
||||
ij_c_introduce_generate_synthesize = true
|
||||
ij_c_introduce_globals_to_header = true
|
||||
ij_c_introduce_prop_to_private_category = false
|
||||
ij_c_introduce_static_consts = true
|
||||
ij_c_introduce_use_ns_types = false
|
||||
ij_c_ivars_prefix = _
|
||||
ij_c_ivars_suffix =
|
||||
ij_c_keep_blank_lines_before_end = 2
|
||||
ij_c_keep_blank_lines_before_right_brace = 2
|
||||
ij_c_keep_blank_lines_in_code = 2
|
||||
ij_c_keep_blank_lines_in_declarations = 2
|
||||
ij_c_keep_case_expressions_in_one_line = false
|
||||
ij_c_keep_control_statement_in_one_line = false
|
||||
ij_c_keep_directive_at_first_column = true
|
||||
ij_c_keep_first_column_comment = false
|
||||
ij_c_keep_line_breaks = true
|
||||
ij_c_keep_nested_namespaces_in_one_line = false
|
||||
ij_c_keep_simple_blocks_in_one_line = false
|
||||
ij_c_keep_simple_methods_in_one_line = false
|
||||
ij_c_keep_structures_in_one_line = false
|
||||
ij_c_lambda_capture_list_align_multiline = false
|
||||
ij_c_lambda_capture_list_align_multiline_bracket = false
|
||||
ij_c_lambda_capture_list_comma_on_next_line = false
|
||||
ij_c_lambda_capture_list_new_line_after_lbracket = false
|
||||
ij_c_lambda_capture_list_new_line_before_rbracket = false
|
||||
ij_c_lambda_capture_list_wrap = off
|
||||
ij_c_line_comment_add_space = false
|
||||
ij_c_line_comment_at_first_column = true
|
||||
ij_c_method_brace_placement = end_of_line
|
||||
ij_c_method_call_arguments_align_by_colons = true
|
||||
ij_c_method_call_arguments_align_multiline = false
|
||||
ij_c_method_call_arguments_special_dictionary_pairs_treatment = true
|
||||
ij_c_method_call_arguments_wrap = off
|
||||
ij_c_method_call_chain_wrap = off
|
||||
ij_c_method_parameters_align_by_colons = true
|
||||
ij_c_method_parameters_align_multiline = false
|
||||
ij_c_method_parameters_wrap = off
|
||||
ij_c_namespace_brace_placement = next_line
|
||||
ij_c_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_c_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_c_place_assignment_sign_on_next_line = false
|
||||
ij_c_property_nonatomic = true
|
||||
ij_c_put_ivars_to_implementation = true
|
||||
ij_c_refactor_compatibility_aliases_and_classes = true
|
||||
ij_c_refactor_properties_and_ivars = true
|
||||
ij_c_release_style = ivar
|
||||
ij_c_retain_object_parameters_in_constructor = true
|
||||
ij_c_semicolon_after_method_signature = false
|
||||
ij_c_shift_operation_align_multiline = true
|
||||
ij_c_shift_operation_wrap = normal
|
||||
ij_c_show_non_virtual_functions = false
|
||||
ij_c_space_after_colon = true
|
||||
ij_c_space_after_colon_in_foreach = true
|
||||
ij_c_space_after_colon_in_selector = false
|
||||
ij_c_space_after_comma = true
|
||||
ij_c_space_after_cup_in_blocks = false
|
||||
ij_c_space_after_dictionary_literal_colon = true
|
||||
ij_c_space_after_for_semicolon = true
|
||||
ij_c_space_after_init_list_colon = true
|
||||
ij_c_space_after_method_parameter_type_parentheses = false
|
||||
ij_c_space_after_method_return_type_parentheses = false
|
||||
ij_c_space_after_pointer_in_declaration = false
|
||||
ij_c_space_after_quest = true
|
||||
ij_c_space_after_reference_in_declaration = false
|
||||
ij_c_space_after_reference_in_rvalue = false
|
||||
ij_c_space_after_structures_rbrace = true
|
||||
ij_c_space_after_superclass_colon = true
|
||||
ij_c_space_after_type_cast = false
|
||||
ij_c_space_after_visibility_sign_in_method_declaration = true
|
||||
ij_c_space_before_autorelease_pool_lbrace = true
|
||||
ij_c_space_before_catch_keyword = true
|
||||
ij_c_space_before_catch_left_brace = true
|
||||
ij_c_space_before_catch_parentheses = false
|
||||
ij_c_space_before_category_parentheses = true
|
||||
ij_c_space_before_chained_send_message = true
|
||||
ij_c_space_before_class_left_brace = true
|
||||
ij_c_space_before_colon = true
|
||||
ij_c_space_before_colon_in_foreach = true
|
||||
ij_c_space_before_comma = false
|
||||
ij_c_space_before_dictionary_literal_colon = true
|
||||
ij_c_space_before_do_left_brace = true
|
||||
ij_c_space_before_else_keyword = true
|
||||
ij_c_space_before_else_left_brace = true
|
||||
ij_c_space_before_export_lbrace = true
|
||||
ij_c_space_before_for_left_brace = true
|
||||
ij_c_space_before_for_parentheses = false
|
||||
ij_c_space_before_for_semicolon = false
|
||||
ij_c_space_before_if_left_brace = true
|
||||
ij_c_space_before_if_parentheses = false
|
||||
ij_c_space_before_init_list = false
|
||||
ij_c_space_before_init_list_colon = true
|
||||
ij_c_space_before_method_call_parentheses = false
|
||||
ij_c_space_before_method_left_brace = true
|
||||
ij_c_space_before_method_parentheses = false
|
||||
ij_c_space_before_namespace_lbrace = true
|
||||
ij_c_space_before_pointer_in_declaration = true
|
||||
ij_c_space_before_property_attributes_parentheses = false
|
||||
ij_c_space_before_protocols_brackets = true
|
||||
ij_c_space_before_quest = true
|
||||
ij_c_space_before_reference_in_declaration = true
|
||||
ij_c_space_before_superclass_colon = true
|
||||
ij_c_space_before_switch_left_brace = true
|
||||
ij_c_space_before_switch_parentheses = false
|
||||
ij_c_space_before_template_call_lt = false
|
||||
ij_c_space_before_template_declaration_lt = true
|
||||
ij_c_space_before_try_left_brace = true
|
||||
ij_c_space_before_while_keyword = true
|
||||
ij_c_space_before_while_left_brace = true
|
||||
ij_c_space_before_while_parentheses = false
|
||||
ij_c_space_between_adjacent_brackets = false
|
||||
ij_c_space_between_operator_and_punctuator = false
|
||||
ij_c_space_within_empty_array_initializer_braces = true
|
||||
ij_c_spaces_around_additive_operators = true
|
||||
ij_c_spaces_around_assignment_operators = true
|
||||
ij_c_spaces_around_bitwise_operators = true
|
||||
ij_c_spaces_around_equality_operators = true
|
||||
ij_c_spaces_around_lambda_arrow = true
|
||||
ij_c_spaces_around_logical_operators = true
|
||||
ij_c_spaces_around_multiplicative_operators = true
|
||||
ij_c_spaces_around_pm_operators = false
|
||||
ij_c_spaces_around_relational_operators = true
|
||||
ij_c_spaces_around_shift_operators = true
|
||||
ij_c_spaces_around_unary_operator = false
|
||||
ij_c_spaces_within_array_initializer_braces = true
|
||||
ij_c_spaces_within_braces = false
|
||||
ij_c_spaces_within_brackets = false
|
||||
ij_c_spaces_within_cast_parentheses = false
|
||||
ij_c_spaces_within_catch_parentheses = true
|
||||
ij_c_spaces_within_category_parentheses = false
|
||||
ij_c_spaces_within_empty_braces = false
|
||||
ij_c_spaces_within_empty_function_call_parentheses = true
|
||||
ij_c_spaces_within_empty_function_declaration_parentheses = true
|
||||
ij_c_spaces_within_empty_lambda_capture_list_bracket = false
|
||||
ij_c_spaces_within_empty_template_call_ltgt = false
|
||||
ij_c_spaces_within_empty_template_declaration_ltgt = false
|
||||
ij_c_spaces_within_for_parentheses = true
|
||||
ij_c_spaces_within_function_call_parentheses = true
|
||||
ij_c_spaces_within_function_declaration_parentheses = true
|
||||
ij_c_spaces_within_if_parentheses = true
|
||||
ij_c_spaces_within_lambda_capture_list_bracket = false
|
||||
ij_c_spaces_within_method_parameter_type_parentheses = false
|
||||
ij_c_spaces_within_method_return_type_parentheses = false
|
||||
ij_c_spaces_within_parentheses = true
|
||||
ij_c_spaces_within_property_attributes_parentheses = false
|
||||
ij_c_spaces_within_protocols_brackets = false
|
||||
ij_c_spaces_within_send_message_brackets = false
|
||||
ij_c_spaces_within_structured_binding_list_bracket = false
|
||||
ij_c_spaces_within_switch_parentheses = true
|
||||
ij_c_spaces_within_template_call_ltgt = false
|
||||
ij_c_spaces_within_template_declaration_ltgt = false
|
||||
ij_c_spaces_within_template_double_gt = false
|
||||
ij_c_spaces_within_while_parentheses = true
|
||||
ij_c_special_else_if_treatment = true
|
||||
ij_c_structured_binding_list_align_multiline = false
|
||||
ij_c_structured_binding_list_align_multiline_bracket = false
|
||||
ij_c_structured_binding_list_comma_on_next_line = false
|
||||
ij_c_structured_binding_list_new_line_after_lbracket = false
|
||||
ij_c_structured_binding_list_new_line_before_rbracket = false
|
||||
ij_c_structured_binding_list_wrap = off
|
||||
ij_c_superclass_list_after_colon = never
|
||||
ij_c_superclass_list_align_multiline = true
|
||||
ij_c_superclass_list_before_colon = if_long
|
||||
ij_c_superclass_list_comma_on_next_line = false
|
||||
ij_c_superclass_list_wrap = on_every_item
|
||||
ij_c_tag_prefix_of_block_comment = at
|
||||
ij_c_tag_prefix_of_line_comment = back_slash
|
||||
ij_c_template_call_arguments_align_multiline = false
|
||||
ij_c_template_call_arguments_align_multiline_pars = false
|
||||
ij_c_template_call_arguments_comma_on_next_line = false
|
||||
ij_c_template_call_arguments_new_line_after_lt = false
|
||||
ij_c_template_call_arguments_new_line_before_gt = false
|
||||
ij_c_template_call_arguments_wrap = off
|
||||
ij_c_template_declaration_function_body_indent = false
|
||||
ij_c_template_declaration_function_wrap = split_into_lines
|
||||
ij_c_template_declaration_struct_body_indent = false
|
||||
ij_c_template_declaration_struct_wrap = split_into_lines
|
||||
ij_c_template_parameters_align_multiline = false
|
||||
ij_c_template_parameters_align_multiline_pars = false
|
||||
ij_c_template_parameters_comma_on_next_line = false
|
||||
ij_c_template_parameters_new_line_after_lt = false
|
||||
ij_c_template_parameters_new_line_before_gt = false
|
||||
ij_c_template_parameters_wrap = off
|
||||
ij_c_ternary_operation_signs_on_next_line = false
|
||||
ij_c_ternary_operation_wrap = off
|
||||
ij_c_type_qualifiers_placement = before
|
||||
ij_c_use_modern_casts = true
|
||||
ij_c_use_setters_in_constructor = true
|
||||
ij_c_while_brace_force = never
|
||||
ij_c_while_on_new_line = false
|
||||
ij_c_wrap_property_declaration = off
|
||||
|
||||
74
.github/workflows/c-cpp.yml
vendored
74
.github/workflows/c-cpp.yml
vendored
@@ -43,80 +43,82 @@ jobs:
|
||||
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
|
||||
targetos: win32
|
||||
targetarch: i386
|
||||
- os: macos-14 # in GitHub documentation, it's an ARM64 machine
|
||||
targetos: apple
|
||||
targetarch: arm64
|
||||
- os: macos-12 # in GitHub documentation, it's an x86 machine
|
||||
targetos: apple
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.28.5
|
||||
SDL_VERSION: 2.30.3
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install dependencies
|
||||
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
|
||||
- name: Build engine
|
||||
env:
|
||||
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
|
||||
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
|
||||
- name: Upload engine (artifacts)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
||||
path: artifacts/*
|
||||
flatpak:
|
||||
name: "Flatpak"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- app: su.xash.Engine.Compat.i386
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
|
||||
image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
|
||||
options: --privileged
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build flatpak (Compat.i386)
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
|
||||
with:
|
||||
bundle: ${{ matrix.app }}.flatpak
|
||||
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||
- name: Upload engine (artifacts)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
||||
path: artifacts/*
|
||||
release:
|
||||
name: "Upload releases"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, flatpak]
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
steps:
|
||||
- name: Remove old release
|
||||
uses: FWGS/delete-tag-and-release@v0.2.1-dev
|
||||
with:
|
||||
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
delete_release: true
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Fetch artifacts
|
||||
uses: actions/download-artifact@v3.0.1
|
||||
with:
|
||||
path: artifacts/
|
||||
- name: Repackage binaries and allow GitHub to process removed release for few seconds
|
||||
- name: Remove old release, fetch artifacts, repackage binaries and upload new release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
RELEASE_TAG: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
run: |
|
||||
cd artifacts/
|
||||
for i in artifact-* su.xash.Engine.*; do
|
||||
gh release delete "$RELEASE_TAG" \
|
||||
--yes \
|
||||
--cleanup-tag \
|
||||
--repo "$GITHUB_REPOSITORY" || true
|
||||
sleep 20s
|
||||
gh run download "$GITHUB_RUN_ID" \
|
||||
--dir artifacts/ \
|
||||
--repo "$GITHUB_REPOSITORY"
|
||||
pushd artifacts/
|
||||
echo "Found artifacts:"
|
||||
ls
|
||||
for i in $(find -mindepth 1 -maxdepth 1 -type d); do
|
||||
mv "$i"/* .
|
||||
rm -rf "$i"
|
||||
done
|
||||
ls -R .
|
||||
cd ../
|
||||
echo "Repackaged artifacts:"
|
||||
ls -R
|
||||
popd
|
||||
sleep 20s
|
||||
- name: Upload new release
|
||||
uses: FWGS/action-gh-release@v0.1.15
|
||||
with:
|
||||
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
|
||||
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
prerelease: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: artifacts/*
|
||||
draft: false
|
||||
gh release create "$RELEASE_TAG" artifacts/* \
|
||||
--title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
|
||||
--target $GITHUB_SHA \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--prerelease
|
||||
|
||||
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/extras/xash-extras
vendored
Submodule 3rdparty/extras/xash-extras updated: 853f633be1...f4ff263d42
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: d75b7f4a57...b7edbaf2de
2
3rdparty/vgui_support
vendored
2
3rdparty/vgui_support
vendored
Submodule 3rdparty/vgui_support updated: a2a7b9073f...7276993f3f
@@ -1,17 +1,17 @@
|
||||
# Bug-compatibility in Xash3D FWGS
|
||||
|
||||
Xash3D FWGS has special mode for games that rely on original engine bugs.
|
||||
|
||||
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
||||
Xash3D FWGS has special mode for games that rely on original engine bugs. In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
||||
|
||||
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
|
||||
|
||||
When `-bugcomp` is specified without argument, it enables everything. This behavior might be changed or removed in future versions.
|
||||
|
||||
When `-bugcomp` is specified with argument, it interpreted as flags separated with `+`. This way it's possible to combine multiple levels of bug-compatibility.
|
||||
|
||||
## GoldSrc bug-compatibility
|
||||
|
||||
### Emulated bugs
|
||||
|
||||
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
|
||||
|
||||
### Games and mods that require this
|
||||
|
||||
* Counter-Strike: Condition Zero - Deleted Scenes
|
||||
| Flag | Description | Games that require this flag |
|
||||
| ------- | ----------- | ---------------------------- |
|
||||
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
|
||||
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol. Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
|
||||
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |
|
||||
|
||||
21
Documentation/environment-variables.md
Normal file
21
Documentation/environment-variables.md
Normal file
@@ -0,0 +1,21 @@
|
||||
## Environment variables
|
||||
|
||||
#### Xash3D FWGS
|
||||
|
||||
The engine respects these environment variables:
|
||||
|
||||
| Variable | Type | Description |
|
||||
| --------------------- | ---------- | ----------- |
|
||||
| `XASH3D_GAME` | _string_ | Overrides default game directory. Ignored if `-game` command line argument is set |
|
||||
| `XASH3D_BASEDIR` | _string_ | Sets path to base (root) directory, instead of current working directory |
|
||||
| `XASH3D_RODIR` | _string_ | Sets path to read-only base (root) directory. Ignored if `-rodir` command line argument is set |
|
||||
| `XASH3D_EXTRAS_PAK1` | _string_ | Archive file from specified path will be added to virtual filesystem search path in the lowest possible priority |
|
||||
| `XASH3D_EXTRAS_PAK2` | _string_ | Similar to `XASH3D_EXTRAS_PAK1` but next to it in priority list |
|
||||
|
||||
Environment variables NOT listed in the table above are used internally, and aren't considered as stable interface.
|
||||
|
||||
#### mdldec
|
||||
|
||||
| Variable | Type | Description |
|
||||
| --------------------- | ---------- | ----------- |
|
||||
| `MDLDEC_ACT_PATH` | _string_ | If set, will read activities list from this path |
|
||||
@@ -78,6 +78,7 @@ These strings are specific to Xash3D FWGS.
|
||||
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
|
||||
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
|
||||
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
|
||||
| `demomap` | string | Empty string | The name of the demo chapter map (Half-Life Uplink) |
|
||||
|
||||
## Note on GoldSrc liblist.gam support
|
||||
|
||||
|
||||
40
Documentation/hd-textures.md
Normal file
40
Documentation/hd-textures.md
Normal file
@@ -0,0 +1,40 @@
|
||||
### HD (external) textures support
|
||||
|
||||
Xash3D supports loading texture replacements in TGA format for almost all types of models in the game, except alias models at this time.
|
||||
|
||||
Textures are expected to be located at:
|
||||
* `modfolder/materials/<mapname>` - for a specific map
|
||||
* `modfolder/materials/common` - common for all maps
|
||||
* `modfolder/materials/decals` - for decals
|
||||
* `modfolder/materials/models/<model>` - for models (texture name must match the internal texture name in the model)
|
||||
|
||||
Support for high-resolution textures is enabled setting `host_allow_materials` cvar to `1` or in the menu, in "Video options" section.
|
||||
|
||||
#### Xash3D FWGS additions
|
||||
|
||||
In addition to paths above, Xash3D FWGS checks following paths:
|
||||
|
||||
* `modfolder/materials/sprites/<sprite>` - for sprites, except HUD sprites
|
||||
|
||||
Also, to check which texture replacements are loaded successfully, failed or weren't found, a mod developer can set `host_allow_materials` cvar value to `2`. The engine will spew log at any developer level in the following format:
|
||||
|
||||
```
|
||||
Looking for <replacement> replacement... <status code> (<path relative to mod directory>)
|
||||
```
|
||||
|
||||
Status codes:
|
||||
* `OK` - texture replacement file was found and loaded into GPU memory successfully
|
||||
* `FAIL` - texture file was found but hasn't been parsed or loaded successfully. Refer to engine log for more details.
|
||||
* `MISS` - texture file wasn't found
|
||||
|
||||
Example:
|
||||
```
|
||||
Looking for maps/bounce.bsp:!waterblue tex replacement...OK (materials/common/!waterblue.tga)
|
||||
Looking for maps/bounce.bsp:!waterblue_luma tex replacement...MISS (not found)
|
||||
Looking for {shot2 decal replacement...MISS (materials/decals/{shot2.tga)
|
||||
Looking for {shot4 decal replacement...MISS (materials/decals/{shot4.tga)
|
||||
Looking for {shot3 decal replacement...MISS (materials/decals/{shot3.tga)
|
||||
Looking for models/gman tex replacement...FAIL (materials/models/gman/GMan_Case1.tga)
|
||||
Looking for models/gman tex replacement...FAIL (materials/models/gman/inside_1.tga)
|
||||
```
|
||||
|
||||
@@ -19,7 +19,22 @@
|
||||
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
|
||||
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
|
||||
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
|
||||
- [List of mods for Counter Strike(Android only)](#list-of-mods-for-counter-strike)
|
||||
- [List of mods for Counter Strike](#list-of-mods-for-counter-strike)
|
||||
- [List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS](#list-of-supported-mods-from-mobile_hacks-branch-of-hlsdk-portable-by-fwgs)
|
||||
|
||||
# List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
|
||||
1. [Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)
|
||||
2. [Big Lolly](https://www.moddb.com/mods/big-lolly)
|
||||
3. [Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)
|
||||
4. [Half-Secret](https://www.moddb.com/mods/half-secret)
|
||||
5. [Case Closed](https://www.moddb.com/mods/caseclosed)
|
||||
6. [Bloody Pizza - Vendetta](https://www.moddb.com/games/half-life/addons/bloody-pizza-vendetta)
|
||||
7. [Borderlands](https://www.moddb.com/games/half-life/addons/borderlands-v04)
|
||||
8. [Half-Life: Induction](https://www.moddb.com/mods/half-life-induction/downloads/half-life-induction-12)
|
||||
9. [Redemption/Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)
|
||||
10. [Sewer beta](https://www.moddb.com/games/half-life/addons/sewer-beta)
|
||||
11. [Times of Troubles](https://www.moddb.com/mods/times-of-troubles)
|
||||
12. [Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)
|
||||
|
||||
# List of Half-Life-based mods
|
||||
Originally this list was written by *Qwertyus*(*Qortez*)
|
||||
@@ -176,7 +191,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
||||
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
|
||||
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
|
||||
145. [Outrun](http://www.moddb.com/mods/outrun)
|
||||
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing)
|
||||
146. [Outwards (Day One)](https://web.archive.org/web/20161026104825/http://visgi.info/maps/)
|
||||
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
|
||||
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
|
||||
149. [pagoda](http://www.moddb.com/mods/pagoda1)
|
||||
@@ -282,7 +297,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
||||
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
|
||||
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
|
||||
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
|
||||
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing)
|
||||
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
|
||||
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
|
||||
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
|
||||
@@ -305,11 +320,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
|
||||
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
|
||||
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
|
||||
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
|
||||
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing)
|
||||
32. [Technology Test 2](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
|
||||
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
|
||||
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
|
||||
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing)
|
||||
36. [Time-Shift](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
|
||||
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
|
||||
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
|
||||
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
|
||||
@@ -379,7 +394,7 @@ Mods:
|
||||
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
|
||||
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
|
||||
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
|
||||
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
|
||||
8. [Lost in Black Mesa(first version without HLFX)](https://web.archive.org/web/20160407041812/http://half-life.ru/forum/showthread.php?threadid=13959) (download links dead!)
|
||||
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
|
||||
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
|
||||
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
|
||||
@@ -440,7 +455,7 @@ Mods:
|
||||
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
|
||||
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
|
||||
53. [De-railed](http://twhl.info/competitions.php?results=7)
|
||||
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing)
|
||||
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://web.archive.org/web/20151030005310/http://www.gamefront.com/files/13532512)
|
||||
55. [Deep](http://twhl.info/vault.php?map=1669)
|
||||
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
|
||||
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
|
||||
@@ -498,8 +513,8 @@ Mods:
|
||||
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
|
||||
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
|
||||
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
|
||||
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
|
||||
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing)
|
||||
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
|
||||
113. [In America](https://web.archive.org/web/20170221213409/http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
|
||||
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
|
||||
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
|
||||
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
|
||||
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
||||
|
||||
@@ -28,7 +28,7 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
|
||||
1) Copy engine binaries to some directory.
|
||||
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
|
||||
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
||||
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
|
||||
You still needed to copy `valve` directory as all game resources located there.
|
||||
3) Run the main executable (`xash3d.exe` or AppImage).
|
||||
|
||||
@@ -46,11 +46,11 @@ NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependenc
|
||||
|
||||
### Prerequisites
|
||||
|
||||
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||
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!
|
||||
|
||||
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
||||
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
|
||||
|
||||
#### Windows (Visual Studio)
|
||||
* Install Visual Studio.
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
boneinfo.h - structure that send delta-compressed bones across network
|
||||
Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef BONEINFO_H
|
||||
#define BONEINFO_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t angles;
|
||||
vec3_t origin;
|
||||
} boneinfo_t;
|
||||
|
||||
#endif//BONEINFO_H
|
||||
@@ -127,14 +127,23 @@ typedef struct
|
||||
int flags; // sky or slime, no lightmap or 256 subdivision
|
||||
} mtexinfo_t;
|
||||
|
||||
typedef struct glpoly_s
|
||||
// a1ba: changed size to avoid undefined behavior. Check your allocations if you take this header!
|
||||
// For example:
|
||||
// before: malloc( sizeof( glpoly_t ) + ( numverts - 4 ) * VERTEXSIZE * sizeof( float ))
|
||||
// after (C): malloc( sizeof( glpoly_t ) + numverts * VERTEXSIZE * sizeof( float ))
|
||||
// after (C++): malloc( sizeof( glpoly_t ) + ( numverts - 1 ) * VERTEXSIZE * sizeof( float ))
|
||||
typedef struct glpoly2_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
struct glpoly_s *chain;
|
||||
struct glpoly2_s *next;
|
||||
struct glpoly2_s *chain;
|
||||
int numverts;
|
||||
int flags; // for SURF_UNDERWATER
|
||||
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
} glpoly_t;
|
||||
#ifdef __cplusplus
|
||||
float verts[1][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
#else
|
||||
float verts[][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
#endif
|
||||
} glpoly2_t;
|
||||
|
||||
typedef struct mnode_s
|
||||
{
|
||||
@@ -173,7 +182,7 @@ struct decal_s
|
||||
short entityIndex; // Entity this is attached to
|
||||
// Xash3D specific
|
||||
vec3_t position; // location of the decal center in world space.
|
||||
glpoly_t *polys; // precomputed decal vertices
|
||||
glpoly2_t *polys; // precomputed decal vertices
|
||||
intptr_t reserved[4]; // just for future expansions or mod-makers
|
||||
};
|
||||
|
||||
@@ -246,7 +255,7 @@ struct msurface_s
|
||||
|
||||
int light_s, light_t; // gl lightmap coordinates
|
||||
|
||||
glpoly_t *polys; // multiple if warped
|
||||
glpoly2_t *polys; // multiple if warped
|
||||
struct msurface_s *texturechain;
|
||||
|
||||
mtexinfo_t *texinfo;
|
||||
@@ -488,7 +497,8 @@ typedef struct
|
||||
int flags;
|
||||
float size;
|
||||
|
||||
int reserved[8]; // VBO offsets
|
||||
const trivertex_t **pposeverts; // only valid during loading, used to build GL mesh
|
||||
intptr_t reserved[7]; // VBO offsets
|
||||
|
||||
int numposes;
|
||||
int poseverts;
|
||||
@@ -531,17 +541,10 @@ typedef struct
|
||||
#define MAX_MOVIES 8
|
||||
#define MAX_CDTRACKS 32
|
||||
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
|
||||
#define MAX_EFRAGS 8192 // Arcane Dimensions required
|
||||
#define MAX_REQUESTS 64
|
||||
|
||||
#if ! XASH_64BIT
|
||||
STATIC_ASSERT( sizeof( mextrasurf_t ) == 324, "mextrasurf_t unexpected size" );
|
||||
STATIC_ASSERT( sizeof( decal_t ) == 60, "decal_t unexpected size");
|
||||
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 176, "mfaceinfo_t unexpected size");
|
||||
#else
|
||||
STATIC_ASSERT( sizeof( mextrasurf_t) == 496, "mextrasurf_t unexpected size");
|
||||
STATIC_ASSERT( sizeof( decal_t ) == 88, "decal_t unexpected size");
|
||||
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 304, "mfaceinfo_t unexpected size");
|
||||
#endif
|
||||
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
|
||||
STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
|
||||
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
|
||||
|
||||
#endif//COM_MODEL_H
|
||||
|
||||
159
common/cvardef.h
159
common/cvardef.h
@@ -1,49 +1,122 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef CVARDEF_H
|
||||
#define CVARDEF_H
|
||||
/*
|
||||
cvardef.h - quake cvar definition
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
Copyright (C) 2024 Alibek Omarov
|
||||
|
||||
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc
|
||||
#define FCVAR_USERINFO (1<<1) // changes the client's info string
|
||||
#define FCVAR_SERVER (1<<2) // notifies players when changed
|
||||
#define FCVAR_EXTDLL (1<<3) // defined by external DLL
|
||||
#define FCVAR_CLIENTDLL (1<<4) // defined by the client dll
|
||||
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
|
||||
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
|
||||
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
|
||||
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
|
||||
#define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar
|
||||
#define FCVAR_PRIVILEGED (1<<10) // only available in privileged mode
|
||||
#define FCVAR_FILTERABLE (1<<11) // filtered in unprivileged mode if cl_filterstuffcmd is 1
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
// Xash3D extensions
|
||||
#define FCVAR_GLCONFIG (1<<12) // write it into <renderer>.cfg(see RefAPI)
|
||||
#define FCVAR_CHANGED (1<<13) // set each time the cvar is changed
|
||||
#define FCVAR_GAMEUIDLL (1<<14) // defined by the menu DLL
|
||||
#define FCVAR_CHEAT (1<<15) // can not be changed if cheats are disabled
|
||||
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.
|
||||
|
||||
// a1ba: let's reuse higher bits for flags extensions from now on
|
||||
#define FCVAR_LATCH (1<<30) // notify client what this cvar will be applied only after server restart (but don't does more nothing)
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
typedef struct cvar_s
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef CVAR
|
||||
#define CVAR
|
||||
|
||||
#include STDINT_H
|
||||
#include "xash3d_types.h"
|
||||
|
||||
/*
|
||||
|
||||
cvar_t variables are used to hold scalar or string variables that can be changed
|
||||
or displayed at the console or prog code as well as accessed directly
|
||||
in C code.
|
||||
|
||||
The user can access cvars from the console in three ways:
|
||||
r_draworder prints the current value
|
||||
r_draworder 0 sets the current value to 0
|
||||
set r_draworder 0 as above, but creates the cvar if not present
|
||||
|
||||
Cvars are restricted from having the same names as commands to keep this
|
||||
interface from being ambiguous.
|
||||
|
||||
The are also occasionally used to communicated information between different
|
||||
modules of the program.
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
char *name;
|
||||
char *string;
|
||||
int flags;
|
||||
float value;
|
||||
struct cvar_s *next;
|
||||
} cvar_t;
|
||||
// GoldSrc compatibility flags
|
||||
FCVAR_ARCHIVE = 1 << 0, // set to cause it to be saved to vars.rc
|
||||
FCVAR_USERINFO = 1 << 1, // added to userinfo when changed
|
||||
FCVAR_SERVER = 1 << 2, // added to serverinfo when changed, will notify clients by default
|
||||
FCVAR_EXTDLL = 1 << 3, // defined by server.dll
|
||||
FCVAR_CLIENTDLL = 1 << 4, // defined by client.dll
|
||||
FCVAR_PROTECTED = 1 << 5, // private server cvar
|
||||
FCVAR_SPONLY = 1 << 6, // can be set only in singleplayer
|
||||
FCVAR_PRINTABLEONLY = 1 << 7, // only allows printable characters
|
||||
FCVAR_UNLOGGED = 1 << 8, // disables notifying client about server cvar change
|
||||
FCVAR_NOEXTRAWHITESPACE = 1 << 9, // removes space characters from the beginning and the end of the string
|
||||
FCVAR_PRIVILEGED = 1 << 10, // only available in privileged mode
|
||||
FCVAR_FILTERABLE = 1 << 11, // treated as privileged if cl_filterstuffcmd is 1, otherwise ignored
|
||||
|
||||
#endif//CVARDEF_H
|
||||
// Xash3D public flags
|
||||
// FCVAR_LATCH = 1 << 11, // deprecated Xash3D flag, conflicts with FCVAR_FILTERABLE. Use another FCVAR_LATCH!
|
||||
FCVAR_GLCONFIG = 1 << 12, // set to cause it to be saved to <renderer>.cfg (see RefAPI)
|
||||
FCVAR_CHANGED = 1 << 13, // set each time the cvar changed
|
||||
FCVAR_GAMEUIDLL = 1 << 14, // defined by menu.dll
|
||||
FCVAR_CHEAT = 1 << 15, // cannot be changed if sv_cheats is 0
|
||||
|
||||
#if REF_DLL || ENGINE_DLL // Xash3D internal flags, MUST NOT be used outside of engine
|
||||
FCVAR_RENDERINFO = 1 << 16, // set to cause it to be saved to video.cfg
|
||||
FCVAR_READ_ONLY = 1 << 17, // display only, cannot be set by user at all
|
||||
FCVAR_EXTENDED = 1 << 18, // extended cvar structure
|
||||
FCVAR_ALLOCATED = 1 << 19, // allocated by the engine, must be freed with Mem_Free
|
||||
FCVAR_VIDRESTART = 1 << 20, // triggers video subsystem to recreate/modify window parameters
|
||||
FCVAR_TEMPORARY = 1 << 21, // only used to temporarly hold some value, can be unlinked
|
||||
FCVAR_MOVEVARS = 1 << 22, // access to movevars_t structure, synchornized between client and server
|
||||
FCVAR_USER_CREATED = 1 << 23, // created by a set command
|
||||
|
||||
FCVAR_REFDLL = 1 << 29, // (Xash3D FWGS internal flag) defined by the renderer DLL
|
||||
#endif // REF_DLL || ENGINE_DLL
|
||||
|
||||
FCVAR_LATCH = 1 << 30, // (Xash3D FWGS public flag, was FCVAR_FILTERABLE in Xash3D) save changes until server restart
|
||||
};
|
||||
|
||||
struct cvar_s {
|
||||
char *name;
|
||||
char *string;
|
||||
uint32_t flags;
|
||||
float value;
|
||||
struct cvar_s *next;
|
||||
};
|
||||
typedef struct cvar_s cvar_t;
|
||||
|
||||
STATIC_CHECK_SIZEOF( struct cvar_s, 20, 32 );
|
||||
|
||||
#if REF_DLL || ENGINE_DLL // Xash3D internal cvar format, MUST NOT be used outside of engine
|
||||
struct convar_s {
|
||||
char *name;
|
||||
char *string;
|
||||
uint32_t flags;
|
||||
float value;
|
||||
struct convar_s *next;
|
||||
char *desc;
|
||||
char *def_string;
|
||||
};
|
||||
typedef struct convar_s convar_t;
|
||||
|
||||
#if XASH_64BIT
|
||||
#define CVAR_SENTINEL (uintptr_t)0xDEADBEEFDEADBEEF
|
||||
#else
|
||||
#define CVAR_SENTINEL (uintptr_t)0xDEADBEEF
|
||||
#endif
|
||||
|
||||
#define CVAR_CHECK_SENTINEL( cv ) ((uintptr_t)(cv)->next == CVAR_SENTINEL)
|
||||
|
||||
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
|
||||
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
|
||||
|
||||
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) CVAR_DEFINE( cv, #cv, cvstr, cvflags, cvdesc )
|
||||
#endif // REF_DLL || ENGINE_DLL
|
||||
|
||||
#endif // CVAR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
features.h - engine features that can be enabled by mod-maker request
|
||||
enginefeatures.h - engine features that can be enabled by mod-maker request
|
||||
Copyright (C) 2012 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -27,6 +27,7 @@ GNU General Public License for more details.
|
||||
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
|
||||
#define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer
|
||||
|
||||
#define ENGINE_DISABLE_HDTEXTURES (1U<<30) // disable support of HD-textures in case custom renderer have separate way to load them
|
||||
#define ENGINE_STEP_POSHISTORY_LERP (1U<<31) // enable MOVETYPE_STEP interpolation based on position history. Incompatible with ENGINE_COMPUTE_STUDIO_LERP!
|
||||
|
||||
// adjust the mask when features will be added or removed
|
||||
|
||||
@@ -30,7 +30,7 @@ GAMEINFO stuff
|
||||
internal shared gameinfo structure (readonly for engine parts)
|
||||
========================================================================
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct GAMEINFO_s
|
||||
{
|
||||
// filesystem info
|
||||
char gamefolder[64]; // used for change game '-game x'
|
||||
@@ -50,4 +50,48 @@ typedef struct
|
||||
int gamemode;
|
||||
} GAMEINFO;
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
Extended GameInfo struct introduced in Xash3D FWGS
|
||||
|
||||
GAMEINFO can't be reliably extended, as nor engine, nor menu can't be
|
||||
sure about struct size. By adding struct versioning, we can check the
|
||||
presense for extra fields.
|
||||
========================================================================
|
||||
*/
|
||||
|
||||
#define GAMEINFO_VERSION 2
|
||||
|
||||
typedef enum gametype_e
|
||||
{
|
||||
GAME_NORMAL,
|
||||
GAME_SINGLEPLAYER_ONLY,
|
||||
GAME_MULTIPLAYER_ONLY,
|
||||
} gametype_t;
|
||||
|
||||
typedef struct gameinfo2_s
|
||||
{
|
||||
int gi_version; // should be set to desired struct version, e.g. GAMEINFO_VERSION
|
||||
|
||||
// filesystem info
|
||||
char gamefolder[64]; // used for change game
|
||||
char startmap[64]; // map to start singleplayer game from
|
||||
char trainmap[64]; // map to start hazardous course from (if specified)
|
||||
char demomap[64]; // map to start demo chapter from (if specified)
|
||||
char title[64]; // game title
|
||||
char iconpath[64]; // path to game icon
|
||||
char version[16]; // game version (optional)
|
||||
uint32_t flags; // gameinfo flags, extended to fit more flags
|
||||
|
||||
// mod info
|
||||
char game_url[256]; // link to a developer's site
|
||||
char update_url[256]; // link to updates page
|
||||
char type[64]; // single, toolkit, multiplayer, etc
|
||||
char date[64]; // release date
|
||||
uint64_t size; // size in bytes
|
||||
|
||||
gametype_t gamemode;
|
||||
} gameinfo2_t;
|
||||
|
||||
#endif//GAMEINFO_H
|
||||
|
||||
@@ -30,6 +30,6 @@ typedef struct
|
||||
int state; // low bit is down state
|
||||
} kbutton_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( kbutton_t ) == 12, "kbutton_t isn't 12 bytes!" );
|
||||
STATIC_CHECK_SIZEOF( kbutton_t, 12, 12 );
|
||||
|
||||
#endif // KBUTTON_H
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// Set this flag for things like broadcast requests, etc. where the engine should not
|
||||
// kill the request hook after receiving the first response
|
||||
#define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 )
|
||||
#define FNETAPI_LEGACY_PROTOCOL ( 1<<1 ) // xash3d-fwgs extension
|
||||
|
||||
struct net_response_s;
|
||||
typedef void (*net_api_response_func_t) ( struct net_response_s *response );
|
||||
@@ -35,6 +36,7 @@ typedef void (*net_api_response_func_t) ( struct net_response_s *response );
|
||||
#define NET_ERROR_TIMEOUT ( 1<<0 )
|
||||
#define NET_ERROR_PROTO_UNSUPPORTED ( 1<<1 )
|
||||
#define NET_ERROR_UNDEFINED ( 1<<2 )
|
||||
#define NET_ERROR_FORBIDDEN ( 1<<3 ) // xash3d-fwgs extension
|
||||
|
||||
typedef struct net_adrlist_s
|
||||
{
|
||||
|
||||
@@ -69,6 +69,6 @@ typedef struct netadr_s
|
||||
} netadr_t;
|
||||
#pragma pack( pop )
|
||||
|
||||
STATIC_ASSERT( sizeof( netadr_t ) == 20, "netadr_t isn't 20 bytes!" );
|
||||
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
|
||||
|
||||
#endif // NET_ADR_H
|
||||
|
||||
@@ -56,6 +56,8 @@ color24 gTracerColors[] =
|
||||
};
|
||||
*/
|
||||
|
||||
#define TRACER_COLORINDEX_DEFAULT 4
|
||||
|
||||
// Temporary entity array
|
||||
#define TENTPRIORITY_LOW 0
|
||||
#define TENTPRIORITY_HIGH 1
|
||||
|
||||
@@ -28,11 +28,7 @@ typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||
typedef vec_t matrix3x4[3][4];
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
|
||||
#if XASH_64BIT
|
||||
typedef uint32_t poolhandle_t;
|
||||
#else
|
||||
typedef void* poolhandle_t;
|
||||
#endif
|
||||
|
||||
#undef true
|
||||
#undef false
|
||||
@@ -74,48 +70,64 @@ typedef uint64_t longtime_t;
|
||||
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
|
||||
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#ifdef __i386__
|
||||
#define EXPORT __attribute__ ((visibility ("default"),force_align_arg_pointer))
|
||||
#define GAME_EXPORT __attribute((force_align_arg_pointer))
|
||||
#if defined( __GNUC__ )
|
||||
#if defined( __i386__ )
|
||||
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
|
||||
#define GAME_EXPORT __attribute(( force_align_arg_pointer ))
|
||||
#else
|
||||
#define EXPORT __attribute__ ((visibility ("default")))
|
||||
#define EXPORT __attribute__(( visibility ( "default" )))
|
||||
#define GAME_EXPORT
|
||||
#endif
|
||||
#define _format(x) __attribute__((format(printf, x, x+1)))
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define NONNULL __attribute__((nonnull))
|
||||
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define EXPORT __declspec( dllexport )
|
||||
#define GAME_EXPORT
|
||||
#define _format(x)
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#define ALLOC_CHECK(x)
|
||||
|
||||
#define MALLOC __attribute__(( malloc ))
|
||||
|
||||
// added in GCC 11
|
||||
#if __GNUC__ >= 11
|
||||
// might want to set noclone due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116893
|
||||
// but it's easier to not force mismatched-dealloc to error yet
|
||||
#define MALLOC_LIKE( x, y ) __attribute__(( malloc( x, y )))
|
||||
#else
|
||||
#define MALLOC_LIKE( x, y ) MALLOC
|
||||
#endif
|
||||
#define NORETURN __attribute__(( noreturn ))
|
||||
#define NONNULL __attribute__(( nonnull ))
|
||||
#define _format( x ) __attribute__(( format( printf, x, x + 1 )))
|
||||
#define ALLOC_CHECK( x ) __attribute__(( alloc_size( x )))
|
||||
#define NO_ASAN __attribute__(( no_sanitize( "address" )))
|
||||
#define WARN_UNUSED_RESULT __attribute__(( warn_unused_result ))
|
||||
#define RENAME_SYMBOL( x ) asm( x )
|
||||
#else
|
||||
#define EXPORT
|
||||
#if defined( _MSC_VER )
|
||||
#define EXPORT __declspec( dllexport )
|
||||
#define NO_ASAN __declspec( no_sanitize_address )
|
||||
#else
|
||||
#define EXPORT
|
||||
#define NO_ASAN
|
||||
#endif
|
||||
#define GAME_EXPORT
|
||||
#define _format(x)
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#define ALLOC_CHECK(x)
|
||||
#define _format( x )
|
||||
#define ALLOC_CHECK( x )
|
||||
#define RENAME_SYMBOL( x )
|
||||
#define MALLOC
|
||||
#define MALLOC_LIKE( x, y )
|
||||
#define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#if ( __GNUC__ >= 3 )
|
||||
#define unlikely(x) __builtin_expect(x, 0)
|
||||
#define likely(x) __builtin_expect(x, 1)
|
||||
#if __GNUC__ >= 3
|
||||
#define unlikely( x ) __builtin_expect( x, 0 )
|
||||
#define likely( x ) __builtin_expect( x, 1 )
|
||||
#elif defined( __has_builtin )
|
||||
#if __has_builtin( __builtin_expect )
|
||||
#define unlikely(x) __builtin_expect(x, 0)
|
||||
#define likely(x) __builtin_expect(x, 1)
|
||||
#else
|
||||
#define unlikely(x) (x)
|
||||
#define likely(x) (x)
|
||||
#if __has_builtin( __builtin_expect ) // this must be after defined() check
|
||||
#define unlikely( x ) __builtin_expect( x, 0 )
|
||||
#define likely( x ) __builtin_expect( x, 1 )
|
||||
#endif
|
||||
#else
|
||||
#define unlikely(x) (x)
|
||||
#define likely(x) (x)
|
||||
#endif
|
||||
|
||||
#if !defined( unlikely ) || !defined( likely )
|
||||
#define unlikely( x ) ( x )
|
||||
#define likely( x ) ( x )
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword
|
||||
@@ -132,6 +144,23 @@ typedef uint64_t longtime_t;
|
||||
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
|
||||
#endif
|
||||
|
||||
// at least, statically check size of some public structures
|
||||
#if XASH_64BIT
|
||||
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
|
||||
STATIC_ASSERT( sizeof( type ) == size64, #type " unexpected size" )
|
||||
#else
|
||||
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
|
||||
STATIC_ASSERT( sizeof( type ) == size32, #type " unexpected size" )
|
||||
#endif
|
||||
|
||||
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
|
||||
#define XASH_RESTRICT restrict
|
||||
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions
|
||||
#define XASH_RESTRICT __restrict
|
||||
#else
|
||||
#define XASH_RESTRICT // nothing
|
||||
#endif
|
||||
|
||||
#ifdef XASH_BIG_ENDIAN
|
||||
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
|
||||
#define LittleLongSW(x) (x = LittleLong(x) )
|
||||
@@ -162,8 +191,9 @@ _inline float LittleFloat( float f )
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
typedef char string[MAX_STRING];
|
||||
typedef struct file_s file_t; // normal file
|
||||
typedef struct stream_s stream_t; // sound stream for background music playing
|
||||
|
||||
@@ -74,7 +74,7 @@ typedef struct
|
||||
float size;
|
||||
} daliashdr_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliashdr_t ) == 84, "invalid daliashdr_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliashdr_t, 84, 84 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -83,7 +83,7 @@ typedef struct
|
||||
int32_t t;
|
||||
} stvert_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( stvert_t ) == 12, "invalid stvert_t size" );
|
||||
STATIC_CHECK_SIZEOF( stvert_t, 12, 12 );
|
||||
|
||||
typedef struct dtriangle_s
|
||||
{
|
||||
@@ -91,7 +91,7 @@ typedef struct dtriangle_s
|
||||
int32_t vertindex[3];
|
||||
} dtriangle_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( dtriangle_t ) == 16, "invalid dtriangle_t size" );
|
||||
STATIC_CHECK_SIZEOF( dtriangle_t, 16, 16 );
|
||||
|
||||
#define DT_FACES_FRONT 0x0010
|
||||
#define ALIAS_ONSEAM 0x0020
|
||||
@@ -103,7 +103,7 @@ typedef struct
|
||||
char name[16]; // frame name from grabbing
|
||||
} daliasframe_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasframe_t ) == 24, "invalid daliasframe_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasframe_t, 24, 24 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -112,41 +112,41 @@ typedef struct
|
||||
trivertex_t bboxmax; // lightnormal isn't used
|
||||
} daliasgroup_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasgroup_t ) == 12, "invalid daliasgrou_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasgroup_t, 12, 12 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t numskins;
|
||||
} daliasskingroup_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasskingroup_t ) == 4, "invalid daliasskingroup_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasskingroup_t, 4, 4 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float interval;
|
||||
} daliasinterval_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasinterval_t ) == 4, "invalid daliasinterval_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasinterval_t, 4, 4 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float interval;
|
||||
} daliasskininterval_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasskininterval_t ) == 4, "invalid daliasskininterval_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasskininterval_t, 4, 4 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type; // was aliasframetype_t
|
||||
} daliasframetype_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasframetype_t ) == 4, "invalid daliasframetype_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasframetype_t, 4, 4 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type; // was aliasskintype_t
|
||||
} daliasskintype_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasskintype_t ) == 4, "invalid daliasskintype_t size" );
|
||||
STATIC_CHECK_SIZEOF( daliasskintype_t, 4, 4 );
|
||||
|
||||
#endif//ALIAS_H
|
||||
|
||||
@@ -274,6 +274,13 @@ void CL_GenericShot_f( void )
|
||||
string checkname;
|
||||
int i;
|
||||
|
||||
// allow overriding screenshot by users request
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
Q_strncpy( cls.shotname, Cmd_Argv( 1 ), sizeof( cls.shotname ));
|
||||
break;
|
||||
}
|
||||
|
||||
if( type == scrshot_snapshot )
|
||||
{
|
||||
fmt = "../%s_%04d.png";
|
||||
@@ -349,7 +356,7 @@ void CL_SetSky_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_SetupSky( Cmd_Argv( 1 ));
|
||||
R_SetupSky( Cmd_Argv( 1 ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -70,16 +70,17 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( cl.downloadUrl[0] )
|
||||
host.downloadcount++;
|
||||
|
||||
if( cl.http_download )
|
||||
{
|
||||
HTTP_AddDownload( filepath, pResource->nDownloadSize, true );
|
||||
host.downloadcount++;
|
||||
return false;
|
||||
}
|
||||
|
||||
MSG_BeginClientCmd( msg, clc_stringcmd );
|
||||
MSG_WriteStringf( msg, "dlfile %s", filepath );
|
||||
host.downloadcount++;
|
||||
else
|
||||
{
|
||||
MSG_BeginClientCmd( msg, clc_stringcmd );
|
||||
MSG_WriteStringf( msg, "dlfile %s", filepath );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -104,7 +105,7 @@ void CL_AddToResourceList( resource_t *pResource, resource_t *pList )
|
||||
void CL_RemoveFromResourceList( resource_t *pResource )
|
||||
{
|
||||
if( pResource->pPrev == NULL || pResource->pNext == NULL )
|
||||
Host_Error( "mislinked resource in CL_RemoveFromResourceList\n" );
|
||||
Host_Error( "mislinked resource in %s\n", __func__ );
|
||||
|
||||
if( pResource->pNext == pResource || pResource->pPrev == pResource )
|
||||
Host_Error( "attempt to free last entry in list.\n" );
|
||||
@@ -119,7 +120,7 @@ void CL_MoveToOnHandList( resource_t *pResource )
|
||||
{
|
||||
if( !pResource )
|
||||
{
|
||||
Con_Reportf( "Null resource passed to CL_MoveToOnHandList\n" );
|
||||
Con_Reportf( "Null resource passed to %s\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,29 @@ const char *CL_MsgInfo( int cmd )
|
||||
if( cmd >= 0 && cmd <= svc_lastmsg )
|
||||
{
|
||||
// get engine message name
|
||||
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
|
||||
const char *svc_string = NULL;
|
||||
|
||||
switch( cls.legacymode )
|
||||
{
|
||||
case PROTO_CURRENT:
|
||||
svc_string = svc_strings[cmd];
|
||||
break;
|
||||
case PROTO_LEGACY:
|
||||
svc_string = svc_legacy_strings[cmd];
|
||||
break;
|
||||
case PROTO_QUAKE:
|
||||
svc_string = svc_quake_strings[cmd];
|
||||
break;
|
||||
case PROTO_GOLDSRC:
|
||||
svc_string = svc_goldsrc_strings[cmd];
|
||||
break;
|
||||
}
|
||||
|
||||
// fall back to current protocol strings
|
||||
if( !svc_string )
|
||||
svc_string = svc_strings[cmd];
|
||||
|
||||
Q_strncpy( sz, svc_string, sizeof( sz ));
|
||||
}
|
||||
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
||||
{
|
||||
|
||||
@@ -79,7 +79,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
demoentry_t *entries; // track entry info
|
||||
int numentries; // number of tracks
|
||||
int32_t numentries; // number of tracks
|
||||
} demodirectory_t;
|
||||
|
||||
// add angles
|
||||
@@ -109,6 +109,40 @@ struct
|
||||
|
||||
static qboolean CL_NextDemo( void );
|
||||
|
||||
static int CL_GetDemoNetProtocol( connprotocol_t proto )
|
||||
{
|
||||
switch( proto )
|
||||
{
|
||||
case PROTO_CURRENT:
|
||||
return PROTOCOL_VERSION;
|
||||
case PROTO_LEGACY:
|
||||
return PROTOCOL_LEGACY_VERSION;
|
||||
case PROTO_QUAKE:
|
||||
return PROTOCOL_VERSION_QUAKE;
|
||||
case PROTO_GOLDSRC:
|
||||
return PROTOCOL_GOLDSRC_VERSION;
|
||||
}
|
||||
|
||||
return PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
|
||||
{
|
||||
switch( net_protocol )
|
||||
{
|
||||
case PROTOCOL_VERSION:
|
||||
return PROTO_CURRENT;
|
||||
case PROTOCOL_LEGACY_VERSION:
|
||||
return PROTO_LEGACY;
|
||||
case PROTOCOL_VERSION_QUAKE:
|
||||
return PROTO_QUAKE;
|
||||
case PROTOCOL_GOLDSRC_VERSION:
|
||||
return PROTO_GOLDSRC;
|
||||
}
|
||||
|
||||
return PROTO_CURRENT;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_StartupDemoHeader
|
||||
@@ -119,12 +153,8 @@ we record a demo on this level
|
||||
*/
|
||||
void CL_StartupDemoHeader( void )
|
||||
{
|
||||
if( cls.demoheader )
|
||||
{
|
||||
FS_Close( cls.demoheader );
|
||||
}
|
||||
CL_CloseDemoHeader();
|
||||
|
||||
// Note: this is replacing tmpfile()
|
||||
cls.demoheader = FS_Open( "demoheader.tmp", "w+b", true );
|
||||
|
||||
if( !cls.demoheader )
|
||||
@@ -297,10 +327,6 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg )
|
||||
|
||||
if( !file ) return;
|
||||
|
||||
// past the start but not recording a demo.
|
||||
if( !startup && !cls.demorecording )
|
||||
return;
|
||||
|
||||
swlen = MSG_GetNumBytesWritten( msg ) - start;
|
||||
if( swlen <= 0 ) return;
|
||||
|
||||
@@ -373,7 +399,7 @@ static void CL_WriteDemoHeader( const char *name )
|
||||
|
||||
demo.header.id = IDEMOHEADER;
|
||||
demo.header.dem_protocol = DEMO_PROTOCOL;
|
||||
demo.header.net_protocol = cls.legacymode ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION;
|
||||
demo.header.net_protocol = CL_GetDemoNetProtocol( cls.legacymode );
|
||||
demo.header.host_fps = host_maxfps.value ? bound( MIN_FPS, host_maxfps.value, MAX_FPS ) : MAX_FPS;
|
||||
Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
|
||||
Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment ));
|
||||
@@ -393,6 +419,7 @@ static void CL_WriteDemoHeader( const char *name )
|
||||
|
||||
// finish off the startup info.
|
||||
CL_WriteDemoCmdHeader( dem_stop, cls.demoheader );
|
||||
FS_Flush( cls.demoheader );
|
||||
|
||||
// now copy the stuff we cached from the server.
|
||||
copysize = savepos = FS_Tell( cls.demoheader );
|
||||
@@ -1119,6 +1146,7 @@ show stats
|
||||
*/
|
||||
static void CL_FinishTimeDemo( void )
|
||||
{
|
||||
qboolean temp = host.allow_console;
|
||||
int frames;
|
||||
double time;
|
||||
|
||||
@@ -1129,7 +1157,9 @@ static void CL_FinishTimeDemo( void )
|
||||
time = host.realtime - cls.td_starttime;
|
||||
if( !time ) time = 1.0;
|
||||
|
||||
host.allow_console = true;
|
||||
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
|
||||
host.allow_console = temp;
|
||||
|
||||
if( Sys_CheckParm( "-timedemo" ))
|
||||
CL_Quit_f();
|
||||
@@ -1418,6 +1448,51 @@ void CL_Record_f( void )
|
||||
CL_WriteDemoHeader( demopath );
|
||||
}
|
||||
|
||||
static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, file_t *f, demoheader_t *hdr, int32_t *numentries )
|
||||
{
|
||||
if( FS_Read( f, hdr, sizeof( *hdr )) != sizeof( *hdr ) || hdr->id != IDEMOHEADER )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: %s is not in supported format or not a demo file\n", callee, filename );
|
||||
return false;
|
||||
}
|
||||
|
||||
// force null terminate strings
|
||||
hdr->mapname[sizeof( hdr->mapname ) - 1] = 0;
|
||||
hdr->comment[sizeof( hdr->comment ) - 1] = 0;
|
||||
hdr->gamedir[sizeof( hdr->gamedir ) - 1] = 0;
|
||||
|
||||
if( hdr->dem_protocol != DEMO_PROTOCOL )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: demo protocol outdated (%i should be %i)\n",
|
||||
callee, hdr->net_protocol, DEMO_PROTOCOL );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
|
||||
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( FS_Seek( f, hdr->directory_offset, SEEK_SET ) < 0
|
||||
|| FS_Read( f, numentries, sizeof( *numentries )) != sizeof( *numentries ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: can't find directory offset in %s, demo file corrupted\n",
|
||||
callee, filename );
|
||||
return false;
|
||||
}
|
||||
|
||||
if(( *numentries < 1 ) || ( *numentries > 1024 ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: demo have bogus # of directory entries: %i\n",
|
||||
callee, *numentries );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_PlayDemo_f
|
||||
@@ -1438,9 +1513,7 @@ void CL_PlayDemo_f( void )
|
||||
}
|
||||
|
||||
if( cls.demoplayback )
|
||||
{
|
||||
CL_StopPlayback();
|
||||
}
|
||||
|
||||
if( cls.demorecording )
|
||||
{
|
||||
@@ -1490,51 +1563,32 @@ void CL_PlayDemo_f( void )
|
||||
|
||||
if( neg ) cls.forcetrack = -cls.forcetrack;
|
||||
CL_DemoStartPlayback( DEMO_QUAKE1 );
|
||||
cls.legacymode = PROTO_QUAKE;
|
||||
return; // quake demo is started
|
||||
}
|
||||
|
||||
// read in the demo header
|
||||
FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t ));
|
||||
|
||||
if( demo.header.id != IDEMOHEADER )
|
||||
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, cls.demofile, &demo.header, &demo.directory.numentries ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s is not a demo file\n", demoname );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
if( demo.header.dem_protocol != DEMO_PROTOCOL )
|
||||
{
|
||||
Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
if( demo.header.net_protocol != PROTOCOL_VERSION &&
|
||||
demo.header.net_protocol != PROTOCOL_LEGACY_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
// now read in the directory structure.
|
||||
FS_Seek( cls.demofile, demo.header.directory_offset, SEEK_SET );
|
||||
FS_Read( cls.demofile, &demo.directory.numentries, sizeof( int ));
|
||||
|
||||
if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
|
||||
{
|
||||
Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate demo entries
|
||||
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
|
||||
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( *demo.directory.entries ) * demo.directory.numentries );
|
||||
|
||||
for( i = 0; i < demo.directory.numentries; i++ )
|
||||
{
|
||||
FS_Read( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
|
||||
demoentry_t *entry = &demo.directory.entries[i];
|
||||
|
||||
if( FS_Read( cls.demofile, entry, sizeof( *entry )) != sizeof( *entry ))
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: demo entry %i of %s corrupted", Cmd_Argv( 0 ), i, filename );
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
entry->description[sizeof( entry->description ) - 1] = 0;
|
||||
}
|
||||
|
||||
demo.entryIndex = 0;
|
||||
@@ -1544,9 +1598,11 @@ void CL_PlayDemo_f( void )
|
||||
|
||||
CL_DemoStartPlayback( DEMO_XASH3D );
|
||||
|
||||
// must be after DemoStartPlayback, as CL_Disconnect_f resets the protocol
|
||||
cls.legacymode = CL_GetProtocolFromDemo( demo.header.net_protocol );
|
||||
|
||||
// g-cont. is this need?
|
||||
Q_strncpy( cls.servername, demoname, sizeof( cls.servername ));
|
||||
cls.legacymode = demo.header.net_protocol == PROTOCOL_LEGACY_VERSION;
|
||||
|
||||
// begin a playback demo
|
||||
}
|
||||
@@ -1588,7 +1644,7 @@ void CL_StartDemos_f( void )
|
||||
c = Cmd_Argc() - 1;
|
||||
if( c > MAX_DEMOS )
|
||||
{
|
||||
Con_DPrintf( S_WARN "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS );
|
||||
Con_DPrintf( S_WARN "%s: max %i demos in demoloop\n", __func__, MAX_DEMOS );
|
||||
c = MAX_DEMOS;
|
||||
}
|
||||
|
||||
@@ -1646,3 +1702,78 @@ void CL_Stop_f( void )
|
||||
S_StopBackgroundTrack();
|
||||
}
|
||||
}
|
||||
|
||||
void CL_ListDemo_f( void )
|
||||
{
|
||||
demoheader_t hdr;
|
||||
int32_t num_entries;
|
||||
file_t *f;
|
||||
char filename[MAX_QPATH];
|
||||
char demoname[MAX_QPATH];
|
||||
int i;
|
||||
|
||||
if( Cmd_Argc() < 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ));
|
||||
COM_StripExtension( demoname );
|
||||
Q_snprintf( filename, sizeof( filename ), "%s.dem", demoname );
|
||||
|
||||
f = FS_Open( filename, "rb", true );
|
||||
if( !f )
|
||||
{
|
||||
Con_Printf( S_ERROR "couldn't open %s\n", filename );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, f, &hdr, &num_entries ))
|
||||
{
|
||||
FS_Close( f );
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf( "Demo contents for %s:\n"
|
||||
"\tProtocol: %i net/%i demo\n"
|
||||
"\tFPS: %g\n"
|
||||
"\tMap: %s\n"
|
||||
"\tComment: %s\n"
|
||||
"\tGame: %s\n",
|
||||
filename, hdr.net_protocol, hdr.dem_protocol, hdr.host_fps, hdr.mapname,
|
||||
hdr.comment, hdr.gamedir );
|
||||
|
||||
for( i = 0; i < num_entries; i++ )
|
||||
{
|
||||
demoentry_t entry;
|
||||
|
||||
Con_Printf( "Demo entry #%i:\n", i );
|
||||
|
||||
if( FS_Read( f, &entry, sizeof( entry )) != sizeof( entry ))
|
||||
{
|
||||
Con_Printf( S_ERROR "can't read demo entry\n" );
|
||||
FS_Close( f );
|
||||
return;
|
||||
}
|
||||
|
||||
entry.description[sizeof( entry.description ) - 1] = 0;
|
||||
|
||||
if( entry.entrytype == DEMO_STARTUP )
|
||||
{
|
||||
// startup entries don't have anything useful
|
||||
Con_Printf( "\tEntry type: " S_YELLOW "startup" S_DEFAULT "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( "\tEntry type: " S_GREEN "normal" S_DEFAULT " (%i)\n"
|
||||
"\tEntry playback time/frames: %.2f seconds/%i frames\n"
|
||||
"\tEntry flags: 0x%x\n"
|
||||
"\tEntry description: %s\n",
|
||||
entry.entrytype, entry.playback_time, entry.playback_frames,
|
||||
entry.flags, entry.description );
|
||||
}
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
}
|
||||
|
||||
@@ -28,10 +28,51 @@ GNU General Public License for more details.
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
#define NUM_EFRAGS_ALLOC 64 // alloc 64 efrags (1-2kb each alloc)
|
||||
|
||||
static efrag_t **lastlink;
|
||||
static mnode_t *r_pefragtopnode;
|
||||
static vec3_t r_emins, r_emaxs;
|
||||
static cl_entity_t *r_addent;
|
||||
static int cl_efrags_num;
|
||||
static efrag_t *cl_efrags;
|
||||
|
||||
static efrag_t *CL_AllocEfrags( int num )
|
||||
{
|
||||
int i;
|
||||
efrag_t *efrags;
|
||||
|
||||
if( !cl.worldmodel )
|
||||
{
|
||||
Host_Error( "%s: called with NULL world\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( num == 0 )
|
||||
return NULL;
|
||||
|
||||
// set world to be the owner, so it will get automatically cleaned up
|
||||
efrags = Mem_Calloc( cl.worldmodel->mempool, sizeof( *efrags ) * num );
|
||||
|
||||
// initialize linked list
|
||||
for( i = 0; i < num - 1; i++ )
|
||||
efrags[i].entnext = &efrags[i + 1];
|
||||
|
||||
cl_efrags_num += num;
|
||||
|
||||
return efrags;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_ClearEfrags
|
||||
==============
|
||||
*/
|
||||
void CL_ClearEfrags( void )
|
||||
{
|
||||
cl_efrags_num = 0;
|
||||
cl_efrags = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
@@ -56,14 +97,11 @@ static void R_SplitEntityOnNode( mnode_t *node )
|
||||
leaf = (mleaf_t *)node;
|
||||
|
||||
// grab an efrag off the free list
|
||||
ef = clgame.free_efrags;
|
||||
ef = cl_efrags;
|
||||
if( !ef )
|
||||
{
|
||||
Con_Printf( S_ERROR "too many efrags!\n" );
|
||||
return; // no free fragments...
|
||||
}
|
||||
ef = CL_AllocEfrags( NUM_EFRAGS_ALLOC );
|
||||
|
||||
clgame.free_efrags = ef->entnext;
|
||||
cl_efrags = ef->entnext;
|
||||
ef->entity = r_addent;
|
||||
|
||||
// add the entity link
|
||||
@@ -133,35 +171,29 @@ R_StoreEfrags
|
||||
*/
|
||||
void R_StoreEfrags( efrag_t **ppefrag, int framecount )
|
||||
{
|
||||
cl_entity_t *pent;
|
||||
model_t *clmodel;
|
||||
efrag_t *pefrag;
|
||||
efrag_t *pefrag;
|
||||
cl_entity_t *pent;
|
||||
model_t *clmodel;
|
||||
|
||||
while(( pefrag = *ppefrag ) != NULL )
|
||||
{
|
||||
pent = pefrag->entity;
|
||||
clmodel = pent->model;
|
||||
|
||||
switch( clmodel->type )
|
||||
{
|
||||
case mod_alias:
|
||||
case mod_brush:
|
||||
case mod_studio:
|
||||
case mod_sprite:
|
||||
if( pent->visframe != framecount )
|
||||
{
|
||||
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
|
||||
{
|
||||
// mark that we've recorded this entity for this frame
|
||||
pent->curstate.messagenum = cl.parsecount;
|
||||
pent->visframe = framecount;
|
||||
}
|
||||
}
|
||||
// how this could happen?
|
||||
if( unlikely( clmodel->type < mod_brush || clmodel->type > mod_studio ))
|
||||
continue;
|
||||
|
||||
ppefrag = &pefrag->leafnext;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if( pent->visframe != framecount )
|
||||
{
|
||||
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
|
||||
{
|
||||
// mark that we've recorded this entity for this frame
|
||||
pent->curstate.messagenum = cl.parsecount;
|
||||
pent->visframe = framecount;
|
||||
}
|
||||
}
|
||||
|
||||
ppefrag = &pefrag->leafnext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
|
||||
VectorCopy( vel, p->vel );
|
||||
p->die = cl.time + life;
|
||||
p->ramp = tracerlength.value;
|
||||
p->color = 4; // select custom color
|
||||
p->color = TRACER_COLORINDEX_DEFAULT; // select custom color
|
||||
p->packedColor = 255; // alpha
|
||||
|
||||
return p;
|
||||
@@ -636,12 +636,24 @@ and all particle trails (if this is a beamfollow)
|
||||
*/
|
||||
void GAME_EXPORT R_BeamKill( int deadEntity )
|
||||
{
|
||||
cl_entity_t *pDeadEntity;
|
||||
BEAM *beam;
|
||||
|
||||
pDeadEntity = R_BeamGetEntity( deadEntity );
|
||||
if( !pDeadEntity ) return;
|
||||
for( beam = cl_active_beams; beam; beam = beam->next )
|
||||
{
|
||||
if( FBitSet( beam->flags, FBEAM_STARTENTITY ) && beam->startEntity == deadEntity )
|
||||
{
|
||||
if( beam->type != TE_BEAMFOLLOW )
|
||||
beam->die = cl.time;
|
||||
|
||||
CL_KillDeadBeams( pDeadEntity );
|
||||
ClearBits( beam->flags, FBEAM_STARTENTITY );
|
||||
}
|
||||
|
||||
if( FBitSet( beam->flags, FBEAM_ENDENTITY ) && beam->endEntity == deadEntity )
|
||||
{
|
||||
beam->die = cl.time;
|
||||
ClearBits( beam->flags, FBEAM_ENDENTITY );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1094,9 +1106,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
|
||||
int colorMod = 0, packedColor;
|
||||
particle_t *p;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
packedColor = 255; // use old code for blob particles
|
||||
else packedColor = 0;
|
||||
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
|
||||
|
||||
for( i = 0; i < 512; i++ )
|
||||
{
|
||||
@@ -1129,9 +1139,7 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
|
||||
particle_t *p;
|
||||
int i, j, packedColor;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
packedColor = 255; // use old code for blob particles
|
||||
else packedColor = 0;
|
||||
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
|
||||
|
||||
for( i = 0; i < 1024; i++ )
|
||||
{
|
||||
|
||||
@@ -192,7 +192,7 @@ void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func )
|
||||
ev = clgame.events[lastnum];
|
||||
|
||||
// NOTE: ev->index will be set later
|
||||
Q_strncpy( ev->name, szEvName, MAX_QPATH );
|
||||
Q_strncpy( ev->name, szEvName, sizeof( ev->name ));
|
||||
ev->func = func;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
|
||||
if( !ev )
|
||||
{
|
||||
idx = bound( 1, ei->index, ( MAX_EVENTS - 1 ));
|
||||
Con_Reportf( S_ERROR "CL_FireEvent: %s not precached\n", cl.event_precache[idx] );
|
||||
Con_Reportf( S_ERROR "%s: %s not precached\n", __func__, cl.event_precache[idx] );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
|
||||
return true;
|
||||
}
|
||||
|
||||
Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name );
|
||||
Con_Reportf( S_ERROR "%s: %s not hooked\n", __func__, name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -497,14 +497,14 @@ void GAME_EXPORT CL_PlaybackEvent( int flags, const edict_t *pInvoker, word even
|
||||
// first check event for out of bounds
|
||||
if( eventindex < 1 || eventindex >= MAX_EVENTS )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex );
|
||||
Con_DPrintf( S_ERROR "%s: invalid eventindex %i\n", __func__, eventindex );
|
||||
return;
|
||||
}
|
||||
|
||||
// check event for precached
|
||||
if( !CL_EventIndex( cl.event_precache[eventindex] ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_PlaybackEvent: event %i was not precached\n", eventindex );
|
||||
Con_DPrintf( S_ERROR "%s: event %i was not precached\n", __func__, eventindex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,8 +95,7 @@ static void CL_ResetPositions( cl_entity_t *ent )
|
||||
ent->current_position = 1;
|
||||
|
||||
memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX );
|
||||
memcpy( &ent->ph[1], &store, sizeof( position_history_t ));
|
||||
memcpy( &ent->ph[0], &store, sizeof( position_history_t ));
|
||||
ent->ph[1] = ent->ph[0] = store;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -712,7 +711,7 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
|
||||
break; // done
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "CL_FlushEntityPacket: overflow\n" );
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ) ? DELTA_PLAYER : DELTA_ENTITY, cl.mtime[0] );
|
||||
}
|
||||
@@ -740,7 +739,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
|
||||
|
||||
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
|
||||
Con_DPrintf( S_ERROR "%s: invalid newnum: %d\n", __func__, newnum );
|
||||
if( has_update )
|
||||
MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
|
||||
return;
|
||||
@@ -752,7 +751,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
|
||||
|
||||
if( has_update )
|
||||
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
|
||||
else memcpy( state, old, sizeof( entity_state_t ));
|
||||
else *state = *old;
|
||||
|
||||
if( !alive )
|
||||
{
|
||||
@@ -885,7 +884,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
break; // done
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "CL_ParsePacketEntities: overflow\n" );
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
player = CL_IsPlayerIndex( newnum );
|
||||
|
||||
@@ -955,7 +954,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
||||
}
|
||||
|
||||
if( newframe->num_entities != count && newframe->num_entities != 0 )
|
||||
Con_Reportf( S_WARN "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count );
|
||||
Con_Reportf( S_WARN "%s%s: (%i should be %i)\n", __func__, delta ? "Delta" : "", newframe->num_entities, count );
|
||||
|
||||
if( !newframe->valid )
|
||||
return playerbytes; // frame is not valid but message was parsed
|
||||
@@ -1187,7 +1186,7 @@ static void CL_LinkPacketEntities( frame_t *frame )
|
||||
|
||||
if( !ent )
|
||||
{
|
||||
Con_Reportf( S_ERROR "CL_LinkPacketEntity: bad entity %i\n", state->number );
|
||||
Con_Reportf( S_ERROR "%s: bad entity %i\n", __func__, state->number );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ static void CL_InitCDAudio( const char *filename )
|
||||
|
||||
if( ++c > MAX_CDTRACKS - 1 )
|
||||
{
|
||||
Con_Reportf( S_WARN "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename );
|
||||
Con_Reportf( S_WARN "%s: too many tracks %i in %s\n", __func__, MAX_CDTRACKS, filename );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -560,7 +560,19 @@ static void CL_DrawScreenFade( void )
|
||||
if( !alpha )
|
||||
return;
|
||||
|
||||
if( FBitSet( sf->fadeFlags, FFADE_MODULATE ))
|
||||
if( !FBitSet( sf->fadeFlags, FFADE_MODULATE ))
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
|
||||
}
|
||||
else if( Host_IsQuakeCompatible( ))
|
||||
{
|
||||
// Quake Wrapper and Quake Remake use FFADE_MODULATE for item pickups
|
||||
// so hack the check here
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
|
||||
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderScreenFadeModulate );
|
||||
|
||||
@@ -570,11 +582,6 @@ static void CL_DrawScreenFade( void )
|
||||
(uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8,
|
||||
255 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1,
|
||||
R_GetBuiltinTexture( REF_WHITE_TEXTURE ));
|
||||
@@ -777,14 +784,14 @@ static const char *CL_SoundFromIndex( int index )
|
||||
|
||||
if( !hSound )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_SoundFromIndex: invalid sound index %i\n", index );
|
||||
Con_DPrintf( S_ERROR "%s: invalid sound index %i\n", __func__, index );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sfx = S_GetSfxByHandle( hSound );
|
||||
if( !sfx )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_SoundFromIndex: bad sfx for index %i\n", index );
|
||||
Con_DPrintf( S_ERROR "%s: bad sfx for index %i\n", __func__, index );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1041,10 +1048,10 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
|
||||
int i;
|
||||
|
||||
if( !pszName || !*pszName )
|
||||
Host_Error( "CL_LinkUserMessage: bad message name\n" );
|
||||
Host_Error( "%s: bad message name\n", __func__ );
|
||||
|
||||
if( svc_num <= svc_lastmsg )
|
||||
Host_Error( "CL_LinkUserMessage: tried to hook a system message \"%s\"\n", svc_strings[svc_num] );
|
||||
Host_Error( "%s: tried to hook a system message \"%s\"\n", __func__, svc_strings[svc_num] );
|
||||
|
||||
// see if already hooked
|
||||
for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ )
|
||||
@@ -1061,7 +1068,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
|
||||
|
||||
if( i == MAX_USER_MESSAGES )
|
||||
{
|
||||
Host_Error( "CL_LinkUserMessage: MAX_USER_MESSAGES hit!\n" );
|
||||
Host_Error( "%s: MAX_USER_MESSAGES hit!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1182,7 +1189,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
|
||||
if( type == SPR_CLIENT || type == SPR_HUDSPRITE )
|
||||
SetBits( m_pSprite->flags, MODEL_CLIENT );
|
||||
|
||||
m_pSprite->numtexinfo = texFlags; // store texFlags into numtexinfo
|
||||
m_pSprite->numtexinfo = texFlags; // store texFlags for renderer into numtexinfo
|
||||
|
||||
if( !FS_FileExists( szSpriteName, false ) )
|
||||
{
|
||||
@@ -1209,7 +1216,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
|
||||
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
|
||||
else
|
||||
{
|
||||
Mod_LoadSpriteModel( m_pSprite, buf, &loaded, texFlags );
|
||||
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
|
||||
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
|
||||
}
|
||||
|
||||
@@ -1242,7 +1249,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
|
||||
|
||||
if( !COM_CheckString( filename ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" );
|
||||
Con_Reportf( S_ERROR "%s: bad name!\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1448,7 +1455,7 @@ pfnSPR_Draw
|
||||
*/
|
||||
static void GAME_EXPORT pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc )
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransAlpha );
|
||||
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
|
||||
}
|
||||
|
||||
@@ -1503,12 +1510,12 @@ static void GAME_EXPORT pfnSPR_DrawAdditive( int frame, int x, int y, const wrec
|
||||
|
||||
/*
|
||||
=========
|
||||
pfnSPR_GetList
|
||||
SPR_GetList
|
||||
|
||||
for parsing half-life scripts - hud.txt etc
|
||||
=========
|
||||
*/
|
||||
static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount )
|
||||
static client_sprite_t *SPR_GetList( char *psz, int *piCount )
|
||||
{
|
||||
cached_spritelist_t *pEntry = &clgame.sprlist[0];
|
||||
int slot, index, numSprites = 0;
|
||||
@@ -1534,7 +1541,7 @@ static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount )
|
||||
|
||||
if( slot == MAX_CLIENT_SPRITES )
|
||||
{
|
||||
Con_Printf( S_ERROR "SPR_GetList: overflow cache!\n" );
|
||||
Con_Printf( S_ERROR "%s: overflow cache!\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1743,7 +1750,7 @@ static int GAME_EXPORT pfnHookUserMsg( const char *pszName, pfnUserMsgHook pfn )
|
||||
|
||||
if( i == MAX_USER_MESSAGES )
|
||||
{
|
||||
Host_Error( "HookUserMsg: MAX_USER_MESSAGES hit!\n" );
|
||||
Host_Error( "%s: MAX_USER_MESSAGES hit!\n", __func__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2293,7 +2300,7 @@ static void GAME_EXPORT pfnHookEvent( const char *filename, pfnEventHook pfn )
|
||||
|
||||
if( !Q_stricmp( name, ev->name ) && ev->func != NULL )
|
||||
{
|
||||
Con_Reportf( S_WARN "CL_HookEvent: %s already hooked!\n", name );
|
||||
Con_Reportf( S_WARN "%s: %s already hooked!\n", __func__, name );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2376,7 +2383,7 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
|
||||
if( lasttimewarn < host.realtime )
|
||||
{
|
||||
// tell user about problem (but don't spam console)
|
||||
Con_Printf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
|
||||
Con_DPrintf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
|
||||
lasttimewarn = host.realtime + 1.0f;
|
||||
}
|
||||
|
||||
@@ -2428,8 +2435,8 @@ static void GAME_EXPORT pfnLocalPlayerBounds( int hull, float *mins, float *maxs
|
||||
{
|
||||
if( hull >= 0 && hull < 4 )
|
||||
{
|
||||
if( mins ) VectorCopy( clgame.pmove->player_mins[hull], mins );
|
||||
if( maxs ) VectorCopy( clgame.pmove->player_maxs[hull], maxs );
|
||||
if( mins ) VectorCopy( host.player_mins[hull], mins );
|
||||
if( maxs ) VectorCopy( host.player_maxs[hull], maxs );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2497,9 +2504,17 @@ CL_PushTraceBounds
|
||||
*/
|
||||
static void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs )
|
||||
{
|
||||
if( !host.trace_bounds_pushed )
|
||||
{
|
||||
memcpy( host.player_mins_backup, host.player_mins, sizeof( host.player_mins_backup ));
|
||||
memcpy( host.player_maxs_backup, host.player_maxs, sizeof( host.player_maxs_backup ));
|
||||
|
||||
host.trace_bounds_pushed = true;
|
||||
}
|
||||
|
||||
hullnum = bound( 0, hullnum, 3 );
|
||||
VectorCopy( mins, clgame.pmove->player_mins[hullnum] );
|
||||
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] );
|
||||
VectorCopy( mins, host.player_mins[hullnum] );
|
||||
VectorCopy( maxs, host.player_maxs[hullnum] );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2510,8 +2525,15 @@ CL_PopTraceBounds
|
||||
*/
|
||||
static void GAME_EXPORT CL_PopTraceBounds( void )
|
||||
{
|
||||
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins ));
|
||||
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs ));
|
||||
if( !host.trace_bounds_pushed )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s called without push!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
host.trace_bounds_pushed = false;
|
||||
memcpy( host.player_mins, host.player_mins_backup, sizeof( host.player_mins ));
|
||||
memcpy( host.player_maxs, host.player_maxs_backup, sizeof( host.player_maxs ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2788,10 +2810,10 @@ static void GAME_EXPORT PlayerInfo_SetValueForKey( const char *key, const char *
|
||||
{
|
||||
Cvar_DirectSet( var, value );
|
||||
}
|
||||
else if( Info_SetValueForStarKey( cls.userinfo, key, value, MAX_INFO_STRING ))
|
||||
else if( Info_SetValueForStarKey( cls.userinfo, key, value, sizeof( cls.userinfo )))
|
||||
{
|
||||
// time to update server copy of userinfo
|
||||
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", key, value );
|
||||
CL_UpdateInfo( key, value );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3283,7 +3305,7 @@ Heavy legacy of Quake...
|
||||
*/
|
||||
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode )
|
||||
{
|
||||
if( clgame.ds.renderMode == kRenderTransAlpha )
|
||||
if( rendermode == kRenderTransAlpha )
|
||||
{
|
||||
clgame.ds.triRGBA[3] = a / 255.0f;
|
||||
ref.dllFuncs.Color4f( r, g, b, a );
|
||||
@@ -3415,16 +3437,15 @@ NetAPI_SendRequest
|
||||
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
|
||||
{
|
||||
net_request_t *nr = NULL;
|
||||
string req;
|
||||
int i;
|
||||
|
||||
if( !response )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Net_SendRequest: no callbcak specified for request with context %i!\n", context );
|
||||
Con_DPrintf( S_ERROR "%s: no callbcak specified for request with context %i!\n", __func__, context );
|
||||
return;
|
||||
}
|
||||
|
||||
if( remote_address->type != NA_IPX && remote_address->type != NA_BROADCAST_IPX )
|
||||
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
@@ -3467,8 +3488,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
nr->flags = flags;
|
||||
|
||||
// local servers request
|
||||
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3772,7 +3792,7 @@ static demo_api_t gDemoApi =
|
||||
Demo_WriteBuffer,
|
||||
};
|
||||
|
||||
static net_api_t gNetApi =
|
||||
net_api_t gNetApi =
|
||||
{
|
||||
NetAPI_InitNetworking,
|
||||
NetAPI_Status,
|
||||
@@ -3808,7 +3828,7 @@ static cl_enginefunc_t gEngfuncs =
|
||||
pfnSPR_DrawAdditive,
|
||||
SPR_EnableScissor,
|
||||
SPR_DisableScissor,
|
||||
pfnSPR_GetList,
|
||||
SPR_GetList,
|
||||
CL_FillRGBA,
|
||||
CL_GetScreenInfo,
|
||||
pfnSetCrosshair,
|
||||
@@ -4030,14 +4050,14 @@ qboolean CL_LoadProgs( const char *name )
|
||||
// trying to get single export
|
||||
if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
|
||||
{
|
||||
Con_Reportf( "CL_LoadProgs: found single callback export\n" );
|
||||
Con_Reportf( "%s: found single callback export\n", __func__ );
|
||||
|
||||
// trying to fill interface now
|
||||
GetClientAPI( &clgame.dllFuncs );
|
||||
}
|
||||
else if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "F" )) != NULL )
|
||||
{
|
||||
Con_Reportf( "CL_LoadProgs: found single callback export (secured client dlls)\n" );
|
||||
Con_Reportf( "%s: found single callback export (secured client dlls)\n", __func__ );
|
||||
|
||||
// trying to fill interface now
|
||||
CL_GetSecuredClientAPI( GetClientAPI );
|
||||
@@ -4065,7 +4085,7 @@ qboolean CL_LoadProgs( const char *name )
|
||||
// functions are cleared before all the extensions are evaluated
|
||||
if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
|
||||
{
|
||||
Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name );
|
||||
Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
|
||||
|
||||
if( critical_exports )
|
||||
{
|
||||
@@ -4092,13 +4112,13 @@ qboolean CL_LoadProgs( const char *name )
|
||||
// functions are cleared before all the extensions are evaluated
|
||||
// NOTE: new exports can be missed without stop the engine
|
||||
if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
|
||||
Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name );
|
||||
Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
|
||||
}
|
||||
|
||||
if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION ))
|
||||
{
|
||||
COM_FreeLibrary( clgame.hInstance );
|
||||
Con_Reportf( "CL_LoadProgs: can't init client API\n" );
|
||||
Con_Reportf( "%s: can't init client API\n", __func__ );
|
||||
clgame.hInstance = NULL;
|
||||
return false;
|
||||
}
|
||||
@@ -4115,10 +4135,10 @@ qboolean CL_LoadProgs( const char *name )
|
||||
CL_InitTempEnts ();
|
||||
|
||||
if( !R_InitRenderAPI()) // Xash3D extension
|
||||
Con_Reportf( S_WARN "CL_LoadProgs: couldn't get render API\n" );
|
||||
Con_Reportf( S_WARN "%s: couldn't get render API\n", __func__ );
|
||||
|
||||
if( !Mobile_Init() ) // Xash3D FWGS extension: mobile interface
|
||||
Con_Reportf( S_WARN "CL_LoadProgs: couldn't get mobility API\n" );
|
||||
Con_Reportf( S_WARN "%s: couldn't get mobility API\n", __func__ );
|
||||
|
||||
CL_InitEdicts( cl.maxclients ); // initailize local player and world
|
||||
CL_InitClientMove(); // initialize pm_shared
|
||||
|
||||
@@ -25,6 +25,14 @@ static void UI_UpdateUserinfo( void );
|
||||
|
||||
gameui_static_t gameui;
|
||||
|
||||
static void UI_ToggleAllowConsole_f( void )
|
||||
{
|
||||
host.allow_console = host.allow_console_init = true;
|
||||
|
||||
if( gameui.globals )
|
||||
gameui.globals->developer = true;
|
||||
}
|
||||
|
||||
void UI_UpdateMenu( float realtime )
|
||||
{
|
||||
if( !gameui.hInstance ) return;
|
||||
@@ -216,12 +224,14 @@ UI_ShowConnectionWarning
|
||||
show message box
|
||||
=================
|
||||
*/
|
||||
void UI_ShowMessageBox( const char *text )
|
||||
qboolean UI_ShowMessageBox( const char *text )
|
||||
{
|
||||
if( gameui.dllFuncs2.pfnShowMessageBox )
|
||||
{
|
||||
gameui.dllFuncs2.pfnShowMessageBox( text );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UI_ConnectionProgress_Disconnect( void )
|
||||
@@ -397,17 +407,21 @@ void Host_Credits( void )
|
||||
gameui.dllFuncs.pfnFinalCredits();
|
||||
}
|
||||
|
||||
static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
|
||||
static void UI_ConvertGameInfo( gameinfo2_t *out, const gameinfo_t *in )
|
||||
{
|
||||
out->gi_version = GAMEINFO_VERSION;
|
||||
|
||||
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
|
||||
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
|
||||
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
|
||||
Q_strncpy( out->demomap, in->demomap, sizeof( out->demomap ));
|
||||
Q_strncpy( out->title, in->title, sizeof( out->title ));
|
||||
Q_snprintf( out->version, sizeof( out->version ), "%g", in->version );
|
||||
Q_strncpy( out->iconpath, in->iconpath, sizeof( out->iconpath ));
|
||||
|
||||
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
|
||||
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
|
||||
Q_strncpy( out->size, Q_pretifymem( in->size, 0 ), sizeof( out->size ));
|
||||
out->size = in->size;
|
||||
Q_strncpy( out->type, in->type, sizeof( out->type ));
|
||||
Q_strncpy( out->date, in->date, sizeof( out->date ));
|
||||
|
||||
@@ -425,6 +439,31 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
|
||||
SetBits( out->flags, GFL_ANIMATED_TITLE );
|
||||
}
|
||||
|
||||
static void UI_ToOldGameInfo( GAMEINFO *out, const gameinfo2_t *in )
|
||||
{
|
||||
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
|
||||
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
|
||||
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
|
||||
Q_strncpy( out->title, in->title, sizeof( out->title ));
|
||||
Q_strncpy( out->version, in->version, sizeof( out->version ));
|
||||
out->flags = in->flags & 0xFFFF;
|
||||
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
|
||||
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
|
||||
Q_strncpy( out->size, Q_memprint( in->size ), sizeof( out->size ));
|
||||
Q_strncpy( out->type, in->type, sizeof( out->type ));
|
||||
Q_strncpy( out->date, in->date, sizeof( out->date ));
|
||||
out->gamemode = in->gamemode;
|
||||
}
|
||||
|
||||
static void UI_GetModsInfo( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
gameui.modsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.modsInfo ) * FI->numgames );
|
||||
for( i = 0; i < FI->numgames; i++ )
|
||||
UI_ConvertGameInfo( &gameui.modsInfo[i], FI->games[i] );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
PIC_DrawGeneric
|
||||
@@ -492,7 +531,7 @@ static HIMAGE GAME_EXPORT pfnPIC_Load( const char *szPicName, const byte *image_
|
||||
|
||||
if( !COM_CheckString( szPicName ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "CL_LoadImage: refusing to load image with empty name\n" );
|
||||
Con_Reportf( S_ERROR "%s: refusing to load image with empty name\n", __func__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -922,11 +961,12 @@ pfnGetGameInfo
|
||||
|
||||
=========
|
||||
*/
|
||||
static int GAME_EXPORT pfnGetGameInfo( GAMEINFO *pgameinfo )
|
||||
static int GAME_EXPORT pfnGetOldGameInfo( GAMEINFO *pgameinfo )
|
||||
{
|
||||
if( !pgameinfo ) return 0;
|
||||
if( !pgameinfo )
|
||||
return 0;
|
||||
|
||||
*pgameinfo = gameui.gameInfo;
|
||||
UI_ToOldGameInfo( pgameinfo, &gameui.gameInfo );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -938,8 +978,26 @@ pfnGetGamesList
|
||||
*/
|
||||
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
|
||||
{
|
||||
if( numGames ) *numGames = FI->numgames;
|
||||
return gameui.modsInfo;
|
||||
if( numGames )
|
||||
*numGames = FI->numgames;
|
||||
|
||||
if( !gameui.oldModsInfo )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !gameui.modsInfo )
|
||||
UI_GetModsInfo();
|
||||
|
||||
// first allocate array of pointers
|
||||
gameui.oldModsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo ) * FI->numgames );
|
||||
for( i = 0; i < FI->numgames; i++ )
|
||||
{
|
||||
gameui.oldModsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo[i] ));
|
||||
UI_ToOldGameInfo( gameui.oldModsInfo[i], &gameui.modsInfo[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return gameui.oldModsInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1011,7 +1069,7 @@ pfnChangeInstance
|
||||
*/
|
||||
static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage )
|
||||
{
|
||||
Con_Reportf( S_ERROR "ChangeInstance menu call is deprecated!\n" );
|
||||
Con_Reportf( S_ERROR "%s menu call is deprecated!\n", __func__ );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1097,8 +1155,22 @@ static void GAME_EXPORT pfnCon_DefaultColor( int r, int g, int b )
|
||||
Con_DefaultColor( r, g, b, true );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnSetCursor( void *hCursor )
|
||||
{
|
||||
uintptr_t cursor;
|
||||
|
||||
if( !gameui.use_extended_api )
|
||||
return; // ignore original Xash menus
|
||||
|
||||
cursor = (uintptr_t)hCursor;
|
||||
if( cursor < dc_user || cursor > dc_last )
|
||||
return;
|
||||
|
||||
Platform_SetCursorType( cursor );
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
static ui_enginefuncs_t gEngfuncs =
|
||||
static const ui_enginefuncs_t gEngfuncs =
|
||||
{
|
||||
pfnPIC_Load,
|
||||
GL_FreeImage,
|
||||
@@ -1162,7 +1234,7 @@ static ui_enginefuncs_t gEngfuncs =
|
||||
pfnKeyGetState,
|
||||
pfnMemAlloc,
|
||||
pfnMemFree,
|
||||
pfnGetGameInfo,
|
||||
pfnGetOldGameInfo,
|
||||
pfnGetGamesList,
|
||||
pfnGetFilesList,
|
||||
SV_GetSaveComment,
|
||||
@@ -1176,7 +1248,7 @@ static ui_enginefuncs_t gEngfuncs =
|
||||
pfnHostEndGame,
|
||||
COM_RandomFloat,
|
||||
COM_RandomLong,
|
||||
IN_SetCursor,
|
||||
pfnSetCursor,
|
||||
pfnIsMapValid,
|
||||
GL_ProcessTexture,
|
||||
COM_CompareFileTime,
|
||||
@@ -1209,6 +1281,28 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static gameinfo2_t *pfnGetGameInfo( int gi_version )
|
||||
{
|
||||
if( gi_version != gameui.gameInfo.gi_version )
|
||||
return NULL;
|
||||
|
||||
return &gameui.gameInfo;
|
||||
}
|
||||
|
||||
static gameinfo2_t *pfnGetModInfo( int gi_version, int i )
|
||||
{
|
||||
if( i < 0 || i >= FI->numgames )
|
||||
return NULL;
|
||||
|
||||
if( !gameui.modsInfo )
|
||||
UI_GetModsInfo();
|
||||
|
||||
if( gi_version != gameui.modsInfo[i].gi_version )
|
||||
return NULL;
|
||||
|
||||
return &gameui.modsInfo[i];
|
||||
}
|
||||
|
||||
static ui_extendedfuncs_t gExtendedfuncs =
|
||||
{
|
||||
pfnEnableTextInput,
|
||||
@@ -1221,6 +1315,9 @@ static ui_extendedfuncs_t gExtendedfuncs =
|
||||
NET_AdrToString,
|
||||
NET_CompareAdrSort,
|
||||
Sys_GetNativeObject,
|
||||
&gNetApi,
|
||||
pfnGetGameInfo,
|
||||
pfnGetModInfo,
|
||||
};
|
||||
|
||||
void UI_UnloadProgs( void )
|
||||
@@ -1230,6 +1327,7 @@ void UI_UnloadProgs( void )
|
||||
// deinitialize game
|
||||
gameui.dllFuncs.pfnShutdown();
|
||||
|
||||
Cmd_RemoveCommand( "ui_allowconsole" );
|
||||
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
|
||||
|
||||
Cvar_Unlink( FCVAR_GAMEUIDLL );
|
||||
@@ -1280,71 +1378,65 @@ qboolean UI_LoadProgs( void )
|
||||
if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL )
|
||||
{
|
||||
COM_FreeLibrary( gameui.hInstance );
|
||||
Con_Reportf( "UI_LoadProgs: can't init menu API\n" );
|
||||
Con_Reportf( "%s: can't init menu API\n", __func__ );
|
||||
gameui.hInstance = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
gameui.use_text_api = false;
|
||||
gameui.use_extended_api = false;
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||
gpEngfuncs = gEngfuncs;
|
||||
|
||||
gameui.mempool = Mem_AllocPool( "Menu Pool" );
|
||||
|
||||
if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals ))
|
||||
{
|
||||
COM_FreeLibrary( gameui.hInstance );
|
||||
Con_Reportf( "UI_LoadProgs: can't init menu API\n" );
|
||||
Con_Reportf( "%s: can't init menu API\n", __func__ );
|
||||
Mem_FreePool( &gameui.mempool );
|
||||
gameui.hInstance = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpExtendedfuncs, &gExtendedfuncs, sizeof( gExtendedfuncs ));
|
||||
gpExtendedfuncs = gExtendedfuncs;
|
||||
memset( &gameui.dllFuncs2, 0, sizeof( gameui.dllFuncs2 ));
|
||||
|
||||
// try to initialize new extended API
|
||||
if( ( GetExtAPI = (UIEXTENEDEDAPI)COM_GetProcAddress( gameui.hInstance, "GetExtAPI" ) ) )
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: extended Menu API found\n" );
|
||||
Con_Reportf( "%s: extended Menu API found\n", __func__ );
|
||||
if( GetExtAPI( MENU_EXTENDED_API_VERSION, &gameui.dllFuncs2, &gpExtendedfuncs ) )
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: extended Menu API initialized\n" );
|
||||
gameui.use_text_api = true;
|
||||
Con_Reportf( "%s: extended Menu API initialized\n", __func__ );
|
||||
gameui.use_extended_api = true;
|
||||
}
|
||||
}
|
||||
else // otherwise, fallback to old and deprecated extensions
|
||||
{
|
||||
if( ( GiveTextApi = (UITEXTAPI)COM_GetProcAddress( gameui.hInstance, "GiveTextAPI" ) ) )
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: extended text API found\n" );
|
||||
Con_Reportf( "%s: extended text API found\n", __func__ );
|
||||
Con_Reportf( S_WARN "Text API is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" );
|
||||
if( GiveTextApi( &gpExtendedfuncs ) ) // they are binary compatible, so we can just pass extended funcs API to menu
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: extended text API initialized\n" );
|
||||
gameui.use_text_api = true;
|
||||
Con_Reportf( "%s: extended text API initialized\n", __func__ );
|
||||
gameui.use_extended_api = true;
|
||||
}
|
||||
}
|
||||
|
||||
gameui.dllFuncs2.pfnAddTouchButtonToList = (ADDTOUCHBUTTONTOLIST)COM_GetProcAddress( gameui.hInstance, "AddTouchButtonToList" );
|
||||
if( gameui.dllFuncs2.pfnAddTouchButtonToList )
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: AddTouchButtonToList call found\n" );
|
||||
Con_Reportf( "%s: AddTouchButtonToList call found\n", __func__ );
|
||||
Con_Reportf( S_WARN "AddTouchButtonToList is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
|
||||
|
||||
// setup gameinfo
|
||||
for( i = 0; i < FI->numgames; i++ )
|
||||
{
|
||||
gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO ));
|
||||
UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] );
|
||||
}
|
||||
Cmd_AddRestrictedCommand( "ui_allowconsole", UI_ToggleAllowConsole_f, "unlocks developer console" );
|
||||
|
||||
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo
|
||||
|
||||
|
||||
@@ -31,15 +31,16 @@ GNU General Public License for more details.
|
||||
#define CL_TEST_RETRIES 5
|
||||
|
||||
CVAR_DEFINE_AUTO( mp_decals, "300", FCVAR_ARCHIVE, "decals limit in multiplayer" );
|
||||
CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" );
|
||||
CVAR_DEFINE_AUTO( cl_resend, "6.0", 0, "time to resend connect" );
|
||||
static CVAR_DEFINE_AUTO( dev_overview, "0", 0, "draw level in overview-mode" );
|
||||
static CVAR_DEFINE_AUTO( cl_resend, "6.0", 0, "time to resend connect" );
|
||||
CVAR_DEFINE( cl_allow_download, "cl_allowdownload", "1", FCVAR_ARCHIVE, "allow to downloading resources from the server" );
|
||||
CVAR_DEFINE_AUTO( cl_allow_upload, "1", FCVAR_ARCHIVE, "allow to uploading resources to the server" );
|
||||
static CVAR_DEFINE( cl_allow_upload, "cl_allowupload", "1", FCVAR_ARCHIVE, "allow to uploading resources to the server" );
|
||||
CVAR_DEFINE_AUTO( cl_download_ingame, "1", FCVAR_ARCHIVE, "allow to downloading resources while client is active" );
|
||||
CVAR_DEFINE_AUTO( cl_logofile, "lambda", FCVAR_ARCHIVE, "player logo name" );
|
||||
CVAR_DEFINE_AUTO( cl_logocolor, "orange", FCVAR_ARCHIVE, "player logo color" );
|
||||
CVAR_DEFINE_AUTO( cl_logoext, "bmp", FCVAR_ARCHIVE, "temporary cvar to tell engine which logo must be packed" );
|
||||
CVAR_DEFINE_AUTO( cl_test_bandwidth, "1", FCVAR_ARCHIVE, "test network bandwith before connection" );
|
||||
static CVAR_DEFINE_AUTO( cl_logofile, "lambda", FCVAR_ARCHIVE, "player logo name" );
|
||||
static CVAR_DEFINE_AUTO( cl_logocolor, "orange", FCVAR_ARCHIVE, "player logo color" );
|
||||
static CVAR_DEFINE_AUTO( cl_logoext, "bmp", FCVAR_ARCHIVE, "temporary cvar to tell engine which logo must be packed" );
|
||||
CVAR_DEFINE_AUTO( cl_logomaxdim, "96", FCVAR_ARCHIVE, "maximum decal dimension" );
|
||||
static CVAR_DEFINE_AUTO( cl_test_bandwidth, "1", FCVAR_ARCHIVE, "test network bandwith before connection" );
|
||||
|
||||
CVAR_DEFINE( cl_draw_particles, "r_drawparticles", "1", FCVAR_CHEAT, "render particles" );
|
||||
CVAR_DEFINE( cl_draw_tracers, "r_drawtracers", "1", FCVAR_CHEAT, "render tracers" );
|
||||
@@ -48,17 +49,17 @@ CVAR_DEFINE( cl_draw_beams, "r_drawbeams", "1", FCVAR_CHEAT, "render beams" );
|
||||
static CVAR_DEFINE_AUTO( rcon_address, "", FCVAR_PRIVILEGED, "remote control address" );
|
||||
CVAR_DEFINE_AUTO( cl_timeout, "60", 0, "connect timeout (in-seconds)" );
|
||||
CVAR_DEFINE_AUTO( cl_nopred, "0", FCVAR_ARCHIVE|FCVAR_USERINFO, "disable client movement prediction" );
|
||||
CVAR_DEFINE_AUTO( cl_nodelta, "0", 0, "disable delta-compression for server messages" );
|
||||
static CVAR_DEFINE_AUTO( cl_nodelta, "0", 0, "disable delta-compression for server messages" );
|
||||
CVAR_DEFINE( cl_crosshair, "crosshair", "1", FCVAR_ARCHIVE, "show weapon chrosshair" );
|
||||
static CVAR_DEFINE_AUTO( cl_cmdbackup, "10", FCVAR_ARCHIVE, "how many additional history commands are sent" );
|
||||
CVAR_DEFINE_AUTO( cl_showerror, "0", FCVAR_ARCHIVE, "show prediction error" );
|
||||
CVAR_DEFINE_AUTO( cl_bmodelinterp, "1", FCVAR_ARCHIVE, "enable bmodel interpolation" );
|
||||
CVAR_DEFINE_AUTO( cl_lightstyle_lerping, "0", FCVAR_ARCHIVE, "enables animated light lerping (perfomance option)" );
|
||||
static CVAR_DEFINE_AUTO( cl_lightstyle_lerping, "0", FCVAR_ARCHIVE, "enables animated light lerping (perfomance option)" );
|
||||
CVAR_DEFINE_AUTO( cl_idealpitchscale, "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" );
|
||||
CVAR_DEFINE_AUTO( cl_nosmooth, "0", FCVAR_ARCHIVE, "disable smooth up stair climbing" );
|
||||
CVAR_DEFINE_AUTO( cl_smoothtime, "0.1", FCVAR_ARCHIVE, "time to smooth up" );
|
||||
CVAR_DEFINE_AUTO( cl_clockreset, "0.1", FCVAR_ARCHIVE, "frametime delta maximum value before reset" );
|
||||
CVAR_DEFINE_AUTO( cl_fixtimerate, "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" );
|
||||
static CVAR_DEFINE_AUTO( cl_fixtimerate, "7.5", FCVAR_ARCHIVE, "time in msec to client clock adjusting" );
|
||||
CVAR_DEFINE_AUTO( hud_fontscale, "1.0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud font texture" );
|
||||
CVAR_DEFINE_AUTO( hud_fontrender, "0", FCVAR_ARCHIVE, "hud font render mode (0: additive, 1: holes, 2: trans)" );
|
||||
CVAR_DEFINE_AUTO( hud_scale, "0", FCVAR_ARCHIVE|FCVAR_LATCH, "scale hud at current resolution" );
|
||||
@@ -68,7 +69,7 @@ CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh ra
|
||||
CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" );
|
||||
CVAR_DEFINE_AUTO( cl_cmdrate, "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
|
||||
CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" );
|
||||
CVAR_DEFINE_AUTO( cl_nointerp, "0", FCVAR_CLIENTDLL, "disable interpolation of entities and players" );
|
||||
CVAR_DEFINE_AUTO( cl_nointerp, "0", 0, "disable interpolation of entities and players" );
|
||||
static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
|
||||
static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
|
||||
|
||||
@@ -86,12 +87,14 @@ CVAR_DEFINE_AUTO( cl_fixmodelinterpolationartifacts, "1", 0, "try to fix up mode
|
||||
//
|
||||
// userinfo
|
||||
//
|
||||
static CVAR_DEFINE_AUTO( name, "player", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
|
||||
static char username[32];
|
||||
static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRINTABLEONLY|FCVAR_FILTERABLE, "player name" );
|
||||
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
|
||||
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
|
||||
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
|
||||
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
|
||||
|
||||
|
||||
client_t cl;
|
||||
client_static_t cls;
|
||||
clgame_static_t clgame;
|
||||
@@ -115,17 +118,12 @@ qboolean CL_IsInGame( void )
|
||||
if( host.type == HOST_DEDICATED )
|
||||
return true; // always active for dedicated servers
|
||||
|
||||
if( cl.background || CL_GetMaxClients() > 1 )
|
||||
if( cl.background || cl.maxclients > 1 )
|
||||
return true; // always active for multiplayer or background map
|
||||
|
||||
return ( cls.key_dest == key_game ); // active if not menu or console
|
||||
}
|
||||
|
||||
qboolean CL_IsInMenu( void )
|
||||
{
|
||||
return ( cls.key_dest == key_menu );
|
||||
}
|
||||
|
||||
qboolean CL_IsInConsole( void )
|
||||
{
|
||||
return ( cls.key_dest == key_console );
|
||||
@@ -222,7 +220,7 @@ An svc_signonnum has been received, perform a client side setup
|
||||
void CL_SignonReply( void )
|
||||
{
|
||||
// g-cont. my favorite message :-)
|
||||
Con_Reportf( "CL_SignonReply: %i\n", cls.signon );
|
||||
Con_Reportf( "%s: %i\n", __func__, cls.signon );
|
||||
|
||||
switch( cls.signon )
|
||||
{
|
||||
@@ -587,21 +585,38 @@ CL_CreateCmd
|
||||
*/
|
||||
static void CL_CreateCmd( void )
|
||||
{
|
||||
usercmd_t nullcmd, *cmd;
|
||||
runcmd_t *pcmd;
|
||||
vec3_t angles;
|
||||
qboolean active;
|
||||
int input_override;
|
||||
int i, ms;
|
||||
usercmd_t nullcmd, *cmd;
|
||||
runcmd_t *pcmd;
|
||||
qboolean active;
|
||||
double accurate_ms;
|
||||
vec3_t angles;
|
||||
int input_override;
|
||||
int i, ms;
|
||||
|
||||
if( cls.state < ca_connected || cls.state == ca_cinematic )
|
||||
return;
|
||||
|
||||
// store viewangles in case it's will be freeze
|
||||
VectorCopy( cl.viewangles, angles );
|
||||
ms = bound( 1, host.frametime * 1000, 255 );
|
||||
input_override = 0;
|
||||
|
||||
// fix rounding error and framerate depending player move
|
||||
accurate_ms = host.frametime * 1000;
|
||||
ms = (int)accurate_ms;
|
||||
cl.frametime_remainder += accurate_ms - ms; // accumulate rounding error each frame
|
||||
|
||||
// add a ms if error accumulates enough
|
||||
if( cl.frametime_remainder >= 1.0 )
|
||||
{
|
||||
int ms2 = (int)cl.frametime_remainder;
|
||||
|
||||
ms += ms2;
|
||||
cl.frametime_remainder -= ms2;
|
||||
}
|
||||
|
||||
// ms can't be negative, rely on error accumulation only if FPS > 1000
|
||||
ms = Q_min( ms, 255 );
|
||||
|
||||
CL_SetSolidEntities();
|
||||
CL_PushPMStates();
|
||||
CL_SetSolidPlayers( cl.playernum );
|
||||
@@ -809,7 +824,7 @@ static void CL_WritePacket( void )
|
||||
from = to;
|
||||
|
||||
if( MSG_CheckOverflow( &buf ))
|
||||
Host_Error( "CL_WritePacket: overflowed command buffer (%i bytes)\n", MAX_CMD_BUFFER );
|
||||
Host_Error( "%s: overflowed command buffer (%i bytes)\n", __func__, MAX_CMD_BUFFER );
|
||||
}
|
||||
|
||||
// calculate a checksum over the move commands
|
||||
@@ -834,7 +849,7 @@ static void CL_WritePacket( void )
|
||||
}
|
||||
|
||||
if( MSG_CheckOverflow( &buf ))
|
||||
Host_Error( "CL_WritePacket: overflowed command buffer (%i bytes)\n", MAX_CMD_BUFFER );
|
||||
Host_Error( "%s: overflowed command buffer (%i bytes)\n", __func__, MAX_CMD_BUFFER );
|
||||
|
||||
// remember outgoing command that we are sending
|
||||
cls.lastoutgoingcommand = cls.netchan.outgoing_sequence;
|
||||
@@ -920,16 +935,16 @@ static void CL_BeginUpload_f( void )
|
||||
memset( &custResource, 0, sizeof( custResource ));
|
||||
COM_HexConvert( name + 4, 32, md5 );
|
||||
|
||||
if( HPAK_ResourceForHash( CUSTOM_RES_PATH, md5, &custResource ))
|
||||
if( HPAK_ResourceForHash( hpk_custom_file.string, md5, &custResource ))
|
||||
{
|
||||
if( memcmp( md5, custResource.rgucMD5_hash, 16 ))
|
||||
{
|
||||
Con_Reportf( "Bogus data retrieved from %s, attempting to delete entry\n", CUSTOM_RES_PATH );
|
||||
HPAK_RemoveLump( CUSTOM_RES_PATH, &custResource );
|
||||
Con_Reportf( "Bogus data retrieved from %s, attempting to delete entry\n", hpk_custom_file.string );
|
||||
HPAK_RemoveLump( hpk_custom_file.string, &custResource );
|
||||
return;
|
||||
}
|
||||
|
||||
if( HPAK_GetDataPointer( CUSTOM_RES_PATH, &custResource, &buf, &size ))
|
||||
if( HPAK_GetDataPointer( hpk_custom_file.string, &custResource, &buf, &size ))
|
||||
{
|
||||
byte md5[16];
|
||||
MD5Context_t ctx;
|
||||
@@ -945,7 +960,7 @@ static void CL_BeginUpload_f( void )
|
||||
Con_Reportf( "Purported: %s\n", MD5_Print( custResource.rgucMD5_hash ) );
|
||||
Con_Reportf( "Actual : %s\n", MD5_Print( md5 ) );
|
||||
Con_Reportf( "Removing conflicting lump\n" );
|
||||
HPAK_RemoveLump( CUSTOM_RES_PATH, &custResource );
|
||||
HPAK_RemoveLump( hpk_custom_file.string, &custResource );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1001,7 +1016,7 @@ static void CL_SendConnectPacket( void )
|
||||
|
||||
if( !NET_StringToAdr( cls.servername, &adr ))
|
||||
{
|
||||
Con_Printf( "CL_SendConnectPacket: bad server address\n");
|
||||
Con_Printf( "%s: bad server address\n", __func__ );
|
||||
cls.connect_time = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1132,7 +1147,7 @@ static void CL_CheckForResend( void )
|
||||
if(( host.realtime - cls.connect_time ) < resendTime )
|
||||
return;
|
||||
|
||||
res = NET_StringToAdrNB( cls.servername, &adr );
|
||||
res = NET_StringToAdrNB( cls.servername, &adr, false );
|
||||
|
||||
if( res == NET_EAI_NONAME )
|
||||
{
|
||||
@@ -1149,7 +1164,7 @@ static void CL_CheckForResend( void )
|
||||
// only retry so many times before failure.
|
||||
if( cls.connect_retry >= CL_CONNECTION_RETRIES )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_CheckForResend: couldn't connected\n" );
|
||||
Con_DPrintf( S_ERROR "%s: couldn't connect\n", __func__ );
|
||||
CL_Disconnect();
|
||||
return;
|
||||
}
|
||||
@@ -1236,7 +1251,7 @@ static void CL_CreateResourceList( void )
|
||||
{
|
||||
SetBits( pNewResource->ucFlags, RES_CUSTOM );
|
||||
memcpy( pNewResource->rgucMD5_hash, rgucMD5_hash, 16 );
|
||||
HPAK_AddLump( false, CUSTOM_RES_PATH, pNewResource, NULL, fp );
|
||||
HPAK_AddLump( false, hpk_custom_file.string, pNewResource, NULL, fp );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1252,16 +1267,28 @@ CL_Connect_f
|
||||
static void CL_Connect_f( void )
|
||||
{
|
||||
string server;
|
||||
qboolean legacyconnect = false;
|
||||
connprotocol_t proto = PROTO_CURRENT;
|
||||
|
||||
// hidden hint to connect by using legacy protocol
|
||||
// hint to connect by using legacy protocol
|
||||
if( Cmd_Argc() == 3 )
|
||||
{
|
||||
legacyconnect = !Q_strcmp( Cmd_Argv( 2 ), "legacy" );
|
||||
const char *s = Cmd_Argv( 2 );
|
||||
|
||||
if( !Q_strcmp( s, "current" ) || !Q_strcmp( s, "49" ))
|
||||
proto = PROTO_CURRENT;
|
||||
else if( !Q_strcmp( s, "legacy" ) || !Q_strcmp( s, "48" ))
|
||||
proto = PROTO_LEGACY;
|
||||
else
|
||||
{
|
||||
// quake protocol only used for demos
|
||||
// goldsrc protocol is not supported yet
|
||||
Con_Printf( "Unknown protocol. Supported are: current, legacy\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "connect <server>\n" );
|
||||
Con_Printf( S_USAGE "connect <server> [protocol]\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1279,7 +1306,7 @@ static void CL_Connect_f( void )
|
||||
Key_SetKeyDest( key_console );
|
||||
|
||||
cls.state = ca_connecting;
|
||||
cls.legacymode = legacyconnect;
|
||||
cls.legacymode = proto;
|
||||
Q_strncpy( cls.servername, server, sizeof( cls.servername ));
|
||||
cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately
|
||||
cls.max_fragment_size = FRAGMENT_MAX_SIZE; // guess a we can establish connection with maximum fragment size
|
||||
@@ -1425,20 +1452,18 @@ static void CL_SendDisconnectMessage( void )
|
||||
|
||||
int CL_GetSplitSize( void )
|
||||
{
|
||||
int splitsize;
|
||||
int splitsize = (int)cl_dlmax.value;
|
||||
|
||||
if( Host_IsDedicated() )
|
||||
return 0;
|
||||
|
||||
if( !(cls.extensions & NET_EXT_SPLITSIZE) )
|
||||
if( !FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
|
||||
return 1400;
|
||||
|
||||
splitsize = cl_dlmax.value;
|
||||
|
||||
if( splitsize < FRAGMENT_MIN_SIZE || splitsize > FRAGMENT_MAX_SIZE )
|
||||
if(( splitsize < FRAGMENT_MIN_SIZE ) || ( splitsize > FRAGMENT_MAX_SIZE ))
|
||||
{
|
||||
Cvar_SetValue( "cl_dlmax", FRAGMENT_DEFAULT_SIZE );
|
||||
return FRAGMENT_DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
return cl_dlmax.value;
|
||||
return (int)cl_dlmax.value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1509,7 +1534,7 @@ This is also called on Host_Error, so it shouldn't cause any errors
|
||||
*/
|
||||
void CL_Disconnect( void )
|
||||
{
|
||||
cls.legacymode = false;
|
||||
cls.legacymode = PROTO_CURRENT;
|
||||
|
||||
if( cls.state == ca_disconnected )
|
||||
return;
|
||||
@@ -1539,7 +1564,7 @@ void CL_Disconnect( void )
|
||||
cls.signon = 0;
|
||||
|
||||
// back to menu in non-developer mode
|
||||
if( host_developer.value || CL_IsInMenu( ))
|
||||
if( host_developer.value || cls.key_dest == key_menu )
|
||||
return;
|
||||
|
||||
UI_SetActiveMenu( true );
|
||||
@@ -1618,9 +1643,17 @@ static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, u
|
||||
#ifndef XASH_ALL_SERVERS
|
||||
Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining );
|
||||
#endif
|
||||
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version
|
||||
// let master know about client version
|
||||
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining );
|
||||
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
|
||||
Info_SetValueForKey( info, "commit", Q_buildcommit(), remaining );
|
||||
Info_SetValueForKey( info, "branch", Q_buildbranch(), remaining );
|
||||
Info_SetValueForKey( info, "os", Q_buildos(), remaining );
|
||||
Info_SetValueForKey( info, "arch", Q_buildarch(), remaining );
|
||||
|
||||
Q_snprintf( temp, sizeof( temp ), "%d", Q_buildnum() );
|
||||
Info_SetValueForKey( info, "buildnum", temp, remaining );
|
||||
|
||||
Q_snprintf( temp, sizeof( temp ), "%x", *key );
|
||||
Info_SetValueForKey( info, "key", temp, remaining );
|
||||
|
||||
@@ -1688,7 +1721,7 @@ static void CL_Reconnect_f( void )
|
||||
|
||||
if( COM_CheckString( cls.servername ))
|
||||
{
|
||||
qboolean legacy = cls.legacymode;
|
||||
connprotocol_t proto = cls.legacymode;
|
||||
|
||||
if( cls.state >= ca_connected )
|
||||
CL_Disconnect();
|
||||
@@ -1697,7 +1730,7 @@ static void CL_Reconnect_f( void )
|
||||
cls.demonum = cls.movienum = -1; // not in the demo loop now
|
||||
cls.state = ca_connecting;
|
||||
cls.signon = 0;
|
||||
cls.legacymode = legacy; // don't change protocol
|
||||
cls.legacymode = proto; // don't change protocol
|
||||
|
||||
Con_Printf( "reconnecting...\n" );
|
||||
}
|
||||
@@ -1710,7 +1743,7 @@ CL_FixupColorStringsForInfoString
|
||||
all the keys and values must be ends with ^7
|
||||
=================
|
||||
*/
|
||||
static void CL_FixupColorStringsForInfoString( const char *in, char *out )
|
||||
static void CL_FixupColorStringsForInfoString( const char *in, char *out, size_t len )
|
||||
{
|
||||
qboolean hasPrefix = false;
|
||||
qboolean endOfKeyVal = false;
|
||||
@@ -1723,7 +1756,7 @@ static void CL_FixupColorStringsForInfoString( const char *in, char *out )
|
||||
count++;
|
||||
}
|
||||
|
||||
while( *in && count < MAX_INFO_STRING )
|
||||
while( *in && count < len )
|
||||
{
|
||||
if( IsColorString( in ))
|
||||
color = ColorIndex( *(in+1));
|
||||
@@ -1794,7 +1827,7 @@ static void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
|
||||
return;
|
||||
}
|
||||
|
||||
CL_FixupColorStringsForInfoString( s, infostring );
|
||||
CL_FixupColorStringsForInfoString( s, infostring, sizeof( infostring ));
|
||||
|
||||
if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" )))
|
||||
{
|
||||
@@ -1823,52 +1856,87 @@ CL_ParseNETInfoMessage
|
||||
Handle a reply from a netinfo
|
||||
=================
|
||||
*/
|
||||
static void CL_ParseNETInfoMessage( netadr_t from, sizebuf_t *msg, const char *s )
|
||||
static void CL_ParseNETInfoMessage( netadr_t from, const char *s )
|
||||
{
|
||||
net_request_t *nr;
|
||||
static char infostring[MAX_INFO_STRING+8];
|
||||
net_request_t *nr = NULL;
|
||||
static char infostring[MAX_PRINT_MSG];
|
||||
int i, context, type;
|
||||
int errorBits = 0;
|
||||
const char *val;
|
||||
size_t slen;
|
||||
|
||||
context = Q_atoi( Cmd_Argv( 1 ));
|
||||
type = Q_atoi( Cmd_Argv( 2 ));
|
||||
while( *s != '\\' ) s++; // fetching infostring
|
||||
|
||||
// check for errors
|
||||
val = Info_ValueForKey( s, "neterror" );
|
||||
|
||||
if( !Q_stricmp( val, "protocol" ))
|
||||
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
|
||||
else if( !Q_stricmp( val, "undefined" ))
|
||||
SetBits( errorBits, NET_ERROR_UNDEFINED );
|
||||
|
||||
CL_FixupColorStringsForInfoString( s, infostring );
|
||||
|
||||
// find a request with specified context
|
||||
// find request with specified context and type
|
||||
for( i = 0; i < MAX_REQUESTS; i++ )
|
||||
{
|
||||
nr = &clgame.net_requests[i];
|
||||
|
||||
if( nr->resp.context == context && nr->resp.type == type )
|
||||
if( clgame.net_requests[i].resp.context == context && clgame.net_requests[i].resp.type == type )
|
||||
{
|
||||
// setup the answer
|
||||
nr->resp.response = infostring;
|
||||
nr->resp.remote_address = from;
|
||||
nr->resp.error = NET_SUCCESS;
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
|
||||
if( nr->timeout <= host.realtime )
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
SetBits( nr->resp.error, errorBits ); // misc error bits
|
||||
|
||||
nr->pfnFunc( &nr->resp );
|
||||
|
||||
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
|
||||
memset( nr, 0, sizeof( *nr )); // done
|
||||
return;
|
||||
nr = &clgame.net_requests[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// not found, ignore
|
||||
if( nr == NULL )
|
||||
return;
|
||||
|
||||
// find the payload
|
||||
s = Q_strchr( s, ' ' ); // skip netinfo
|
||||
if( !s )
|
||||
return;
|
||||
|
||||
s = Q_strchr( s + 1, ' ' ); // skip challenge
|
||||
if( !s )
|
||||
return;
|
||||
|
||||
s = Q_strchr( s + 1, ' ' ); // skip type
|
||||
if( s )
|
||||
s++; // skip final whitespace
|
||||
else if( type != NETAPI_REQUEST_PING ) // ping have no payload, and that's ok
|
||||
return;
|
||||
|
||||
if( s )
|
||||
{
|
||||
if( s[0] == '\\' )
|
||||
{
|
||||
// check for errors
|
||||
val = Info_ValueForKey( s, "neterror" );
|
||||
|
||||
if( !Q_stricmp( val, "protocol" ))
|
||||
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
|
||||
else if( !Q_stricmp( val, "undefined" ))
|
||||
SetBits( errorBits, NET_ERROR_UNDEFINED );
|
||||
else if( !Q_stricmp( val, "forbidden" ))
|
||||
SetBits( errorBits, NET_ERROR_FORBIDDEN );
|
||||
|
||||
CL_FixupColorStringsForInfoString( s, infostring, sizeof( infostring ));
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncpy( infostring, s, sizeof( infostring ));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
infostring[0] = 0;
|
||||
}
|
||||
|
||||
// setup the answer
|
||||
nr->resp.response = infostring;
|
||||
nr->resp.remote_address = from;
|
||||
nr->resp.error = NET_SUCCESS;
|
||||
nr->resp.ping = host.realtime - nr->timesend;
|
||||
|
||||
if( nr->timeout <= host.realtime )
|
||||
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
|
||||
SetBits( nr->resp.error, errorBits ); // misc error bits
|
||||
|
||||
nr->pfnFunc( &nr->resp );
|
||||
|
||||
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
|
||||
memset( nr, 0, sizeof( *nr )); // done
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1966,7 +2034,6 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
const char *c;
|
||||
char buf[MAX_SYSPATH];
|
||||
int len = sizeof( buf );
|
||||
int dataoffset = 0;
|
||||
netadr_t servadr;
|
||||
|
||||
MSG_Clear( msg );
|
||||
@@ -1977,7 +2044,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
Cmd_TokenizeString( args );
|
||||
c = Cmd_Argv( 0 );
|
||||
|
||||
Con_Reportf( "CL_ConnectionlessPacket: %s : %s\n", NET_AdrToString( from ), c );
|
||||
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
|
||||
|
||||
// server connection
|
||||
if( !Q_strcmp( c, "client_connect" ))
|
||||
@@ -2002,7 +2069,7 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
else if( !Q_strcmp( c, "netinfo" ))
|
||||
{
|
||||
// server responding to a status broadcast
|
||||
CL_ParseNETInfoMessage( from, msg, args );
|
||||
CL_ParseNETInfoMessage( from, args );
|
||||
}
|
||||
else if( !Q_strcmp( c, "cmd" ))
|
||||
{
|
||||
@@ -2023,7 +2090,11 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
else if( !Q_strcmp( c, "print" ))
|
||||
{
|
||||
// print command from somewhere
|
||||
Con_Printf( "%s", MSG_ReadString( msg ));
|
||||
char *s = MSG_ReadString( msg );
|
||||
|
||||
Con_Printf( S_CYAN "r:" S_DEFAULT " %s", s );
|
||||
if( !COM_CheckStringEmpty( s ) || s[Q_strlen( s ) - 1] != '\n' )
|
||||
Con_Printf( "\n" );
|
||||
}
|
||||
else if( !Q_strcmp( c, "testpacket" ))
|
||||
{
|
||||
@@ -2134,30 +2205,21 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
|
||||
// a disconnect message from the server, which will happen if the server
|
||||
// dropped the connection but it is still getting packets from us
|
||||
CL_Disconnect_f();
|
||||
|
||||
if( NET_CompareAdr( from, cls.legacyserver ))
|
||||
{
|
||||
Cbuf_AddTextf( "connect %s legacy\n", NET_AdrToString( from ));
|
||||
memset( &cls.legacyserver, 0, sizeof( cls.legacyserver ));
|
||||
}
|
||||
}
|
||||
else if( !Q_strcmp( c, "errormsg" ))
|
||||
{
|
||||
char formatted_msg[MAX_VA_STRING];
|
||||
|
||||
if( !CL_IsFromConnectingServer( from ))
|
||||
return;
|
||||
|
||||
args = MSG_ReadString( msg );
|
||||
|
||||
if( !Q_strcmp( args, "Server uses protocol version 48.\n" ))
|
||||
{
|
||||
cls.legacyserver = from;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( UI_IsVisible() )
|
||||
UI_ShowMessageBox( va("^3Server message^7\n%s", args ) );
|
||||
Msg( "%s", args );
|
||||
}
|
||||
Q_snprintf( formatted_msg, sizeof( formatted_msg ), "^3Server message^7\n%s", args );
|
||||
|
||||
// in case we're in console or it's classic mainui which doesn't support messageboxes
|
||||
if( !UI_IsVisible() || !UI_ShowMessageBox( formatted_msg ))
|
||||
Msg( "%s\n", formatted_msg );
|
||||
}
|
||||
else if( !Q_strcmp( c, "updatemsg" ))
|
||||
{
|
||||
@@ -2271,6 +2333,29 @@ static int CL_GetMessage( byte *data, size_t *length )
|
||||
return false;
|
||||
}
|
||||
|
||||
static void CL_ParseNetMessage( sizebuf_t *msg, void (*parsefn)( sizebuf_t * ))
|
||||
{
|
||||
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||
CL_Parse_Debug( true ); // begin parsing
|
||||
|
||||
parsefn( msg );
|
||||
|
||||
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
|
||||
CL_Parse_Debug( false ); // done
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
// after we have parsed the frame
|
||||
if( !cls.demoplayback )
|
||||
{
|
||||
if( cls.state != ca_active )
|
||||
CL_WriteDemoMessage( true, cls.starting_count, msg );
|
||||
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ReadNetMessage
|
||||
@@ -2279,11 +2364,29 @@ CL_ReadNetMessage
|
||||
static void CL_ReadNetMessage( void )
|
||||
{
|
||||
size_t curSize;
|
||||
void (*parsefn)( sizebuf_t *msg );
|
||||
|
||||
switch( cls.legacymode )
|
||||
{
|
||||
case PROTO_CURRENT:
|
||||
parsefn = CL_ParseServerMessage;
|
||||
break;
|
||||
case PROTO_LEGACY:
|
||||
parsefn = CL_ParseLegacyServerMessage;
|
||||
break;
|
||||
case PROTO_QUAKE:
|
||||
parsefn = CL_ParseQuakeMessage;
|
||||
break;
|
||||
case PROTO_GOLDSRC:
|
||||
default:
|
||||
ASSERT( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
while( CL_GetMessage( net_message_buffer, &curSize ))
|
||||
{
|
||||
const int split_header = LittleLong( 0xFFFFFFFE );
|
||||
if( cls.legacymode && !memcmp( &split_header, net_message_buffer, sizeof( split_header )))
|
||||
if( cls.legacymode == PROTO_LEGACY && !memcmp( &split_header, net_message_buffer, sizeof( split_header )))
|
||||
{
|
||||
// Will rewrite existing packet by merged
|
||||
if( !NetSplit_GetLong( &cls.netchan.netsplit, &net_from, net_message_buffer, &curSize ) )
|
||||
@@ -2302,27 +2405,36 @@ static void CL_ReadNetMessage( void )
|
||||
// can't be a valid sequenced packet
|
||||
if( cls.state < ca_connected ) continue;
|
||||
|
||||
if( !cls.demoplayback && MSG_GetMaxBytes( &net_message ) < 8 )
|
||||
if( !cls.demoplayback )
|
||||
{
|
||||
Con_Printf( S_WARN "CL_ReadPackets: %s:runt packet\n", NET_AdrToString( net_from ));
|
||||
continue;
|
||||
if( MSG_GetMaxBytes( &net_message ) < 8 )
|
||||
{
|
||||
Con_Printf( S_WARN "%s: %s:runt packet\n", __func__, NET_AdrToString( net_from ));
|
||||
continue;
|
||||
}
|
||||
|
||||
// packet from server
|
||||
if( !NET_CompareAdr( net_from, cls.netchan.remote_address ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: %s:sequenced packet without connection\n", __func__, NET_AdrToString( net_from ));
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !Netchan_Process( &cls.netchan, &net_message ))
|
||||
continue; // wasn't accepted for some reason
|
||||
}
|
||||
|
||||
// packet from server
|
||||
if( !cls.demoplayback && !NET_CompareAdr( net_from, cls.netchan.remote_address ))
|
||||
if( cls.state == ca_active )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( net_from ));
|
||||
continue;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
|
||||
}
|
||||
|
||||
if( !cls.demoplayback && !Netchan_Process( &cls.netchan, &net_message ))
|
||||
continue; // wasn't accepted for some reason
|
||||
|
||||
// run special handler for quake demos
|
||||
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||
CL_ParseQuakeMessage( &net_message, true );
|
||||
else if( cls.legacymode ) CL_ParseLegacyServerMessage( &net_message, true );
|
||||
else CL_ParseServerMessage( &net_message, true );
|
||||
CL_ParseNetMessage( &net_message, parsefn );
|
||||
cl.send_reply = true;
|
||||
}
|
||||
|
||||
@@ -2336,7 +2448,7 @@ static void CL_ReadNetMessage( void )
|
||||
if( Netchan_CopyNormalFragments( &cls.netchan, &net_message, &curSize ))
|
||||
{
|
||||
MSG_Init( &net_message, "ServerData", net_message_buffer, curSize );
|
||||
CL_ParseServerMessage( &net_message, false );
|
||||
CL_ParseNetMessage( &net_message, parsefn );
|
||||
}
|
||||
|
||||
if( Netchan_CopyFileFragments( &cls.netchan, &net_message ))
|
||||
@@ -2479,7 +2591,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
{
|
||||
int sound_len = sizeof( DEFAULT_SOUNDPATH ) - 1;
|
||||
byte rgucMD5_hash[16];
|
||||
const char *pfilename;
|
||||
resource_t *p;
|
||||
|
||||
if( COM_CheckString( filename ) && successfully_received )
|
||||
@@ -2487,10 +2598,10 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
if( filename[0] != '!' )
|
||||
Con_Printf( "processing %s\n", filename );
|
||||
|
||||
if( !Q_strnicmp( filename, "downloaded/", 11 ))
|
||||
if( !Q_strnicmp( filename, DEFAULT_DOWNLOADED_DIRECTORY, sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1 ))
|
||||
{
|
||||
// skip "downloaded/" part to avoid mismatch with needed resources list
|
||||
filename += 11;
|
||||
filename += sizeof( DEFAULT_DOWNLOADED_DIRECTORY ) - 1;
|
||||
}
|
||||
}
|
||||
else if( !successfully_received )
|
||||
@@ -2510,11 +2621,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
return;
|
||||
}
|
||||
|
||||
pfilename = filename;
|
||||
|
||||
if( !Q_strnicmp( filename, DEFAULT_SOUNDPATH, sound_len ))
|
||||
pfilename += sound_len;
|
||||
|
||||
for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext )
|
||||
{
|
||||
if( !Q_strnicmp( filename, "!MD5", 4 ))
|
||||
@@ -2524,18 +2630,20 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
if( !memcmp( p->rgucMD5_hash, rgucMD5_hash, 16 ))
|
||||
break;
|
||||
}
|
||||
else if( p->type == t_sound )
|
||||
{
|
||||
const char *pfilename = filename;
|
||||
|
||||
if( !Q_strnicmp( filename, DEFAULT_SOUNDPATH, sound_len ))
|
||||
pfilename += sound_len;
|
||||
|
||||
if( !Q_stricmp( p->szFileName, pfilename ))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( p->type == t_generic )
|
||||
{
|
||||
if( !Q_stricmp( p->szFileName, filename ))
|
||||
if( !Q_stricmp( p->szFileName, filename ))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !Q_stricmp( p->szFileName, pfilename ))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2552,14 +2660,14 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
{
|
||||
if( p->ucFlags & RES_CUSTOM )
|
||||
{
|
||||
HPAK_AddLump( true, CUSTOM_RES_PATH, p, cls.netchan.tempbuffer, NULL );
|
||||
HPAK_AddLump( true, hpk_custom_file.string, p, cls.netchan.tempbuffer, NULL );
|
||||
CL_RegisterCustomization( p );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( "Downloaded %i bytes for purported %i byte file, ignoring download\n",
|
||||
cls.netchan.tempbuffersize, p->nDownloadSize );
|
||||
cls.netchan.tempbuffersize, p->nDownloadSize );
|
||||
}
|
||||
|
||||
if( cls.netchan.tempbuffer )
|
||||
@@ -2600,7 +2708,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
||||
|
||||
if( cls.netchan.tempbuffer )
|
||||
{
|
||||
Con_Printf( "Received a decal %s, but didn't find it in resources needed list!\n", pfilename );
|
||||
Con_Printf( "Received a decal %s, but didn't find it in resources needed list!\n", filename );
|
||||
Mem_Free( cls.netchan.tempbuffer );
|
||||
}
|
||||
|
||||
@@ -2640,6 +2748,29 @@ void CL_ServerCommand( qboolean reliable, const char *fmt, ... )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_UpdateInfo
|
||||
|
||||
tell server about changed userinfo
|
||||
===============
|
||||
*/
|
||||
void CL_UpdateInfo( const char *key, const char *value )
|
||||
{
|
||||
if( !cls.legacymode )
|
||||
{
|
||||
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", key, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cls.state != ca_active )
|
||||
return;
|
||||
|
||||
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
|
||||
MSG_WriteString( &cls.netchan.message, cls.userinfo );
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
/*
|
||||
==============
|
||||
@@ -2654,7 +2785,7 @@ static void CL_SetInfo_f( void )
|
||||
{
|
||||
Con_Printf( "User info settings:\n" );
|
||||
Info_Print( cls.userinfo );
|
||||
Con_Printf( "Total %i symbols\n", Q_strlen( cls.userinfo ));
|
||||
Con_Printf( "Total %zu symbols\n", Q_strlen( cls.userinfo ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2674,7 +2805,7 @@ static void CL_SetInfo_f( void )
|
||||
{
|
||||
Cvar_DirectSet( var, Cmd_Argv( 2 ));
|
||||
}
|
||||
else if( Info_SetValueForKey( cls.userinfo, Cmd_Argv( 1 ), Cmd_Argv( 2 ), MAX_INFO_STRING ))
|
||||
else if( Info_SetValueForKey( cls.userinfo, Cmd_Argv( 1 ), Cmd_Argv( 2 ), sizeof( cls.userinfo )))
|
||||
{
|
||||
// send update only on successfully changed userinfo
|
||||
Cmd_ForwardToServer ();
|
||||
@@ -2690,13 +2821,42 @@ static void CL_Physinfo_f( void )
|
||||
{
|
||||
Con_Printf( "Phys info settings:\n" );
|
||||
Info_Print( cls.physinfo );
|
||||
Con_Printf( "Total %i symbols\n", Q_strlen( cls.physinfo ));
|
||||
Con_Printf( "Total %zu symbols\n", Q_strlen( cls.physinfo ));
|
||||
}
|
||||
|
||||
static qboolean CL_ShouldRescanFilesystem( void )
|
||||
{
|
||||
resource_t *res;
|
||||
qboolean retval = false;
|
||||
|
||||
for( res = cl.resourcesonhand.pNext; res && res != &cl.resourcesonhand; res = res->pNext )
|
||||
{
|
||||
if( res->type == t_generic )
|
||||
{
|
||||
const char *ext = COM_FileExtension( res->szFileName );
|
||||
|
||||
if( !g_fsapi.IsArchiveExtensionSupported( ext, IAES_ONLY_REAL_ARCHIVES ))
|
||||
continue;
|
||||
|
||||
if( FBitSet( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED ))
|
||||
continue;
|
||||
|
||||
SetBits( res->ucExtraFlags, RES_EXTRA_ARCHIVE_CHECKED );
|
||||
retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
qboolean CL_PrecacheResources( void )
|
||||
{
|
||||
resource_t *pRes;
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
g_fsapi.Rescan();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
{
|
||||
@@ -2895,6 +3055,7 @@ static void CL_InitLocal( void )
|
||||
Cvar_RegisterVariable( &cl_logofile );
|
||||
Cvar_RegisterVariable( &cl_logocolor );
|
||||
Cvar_RegisterVariable( &cl_logoext );
|
||||
Cvar_RegisterVariable( &cl_logomaxdim );
|
||||
Cvar_RegisterVariable( &cl_test_bandwidth );
|
||||
|
||||
Voice_RegisterCvars();
|
||||
@@ -2918,8 +3079,9 @@ static void CL_InitLocal( void )
|
||||
|
||||
// userinfo
|
||||
Cvar_RegisterVariable( &cl_nopred );
|
||||
Q_strncpy( username, Sys_GetCurrentUser(), sizeof( username )); // initialize before registering variable
|
||||
Cvar_RegisterVariable( &name );
|
||||
Cvar_DirectSet( &name, Sys_GetCurrentUser( ));
|
||||
Cvar_Get( "ui_username", username, FCVAR_READ_ONLY|FCVAR_PRIVILEGED, "default user name" );
|
||||
Cvar_RegisterVariable( &model );
|
||||
Cvar_RegisterVariable( &cl_updaterate );
|
||||
Cvar_RegisterVariable( &cl_dlmax );
|
||||
@@ -2995,6 +3157,7 @@ static void CL_InitLocal( void )
|
||||
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
|
||||
Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" );
|
||||
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
|
||||
Cmd_AddCommand( "listdemo", CL_ListDemo_f, "list demo entries" );
|
||||
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
|
||||
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
|
||||
Cmd_AddCommand ("togglemenu", CL_Escape_f, "toggle between game and menu" );
|
||||
@@ -3190,7 +3353,7 @@ CL_Shutdown
|
||||
*/
|
||||
void CL_Shutdown( void )
|
||||
{
|
||||
Con_Printf( "CL_Shutdown()\n" );
|
||||
Con_Printf( "%s()\n", __func__ );
|
||||
|
||||
if( !host.crashed && cls.initialized )
|
||||
{
|
||||
|
||||
@@ -20,8 +20,6 @@ GNU General Public License for more details.
|
||||
#include "input.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
static mobile_engfuncs_t *gMobileEngfuncs;
|
||||
|
||||
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
|
||||
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
|
||||
|
||||
@@ -30,17 +28,9 @@ static float g_font_scale;
|
||||
|
||||
static void pfnVibrate( float life, char flags )
|
||||
{
|
||||
if( !vibration_enable.value )
|
||||
if( !vibration_enable.value || life < 0.0f )
|
||||
return;
|
||||
|
||||
if( life < 0.0f )
|
||||
{
|
||||
Con_Reportf( S_WARN "Negative vibrate time: %f\n", life );
|
||||
return;
|
||||
}
|
||||
|
||||
//Con_Reportf( "Vibrate: %f %d\n", life, flags );
|
||||
|
||||
// here goes platform-specific backends
|
||||
Platform_Vibrate( life * vibration_length.value, flags );
|
||||
}
|
||||
@@ -53,7 +43,7 @@ static void Vibrate_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
pfnVibrate( Q_atof( Cmd_Argv(1) ), VIBRATE_NORMAL );
|
||||
pfnVibrate( Q_atof( Cmd_Argv( 1 )), VIBRATE_NORMAL );
|
||||
}
|
||||
|
||||
static void pfnEnableTextInput( int enable )
|
||||
@@ -102,7 +92,7 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static mobile_engfuncs_t gpMobileEngfuncs =
|
||||
static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
{
|
||||
MOBILITY_API_VERSION,
|
||||
pfnVibrate,
|
||||
@@ -122,21 +112,38 @@ static mobile_engfuncs_t gpMobileEngfuncs =
|
||||
|
||||
qboolean Mobile_Init( void )
|
||||
{
|
||||
qboolean success = false;
|
||||
pfnMobilityInterface ExportToClient;
|
||||
|
||||
// find a mobility interface
|
||||
ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT );
|
||||
gMobileEngfuncs = &gpMobileEngfuncs;
|
||||
|
||||
if( ExportToClient && !ExportToClient( gMobileEngfuncs ) )
|
||||
success = true;
|
||||
|
||||
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
|
||||
Cmd_AddCommand( "vibrate", Vibrate_f, "Vibrate for specified time");
|
||||
Cvar_RegisterVariable( &vibration_length );
|
||||
Cvar_RegisterVariable( &vibration_enable );
|
||||
|
||||
return success;
|
||||
// find mobility interface
|
||||
if(( ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT )))
|
||||
{
|
||||
static mobile_engfuncs_t mobile_engfuncs; // keep a copy, don't let user change engine pointers
|
||||
|
||||
mobile_engfuncs = gMobileEngfuncs;
|
||||
|
||||
if( !ExportToClient( &mobile_engfuncs ))
|
||||
{
|
||||
Con_Reportf( "%s: ^2initailized extended MobilityAPI ^7ver. %i\n", __func__, MOBILITY_API_VERSION );
|
||||
return true;
|
||||
}
|
||||
|
||||
// make sure that mobile functions are cleared
|
||||
#if 1
|
||||
// some SDKs define export as returning void, breaking the contract
|
||||
// ignore result for now...
|
||||
return true;
|
||||
#else
|
||||
memset( &mobile_engfuncs, 0, sizeof( mobile_engfuncs ));
|
||||
|
||||
return false; // just tell user about problems
|
||||
#endif
|
||||
}
|
||||
|
||||
return true; // mobile interface is missed
|
||||
}
|
||||
|
||||
void Mobile_Shutdown( void )
|
||||
|
||||
@@ -188,7 +188,7 @@ void CL_ParseServerTime( sizebuf_t *msg )
|
||||
cl.mtime[1] = cl.mtime[0];
|
||||
cl.mtime[0] = MSG_ReadFloat( msg );
|
||||
|
||||
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||
if( cls.legacymode == PROTO_QUAKE )
|
||||
return; // don't mess the time
|
||||
|
||||
if( cl.maxclients == 1 )
|
||||
@@ -249,9 +249,9 @@ void CL_ParseMovevars( sizebuf_t *msg )
|
||||
|
||||
// update sky if changed
|
||||
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
|
||||
ref.dllFuncs.R_SetupSky( clgame.movevars.skyName );
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
|
||||
// keep features an actual!
|
||||
@@ -388,7 +388,6 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
|
||||
{
|
||||
vec3_t origin;
|
||||
int decalIndex, entityIndex, modelIndex;
|
||||
cl_entity_t *ent = NULL;
|
||||
float scale;
|
||||
int flags;
|
||||
|
||||
@@ -458,6 +457,7 @@ void CL_BatchResourceRequest( qboolean initialize )
|
||||
byte data[MAX_INIT_MSG];
|
||||
resource_t *p, *n;
|
||||
sizebuf_t msg;
|
||||
qboolean done_downloading = true;
|
||||
|
||||
MSG_Init( &msg, "Resource Batch", data, sizeof( data ));
|
||||
|
||||
@@ -487,20 +487,24 @@ void CL_BatchResourceRequest( qboolean initialize )
|
||||
case t_model:
|
||||
case t_eventscript:
|
||||
if( !CL_CheckFile( &msg, p ))
|
||||
{
|
||||
done_downloading = false;
|
||||
break;
|
||||
}
|
||||
CL_MoveToOnHandList( p );
|
||||
break;
|
||||
case t_skin:
|
||||
CL_MoveToOnHandList( p );
|
||||
break;
|
||||
case t_decal:
|
||||
if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, p, NULL, NULL ))
|
||||
if( !HPAK_GetDataPointer( hpk_custom_file.string, p, NULL, NULL ))
|
||||
{
|
||||
if( !FBitSet( p->ucFlags, RES_REQUESTED ))
|
||||
{
|
||||
MSG_BeginClientCmd( &msg, clc_stringcmd );
|
||||
MSG_WriteStringf( &msg, "dlfile !MD5%s", MD5_Print( p->rgucMD5_hash ));;
|
||||
SetBits( p->ucFlags, RES_REQUESTED );
|
||||
done_downloading = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -525,11 +529,7 @@ void CL_BatchResourceRequest( qboolean initialize )
|
||||
|
||||
if( cls.state != ca_disconnected )
|
||||
{
|
||||
if( !cl.downloadUrl[0] && !MSG_GetNumBytesWritten( &msg ) && CL_PrecacheResources( ))
|
||||
{
|
||||
CL_RegisterResources( &msg );
|
||||
}
|
||||
if( cl.downloadUrl[0] && host.downloadcount == 0 && CL_PrecacheResources( ) )
|
||||
if( done_downloading && CL_PrecacheResources( ))
|
||||
{
|
||||
CL_RegisterResources( &msg );
|
||||
}
|
||||
@@ -721,7 +721,7 @@ void CL_ParseCustomization( sizebuf_t *msg )
|
||||
}
|
||||
}
|
||||
|
||||
if( HPAK_GetDataPointer( CUSTOM_RES_PATH, pRes, NULL, NULL ))
|
||||
if( HPAK_GetDataPointer( hpk_custom_file.string, pRes, NULL, NULL ))
|
||||
{
|
||||
qboolean bError = false;
|
||||
|
||||
@@ -853,7 +853,7 @@ void CL_ParseServerData( sizebuf_t *msg, qboolean legacy )
|
||||
int i;
|
||||
uint32_t mapCRC;
|
||||
|
||||
HPAK_CheckSize( CUSTOM_RES_PATH );
|
||||
HPAK_CheckSize( hpk_custom_file.string );
|
||||
|
||||
Con_Reportf( "%s packet received.\n", legacy ? "Legacy serverdata" : "Serverdata" );
|
||||
|
||||
@@ -1180,17 +1180,16 @@ CL_ParseBaseline
|
||||
*/
|
||||
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
|
||||
{
|
||||
int i, newnum;
|
||||
entity_state_t nullstate;
|
||||
qboolean player;
|
||||
cl_entity_t *ent;
|
||||
const entity_state_t nullstate = { 0 };
|
||||
|
||||
Delta_InitClient (); // finalize client delta's
|
||||
|
||||
memset( &nullstate, 0, sizeof( nullstate ));
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
cl_entity_t *ent;
|
||||
qboolean player;
|
||||
int newnum;
|
||||
|
||||
if( legacy )
|
||||
{
|
||||
newnum = MSG_ReadWord( msg );
|
||||
@@ -1203,13 +1202,13 @@ void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
|
||||
player = CL_IsPlayerIndex( newnum );
|
||||
|
||||
if( newnum >= clgame.maxEntities )
|
||||
Host_Error( "CL_AllocEdict: no free edicts\n" );
|
||||
Host_Error( "%s: no free edicts\n", __func__ );
|
||||
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
memset( &ent->prevstate, 0, sizeof( ent->prevstate ));
|
||||
ent->prevstate = nullstate;
|
||||
ent->index = newnum;
|
||||
|
||||
MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, player, 1.0f );
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &ent->baseline, newnum, player, 1.0f );
|
||||
|
||||
if( legacy )
|
||||
{
|
||||
@@ -1219,11 +1218,13 @@ void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy )
|
||||
|
||||
if( !legacy )
|
||||
{
|
||||
int i;
|
||||
|
||||
cl.instanced_baseline_count = MSG_ReadUBitLong( msg, 6 );
|
||||
|
||||
for( i = 0; i < cl.instanced_baseline_count; i++ )
|
||||
{
|
||||
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
int newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
MSG_ReadDeltaEntity( msg, &nullstate, &cl.instanced_baseline[i], newnum, false, 1.0f );
|
||||
}
|
||||
}
|
||||
@@ -1380,7 +1381,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
||||
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
|
||||
|
||||
if( slot >= MAX_CLIENTS )
|
||||
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo >= MAX_CLIENTS\n" );
|
||||
Host_Error( "%s: svc_updateuserinfo >= MAX_CLIENTS\n", __func__ );
|
||||
|
||||
player = &cl.players[slot];
|
||||
|
||||
@@ -1402,7 +1403,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy )
|
||||
if( !legacy )
|
||||
MSG_ReadBytes( msg, player->hashedcdkey, sizeof( player->hashedcdkey ));
|
||||
|
||||
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
|
||||
if( slot == cl.playernum ) gameui.playerinfo = *player;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1493,7 +1494,7 @@ void CL_UpdateUserPings( sizebuf_t *msg )
|
||||
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
|
||||
|
||||
if( slot >= MAX_CLIENTS )
|
||||
Host_Error( "CL_ParseServerMessage: svc_pings > MAX_CLIENTS\n" );
|
||||
Host_Error( "%s: svc_pings > MAX_CLIENTS\n", __func__ );
|
||||
|
||||
player = &cl.players[slot];
|
||||
player->ping = MSG_ReadUBitLong( msg, 12 );
|
||||
@@ -1645,6 +1646,9 @@ void CL_RegisterResources( sizebuf_t *msg )
|
||||
|
||||
CL_ClearWorld ();
|
||||
|
||||
// load skybox
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
// tell rendering system we have a new set of models.
|
||||
ref.dllFuncs.R_NewMap ();
|
||||
|
||||
@@ -1718,7 +1722,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg )
|
||||
}
|
||||
|
||||
if( cl.num_consistency >= MAX_MODELS )
|
||||
Host_Error( "CL_CheckConsistency: MAX_MODELS limit exceeded (%d)\n", MAX_MODELS );
|
||||
Host_Error( "%s: MAX_MODELS limit exceeded (%d)\n", __func__, MAX_MODELS );
|
||||
|
||||
pc = &cl.consistency_list[cl.num_consistency];
|
||||
cl.num_consistency++;
|
||||
@@ -1840,13 +1844,10 @@ void CL_ParseResLocation( sizebuf_t *msg )
|
||||
return;
|
||||
}
|
||||
|
||||
while( ( data = COM_ParseFile( data, token, sizeof( token ) ) ) )
|
||||
while(( data = COM_ParseFile( data, token, sizeof( token ))))
|
||||
{
|
||||
Con_Reportf( "Adding %s as download location\n", token );
|
||||
|
||||
if( !cl.downloadUrl[0] )
|
||||
Q_strncpy( cl.downloadUrl, token, sizeof( token ) );
|
||||
|
||||
cl.http_download = true;
|
||||
HTTP_AddCustomServer( token );
|
||||
}
|
||||
}
|
||||
@@ -1877,8 +1878,12 @@ void CL_ParseHLTV( sizebuf_t *msg )
|
||||
break;
|
||||
case HLTV_LISTEN:
|
||||
cls.signon = SIGNONS;
|
||||
#if 1
|
||||
MSG_ReadString( msg );
|
||||
#else
|
||||
NET_StringToAdr( MSG_ReadString( msg ), &cls.hltv_listen_address );
|
||||
// NET_JoinGroup( cls.netchan.sock, cls.hltv_listen_address );
|
||||
NET_JoinGroup( cls.netchan.sock, cls.hltv_listen_address );
|
||||
#endif
|
||||
SCR_EndLoadingPlaque();
|
||||
break;
|
||||
default:
|
||||
@@ -1988,7 +1993,7 @@ Find the client cvar value
|
||||
and sent it back to the server
|
||||
==============
|
||||
*/
|
||||
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext )
|
||||
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto )
|
||||
{
|
||||
const char *cvarName, *response;
|
||||
convar_t *cvar;
|
||||
@@ -2011,7 +2016,14 @@ void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext )
|
||||
else
|
||||
response = cvar->string;
|
||||
}
|
||||
else response = "Bad CVAR request";
|
||||
else if( proto == PROTO_LEGACY )
|
||||
{
|
||||
response = "Not Found";
|
||||
}
|
||||
else
|
||||
{
|
||||
response = "Bad CVAR request";
|
||||
}
|
||||
|
||||
if( ext )
|
||||
{
|
||||
@@ -2128,7 +2140,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
|
||||
if( svc_num <= svc_lastmsg || svc_num > ( MAX_USER_MESSAGES + svc_lastmsg ))
|
||||
{
|
||||
// out or range
|
||||
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num );
|
||||
Host_Error( "%s: illegible server message %d\n", __func__, svc_num );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2140,7 +2152,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
|
||||
}
|
||||
|
||||
if( i == MAX_USER_MESSAGES ) // probably unregistered
|
||||
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num );
|
||||
Host_Error( "%s: illegible server message %d\n", __func__, svc_num );
|
||||
|
||||
// NOTE: some user messages handled into engine
|
||||
if( !Q_strcmp( clgame.msg[i].name, "ScreenShake" ))
|
||||
@@ -2166,7 +2178,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
|
||||
|
||||
if( iSize >= MAX_USERMSG_LENGTH )
|
||||
{
|
||||
Msg("WTF??? %d %d\n", i, svc_num );
|
||||
Con_Reportf( "%s: user message %s size limit hit (%d > %d)!\n", __func__, clgame.msg[i].name, iSize, MAX_USERMSG_LENGTH );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2195,7 +2207,7 @@ void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf( S_ERROR "UserMsg: No pfn %s %d\n", clgame.msg[i].name, clgame.msg[i].number );
|
||||
Con_DPrintf( S_ERROR "%s: No pfn %s %d\n", __func__, clgame.msg[i].name, clgame.msg[i].number );
|
||||
clgame.msg[i].func = CL_UserMsgStub; // throw warning only once
|
||||
}
|
||||
}
|
||||
@@ -2214,36 +2226,19 @@ CL_ParseServerMessage
|
||||
dispatch messages
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
void CL_ParseServerMessage( sizebuf_t *msg )
|
||||
{
|
||||
size_t bufStart, playerbytes;
|
||||
int cmd, param1, param2;
|
||||
int old_background;
|
||||
const char *s;
|
||||
|
||||
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||
CL_Parse_Debug( true ); // begin parsing
|
||||
|
||||
if( normal_message )
|
||||
{
|
||||
// assume no entity/player update this packet
|
||||
if( cls.state == ca_active )
|
||||
{
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
|
||||
}
|
||||
}
|
||||
|
||||
// parse the message
|
||||
while( 1 )
|
||||
{
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
{
|
||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
||||
Host_Error( "%s: overflow!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2488,10 +2483,10 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
CL_ParseResLocation( msg );
|
||||
break;
|
||||
case svc_querycvarvalue:
|
||||
CL_ParseCvarValue( msg, false );
|
||||
CL_ParseCvarValue( msg, false, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_querycvarvalue2:
|
||||
CL_ParseCvarValue( msg, true );
|
||||
CL_ParseCvarValue( msg, true, PROTO_CURRENT );
|
||||
break;
|
||||
case svc_exec:
|
||||
CL_ParseExec( msg );
|
||||
@@ -2502,21 +2497,4 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
|
||||
CL_Parse_Debug( false ); // done
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
// after we have parsed the frame
|
||||
if( !cls.demoplayback )
|
||||
{
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
{
|
||||
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||
}
|
||||
else if( cls.state != ca_active )
|
||||
{
|
||||
CL_WriteDemoMessage( true, cls.starting_count, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ static void CL_LegacyPrecacheSound( sizebuf_t *msg )
|
||||
soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
|
||||
|
||||
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
|
||||
Host_Error( "CL_PrecacheSound: bad soundindex %i\n", soundIndex );
|
||||
Host_Error( "%s: bad soundindex %i\n", __func__, soundIndex );
|
||||
|
||||
Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] ));
|
||||
|
||||
@@ -192,9 +192,9 @@ static void CL_LegacyPrecacheModel( sizebuf_t *msg )
|
||||
modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS );
|
||||
|
||||
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
|
||||
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );
|
||||
Host_Error( "%s: bad modelindex %i\n", __func__, modelIndex );
|
||||
|
||||
Q_strncpy( model, MSG_ReadString( msg ), MAX_STRING );
|
||||
Q_strncpy( model, MSG_ReadString( msg ), sizeof( model ));
|
||||
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
|
||||
|
||||
// when we loading map all resources is precached sequentially
|
||||
@@ -221,7 +221,7 @@ static void CL_LegacyPrecacheEvent( sizebuf_t *msg )
|
||||
eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
|
||||
|
||||
if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
|
||||
Host_Error( "CL_PrecacheEvent: bad eventindex %i\n", eventIndex );
|
||||
Host_Error( "%s: bad eventindex %i\n", __func__, eventIndex );
|
||||
|
||||
Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] ));
|
||||
|
||||
@@ -256,15 +256,15 @@ static void CL_LegacyParseResourceList( sizebuf_t *msg )
|
||||
reslist.rescount = MSG_ReadWord( msg ) - 1;
|
||||
|
||||
if( reslist.rescount > MAX_LEGACY_RESOURCES )
|
||||
Host_Error("MAX_RESOURCES reached\n");
|
||||
Host_Error( "MAX_RESOURCES reached\n" );
|
||||
|
||||
for( i = 0; i < reslist.rescount; i++ )
|
||||
{
|
||||
reslist.restype[i] = MSG_ReadWord( msg );
|
||||
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), MAX_QPATH );
|
||||
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), sizeof( reslist.resnames[i] ));
|
||||
}
|
||||
|
||||
if( CL_IsPlaybackDemo() )
|
||||
if( cls.demoplayback )
|
||||
return;
|
||||
|
||||
if( !cl_allow_download.value )
|
||||
@@ -317,36 +317,19 @@ CL_ParseLegacyServerMessage
|
||||
dispatch messages
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg )
|
||||
{
|
||||
size_t bufStart, playerbytes;
|
||||
int cmd, param1, param2;
|
||||
int old_background;
|
||||
const char *s;
|
||||
|
||||
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||
CL_Parse_Debug( true ); // begin parsing
|
||||
|
||||
if( normal_message )
|
||||
{
|
||||
// assume no entity/player update this packet
|
||||
if( cls.state == ca_active )
|
||||
{
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
|
||||
}
|
||||
}
|
||||
|
||||
// parse the message
|
||||
while( 1 )
|
||||
{
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
{
|
||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
||||
Host_Error( "%s: overflow!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -385,7 +368,9 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
{
|
||||
int maxclients = cl.maxclients;
|
||||
|
||||
cls.changelevel = true;
|
||||
// we can only changelevel in singleplayer
|
||||
// and singleplayer always runs in current protocol
|
||||
// cls.changelevel = true;
|
||||
S_StopAllSounds( true );
|
||||
|
||||
Con_Printf( "Server changing, reconnecting\n" );
|
||||
@@ -612,10 +597,10 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
CL_ParseResLocation( msg );
|
||||
break;
|
||||
case svc_querycvarvalue:
|
||||
CL_ParseCvarValue( msg, false );
|
||||
CL_ParseCvarValue( msg, false, PROTO_LEGACY );
|
||||
break;
|
||||
case svc_querycvarvalue2:
|
||||
CL_ParseCvarValue( msg, true );
|
||||
CL_ParseCvarValue( msg, true, PROTO_LEGACY );
|
||||
break;
|
||||
default:
|
||||
CL_ParseUserMessage( msg, cmd );
|
||||
@@ -623,23 +608,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
|
||||
CL_Parse_Debug( false ); // done
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
// after we have parsed the frame
|
||||
if( !cls.demoplayback )
|
||||
{
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
{
|
||||
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||
}
|
||||
else if( cls.state != ca_active )
|
||||
{
|
||||
CL_WriteDemoMessage( true, cls.starting_count, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CL_LegacyPrecache_f( void )
|
||||
@@ -664,6 +632,9 @@ void CL_LegacyPrecache_f( void )
|
||||
if( clgame.entities )
|
||||
clgame.entities->model = cl.worldmodel;
|
||||
|
||||
// load skybox
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
// tell rendering system we have a new set of models.
|
||||
ref.dllFuncs.R_NewMap ();
|
||||
|
||||
@@ -685,22 +656,10 @@ void CL_LegacyPrecache_f( void )
|
||||
// Include server count in case server disconnects and changes level during d/l
|
||||
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
|
||||
cls.signon = SIGNONS;
|
||||
}
|
||||
|
||||
void CL_LegacyUpdateInfo( void )
|
||||
{
|
||||
if( !cls.legacymode )
|
||||
return;
|
||||
|
||||
if( cls.state != ca_active )
|
||||
return;
|
||||
|
||||
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
|
||||
MSG_WriteString( &cls.netchan.message, cls.userinfo );
|
||||
cls.signon = SIGNONS - 1;
|
||||
}
|
||||
|
||||
qboolean CL_LegacyMode( void )
|
||||
{
|
||||
return cls.legacymode;
|
||||
return cls.legacymode == PROTO_LEGACY;
|
||||
}
|
||||
|
||||
@@ -544,8 +544,8 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
|
||||
// some fields needs to be override from cls.predicted_players
|
||||
VectorCopy( player->origin, pe->origin );
|
||||
VectorCopy( player->angles, pe->angles );
|
||||
VectorCopy( clgame.pmove->player_mins[player->usehull], pe->mins );
|
||||
VectorCopy( clgame.pmove->player_maxs[player->usehull], pe->maxs );
|
||||
VectorCopy( host.player_mins[player->usehull], pe->mins );
|
||||
VectorCopy( host.player_maxs[player->usehull], pe->maxs );
|
||||
pe->movetype = player->movetype;
|
||||
pe->solid = player->solid;
|
||||
}
|
||||
@@ -853,7 +853,7 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
|
||||
VectorCopy( cd->vuser4, pmove->vuser4 );
|
||||
pmove->cmd = *ucmd; // copy current cmds
|
||||
|
||||
Q_strncpy( pmove->physinfo, cls.physinfo, MAX_INFO_STRING );
|
||||
Q_strncpy( pmove->physinfo, cls.physinfo, sizeof( pmove->physinfo ));
|
||||
}
|
||||
|
||||
static const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )
|
||||
|
||||
@@ -22,22 +22,24 @@ GNU General Public License for more details.
|
||||
#include "hltv.h"
|
||||
#include "input.h"
|
||||
|
||||
#define STAT_HEALTH 0
|
||||
#define STAT_FRAGS 1
|
||||
#define STAT_WEAPON 2
|
||||
#define STAT_AMMO 3
|
||||
#define STAT_ARMOR 4
|
||||
#define STAT_WEAPONFRAME 5
|
||||
#define STAT_SHELLS 6
|
||||
#define STAT_NAILS 7
|
||||
#define STAT_ROCKETS 8
|
||||
#define STAT_CELLS 9
|
||||
#define STAT_ACTIVEWEAPON 10
|
||||
#define STAT_TOTALSECRETS 11
|
||||
#define STAT_TOTALMONSTERS 12
|
||||
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
|
||||
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
|
||||
#define MAX_STATS 32
|
||||
enum {
|
||||
STAT_HEALTH = 0,
|
||||
STAT_FRAGS,
|
||||
STAT_WEAPON,
|
||||
STAT_AMMO,
|
||||
STAT_ARMOR,
|
||||
STAT_WEAPONFRAME,
|
||||
STAT_SHELLS,
|
||||
STAT_NAILS,
|
||||
STAT_ROCKETS,
|
||||
STAT_CELLS,
|
||||
STAT_ACTIVEWEAPON,
|
||||
STAT_TOTALSECRETS,
|
||||
STAT_TOTALMONSTERS,
|
||||
STAT_SECRETS, // bumped on client side by svc_foundsecret
|
||||
STAT_MONSTERS, // bumped by svc_killedmonster
|
||||
MAX_STATS = 32,
|
||||
};
|
||||
|
||||
static char cmd_buf[8192];
|
||||
static char msg_buf[8192];
|
||||
@@ -211,7 +213,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
||||
clgame.maxEntities = GI->max_edicts;
|
||||
clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS );
|
||||
clgame.maxModels = MAX_MODELS;
|
||||
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING );
|
||||
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
|
||||
|
||||
// Re-init hud video, especially if we changed game directories
|
||||
clgame.dllFuncs.pfnVidInit();
|
||||
@@ -328,7 +330,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
||||
clgame.movevars.gravity = 800.0f; // quake doesn't write gravity in demos
|
||||
clgame.movevars.maxvelocity = 2000.0f;
|
||||
|
||||
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -620,11 +622,11 @@ static void CL_ParseQuakeDamage( sizebuf_t *msg )
|
||||
|
||||
/*
|
||||
===================
|
||||
CL_ParseQuakeStaticEntity
|
||||
CL_ParseStaticEntity
|
||||
|
||||
===================
|
||||
*/
|
||||
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
|
||||
static void CL_ParseStaticEntity( sizebuf_t *msg )
|
||||
{
|
||||
entity_state_t state;
|
||||
cl_entity_t *ent;
|
||||
@@ -646,7 +648,7 @@ static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
|
||||
i = clgame.numStatics;
|
||||
if( i >= MAX_STATIC_ENTITIES )
|
||||
{
|
||||
Con_Printf( S_ERROR "CL_ParseStaticEntity: static entities limit exceeded!\n" );
|
||||
Con_Printf( S_ERROR "%s: static entities limit exceeded!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -697,7 +699,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
|
||||
newnum = MSG_ReadWord( msg ); // entnum
|
||||
|
||||
if( newnum >= clgame.maxEntities )
|
||||
Host_Error( "CL_AllocEdict: no free edicts\n" );
|
||||
Host_Error( "%s: no free edicts\n", __func__ );
|
||||
|
||||
// parse baseline
|
||||
memset( &state, 0, sizeof( state ));
|
||||
@@ -715,8 +717,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
ent->index = newnum;
|
||||
ent->player = CL_IsPlayerIndex( newnum );
|
||||
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
|
||||
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
|
||||
ent->prevstate = ent->baseline = state;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -778,7 +779,7 @@ static void CL_ParseQuakeSignon( sizebuf_t *msg )
|
||||
int i = MSG_ReadByte( msg );
|
||||
|
||||
if( i == 3 ) cls.signon = SIGNONS - 1;
|
||||
Con_Reportf( "CL_Signon: %d\n", i );
|
||||
Con_Reportf( "%s: %d\n", __func__, i );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -844,7 +845,7 @@ static void CL_QuakeExecStuff( void )
|
||||
while( 1 )
|
||||
{
|
||||
// skip whitespace up to a /n
|
||||
while( *text && ((byte)*text) <= ' ' && *text != '\r' && *text != '\n' )
|
||||
while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
|
||||
text++;
|
||||
|
||||
if( *text == '\n' || *text == '\r' )
|
||||
@@ -886,38 +887,21 @@ CL_ParseQuakeMessage
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
{
|
||||
int cmd, param1, param2;
|
||||
size_t bufStart;
|
||||
const char *str;
|
||||
|
||||
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||
CL_Parse_Debug( true ); // begin parsing
|
||||
|
||||
// init excise buffer
|
||||
MSG_Init( &msg_demo, "UserMsg", msg_buf, sizeof( msg_buf ));
|
||||
|
||||
if( normal_message )
|
||||
{
|
||||
// assume no entity/player update this packet
|
||||
if( cls.state == ca_active )
|
||||
{
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
|
||||
}
|
||||
}
|
||||
|
||||
// parse the message
|
||||
while( 1 )
|
||||
{
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
{
|
||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
||||
Host_Error( "%s: overflow!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1022,7 +1006,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
CL_ParseQuakeDamage( msg );
|
||||
break;
|
||||
case svc_spawnstatic:
|
||||
CL_ParseQuakeStaticEntity( msg );
|
||||
CL_ParseStaticEntity( msg );
|
||||
break;
|
||||
case svc_spawnbinary:
|
||||
// never used in Quake
|
||||
@@ -1108,14 +1092,11 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Host_Error( "CL_ParseServerMessage: Illegible server message\n" );
|
||||
Host_Error( "%s: Illegible server message\n", __func__ );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
|
||||
CL_Parse_Debug( false ); // done
|
||||
|
||||
// now process packet.
|
||||
CL_ProcessPacket( &cl.frames[cl.parsecountmod] );
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ GNU General Public License for more details.
|
||||
|
||||
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis )
|
||||
{
|
||||
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis );
|
||||
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis, false );
|
||||
}
|
||||
|
||||
lightstyle_t *CL_GetLightStyle( int number )
|
||||
@@ -170,6 +170,12 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
|
||||
return refState.width;
|
||||
case PARM_SCREEN_HEIGHT:
|
||||
return refState.height;
|
||||
case PARM_SKY_SPHERE:
|
||||
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX );
|
||||
case PARM_SURF_SAMPLESIZE:
|
||||
if( arg >= 0 && arg < cl.worldmodel->numsurfaces )
|
||||
return Mod_SampleSizeForFace( &cl.worldmodel->surfaces[arg] );
|
||||
return LM_SAMPLE_SIZE;
|
||||
default:
|
||||
// indicates call from client.dll
|
||||
if( checkRef )
|
||||
@@ -341,7 +347,7 @@ qboolean R_InitRenderAPI( void )
|
||||
{
|
||||
if( clgame.dllFuncs.pfnGetRenderInterface( CL_RENDER_INTERFACE_VERSION, &gRenderAPI, &clgame.drawFuncs ))
|
||||
{
|
||||
Con_Reportf( "CL_LoadProgs: ^2initailized extended RenderAPI ^7ver. %i\n", CL_RENDER_INTERFACE_VERSION );
|
||||
Con_Reportf( "%s: ^2initailized extended RenderAPI ^7ver. %i\n", __func__, CL_RENDER_INTERFACE_VERSION );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ CVAR_DEFINE_AUTO( scr_centertime, "2.5", 0, "centerprint hold time" );
|
||||
CVAR_DEFINE_AUTO( scr_loading, "0", 0, "loading bar progress" );
|
||||
CVAR_DEFINE_AUTO( scr_download, "-1", 0, "downloading bar progress" );
|
||||
CVAR_DEFINE( scr_viewsize, "viewsize", "120", FCVAR_ARCHIVE, "screen size (quake only)" );
|
||||
CVAR_DEFINE_AUTO( cl_testlights, "0", 0, "test dynamic lights" );
|
||||
CVAR_DEFINE_AUTO( cl_testlights, "0", FCVAR_CHEAT, "test dynamic lights" );
|
||||
CVAR_DEFINE( cl_allow_levelshots, "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" );
|
||||
CVAR_DEFINE_AUTO( cl_levelshot_name, "*black", 0, "contains path to current levelshot" );
|
||||
static CVAR_DEFINE_AUTO( cl_envshot_size, "256", FCVAR_ARCHIVE, "envshot size of cube side" );
|
||||
@@ -32,6 +32,7 @@ CVAR_DEFINE_AUTO( v_dark, "0", 0, "starts level from dark screen" );
|
||||
static CVAR_DEFINE_AUTO( net_speeds, "0", FCVAR_ARCHIVE, "show network packets" );
|
||||
static CVAR_DEFINE_AUTO( cl_showfps, "0", FCVAR_ARCHIVE, "show client fps" );
|
||||
static CVAR_DEFINE_AUTO( cl_showpos, "0", FCVAR_ARCHIVE, "show local player position and velocity" );
|
||||
static CVAR_DEFINE_AUTO( cl_showents, "0", FCVAR_ARCHIVE | FCVAR_CHEAT, "show entities information (largely undone)" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -122,7 +123,7 @@ void SCR_DrawPos( void )
|
||||
if( cls.state != ca_active || !cl_showpos.value || cl.background )
|
||||
return;
|
||||
|
||||
ent = CL_GetLocalPlayer();
|
||||
ent = CL_EDICT_NUM( cl.playernum + 1 );
|
||||
speed = VectorLength( cl.simvel );
|
||||
|
||||
Q_snprintf( msg, MAX_SYSPATH,
|
||||
@@ -140,6 +141,68 @@ void SCR_DrawPos( void )
|
||||
Con_DrawString( refState.width / 2, 4, msg, color );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SCR_DrawEnts
|
||||
==============
|
||||
*/
|
||||
void SCR_DrawEnts( void )
|
||||
{
|
||||
rgba_t color = { 255, 255, 255, 255 };
|
||||
int i;
|
||||
|
||||
if( cls.state != ca_active || !cl_showents.value || ( cl.maxclients > 1 && !cls.demoplayback ))
|
||||
return;
|
||||
|
||||
// this probably better hook CL_AddVisibleEntities
|
||||
// as entities might get added by client.dll
|
||||
for( i = 0; i < clgame.maxEntities; i++ )
|
||||
{
|
||||
const cl_entity_t *ent = &clgame.entities[i];
|
||||
string msg;
|
||||
vec3_t screen, pos;
|
||||
|
||||
if( ent->curstate.messagenum != cl.parsecount )
|
||||
continue;
|
||||
|
||||
VectorCopy( ent->origin, pos );
|
||||
|
||||
if( ent->model != NULL )
|
||||
{
|
||||
vec3_t v;
|
||||
|
||||
// simple model type filter
|
||||
if( cl_showents.value > 1 )
|
||||
{
|
||||
if( ent->model->type != (modtype_t)( cl_showents.value - 2 ))
|
||||
continue;
|
||||
}
|
||||
|
||||
VectorAverage( ent->model->mins, ent->model->maxs, v );
|
||||
VectorAdd( pos, v, pos );
|
||||
}
|
||||
|
||||
if( !ref.dllFuncs.WorldToScreen( pos, screen ))
|
||||
{
|
||||
Q_snprintf( msg, sizeof( msg ),
|
||||
"entity %d\n"
|
||||
"model %s\n"
|
||||
"movetype %d\n",
|
||||
ent->index,
|
||||
ent->model ? ent->model->name : "(null)",
|
||||
ent->curstate.movetype );
|
||||
|
||||
screen[0] = 0.5f * screen[0] * refState.width;
|
||||
screen[1] = -0.5f * screen[1] * refState.height;
|
||||
screen[0] += 0.5f * refState.width;
|
||||
screen[1] += 0.5f * refState.height;
|
||||
|
||||
|
||||
Con_DrawString( screen[0], screen[1], msg, color );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SCR_NetSpeeds
|
||||
@@ -345,7 +408,7 @@ void SCR_MakeScreenShot( void )
|
||||
SCR_DrawPlaque
|
||||
================
|
||||
*/
|
||||
static void SCR_DrawPlaque( void )
|
||||
static qboolean SCR_DrawPlaque( void )
|
||||
{
|
||||
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
|
||||
{
|
||||
@@ -353,7 +416,11 @@ static void SCR_DrawPlaque( void )
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
||||
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1, levelshot );
|
||||
if( !cl.background ) CL_DrawHUD( CL_LOADING );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -363,15 +430,10 @@ SCR_BeginLoadingPlaque
|
||||
*/
|
||||
void SCR_BeginLoadingPlaque( qboolean is_background )
|
||||
{
|
||||
float oldclear = 0;;
|
||||
S_StopAllSounds( true );
|
||||
cl.audio_prepped = false; // don't play ambients
|
||||
cl.video_prepped = false;
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
oldclear = gl_clear.value;
|
||||
|
||||
if( CL_IsInMenu( ) && !cls.changedemo && !is_background )
|
||||
if( cls.key_dest == key_menu && !cls.changedemo && !is_background )
|
||||
{
|
||||
UI_SetActiveMenu( false );
|
||||
if( cls.state == ca_disconnected && !(GameState->curstate == STATE_RUNFRAME && GameState->nextstate != STATE_RUNFRAME) )
|
||||
@@ -384,18 +446,15 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
|
||||
if( cls.key_dest == key_console )
|
||||
return;
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
gl_clear.value = 0.0f;
|
||||
|
||||
if( is_background ) IN_MouseSavePos( );
|
||||
cls.draw_changelevel = !is_background;
|
||||
SCR_UpdateScreen();
|
||||
|
||||
// set video_prepped after update screen, so engine can draw last remaining frame
|
||||
cl.video_prepped = false;
|
||||
cls.disable_screen = host.realtime;
|
||||
cl.background = is_background; // set right state before svc_serverdata is came
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
gl_clear.value = oldclear;
|
||||
|
||||
// SNDDMA_LockSound();
|
||||
}
|
||||
|
||||
@@ -445,7 +504,7 @@ void SCR_TileClear( void )
|
||||
int i, top, bottom, left, right;
|
||||
dirty_t clear;
|
||||
|
||||
if( scr_viewsize.value >= 120 )
|
||||
if( likely( scr_viewsize.value >= 120 ))
|
||||
return; // full screen rendering
|
||||
|
||||
// erase rect will be the union of the past three frames
|
||||
@@ -523,6 +582,8 @@ text to the screen.
|
||||
*/
|
||||
void SCR_UpdateScreen( void )
|
||||
{
|
||||
qboolean screen_redraw = true; // assume screen has been redrawn
|
||||
|
||||
if( !V_PreRender( )) return;
|
||||
|
||||
switch( cls.state )
|
||||
@@ -533,7 +594,7 @@ void SCR_UpdateScreen( void )
|
||||
case ca_connecting:
|
||||
case ca_connected:
|
||||
case ca_validate:
|
||||
SCR_DrawPlaque();
|
||||
screen_redraw = SCR_DrawPlaque();
|
||||
break;
|
||||
case ca_active:
|
||||
Con_RunConsole ();
|
||||
@@ -543,11 +604,15 @@ void SCR_UpdateScreen( void )
|
||||
SCR_DrawCinematic();
|
||||
break;
|
||||
default:
|
||||
Host_Error( "SCR_UpdateScreen: bad cls.state\n" );
|
||||
Host_Error( "%s: bad cls.state\n", __func__ );
|
||||
break;
|
||||
}
|
||||
|
||||
V_PostRender();
|
||||
// during changelevel we might have a few frames when we have nothing to draw
|
||||
// (assuming levelshots are off) and drawing 2d on top of nothing or cleared screen
|
||||
// is ugly, specifically with Adreno and ImgTec GPUs
|
||||
if( screen_redraw || !cls.changelevel || !cls.changedemo )
|
||||
V_PostRender();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -753,6 +818,9 @@ void SCR_Init( void )
|
||||
Cvar_RegisterVariable( &net_speeds );
|
||||
Cvar_RegisterVariable( &cl_showfps );
|
||||
Cvar_RegisterVariable( &cl_showpos );
|
||||
#ifdef _DEBUG
|
||||
Cvar_RegisterVariable( &cl_showents );
|
||||
#endif // NDEBUG
|
||||
|
||||
// register our commands
|
||||
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );
|
||||
|
||||
@@ -1269,6 +1269,73 @@ void GAME_EXPORT R_Sprite_Smoke( TEMPENTITY *pTemp, float scale )
|
||||
pTemp->entity.curstate.scale = scale;
|
||||
}
|
||||
|
||||
static void R_Spray_Generic( const char *func, const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode, qboolean sprite_spray )
|
||||
{
|
||||
model_t *mod = CL_ModelHandle( modelIndex );
|
||||
float noise = spread / 100.0f;
|
||||
float znoise = noise * 1.5f;
|
||||
int i;
|
||||
|
||||
znoise = Q_min( 1.0f, znoise );
|
||||
|
||||
if( !mod )
|
||||
{
|
||||
Con_Reportf( "%s: No model %d!\n", func, modelIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
TEMPENTITY *tent = CL_TempEntAlloc( pos, mod );
|
||||
float rand_speed;
|
||||
vec3_t noise_vec, vout;
|
||||
|
||||
if( !tent )
|
||||
break;
|
||||
|
||||
tent->flags |= FTENT_SLOWGRAVITY;
|
||||
tent->entity.curstate.rendermode = rendermode;
|
||||
tent->entity.curstate.renderamt = 255;
|
||||
tent->entity.baseline.renderamt = 255;
|
||||
tent->entity.curstate.renderfx = kRenderFxNoDissipation;
|
||||
|
||||
noise_vec[0] = COM_RandomFloat( -noise, noise );
|
||||
noise_vec[1] = COM_RandomFloat( -noise, noise );
|
||||
noise_vec[2] = COM_RandomFloat( 0.0f, znoise );
|
||||
rand_speed = COM_RandomFloat( speed * 0.8f, speed * 1.2f );
|
||||
|
||||
VectorAdd( dir, noise_vec, vout );
|
||||
VectorScale( vout, rand_speed, tent->entity.baseline.origin );
|
||||
|
||||
if( sprite_spray ) // if TE_SPRITE_SPRAY
|
||||
{
|
||||
tent->flags |= FTENT_FADEOUT;
|
||||
tent->fadeSpeed = 2.0f;
|
||||
|
||||
tent->entity.curstate.framerate = 0.5f;
|
||||
tent->die = cl.time + 0.35;
|
||||
tent->entity.curstate.frame = COM_RandomLong( 0, tent->frameMax ); // frameMax inclusive
|
||||
}
|
||||
else
|
||||
{
|
||||
tent->flags |= FTENT_COLLIDEWORLD;
|
||||
|
||||
if( tent->frameMax > 1 )
|
||||
{
|
||||
tent->flags |= FTENT_SPRANIMATE;
|
||||
tent->entity.curstate.framerate = 10.0f;
|
||||
tent->die = cl.time + tent->frameMax * 0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tent->entity.curstate.framerate = 1.0f;
|
||||
tent->die = cl.time + 0.35;
|
||||
}
|
||||
tent->entity.curstate.frame = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Spray
|
||||
@@ -1278,61 +1345,7 @@ Throws a shower of sprites or models
|
||||
*/
|
||||
void GAME_EXPORT R_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread, int rendermode )
|
||||
{
|
||||
TEMPENTITY *pTemp;
|
||||
float noise;
|
||||
float znoise;
|
||||
model_t *pmodel;
|
||||
int i;
|
||||
|
||||
if(( pmodel = CL_ModelHandle( modelIndex )) == NULL )
|
||||
{
|
||||
Con_Reportf( "No model %d!\n", modelIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
noise = (float)spread / 100.0f;
|
||||
|
||||
// more vertical displacement
|
||||
znoise = Q_min( 1.0f, noise * 1.5f );
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
pTemp = CL_TempEntAlloc( pos, pmodel );
|
||||
if( !pTemp ) return;
|
||||
|
||||
pTemp->entity.curstate.rendermode = rendermode;
|
||||
pTemp->entity.baseline.renderamt = pTemp->entity.curstate.renderamt = 255;
|
||||
pTemp->entity.curstate.renderfx = kRenderFxNoDissipation;
|
||||
|
||||
if( rendermode != kRenderGlow )
|
||||
{
|
||||
// spray
|
||||
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SLOWGRAVITY;
|
||||
|
||||
if( pTemp->frameMax > 1 )
|
||||
{
|
||||
pTemp->flags |= FTENT_COLLIDEWORLD | FTENT_SLOWGRAVITY | FTENT_SPRANIMATE;
|
||||
pTemp->die = cl.time + (pTemp->frameMax * 0.1f);
|
||||
pTemp->entity.curstate.framerate = 10;
|
||||
}
|
||||
else pTemp->die = cl.time + 0.35f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sprite spray
|
||||
pTemp->entity.curstate.frame = COM_RandomLong( 0, pTemp->frameMax );
|
||||
pTemp->flags |= FTENT_FADEOUT | FTENT_SLOWGRAVITY;
|
||||
pTemp->entity.curstate.framerate = 0.5;
|
||||
pTemp->die = cl.time + 0.35f;
|
||||
pTemp->fadeSpeed = 2.0;
|
||||
}
|
||||
|
||||
// make the spittle fly the direction indicated, but mix in some noise.
|
||||
pTemp->entity.baseline.origin[0] = dir[0] + COM_RandomFloat( -noise, noise );
|
||||
pTemp->entity.baseline.origin[1] = dir[1] + COM_RandomFloat( -noise, noise );
|
||||
pTemp->entity.baseline.origin[2] = dir[2] + COM_RandomFloat( 0, znoise );
|
||||
VectorScale( pTemp->entity.baseline.origin, COM_RandomFloat(( speed * 0.8f ), ( speed * 1.2f )), pTemp->entity.baseline.origin );
|
||||
}
|
||||
R_Spray_Generic( __func__, pos, dir, modelIndex, count, speed, spread, rendermode, false );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1344,7 +1357,7 @@ Spray of alpha sprites
|
||||
*/
|
||||
void GAME_EXPORT R_Sprite_Spray( const vec3_t pos, const vec3_t dir, int modelIndex, int count, int speed, int spread )
|
||||
{
|
||||
R_Spray( pos, dir, modelIndex, count, speed, spread, kRenderGlow );
|
||||
R_Spray_Generic( __func__, pos, dir, modelIndex, count, speed, spread, kRenderTransAlpha, true );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1904,7 +1917,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
|
||||
// this will probably be fatal anyway
|
||||
if( iSize > sizeof( pbuf ))
|
||||
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __FUNCTION__ );
|
||||
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
|
||||
|
||||
// parse user message into buffer
|
||||
MSG_ReadBytes( msg, pbuf, iSize );
|
||||
@@ -2384,13 +2397,13 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
||||
R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL );
|
||||
break;
|
||||
default:
|
||||
Con_DPrintf( S_ERROR "ParseTempEntity: illegible TE message %i\n", type );
|
||||
Con_DPrintf( S_ERROR "%s: illegible TE message %i\n", __func__, type );
|
||||
break;
|
||||
}
|
||||
|
||||
// throw warning
|
||||
if( MSG_CheckOverflow( &buf ))
|
||||
Con_DPrintf( S_WARN "ParseTempEntity: overflow TE message %i\n", type );
|
||||
Con_DPrintf( S_WARN "%s: overflow TE message %i\n", __func__, type );
|
||||
}
|
||||
|
||||
|
||||
@@ -2448,7 +2461,8 @@ void CL_SetLightstyle( int style, const char *s, float f )
|
||||
}
|
||||
}
|
||||
|
||||
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
|
||||
if( ls->length >= 1 )
|
||||
Con_Reportf( "Lightstyle %i (%s), interp %s\n", style, ls->pattern, ls->interp ? "Yes" : "No" );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2570,31 +2584,43 @@ CL_DecayLights
|
||||
*/
|
||||
void CL_DecayLights( void )
|
||||
{
|
||||
dlight_t *dl;
|
||||
float time;
|
||||
const float time = cl.time;
|
||||
const float dt = cl.time - cl.oldtime;
|
||||
int i;
|
||||
|
||||
time = cl.time - cl.oldtime;
|
||||
|
||||
for( i = 0, dl = cl_dlights; i < MAX_DLIGHTS; i++, dl++ )
|
||||
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
if( !dl->radius ) continue;
|
||||
dlight_t *dl = &cl_dlights[i];
|
||||
|
||||
dl->radius -= time * dl->decay;
|
||||
if( dl->radius < 0 ) dl->radius = 0;
|
||||
if( !dl->radius )
|
||||
continue;
|
||||
|
||||
if( dl->die < cl.time || !dl->radius )
|
||||
if( dl->die < time )
|
||||
{
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
continue;
|
||||
}
|
||||
|
||||
dl->radius -= dt * dl->decay;
|
||||
if( dl->radius <= 0 )
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
}
|
||||
|
||||
for( i = 0, dl = cl_elights; i < MAX_ELIGHTS; i++, dl++ )
|
||||
for( i = 0; i < MAX_ELIGHTS; i++ )
|
||||
{
|
||||
if( !dl->radius ) continue;
|
||||
dlight_t *dl = &cl_elights[i];
|
||||
|
||||
dl->radius -= time * dl->decay;
|
||||
if( dl->radius < 0 ) dl->radius = 0;
|
||||
if( !dl->radius )
|
||||
continue;
|
||||
|
||||
if( dl->die < cl.time || !dl->radius )
|
||||
if( dl->die < time )
|
||||
{
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
continue;
|
||||
}
|
||||
|
||||
dl->radius -= dt * dl->decay;
|
||||
if( dl->radius <= 0 )
|
||||
memset( dl, 0, sizeof( *dl ));
|
||||
}
|
||||
}
|
||||
@@ -2737,7 +2763,12 @@ void CL_AddEntityEffects( cl_entity_t *ent )
|
||||
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
|
||||
R_EntityBrightlight( ent, ent->index /* 1 in GoldSrc */, 400 );
|
||||
else if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
|
||||
CL_UpdateFlashlight( ent );
|
||||
{
|
||||
if( Host_IsQuakeCompatible( ))
|
||||
R_EntityDimlight( ent, ent->index );
|
||||
else
|
||||
CL_UpdateFlashlight( ent );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2927,16 +2958,26 @@ static void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, flo
|
||||
{
|
||||
if( !pCust->nUserData1 )
|
||||
{
|
||||
int sprayTextureIndex;
|
||||
char decalname[MAX_VA_STRING];
|
||||
int width, height;
|
||||
|
||||
Q_snprintf( decalname, sizeof( decalname ), "player%dlogo%d", playernum, customIndex );
|
||||
sprayTextureIndex = ref.dllFuncs.GL_FindTexture( decalname );
|
||||
if( sprayTextureIndex != 0 )
|
||||
{
|
||||
ref.dllFuncs.GL_FreeTexture( sprayTextureIndex );
|
||||
}
|
||||
textureIndex = ref.dllFuncs.GL_FindTexture( decalname );
|
||||
if( textureIndex != 0 )
|
||||
ref.dllFuncs.GL_FreeTexture( textureIndex );
|
||||
|
||||
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );
|
||||
|
||||
width = REF_GET_PARM( PARM_TEX_WIDTH, pCust->nUserData1 );
|
||||
height = REF_GET_PARM( PARM_TEX_HEIGHT, pCust->nUserData1 );
|
||||
|
||||
if( width > cl_logomaxdim.value || height > cl_logomaxdim.value )
|
||||
{
|
||||
double scale = cl_logomaxdim.value / Q_max( width, height );
|
||||
width = round( width * scale );
|
||||
height = round( height * scale );
|
||||
ref.dllFuncs.R_OverrideTextureSourceSize( pCust->nUserData1, width, height ); // default custom decal from HL1
|
||||
}
|
||||
}
|
||||
textureIndex = pCust->nUserData1;
|
||||
}
|
||||
@@ -2981,8 +3022,47 @@ int GAME_EXPORT CL_DecalIndex( int id )
|
||||
|
||||
if( cl.decal_index[id] == 0 )
|
||||
{
|
||||
int gl_texturenum = 0;
|
||||
|
||||
Image_SetForceFlags( IL_LOAD_DECAL );
|
||||
cl.decal_index[id] = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
|
||||
|
||||
if( Mod_AllowMaterials( ))
|
||||
{
|
||||
string decalname;
|
||||
|
||||
if( Q_snprintf( decalname, sizeof( decalname ), "materials/decals/%s.tga", host.draw_decals[id] ) > 0 )
|
||||
{
|
||||
if( g_fsapi.FileExists( decalname, false ))
|
||||
{
|
||||
gl_texturenum = ref.dllFuncs.GL_LoadTexture( decalname, NULL, 0, TF_DECAL );
|
||||
if( host_allow_materials.value == 2.0f )
|
||||
Con_Printf( "Looking for %s decal replacement...%s (%s)\n", host.draw_decals[id], gl_texturenum != 0 ? S_GREEN "OK" : S_RED "FAIL", decalname );
|
||||
}
|
||||
else if( host_allow_materials.value == 2.0f )
|
||||
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (%s)\n", host.draw_decals[id], decalname );
|
||||
}
|
||||
else if( host_allow_materials.value == 2.0f )
|
||||
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (overflow)\n", host.draw_decals[id] );
|
||||
|
||||
if( gl_texturenum )
|
||||
{
|
||||
byte *fin;
|
||||
|
||||
Q_snprintf( decalname, sizeof( decalname ), "decals.wad/%s", host.draw_decals[id] );
|
||||
|
||||
if(( fin = g_fsapi.LoadFile( decalname, NULL, false )) != NULL )
|
||||
{
|
||||
mip_t *mip = (mip_t *)fin;
|
||||
ref.dllFuncs.R_OverrideTextureSourceSize( gl_texturenum, mip->width, mip->height );
|
||||
Mem_Free( fin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !gl_texturenum )
|
||||
gl_texturenum = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
|
||||
|
||||
cl.decal_index[id] = gl_texturenum;
|
||||
Image_ClearForceFlags();
|
||||
}
|
||||
|
||||
@@ -3009,26 +3089,6 @@ EFRAGS MANAGEMENT
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
efrag_t cl_efrags[MAX_EFRAGS];
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_ClearEfrags
|
||||
==============
|
||||
*/
|
||||
void CL_ClearEfrags( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
memset( cl_efrags, 0, sizeof( cl_efrags ));
|
||||
|
||||
// allocate the efrags and chain together into a free list
|
||||
clgame.free_efrags = cl_efrags;
|
||||
for( i = 0; i < MAX_EFRAGS - 1; i++ )
|
||||
clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1];
|
||||
clgame.free_efrags[i].entnext = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
R_ClearStaticEntities
|
||||
@@ -3066,4 +3126,3 @@ void CL_ClearEffects( void )
|
||||
CL_ClearParticles ();
|
||||
CL_ClearLightStyles ();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ static void V_CalcViewRect( void )
|
||||
int sb_lines;
|
||||
float size;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
if( Host_IsQuakeCompatible( ))
|
||||
{
|
||||
// intermission is always full screen
|
||||
if( cl.intermission ) size = 120.0f;
|
||||
@@ -144,7 +144,9 @@ static void V_SetRefParams( ref_params_t *fd )
|
||||
VectorCopy( cl.viewangles, fd->cl_viewangles );
|
||||
fd->health = cl.local.health;
|
||||
VectorCopy( cl.crosshairangle, fd->crosshairangle );
|
||||
fd->viewsize = scr_viewsize.value;
|
||||
if( Host_IsQuakeCompatible( ))
|
||||
fd->viewsize = scr_viewsize.value;
|
||||
else fd->viewsize = 120.0f;
|
||||
|
||||
VectorCopy( cl.punchangle, fd->punchangle );
|
||||
fd->maxclients = cl.maxclients;
|
||||
@@ -341,7 +343,7 @@ qboolean V_PreRender( void )
|
||||
{
|
||||
if(( host.realtime - cls.disable_screen ) > cl_timeout.value )
|
||||
{
|
||||
Con_Reportf( "V_PreRender: loading plaque timed out\n" );
|
||||
Con_Reportf( "%s: loading plaque timed out\n", __func__ );
|
||||
cls.disable_screen = 0.0f;
|
||||
}
|
||||
return false;
|
||||
@@ -506,7 +508,6 @@ V_PostRender
|
||||
*/
|
||||
void V_PostRender( void )
|
||||
{
|
||||
static double oldtime;
|
||||
qboolean draw_2d = false;
|
||||
|
||||
ref.dllFuncs.R_AllowFog( false );
|
||||
@@ -533,6 +534,7 @@ void V_PostRender( void )
|
||||
SCR_RSpeeds();
|
||||
SCR_NetSpeeds();
|
||||
SCR_DrawPos();
|
||||
SCR_DrawEnts();
|
||||
SCR_DrawNetGraph();
|
||||
SV_DrawOrthoTriangles();
|
||||
CL_DrawDemoRecording();
|
||||
|
||||
@@ -229,7 +229,7 @@ typedef struct
|
||||
char serverinfo[MAX_SERVERINFO_STRING];
|
||||
player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself
|
||||
double lastresourcecheck;
|
||||
string downloadUrl;
|
||||
qboolean http_download;
|
||||
event_state_t events;
|
||||
|
||||
// predicting stuff but not only...
|
||||
@@ -276,6 +276,8 @@ typedef struct
|
||||
model_t *worldmodel; // pointer to world
|
||||
|
||||
int lostpackets; // count lost packets and show dialog in menu
|
||||
|
||||
double frametime_remainder;
|
||||
} client_t;
|
||||
|
||||
/*
|
||||
@@ -307,6 +309,14 @@ 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];
|
||||
@@ -491,7 +501,6 @@ typedef struct
|
||||
|
||||
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
|
||||
|
||||
efrag_t *free_efrags; // linked efrags
|
||||
cl_entity_t viewent; // viewmodel
|
||||
|
||||
qboolean client_dll_uses_sdl;
|
||||
@@ -508,8 +517,9 @@ typedef struct
|
||||
player_info_t playerinfo; // local playerinfo
|
||||
|
||||
gameui_draw_t ds; // draw2d stuff (menu images)
|
||||
GAMEINFO gameInfo; // current gameInfo
|
||||
GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI
|
||||
gameinfo2_t gameInfo; // current gameInfo
|
||||
gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand
|
||||
GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand
|
||||
|
||||
ui_globalvars_t *globals;
|
||||
|
||||
@@ -518,7 +528,7 @@ typedef struct
|
||||
int logo_yres;
|
||||
float logo_length;
|
||||
|
||||
qboolean use_text_api;
|
||||
qboolean use_extended_api;
|
||||
} gameui_static_t;
|
||||
|
||||
typedef struct
|
||||
@@ -539,12 +549,8 @@ typedef struct
|
||||
|
||||
poolhandle_t mempool; // client premamnent pool: edicts etc
|
||||
|
||||
netadr_t hltv_listen_address;
|
||||
|
||||
int signon; // 0 to SIGNONS, for the signon sequence.
|
||||
int quakePort; // a 16 bit value that allows quake servers
|
||||
// to work around address translating routers
|
||||
// g-cont. this port allow many copies of engine in multiplayer game
|
||||
|
||||
// connection information
|
||||
char servername[MAX_QPATH]; // name of server from original connect
|
||||
double connect_time; // for connection retransmits
|
||||
@@ -628,12 +634,14 @@ typedef struct
|
||||
char internetservers_query[512]; // cached query
|
||||
uint32_t internetservers_query_len;
|
||||
|
||||
// legacy mode support
|
||||
qboolean legacymode; // one-way 48 protocol compatibility
|
||||
netadr_t legacyserver;
|
||||
// multiprotocol support
|
||||
connprotocol_t legacymode;
|
||||
int extensions;
|
||||
|
||||
netadr_t serveradr;
|
||||
|
||||
// do we accept utf8 as input
|
||||
qboolean accept_utf8;
|
||||
} client_static_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -653,14 +661,11 @@ extern gameui_static_t gameui;
|
||||
// cvars
|
||||
//
|
||||
extern convar_t mp_decals;
|
||||
extern convar_t cl_logofile;
|
||||
extern convar_t cl_logocolor;
|
||||
extern convar_t cl_logomaxdim;
|
||||
extern convar_t cl_allow_download;
|
||||
extern convar_t cl_allow_upload;
|
||||
extern convar_t cl_download_ingame;
|
||||
extern convar_t cl_nopred;
|
||||
extern convar_t cl_timeout;
|
||||
extern convar_t cl_nodelta;
|
||||
extern convar_t cl_interp;
|
||||
extern convar_t cl_nointerp;
|
||||
extern convar_t cl_showerror;
|
||||
@@ -673,13 +678,11 @@ extern convar_t cl_updaterate;
|
||||
extern convar_t cl_solid_players;
|
||||
extern convar_t cl_idealpitchscale;
|
||||
extern convar_t cl_allow_levelshots;
|
||||
extern convar_t cl_lightstyle_lerping;
|
||||
extern convar_t cl_draw_particles;
|
||||
extern convar_t cl_draw_tracers;
|
||||
extern convar_t cl_levelshot_name;
|
||||
extern convar_t cl_draw_beams;
|
||||
extern convar_t cl_clockreset;
|
||||
extern convar_t cl_fixtimerate;
|
||||
extern convar_t hud_fontscale;
|
||||
extern convar_t hud_fontrender;
|
||||
extern convar_t hud_scale;
|
||||
@@ -781,6 +784,7 @@ void CL_Demos_f( void );
|
||||
void CL_DeleteDemo_f( void );
|
||||
void CL_Record_f( void );
|
||||
void CL_Stop_f( void );
|
||||
void CL_ListDemo_f( void );
|
||||
int CL_GetDemoComment( const char *demoname, char *comment );
|
||||
|
||||
//
|
||||
@@ -849,14 +853,14 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
if( !clgame.entities )
|
||||
{
|
||||
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n");
|
||||
Host_Error( "%s: clgame.entities is NULL\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
||||
return clgame.entities + n;
|
||||
|
||||
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
||||
Host_Error( "%s: bad number %i\n", __func__, n );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -887,8 +891,8 @@ void CL_ParseFileTransferFailed( sizebuf_t *msg );
|
||||
void CL_ParseHLTV( sizebuf_t *msg );
|
||||
void CL_ParseDirector( sizebuf_t *msg );
|
||||
void CL_ParseResLocation( sizebuf_t *msg );
|
||||
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext );
|
||||
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message );
|
||||
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_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
|
||||
qboolean CL_RequestMissingResources( void );
|
||||
@@ -904,7 +908,7 @@ int CL_EstimateNeededResources( void );
|
||||
//
|
||||
// cl_parse_48.c
|
||||
//
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message );
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg );
|
||||
void CL_LegacyPrecache_f( void );
|
||||
|
||||
//
|
||||
@@ -922,6 +926,7 @@ void SCR_NetSpeeds( void );
|
||||
void SCR_RSpeeds( void );
|
||||
void SCR_DrawFPS( int height );
|
||||
void SCR_DrawPos( void );
|
||||
void SCR_DrawEnts( void );
|
||||
|
||||
//
|
||||
// cl_netgraph.c
|
||||
@@ -963,7 +968,7 @@ void CL_SetIdealPitch( void );
|
||||
//
|
||||
// cl_qparse.c
|
||||
//
|
||||
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message );
|
||||
void CL_ParseQuakeMessage( sizebuf_t *msg );
|
||||
|
||||
//
|
||||
// cl_frame.c
|
||||
@@ -1056,7 +1061,6 @@ int Con_UtfMoveRight( char *str, int pos, int length );
|
||||
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
|
||||
cl_font_t *Con_GetCurFont( void );
|
||||
cl_font_t *Con_GetFont( int num );
|
||||
void Con_DrawCharacterLen( int number, int *width, int *height );
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
|
||||
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
|
||||
void Con_CharEvent( int key );
|
||||
@@ -1107,7 +1111,7 @@ qboolean UI_MouseInRect( void );
|
||||
qboolean UI_IsVisible( void );
|
||||
void UI_ResetPing( void );
|
||||
void UI_ShowUpdateDialog( qboolean preferStore );
|
||||
void UI_ShowMessageBox( const char *text );
|
||||
qboolean UI_ShowMessageBox( const char *text );
|
||||
void UI_AddTouchButtonToList( const char *name, const char *texture, const char *command, unsigned char *color, int flags );
|
||||
void UI_ConnectionProgress_Disconnect( void );
|
||||
void UI_ConnectionProgress_Download( const char *pszFileName, const char *pszServerName, const char *pszServerPath, int iCurrent, int iTotal, const char *comment );
|
||||
@@ -1161,5 +1165,7 @@ int Key_ToUpper( int key );
|
||||
void OSK_Draw( void );
|
||||
|
||||
extern rgba_t g_color_table[8];
|
||||
extern triangleapi_t gTriApi;
|
||||
extern net_api_t gNetApi;
|
||||
|
||||
#endif//CLIENT_H
|
||||
|
||||
@@ -21,6 +21,7 @@ GNU General Public License for more details.
|
||||
#include "qfont.h"
|
||||
#include "wadfile.h"
|
||||
#include "input.h"
|
||||
#include "utflib.h"
|
||||
|
||||
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
|
||||
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
|
||||
@@ -34,7 +35,6 @@ static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in m
|
||||
static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" );
|
||||
|
||||
static int g_codepage = 0;
|
||||
static qboolean g_utf8 = false;
|
||||
|
||||
static qboolean g_messagemode_privileged = true;
|
||||
|
||||
@@ -610,19 +610,6 @@ static void Con_LoadConchars( void )
|
||||
con.curFont = &con.chars[fontSize];
|
||||
}
|
||||
|
||||
// CP1251 table
|
||||
|
||||
int table_cp1251[64] = {
|
||||
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
|
||||
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
|
||||
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
|
||||
0x007F, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
|
||||
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
|
||||
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
|
||||
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
|
||||
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
|
||||
};
|
||||
|
||||
/*
|
||||
============================
|
||||
Con_UtfProcessChar
|
||||
@@ -632,84 +619,28 @@ Convert utf char to current font's single-byte encoding
|
||||
*/
|
||||
int Con_UtfProcessCharForce( int in )
|
||||
{
|
||||
static int m = -1, k = 0; //multibyte state
|
||||
static int uc = 0; //unicode char
|
||||
// TODO: get rid of global state where possible
|
||||
static utfstate_t state = { 0 };
|
||||
|
||||
if( !in )
|
||||
{
|
||||
m = -1;
|
||||
k = 0;
|
||||
uc = 0;
|
||||
return 0;
|
||||
}
|
||||
int ch = Q_DecodeUTF8( &state, in );
|
||||
|
||||
// Get character length
|
||||
if(m == -1)
|
||||
{
|
||||
uc = 0;
|
||||
if( in >= 0xF8 )
|
||||
return 0;
|
||||
else if( in >= 0xF0 )
|
||||
uc = in & 0x07, m = 3;
|
||||
else if( in >= 0xE0 )
|
||||
uc = in & 0x0F, m = 2;
|
||||
else if( in >= 0xC0 )
|
||||
uc = in & 0x1F, m = 1;
|
||||
else if( in <= 0x7F)
|
||||
return in; //ascii
|
||||
// return 0 if we need more chars to decode one
|
||||
k=0;
|
||||
return 0;
|
||||
}
|
||||
// get more chars
|
||||
else if( k <= m )
|
||||
{
|
||||
uc <<= 6;
|
||||
uc += in & 0x3F;
|
||||
k++;
|
||||
}
|
||||
if( in > 0xBF || m < 0 )
|
||||
{
|
||||
m = -1;
|
||||
return 0;
|
||||
}
|
||||
if( k == m )
|
||||
{
|
||||
k = m = -1;
|
||||
if( g_codepage == 1251 )
|
||||
{
|
||||
// cp1251 now
|
||||
if( uc >= 0x0410 && uc <= 0x042F )
|
||||
return uc - 0x410 + 0xC0;
|
||||
if( uc >= 0x0430 && uc <= 0x044F )
|
||||
return uc - 0x430 + 0xE0;
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < 64; i++ )
|
||||
if( table_cp1251[i] == uc )
|
||||
return i + 0x80;
|
||||
}
|
||||
}
|
||||
else if( g_codepage == 1252 )
|
||||
{
|
||||
if( uc < 255 )
|
||||
return uc;
|
||||
}
|
||||
if( g_codepage == 1251 )
|
||||
return Q_UnicodeToCP1251( ch );
|
||||
if( g_codepage == 1252 )
|
||||
return Q_UnicodeToCP1252( ch );
|
||||
|
||||
// not implemented yet
|
||||
return '?';
|
||||
}
|
||||
return 0;
|
||||
return '?'; // not implemented yet
|
||||
}
|
||||
|
||||
int GAME_EXPORT Con_UtfProcessChar( int in )
|
||||
{
|
||||
if( !g_utf8 )
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
return in;
|
||||
else
|
||||
return Con_UtfProcessCharForce( in );
|
||||
|
||||
// otherwise, decode it and convert to selected codepage
|
||||
return Con_UtfProcessCharForce( in );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Con_UtfMoveLeft
|
||||
@@ -719,16 +650,22 @@ get position of previous printful char
|
||||
*/
|
||||
int Con_UtfMoveLeft( char *str, int pos )
|
||||
{
|
||||
int i, k = 0;
|
||||
// int j;
|
||||
if( !g_utf8 )
|
||||
utfstate_t state = { 0 };
|
||||
int k = 0;
|
||||
int i;
|
||||
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
return pos - 1;
|
||||
Con_UtfProcessChar( 0 );
|
||||
if(pos == 1) return 0;
|
||||
for( i = 0; i < pos-1; i++ )
|
||||
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
|
||||
k = i+1;
|
||||
Con_UtfProcessChar( 0 );
|
||||
|
||||
if( pos == 1 )
|
||||
return 0;
|
||||
|
||||
for( i = 0; i < pos - 1; i++ )
|
||||
{
|
||||
if( Q_DecodeUTF8( &state, (byte)str[i] ))
|
||||
k = i + 1;
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
@@ -741,17 +678,19 @@ get next of previous printful char
|
||||
*/
|
||||
int Con_UtfMoveRight( char *str, int pos, int length )
|
||||
{
|
||||
utfstate_t state = { 0 };
|
||||
int i;
|
||||
if( !g_utf8 )
|
||||
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
return pos + 1;
|
||||
Con_UtfProcessChar( 0 );
|
||||
|
||||
for( i = pos; i <= length; i++ )
|
||||
{
|
||||
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
|
||||
return i+1;
|
||||
if( Q_DecodeUTF8( &state, (byte)str[i] ))
|
||||
return i + 1;
|
||||
}
|
||||
Con_UtfProcessChar( 0 );
|
||||
return pos+1;
|
||||
|
||||
return pos + 1;
|
||||
}
|
||||
|
||||
static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
|
||||
@@ -908,7 +847,6 @@ void Con_Print( const char *txt )
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
qboolean norefresh = false;
|
||||
static int lastlength = 0;
|
||||
static qboolean inupdate;
|
||||
static int bufpos = 0;
|
||||
int c, mask = 0;
|
||||
|
||||
@@ -999,6 +937,27 @@ void Con_Print( const char *txt )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_NXPrintfv
|
||||
|
||||
Draw a single debug line with specified height, color and time to live
|
||||
================
|
||||
*/
|
||||
static void Con_NXPrintfv( keydest_t key_dest, const con_nprint_t *info, const char *fmt, va_list va )
|
||||
{
|
||||
if( info->index < 0 || info->index >= ARRAYSIZE( con.notify ))
|
||||
return;
|
||||
|
||||
Q_vsnprintf( con.notify[info->index].szNotify, sizeof( con.notify[info->index].szNotify ), fmt, va );
|
||||
|
||||
// setup values
|
||||
con.notify[info->index].key_dest = key_dest;
|
||||
con.notify[info->index].expire = host.realtime + info->time_to_live;
|
||||
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
|
||||
con.draw_notify = true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_NPrint
|
||||
@@ -1009,21 +968,16 @@ Draw a single debug line with specified height
|
||||
void GAME_EXPORT Con_NPrintf( int idx, const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if( idx < 0 || idx >= MAX_DBG_NOTIFY )
|
||||
return;
|
||||
|
||||
memset( con.notify[idx].szNotify, 0, MAX_STRING );
|
||||
con_nprint_t info =
|
||||
{
|
||||
.index = idx,
|
||||
.time_to_live = 4.0f,
|
||||
.color = { 1.0f, 1.0f, 1.0f },
|
||||
};
|
||||
|
||||
va_start( args, fmt );
|
||||
Q_vsnprintf( con.notify[idx].szNotify, MAX_STRING, fmt, args );
|
||||
Con_NXPrintfv( key_game, &info, fmt, args );
|
||||
va_end( args );
|
||||
|
||||
// reset values
|
||||
con.notify[idx].key_dest = key_game;
|
||||
con.notify[idx].expire = host.realtime + 4.0f;
|
||||
MakeRGBA( con.notify[idx].color, 255, 255, 255, 255 );
|
||||
con.draw_notify = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1039,20 +993,9 @@ void GAME_EXPORT Con_NXPrintf( con_nprint_t *info, const char *fmt, ... )
|
||||
|
||||
if( !info ) return;
|
||||
|
||||
if( info->index < 0 || info->index >= MAX_DBG_NOTIFY )
|
||||
return;
|
||||
|
||||
memset( con.notify[info->index].szNotify, 0, MAX_STRING );
|
||||
|
||||
va_start( args, fmt );
|
||||
Q_vsnprintf( con.notify[info->index].szNotify, MAX_STRING, fmt, args );
|
||||
Con_NXPrintfv( key_game, info, fmt, args );
|
||||
va_end( args );
|
||||
|
||||
// setup values
|
||||
con.notify[info->index].key_dest = key_game;
|
||||
con.notify[info->index].expire = host.realtime + info->time_to_live;
|
||||
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
|
||||
con.draw_notify = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1065,21 +1008,16 @@ Draw a single debug line with specified height (menu version)
|
||||
void GAME_EXPORT UI_NPrintf( int idx, const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if( idx < 0 || idx >= MAX_DBG_NOTIFY )
|
||||
return;
|
||||
|
||||
memset( con.notify[idx].szNotify, 0, MAX_STRING );
|
||||
con_nprint_t info =
|
||||
{
|
||||
.index = idx,
|
||||
.time_to_live = 4.0f,
|
||||
.color = { 1.0f, 1.0f, 1.0f },
|
||||
};
|
||||
|
||||
va_start( args, fmt );
|
||||
Q_vsnprintf( con.notify[idx].szNotify, MAX_STRING, fmt, args );
|
||||
Con_NXPrintfv( key_menu, &info, fmt, args );
|
||||
va_end( args );
|
||||
|
||||
// reset values
|
||||
con.notify[idx].key_dest = key_menu;
|
||||
con.notify[idx].expire = host.realtime + 4.0f;
|
||||
MakeRGBA( con.notify[idx].color, 255, 255, 255, 255 );
|
||||
con.draw_notify = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1095,20 +1033,9 @@ void GAME_EXPORT UI_NXPrintf( con_nprint_t *info, const char *fmt, ... )
|
||||
|
||||
if( !info ) return;
|
||||
|
||||
if( info->index < 0 || info->index >= MAX_DBG_NOTIFY )
|
||||
return;
|
||||
|
||||
memset( con.notify[info->index].szNotify, 0, MAX_STRING );
|
||||
|
||||
va_start( args, fmt );
|
||||
Q_vsnprintf( con.notify[info->index].szNotify, MAX_STRING, fmt, args );
|
||||
Con_NXPrintfv( key_menu, info, fmt, args );
|
||||
va_end( args );
|
||||
|
||||
// setup values
|
||||
con.notify[info->index].key_dest = key_menu;
|
||||
con.notify[info->index].expire = host.realtime + info->time_to_live;
|
||||
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
|
||||
con.draw_notify = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1138,7 +1065,7 @@ Field_Set
|
||||
static void Field_Set( field_t *f, const char *string )
|
||||
{
|
||||
f->scroll = 0;
|
||||
f->cursor = Q_strncpy( f->buffer, string, MAX_STRING );
|
||||
f->cursor = Q_strncpy( f->buffer, string, sizeof( f->buffer ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1507,7 +1434,15 @@ static void Con_SaveHistory( con_history_t *self )
|
||||
f = FS_Open( "console_history.txt", "wb", true );
|
||||
|
||||
for( i = historyStart; i < self->next; i++ )
|
||||
FS_Printf( f, "%s\n", self->lines[i % CON_HISTORY].buffer );
|
||||
{
|
||||
const char *s = self->lines[i % CON_HISTORY].buffer;
|
||||
|
||||
// HACKHACK: don't save lines that have something that looks like a password
|
||||
if( Q_stristr( s, "password" ) || Q_stristr( s, "_pw" ))
|
||||
continue;
|
||||
|
||||
FS_Printf( f, "%s\n", s );
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
}
|
||||
@@ -1549,6 +1484,9 @@ void Key_Console( int key )
|
||||
Con_Printf( ">%s\n", con.input.buffer );
|
||||
|
||||
// copy line to history buffer
|
||||
// just in case, remove all CR and LF characters pushing it to the history
|
||||
// not sure how they get even added in the first place
|
||||
COM_RemoveLineFeed( con.input.buffer, sizeof( con.input.buffer ));
|
||||
Con_HistoryAppend( &con.history, &con.input );
|
||||
|
||||
Con_ClearField( &con.input );
|
||||
@@ -1815,7 +1753,7 @@ static void Con_DrawNotify( void )
|
||||
|
||||
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
|
||||
{
|
||||
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
|
||||
for( i = Q_max( 0, CON_LINES_COUNT - con.num_times ); i < CON_LINES_COUNT; i++ )
|
||||
{
|
||||
con_lineinfo_t *l = &CON_LINES( i );
|
||||
|
||||
@@ -2157,7 +2095,7 @@ void Con_RunConsole( void )
|
||||
g_codepage = 1252;
|
||||
}
|
||||
|
||||
g_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
Con_InvalidateFonts();
|
||||
Con_LoadConchars();
|
||||
ClearBits( con_charset.flags, FCVAR_CHANGED );
|
||||
@@ -2195,6 +2133,34 @@ void Con_CharEvent( int key )
|
||||
}
|
||||
}
|
||||
|
||||
static int Con_LoadSimpleConback( const char *name, int flags )
|
||||
{
|
||||
const char *paths[] = {
|
||||
"gfx/shell/%s.dds",
|
||||
"gfx/shell/%s.bmp",
|
||||
"gfx/shell/%s.tga",
|
||||
"cached/%s640",
|
||||
"cached/%s",
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( paths ); i++ )
|
||||
{
|
||||
string path;
|
||||
|
||||
Q_snprintf( path, sizeof( path ), paths[i], name );
|
||||
if( g_fsapi.FileExists( path, false ))
|
||||
{
|
||||
int gl_texturenum = ref.dllFuncs.GL_LoadTexture( path, NULL, 0, flags );
|
||||
|
||||
if( gl_texturenum )
|
||||
return gl_texturenum;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=========
|
||||
Con_VidInit
|
||||
@@ -2217,38 +2183,12 @@ void Con_VidInit( void )
|
||||
|
||||
Con_LoadConchars();
|
||||
Con_CheckResize();
|
||||
|
||||
#if XASH_LOW_MEMORY
|
||||
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE );
|
||||
con.background = R_GetBuiltinTexture( REF_GRAY_TEXTURE );
|
||||
#else
|
||||
// loading console image
|
||||
if( host.allow_console )
|
||||
{
|
||||
// trying to load truecolor image first
|
||||
if( FS_FileExists( "gfx/shell/conback.bmp", false ) || FS_FileExists( "gfx/shell/conback.tga", false ))
|
||||
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/conback", NULL, 0, flags );
|
||||
|
||||
if( !con.background )
|
||||
{
|
||||
if( FS_FileExists( "cached/conback640", false ))
|
||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback640", NULL, 0, flags );
|
||||
else if( FS_FileExists( "cached/conback", false ))
|
||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback", NULL, 0, flags );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// trying to load truecolor image first
|
||||
if( FS_FileExists( "gfx/shell/loading.bmp", false ) || FS_FileExists( "gfx/shell/loading.tga", false ))
|
||||
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/loading", NULL, 0, flags );
|
||||
|
||||
if( !con.background )
|
||||
{
|
||||
if( FS_FileExists( "cached/loading640", false ))
|
||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading640", NULL, 0, flags );
|
||||
else if( FS_FileExists( "cached/loading", false ))
|
||||
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading", NULL, 0, flags );
|
||||
}
|
||||
}
|
||||
con.background = Con_LoadSimpleConback( host.allow_console ? "conback" : "loading", flags );
|
||||
|
||||
if( !con.background ) // last chance - quake conback image
|
||||
{
|
||||
|
||||
@@ -134,7 +134,7 @@ static void Joy_ProcessTrigger( const engineAxis_t engineAxis, short value )
|
||||
trigThreshold = joy_lt_threshold.value;
|
||||
break;
|
||||
default:
|
||||
Con_Reportf( S_ERROR "Joy_ProcessTrigger: invalid axis = %i", engineAxis );
|
||||
Con_Reportf( S_ERROR "%s: invalid axis = %i\n", __func__, engineAxis );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
|
||||
case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone.value; break;
|
||||
case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone.value; break;
|
||||
default:
|
||||
Con_Reportf( S_ERROR "Joy_ProcessStick: invalid axis = %i", engineAxis );
|
||||
Con_Reportf( S_ERROR "%s: invalid axis = %i\n", __func__, engineAxis );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
|
||||
|
||||
// fwd/side axis simulate hat movement
|
||||
if( ( engineAxis == JOY_AXIS_SIDE || engineAxis == JOY_AXIS_FWD ) &&
|
||||
( CL_IsInMenu() || CL_IsInConsole() ) )
|
||||
( cls.key_dest == key_menu || cls.key_dest == key_console ))
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ static struct touch_s
|
||||
touchdefaultbutton_t g_DefaultButtons[256];
|
||||
int g_LastDefaultButton;
|
||||
|
||||
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
|
||||
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_PRIVILEGED, "draw touch in menu (for internal use only)" );
|
||||
static CVAR_DEFINE_AUTO( touch_forwardzone, "0.06", FCVAR_FILTERABLE, "forward touch zone" );
|
||||
static CVAR_DEFINE_AUTO( touch_sidezone, "0.06", FCVAR_FILTERABLE, "side touch zone" );
|
||||
static CVAR_DEFINE_AUTO( touch_pitch, "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
|
||||
@@ -163,8 +163,8 @@ static CVAR_DEFINE_AUTO( touch_dpad_radius, "1.0", FCVAR_FILTERABLE, "dpad radiu
|
||||
static CVAR_DEFINE_AUTO( touch_joy_radius, "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
|
||||
static CVAR_DEFINE_AUTO( touch_move_indicator, "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
|
||||
static CVAR_DEFINE_AUTO( touch_joy_texture, "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
|
||||
static CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "emulate touch with mouse" );
|
||||
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
|
||||
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
|
||||
|
||||
// code looks smaller with it
|
||||
#define B(x) (button->x)
|
||||
@@ -333,7 +333,7 @@ void Touch_WriteConfig( void )
|
||||
if( Sys_CheckParm( "-nowriteconfig" ) || !touch.configchanged || !touch.config_loaded )
|
||||
return;
|
||||
|
||||
Con_DPrintf( "Touch_WriteConfig(): %s\n", touch_config_file.string );
|
||||
Con_DPrintf( "%s: %s\n", __func__, touch_config_file.string );
|
||||
|
||||
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file.string );
|
||||
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file.string );
|
||||
@@ -767,14 +767,18 @@ static void Touch_ReloadConfig_f( void )
|
||||
touch.state = state_none;
|
||||
if( touch.edit )
|
||||
touch.edit->finger = -1;
|
||||
|
||||
if( touch.selection )
|
||||
touch.selection->finger = -1;
|
||||
|
||||
touch.edit = touch.selection = NULL;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
if( FS_FileExists( touch_config_file.string, true ) )
|
||||
{
|
||||
|
||||
if( touch_in_menu.value )
|
||||
Cvar_DirectSet( &touch_in_menu, "0" );
|
||||
|
||||
if( FS_FileExists( touch_config_file.string, true ))
|
||||
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
|
||||
}
|
||||
else
|
||||
{
|
||||
Touch_LoadDefaults_f();
|
||||
@@ -1010,7 +1014,7 @@ static void Touch_DisableEdit_f( void )
|
||||
{
|
||||
Cvar_Set( "touch_in_menu", "0" );
|
||||
}
|
||||
else if( cls.key_dest == key_game )
|
||||
else if( cls.key_dest == key_game )
|
||||
Touch_WriteConfig();
|
||||
}
|
||||
|
||||
@@ -1064,7 +1068,7 @@ void Touch_Init( void )
|
||||
return;
|
||||
touch.mempool = Mem_AllocPool( "Touch" );
|
||||
//touch.first = touch.last = NULL;
|
||||
Con_Printf( "IN_TouchInit()\n");
|
||||
Con_Printf( "%s()\n", __func__ );
|
||||
touch.move_finger = touch.resize_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
touch.state = state_none;
|
||||
touch.showeditbuttons = true;
|
||||
@@ -1087,18 +1091,19 @@ void Touch_Init( void )
|
||||
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
|
||||
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.680000, 0.000000, 0.760000, 0.142222, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "voicechat", "touch_default/microphone", "+voicerecord", 0.780000, 0.817778, 0.860000, 0.960000, color, 2, 1, 8 );
|
||||
|
||||
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
|
||||
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
|
||||
@@ -1217,10 +1222,10 @@ static qboolean Touch_IsVisible( touch_button_t *button )
|
||||
if( FBitSet( button->flags, TOUCH_FL_HIDE ))
|
||||
return false; // skip hidden
|
||||
|
||||
if( FBitSet( button->flags, TOUCH_FL_SP ) && CL_GetMaxClients() != 1 )
|
||||
if( FBitSet( button->flags, TOUCH_FL_SP ) && cl.maxclients != 1 )
|
||||
return false; // skip singleplayer(load, save) buttons in multiplayer
|
||||
|
||||
if( FBitSet( button->flags, TOUCH_FL_MP ) && CL_GetMaxClients() == 1 )
|
||||
if( FBitSet( button->flags, TOUCH_FL_MP ) && cl.maxclients == 1 )
|
||||
return false; // skip multiplayer buttons in singleplayer
|
||||
|
||||
return true;
|
||||
@@ -2122,7 +2127,7 @@ void Touch_KeyEvent( int key, int down )
|
||||
float x, y;
|
||||
int finger, xi, yi;
|
||||
|
||||
if( !touch_emulate.value )
|
||||
if( !Touch_Emulated( ))
|
||||
{
|
||||
if( touch_enable.value )
|
||||
return;
|
||||
@@ -2163,8 +2168,7 @@ void Touch_KeyEvent( int key, int down )
|
||||
x = xi / SCR_W;
|
||||
y = yi / SCR_H;
|
||||
|
||||
Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n",
|
||||
event, x, y, x - lx, y - ly );
|
||||
// Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n", event, x, y, x - lx, y - ly );
|
||||
|
||||
IN_TouchEvent( event, finger, x, y, x - lx, y - ly );
|
||||
|
||||
@@ -2177,6 +2181,11 @@ qboolean Touch_WantVisibleCursor( void )
|
||||
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly;
|
||||
}
|
||||
|
||||
qboolean Touch_Emulated( void )
|
||||
{
|
||||
return touch_emulate.value || touch_in_menu.value;
|
||||
}
|
||||
|
||||
void Touch_Shutdown( void )
|
||||
{
|
||||
if( !touch.initialized )
|
||||
|
||||
@@ -17,6 +17,7 @@ GNU General Public License for more details.
|
||||
#include "input.h"
|
||||
#include "client.h"
|
||||
#include "vgui_draw.h"
|
||||
#include "cursor_type.h"
|
||||
|
||||
#if XASH_SDL
|
||||
#include <SDL.h>
|
||||
@@ -46,6 +47,8 @@ static CVAR_DEFINE_AUTO( cl_forwardspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL
|
||||
static CVAR_DEFINE_AUTO( cl_backspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
|
||||
static CVAR_DEFINE_AUTO( cl_sidespeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
|
||||
|
||||
static CVAR_DEFINE_AUTO( m_grab_debug, "0", FCVAR_PRIVILEGED, "show debug messages on mouse state change" );
|
||||
|
||||
/*
|
||||
================
|
||||
IN_CollectInputDevices
|
||||
@@ -115,6 +118,7 @@ static void IN_StartupMouse( void )
|
||||
Cvar_RegisterVariable( &m_yaw );
|
||||
Cvar_RegisterVariable( &look_filter );
|
||||
Cvar_RegisterVariable( &m_rawinput );
|
||||
Cvar_RegisterVariable( &m_grab_debug );
|
||||
|
||||
// You can use -nomouse argument to prevent using mouse from client
|
||||
// -noenginemouse will disable all mouse input
|
||||
@@ -123,11 +127,6 @@ static void IN_StartupMouse( void )
|
||||
in_mouseinitialized = true;
|
||||
}
|
||||
|
||||
void GAME_EXPORT IN_SetCursor( void *hCursor )
|
||||
{
|
||||
// stub
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_MouseSavePos
|
||||
@@ -206,68 +205,81 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bRawInput;
|
||||
|
||||
if( set && !s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_TRUE );
|
||||
#endif
|
||||
s_bRawInput = true;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: true\n", __func__ );
|
||||
}
|
||||
else if( !set && s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||
#endif
|
||||
s_bRawInput = false;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: false\n", __func__ );
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_SetMouseGrab( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bMouseGrab;
|
||||
|
||||
if( set && !s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
s_bMouseGrab = true;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: true\n", __func__ );
|
||||
}
|
||||
else if( !set && s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
|
||||
s_bMouseGrab = false;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: false\n", __func__ );
|
||||
}
|
||||
}
|
||||
|
||||
static void IN_CheckMouseState( qboolean active )
|
||||
{
|
||||
static qboolean s_bRawInput, s_bMouseGrab;
|
||||
qboolean use_raw_input, verbose;
|
||||
|
||||
#if XASH_WIN32
|
||||
qboolean useRawInput = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
#else
|
||||
qboolean useRawInput = true; // always use SDL code
|
||||
use_raw_input = true; // always use SDL code
|
||||
#endif
|
||||
|
||||
verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( m_ignore.value )
|
||||
return;
|
||||
active = false;
|
||||
|
||||
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
|
||||
{
|
||||
if( !s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_TRUE );
|
||||
#endif
|
||||
|
||||
// Con_Printf( "Enable relative mode\n" );
|
||||
s_bRawInput = true;
|
||||
}
|
||||
}
|
||||
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
|
||||
IN_SetRelativeMouseMode( true, verbose );
|
||||
else
|
||||
{
|
||||
if( s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||
#endif
|
||||
// Con_Printf( "Disable relative mode\n" );
|
||||
s_bRawInput = false;
|
||||
}
|
||||
}
|
||||
IN_SetRelativeMouseMode( false, verbose );
|
||||
|
||||
if( active && !host.mouse_visible && cls.state == ca_active )
|
||||
{
|
||||
if( !s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
// Con_Printf( "Enable grab\n" );
|
||||
s_bMouseGrab = true;
|
||||
}
|
||||
}
|
||||
IN_SetMouseGrab( true, verbose );
|
||||
else
|
||||
{
|
||||
if( s_bMouseGrab )
|
||||
{
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
|
||||
// Con_Printf( "Disable grab\n" );
|
||||
s_bMouseGrab = false;
|
||||
}
|
||||
}
|
||||
IN_SetMouseGrab( false, verbose );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -320,7 +332,7 @@ static void IN_MouseMove( void )
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
if( touch_emulate.value )
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
// touch emulation overrides all input
|
||||
Touch_KeyEvent( 0, 0 );
|
||||
@@ -351,7 +363,7 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
if( touch_emulate.value )
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ void IN_DeactivateMouse( void );
|
||||
void IN_MouseSavePos( void );
|
||||
void IN_MouseRestorePos( void );
|
||||
void IN_ToggleClientMouse( int newstate, int oldstate );
|
||||
void IN_SetCursor( void *hCursor );
|
||||
|
||||
uint IN_CollectInputDevices( void );
|
||||
void IN_LockInputDevices( qboolean lock );
|
||||
@@ -59,7 +58,6 @@ typedef enum
|
||||
} touchEventType;
|
||||
|
||||
extern convar_t touch_enable;
|
||||
extern convar_t touch_emulate;
|
||||
|
||||
void Touch_Draw( void );
|
||||
void Touch_SetClientOnly( byte state );
|
||||
@@ -75,6 +73,7 @@ void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
qboolean Touch_WantVisibleCursor( void );
|
||||
qboolean Touch_Emulated( void );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
|
||||
@@ -553,7 +553,7 @@ static void Key_AddKeyCommands( int key, const char *kb, qboolean down )
|
||||
}
|
||||
|
||||
buttonPtr = button;
|
||||
while(( kb[i] <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
|
||||
while((((byte)kb[i]) <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -749,10 +749,10 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
if( cls.key_dest == key_menu )
|
||||
{
|
||||
// only non printable keys passed
|
||||
if( !gameui.use_text_api )
|
||||
if( !gameui.use_extended_api )
|
||||
Key_EnableTextInput( true, false );
|
||||
//pass printable chars for old menus
|
||||
if( !gameui.use_text_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
|
||||
if( !gameui.use_extended_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
|
||||
{
|
||||
if( Key_IsDown( K_SHIFT ) )
|
||||
{
|
||||
@@ -840,7 +840,7 @@ void GAME_EXPORT Key_SetKeyDest( int key_dest )
|
||||
cls.key_dest = key_message;
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Key_SetKeyDest: wrong destination (%i)\n", key_dest );
|
||||
Host_Error( "%s: wrong destination (%i)\n", __func__, key_dest );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1055,18 +1055,16 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
break;
|
||||
}
|
||||
|
||||
if( !Q_stricmp( cl_charset.string, "utf-8" ) )
|
||||
ch = (unsigned char)osk.curbutton.val;
|
||||
else
|
||||
ch = Con_UtfProcessCharForce( (unsigned char)osk.curbutton.val );
|
||||
ch = (byte)osk.curbutton.val;
|
||||
|
||||
// do not pass UTF-8 sequence into the engine, convert it here
|
||||
if( !cls.accept_utf8 )
|
||||
ch = Con_UtfProcessCharForce( ch );
|
||||
|
||||
if( !ch )
|
||||
break;
|
||||
|
||||
Con_CharEvent( ch );
|
||||
if( cls.key_dest == key_menu )
|
||||
UI_CharEvent ( ch );
|
||||
|
||||
CL_CharEvent( ch );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1121,7 +1119,6 @@ static void OSK_EnableTextInput( qboolean enable, qboolean force )
|
||||
{
|
||||
osk.curlayout = 0;
|
||||
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ static void free_winding( winding_t *w )
|
||||
{
|
||||
// simple sentinel by Carmack
|
||||
if( *(unsigned *)w == 0xDEADC0DE )
|
||||
Host_Error( "free_winding: freed a freed winding\n" );
|
||||
Host_Error( "%s: freed a freed winding\n", __func__ );
|
||||
*(unsigned *)w = 0xDEADC0DE;
|
||||
free( w );
|
||||
}
|
||||
@@ -154,7 +154,7 @@ static winding_t *winding_for_plane( const mplane_t *p )
|
||||
vup[0] = 1;
|
||||
break;
|
||||
default:
|
||||
Host_Error( "BaseWindingForPlane: no axis found\n" );
|
||||
Host_Error( "%s: no axis found\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -685,6 +685,9 @@ void Mod_CreatePolygonsForHull( int hullnum )
|
||||
if( hullnum < 1 || hullnum > 3 )
|
||||
return;
|
||||
|
||||
if( !world.num_hull_models )
|
||||
Mod_InitDebugHulls( mod ); // FIXME: build hulls for separate bmodels (shells, medkits etc)
|
||||
|
||||
Con_Printf( "generating polygons for hull %u...\n", hullnum );
|
||||
start = Sys_DoubleTime();
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
struct ref_state_s ref;
|
||||
ref_globals_t refState;
|
||||
|
||||
CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
|
||||
static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" };
|
||||
|
||||
CVAR_DEFINE_AUTO( gl_vsync, "1", FCVAR_ARCHIVE, "enable vertical syncronization" );
|
||||
CVAR_DEFINE_AUTO( r_showtextures, "0", FCVAR_CHEAT, "show all uploaded textures" );
|
||||
CVAR_DEFINE_AUTO( r_adjust_fov, "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
|
||||
CVAR_DEFINE_AUTO( r_decals, "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
|
||||
@@ -49,13 +51,102 @@ void R_GetTextureParms( int *w, int *h, int texnum )
|
||||
if( h ) *h = REF_GET_PARM( PARM_TEX_HEIGHT, texnum );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_FreeImage
|
||||
static qboolean CheckSkybox( const char *name, char out[SKYBOX_MAX_SIDES][MAX_STRING] )
|
||||
{
|
||||
static const char *skybox_ext[3] = { "dds", "tga", "bmp" };
|
||||
static const char *skybox_delim[2] = { "", "_" }; // no space for HL style, underscore for Q1 style
|
||||
int i;
|
||||
|
||||
// search for skybox images
|
||||
for( i = 0; i < ARRAYSIZE( skybox_ext ); i++ )
|
||||
{
|
||||
int j;
|
||||
|
||||
for( j = 0; j < ARRAYSIZE( skybox_delim ); j++ )
|
||||
{
|
||||
int k, num_checked_sides = 0;
|
||||
|
||||
for( k = 0; k < SKYBOX_MAX_SIDES; k++ )
|
||||
{
|
||||
char sidename[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s%s%s.%s", name, skybox_delim[j], r_skyBoxSuffix[k], skybox_ext[i] );
|
||||
if( g_fsapi.FileExists( sidename, false ))
|
||||
{
|
||||
Q_strncpy( out[k], sidename, sizeof( out[k] ));
|
||||
num_checked_sides++;
|
||||
}
|
||||
}
|
||||
|
||||
if( num_checked_sides == SKYBOX_MAX_SIDES )
|
||||
return true; // image exists
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void R_SetupSky( const char *name )
|
||||
{
|
||||
string loadname;
|
||||
char sidenames[SKYBOX_MAX_SIDES][MAX_STRING];
|
||||
int skyboxTextures[SKYBOX_MAX_SIDES] = { 0 };
|
||||
int i, len;
|
||||
qboolean result;
|
||||
|
||||
if( !COM_CheckString( name ))
|
||||
{
|
||||
ref.dllFuncs.R_SetupSky( NULL ); // unload skybox
|
||||
return;
|
||||
}
|
||||
|
||||
Q_snprintf( loadname, sizeof( loadname ), "gfx/env/%s", name );
|
||||
COM_StripExtension( loadname );
|
||||
|
||||
// kill the underline suffix to find them manually later
|
||||
len = Q_strlen( loadname );
|
||||
|
||||
if( loadname[len - 1] == '_' )
|
||||
loadname[len - 1] = '\0';
|
||||
result = CheckSkybox( loadname, sidenames );
|
||||
|
||||
// to prevent infinite recursion if default skybox was missed
|
||||
if( !result && Q_stricmp( name, DEFAULT_SKYBOX_NAME ))
|
||||
{
|
||||
Con_Reportf( S_WARN "missed or incomplete skybox '%s'\n", name );
|
||||
R_SetupSky( DEFAULT_SKYBOX_NAME ); // force to default
|
||||
return;
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_SetupSky( NULL ); // unload skybox
|
||||
Con_DPrintf( "SKY: " );
|
||||
|
||||
for( i = 0; i < SKYBOX_MAX_SIDES; i++ )
|
||||
{
|
||||
skyboxTextures[i] = ref.dllFuncs.GL_LoadTexture( sidenames[i], NULL, 0, TF_CLAMP|TF_SKY );
|
||||
|
||||
if( !skyboxTextures[i] )
|
||||
break;
|
||||
|
||||
Con_DPrintf( "%s%s%s", name, r_skyBoxSuffix[i], i != 5 ? ", " : ". " );
|
||||
}
|
||||
|
||||
if( i == SKYBOX_MAX_SIDES )
|
||||
{
|
||||
SetBits( world.flags, FWORLD_CUSTOM_SKYBOX );
|
||||
Con_DPrintf( "done\n" );
|
||||
ref.dllFuncs.R_SetupSky( skyboxTextures );
|
||||
return; // loaded
|
||||
}
|
||||
|
||||
Con_DPrintf( "^2failed\n" );
|
||||
for( i = 0; i < SKYBOX_MAX_SIDES; i++ )
|
||||
{
|
||||
if( skyboxTextures[i] )
|
||||
ref.dllFuncs.GL_FreeTexture( skyboxTextures[i] );
|
||||
}
|
||||
}
|
||||
|
||||
Frees image by name
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT GL_FreeImage( const char *name )
|
||||
{
|
||||
int texnum;
|
||||
@@ -80,6 +171,22 @@ static intptr_t pfnEngineGetParm( int parm, int arg )
|
||||
return CL_RenderGetParm( parm, arg, false ); // prevent recursion
|
||||
}
|
||||
|
||||
static cvar_t *pfnCvar_Get( const char *szName, const char *szValue, int flags, const char *description )
|
||||
{
|
||||
return (cvar_t *)Cvar_Get( szName, szValue, flags | FCVAR_REFDLL, description );
|
||||
}
|
||||
|
||||
static void pfnCvar_RegisterVariable( convar_t *var )
|
||||
{
|
||||
SetBits( var->flags, FCVAR_REFDLL );
|
||||
Cvar_RegisterVariable( var );
|
||||
}
|
||||
|
||||
static void pfnCvar_FullSet( const char *var_name, const char *value, int flags )
|
||||
{
|
||||
Cvar_FullSet( var_name, value, flags | FCVAR_REFDLL );
|
||||
}
|
||||
|
||||
static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
|
||||
{
|
||||
clgame.dllFuncs.pfnStudioEvent( event, e );
|
||||
@@ -91,7 +198,7 @@ static model_t *pfnGetDefaultSprite( enum ref_defaultsprite_e spr )
|
||||
{
|
||||
case REF_DOT_SPRITE: return cl_sprite_dot;
|
||||
case REF_CHROME_SPRITE: return cl_sprite_shell;
|
||||
default: Host_Error( "GetDefaultSprite: unknown sprite %d\n", spr );
|
||||
default: Host_Error( "%s: unknown sprite %d\n", __func__, spr );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -104,7 +211,7 @@ static void *pfnMod_Extradata( int type, model_t *m )
|
||||
case mod_studio: return Mod_StudioExtradata( m );
|
||||
case mod_sprite: // fallthrough
|
||||
case mod_brush: return NULL;
|
||||
default: Host_Error( "Mod_Extradata: unknown type %d\n", type );
|
||||
default: Host_Error( "%s: unknown type %d\n", __func__, type );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -194,18 +301,18 @@ static qboolean R_Init_Video_( const int type )
|
||||
return R_Init_Video( type );
|
||||
}
|
||||
|
||||
static ref_api_t gEngfuncs =
|
||||
static const ref_api_t gEngfuncs =
|
||||
{
|
||||
pfnEngineGetParm,
|
||||
|
||||
(void*)Cvar_Get,
|
||||
pfnCvar_Get,
|
||||
(void*)Cvar_FindVarExt,
|
||||
Cvar_VariableValue,
|
||||
Cvar_VariableString,
|
||||
Cvar_SetValue,
|
||||
Cvar_Set,
|
||||
Cvar_RegisterVariable,
|
||||
Cvar_FullSet,
|
||||
pfnCvar_RegisterVariable,
|
||||
pfnCvar_FullSet,
|
||||
|
||||
Cmd_AddRefCommand,
|
||||
Cmd_RemoveCommand,
|
||||
@@ -340,7 +447,7 @@ static void R_UnloadProgs( void )
|
||||
|
||||
Cvar_FullSet( "host_refloaded", "0", FCVAR_READ_ONLY );
|
||||
|
||||
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
|
||||
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG | FCVAR_REFDLL );
|
||||
Cmd_Unlink( CMD_REFDLL );
|
||||
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
@@ -376,48 +483,41 @@ static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src
|
||||
|
||||
static qboolean R_LoadProgs( const char *name )
|
||||
{
|
||||
extern triangleapi_t gTriApi;
|
||||
static ref_api_t gpEngfuncs;
|
||||
REFAPI GetRefAPI; // single export
|
||||
|
||||
if( ref.hInstance ) R_UnloadProgs();
|
||||
|
||||
FS_AllowDirectPaths( true );
|
||||
if( !(ref.hInstance = COM_LoadLibrary( name, false, true ) ))
|
||||
if( !( ref.hInstance = COM_LoadLibrary( name, false, true )))
|
||||
{
|
||||
FS_AllowDirectPaths( false );
|
||||
Con_Reportf( "R_LoadProgs: can't load renderer library %s: %s\n", name, COM_GetLibraryError() );
|
||||
Con_Reportf( "%s: can't load renderer library %s: %s\n", __func__, name, COM_GetLibraryError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
FS_AllowDirectPaths( false );
|
||||
|
||||
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )) )
|
||||
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )))
|
||||
{
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
Con_Reportf( "R_LoadProgs: can't find GetRefAPI entry point in %s\n", name );
|
||||
ref.hInstance = NULL;
|
||||
Con_Reportf( "%s: can't find GetRefAPI entry point in %s\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||
gpEngfuncs = gEngfuncs;
|
||||
|
||||
if( GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ) != REF_API_VERSION )
|
||||
{
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
Con_Reportf( "R_LoadProgs: can't init renderer API: wrong version\n" );
|
||||
ref.hInstance = NULL;
|
||||
Con_Reportf( "%s: can't init renderer API: wrong version\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
refState.developer = host_developer.value;
|
||||
|
||||
if( !ref.dllFuncs.R_Init( ) )
|
||||
if( !ref.dllFuncs.R_Init( ))
|
||||
{
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
Con_Reportf( "R_LoadProgs: can't init renderer!\n" ); //, ref.dllFuncs.R_GetInitError() );
|
||||
ref.hInstance = NULL;
|
||||
Con_Reportf( "%s: can't init renderer!\n", __func__ ); //, ref.dllFuncs.R_GetInitError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -454,21 +554,19 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
|
||||
{
|
||||
if( !Q_strstr( opt, "." OS_LIB_EXT ))
|
||||
{
|
||||
const char *format;
|
||||
|
||||
#ifdef XASH_INTERNAL_GAMELIBS
|
||||
if( !Q_strcmp( opt, "ref_" ))
|
||||
format = "%s";
|
||||
else
|
||||
format = "ref_%s";
|
||||
#define FMT1 "%s"
|
||||
#define FMT2 "ref_%s"
|
||||
#else
|
||||
if( !Q_strcmp( opt, "ref_" ))
|
||||
format = OS_LIB_PREFIX "%s." OS_LIB_EXT;
|
||||
else
|
||||
format = OS_LIB_PREFIX "ref_%s." OS_LIB_EXT;
|
||||
#define FMT1 OS_LIB_PREFIX "%s." OS_LIB_EXT
|
||||
#define FMT2 OS_LIB_PREFIX "ref_%s." OS_LIB_EXT
|
||||
#endif
|
||||
Q_snprintf( dest, size, format, opt );
|
||||
|
||||
if( !Q_strncmp( opt, "ref_", 4 ))
|
||||
Q_snprintf( dest, size, FMT1, opt );
|
||||
else
|
||||
Q_snprintf( dest, size, FMT2, opt );
|
||||
#undef FMT1
|
||||
#undef FMT2
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -580,7 +678,8 @@ static void R_CollectRendererNames( void )
|
||||
qboolean R_Init( void )
|
||||
{
|
||||
qboolean success = false;
|
||||
string requested;
|
||||
string requested_cmdline;
|
||||
string requested_cvar;
|
||||
|
||||
Cvar_RegisterVariable( &gl_vsync );
|
||||
Cvar_RegisterVariable( &r_showtextures );
|
||||
@@ -630,15 +729,16 @@ qboolean R_Init( void )
|
||||
// 1. Command line `-ref` argument.
|
||||
// 2. `ref_dll` cvar.
|
||||
// 3. Detected renderers in `DEFAULT_RENDERERS` order.
|
||||
requested[0] = 0;
|
||||
requested_cmdline[0] = 0;
|
||||
requested_cvar[0] = 0;
|
||||
|
||||
if( !success && Sys_GetParmFromCmdLine( "-ref", requested ))
|
||||
success = R_LoadRenderer( requested );
|
||||
if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline ))
|
||||
success = R_LoadRenderer( requested_cmdline );
|
||||
|
||||
if( !success && COM_CheckString( r_refdll.string ))
|
||||
if( !success && COM_CheckString( r_refdll.string ) && Q_stricmp( requested_cmdline, r_refdll.string ))
|
||||
{
|
||||
Q_strncpy( requested, r_refdll.string, sizeof( requested ));
|
||||
success = R_LoadRenderer( requested );
|
||||
Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar ));
|
||||
success = R_LoadRenderer( requested_cvar );
|
||||
}
|
||||
|
||||
if( !success )
|
||||
@@ -648,7 +748,10 @@ qboolean R_Init( void )
|
||||
for( i = 0; i < ref.numRenderers && !success; i++ )
|
||||
{
|
||||
// skip renderer that was requested but failed to load
|
||||
if( !Q_strcmp( requested, ref.shortNames[i] ))
|
||||
if( !Q_strcmp( requested_cmdline, ref.shortNames[i] ))
|
||||
continue;
|
||||
|
||||
if( !Q_strcmp( requested_cvar, ref.shortNames[i] ))
|
||||
continue;
|
||||
|
||||
success = R_LoadRenderer( ref.shortNames[i] );
|
||||
@@ -657,7 +760,7 @@ qboolean R_Init( void )
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Host_Error( "Can't initialize any renderer. Check your video drivers!\n" );
|
||||
Sys_Error( "Can't initialize any renderer. Check your video drivers!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,19 +18,18 @@ GNU General Public License for more details.
|
||||
|
||||
#include "ref_api.h"
|
||||
|
||||
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
|
||||
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
|
||||
|
||||
struct ref_state_s
|
||||
{
|
||||
qboolean initialized;
|
||||
|
||||
HINSTANCE hInstance;
|
||||
HINSTANCE hInstance;
|
||||
qboolean initialized;
|
||||
int numRenderers;
|
||||
ref_interface_t dllFuncs;
|
||||
|
||||
// depends on build configuration
|
||||
int numRenderers;
|
||||
const char **shortNames;
|
||||
const char **readableNames;
|
||||
const char **shortNames;
|
||||
const char **readableNames;
|
||||
};
|
||||
|
||||
extern struct ref_state_s ref;
|
||||
@@ -45,14 +44,14 @@ void R_GetTextureParms( int *w, int *h, int texnum );
|
||||
|
||||
void GL_RenderFrame( const struct ref_viewpass_s *rvp );
|
||||
|
||||
void R_SetupSky( const char *name );
|
||||
|
||||
// common engine and renderer cvars
|
||||
extern convar_t r_decals;
|
||||
extern convar_t r_adjust_fov;
|
||||
extern convar_t r_decals;
|
||||
extern convar_t r_adjust_fov;
|
||||
extern convar_t gl_clear;
|
||||
|
||||
qboolean R_Init( void );
|
||||
void R_Shutdown( void );
|
||||
|
||||
extern triangleapi_t gTriApi;
|
||||
|
||||
#endif // REF_COMMON_H
|
||||
|
||||
@@ -154,7 +154,8 @@ static const sx_preset_t rgsxpre_hlalpha052[] =
|
||||
static const sx_preset_t *ptable = rgsxpre;
|
||||
|
||||
// cvars
|
||||
static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing" );
|
||||
static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing (deprecated)" );
|
||||
static CVAR_DEFINE_AUTO( room_off, "0", FCVAR_ARCHIVE, "disable DSP processing (GoldSrc compatible cvar)" );
|
||||
static CVAR_DEFINE_AUTO( dsp_coeff_table, "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" );
|
||||
static CVAR_DEFINE_AUTO( room_type, "0", 0, "current room type preset" );
|
||||
|
||||
@@ -232,6 +233,7 @@ void SX_Init( void )
|
||||
sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k );
|
||||
|
||||
Cvar_RegisterVariable( &dsp_off );
|
||||
Cvar_RegisterVariable( &room_off );
|
||||
Cvar_RegisterVariable( &dsp_coeff_table );
|
||||
|
||||
Cvar_RegisterVariable( &roomwater_type );
|
||||
@@ -809,7 +811,7 @@ DSP_Process
|
||||
*/
|
||||
void DSP_Process( portable_samplepair_t *pbfront, int sampleCount )
|
||||
{
|
||||
if( dsp_off.value || !sampleCount )
|
||||
if( dsp_off.value || room_off.value || !sampleCount )
|
||||
return;
|
||||
|
||||
// preset is already installed by CheckNewDspPresets
|
||||
@@ -843,7 +845,7 @@ CheckNewDspPresets
|
||||
*/
|
||||
void CheckNewDspPresets( void )
|
||||
{
|
||||
if( dsp_off.value != 0.0f )
|
||||
if( dsp_off.value || room_off.value )
|
||||
return;
|
||||
|
||||
if( FBitSet( dsp_coeff_table.flags, FCVAR_CHANGED ))
|
||||
|
||||
@@ -52,8 +52,11 @@ void S_SoundList_f( void )
|
||||
{
|
||||
totalSize += sc->size;
|
||||
|
||||
if( sc->loopStart >= 0 ) Con_Printf( "L" );
|
||||
else Con_Printf( " " );
|
||||
if( FBitSet( sc->flags, SOUND_LOOPED ))
|
||||
Con_Printf( "L" );
|
||||
else
|
||||
Con_Printf( " " );
|
||||
|
||||
if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ))
|
||||
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
|
||||
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
|
||||
@@ -110,7 +113,7 @@ static wavdata_t *S_CreateDefaultSound( void )
|
||||
|
||||
sc->width = 2;
|
||||
sc->channels = 1;
|
||||
sc->loopStart = -1;
|
||||
sc->loopStart = 0;
|
||||
sc->rate = SOUND_DMA_SPEED;
|
||||
sc->samples = SOUND_DMA_SPEED;
|
||||
sc->size = sc->samples * sc->width * sc->channels;
|
||||
@@ -141,8 +144,8 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
|
||||
if( Q_stricmp( sfx->name, "*default" ))
|
||||
{
|
||||
// load it from disk
|
||||
if( s_warn_late_precache.value > 0 && CL_Active() )
|
||||
Con_Printf( S_WARN "S_LoadSound: late precache of %s\n", sfx->name );
|
||||
if( s_warn_late_precache.value > 0 && cls.state == ca_active )
|
||||
Con_Printf( S_WARN "%s: late precache of %s\n", __func__, sfx->name );
|
||||
|
||||
if( sfx->name[0] == '*' )
|
||||
sc = FS_LoadSound( sfx->name + 1, NULL, 0 );
|
||||
@@ -152,11 +155,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
|
||||
if( !sc ) sc = S_CreateDefaultSound();
|
||||
|
||||
if( sc->rate < SOUND_11k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
|
||||
Sound_Process( &sc, SOUND_11k, sc->width, sc->channels, SOUND_RESAMPLE );
|
||||
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
|
||||
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
|
||||
Sound_Process( &sc, SOUND_22k, sc->width, sc->channels, SOUND_RESAMPLE );
|
||||
else if( sc->rate > SOUND_22k && sc->rate < SOUND_44k ) // some bad sounds
|
||||
Sound_Process( &sc, SOUND_44k, sc->width, sc->channels, SOUND_RESAMPLE );
|
||||
|
||||
sfx->cache = sc;
|
||||
|
||||
@@ -218,7 +221,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
|
||||
sfx = &s_knownSfx[i];
|
||||
memset( sfx, 0, sizeof( *sfx ));
|
||||
if( pfInCache ) *pfInCache = false;
|
||||
Q_strncpy( sfx->name, name, MAX_STRING );
|
||||
Q_strncpy( sfx->name, name, sizeof( sfx->name ));
|
||||
sfx->servercount = cl.servercount;
|
||||
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
|
||||
|
||||
@@ -377,7 +380,7 @@ S_InitSounds
|
||||
void S_InitSounds( void )
|
||||
{
|
||||
// create unused 0-entry
|
||||
Q_strncpy( s_knownSfx->name, "*default", MAX_QPATH );
|
||||
Q_strncpy( s_knownSfx->name, "*default", sizeof( s_knownSfx->name ));
|
||||
s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH );
|
||||
s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue];
|
||||
s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx;
|
||||
|
||||
@@ -43,7 +43,7 @@ CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "apply interpo
|
||||
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" );
|
||||
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" );
|
||||
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" );
|
||||
static CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
|
||||
CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
|
||||
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
|
||||
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" );
|
||||
CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" );
|
||||
@@ -328,7 +328,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
|
||||
// don't restart looping sounds for the same entity
|
||||
wavdata_t *sc = channels[first_to_die].sfx->cache;
|
||||
|
||||
if( sc && sc->loopStart != -1 )
|
||||
if( sc && FBitSet( sc->flags, SOUND_LOOPED ))
|
||||
{
|
||||
channel_t *ch = &channels[first_to_die];
|
||||
|
||||
@@ -382,7 +382,7 @@ channel_t *SND_PickStaticChannel( const vec3_t pos, sfx_t *sfx )
|
||||
// no empty slots, alloc a new static sound channel
|
||||
if( total_channels == MAX_CHANNELS )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "S_PickStaticChannel: no free channels\n" );
|
||||
Con_DPrintf( S_ERROR "%s: no free channels\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ static void SND_Spatialize( channel_t *ch )
|
||||
|
||||
pSource = ch->sfx->cache;
|
||||
|
||||
if( ch->use_loop && pSource && pSource->loopStart != -1 )
|
||||
if( ch->use_loop && pSource && FBitSet( pSource->flags, SOUND_LOOPED ))
|
||||
looping = true;
|
||||
|
||||
if( !ch->staticsound )
|
||||
@@ -524,8 +524,11 @@ static void SND_Spatialize( channel_t *ch )
|
||||
dist = VectorNormalizeLength( source_vec );
|
||||
dot = DotProduct( s_listener.right, source_vec );
|
||||
|
||||
// don't pan sounds with no attenuation
|
||||
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
|
||||
if( !FBitSet( host.bugcomp, BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE ))
|
||||
{
|
||||
// don't pan sounds with no attenuation
|
||||
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
|
||||
}
|
||||
|
||||
// fill out channel volumes for single location
|
||||
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult );
|
||||
@@ -641,7 +644,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
|
||||
if( !target_chan->leftvol && !target_chan->rightvol )
|
||||
{
|
||||
// looping sounds don't use this optimization because they should stick around until they're killed.
|
||||
if( !sfx->cache || sfx->cache->loopStart == -1 )
|
||||
if( !sfx->cache || !FBitSet( sfx->cache->flags, SOUND_LOOPED ))
|
||||
{
|
||||
// if this is a streaming sound, play the whole thing.
|
||||
if( chan != CHAN_STREAM )
|
||||
@@ -893,7 +896,7 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
|
||||
VectorCopy( channels[i].origin, pout->origin );
|
||||
pout->volume = (float)channels[i].master_vol / 255.0f;
|
||||
pout->attenuation = channels[i].dist_mult * SND_CLIP_DISTANCE;
|
||||
pout->looping = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
|
||||
pout->looping = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
|
||||
pout->pitch = channels[i].basePitch;
|
||||
pout->channel = channels[i].entchannel;
|
||||
pout->wordIndex = channels[i].wordIndex;
|
||||
@@ -928,7 +931,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
|
||||
if( !channels[i].sfx || !channels[i].sfx->name[0] || !Q_stricmp( channels[i].sfx->name, "*default" ))
|
||||
continue; // don't serialize default sounds
|
||||
|
||||
looped = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
|
||||
looped = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
|
||||
|
||||
if( channels[i].entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible())
|
||||
continue; // never serialize static looped sounds. It will be restoring in game code
|
||||
@@ -1092,7 +1095,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
|
||||
if( !raw_channels[best] )
|
||||
{
|
||||
raw_samples = MAX_RAW_SAMPLES;
|
||||
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
|
||||
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
|
||||
}
|
||||
|
||||
ch = raw_channels[best];
|
||||
@@ -1599,11 +1602,10 @@ void SND_UpdateSound( void )
|
||||
// release raw-channels that no longer used more than 10 secs
|
||||
S_FreeIdleRawChannels();
|
||||
|
||||
VectorCopy( cl.simvel, s_listener.velocity );
|
||||
s_listener.frametime = (cl.time - cl.oldtime);
|
||||
s_listener.waterlevel = cl.local.waterlevel;
|
||||
s_listener.active = CL_IsInGame();
|
||||
s_listener.inmenu = CL_IsInMenu();
|
||||
s_listener.inmenu = cls.key_dest == key_menu;
|
||||
s_listener.paused = cl.paused;
|
||||
|
||||
// update general area ambient sound sources
|
||||
|
||||
@@ -17,30 +17,56 @@ GNU General Public License for more details.
|
||||
#include "sound.h"
|
||||
#include "client.h"
|
||||
|
||||
#define IPAINTBUFFER 0
|
||||
#define IROOMBUFFER 1
|
||||
#define ISTREAMBUFFER 2
|
||||
enum
|
||||
{
|
||||
IPAINTBUFFER = 0,
|
||||
IROOMBUFFER,
|
||||
ISTREAMBUFFER,
|
||||
CPAINTBUFFERS,
|
||||
};
|
||||
|
||||
#define FILTERTYPE_NONE 0
|
||||
#define FILTERTYPE_LINEAR 1
|
||||
#define FILTERTYPE_CUBIC 2
|
||||
enum
|
||||
{
|
||||
FILTERTYPE_NONE = 0,
|
||||
FILTERTYPE_LINEAR,
|
||||
FILTERTYPE_CUBIC,
|
||||
};
|
||||
|
||||
#define CCHANVOLUMES 2
|
||||
|
||||
#define SND_SCALE_BITS 7
|
||||
#define SND_SCALE_SHIFT (8 - SND_SCALE_BITS)
|
||||
#define SND_SCALE_LEVELS (1 << SND_SCALE_BITS)
|
||||
#define SND_SCALE_BITS 7
|
||||
#define SND_SCALE_SHIFT ( 8 - SND_SCALE_BITS )
|
||||
#define SND_SCALE_LEVELS ( 1 << SND_SCALE_BITS )
|
||||
|
||||
portable_samplepair_t *g_curpaintbuffer;
|
||||
portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
|
||||
portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
|
||||
portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
|
||||
portable_samplepair_t facingbuffer[(PAINTBUFFER_SIZE+1)];
|
||||
portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
|
||||
paintbuffer_t paintbuffers[CPAINTBUFFERS];
|
||||
// sound mixing buffer
|
||||
#define CPAINTFILTERMEM 3
|
||||
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
|
||||
|
||||
int snd_scaletable[SND_SCALE_LEVELS][256];
|
||||
// fixed point stuff for real-time resampling
|
||||
#define FIX_BITS 28
|
||||
#define FIX_SCALE ( 1 << FIX_BITS )
|
||||
#define FIX_MASK (( 1 << FIX_BITS ) - 1 )
|
||||
#define FIX_FLOAT( a ) ((int)(( a ) * FIX_SCALE ))
|
||||
#define FIX( a ) (((int)( a )) << FIX_BITS )
|
||||
#define FIX_INTPART( a ) (((int)( a )) >> FIX_BITS )
|
||||
#define FIX_FRACPART( a ) (( a ) & FIX_MASK )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean factive; // if true, mix to this paintbuffer using flags
|
||||
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
|
||||
int ifilter; // current filter memory buffer to use for upsampling pass
|
||||
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
|
||||
} paintbuffer_t;
|
||||
|
||||
static portable_samplepair_t *g_curpaintbuffer;
|
||||
static portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
|
||||
static portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
|
||||
static portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
|
||||
static portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
|
||||
static paintbuffer_t paintbuffers[CPAINTBUFFERS];
|
||||
|
||||
static int snd_scaletable[SND_SCALE_LEVELS][256];
|
||||
void S_InitScaletable( void )
|
||||
{
|
||||
int i, j;
|
||||
@@ -67,7 +93,7 @@ static void S_TransferPaintBuffer( int endtime )
|
||||
dword *pbuf;
|
||||
|
||||
pbuf = (dword *)dma.buffer;
|
||||
snd_p = (int *)PAINTBUFFER;
|
||||
snd_p = (int *)g_curpaintbuffer;
|
||||
lpaintedtime = paintedtime;
|
||||
sampleMask = ((dma.samples >> 1) - 1);
|
||||
|
||||
@@ -111,20 +137,20 @@ static void S_TransferPaintBuffer( int endtime )
|
||||
//===============================================================================
|
||||
// Activate a paintbuffer. All active paintbuffers are mixed in parallel within
|
||||
// MIX_MixChannelsToPaintbuffer, according to flags
|
||||
_inline void MIX_ActivatePaintbuffer( int ipaintbuffer )
|
||||
static void MIX_ActivatePaintbuffer( int ipaintbuffer )
|
||||
{
|
||||
Assert( ipaintbuffer < CPAINTBUFFERS );
|
||||
paintbuffers[ipaintbuffer].factive = true;
|
||||
}
|
||||
|
||||
_inline void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
|
||||
static void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
|
||||
{
|
||||
Assert( ipaintbuffer < CPAINTBUFFERS );
|
||||
g_curpaintbuffer = paintbuffers[ipaintbuffer].pbuf;
|
||||
Assert( g_curpaintbuffer != NULL );
|
||||
}
|
||||
|
||||
_inline int MIX_GetCurrentPaintbufferIndex( void )
|
||||
static int MIX_GetCurrentPaintbufferIndex( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -136,7 +162,7 @@ _inline int MIX_GetCurrentPaintbufferIndex( void )
|
||||
return 0;
|
||||
}
|
||||
|
||||
_inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
|
||||
static paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
|
||||
{
|
||||
int ipaint = MIX_GetCurrentPaintbufferIndex();
|
||||
|
||||
@@ -145,7 +171,7 @@ _inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
|
||||
}
|
||||
|
||||
// Don't mix into any paintbuffers
|
||||
_inline void MIX_DeactivateAllPaintbuffers( void )
|
||||
static void MIX_DeactivateAllPaintbuffers( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -154,7 +180,7 @@ _inline void MIX_DeactivateAllPaintbuffers( void )
|
||||
}
|
||||
|
||||
// set upsampling filter indexes back to 0
|
||||
_inline void MIX_ResetPaintbufferFilterCounters( void )
|
||||
static void MIX_ResetPaintbufferFilterCounters( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -163,13 +189,13 @@ _inline void MIX_ResetPaintbufferFilterCounters( void )
|
||||
}
|
||||
|
||||
// return pointer to front paintbuffer pbuf, given index
|
||||
_inline portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
|
||||
static portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
|
||||
{
|
||||
Assert( ipaintbuffer < CPAINTBUFFERS );
|
||||
return paintbuffers[ipaintbuffer].pbuf;
|
||||
}
|
||||
|
||||
_inline paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
|
||||
static paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
|
||||
{
|
||||
Assert( ipaint < CPAINTBUFFERS );
|
||||
return &paintbuffers[ipaint];
|
||||
@@ -523,6 +549,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
|
||||
wavdata_t *pSource;
|
||||
int i, sampleCount;
|
||||
qboolean bZeroVolume;
|
||||
qboolean local = Host_IsLocalGame();
|
||||
|
||||
// mix each channel into paintbuffer
|
||||
ch = channels;
|
||||
@@ -549,7 +576,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
|
||||
{
|
||||
// play, playvol
|
||||
}
|
||||
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound )
|
||||
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound && local )
|
||||
{
|
||||
// play only local sounds, keep pause for other
|
||||
continue;
|
||||
@@ -567,6 +594,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
|
||||
|
||||
// Don't mix sound data for sounds with zero volume. If it's a non-looping sound,
|
||||
// just remove the sound when its volume goes to zero.
|
||||
|
||||
bZeroVolume = !ch->leftvol && !ch->rightvol;
|
||||
|
||||
if( !bZeroVolume )
|
||||
@@ -576,7 +604,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
|
||||
bZeroVolume = true;
|
||||
}
|
||||
|
||||
if( !pSource || ( bZeroVolume && pSource->loopStart == -1 ))
|
||||
if( !pSource || ( bZeroVolume && !FBitSet( pSource->flags, SOUND_LOOPED )))
|
||||
{
|
||||
if( !pSource )
|
||||
{
|
||||
@@ -629,7 +657,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
|
||||
}
|
||||
|
||||
// pass in index -1...count+2, return pointer to source sample in either paintbuffer or delay buffer
|
||||
_inline portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
|
||||
static portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
|
||||
{
|
||||
// The delay buffer is assumed to precede the paintbuffer by 6 duplicated samples
|
||||
if( i == -1 ) return (&(pfiltermem[0]));
|
||||
@@ -838,6 +866,14 @@ static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, flo
|
||||
pbuf2 = paintbuffers[ibuf2].pbuf;
|
||||
pbuf3 = paintbuffers[ibuf3].pbuf;
|
||||
|
||||
if( !gain )
|
||||
{
|
||||
// do not mix buf2 into buf3, just copy
|
||||
if( pbuf1 != pbuf3 )
|
||||
memcpy( pbuf3, pbuf1, sizeof( *pbuf1 ) * count );
|
||||
return;
|
||||
}
|
||||
|
||||
// destination buffer stereo - average n chans down to stereo
|
||||
|
||||
// destination 2ch:
|
||||
@@ -887,7 +923,7 @@ static void S_MixUpsample( int sampleCount, int filtertype )
|
||||
static void MIX_MixRawSamplesBuffer( int end )
|
||||
{
|
||||
portable_samplepair_t *pbuf, *roombuf, *streambuf;
|
||||
uint i, j, stop;
|
||||
uint i, j, stop;
|
||||
|
||||
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
|
||||
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
|
||||
@@ -920,7 +956,11 @@ static void MIX_MixRawSamplesBuffer( int end )
|
||||
}
|
||||
|
||||
if( ch->entnum > 0 )
|
||||
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
|
||||
{
|
||||
int pos = paintedtime & ( ch->max_samples - 1 );
|
||||
|
||||
SND_MoveMouthRaw( ch, &ch->rawsamples[pos], bound( 0, ch->max_samples - pos, stop - paintedtime ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ float S_GetMusicVolume( void )
|
||||
{
|
||||
float scale = 1.0f;
|
||||
|
||||
if( host.status == HOST_NOFOCUS && snd_mute_losefocus.value != 0.0f )
|
||||
{
|
||||
// we return zero volume to keep sounds running
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if( !s_listener.inmenu && musicfade.percent != 0 )
|
||||
{
|
||||
scale = bound( 0.0f, musicfade.percent / 100.0f, 1.0f );
|
||||
@@ -142,7 +148,7 @@ S_StreamGetCurrentState
|
||||
save\restore code
|
||||
=================
|
||||
*/
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position )
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position )
|
||||
{
|
||||
if( !s_bgTrack.stream )
|
||||
return false; // not active
|
||||
@@ -150,15 +156,15 @@ qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *posi
|
||||
if( currentTrack )
|
||||
{
|
||||
if( s_bgTrack.current[0] )
|
||||
Q_strncpy( currentTrack, s_bgTrack.current, MAX_STRING );
|
||||
else Q_strncpy( currentTrack, "*", MAX_STRING ); // no track
|
||||
Q_strncpy( currentTrack, s_bgTrack.current, currentTrackSize );
|
||||
else Q_strncpy( currentTrack, "*", currentTrackSize ); // no track
|
||||
}
|
||||
|
||||
if( loopTrack )
|
||||
{
|
||||
if( s_bgTrack.loopName[0] )
|
||||
Q_strncpy( loopTrack, s_bgTrack.loopName, MAX_STRING );
|
||||
else Q_strncpy( loopTrack, "*", MAX_STRING ); // no track
|
||||
Q_strncpy( loopTrack, s_bgTrack.loopName, loopTrackSize );
|
||||
else Q_strncpy( loopTrack, "*", loopTrackSize ); // no track
|
||||
}
|
||||
|
||||
if( position )
|
||||
|
||||
@@ -27,7 +27,7 @@ int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean us
|
||||
// convert to a position within the loop
|
||||
// At the end of the loop, we return a short buffer, and subsequent call
|
||||
// will loop back and get the rest of the buffer
|
||||
if( pSource->loopStart >= 0 && samplePosition >= pSource->samples && use_loop )
|
||||
if( FBitSet( pSource->flags, SOUND_LOOPED ) && samplePosition >= pSource->samples && use_loop )
|
||||
{
|
||||
// size of loop
|
||||
int loopSize = pSource->samples - pSource->loopStart;
|
||||
|
||||
@@ -96,7 +96,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
|
||||
|
||||
if( width == 1 )
|
||||
{
|
||||
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * end];
|
||||
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * ( end - 1 )];
|
||||
|
||||
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
|
||||
{
|
||||
@@ -109,7 +109,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
|
||||
}
|
||||
else if( width == 2 )
|
||||
{
|
||||
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * end];
|
||||
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * ( end - 1 )];
|
||||
|
||||
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
|
||||
{
|
||||
@@ -261,7 +261,7 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
|
||||
|
||||
if( len > nsize )
|
||||
{
|
||||
Con_Printf( "VOX_GetDirectory: invalid directory in: %s\n", psz );
|
||||
Con_Printf( "%s: invalid directory in: %s\n", __func__, psz );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -467,7 +467,7 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
|
||||
|
||||
if( !psz )
|
||||
{
|
||||
Con_Printf( "VOX_LoadSound: no sentence named %s\n", pszin );
|
||||
Con_Printf( "%s: no sentence named %s\n", __func__, pszin );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -475,13 +475,13 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
|
||||
|
||||
if( !psz )
|
||||
{
|
||||
Con_Printf( "VOX_LoadSound: failed getting directory for %s\n", pszin );
|
||||
Con_Printf( "%s: failed getting directory for %s\n", __func__, pszin );
|
||||
return;
|
||||
}
|
||||
|
||||
if( Q_strlen( psz ) >= sizeof( buffer ) )
|
||||
{
|
||||
Con_Printf( "VOX_LoadSound: sentence is too long %s", psz );
|
||||
Con_Printf( "%s: sentence is too long %s", __func__, psz );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,208 +20,181 @@ extern poolhandle_t sndpool;
|
||||
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
// sound engine rate defines
|
||||
#define SOUND_DMA_SPEED 44100 // hardware playback rate
|
||||
#define SOUND_11k 11025 // 11khz sample rate
|
||||
#define SOUND_16k 16000 // 16khz sample rate
|
||||
#define SOUND_22k 22050 // 22khz sample rate
|
||||
#define SOUND_32k 32000 // 32khz sample rate
|
||||
#define SOUND_44k 44100 // 44khz sample rate
|
||||
#define DMA_MSEC_PER_SAMPLE ((float)(1000.0 / SOUND_DMA_SPEED))
|
||||
#define XASH_AUDIO_CD_QUALITY 1 // some platforms might need this
|
||||
|
||||
// fixed point stuff for real-time resampling
|
||||
#define FIX_BITS 28
|
||||
#define FIX_SCALE (1 << FIX_BITS)
|
||||
#define FIX_MASK ((1 << FIX_BITS)-1)
|
||||
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE))
|
||||
#define FIX(a) (((int)(a)) << FIX_BITS)
|
||||
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS)
|
||||
#define FIX_FRACTION(a,b) (FIX(a)/(b))
|
||||
#define FIX_FRACPART(a) ((a) & FIX_MASK)
|
||||
// sound engine rate defines
|
||||
#if XASH_AUDIO_CD_QUALITY
|
||||
#define SOUND_11k 11025 // 11khz sample rate
|
||||
#define SOUND_22k 22050 // 22khz sample rate
|
||||
#define SOUND_44k 44100 // 44khz sample rate
|
||||
#else // XASH_AUDIO_CD_QUALITY
|
||||
#define SOUND_11k 12000 // 11khz sample rate
|
||||
#define SOUND_22k 24000 // 22khz sample rate
|
||||
#define SOUND_44k 48000 // 44khz sample rate
|
||||
#endif // XASH_AUDIO_CD_QUALITY
|
||||
|
||||
#define SOUND_DMA_SPEED SOUND_44k // hardware playback rate
|
||||
|
||||
// NOTE: clipped sound at 32760 to avoid overload
|
||||
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
|
||||
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
|
||||
|
||||
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
|
||||
#define PAINTBUFFER (g_curpaintbuffer)
|
||||
#define CPAINTBUFFERS 3
|
||||
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
|
||||
|
||||
// sound mixing buffer
|
||||
#define CPAINTFILTERMEM 3
|
||||
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
|
||||
|
||||
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
|
||||
#define S_RAW_SOUND_BACKGROUNDTRACK -2
|
||||
#define S_RAW_SOUND_SOUNDTRACK -1
|
||||
#define S_RAW_SAMPLES_PRECISION_BITS 14
|
||||
|
||||
#define CIN_FRAMETIME (1.0f / 30.0f)
|
||||
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
|
||||
#define S_RAW_SOUND_BACKGROUNDTRACK -2
|
||||
#define S_RAW_SOUND_SOUNDTRACK -1
|
||||
#define S_RAW_SAMPLES_PRECISION_BITS 14
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int left;
|
||||
int right;
|
||||
int left;
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean factive; // if true, mix to this paintbuffer using flags
|
||||
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
|
||||
int ifilter; // current filter memory buffer to use for upsampling pass
|
||||
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
|
||||
} paintbuffer_t;
|
||||
|
||||
typedef struct sfx_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
wavdata_t *cache;
|
||||
char name[MAX_QPATH];
|
||||
wavdata_t *cache;
|
||||
|
||||
int servercount;
|
||||
uint hashValue;
|
||||
struct sfx_s *hashNext;
|
||||
int servercount;
|
||||
uint hashValue;
|
||||
struct sfx_s *hashNext;
|
||||
} sfx_t;
|
||||
|
||||
extern portable_samplepair_t paintbuffer[];
|
||||
extern portable_samplepair_t roombuffer[];
|
||||
extern portable_samplepair_t temppaintbuffer[];
|
||||
extern portable_samplepair_t *g_curpaintbuffer;
|
||||
extern paintbuffer_t paintbuffers[];
|
||||
|
||||
// structure used for fading in and out client sound volume.
|
||||
typedef struct
|
||||
{
|
||||
float initial_percent;
|
||||
float percent; // how far to adjust client's volume down by.
|
||||
float starttime; // GetHostTime() when we started adjusting volume
|
||||
float fadeouttime; // # of seconds to get to faded out state
|
||||
float holdtime; // # of seconds to hold
|
||||
float fadeintime; // # of seconds to restore
|
||||
float initial_percent;
|
||||
float percent; // how far to adjust client's volume down by.
|
||||
float starttime; // GetHostTime() when we started adjusting volume
|
||||
float fadeouttime; // # of seconds to get to faded out state
|
||||
float holdtime; // # of seconds to hold
|
||||
float fadeintime; // # of seconds to restore
|
||||
} soundfade_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float percent;
|
||||
float percent;
|
||||
} musicfade_t;
|
||||
|
||||
typedef struct snd_format_s
|
||||
{
|
||||
unsigned int speed;
|
||||
unsigned int width;
|
||||
unsigned int channels;
|
||||
uint speed;
|
||||
byte width;
|
||||
byte channels;
|
||||
} snd_format_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
snd_format_t format;
|
||||
int samples; // mono samples in buffer
|
||||
int samplepos; // in mono samples
|
||||
byte *buffer;
|
||||
qboolean initialized; // sound engine is active
|
||||
const char *backendName;
|
||||
snd_format_t format;
|
||||
int samples; // mono samples in buffer
|
||||
int samplepos; // in mono samples
|
||||
qboolean initialized; // sound engine is active
|
||||
byte *buffer;
|
||||
const char *backendName;
|
||||
} dma_t;
|
||||
|
||||
#include "vox.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double sample;
|
||||
|
||||
wavdata_t *pData;
|
||||
double forcedEndSample;
|
||||
qboolean finished;
|
||||
double sample;
|
||||
wavdata_t *pData;
|
||||
double forcedEndSample;
|
||||
qboolean finished;
|
||||
} mixer_t;
|
||||
|
||||
typedef struct rawchan_s
|
||||
{
|
||||
int entnum;
|
||||
int master_vol;
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
volatile uint s_rawend;
|
||||
wavdata_t sound_info; // advance play position
|
||||
float oldtime; // catch time jumps
|
||||
size_t max_samples; // buffer length
|
||||
portable_samplepair_t rawsamples[1]; // variable sized
|
||||
int entnum;
|
||||
int master_vol;
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
volatile uint s_rawend;
|
||||
float oldtime; // catch time jumps
|
||||
wavdata_t sound_info; // advance play position
|
||||
size_t max_samples; // buffer length
|
||||
portable_samplepair_t rawsamples[]; // variable sized
|
||||
} rawchan_t;
|
||||
|
||||
typedef struct channel_s
|
||||
{
|
||||
char name[16]; // keept sentence name
|
||||
sfx_t *sfx; // sfx number
|
||||
char name[16]; // keep sentence name
|
||||
sfx_t *sfx; // sfx number
|
||||
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
|
||||
int entnum; // entity soundsource
|
||||
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
int master_vol; // 0-255 master volume
|
||||
qboolean isSentence; // bit who indicated sentence
|
||||
int basePitch; // base pitch percent (100% is normal pitch playback)
|
||||
float pitch; // real-time pitch after any modulation or shift by dynamic data
|
||||
qboolean use_loop; // don't loop default and local sounds
|
||||
qboolean staticsound; // use origin instead of fetching entnum's origin
|
||||
qboolean localsound; // it's a local menu sound (not looped, not paused)
|
||||
mixer_t pMixer;
|
||||
int entnum; // entity soundsource
|
||||
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
int master_vol; // 0-255 master volume
|
||||
int basePitch; // base pitch percent (100% is normal pitch playback)
|
||||
float pitch; // real-time pitch after any modulation or shift by dynamic data
|
||||
qboolean use_loop; // don't loop default and local sounds
|
||||
qboolean staticsound; // use origin instead of fetching entnum's origin
|
||||
qboolean localsound; // it's a local menu sound (not looped, not paused)
|
||||
mixer_t pMixer;
|
||||
|
||||
// sentence mixer
|
||||
int wordIndex;
|
||||
mixer_t *currentWord; // NULL if sentence is finished
|
||||
voxword_t words[CVOXWORDMAX];
|
||||
qboolean isSentence; // bit indicating sentence
|
||||
int wordIndex;
|
||||
mixer_t *currentWord; // NULL if sentence is finished
|
||||
voxword_t words[CVOXWORDMAX];
|
||||
} channel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin; // simorg + view_ofs
|
||||
vec3_t velocity;
|
||||
vec3_t forward;
|
||||
vec3_t right;
|
||||
vec3_t up;
|
||||
vec3_t origin; // simorg + view_ofs
|
||||
vec3_t forward;
|
||||
vec3_t right;
|
||||
vec3_t up;
|
||||
|
||||
int entnum;
|
||||
int waterlevel;
|
||||
float frametime; // used for sound fade
|
||||
qboolean active;
|
||||
qboolean inmenu; // listener in-menu ?
|
||||
qboolean paused;
|
||||
qboolean streaming; // playing AVI-file
|
||||
qboolean stream_paused; // pause only background track
|
||||
int entnum;
|
||||
int waterlevel;
|
||||
float frametime; // used for sound fade
|
||||
qboolean active;
|
||||
qboolean inmenu; // listener in-menu ?
|
||||
qboolean paused;
|
||||
qboolean streaming; // playing AVI-file
|
||||
qboolean stream_paused; // pause only background track
|
||||
} listener_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string current; // a currently playing track
|
||||
string loopName; // may be empty
|
||||
stream_t *stream;
|
||||
int source; // may be game, menu, etc
|
||||
string current; // a currently playing track
|
||||
string loopName; // may be empty
|
||||
stream_t *stream;
|
||||
int source; // may be game, menu, etc
|
||||
} bg_track_t;
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 48
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 48
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
extern qboolean snd_ambient;
|
||||
extern channel_t channels[MAX_CHANNELS];
|
||||
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
|
||||
extern int total_channels;
|
||||
extern int paintedtime;
|
||||
extern int soundtime;
|
||||
extern listener_t s_listener;
|
||||
extern int idsp_room;
|
||||
extern dma_t dma;
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
extern qboolean snd_ambient;
|
||||
extern channel_t channels[MAX_CHANNELS];
|
||||
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
|
||||
extern int total_channels;
|
||||
extern int paintedtime;
|
||||
extern int soundtime;
|
||||
extern listener_t s_listener;
|
||||
extern int idsp_room;
|
||||
extern dma_t dma;
|
||||
|
||||
extern convar_t s_musicvolume;
|
||||
extern convar_t s_lerping;
|
||||
extern convar_t s_test; // cvar to testify new effects
|
||||
extern convar_t s_musicvolume;
|
||||
extern convar_t s_lerping;
|
||||
extern convar_t s_test; // cvar to test new effects
|
||||
extern convar_t s_samplecount;
|
||||
extern convar_t s_warn_late_precache;
|
||||
extern convar_t snd_mute_losefocus;
|
||||
|
||||
void S_InitScaletable( void );
|
||||
wavdata_t *S_LoadSound( sfx_t *sfx );
|
||||
@@ -292,7 +265,6 @@ void SND_ForceCloseMouth( int entnum );
|
||||
//
|
||||
void S_StreamSoundTrack( void );
|
||||
void S_StreamBackgroundTrack( void );
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
||||
void S_PrintBackgroundTrackState( void );
|
||||
void S_FadeMusicVolume( float fadePercent );
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
|
||||
if( IsEndOfText( trim ))
|
||||
{
|
||||
Con_Reportf( "TextMessage: unexpected '}' found, line %d\n", lineNumber );
|
||||
Con_Reportf( "%s: unexpected '}' found, line %d\n", __func__, lineNumber );
|
||||
return;
|
||||
}
|
||||
Q_strncpy( currentName, trim, sizeof( currentName ));
|
||||
@@ -263,7 +263,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
// save name on name heap
|
||||
if( lastNamePos + length > 32768 )
|
||||
{
|
||||
Con_Reportf( "TextMessage: error while parsing!\n" );
|
||||
Con_Reportf( "%s: error while parsing!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
}
|
||||
if( IsStartOfText( trim ))
|
||||
{
|
||||
Con_Reportf( "TextMessage: unexpected '{' found, line %d\n", lineNumber );
|
||||
Con_Reportf( "%s: unexpected '{' found, line %d\n", __func__, lineNumber );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -302,7 +302,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
}
|
||||
}
|
||||
|
||||
Con_Reportf( "TextMessage: parsed %d text messages\n", messageCount );
|
||||
Con_Reportf( "%s: parsed %d text messages\n", __func__, messageCount );
|
||||
nameHeapSize = lastNamePos;
|
||||
textHeapSize = 0;
|
||||
|
||||
@@ -347,7 +347,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
||||
}
|
||||
|
||||
if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize ))
|
||||
Con_DPrintf( S_ERROR "TextMessage: overflow text message buffer!\n" );
|
||||
Con_DPrintf( S_ERROR "%s: overflow text message buffer!\n", __func__ );
|
||||
|
||||
clgame.numTitles = messageCount;
|
||||
}
|
||||
|
||||
@@ -23,55 +23,182 @@ GNU General Public License for more details.
|
||||
#include "input.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
|
||||
#define VGUI_MAX_TEXTURES 1024
|
||||
|
||||
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size );
|
||||
static void GAME_EXPORT VGUI_GetMousePos( int *, int * );
|
||||
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor );
|
||||
static byte GAME_EXPORT VGUI_GetColor( int, int );
|
||||
static int GAME_EXPORT VGUI_UtfProcessChar( int in );
|
||||
static qboolean GAME_EXPORT VGUI_IsInGame( void );
|
||||
|
||||
static struct
|
||||
typedef struct vgui_static_s
|
||||
{
|
||||
qboolean initialized;
|
||||
vguiapi_t dllFuncs;
|
||||
VGUI_DefaultCursor cursor;
|
||||
vguiapi_t dllFuncs;
|
||||
|
||||
int textures[VGUI_MAX_TEXTURES];
|
||||
int texture_id;
|
||||
int bound_texture;
|
||||
byte color[4];
|
||||
qboolean enable_texture;
|
||||
|
||||
HINSTANCE hInstance;
|
||||
|
||||
enum VGUI_KeyCode virtualKeyTrans[256];
|
||||
} vgui =
|
||||
{
|
||||
false,
|
||||
{
|
||||
false, // Not initialized yet
|
||||
NULL, // VGUI_DrawInit,
|
||||
NULL, // VGUI_DrawShutdown,
|
||||
NULL, // VGUI_SetupDrawingText,
|
||||
NULL, // VGUI_SetupDrawingRect,
|
||||
NULL, // VGUI_SetupDrawingImage,
|
||||
NULL, // VGUI_BindTexture,
|
||||
NULL, // VGUI_EnableTexture,
|
||||
NULL, // VGUI_CreateTexture,
|
||||
NULL, // VGUI_UploadTexture,
|
||||
NULL, // VGUI_UploadTextureBlock,
|
||||
NULL, // VGUI_DrawQuad,
|
||||
NULL, // VGUI_GetTextureSizes,
|
||||
NULL, // VGUI_GenerateTexture,
|
||||
VGUI_EngineMalloc,
|
||||
VGUI_CursorSelect,
|
||||
VGUI_GetColor,
|
||||
VGUI_IsInGame,
|
||||
Key_EnableTextInput,
|
||||
VGUI_GetMousePos,
|
||||
VGUI_UtfProcessChar,
|
||||
Platform_GetClipboardText,
|
||||
Platform_SetClipboardText,
|
||||
Platform_GetKeyModifiers,
|
||||
},
|
||||
-1
|
||||
} vgui_static_t;
|
||||
|
||||
static vgui_static_t vgui = {
|
||||
false, -1
|
||||
};
|
||||
static CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
|
||||
|
||||
static void GAME_EXPORT VGUI_DrawInit( void )
|
||||
{
|
||||
memset( vgui.textures, 0, sizeof( vgui.textures ));
|
||||
memset( vgui.color, 0, sizeof( vgui.color ));
|
||||
vgui.texture_id = vgui.bound_texture = 0;
|
||||
vgui.enable_texture = true;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_DrawShutdown( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 1; i < vgui.texture_id; i++ )
|
||||
ref.dllFuncs.GL_FreeTexture( vgui.textures[i] );
|
||||
}
|
||||
|
||||
static int GAME_EXPORT VGUI_GenerateTexture( void )
|
||||
{
|
||||
if( ++vgui.texture_id >= VGUI_MAX_TEXTURES )
|
||||
Host_Error( "%s: VGUI_MAX_TEXTURES limit exceeded\n", __func__ );
|
||||
|
||||
return vgui.texture_id;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height )
|
||||
{
|
||||
rgbdata_t r_image = { 0 };
|
||||
char texName[32];
|
||||
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
|
||||
|
||||
r_image.width = width;
|
||||
r_image.height = height;
|
||||
r_image.type = PF_RGBA_32;
|
||||
r_image.size = width * height * 4;
|
||||
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
|
||||
r_image.buffer = (byte*)buffer;
|
||||
|
||||
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height )
|
||||
{
|
||||
rgbdata_t r_image = { 0 };
|
||||
char texName[32];
|
||||
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
|
||||
|
||||
r_image.width = width;
|
||||
r_image.height = height;
|
||||
r_image.type = PF_RGBA_32;
|
||||
r_image.size = width * height * 4;
|
||||
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
|
||||
r_image.buffer = NULL;
|
||||
|
||||
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
|
||||
vgui.bound_texture = id;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
|
||||
{
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES || vgui.textures[id] == 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
|
||||
return;
|
||||
}
|
||||
|
||||
ref.dllFuncs.VGUI_UploadTextureBlock( drawX, drawY, rgba, blockWidth, blockHeight );
|
||||
vgui.bound_texture = id;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_BindTexture( int id )
|
||||
{
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES || !vgui.textures[id] )
|
||||
id = 1; // NOTE: same as bogus index 2700 in GoldSrc
|
||||
|
||||
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, vgui.textures[id] );
|
||||
vgui.bound_texture = id;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_GetTextureSizes( int *w, int *h )
|
||||
{
|
||||
int texnum;
|
||||
|
||||
if( vgui.bound_texture )
|
||||
texnum = vgui.textures[vgui.bound_texture];
|
||||
else
|
||||
texnum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
|
||||
|
||||
R_GetTextureParms( w, h, texnum );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor )
|
||||
{
|
||||
ref.dllFuncs.VGUI_SetupDrawing( true );
|
||||
Vector4Set( vgui.color, pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_SetupDrawingText( int *pColor )
|
||||
{
|
||||
ref.dllFuncs.VGUI_SetupDrawing( false );
|
||||
Vector4Set( vgui.color, pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr )
|
||||
{
|
||||
float x, y, w, h;
|
||||
|
||||
if( !ul || !lr )
|
||||
return;
|
||||
|
||||
x = ul->point[0];
|
||||
y = ul->point[1];
|
||||
w = lr->point[0] - x;
|
||||
h = lr->point[1] - y;
|
||||
|
||||
SPR_AdjustSize( &x, &y, &w, &h );
|
||||
|
||||
if( vgui.enable_texture )
|
||||
{
|
||||
float s1, s2, t1, t2;
|
||||
|
||||
s1 = ul->coord[0];
|
||||
t1 = ul->coord[1];
|
||||
s2 = lr->coord[0];
|
||||
t2 = lr->coord[1];
|
||||
|
||||
ref.dllFuncs.Color4ub( vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
|
||||
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, vgui.textures[vgui.bound_texture] );
|
||||
}
|
||||
else
|
||||
{
|
||||
ref.dllFuncs.FillRGBABlend( x, y, w, h, vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
|
||||
}
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_EnableTexture( qboolean enable )
|
||||
{
|
||||
vgui.enable_texture = enable;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size )
|
||||
{
|
||||
@@ -117,33 +244,46 @@ qboolean VGui_IsActive( void )
|
||||
return vgui.initialized;
|
||||
}
|
||||
|
||||
static void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
|
||||
{
|
||||
to->DrawInit = from->VGUI_DrawInit;
|
||||
to->DrawShutdown = from->VGUI_DrawShutdown;
|
||||
to->SetupDrawingText = from->VGUI_SetupDrawingText;
|
||||
to->SetupDrawingRect = from->VGUI_SetupDrawingRect;
|
||||
to->SetupDrawingImage = from->VGUI_SetupDrawingImage;
|
||||
to->BindTexture = from->VGUI_BindTexture;
|
||||
to->EnableTexture = from->VGUI_EnableTexture;
|
||||
to->CreateTexture = from->VGUI_CreateTexture;
|
||||
to->UploadTexture = from->VGUI_UploadTexture;
|
||||
to->UploadTextureBlock = from->VGUI_UploadTextureBlock;
|
||||
to->DrawQuad = from->VGUI_DrawQuad;
|
||||
to->GetTextureSizes = from->VGUI_GetTextureSizes;
|
||||
to->GenerateTexture = from->VGUI_GenerateTexture;
|
||||
}
|
||||
|
||||
void VGui_RegisterCvars( void )
|
||||
{
|
||||
Cvar_RegisterVariable( &vgui_utf8 );
|
||||
}
|
||||
|
||||
static const vguiapi_t gEngfuncs =
|
||||
{
|
||||
false, // Not initialized yet
|
||||
VGUI_DrawInit, // VGUI_DrawInit,
|
||||
VGUI_DrawShutdown, // VGUI_DrawShutdown,
|
||||
VGUI_SetupDrawingText, // VGUI_SetupDrawingText,
|
||||
VGUI_SetupDrawingRect, // VGUI_SetupDrawingRect,
|
||||
VGUI_SetupDrawingText, // VGUI_SetupDrawingImage, (same as text)
|
||||
VGUI_BindTexture, // VGUI_BindTexture,
|
||||
VGUI_EnableTexture, // VGUI_EnableTexture,
|
||||
VGUI_CreateTexture, // VGUI_CreateTexture,
|
||||
VGUI_UploadTexture, // VGUI_UploadTexture,
|
||||
VGUI_UploadTextureBlock, // VGUI_UploadTextureBlock,
|
||||
VGUI_DrawQuad, // VGUI_DrawQuad,
|
||||
VGUI_GetTextureSizes, // VGUI_GetTextureSizes,
|
||||
VGUI_GenerateTexture, // VGUI_GenerateTexture,
|
||||
VGUI_EngineMalloc,
|
||||
VGUI_CursorSelect,
|
||||
VGUI_GetColor,
|
||||
VGUI_IsInGame,
|
||||
Key_EnableTextInput,
|
||||
VGUI_GetMousePos,
|
||||
VGUI_UtfProcessChar,
|
||||
Platform_GetClipboardText,
|
||||
Platform_SetClipboardText,
|
||||
Platform_GetKeyModifiers,
|
||||
};
|
||||
|
||||
qboolean VGui_LoadProgs( HINSTANCE hInstance )
|
||||
{
|
||||
void (*F)( vguiapi_t* );
|
||||
qboolean client = hInstance != NULL;
|
||||
|
||||
vgui.dllFuncs = gEngfuncs;
|
||||
|
||||
// not loading interface from client.dll, load vgui_support.dll instead
|
||||
if( !client )
|
||||
{
|
||||
@@ -167,7 +307,7 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
|
||||
{
|
||||
if( FS_FileExists( vguiloader, false ))
|
||||
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
|
||||
else Con_Reportf( "vgui_support: not found\n" );
|
||||
else Con_Reportf( "%s: not found\n", __func__ );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -178,16 +318,15 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
|
||||
|
||||
if( F )
|
||||
{
|
||||
VGui_FillAPIFromRef( &vgui.dllFuncs, &ref.dllFuncs );
|
||||
F( &vgui.dllFuncs );
|
||||
|
||||
vgui.initialized = vgui.dllFuncs.initialized = true;
|
||||
Con_Reportf( "vgui_support: initialized legacy API in %s module\n", client ? "client" : "support" );
|
||||
Con_Reportf( "%s: initialized legacy API in %s module\n", __func__, client ? "client" : "support" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Con_Reportf( S_ERROR "Failed to find VGUI support API entry point in %s module\n", client ? "client" : "support" );
|
||||
Con_Reportf( S_ERROR "%s: Failed to find VGUI support API entry point in %s module\n", __func__, client ? "client" : "support" );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -233,8 +372,9 @@ void VGui_Shutdown( void )
|
||||
if( vgui.hInstance )
|
||||
COM_FreeLibrary( vgui.hInstance );
|
||||
|
||||
// drop pointers to now unloaded vgui_support
|
||||
vgui.dllFuncs = gEngfuncs;
|
||||
vgui.hInstance = NULL;
|
||||
vgui.initialized = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "p
|
||||
|
||||
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
|
||||
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
|
||||
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
||||
CVAR_DEFINE( vid_fullscreen, "fullscreen", DEFAULT_FULLSCREEN, FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
||||
CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
|
||||
CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
|
||||
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
|
||||
@@ -175,7 +175,7 @@ static void VID_Mode_f( void )
|
||||
vidmode = R_GetVideoMode( Q_atoi( Cmd_Argv( 1 )) );
|
||||
if( !vidmode )
|
||||
{
|
||||
Con_Print( S_ERROR "unable to set mode, backend returned null" );
|
||||
Con_Printf( S_ERROR "unable to set mode, backend returned null" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,17 @@ voice_state_t voice = { 0 };
|
||||
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
|
||||
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
|
||||
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
|
||||
CVAR_DEFINE_AUTO( voice_transmit_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "outcoming voice volume scale" );
|
||||
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
|
||||
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
|
||||
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
|
||||
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale );
|
||||
|
||||
// in case user enabled voice after connection
|
||||
// can't keep in `voice` struct because it gets zeroed on shutdown
|
||||
static string voice_codec_init;
|
||||
static int voice_quality_init;
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
@@ -39,6 +45,25 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count );
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static qboolean Voice_InitCustomMode( void )
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
voice.width = sizeof( opus_int16 );
|
||||
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
|
||||
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
|
||||
|
||||
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
|
||||
|
||||
if( !voice.custom_mode )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_InitOpusDecoder
|
||||
@@ -47,24 +72,17 @@ Voice_InitOpusDecoder
|
||||
*/
|
||||
static qboolean Voice_InitOpusDecoder( void )
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
voice.width = sizeof( opus_int16 );
|
||||
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
|
||||
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
|
||||
|
||||
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
|
||||
if( !voice.custom_mode )
|
||||
for( int i = 0; i < cl.maxclients; i++ )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
|
||||
return false;
|
||||
}
|
||||
voice.decoders[i] = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||
|
||||
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||
if( !voice.decoder )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
|
||||
return false;
|
||||
if( !voice.decoders[i] )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus decoder for %i: %s\n", i, opus_strerror( err ));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -78,7 +96,7 @@ Voice_InitOpusEncoder
|
||||
*/
|
||||
static qboolean Voice_InitOpusEncoder( int quality )
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||
if( !voice.encoder )
|
||||
@@ -117,10 +135,13 @@ Voice_ShutdownOpusDecoder
|
||||
*/
|
||||
static void Voice_ShutdownOpusDecoder( void )
|
||||
{
|
||||
if( voice.decoder )
|
||||
for( int i = 0; i < MAX_CLIENTS; i++ )
|
||||
{
|
||||
opus_custom_decoder_destroy( voice.decoder );
|
||||
voice.decoder = NULL;
|
||||
if( !voice.decoders[i] )
|
||||
continue;
|
||||
|
||||
opus_custom_decoder_destroy( voice.decoders[i] );
|
||||
voice.decoders[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +158,10 @@ static void Voice_ShutdownOpusEncoder( void )
|
||||
opus_custom_encoder_destroy( voice.encoder );
|
||||
voice.encoder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void Voice_ShutdownCustomMode( void )
|
||||
{
|
||||
if( voice.custom_mode )
|
||||
{
|
||||
opus_custom_mode_destroy( voice.custom_mode );
|
||||
@@ -184,7 +208,7 @@ static uint Voice_GetOpusCompressedData( byte *out, uint maxsize, uint *frames )
|
||||
if( !voice.input_file )
|
||||
{
|
||||
// adjust gain before encoding, but only for input from voice
|
||||
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size);
|
||||
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size, voice_transmit_scale.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -238,10 +262,10 @@ Voice_ApplyGainAdjust
|
||||
|
||||
=========================
|
||||
*/
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale )
|
||||
{
|
||||
float gain, modifiedMax;
|
||||
int average, adjustedSample, blockOffset = 0;
|
||||
int average, blockOffset = 0;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
@@ -260,10 +284,8 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
||||
localMax = absSample;
|
||||
|
||||
localSum += absSample;
|
||||
|
||||
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
|
||||
adjustedSample = Q_min( SHRT_MAX, Q_max(( int )( sample * gain ), SHRT_MIN ));
|
||||
samples[blockOffset + i] = adjustedSample;
|
||||
samples[blockOffset + i] = bound( SHRT_MIN, (int)( sample * gain ), SHRT_MAX );
|
||||
}
|
||||
|
||||
if( blockOffset % voice.autogain.block_size == 0 )
|
||||
@@ -271,9 +293,9 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
||||
average = localSum / blockSize;
|
||||
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
|
||||
|
||||
voice.autogain.current_gain = voice.autogain.next_gain * voice_scale.value;
|
||||
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * voice_scale.value;
|
||||
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( voice.autogain.block_size - 1 );
|
||||
voice.autogain.current_gain = voice.autogain.next_gain * scale;
|
||||
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * scale;
|
||||
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( blockSize - 1 );
|
||||
}
|
||||
blockOffset += blockSize;
|
||||
}
|
||||
@@ -380,7 +402,7 @@ void Voice_RecordStart( void )
|
||||
|
||||
if( voice.input_file )
|
||||
{
|
||||
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
|
||||
Sound_Process( &voice.input_file, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, SOUND_RESAMPLE );
|
||||
voice.input_file_pos = 0;
|
||||
|
||||
voice.start_time = Sys_DoubleTime();
|
||||
@@ -443,7 +465,7 @@ Feed the decoded data to engine sound subsystem
|
||||
static void Voice_StartChannel( uint samples, byte *data, int entnum )
|
||||
{
|
||||
SND_ForceInitMouth( entnum );
|
||||
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, 255 );
|
||||
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, bound( 0, 255 * voice_scale.value, 255 ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -455,10 +477,11 @@ Received encoded voice data, decode it
|
||||
*/
|
||||
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
|
||||
{
|
||||
const int playernum = ent - 1;
|
||||
int samples = 0;
|
||||
int ofs = 0;
|
||||
|
||||
if( !voice.decoder )
|
||||
if( playernum < 0 || playernum >= cl.maxclients || !voice.decoders[playernum] )
|
||||
return;
|
||||
|
||||
// decode frame by frame
|
||||
@@ -478,7 +501,7 @@ void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
|
||||
if( ofs + compressed_size > size )
|
||||
break;
|
||||
|
||||
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size,
|
||||
frame_samples = opus_custom_decode( voice.decoders[playernum], data + ofs, compressed_size,
|
||||
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
|
||||
|
||||
ofs += compressed_size;
|
||||
@@ -502,8 +525,8 @@ void CL_AddVoiceToDatagram( void )
|
||||
|
||||
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
|
||||
return;
|
||||
|
||||
size = Voice_GetOpusCompressedData( voice.output_buffer, sizeof( voice.output_buffer ), &frames );
|
||||
|
||||
size = Voice_GetOpusCompressedData( voice.compress_buffer, sizeof( voice.compress_buffer ), &frames );
|
||||
|
||||
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
|
||||
{
|
||||
@@ -511,7 +534,7 @@ void CL_AddVoiceToDatagram( void )
|
||||
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
|
||||
MSG_WriteByte( &cls.datagram, frames );
|
||||
MSG_WriteShort( &cls.datagram, size );
|
||||
MSG_WriteBytes( &cls.datagram, voice.output_buffer, size );
|
||||
MSG_WriteBytes( &cls.datagram, voice.compress_buffer, size );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,6 +550,7 @@ void Voice_RegisterCvars( void )
|
||||
Cvar_RegisterVariable( &voice_enable );
|
||||
Cvar_RegisterVariable( &voice_loopback );
|
||||
Cvar_RegisterVariable( &voice_scale );
|
||||
Cvar_RegisterVariable( &voice_transmit_scale );
|
||||
Cvar_RegisterVariable( &voice_avggain );
|
||||
Cvar_RegisterVariable( &voice_maxgain );
|
||||
Cvar_RegisterVariable( &voice_inputfromfile );
|
||||
@@ -544,8 +568,9 @@ static void Voice_Shutdown( void )
|
||||
int i;
|
||||
|
||||
Voice_RecordStop();
|
||||
Voice_ShutdownOpusEncoder();
|
||||
Voice_ShutdownOpusDecoder();
|
||||
Voice_ShutdownOpusEncoder();
|
||||
Voice_ShutdownCustomMode();
|
||||
VoiceCapture_Shutdown();
|
||||
|
||||
if( voice.local.talking_ack )
|
||||
@@ -571,10 +596,17 @@ void Voice_Idle( double frametime )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
|
||||
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
Voice_Shutdown();
|
||||
return;
|
||||
ClearBits( voice_enable.flags, FCVAR_CHANGED );
|
||||
|
||||
if( voice_enable.value )
|
||||
{
|
||||
if( cls.state == ca_active && COM_CheckString( voice_codec_init ) && voice_quality_init != 0 )
|
||||
Voice_Init( voice_codec_init, voice_quality_init, false );
|
||||
}
|
||||
else
|
||||
Voice_Shutdown();
|
||||
}
|
||||
|
||||
// update local player status first
|
||||
@@ -593,6 +625,19 @@ Initialize the voice subsystem
|
||||
*/
|
||||
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 );
|
||||
|
||||
// reset saved codec name, we won't enable voice for this connection
|
||||
voice_codec_init[0] = 0;
|
||||
voice_quality_init = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_strncpy( voice_codec_init, pszCodecName, sizeof( voice_codec_init ));
|
||||
voice_quality_init = quality;
|
||||
|
||||
if( !voice_enable.value )
|
||||
return false;
|
||||
|
||||
@@ -600,20 +645,12 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
||||
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
|
||||
{
|
||||
Voice_Shutdown();
|
||||
|
||||
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.autogain.block_size = 128;
|
||||
|
||||
if( !Voice_InitOpusDecoder( ))
|
||||
if( !Voice_InitCustomMode( ))
|
||||
{
|
||||
// no reason to init encoder and open audio device
|
||||
// if we can't hear other players
|
||||
Con_Printf( S_ERROR "Voice chat disabled.\n" );
|
||||
Voice_Shutdown();
|
||||
return false;
|
||||
}
|
||||
@@ -633,6 +670,16 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
||||
|
||||
if( !preinit )
|
||||
{
|
||||
Voice_ShutdownOpusDecoder();
|
||||
if( !Voice_InitOpusDecoder())
|
||||
{
|
||||
// no reason to init encoder and open audio device
|
||||
// if we can't hear other players
|
||||
Con_Printf( S_ERROR "Can't create decoders, voice chat is disabled.\n" );
|
||||
Voice_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.device_opened = VoiceCapture_Init();
|
||||
|
||||
if( !voice.device_opened )
|
||||
|
||||
@@ -31,7 +31,7 @@ typedef struct OpusCustomMode OpusCustomMode;
|
||||
#define VOICE_PCM_CHANNELS 1 // always mono
|
||||
|
||||
// never change these parameters when using opuscustom
|
||||
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k
|
||||
#define VOICE_OPUS_CUSTOM_SAMPLERATE 44100
|
||||
// must follow opus custom requirements
|
||||
// also be divisible with MAX_RAW_SAMPLES
|
||||
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024
|
||||
@@ -62,7 +62,7 @@ typedef struct voice_state_s
|
||||
// opus stuff
|
||||
OpusCustomMode *custom_mode;
|
||||
OpusCustomEncoder *encoder;
|
||||
OpusCustomDecoder *decoder;
|
||||
OpusCustomDecoder *decoders[MAX_CLIENTS];
|
||||
|
||||
// audio info
|
||||
uint width;
|
||||
@@ -71,7 +71,7 @@ typedef struct voice_state_s
|
||||
|
||||
// buffers
|
||||
byte input_buffer[MAX_RAW_SAMPLES];
|
||||
byte output_buffer[MAX_RAW_SAMPLES];
|
||||
byte compress_buffer[MAX_RAW_SAMPLES];
|
||||
byte decompress_buffer[MAX_RAW_SAMPLES];
|
||||
fs_offset_t input_buffer_pos; // in bytes
|
||||
|
||||
|
||||
@@ -16,21 +16,20 @@ GNU General Public License for more details.
|
||||
#ifndef VOX_H
|
||||
#define VOX_H
|
||||
|
||||
#define CVOXWORDMAX 64
|
||||
|
||||
#define SENTENCE_INDEX -99999 // unique sentence index
|
||||
#define CVOXWORDMAX 64
|
||||
#define SENTENCE_INDEX -99999 // unique sentence index
|
||||
|
||||
typedef struct voxword_s
|
||||
{
|
||||
int volume; // increase percent, ie: 125 = 125% increase
|
||||
int pitch; // pitch shift up percent
|
||||
int start; // offset start of wave percent
|
||||
int end; // offset end of wave percent
|
||||
int cbtrim; // end of wave after being trimmed to 'end'
|
||||
int fKeepCached; // 1 if this word was already in cache before sentence referenced it
|
||||
int samplefrac; // if pitch shifting, this is position into wav * 256
|
||||
int timecompress; // % of wave to skip during playback (causes no pitch shift)
|
||||
sfx_t *sfx; // name and cache pointer
|
||||
int volume; // increase percent, ie: 125 = 125% increase
|
||||
int pitch; // pitch shift up percent
|
||||
int start; // offset start of wave percent
|
||||
int end; // offset end of wave percent
|
||||
int cbtrim; // end of wave after being trimmed to 'end'
|
||||
int fKeepCached; // 1 if this word was already in cache before sentence referenced it
|
||||
int samplefrac; // if pitch shifting, this is position into wav * 256
|
||||
int timecompress; // % of wave to skip during playback (causes no pitch shift)
|
||||
sfx_t *sfx; // name and cache pointer
|
||||
} voxword_t;
|
||||
|
||||
struct channel_s;
|
||||
|
||||
@@ -19,13 +19,15 @@ GNU General Public License for more details.
|
||||
|
||||
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
|
||||
|
||||
typedef struct base_command_hashmap_s
|
||||
typedef struct base_command_hashmap_s base_command_hashmap_t;
|
||||
|
||||
struct base_command_hashmap_s
|
||||
{
|
||||
base_command_t *basecmd; // base command: cvar, alias or command
|
||||
const char *name; // key for searching
|
||||
base_command_type_e type; // type for faster searching
|
||||
struct base_command_hashmap_s *next;
|
||||
} base_command_hashmap_t;
|
||||
base_command_t *basecmd; // base command: cvar, alias or command
|
||||
base_command_hashmap_t *next;
|
||||
base_command_type_e type; // type for faster searching
|
||||
char name[1]; // key for searching
|
||||
};
|
||||
|
||||
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
|
||||
|
||||
@@ -124,11 +126,12 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
|
||||
{
|
||||
base_command_hashmap_t *elem, *cur, *find;
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
size_t len = Q_strlen( name );
|
||||
|
||||
elem = Z_Malloc( sizeof( base_command_hashmap_t ) );
|
||||
elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
|
||||
elem->basecmd = basecmd;
|
||||
elem->type = type;
|
||||
elem->name = name;
|
||||
Q_strncpy( elem->name, name, len + 1 );
|
||||
|
||||
// link the variable in alphanumerical order
|
||||
for( cur = NULL, find = hashed_cmds[hash];
|
||||
@@ -159,7 +162,7 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
|
||||
|
||||
if( !i )
|
||||
{
|
||||
Con_Reportf( S_ERROR "Couldn't find %s in buckets\n", name );
|
||||
Con_Reportf( S_ERROR "%s: Couldn't find %s in buckets\n", __func__, name );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ typedef enum base_command_type
|
||||
|
||||
typedef void base_command_t;
|
||||
|
||||
|
||||
|
||||
void BaseCmd_Init( void );
|
||||
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
|
||||
void BaseCmd_FindAll( const char *name,
|
||||
|
||||
@@ -86,7 +86,7 @@ static void *Cbuf_GetSpace( cmdbuf_t *buf, int length )
|
||||
if(( buf->cursize + length ) > buf->maxsize )
|
||||
{
|
||||
buf->cursize = 0;
|
||||
Host_Error( "Cbuf_GetSpace: overflow\n" );
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
}
|
||||
|
||||
data = buf->data + buf->cursize;
|
||||
@@ -156,7 +156,7 @@ static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text )
|
||||
|
||||
if(( buf->cursize + l ) >= buf->maxsize )
|
||||
{
|
||||
Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" );
|
||||
Con_Reportf( S_WARN "%s: overflow\n", __func__ );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -224,7 +224,7 @@ static void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged
|
||||
|
||||
if( i >= ( MAX_CMD_LINE - 1 ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Cbuf_Execute: command string owerflow\n" );
|
||||
Con_DPrintf( S_ERROR "%s: command string owerflow\n", __func__ );
|
||||
line[0] = 0;
|
||||
}
|
||||
else
|
||||
@@ -387,7 +387,7 @@ static void Cmd_Echo_f( void )
|
||||
int i;
|
||||
|
||||
for( i = 1; i < Cmd_Argc(); i++ )
|
||||
Con_Printf( "%s", Cmd_Argv( i ));
|
||||
Con_Printf( "%s ", Cmd_Argv( i ));
|
||||
Con_Printf( "\n" );
|
||||
}
|
||||
|
||||
@@ -640,7 +640,7 @@ void Cmd_TokenizeString( const char *text )
|
||||
while( 1 )
|
||||
{
|
||||
// skip whitespace up to a /n
|
||||
while( *text && *text <= ' ' && *text != '\r' && *text != '\n' )
|
||||
while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
|
||||
text++;
|
||||
|
||||
if( *text == '\n' || *text == '\r' )
|
||||
@@ -682,7 +682,7 @@ static int Cmd_AddCommandEx( const char *funcname, const char *cmd_name, xcomman
|
||||
|
||||
if( !COM_CheckString( cmd_name ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: NULL name\n", funcname );
|
||||
Con_Reportf( S_ERROR "%s: NULL name\n", funcname );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -728,7 +728,7 @@ Cmd_AddCommand
|
||||
*/
|
||||
void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
|
||||
{
|
||||
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, cmd_desc, 0 );
|
||||
Cmd_AddCommandEx( __func__, cmd_name, function, cmd_desc, 0 );
|
||||
}
|
||||
|
||||
|
||||
@@ -739,7 +739,7 @@ Cmd_AddRestrictedCommand
|
||||
*/
|
||||
void Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
|
||||
{
|
||||
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, cmd_desc, CMD_PRIVILEGED );
|
||||
Cmd_AddCommandEx( __func__, cmd_name, function, cmd_desc, CMD_PRIVILEGED );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -749,7 +749,7 @@ Cmd_AddServerCommand
|
||||
*/
|
||||
void GAME_EXPORT Cmd_AddServerCommand( const char *cmd_name, xcommand_t function )
|
||||
{
|
||||
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "server command", CMD_SERVERDLL );
|
||||
Cmd_AddCommandEx( __func__, cmd_name, function, "server command", CMD_SERVERDLL );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -767,7 +767,7 @@ int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function
|
||||
flags |= CMD_PRIVILEGED;
|
||||
}
|
||||
|
||||
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "client command", flags );
|
||||
return Cmd_AddCommandEx( __func__, cmd_name, function, "client command", flags );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -777,7 +777,7 @@ Cmd_AddGameUICommand
|
||||
*/
|
||||
int GAME_EXPORT Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function )
|
||||
{
|
||||
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "gameui command", CMD_GAMEUIDLL );
|
||||
return Cmd_AddCommandEx( __func__, cmd_name, function, "gameui command", CMD_GAMEUIDLL );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -787,7 +787,7 @@ Cmd_AddRefCommand
|
||||
*/
|
||||
int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description )
|
||||
{
|
||||
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, description, CMD_REFDLL );
|
||||
return Cmd_AddCommandEx( __func__, cmd_name, function, description, CMD_REFDLL );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -949,7 +949,7 @@ static void Cmd_Else_f( void )
|
||||
|
||||
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
|
||||
{
|
||||
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_" };
|
||||
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_", "con_", "scr_" };
|
||||
int i;
|
||||
|
||||
// always allow local commands
|
||||
@@ -1015,7 +1015,7 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
|
||||
*ptoken++ = *text++;
|
||||
*ptoken = 0;
|
||||
|
||||
len += Q_strncpy( pcmd, Cvar_VariableString( token ), MAX_CMD_LINE - len );
|
||||
len += Q_strncpy( pcmd, Cvar_VariableString( token ), sizeof( token ) - len );
|
||||
pcmd = command + len;
|
||||
|
||||
if( !*text ) break;
|
||||
|
||||
@@ -39,9 +39,6 @@ GNU General Public License for more details.
|
||||
// end game final default message
|
||||
#define DEFAULT_ENDGAME_MESSAGE "The End"
|
||||
|
||||
// path to the hash-pak that contain custom player decals
|
||||
#define CUSTOM_RES_PATH "custom.hpk"
|
||||
|
||||
// path to default playermodel in GoldSrc
|
||||
#define DEFAULT_PLAYER_PATH_HALFLIFE "models/player.mdl"
|
||||
|
||||
@@ -55,14 +52,20 @@ GNU General Public License for more details.
|
||||
|
||||
#define DEFAULT_EXTERNAL_PALETTE "gfx/palette.pal"
|
||||
|
||||
// path to folders where placed all sounds
|
||||
// path to sound files
|
||||
#define DEFAULT_SOUNDPATH "sound/"
|
||||
|
||||
// path store saved games
|
||||
// path to saved games
|
||||
#define DEFAULT_SAVE_DIRECTORY "save/"
|
||||
|
||||
// path to download games
|
||||
#define DEFAULT_DOWNLOADED_DIRECTORY "downloaded/"
|
||||
|
||||
// path to user mod directory
|
||||
#define DEFAULT_CUSTOM_DIRECTORY "custom/"
|
||||
|
||||
// fallback to this skybox
|
||||
#define DEFAULT_SKYBOX_PATH "gfx/env/desert"
|
||||
#define DEFAULT_SKYBOX_NAME "desert"
|
||||
|
||||
// playlist for startup videos
|
||||
#define DEFAULT_VIDEOLIST_PATH "media/StartupVids.txt"
|
||||
@@ -74,7 +77,8 @@ GNU General Public License for more details.
|
||||
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
|
||||
|
||||
#define XASH_ENGINE_NAME "Xash3D FWGS"
|
||||
#define XASH_VERSION "0.20" // engine current version
|
||||
#define XASH_DEDICATED_SERVER_NAME "XashDS"
|
||||
#define XASH_VERSION "0.21" // engine current version
|
||||
#define XASH_COMPAT_VERSION "0.99" // version we are based on
|
||||
|
||||
#endif//COM_STRINGS_H
|
||||
|
||||
@@ -25,16 +25,19 @@ GNU General Public License for more details.
|
||||
|
||||
static const char *file_exts[] =
|
||||
{
|
||||
"cfg",
|
||||
"lst",
|
||||
"exe",
|
||||
"vbs",
|
||||
"com",
|
||||
"bat",
|
||||
"dll",
|
||||
"ini",
|
||||
"log",
|
||||
"sys",
|
||||
// ban text files that don't make sense as resource
|
||||
"cfg", "lst", "ini", "log",
|
||||
|
||||
// ban Windows code
|
||||
"exe", "vbs", "com", "bat",
|
||||
"dll", "sys", "ps1",
|
||||
|
||||
// ban common unix code
|
||||
// NOTE: in unix anything can be executed as long it has access flag
|
||||
"so", "sh", "dylib",
|
||||
|
||||
// ban mobile archives
|
||||
"apk", "ipa",
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
@@ -390,6 +393,9 @@ byte *LZSS_Compress( byte *pInput, int inputLength, uint *pOutputSize )
|
||||
byte *pFinal = NULL;
|
||||
lzss_state_t state;
|
||||
|
||||
if( !pStart )
|
||||
return NULL;
|
||||
|
||||
memset( &state, 0, sizeof( state ));
|
||||
state.window_size = LZSS_WINDOW_SIZE;
|
||||
|
||||
@@ -897,7 +903,10 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
|
||||
if( !COM_CheckString( filename ))
|
||||
return false;
|
||||
|
||||
if( !Q_strncmp( filename, "!MD5", 4 ))
|
||||
ext = COM_FileExtension( lwrfilename );
|
||||
|
||||
// only allow extensionless files that start with !MD5
|
||||
if( !Q_strncmp( filename, "!MD5", 4 ) && ext[0] == 0 )
|
||||
return true;
|
||||
|
||||
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
|
||||
@@ -920,8 +929,6 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
|
||||
if( Q_strlen( first ) != 4 )
|
||||
return false;
|
||||
|
||||
ext = COM_FileExtension( lwrfilename );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( file_exts ); i++ )
|
||||
{
|
||||
if( !Q_stricmp( ext, file_exts[i] ))
|
||||
@@ -964,7 +971,7 @@ used by CS:CZ
|
||||
*/
|
||||
void *GAME_EXPORT pfnSequenceGet( const char *fileName, const char *entryName )
|
||||
{
|
||||
Msg( "Sequence_Get: file %s, entry %s\n", fileName, entryName );
|
||||
Msg( "%s: file %s, entry %s\n", __func__, fileName, entryName );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -978,7 +985,7 @@ used by CS:CZ
|
||||
*/
|
||||
void *GAME_EXPORT pfnSequencePickSentence( const char *groupName, int pickMethod, int *picked )
|
||||
{
|
||||
Msg( "Sequence_PickSentence: group %s, pickMethod %i\n", groupName, pickMethod );
|
||||
Msg( "%s: group %s, pickMethod %i\n", __func__, groupName, pickMethod );
|
||||
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@ typedef enum
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
#define FSCALLBACK_OVERRIDE_OPEN
|
||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#include "fscallback.h"
|
||||
|
||||
// PERFORMANCE INFO
|
||||
@@ -157,13 +160,16 @@ extern convar_t gl_vsync;
|
||||
extern convar_t scr_loading;
|
||||
extern convar_t scr_download;
|
||||
extern convar_t cmd_scripting;
|
||||
extern convar_t cl_allow_levelshots;
|
||||
extern convar_t host_allow_materials;
|
||||
extern convar_t host_developer;
|
||||
extern convar_t host_limitlocal;
|
||||
extern convar_t host_maxfps;
|
||||
extern convar_t sys_timescale;
|
||||
extern convar_t cl_filterstuffcmd;
|
||||
extern convar_t rcon_password;
|
||||
extern convar_t hpk_custom_file;
|
||||
|
||||
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
@@ -180,15 +186,6 @@ GAMEINFO stuff
|
||||
internal shared gameinfo structure (readonly for engine parts)
|
||||
========================================================================
|
||||
*/
|
||||
typedef struct sysinfo_s
|
||||
{
|
||||
string exeName; // exe.filename
|
||||
string rcName; // .rc script name
|
||||
string basedirName; // name of base directory
|
||||
string gamedll;
|
||||
string clientlib;
|
||||
} sysinfo_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HOST_INIT = 0, // initalize operations
|
||||
@@ -273,100 +270,91 @@ typedef struct
|
||||
|
||||
typedef enum bugcomp_e
|
||||
{
|
||||
// default mode, we assume that user dlls are not relying on engine bugs
|
||||
BUGCOMP_OFF,
|
||||
// reverts fix for pfnPEntityOfEntIndex for bug compatibility with GoldSrc
|
||||
BUGCOMP_PENTITYOFENTINDEX_FLAG = BIT( 0 ),
|
||||
|
||||
// GoldSrc mode, user dlls are relying on GoldSrc specific bugs
|
||||
// but fixing them may break regular Xash games
|
||||
BUGCOMP_GOLDSRC,
|
||||
// rewrites mod's attempts to write GoldSrc-specific messages into Xash protocol
|
||||
// (new wrappers are added by request)
|
||||
BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG = BIT( 1 ),
|
||||
|
||||
// makes sound with no attenuation spatialized, like in GoldSrc
|
||||
BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE = BIT( 2 ),
|
||||
} bugcomp_t;
|
||||
|
||||
typedef struct host_parm_s
|
||||
{
|
||||
HINSTANCE hInst;
|
||||
HANDLE hMutex;
|
||||
// ==== shared through RefAPI's ref_host_t
|
||||
double realtime; // host.curtime
|
||||
double frametime; // time between engine frames
|
||||
uint features; // custom features that enables by mod-maker request
|
||||
// ==== shared through RefAPI's ref_host_t
|
||||
|
||||
host_status_t status; // global host state
|
||||
game_status_t game; // game manager
|
||||
uint type; // running at
|
||||
jmp_buf abortframe; // abort current frame
|
||||
dword errorframe; // to prevent multiple host error
|
||||
poolhandle_t mempool; // static mempool for misc allocations
|
||||
string finalmsg; // server shutdown final message
|
||||
string downloadfile; // filename to be downloading
|
||||
int downloadcount; // how many files remain to downloading
|
||||
char deferred_cmd[128]; // deferred commands
|
||||
host_redirect_t rd; // remote console
|
||||
host_status_t status; // global host state
|
||||
game_status_t game; // game manager
|
||||
uint type; // running at
|
||||
poolhandle_t mempool; // static mempool for misc allocations
|
||||
poolhandle_t imagepool; // imagelib mempool
|
||||
poolhandle_t soundpool; // soundlib mempool
|
||||
string finalmsg; // server shutdown final message
|
||||
string downloadfile; // filename to be downloading
|
||||
int downloadcount; // how many files remain to downloading
|
||||
char deferred_cmd[128];// deferred commands
|
||||
|
||||
host_redirect_t rd; // remote console
|
||||
|
||||
void *hWnd; // main window
|
||||
|
||||
// command line parms
|
||||
int argc;
|
||||
char **argv;
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
// ==== shared through RefAPI's ref_host_t
|
||||
double realtime; // host.curtime
|
||||
double frametime; // time between engine frames
|
||||
uint features; // custom features that enables by mod-maker request
|
||||
// ==== shared through RefAPI's ref_host_t
|
||||
uint framecount; // global framecount
|
||||
uint errorframe; // to prevent multiple host error
|
||||
uint32_t bugcomp; // bug compatibility level, for very "special" games
|
||||
double realframetime; // for some system events, e.g. console animations
|
||||
double starttime; // measure time to first frame
|
||||
double pureframetime; // count of sleeps can be inserted between frames
|
||||
double force_draw_version_time;
|
||||
|
||||
double realframetime; // for some system events, e.g. console animations
|
||||
char draw_decals[MAX_DECALS][MAX_QPATH]; // list of unique decal indexes
|
||||
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
|
||||
uint framecount; // global framecount
|
||||
// for CL_{Push,Pop}TraceBounds
|
||||
vec3_t player_mins_backup[MAX_MAP_HULLS];
|
||||
vec3_t player_maxs_backup[MAX_MAP_HULLS];
|
||||
qboolean trace_bounds_pushed;
|
||||
|
||||
// list of unique decal indexes
|
||||
char draw_decals[MAX_DECALS][MAX_QPATH];
|
||||
|
||||
vec3_t player_mins[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
vec3_t player_maxs[MAX_MAP_HULLS]; // 4 hulls allowed
|
||||
|
||||
void* hWnd; // main window
|
||||
qboolean allow_console; // allow console in dev-mode or multiplayer game
|
||||
qboolean allow_console_init; // initial value to allow the console
|
||||
qboolean key_overstrike; // key overstrike mode
|
||||
qboolean stuffcmds_pending; // should execute stuff commands
|
||||
qboolean allow_cheats; // this host will allow cheating
|
||||
qboolean con_showalways; // show console always (developer and dedicated)
|
||||
qboolean change_game; // initialize when game is changed
|
||||
qboolean mouse_visible; // vgui override cursor control (never change outside Platform_SetCursorType!)
|
||||
qboolean shutdown_issued; // engine is shutting down
|
||||
double force_draw_version_time;
|
||||
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
|
||||
qboolean apply_opengl_config;// when true apply only to opengl cvars and ignore all other commands
|
||||
qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
|
||||
qboolean crashed; // set to true if crashed
|
||||
qboolean daemonized;
|
||||
qboolean enabledll;
|
||||
qboolean textmode;
|
||||
qboolean allow_console; // allow console in dev-mode or multiplayer game
|
||||
qboolean allow_console_init; // initial value to allow the console
|
||||
qboolean key_overstrike; // key overstrike mode
|
||||
qboolean stuffcmds_pending; // should execute stuff commands
|
||||
qboolean allow_cheats; // this host will allow cheating
|
||||
qboolean change_game; // initialize when game is changed
|
||||
qboolean mouse_visible; // vgui override cursor control (never change outside Platform_SetCursorType!)
|
||||
qboolean shutdown_issued; // engine is shutting down
|
||||
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
|
||||
qboolean apply_opengl_config; // when true apply only to opengl cvars and ignore all other commands
|
||||
qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
|
||||
qboolean crashed; // set to true if crashed
|
||||
#if XASH_DLL_LOADER
|
||||
qboolean enabledll;
|
||||
#endif
|
||||
qboolean textmode;
|
||||
|
||||
// some settings were changed and needs to global update
|
||||
qboolean userinfo_changed;
|
||||
qboolean movevars_changed;
|
||||
qboolean renderinfo_changed;
|
||||
|
||||
char rootdir[MAX_OSPATH]; // member root directory
|
||||
char rodir[MAX_OSPATH]; // readonly root
|
||||
char gamefolder[MAX_QPATH]; // it's a default gamefolder
|
||||
poolhandle_t imagepool; // imagelib mempool
|
||||
poolhandle_t soundpool; // soundlib mempool
|
||||
qboolean userinfo_changed;
|
||||
qboolean movevars_changed;
|
||||
qboolean renderinfo_changed;
|
||||
|
||||
// for IN_MouseMove() easy access
|
||||
int window_center_x;
|
||||
int window_center_y;
|
||||
|
||||
struct decallist_s *decalList; // used for keep decals, when renderer is restarted or changed
|
||||
int numdecals;
|
||||
|
||||
// bug compatibility level, for very "special" games
|
||||
bugcomp_t bugcomp;
|
||||
|
||||
// measure time to first frame
|
||||
double starttime;
|
||||
|
||||
// count of sleeps can be inserted between frames
|
||||
double pureframetime;
|
||||
int window_center_x;
|
||||
int window_center_y;
|
||||
string gamedll;
|
||||
string clientlib;
|
||||
} host_parm_t;
|
||||
|
||||
extern host_parm_t host;
|
||||
extern sysinfo_t SI;
|
||||
|
||||
#define CMD_SERVERDLL BIT( 0 ) // added by server.dll
|
||||
#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll
|
||||
@@ -377,13 +365,49 @@ extern sysinfo_t SI;
|
||||
|
||||
typedef void (*xcommand_t)( void );
|
||||
|
||||
//
|
||||
// zone.c
|
||||
//
|
||||
void Memory_Init( void );
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 3 ) WARN_UNUSED_RESULT;
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline )
|
||||
WARN_UNUSED_RESULT;
|
||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
|
||||
void _Mem_Check( const char *filename, int fileline );
|
||||
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data );
|
||||
void Mem_PrintList( size_t minallocationsize );
|
||||
void Mem_PrintStats( void );
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
|
||||
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
|
||||
|
||||
//
|
||||
// filesystem_engine.c
|
||||
//
|
||||
qboolean FS_LoadProgs( void );
|
||||
void FS_Init( void );
|
||||
void FS_Init( const char *basedir );
|
||||
void FS_Shutdown( void );
|
||||
void *FS_GetNativeObject( const char *obj );
|
||||
int FS_Close( file_t *file );
|
||||
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
MALLOC_LIKE( FS_Close, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
|
||||
//
|
||||
// cmd.c
|
||||
@@ -416,30 +440,6 @@ void Cmd_ExecuteString( const char *text );
|
||||
void Cmd_ForwardToServer( void );
|
||||
void Cmd_Escape( char *newCommand, const char *oldCommand, int len );
|
||||
|
||||
//
|
||||
// zone.c
|
||||
//
|
||||
void Memory_Init( void );
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 3 );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 );
|
||||
poolhandle_t _Mem_AllocPool( const char *name, const char *filename, int fileline );
|
||||
void _Mem_FreePool( poolhandle_t *poolptr, const char *filename, int fileline );
|
||||
void _Mem_EmptyPool( poolhandle_t poolptr, const char *filename, int fileline );
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void _Mem_Check( const char *filename, int fileline );
|
||||
qboolean Mem_IsAllocatedExt( poolhandle_t poolptr, void *data );
|
||||
void Mem_PrintList( size_t minallocationsize );
|
||||
void Mem_PrintStats( void );
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
|
||||
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
|
||||
|
||||
//
|
||||
// imagelib
|
||||
@@ -450,10 +450,10 @@ void Image_Setup( void );
|
||||
void Image_Init( void );
|
||||
void Image_Shutdown( void );
|
||||
void Image_AddCmdFlags( uint flags );
|
||||
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size );
|
||||
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
|
||||
rgbdata_t *FS_CopyImage( rgbdata_t *in );
|
||||
void FS_FreeImage( rgbdata_t *pack );
|
||||
rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeImage, 1 ) WARN_UNUSED_RESULT;
|
||||
qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
|
||||
rgbdata_t *FS_CopyImage( rgbdata_t *in ) MALLOC_LIKE( FS_FreeImage, 1 ) WARN_UNUSED_RESULT;
|
||||
extern const bpc_desc_t PFDesc[]; // image get pixelformat
|
||||
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved );
|
||||
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size );
|
||||
@@ -479,14 +479,6 @@ typedef enum
|
||||
WF_TOTALCOUNT, // must be last
|
||||
} sndformat_t;
|
||||
|
||||
// soundlib global settings
|
||||
typedef enum
|
||||
{
|
||||
SL_USE_LERPING = BIT(0), // lerping sounds during resample
|
||||
SL_KEEP_8BIT = BIT(1), // don't expand 8bit sounds automatically up to 16 bit
|
||||
SL_ALLOW_OVERWRITE = BIT(2), // allow to overwrite stored sounds
|
||||
} slFlags_t;
|
||||
|
||||
// wavdata output flags
|
||||
typedef enum
|
||||
{
|
||||
@@ -495,21 +487,20 @@ typedef enum
|
||||
SOUND_STREAM = BIT( 1 ), // this is a streaminfo, not a real sound
|
||||
|
||||
// Sound_Process manipulation flags
|
||||
SOUND_RESAMPLE = BIT(12), // resample sound to specified rate
|
||||
SOUND_CONVERT16BIT = BIT(13), // change sound resolution from 8 bit to 16
|
||||
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
|
||||
} sndFlags_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word rate; // num samples per second (e.g. 11025 - 11 khz)
|
||||
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
|
||||
byte channels; // num channels (1 - mono, 2 - stereo)
|
||||
int loopStart; // offset at this point sound will be looping while playing more than only once
|
||||
int samples; // total samplecount in wav
|
||||
uint type; // compression type
|
||||
uint flags; // misc sound flags
|
||||
byte *buffer; // sound buffer
|
||||
size_t size; // for bounds checking
|
||||
word rate; // num samples per second (e.g. 11025 - 11 khz)
|
||||
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
|
||||
byte channels; // num channels (1 - mono, 2 - stereo)
|
||||
uint loopStart; // offset at this point sound will be looping while playing more than only once
|
||||
uint samples; // total samplecount in wav
|
||||
uint type; // compression type
|
||||
uint flags; // misc sound flags
|
||||
byte *buffer; // sound buffer
|
||||
size_t size; // for bounds checking
|
||||
} wavdata_t;
|
||||
|
||||
//
|
||||
@@ -517,15 +508,15 @@ typedef struct
|
||||
//
|
||||
void Sound_Init( void );
|
||||
void Sound_Shutdown( void );
|
||||
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size );
|
||||
void FS_FreeSound( wavdata_t *pack );
|
||||
stream_t *FS_OpenStream( const char *filename );
|
||||
void FS_FreeStream( stream_t *stream );
|
||||
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT;
|
||||
stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT;
|
||||
wavdata_t *FS_StreamInfo( stream_t *stream );
|
||||
int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
|
||||
int FS_SetStreamPos( stream_t *stream, int newpos );
|
||||
int FS_GetStreamPos( stream_t *stream );
|
||||
void FS_FreeStream( stream_t *stream );
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags );
|
||||
uint Sound_GetApproxWavePlayLen( const char *filepath );
|
||||
qboolean Sound_SupportedFileFormat( const char *fileext );
|
||||
|
||||
@@ -544,12 +535,10 @@ void Host_WriteServerConfig( const char *name );
|
||||
void Host_WriteOpenGLConfig( void );
|
||||
void Host_WriteVideoConfig( void );
|
||||
void Host_WriteConfig( void );
|
||||
qboolean Host_IsLocalGame( void );
|
||||
qboolean Host_IsLocalClient( void );
|
||||
void Host_ShutdownServer( void );
|
||||
void Host_Error( const char *error, ... ) _format( 1 );
|
||||
void Host_ValidateEngineFeatures( uint32_t features );
|
||||
void Host_Frame( float time );
|
||||
void Host_Frame( double time );
|
||||
void Host_Credits( void );
|
||||
|
||||
//
|
||||
@@ -560,7 +549,7 @@ void COM_NewGame( char const *pMapName );
|
||||
void COM_LoadLevel( char const *pMapName, qboolean background );
|
||||
void COM_LoadGame( char const *pSaveFileName );
|
||||
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background );
|
||||
void COM_Frame( float time );
|
||||
void COM_Frame( double time );
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
@@ -591,7 +580,7 @@ qboolean SV_Active( void );
|
||||
char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize );
|
||||
void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput );
|
||||
int COM_SaveFile( const char *filename, const void *data, int len );
|
||||
byte* COM_LoadFileForMe( const char *filename, int *pLength );
|
||||
byte *COM_LoadFileForMe( const char *filename, int *pLength ) MALLOC_LIKE( free, 1 );
|
||||
qboolean COM_IsSafeFileToDownload( const char *filename );
|
||||
cvar_t *pfnCVarGetPointer( const char *szVarName );
|
||||
int pfnDrawConsoleString( int x, int y, char *string );
|
||||
@@ -686,7 +675,6 @@ struct physent_s;
|
||||
struct sv_client_s;
|
||||
typedef struct sizebuf_s sizebuf_t;
|
||||
qboolean CL_IsInGame( void );
|
||||
qboolean CL_IsInMenu( void );
|
||||
qboolean CL_IsInConsole( void );
|
||||
qboolean CL_IsThirdPerson( void );
|
||||
qboolean CL_IsIntermission( void );
|
||||
@@ -695,7 +683,7 @@ 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 );
|
||||
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
|
||||
struct cmd_s *Cmd_GetFirstFunctionHandle( void );
|
||||
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
|
||||
struct cmdalias_s *Cmd_AliasGetList( void );
|
||||
@@ -704,8 +692,9 @@ void Log_Printf( const char *fmt, ... ) _format( 1 );
|
||||
void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 );
|
||||
void SV_BroadcastPrintf( struct sv_client_s *ignore, const char *fmt, ... ) _format( 2 );
|
||||
void CL_ClearStaticEntities( void );
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position );
|
||||
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
|
||||
void CL_UpdateInfo( const char *key, const char *value );
|
||||
void CL_HudMessage( const char *pMessage );
|
||||
const char *CL_MsgInfo( int cmd );
|
||||
void SV_DrawDebugTriangles( void );
|
||||
@@ -779,6 +768,18 @@ int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCom
|
||||
char *va( const char *format, ... ) _format( 1 );
|
||||
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer );
|
||||
|
||||
static inline qboolean Host_IsLocalGame( void )
|
||||
{
|
||||
if( SV_Active( ))
|
||||
return SV_GetMaxClients() == 1 ? true : false;
|
||||
return CL_GetMaxClients() == 1 ? true : false;
|
||||
}
|
||||
|
||||
static inline qboolean Host_IsLocalClient( void )
|
||||
{
|
||||
return CL_Initialized( ) && SV_Initialized( ) ? true : false;
|
||||
}
|
||||
|
||||
// soundlib shared exports
|
||||
qboolean S_Init( void );
|
||||
void S_Shutdown( void );
|
||||
|
||||
@@ -465,7 +465,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
t = FS_Search( va( "%s%s*.*", DEFAULT_SOUNDPATH, s ), true, false );
|
||||
if( !t ) return false;
|
||||
|
||||
Q_strncpy( matchbuf, t->filenames[0] + sizeof( DEFAULT_SOUNDPATH ) - 1, MAX_STRING );
|
||||
Q_strncpy( matchbuf, t->filenames[0] + sizeof( DEFAULT_SOUNDPATH ) - 1, sizeof( matchbuf ));
|
||||
COM_StripExtension( matchbuf );
|
||||
if( completedname && length )
|
||||
Q_strncpy( completedname, matchbuf, length );
|
||||
@@ -478,7 +478,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
if( Q_stricmp( ext, "wav" ) && Q_stricmp( ext, "mp3" ))
|
||||
continue;
|
||||
|
||||
Q_strncpy( matchbuf, t->filenames[i] + sizeof( DEFAULT_SOUNDPATH ) - 1, MAX_STRING );
|
||||
Q_strncpy( matchbuf, t->filenames[i] + sizeof( DEFAULT_SOUNDPATH ) - 1, sizeof( matchbuf ));
|
||||
COM_StripExtension( matchbuf );
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
numsounds++;
|
||||
@@ -585,7 +585,7 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Con_Printf( "\n^3 %lu keys found.\n", numkeys );
|
||||
Con_Printf( "\n^3 %zu keys found.\n", numkeys );
|
||||
|
||||
if( completedname && length )
|
||||
{
|
||||
@@ -764,14 +764,14 @@ static qboolean Cmd_GetGamesList( const char *s, char *completedname, int length
|
||||
}
|
||||
|
||||
if( !numgamedirs ) return false;
|
||||
Q_strncpy( matchbuf, gamedirs[0], MAX_STRING );
|
||||
Q_strncpy( matchbuf, gamedirs[0], sizeof( matchbuf ));
|
||||
if( completedname && length )
|
||||
Q_strncpy( completedname, matchbuf, length );
|
||||
if( numgamedirs == 1 ) return true;
|
||||
|
||||
for( i = 0; i < numgamedirs; i++ )
|
||||
{
|
||||
Q_strncpy( matchbuf, gamedirs[i], MAX_STRING );
|
||||
Q_strncpy( matchbuf, gamedirs[i], sizeof( matchbuf ));
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
@@ -825,14 +825,14 @@ static qboolean Cmd_GetCDList( const char *s, char *completedname, int length )
|
||||
}
|
||||
|
||||
if( !numcdcommands ) return false;
|
||||
Q_strncpy( matchbuf, cdcommands[0], MAX_STRING );
|
||||
Q_strncpy( matchbuf, cdcommands[0], sizeof( matchbuf ));
|
||||
if( completedname && length )
|
||||
Q_strncpy( completedname, matchbuf, length );
|
||||
if( numcdcommands == 1 ) return true;
|
||||
|
||||
for( i = 0; i < numcdcommands; i++ )
|
||||
{
|
||||
Q_strncpy( matchbuf, cdcommands[i], MAX_STRING );
|
||||
Q_strncpy( matchbuf, cdcommands[i], sizeof( matchbuf ));
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
@@ -866,7 +866,7 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
||||
return true; // exist
|
||||
|
||||
// setup mpfilter
|
||||
size = Q_snprintf( mpfilter, sizeof( mpfilter ), "maps/%s", GI->mp_filter );
|
||||
Q_snprintf( mpfilter, sizeof( mpfilter ), "maps/%s", GI->mp_filter );
|
||||
t = FS_Search( "maps/*.bsp", false, onlyingamedir );
|
||||
|
||||
if( !t )
|
||||
@@ -900,13 +900,11 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
||||
|
||||
if( f )
|
||||
{
|
||||
int num_spawnpoints = 0;
|
||||
dheader_t *header;
|
||||
dlump_t entities;
|
||||
qboolean have_spawnpoints = false;
|
||||
dlump_t entities;
|
||||
|
||||
memset( buf, 0, MAX_SYSPATH );
|
||||
FS_Read( f, buf, MAX_SYSPATH );
|
||||
header = (dheader_t *)buf;
|
||||
|
||||
// check all the lumps and some other errors
|
||||
if( !Mod_TestBmodelLumps( f, t->filenames[i], buf, true, &entities ))
|
||||
@@ -937,13 +935,24 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
||||
char token[MAX_TOKEN];
|
||||
qboolean worldspawn = true;
|
||||
|
||||
Q_strncpy( message, "No Title", MAX_STRING );
|
||||
Q_strncpy( message, "No Title", sizeof( message ));
|
||||
pfile = ents;
|
||||
|
||||
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
||||
{
|
||||
if( token[0] == '}' && worldspawn )
|
||||
{
|
||||
worldspawn = false;
|
||||
|
||||
// if mod has mp_filter set up, then it's a mod that
|
||||
// might not have valid mp_entity set in GI
|
||||
// if mod is multiplayer only, assume all maps are valid
|
||||
if( use_filter || GI->gamemode == GAME_MULTIPLAYER_ONLY )
|
||||
{
|
||||
have_spawnpoints = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( !Q_strcmp( token, "message" ) && worldspawn )
|
||||
{
|
||||
// get the message contents
|
||||
@@ -952,17 +961,23 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
|
||||
else if( !Q_strcmp( token, "classname" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
if( !Q_strcmp( token, GI->mp_entity ) || use_filter )
|
||||
num_spawnpoints++;
|
||||
|
||||
if( !Q_strcmp( token, GI->mp_entity ))
|
||||
{
|
||||
have_spawnpoints = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( num_spawnpoints ) break; // valid map
|
||||
|
||||
if( have_spawnpoints )
|
||||
break; // valid map
|
||||
}
|
||||
Mem_Free( ents );
|
||||
}
|
||||
|
||||
if( f ) FS_Close( f );
|
||||
|
||||
if( num_spawnpoints )
|
||||
if( have_spawnpoints )
|
||||
{
|
||||
// format: mapname "maptitle"\n
|
||||
Q_snprintf( result, sizeof( result ), "%s \"%s\"\n", mapname, message );
|
||||
@@ -1004,6 +1019,7 @@ autocomplete_list_t cmd_list[] =
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
@@ -1186,7 +1202,7 @@ void Con_CompleteCommand( field_t *field )
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
memcpy( &temp, con.completionField, sizeof( field_t ) );
|
||||
temp = *con.completionField;
|
||||
|
||||
// autocomplete second arg
|
||||
if( (Cmd_Argc() >= 2) || ((Cmd_Argc() == 1) && nextcmd) )
|
||||
@@ -1380,7 +1396,7 @@ void Host_WriteConfig( void )
|
||||
f = FS_Open( "config.cfg.new", "w", false );
|
||||
if( f )
|
||||
{
|
||||
Con_Reportf( "Host_WriteConfig()\n" );
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t\tconfig.cfg - archive of cvars\n" );
|
||||
@@ -1463,7 +1479,7 @@ void Host_WriteOpenGLConfig( void )
|
||||
f = FS_Open( va( "%s.new", name ), "w", false );
|
||||
if( f )
|
||||
{
|
||||
Con_Reportf( "Host_WriteGLConfig()\n" );
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t %s - archive of renderer implementation cvars\n", name );
|
||||
@@ -1493,7 +1509,7 @@ void Host_WriteVideoConfig( void )
|
||||
f = FS_Open( "video.cfg.new", "w", false );
|
||||
if( f )
|
||||
{
|
||||
Con_Reportf( "Host_WriteVideoConfig()\n" );
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\t\t\tCopyright XashXT Group & Flying With Gauss %s (C)\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");
|
||||
|
||||
@@ -80,7 +80,7 @@ static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
|
||||
|
||||
static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
|
||||
{
|
||||
char message[1024];
|
||||
char message[8192]; // match *nix Sys_Crash
|
||||
int len = 0;
|
||||
size_t i;
|
||||
HANDLE process = GetCurrentProcess();
|
||||
@@ -92,7 +92,7 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
|
||||
STACKFRAME64 stackframe;
|
||||
DWORD image;
|
||||
|
||||
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT ));
|
||||
context = *pInfo->ContextRecord;
|
||||
|
||||
options = SymGetOptions();
|
||||
options |= SYMOPT_DEBUG;
|
||||
@@ -129,9 +129,29 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
|
||||
stackframe.AddrBStore.Mode = AddrModeFlat;
|
||||
stackframe.AddrStack.Offset = context.IntSp;
|
||||
stackframe.AddrStack.Mode = AddrModeFlat;
|
||||
#elif _M_ARM
|
||||
image = IMAGE_FILE_MACHINE_ARMNT;
|
||||
stackframe.AddrPC.Offset = context.Pc;
|
||||
stackframe.AddrPC.Mode = AddrModeFlat;
|
||||
stackframe.AddrFrame.Offset = context.R11;
|
||||
stackframe.AddrFrame.Mode = AddrModeFlat;
|
||||
stackframe.AddrStack.Offset = context.Sp;
|
||||
stackframe.AddrStack.Mode = AddrModeFlat;
|
||||
#elif _M_ARM64
|
||||
image = IMAGE_FILE_MACHINE_ARM64;
|
||||
stackframe.AddrPC.Offset = context.Pc;
|
||||
stackframe.AddrPC.Mode = AddrModeFlat;
|
||||
stackframe.AddrFrame.Offset = context.Fp;
|
||||
stackframe.AddrFrame.Mode = AddrModeFlat;
|
||||
stackframe.AddrStack.Offset = context.Sp;
|
||||
stackframe.AddrStack.Mode = AddrModeFlat;
|
||||
#elif
|
||||
#error
|
||||
#endif
|
||||
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
|
||||
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
|
||||
|
||||
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n",
|
||||
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
|
||||
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) )
|
||||
@@ -259,6 +279,10 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
|
||||
// check to avoid recursive call
|
||||
host.crashed = true;
|
||||
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif // XASH_SDL
|
||||
|
||||
#if DBGHELP
|
||||
Sys_StackTrace( pInfo );
|
||||
#else
|
||||
@@ -309,7 +333,6 @@ void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
|
||||
oldFilter = SetUnhandledExceptionFilter( Sys_Crash );
|
||||
host.hInst = GetModuleHandle( NULL );
|
||||
}
|
||||
|
||||
void Sys_RestoreCrashHandler( void )
|
||||
|
||||
@@ -16,6 +16,7 @@ GNU General Public License for more details.
|
||||
#include "common.h"
|
||||
#include "custom.h"
|
||||
#include "ref_common.h"
|
||||
#include "hpak.h" // be aware of HPK limits
|
||||
|
||||
static rgbdata_t *CustomDecal_LoadImage( const char *path, void *raw, int size )
|
||||
{
|
||||
@@ -93,7 +94,7 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
|
||||
|
||||
if( FBitSet( flags, FCUST_FROMHPAK ))
|
||||
{
|
||||
if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, pResource, (byte **)&pCust->pBuffer, NULL ))
|
||||
if( !HPAK_GetDataPointer( hpk_custom_file.string, pResource, (byte **)&pCust->pBuffer, NULL ))
|
||||
bError = true;
|
||||
}
|
||||
else
|
||||
@@ -115,11 +116,11 @@ qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResou
|
||||
{
|
||||
if( !FBitSet( flags, FCUST_IGNOREINIT ))
|
||||
{
|
||||
if( pResource->nDownloadSize >= (1 * 1024) && pResource->nDownloadSize <= ( 128 * 1024 ))
|
||||
if( pResource->nDownloadSize >= HPAK_ENTRY_MIN_SIZE && pResource->nDownloadSize <= HPAK_ENTRY_MAX_SIZE )
|
||||
{
|
||||
pCust->bTranslated = true;
|
||||
pCust->nUserData1 = 0;
|
||||
pCust->nUserData2 = 1;
|
||||
pCust->nUserData2 = 7;
|
||||
|
||||
if( !FBitSet( flags, FCUST_WIPEDATA ))
|
||||
pCust->pInfo = CustomDecal_LoadImage( pResource->szFileName, pCust->pBuffer, pCust->resource.nDownloadSize );
|
||||
|
||||
@@ -152,8 +152,10 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
||||
if ( Host_IsDedicated() )
|
||||
{
|
||||
// g-cont. this is a very strange behavior...
|
||||
Info_SetValueForKey( SV_Serverinfo(), var->name, value, MAX_SERVERINFO_STRING ),
|
||||
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", SV_Serverinfo( ));
|
||||
char *info = SV_Serverinfo();
|
||||
|
||||
Info_SetValueForKey( info, var->name, value, MAX_SERVERINFO_STRING ),
|
||||
SV_BroadcastCommand( "fullserverinfo \"%s\"\n", info );
|
||||
}
|
||||
#if !XASH_DEDICATED
|
||||
else
|
||||
@@ -162,8 +164,7 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
||||
return false; // failed to change value
|
||||
|
||||
// time to update server copy of userinfo
|
||||
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", var->name, value );
|
||||
CL_LegacyUpdateInfo();
|
||||
CL_UpdateInfo( var->name, value );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -229,7 +230,7 @@ static const char *Cvar_ValidateString( convar_t *var, const char *value )
|
||||
if( !COM_CheckStringEmpty( szNew ) ) Q_strncpy( szNew, "empty", sizeof( szNew ));
|
||||
}
|
||||
|
||||
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITEPACE ))
|
||||
if( FBitSet( var->flags, FCVAR_NOEXTRAWHITESPACE ))
|
||||
{
|
||||
char *szVal = szNew;
|
||||
int len = 0;
|
||||
@@ -271,6 +272,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
|
||||
@@ -310,17 +320,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++;
|
||||
}
|
||||
|
||||
@@ -792,7 +798,7 @@ void GAME_EXPORT Cvar_Set( const char *var_name, const char *value )
|
||||
if( !var_name )
|
||||
{
|
||||
// there is an error in C code if this happens
|
||||
Con_Printf( "Cvar_Set: passed NULL variable name\n" );
|
||||
Con_Printf( "%s: passed NULL variable name\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -801,7 +807,7 @@ void GAME_EXPORT Cvar_Set( const char *var_name, const char *value )
|
||||
if( !var )
|
||||
{
|
||||
// there is an error in C code if this happens
|
||||
Con_Printf( "Cvar_Set: variable '%s' not found\n", var_name );
|
||||
Con_Printf( "%s: variable '%s' not found\n", __func__, var_name );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -846,7 +852,7 @@ float GAME_EXPORT Cvar_VariableValue( const char *var_name )
|
||||
if( !var_name )
|
||||
{
|
||||
// there is an error in C code if this happens
|
||||
Con_Printf( "Cvar_VariableValue: passed NULL variable name\n" );
|
||||
Con_Printf( "%s: passed NULL variable name\n", __func__ );
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -883,7 +889,7 @@ const char *Cvar_VariableString( const char *var_name )
|
||||
if( !var_name )
|
||||
{
|
||||
// there is an error in C code if this happens
|
||||
Con_Printf( "Cvar_VariableString: passed NULL variable name\n" );
|
||||
Con_Printf( "%s: passed NULL variable name\n", __func__ );
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -953,7 +959,7 @@ static void Cvar_SetGL( const char *name, const char *value )
|
||||
|
||||
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
|
||||
{
|
||||
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_" };
|
||||
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_", "con_", "scr_" };
|
||||
int i;
|
||||
|
||||
if( isPrivileged )
|
||||
@@ -1216,6 +1222,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
|
||||
@@ -1227,19 +1247,88 @@ 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;
|
||||
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 = list;
|
||||
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 );
|
||||
list = 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
|
||||
|
||||
@@ -18,45 +18,18 @@ GNU General Public License for more details.
|
||||
|
||||
#include "cvardef.h"
|
||||
|
||||
#ifdef XASH_64BIT
|
||||
#define CVAR_SENTINEL 0xDEADBEEFDEADBEEF
|
||||
#else
|
||||
#define CVAR_SENTINEL 0xDEADBEEF
|
||||
#endif
|
||||
#define CVAR_CHECK_SENTINEL( cv ) ((uintptr_t)(cv)->next == CVAR_SENTINEL)
|
||||
|
||||
// NOTE: if this is changed, it must be changed in cvardef.h too
|
||||
typedef struct convar_s
|
||||
// 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
|
||||
{
|
||||
// this part shared with cvar_t
|
||||
char *name;
|
||||
char *string;
|
||||
int flags;
|
||||
float value;
|
||||
struct convar_s *next;
|
||||
struct pending_cvar_s *next;
|
||||
|
||||
// this part unique for convar_t
|
||||
char *desc; // variable descrition info
|
||||
char *def_string; // keep pointer to initial value
|
||||
} convar_t;
|
||||
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 internal flags
|
||||
#define FCVAR_RENDERINFO (1<<16) // save to a seperate config called video.cfg
|
||||
#define FCVAR_READ_ONLY (1<<17) // cannot be set by user at all, and can't be requested by CvarGetPointer from game dlls
|
||||
#define FCVAR_EXTENDED (1<<18) // this is convar_t (sets on registration)
|
||||
#define FCVAR_ALLOCATED (1<<19) // this convar_t is fully dynamic allocated (include description)
|
||||
#define FCVAR_VIDRESTART (1<<20) // recreate the window is cvar with this flag was changed
|
||||
#define FCVAR_TEMPORARY (1<<21) // these cvars holds their values and can be unlink in any time
|
||||
#define FCVAR_MOVEVARS (1<<22) // this cvar is a part of movevars_t struct that shared between client and server
|
||||
#define FCVAR_USER_CREATED (1<<23) // created by a set command (dll's used)
|
||||
|
||||
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
|
||||
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
|
||||
|
||||
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) \
|
||||
CVAR_DEFINE( cv, #cv, cvstr, cvflags, cvdesc )
|
||||
|
||||
#ifndef REF_DLL
|
||||
cvar_t *Cvar_GetList( void );
|
||||
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
|
||||
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
|
||||
@@ -81,6 +54,8 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
|
||||
void Cvar_Init( void );
|
||||
void Cvar_PostFSInit( void );
|
||||
void Cvar_Unlink( int group );
|
||||
#endif // REF_DLL
|
||||
|
||||
pending_cvar_t *Cvar_PrepareToUnlink( int group );
|
||||
void Cvar_UnlinkPendingCvars( pending_cvar_t *pending_cvars );
|
||||
|
||||
#endif//CVAR_H
|
||||
|
||||
@@ -39,11 +39,6 @@ qboolean CL_IsInGame( void )
|
||||
return true; // always active for dedicated servers
|
||||
}
|
||||
|
||||
qboolean CL_IsInMenu( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsInConsole( void )
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -16,6 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "library.h"
|
||||
#include "platform/platform.h"
|
||||
@@ -26,6 +27,40 @@ fs_globals_t *FI;
|
||||
static pfnCreateInterface_t fs_pfnCreateInterface;
|
||||
static HINSTANCE fs_hInstance;
|
||||
|
||||
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
|
||||
{
|
||||
return g_fsapi.Search( pattern, caseinsensitive, gamedironly );
|
||||
}
|
||||
|
||||
int FS_Close( file_t *file )
|
||||
{
|
||||
return g_fsapi.Close( file );
|
||||
}
|
||||
|
||||
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
{
|
||||
return g_fsapi.Open( filepath, mode, gamedironly );
|
||||
}
|
||||
|
||||
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
|
||||
{
|
||||
return g_fsapi.LoadFile( path, filesizeptr, gamedironly );
|
||||
}
|
||||
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
{
|
||||
return g_fsapi.LoadDirectFile( path, filesizeptr );
|
||||
}
|
||||
|
||||
static void COM_StripDirectorySlash( char *pname )
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = Q_strlen( pname );
|
||||
if( len > 0 && pname[len - 1] == '/' )
|
||||
pname[len - 1] = 0;
|
||||
}
|
||||
|
||||
void *FS_GetNativeObject( const char *obj )
|
||||
{
|
||||
if( fs_pfnCreateInterface )
|
||||
@@ -49,7 +84,7 @@ static void FS_Path_f_( void )
|
||||
FS_Path_f();
|
||||
}
|
||||
|
||||
static fs_interface_t fs_memfuncs =
|
||||
static const fs_interface_t fs_memfuncs =
|
||||
{
|
||||
Con_Printf,
|
||||
Con_DPrintf,
|
||||
@@ -80,7 +115,7 @@ static void FS_UnloadProgs( void )
|
||||
#define FILESYSTEM_STDIO_DLL "filesystem_stdio." OS_LIB_EXT
|
||||
#endif
|
||||
|
||||
qboolean FS_LoadProgs( void )
|
||||
static qboolean FS_LoadProgs( void )
|
||||
{
|
||||
const char *name = FILESYSTEM_STDIO_DLL;
|
||||
FSAPI GetFSAPI;
|
||||
@@ -89,63 +124,160 @@ qboolean FS_LoadProgs( void )
|
||||
|
||||
if( !fs_hInstance )
|
||||
{
|
||||
Host_Error( "FS_LoadProgs: can't load filesystem library %s: %s\n", name, COM_GetLibraryError() );
|
||||
Sys_Error( "%s: can't load filesystem library %s: %s\n", __func__, name, COM_GetLibraryError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API )))
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't find GetFSAPI entry point in %s\n", name );
|
||||
Sys_Error( "%s: can't find GetFSAPI entry point in %s\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ))
|
||||
if( GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ) != FS_API_VERSION )
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't initialize filesystem API: wrong version\n" );
|
||||
Sys_Error( "%s: can't initialize filesystem API: wrong version\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" )))
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't find CreateInterface entry point in %s\n", name );
|
||||
Sys_Error( "%s: can't find CreateInterface entry point in %s\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
Con_DPrintf( "FS_LoadProgs: filesystem_stdio successfully loaded\n" );
|
||||
|
||||
Con_DPrintf( "%s: filesystem_stdio successfully loaded\n", __func__ );
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean FS_DetermineRootDirectory( char *out, size_t size )
|
||||
{
|
||||
const char *path = getenv( "XASH3D_BASEDIR" );
|
||||
|
||||
if( COM_CheckString( path ))
|
||||
{
|
||||
Q_strncpy( out, path, size );
|
||||
return true;
|
||||
}
|
||||
|
||||
#if TARGET_OS_IOS
|
||||
Q_strncpy( out, IOS_GetDocsDir(), size );
|
||||
return true;
|
||||
#elif XASH_ANDROID && XASH_SDL
|
||||
path = SDL_AndroidGetExternalStoragePath();
|
||||
if( path != NULL )
|
||||
{
|
||||
Q_strncpy( out, path, size );
|
||||
return true;
|
||||
}
|
||||
Sys_Error( "couldn't determine Android external storage path: %s", SDL_GetError( ));
|
||||
return false;
|
||||
#elif XASH_PSVITA
|
||||
if( PSVita_GetBasePath( out, size ))
|
||||
return true;
|
||||
Sys_Error( "couldn't find Xash3D data directory" );
|
||||
return false;
|
||||
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
path = SDL_GetBasePath();
|
||||
if( path != NULL )
|
||||
{
|
||||
Q_strncpy( out, path, size );
|
||||
SDL_free(( void *)path );
|
||||
return true;
|
||||
}
|
||||
|
||||
#if XASH_POSIX || XASH_WIN32
|
||||
if( getcwd( out, size ))
|
||||
return true;
|
||||
Sys_Error( "couldn't determine current directory: %s, getcwd: %s", SDL_GetError(), strerror( errno ));
|
||||
#else // !( XASH_POSIX || XASH_WIN32 )
|
||||
Sys_Error( "couldn't determine current directory: %s", SDL_GetError( ));
|
||||
#endif // !( XASH_POSIX || XASH_WIN32 )
|
||||
return false;
|
||||
#else // generic case
|
||||
if( getcwd( out, size ))
|
||||
return true;
|
||||
|
||||
Sys_Error( "couldn't determine current directory: %s", strerror( errno ));
|
||||
return false;
|
||||
#endif // generic case
|
||||
}
|
||||
|
||||
static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
{
|
||||
const char *env_rodir = getenv( "XASH3D_RODIR" );
|
||||
|
||||
if( _Sys_GetParmFromCmdLine( "-rodir", out, size ))
|
||||
return true;
|
||||
|
||||
if( COM_CheckString( env_rodir ))
|
||||
{
|
||||
Q_strncpy( out, env_rodir, size );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_Init
|
||||
================
|
||||
*/
|
||||
void FS_Init( void )
|
||||
void FS_Init( const char *basedir )
|
||||
{
|
||||
string gamedir;
|
||||
char rodir[MAX_OSPATH], rootdir[MAX_OSPATH];
|
||||
rodir[0] = rootdir[0] = 0;
|
||||
|
||||
if( !FS_DetermineRootDirectory( rootdir, sizeof( rootdir )) || !COM_CheckStringEmpty( rootdir ))
|
||||
{
|
||||
Sys_Error( "couldn't determine current directory (empty string)" );
|
||||
return;
|
||||
}
|
||||
COM_FixSlashes( rootdir );
|
||||
COM_StripDirectorySlash( rootdir );
|
||||
|
||||
FS_DetermineReadOnlyRootDirectory( rodir, sizeof( rodir ));
|
||||
COM_FixSlashes( rodir );
|
||||
COM_StripDirectorySlash( rodir );
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
|
||||
{
|
||||
char *env = getenv( "XASH3D_GAME" );
|
||||
if( env )
|
||||
Q_strncpy( gamedir, env, sizeof( gamedir ));
|
||||
else
|
||||
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
|
||||
}
|
||||
|
||||
FS_LoadProgs();
|
||||
|
||||
// TODO: this function will cause engine to stop in case of fail
|
||||
// when it will have an option to return string error, restore Sys_Error
|
||||
// FIXME: why do we call this function before InitStdio?
|
||||
// because InitStdio immediately scans all available game directories
|
||||
// and this better be reworked at some point
|
||||
g_fsapi.SetCurrentDirectory( rootdir );
|
||||
|
||||
if( !g_fsapi.InitStdio( true, rootdir, basedir, gamedir, rodir ))
|
||||
{
|
||||
Sys_Error( "Can't init filesystem_stdio!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Cmd_AddRestrictedCommand( "fs_rescan", FS_Rescan_f, "rescan filesystem search pathes" );
|
||||
Cmd_AddRestrictedCommand( "fs_path", FS_Path_f_, "show filesystem search pathes" );
|
||||
Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
|
||||
Q_strncpy( gamedir, SI.basedirName, sizeof( gamedir )); // gamedir == basedir
|
||||
if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
|
||||
host.gamedll[0] = 0;
|
||||
|
||||
if( !FS_InitStdio( true, host.rootdir, SI.basedirName, gamedir, host.rodir ))
|
||||
{
|
||||
Host_Error( "Can't init filesystem_stdio!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-dll", SI.gamedll ))
|
||||
SI.gamedll[0] = 0;
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-clientlib", SI.clientlib ))
|
||||
SI.clientlib[0] = 0;
|
||||
if( !Sys_GetParmFromCmdLine( "-clientlib", host.clientlib ))
|
||||
host.clientlib[0] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,11 +290,5 @@ void FS_Shutdown( void )
|
||||
if( g_fsapi.ShutdownStdio )
|
||||
g_fsapi.ShutdownStdio();
|
||||
|
||||
memset( &SI, 0, sizeof( sysinfo_t ));
|
||||
|
||||
FS_UnloadProgs();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ GNU General Public License for more details.
|
||||
#include <SDL.h>
|
||||
#endif // XASH_SDL
|
||||
#include <stdarg.h> // va_args
|
||||
#include <errno.h> // errno
|
||||
#include <string.h> // strerror
|
||||
#if !XASH_WIN32
|
||||
#include <unistd.h> // fork
|
||||
#include <sys/types.h>
|
||||
@@ -29,7 +27,6 @@ GNU General Public License for more details.
|
||||
#if XASH_EMSCRIPTEN
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "base_cmd.h"
|
||||
#include "client.h"
|
||||
@@ -45,7 +42,6 @@ GNU General Public License for more details.
|
||||
|
||||
pfnChangeGame pChangeGame = NULL;
|
||||
host_parm_t host; // host parms
|
||||
sysinfo_t SI;
|
||||
|
||||
#ifdef XASH_ENGINE_TESTS
|
||||
struct tests_stats_s tests_stats;
|
||||
@@ -53,7 +49,7 @@ 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", 0, "framerate in dedicated mode" );
|
||||
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" );
|
||||
@@ -63,9 +59,38 @@ CVAR_DEFINE( host_maxfps, "fps_max", "72", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "host
|
||||
static CVAR_DEFINE_AUTO( host_framerate, "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" );
|
||||
static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
|
||||
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
||||
CVAR_DEFINE_AUTO( host_allow_materials, "0", FCVAR_LATCH|FCVAR_ARCHIVE, "allow texture replacements from materials/ folder" );
|
||||
CVAR_DEFINE( con_gamemaps, "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
|
||||
|
||||
static void Sys_PrintUsage( void )
|
||||
typedef struct feature_message_s
|
||||
{
|
||||
uint32_t mask;
|
||||
const char *msg;
|
||||
const char *arg;
|
||||
} feature_message_t;
|
||||
|
||||
static 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[] =
|
||||
{
|
||||
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
|
||||
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
|
||||
{ ENGINE_LOAD_DELUXEDATA, "Deluxemap Support" },
|
||||
{ ENGINE_PHYSICS_PUSHER_EXT, "Improved MOVETYPE_PUSH" },
|
||||
{ ENGINE_LARGE_LIGHTMAPS, "Large Lightmaps" },
|
||||
{ ENGINE_COMPENSATE_QUAKE_BUG, "Stupid Quake Bug Compensation" },
|
||||
{ ENGINE_IMPROVED_LINETRACE, "Improved Trace Line" },
|
||||
{ ENGINE_COMPUTE_STUDIO_LERP, "Studio MOVETYPE_STEP Lerping" },
|
||||
{ ENGINE_LINEAR_GAMMA_SPACE, "Linear Gamma Space" },
|
||||
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
|
||||
};
|
||||
|
||||
static void Sys_PrintUsage( const char *exename )
|
||||
{
|
||||
string version_str;
|
||||
const char *usage_str;
|
||||
@@ -73,10 +98,14 @@ static void Sys_PrintUsage( void )
|
||||
Q_snprintf( version_str, sizeof( version_str ),
|
||||
XASH_ENGINE_NAME " %i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
|
||||
#if XASH_WIN32
|
||||
#define XASH_EXE "(xash).exe"
|
||||
#if XASH_MESSAGEBOX != MSGBOX_STDERR
|
||||
#if XASH_WIN32
|
||||
#define XASH_EXE "(xash).exe"
|
||||
#else
|
||||
#define XASH_EXE "(xash)"
|
||||
#endif
|
||||
#else
|
||||
#define XASH_EXE "(xash)"
|
||||
#define XASH_EXE "%s"
|
||||
#endif
|
||||
|
||||
#define O( x, y ) " "x" "y"\n"
|
||||
@@ -92,8 +121,9 @@ static void Sys_PrintUsage( void )
|
||||
O("-minidumps ", "enable writing minidumps when game is crashed")
|
||||
#endif
|
||||
O("-rodir <path> ", "set read-only base directory")
|
||||
O("-bugcomp ", "enable precise bug compatibility. Will break games that don't require it")
|
||||
O(" ", "Refer to engine documentation for more info")
|
||||
O("-bugcomp [opts] ", "enable precise bug compatibility")
|
||||
O(" ", "will break games that don't require it")
|
||||
O(" ", "refer to engine documentation for more info")
|
||||
O("-disablehelp ", "disable this message")
|
||||
#if !XASH_DEDICATED
|
||||
O("-dedicated ", "run engine in dedicated mode")
|
||||
@@ -106,7 +136,8 @@ static void Sys_PrintUsage( void )
|
||||
O("-noip6 ", "disable IPv6")
|
||||
O("-ip6 <ip> ", "set IPv6 address")
|
||||
O("-port6 <port> ", "set IPv6 port")
|
||||
O("-clockwindow <cw>", "adjust clockwindow used to ignore client commands to prevent speed hacks")
|
||||
O("-clockwindow <cw>", "adjust clockwindow used to ignore client commands")
|
||||
O(" ", "to prevent speed hacks")
|
||||
|
||||
"\nGame options:\n"
|
||||
O("-game <directory>", "set game directory to start engine with")
|
||||
@@ -162,7 +193,8 @@ static void Sys_PrintUsage( void )
|
||||
#if XASH_MESSAGEBOX != MSGBOX_STDERR
|
||||
Platform_MessageBox( version_str, usage_str, false );
|
||||
#else
|
||||
fprintf( stderr, "%s\n%s", version_str, usage_str );
|
||||
fprintf( stderr, "%s\n", version_str );
|
||||
fprintf( stderr, usage_str, exename );
|
||||
#endif
|
||||
|
||||
Sys_Quit();
|
||||
@@ -191,31 +223,14 @@ void Host_ShutdownServer( void )
|
||||
Host_PrintEngineFeatures
|
||||
================
|
||||
*/
|
||||
static void Host_PrintEngineFeatures( int features )
|
||||
static void Host_PrintFeatures( uint32_t flags, const char *s, feature_message_t *features, size_t size )
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t mask;
|
||||
const char *msg;
|
||||
} features_str[] =
|
||||
{
|
||||
{ ENGINE_WRITE_LARGE_COORD, "Big World Support" },
|
||||
{ ENGINE_QUAKE_COMPATIBLE, "Quake Compatibility" },
|
||||
{ ENGINE_LOAD_DELUXEDATA, "Deluxemap Support" },
|
||||
{ ENGINE_PHYSICS_PUSHER_EXT, "Improved MOVETYPE_PUSH" },
|
||||
{ ENGINE_LARGE_LIGHTMAPS, "Large Lightmaps" },
|
||||
{ ENGINE_COMPENSATE_QUAKE_BUG, "Stupid Quake Bug Compensation" },
|
||||
{ ENGINE_IMPROVED_LINETRACE, "Improved Trace Line" },
|
||||
{ ENGINE_COMPUTE_STUDIO_LERP, "Studio MOVETYPE_STEP Lerping" },
|
||||
{ ENGINE_LINEAR_GAMMA_SPACE, "Linear Gamma Space" },
|
||||
{ ENGINE_STEP_POSHISTORY_LERP, "MOVETYPE_STEP Position History Based Lerping" },
|
||||
};
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( features_str ); i++ )
|
||||
for( i = 0; i < size; i++ )
|
||||
{
|
||||
if( FBitSet( features, features_str[i].mask ))
|
||||
Con_Reportf( "^3EXT:^7 %s is enabled\n", features_str[i].msg );
|
||||
if( FBitSet( flags, features[i].mask ))
|
||||
Con_Printf( "^3%s:^7 %s is enabled\n", s, features[i].msg );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +245,7 @@ void Host_ValidateEngineFeatures( uint32_t features )
|
||||
{
|
||||
uint32_t mask = ENGINE_FEATURES_MASK;
|
||||
|
||||
#if !HOST_DEDICATED
|
||||
#if !XASH_DEDICATED
|
||||
if( !Host_IsDedicated( ) && cls.legacymode )
|
||||
mask = ENGINE_LEGACY_FEATURES_MASK;
|
||||
#endif
|
||||
@@ -243,7 +258,7 @@ void Host_ValidateEngineFeatures( uint32_t features )
|
||||
SetBits( features, ENGINE_STEP_POSHISTORY_LERP );
|
||||
|
||||
// print requested first
|
||||
Host_PrintEngineFeatures( features );
|
||||
Host_PrintFeatures( features, "EXT", engine_features, ARRAYSIZE( engine_features ));
|
||||
|
||||
// now warn about incompatible bits
|
||||
if( FBitSet( features, ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ) == ( ENGINE_STEP_POSHISTORY_LERP|ENGINE_COMPUTE_STUDIO_LERP ))
|
||||
@@ -304,18 +319,6 @@ void Host_EndGame( qboolean abort, const char *message, ... )
|
||||
if( abort ) Host_AbortCurrentFrame ();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Host_AbortCurrentFrame
|
||||
|
||||
aborts the current host frame and goes on with the next one
|
||||
================
|
||||
*/
|
||||
void Host_AbortCurrentFrame( void )
|
||||
{
|
||||
longjmp( host.abortframe, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Host_CalcSleep
|
||||
@@ -323,14 +326,7 @@ Host_CalcSleep
|
||||
*/
|
||||
static int Host_CalcSleep( void )
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
// never sleep in timedemo for benchmarking purposes
|
||||
// also don't sleep with vsync for less lag
|
||||
if( CL_IsTimeDemo( ) || gl_vsync.value )
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if( Host_IsDedicated() )
|
||||
if( Host_IsDedicated( ))
|
||||
{
|
||||
// let the dedicated server some sleep
|
||||
return host_sleeptime.value;
|
||||
@@ -412,7 +408,6 @@ static void Host_Exec_f( void )
|
||||
byte *f;
|
||||
char *txt;
|
||||
fs_offset_t len;
|
||||
const char *arg;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
@@ -420,7 +415,8 @@ static void Host_Exec_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
arg = Cmd_Argv( 1 );
|
||||
Q_strncpy( cfgpath, Cmd_Argv( 1 ), sizeof( cfgpath ));
|
||||
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath )); // append as default
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( !Cmd_CurrentCommandIsPrivileged() )
|
||||
@@ -440,7 +436,7 @@ static void Host_Exec_f( void )
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( unprivilegedWhitelist ); i++ )
|
||||
{
|
||||
if( !Q_strcmp( arg, unprivilegedWhitelist[i] ))
|
||||
if( !Q_strcmp( cfgpath, unprivilegedWhitelist[i] ))
|
||||
{
|
||||
allow = true;
|
||||
break;
|
||||
@@ -449,21 +445,15 @@ static void Host_Exec_f( void )
|
||||
|
||||
if( !allow )
|
||||
{
|
||||
Con_Printf( "exec %s: not privileged or in whitelist\n", arg );
|
||||
Con_Printf( "exec %s: not privileged or in whitelist\n", cfgpath );
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
if( !Q_stricmp( "game.cfg", arg ))
|
||||
{
|
||||
// don't execute game.cfg in singleplayer
|
||||
if( SV_GetMaxClients() == 1 )
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( cfgpath, arg, sizeof( cfgpath ));
|
||||
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath )); // append as default
|
||||
// don't execute game.cfg in singleplayer
|
||||
if( SV_GetMaxClients() == 1 && !Q_stricmp( "game.cfg", cfgpath ))
|
||||
return;
|
||||
|
||||
f = FS_LoadFile( cfgpath, &len, false );
|
||||
if( !f )
|
||||
@@ -472,17 +462,18 @@ static void Host_Exec_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
if( !Q_stricmp( "config.cfg", arg ))
|
||||
if( !Q_stricmp( "config.cfg", cfgpath ))
|
||||
host.config_executed = true;
|
||||
|
||||
// adds \n\0 at end of the file
|
||||
txt = Z_Calloc( len + 2 );
|
||||
memcpy( txt, f, len );
|
||||
Q_strncat( txt, "\n", len + 2 );
|
||||
txt[len] = '\n';
|
||||
txt[len + 1] = '\0';
|
||||
Mem_Free( f );
|
||||
|
||||
if( !host.apply_game_config )
|
||||
Con_Printf( "execing %s\n", arg );
|
||||
Con_Printf( "execing %s\n", Cmd_Argv( 1 ));
|
||||
Cbuf_InsertText( txt );
|
||||
Mem_Free( txt );
|
||||
}
|
||||
@@ -517,33 +508,6 @@ static void Host_Minimize_f( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Host_IsLocalGame
|
||||
|
||||
singleplayer game detect
|
||||
=================
|
||||
*/
|
||||
qboolean Host_IsLocalGame( void )
|
||||
{
|
||||
if( SV_Active( ))
|
||||
{
|
||||
return ( SV_GetMaxClients() == 1 ) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( CL_GetMaxClients() == 1 ) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean Host_IsLocalClient( void )
|
||||
{
|
||||
// only the local client have the active server
|
||||
if( CL_Initialized( ) && SV_Initialized( ))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Host_RegisterDecal
|
||||
@@ -588,10 +552,6 @@ static void Host_InitDecals( void )
|
||||
int i, num_decals = 0;
|
||||
search_t *t;
|
||||
|
||||
// NOTE: only once resource without which engine can't continue work
|
||||
if( !FS_FileExists( "gfx/conchars", false ))
|
||||
Sys_Error( "W_LoadWadFile: couldn't load gfx.wad\n" );
|
||||
|
||||
memset( host.draw_decals, 0, sizeof( host.draw_decals ));
|
||||
|
||||
// lookup all the decals in decals.wad (basedir, gamedir, falldir)
|
||||
@@ -604,7 +564,7 @@ static void Host_InitDecals( void )
|
||||
}
|
||||
|
||||
if( t ) Mem_Free( t );
|
||||
Con_Reportf( "InitDecals: %i decals\n", num_decals );
|
||||
Con_Reportf( "%s: %i decals\n", __func__, num_decals );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -636,7 +596,7 @@ static double Host_CalcFPS( void )
|
||||
{
|
||||
double fps = 0.0;
|
||||
|
||||
if( Host_IsDedicated() )
|
||||
if( Host_IsDedicated( ))
|
||||
{
|
||||
fps = sys_ticrate.value;
|
||||
}
|
||||
@@ -749,7 +709,7 @@ Host_FilterTime
|
||||
Returns false if the time is too short to run a frame
|
||||
===================
|
||||
*/
|
||||
static qboolean Host_FilterTime( float time )
|
||||
static qboolean Host_FilterTime( double time )
|
||||
{
|
||||
static double oldtime;
|
||||
double dt;
|
||||
@@ -779,9 +739,9 @@ static qboolean Host_FilterTime( float time )
|
||||
Host_Frame
|
||||
=================
|
||||
*/
|
||||
void Host_Frame( float time )
|
||||
void Host_Frame( double time )
|
||||
{
|
||||
double t1, t2;
|
||||
double t1;
|
||||
|
||||
// decide the simulation time
|
||||
if( !Host_FilterTime( time ))
|
||||
@@ -799,11 +759,8 @@ void Host_Frame( float time )
|
||||
Host_ClientFrame (); // client frame
|
||||
HTTP_Run(); // both server and client
|
||||
|
||||
t2 = Sys_DoubleTime();
|
||||
|
||||
host.pureframetime = t2 - t1;
|
||||
|
||||
host.framecount++;
|
||||
host.pureframetime = Sys_DoubleTime() - t1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -826,11 +783,11 @@ void GAME_EXPORT Host_Error( const char *error, ... )
|
||||
|
||||
if( host.framecount < 3 )
|
||||
{
|
||||
Sys_Error( "Host_InitError: %s", hosterror1 );
|
||||
Sys_Error( "%sInit: %s", __func__, hosterror1 );
|
||||
}
|
||||
else if( host.framecount == host.errorframe )
|
||||
{
|
||||
Sys_Error( "Host_MultiError: %s", hosterror2 );
|
||||
Sys_Error( "%sMulti: %s", __func__, hosterror2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -838,7 +795,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
|
||||
{
|
||||
UI_SetActiveMenu( false );
|
||||
Key_SetKeyDest( key_console );
|
||||
Con_Printf( "Host_Error: %s", hosterror1 );
|
||||
Con_Printf( "%s: %s", __func__, hosterror1 );
|
||||
}
|
||||
else Platform_MessageBox( "Host Error", hosterror1, true );
|
||||
}
|
||||
@@ -848,12 +805,12 @@ void GAME_EXPORT Host_Error( const char *error, ... )
|
||||
|
||||
if( recursive )
|
||||
{
|
||||
Con_Printf( "Host_RecursiveError: %s", hosterror2 );
|
||||
Con_Printf( "%sRecursive: %s", __func__, hosterror2 );
|
||||
Sys_Error( "%s", hosterror1 );
|
||||
}
|
||||
|
||||
recursive = true;
|
||||
Q_strncpy( hosterror2, hosterror1, MAX_SYSPATH );
|
||||
Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 ));
|
||||
host.errorframe = host.framecount; // to avoid multply calls per frame
|
||||
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 );
|
||||
|
||||
@@ -939,45 +896,112 @@ static void Host_RunTests( int stage )
|
||||
TEST_LIST_1_CLIENT;
|
||||
#endif
|
||||
Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed );
|
||||
error_on_exit = tests_stats.failed > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
Sys_Quit();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t Host_CheckBugcomp( void )
|
||||
{
|
||||
const char *prev, *next;
|
||||
uint32_t flags = 0;
|
||||
string args, arg;
|
||||
size_t i;
|
||||
|
||||
if( !Sys_CheckParm( "-bugcomp" ))
|
||||
return 0;
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && isalpha( args[0] ))
|
||||
{
|
||||
for( prev = args, next = Q_strchrnul( prev, '+' ); ; prev = next + 1, next = Q_strchrnul( prev, '+' ))
|
||||
{
|
||||
Q_strncpy( arg, prev, next - prev + 1 );
|
||||
for( i = 0; i < ARRAYSIZE( bugcomp_features ); i++ )
|
||||
{
|
||||
if( !Q_stricmp( bugcomp_features[i].arg, arg ))
|
||||
{
|
||||
SetBits( flags, bugcomp_features[i].mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == ARRAYSIZE( bugcomp_features ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Unknown bugcomp flag %s\n", arg );
|
||||
Con_Printf( "Valid flags are:\n" );
|
||||
for( i = 0; i < ARRAYSIZE( bugcomp_features ); i++ )
|
||||
Con_Printf( "\t%s: %s\n", bugcomp_features[i].arg, bugcomp_features[i].msg );
|
||||
}
|
||||
|
||||
if( !*next )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// no argument specified -bugcomp just enables everything
|
||||
flags = -1;
|
||||
}
|
||||
|
||||
Host_PrintFeatures( flags, "BUGCOMP", bugcomp_features, ARRAYSIZE( bugcomp_features ));
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void Host_DetermineExecutableName( char *out, size_t size )
|
||||
{
|
||||
#if XASH_WIN32
|
||||
char temp[MAX_SYSPATH];
|
||||
|
||||
if( GetModuleFileName( NULL, temp, sizeof( temp )))
|
||||
COM_FileBase( temp, out, size );
|
||||
#else
|
||||
if( host.argc > 0 )
|
||||
COM_FileBase( host.argv[0], out, size );
|
||||
else
|
||||
Q_strncpy( out, "xash", size );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Host_InitCommon
|
||||
=================
|
||||
*/
|
||||
static void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bChangeGame )
|
||||
static void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bChangeGame, char *exename, size_t exename_size )
|
||||
{
|
||||
char dev_level[4];
|
||||
int developer = DEFAULT_DEV;
|
||||
const char *baseDir;
|
||||
char ticrate[16];
|
||||
int len, i;
|
||||
const char *basedir = progname[0] == '#' ? progname + 1 : progname;
|
||||
char dev_level[4], ticrate[16];
|
||||
int developer = DEFAULT_DEV;
|
||||
|
||||
// some commands may turn engine into infinite loop,
|
||||
// e.g. xash.exe +game xash -game xash
|
||||
// so we clear all cmd_args, but leave dbg states as well
|
||||
Sys_ParseCommandLine( argc, argv );
|
||||
Host_DetermineExecutableName( exename, exename_size );
|
||||
|
||||
if( !Sys_CheckParm( "-disablehelp" ) )
|
||||
if( !Sys_CheckParm( "-disablehelp" ))
|
||||
{
|
||||
if( Sys_CheckParm( "-help" ) || Sys_CheckParm( "-h" ) || Sys_CheckParm( "--help" ) )
|
||||
{
|
||||
Sys_PrintUsage();
|
||||
}
|
||||
if( Sys_CheckParm( "-help" ) || Sys_CheckParm( "-h" ) || Sys_CheckParm( "--help" ))
|
||||
Sys_PrintUsage( exename );
|
||||
}
|
||||
|
||||
if( !Sys_CheckParm( "-noch" ) )
|
||||
if( !Sys_CheckParm( "-noch" ))
|
||||
Sys_SetupCrashHandler();
|
||||
|
||||
#if XASH_DLL_LOADER
|
||||
host.enabledll = !Sys_CheckParm( "-nodll" );
|
||||
#endif
|
||||
|
||||
host.change_game = bChangeGame || Sys_CheckParm( "-changegame" );
|
||||
host.config_executed = false;
|
||||
host.status = HOST_INIT; // initialzation started
|
||||
host.type = HOST_DEDICATED; // predict state
|
||||
#ifndef XASH_DEDICATED
|
||||
if( !Sys_CheckParm( "-dedicated" ))
|
||||
host.type = HOST_NORMAL;
|
||||
#endif
|
||||
|
||||
Memory_Init(); // init memory subsystem
|
||||
|
||||
@@ -985,11 +1009,6 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
|
||||
host.allow_console = DEFAULT_ALLOWCONSOLE;
|
||||
|
||||
// HACKHACK: Quake console is always allowed
|
||||
// TODO: determine if we are running QWrap more reliable
|
||||
if( !host.allow_console && ( Sys_CheckParm( "-console" ) || !Q_stricmp( SI.exeName, "quake" )))
|
||||
host.allow_console = true;
|
||||
|
||||
if( Sys_CheckParm( "-dev" ))
|
||||
{
|
||||
host.allow_console = true;
|
||||
@@ -1010,51 +1029,13 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
#endif
|
||||
|
||||
host.con_showalways = true;
|
||||
|
||||
#if XASH_DEDICATED
|
||||
host.type = HOST_DEDICATED; // predict state
|
||||
#else
|
||||
if( Sys_CheckParm("-dedicated") || progname[0] == '#' )
|
||||
{
|
||||
host.type = HOST_DEDICATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
host.type = HOST_NORMAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// set default gamedir
|
||||
if( progname[0] == '#' )
|
||||
progname++;
|
||||
|
||||
Q_strncpy( SI.exeName, progname, sizeof( SI.exeName ));
|
||||
Q_strncpy( SI.basedirName, progname, sizeof( SI.basedirName ));
|
||||
|
||||
if( Host_IsDedicated() )
|
||||
{
|
||||
Sys_MergeCommandLine( );
|
||||
|
||||
// always enable console for Quake and dedicated
|
||||
if( !host.allow_console && ( Host_IsDedicated() || Sys_CheckParm( "-console" ) || !Q_strnicmp( exename, "quake", 5 )))
|
||||
host.allow_console = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't show console as default
|
||||
if( developer <= DEV_NORMAL )
|
||||
host.con_showalways = false;
|
||||
}
|
||||
|
||||
// member console allowing
|
||||
host.allow_console_init = host.allow_console;
|
||||
|
||||
if( Sys_CheckParm( "-bugcomp" ))
|
||||
{
|
||||
// add argument check here when we add other levels
|
||||
// of bugcompatibility
|
||||
host.bugcomp = BUGCOMP_GOLDSRC;
|
||||
}
|
||||
|
||||
// timeBeginPeriod( 1 ); // a1ba: Do we need this?
|
||||
|
||||
// NOTE: this message couldn't be passed into game console but it doesn't matter
|
||||
@@ -1091,102 +1072,26 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
Host_RunTests( 0 );
|
||||
#endif
|
||||
|
||||
Platform_Init();
|
||||
|
||||
baseDir = getenv( "XASH3D_BASEDIR" );
|
||||
|
||||
if( COM_CheckString( baseDir ) )
|
||||
{
|
||||
Q_strncpy( host.rootdir, baseDir, sizeof( host.rootdir ));
|
||||
}
|
||||
else
|
||||
{
|
||||
#if TARGET_OS_IOS
|
||||
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof( host.rootdir ));
|
||||
#elif XASH_ANDROID && XASH_SDL
|
||||
Q_strncpy( host.rootdir, SDL_AndroidGetExternalStoragePath(), sizeof( host.rootdir ));
|
||||
#elif XASH_PSVITA
|
||||
if ( !PSVita_GetBasePath( host.rootdir, sizeof( host.rootdir )))
|
||||
{
|
||||
Sys_Error( "couldn't find xash3d data directory" );
|
||||
host.rootdir[0] = 0;
|
||||
}
|
||||
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
char *szBasePath = SDL_GetBasePath();
|
||||
if( szBasePath )
|
||||
{
|
||||
Q_strncpy( host.rootdir, szBasePath, sizeof( host.rootdir ));
|
||||
SDL_free( szBasePath );
|
||||
}
|
||||
else
|
||||
{
|
||||
#if XASH_POSIX || XASH_WIN32
|
||||
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
|
||||
Sys_Error( "couldn't determine current directory: %s, getcwd: %s", SDL_GetError(), strerror( errno ));
|
||||
#else
|
||||
Sys_Error( "couldn't determine current directory: %s", SDL_GetError() );
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if( !getcwd( host.rootdir, sizeof( host.rootdir )))
|
||||
{
|
||||
Sys_Error( "couldn't determine current directory: %s", strerror( errno ) );
|
||||
host.rootdir[0] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_WIN32
|
||||
COM_FixSlashes( host.rootdir );
|
||||
#endif
|
||||
|
||||
len = Q_strlen( host.rootdir );
|
||||
|
||||
if( len && host.rootdir[len - 1] == '/' )
|
||||
host.rootdir[len - 1] = 0;
|
||||
|
||||
// get readonly root. The order is: check for arg, then env.
|
||||
// if still not got it, rodir is disabled.
|
||||
host.rodir[0] = '\0';
|
||||
if( !Sys_GetParmFromCmdLine( "-rodir", host.rodir ))
|
||||
{
|
||||
char *roDir = getenv( "XASH3D_RODIR" );
|
||||
|
||||
if( COM_CheckString( roDir ))
|
||||
Q_strncpy( host.rodir, roDir, sizeof( host.rodir ));
|
||||
}
|
||||
|
||||
#if XASH_WIN32
|
||||
COM_FixSlashes( host.rootdir );
|
||||
#endif
|
||||
|
||||
len = Q_strlen( host.rodir );
|
||||
|
||||
if( len && host.rodir[len - 1] == '/' )
|
||||
host.rodir[len - 1] = 0;
|
||||
|
||||
if( !COM_CheckStringEmpty( host.rootdir ))
|
||||
{
|
||||
Sys_Error( "Changing working directory failed (empty working directory)\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
FS_LoadProgs();
|
||||
|
||||
// TODO: this function will cause engine to stop in case of fail
|
||||
// when it will have an option to return string error, restore Sys_Error
|
||||
FS_SetCurrentDirectory( host.rootdir );
|
||||
|
||||
FS_Init();
|
||||
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
|
||||
FS_Init( basedir );
|
||||
|
||||
Sys_InitLog();
|
||||
|
||||
// print bugcompatibility level here, after log was initialized
|
||||
if( host.bugcomp == BUGCOMP_GOLDSRC )
|
||||
// print current developer level to simplify processing users feedback
|
||||
if( developer > 0 )
|
||||
{
|
||||
Con_Printf( "^3BUGCOMP^7: GoldSrc bug-compatibility enabled\n" );
|
||||
int i;
|
||||
|
||||
Con_Printf( "Program args: " S_YELLOW );
|
||||
for( i = 0; i < host.argc; i++ )
|
||||
Con_Printf( "%s ", host.argv[i] );
|
||||
Con_Printf( S_DEFAULT "\n" );
|
||||
|
||||
Con_Printf( "Developer level: " S_YELLOW "%i" S_DEFAULT "\n", developer );
|
||||
}
|
||||
|
||||
host.bugcomp = Host_CheckBugcomp();
|
||||
|
||||
Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
|
||||
Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );
|
||||
Cmd_AddRestrictedCommand( "userconfigd", Host_Userconfigd_f, "execute all scripts from userconfig.d" );
|
||||
@@ -1202,39 +1107,14 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
FS_LoadGameInfo( NULL );
|
||||
Cvar_PostFSInit();
|
||||
|
||||
Q_strncpy( host.gamefolder, GI->gamefolder, sizeof( host.gamefolder ));
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
const char *rcName;
|
||||
switch( i )
|
||||
{
|
||||
case 0: rcName = SI.basedirName; break; // e.g. valve.rc
|
||||
case 1: rcName = SI.exeName; break; // e.g. quake.rc
|
||||
case 2: rcName = host.gamefolder; break; // e.g. game.rc (ran from default launcher)
|
||||
}
|
||||
|
||||
if( FS_FileExists( va( "%s.rc", rcName ), false ))
|
||||
{
|
||||
Q_strncpy( SI.rcName, rcName, sizeof( SI.rcName ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Image_CheckPaletteQ1 ();
|
||||
|
||||
// NOTE: only once resource without which engine can't continue work
|
||||
if( !FS_FileExists( "gfx/conchars", false ))
|
||||
Sys_Error( "%s: couldn't load gfx.wad\n", __func__ );
|
||||
|
||||
Host_InitDecals (); // reload decals
|
||||
|
||||
// DEPRECATED: by FWGS fork
|
||||
#if 0
|
||||
if( GI->secure )
|
||||
{
|
||||
// clear all developer levels when game is protected
|
||||
Cvar_DirectSet( &host_developer, "0" );
|
||||
host.allow_console_init = false;
|
||||
host.con_showalways = false;
|
||||
host.allow_console = false;
|
||||
}
|
||||
#endif
|
||||
HPAK_Init();
|
||||
|
||||
IN_Init();
|
||||
@@ -1258,13 +1138,13 @@ Host_Main
|
||||
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func )
|
||||
{
|
||||
static double oldtime, newtime;
|
||||
string demoname;
|
||||
string demoname, exename;
|
||||
|
||||
host.starttime = Sys_DoubleTime();
|
||||
|
||||
pChangeGame = func; // may be NULL
|
||||
|
||||
Host_InitCommon( argc, argv, progname, bChangeGame );
|
||||
Host_InitCommon( argc, argv, progname, bChangeGame, exename, sizeof( exename ));
|
||||
|
||||
// init commands and vars
|
||||
if( host_developer.value >= DEV_EXTENDED )
|
||||
@@ -1274,6 +1154,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cmd_AddRestrictedCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
|
||||
}
|
||||
|
||||
Cvar_RegisterVariable( &host_allow_materials );
|
||||
Cvar_RegisterVariable( &host_serverstate );
|
||||
Cvar_RegisterVariable( &host_maxfps );
|
||||
Cvar_RegisterVariable( &host_framerate );
|
||||
@@ -1313,21 +1194,25 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
ID_Init();
|
||||
SoundList_Init();
|
||||
|
||||
if( Host_IsDedicated() )
|
||||
if( Host_IsDedicated( ))
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Wcon_InitConsoleCommands ();
|
||||
#endif
|
||||
|
||||
// disable texture replacements for dedicated
|
||||
Cvar_FullSet( "host_allow_materials", "0", FCVAR_READ_ONLY );
|
||||
|
||||
Cmd_AddRestrictedCommand( "quit", Sys_Quit, "quit the game" );
|
||||
Cmd_AddRestrictedCommand( "exit", Sys_Quit, "quit the game" );
|
||||
}
|
||||
else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
|
||||
|
||||
HPAK_CheckIntegrity( CUSTOM_RES_PATH );
|
||||
|
||||
host.errorframe = 0;
|
||||
|
||||
if( progname[0] == '#' )
|
||||
progname++;
|
||||
|
||||
// post initializations
|
||||
switch( host.type )
|
||||
{
|
||||
@@ -1336,8 +1221,14 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Wcon_ShowConsole( false ); // hide console
|
||||
#endif
|
||||
// execute startup config and cmdline
|
||||
Cbuf_AddTextf( "exec %s.rc\n", SI.rcName );
|
||||
if( FS_FileExists( va( "%s.rc", progname ), false )) // e.g. valve.rc
|
||||
Cbuf_AddTextf( "exec %s.rc", progname );
|
||||
else if( FS_FileExists( va( "%s.rc", exename ), false )) // e.g. quake.rc
|
||||
Cbuf_AddTextf( "exec %s.rc", exename );
|
||||
else if( FS_FileExists( va( "%s.rc", GI->gamefolder ), false )) // e.g. game.rc (ran from default launcher)
|
||||
Cbuf_AddTextf( "exec %s.rc", GI->gamefolder );
|
||||
Cbuf_Execute();
|
||||
|
||||
if( !host.config_executed )
|
||||
{
|
||||
Cbuf_AddText( "exec config.cfg\n" );
|
||||
@@ -1369,7 +1260,11 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
host.status = HOST_FRAME;
|
||||
|
||||
if( GameState->nextstate == STATE_RUNFRAME )
|
||||
#if XASH_WIN32 // FIXME: implement autocomplete on *nix
|
||||
Con_Printf( "Type 'map <mapname>' to start game... (TAB-autocomplete is working too)\n" );
|
||||
#else // !XASH_WIN32
|
||||
Con_Printf( "Type 'map <mapname>' to start game...\n" );
|
||||
#endif // !XASH_WIN32
|
||||
|
||||
// execute server.cfg after commandline
|
||||
// so we have a chance to set servercfgfile
|
||||
@@ -1377,6 +1272,9 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cbuf_Execute();
|
||||
}
|
||||
|
||||
// check after all configs were executed
|
||||
HPAK_CheckIntegrity( hpk_custom_file.string );
|
||||
|
||||
// main window message loop
|
||||
while( !host.crashed )
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@ GNU General Public License for more details.
|
||||
#include "common.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
static jmp_buf g_abortframe;
|
||||
|
||||
void COM_InitHostState( void )
|
||||
{
|
||||
memset( GameState, 0, sizeof( game_status_t ));
|
||||
@@ -58,6 +60,9 @@ void COM_NewGame( char const *pMapName )
|
||||
GameState->loadGame = false;
|
||||
GameState->newGame = true;
|
||||
|
||||
if( !SV_Active( ))
|
||||
CL_Disconnect( ); // disconnect from current online game
|
||||
|
||||
SV_ShutdownGame(); // exit from current game
|
||||
}
|
||||
|
||||
@@ -77,6 +82,9 @@ void COM_LoadLevel( char const *pMapName, qboolean background )
|
||||
GameState->loadGame = false;
|
||||
GameState->newGame = false;
|
||||
|
||||
if( !SV_Active( ))
|
||||
CL_Disconnect( ); // disconnect from current online game
|
||||
|
||||
SV_ShutdownGame(); // exit from current game
|
||||
}
|
||||
|
||||
@@ -93,6 +101,9 @@ void COM_LoadGame( char const *pMapName )
|
||||
GameState->backgroundMap = false;
|
||||
GameState->newGame = false;
|
||||
GameState->loadGame = true;
|
||||
|
||||
if( !SV_Active( ))
|
||||
CL_Disconnect( ); // disconnect from current online game
|
||||
}
|
||||
|
||||
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background )
|
||||
@@ -137,7 +148,7 @@ static void Host_ShutdownGame( void )
|
||||
}
|
||||
}
|
||||
|
||||
static void Host_RunFrame( float time )
|
||||
static void Host_RunFrame( double time )
|
||||
{
|
||||
// at this time, we don't need to get events from OS on dedicated
|
||||
#if !XASH_DEDICATED
|
||||
@@ -168,11 +179,23 @@ static void Host_RunFrame( float time )
|
||||
}
|
||||
}
|
||||
|
||||
void COM_Frame( float time )
|
||||
/*
|
||||
================
|
||||
Host_AbortCurrentFrame
|
||||
|
||||
aborts the current host frame and goes on with the next one
|
||||
================
|
||||
*/
|
||||
void Host_AbortCurrentFrame( void )
|
||||
{
|
||||
longjmp( g_abortframe, 1 );
|
||||
}
|
||||
|
||||
void COM_Frame( double time )
|
||||
{
|
||||
int loopCount = 0;
|
||||
|
||||
if( setjmp( host.abortframe ))
|
||||
if( setjmp( g_abortframe ))
|
||||
return;
|
||||
|
||||
while( 1 )
|
||||
|
||||
@@ -17,8 +17,6 @@ GNU General Public License for more details.
|
||||
#include "hpak.h"
|
||||
|
||||
#define HPAK_MAX_ENTRIES 0x8000
|
||||
#define HPAK_ENTRY_MIN_SIZE (512)
|
||||
#define HPAK_ENTRY_MAX_SIZE (128 * 1024)
|
||||
|
||||
typedef struct hash_pack_queue_s
|
||||
{
|
||||
@@ -29,11 +27,17 @@ typedef struct hash_pack_queue_s
|
||||
struct hash_pack_queue_s *next;
|
||||
} hash_pack_queue_t;
|
||||
|
||||
static CVAR_DEFINE_AUTO( hpk_maxsize, "4", FCVAR_ARCHIVE, "set limit by size for all HPK-files ( 0 - unlimited )" );
|
||||
static CVAR_DEFINE( hpk_maxsize, "hpk_max_size", "64", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "set limit by size for all HPK-files in megabytes ( 0 - unlimited )" );
|
||||
CVAR_DEFINE_AUTO( hpk_custom_file, "custom.hpk", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "set custom path for players customizations cache file" );
|
||||
static hash_pack_queue_t *gp_hpak_queue = NULL;
|
||||
static hpak_header_t hash_pack_header;
|
||||
static hpak_info_t hash_pack_info;
|
||||
|
||||
static void HPAK_MaxSize_f( void )
|
||||
{
|
||||
Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" );
|
||||
}
|
||||
|
||||
static const char *HPAK_TypeFromIndex( int type )
|
||||
{
|
||||
switch( type )
|
||||
@@ -73,7 +77,7 @@ static void HPAK_AddToQueue( const char *name, resource_t *pResource, void *data
|
||||
|
||||
if( data != NULL ) memcpy( p->data, data, p->size );
|
||||
else if( f != NULL ) FS_Read( f, p->data, p->size );
|
||||
else Host_Error( "HPAK_AddToQueue: data == NULL.\n" );
|
||||
else Host_Error( "%s: data == NULL.\n", __func__ );
|
||||
|
||||
p->next = gp_hpak_queue;
|
||||
gp_hpak_queue = p;
|
||||
@@ -116,7 +120,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
|
||||
fout = FS_Open( pakname, "wb", true );
|
||||
if( !fout )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_CreatePak: can't write %s.\n", pakname );
|
||||
Con_DPrintf( S_ERROR "%s: can't write %s.\n", __func__, pakname );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,7 +149,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
|
||||
|
||||
if( memcmp( md5, pResource->rgucMD5_hash, 16 ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_CreatePak: bad checksum for %s. Ignored\n", pakname );
|
||||
Con_DPrintf( S_ERROR "%s: bad checksum for %s. Ignored\n", __func__, pakname );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -246,7 +250,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
|
||||
if( memcmp( md5, pResource->rgucMD5_hash, 16 ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_AddLump: bad checksum for %s. Ignored\n", pResource->szFileName );
|
||||
Con_DPrintf( S_ERROR "%s: bad checksum for %s. Ignored\n", __func__, pResource->szFileName );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -275,7 +279,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
|
||||
if( !file_dst )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_AddLump: couldn't open %s.\n", srcname );
|
||||
Con_DPrintf( S_ERROR "%s: couldn't open %s.\n", __func__, srcname );
|
||||
FS_Close( file_src );
|
||||
return;
|
||||
}
|
||||
@@ -286,7 +290,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
if( hash_pack_header.version != IDHPAK_VERSION )
|
||||
{
|
||||
// we don't check the HPAK bit for some reason.
|
||||
Con_DPrintf( S_ERROR "HPAK_AddLump: %s does not have a valid header.\n", srcname );
|
||||
Con_DPrintf( S_ERROR "%s: %s does not have a valid header.\n", __func__, srcname );
|
||||
FS_Close( file_src );
|
||||
FS_Close( file_dst );
|
||||
return;
|
||||
@@ -301,7 +305,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
|
||||
if( srcpak.count < 1 || srcpak.count > HPAK_MAX_ENTRIES )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_AddLump: %s contain too many lumps.\n", srcname );
|
||||
Con_DPrintf( S_ERROR "%s: %s contain too many lumps.\n", __func__, srcname );
|
||||
FS_Close( file_src );
|
||||
FS_Close( file_dst );
|
||||
return;
|
||||
@@ -400,7 +404,8 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
f = FS_Open( pakname, "rb", true );
|
||||
if( !f )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Couldn't find %s.\n", pakname );
|
||||
if( !quiet )
|
||||
Con_DPrintf( S_ERROR "Couldn't find %s.\n", pakname );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -409,7 +414,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
FS_Read( f, &hdr, sizeof( hdr ));
|
||||
if( hdr.ident != IDHPAKHEADER || hdr.version != IDHPAK_VERSION )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s does not have a valid HPAK header.\n", pakname );
|
||||
Con_DPrintf( S_ERROR "%s: %s does not have a valid HPAK header.\n", __func__, pakname );
|
||||
FS_Close( f );
|
||||
if( delete ) FS_Delete( pakname );
|
||||
return false;
|
||||
@@ -420,7 +425,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
|
||||
if( num_lumps < 1 || num_lumps > HPAK_MAX_ENTRIES )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s has too many lumps %u.\n", pakname, num_lumps );
|
||||
Con_DPrintf( S_ERROR "%s: %s has too many lumps %u.\n", __func__, pakname, num_lumps );
|
||||
FS_Close( f );
|
||||
if( delete ) FS_Delete( pakname );
|
||||
return false;
|
||||
@@ -438,7 +443,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
if( dataDir[i].disksize < HPAK_ENTRY_MIN_SIZE || dataDir[i].disksize > HPAK_ENTRY_MAX_SIZE )
|
||||
{
|
||||
// odd max size
|
||||
Con_DPrintf( S_ERROR "HPAK_ValidatePak: lump %i has invalid size %s\n", i, Q_pretifymem( dataDir[i].disksize, 2 ));
|
||||
Con_DPrintf( S_ERROR "%s: lump %i has invalid size %s\n", __func__, i, Q_pretifymem( dataDir[i].disksize, 2 ));
|
||||
Mem_Free( dataDir );
|
||||
FS_Close( f );
|
||||
if( delete ) FS_Delete( pakname );
|
||||
@@ -466,7 +471,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
{
|
||||
if( quiet )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s has invalid checksum.\n", pakname );
|
||||
Con_DPrintf( S_ERROR "%s: %s has invalid checksum.\n", __func__, pakname );
|
||||
Mem_Free( dataPak );
|
||||
Mem_Free( dataDir );
|
||||
FS_Close( f );
|
||||
@@ -516,7 +521,7 @@ void HPAK_CheckSize( const char *filename )
|
||||
Q_strncpy( pakname, filename, sizeof( pakname ));
|
||||
COM_ReplaceExtension( pakname, ".hpk", sizeof( pakname ));
|
||||
|
||||
if( FS_FileSize( pakname, false ) > ( maxsize * 1048576 ))
|
||||
if( FS_FileSize( pakname, false ) > ( maxsize * 1024 * 1024 ))
|
||||
{
|
||||
Con_Printf( "Server: Size of %s > %f MB, deleting.\n", filename, hpk_maxsize.value );
|
||||
Log_Printf( "Server: Size of %s > %f MB, deleting.\n", filename, hpk_maxsize.value );
|
||||
@@ -707,7 +712,7 @@ qboolean HPAK_GetDataPointer( const char *filename, resource_t *pResource, byte
|
||||
|
||||
if( directory.count < 1 || directory.count > HPAK_MAX_ENTRIES )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "HPAK_GetDataPointer: %s has too many lumps %u.\n", filename, directory.count );
|
||||
Con_DPrintf( S_ERROR "%s: %s has too many lumps %u.\n", __func__, filename, directory.count );
|
||||
FS_Close( f );
|
||||
return false;
|
||||
}
|
||||
@@ -1100,7 +1105,9 @@ void HPAK_Init( void )
|
||||
Cmd_AddRestrictedCommand( "hpkremove", HPAK_Remove_f, "remove specified file from HPK-file" );
|
||||
Cmd_AddRestrictedCommand( "hpkval", HPAK_Validate_f, "validate specified HPK-file" );
|
||||
Cmd_AddRestrictedCommand( "hpkextract", HPAK_Extract_f, "extract all lumps from specified HPK-file" );
|
||||
Cmd_AddRestrictedCommand( "hpk_maxsize", HPAK_MaxSize_f, "deprecation notice for hpk_maxsize" );
|
||||
Cvar_RegisterVariable( &hpk_maxsize );
|
||||
Cvar_RegisterVariable( &hpk_custom_file );
|
||||
|
||||
gp_hpak_queue = NULL;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ GNU General Public License for more details.
|
||||
|
||||
#include "custom.h"
|
||||
|
||||
#define HPAK_ENTRY_MIN_SIZE (512)
|
||||
#define HPAK_ENTRY_MAX_SIZE (256 * 1024)
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
.HPK archive format (Hash PAK - HPK)
|
||||
@@ -64,7 +67,7 @@ typedef struct dresource_s
|
||||
} dresource_t;
|
||||
#pragma pack( pop )
|
||||
|
||||
STATIC_ASSERT( sizeof( dresource_t ) == 136, "invalid dresource_t size, HPAKs won't be compatible (no custom logo in multiplayer!)" );
|
||||
STATIC_CHECK_SIZEOF( dresource_t, 136, 136 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -73,6 +76,8 @@ typedef struct
|
||||
int infotableofs;
|
||||
} hpak_header_t;
|
||||
|
||||
STATIC_CHECK_SIZEOF( hpak_header_t, 12, 12 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dresource_t resource;
|
||||
@@ -80,6 +85,8 @@ typedef struct
|
||||
int disksize;
|
||||
} hpak_lump_t;
|
||||
|
||||
STATIC_CHECK_SIZEOF( hpak_lump_t, 144, 144 );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int count;
|
||||
|
||||
@@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "common.h"
|
||||
#include <fcntl.h>
|
||||
#if !XASH_WIN32
|
||||
@@ -104,7 +105,7 @@ static void ID_BloomFilter_f( void )
|
||||
for( i = 1; i < Cmd_Argc(); i++ )
|
||||
value |= BloomFilter_ProcessStr( Cmd_Argv( i ) );
|
||||
|
||||
Msg( "%d %016llX\n", BloomFilter_Weight( value ), value );
|
||||
Msg( "%d %016"PRIX64"\n", BloomFilter_Weight( value ), value );
|
||||
|
||||
// test
|
||||
// for( i = 1; i < Cmd_Argc(); i++ )
|
||||
@@ -283,7 +284,7 @@ static void ID_TestCPUInfo_f( void )
|
||||
bloomfilter_t value = 0;
|
||||
|
||||
if( ID_ProcessCPUInfo( &value ) )
|
||||
Msg( "Got %016llX\n", value );
|
||||
Msg( "Got %016"PRIX64"\n", value );
|
||||
else
|
||||
Msg( "Could not get serial\n" );
|
||||
}
|
||||
@@ -555,7 +556,7 @@ static uint ID_CheckRawId( bloomfilter_t filter )
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
Msg( "ID_CheckRawId: %d\n", count );
|
||||
Msg( "%s: %d\n", __func__, count );
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
@@ -575,7 +576,7 @@ static void ID_Check( void )
|
||||
{
|
||||
id = 0;
|
||||
#if 0
|
||||
Msg( "ID_Check(): fail %d\n", weight );
|
||||
Msg( "%s: fail %d\n", __func__, weight );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -583,7 +584,7 @@ static void ID_Check( void )
|
||||
if( ID_CheckRawId( id ) < mincount )
|
||||
id = 0;
|
||||
#if 0
|
||||
Msg( "ID_Check(): success %d\n", weight );
|
||||
Msg( "%s: success %d\n", __func__, weight );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -621,7 +622,7 @@ void ID_Init( void )
|
||||
#endif
|
||||
|
||||
#if XASH_ANDROID && !XASH_DEDICATED
|
||||
sscanf( Android_LoadID(), "%016llX", &id );
|
||||
sscanf( Android_LoadID(), "%016"PRIX64, &id );
|
||||
if( id )
|
||||
{
|
||||
id ^= SYSTEM_XOR_MASK;
|
||||
@@ -633,7 +634,7 @@ void ID_Init( void )
|
||||
CHAR szBuf[MAX_PATH];
|
||||
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
|
||||
|
||||
sscanf(szBuf, "%016llX", &id);
|
||||
sscanf(szBuf, "%016"PRIX64, &id);
|
||||
id ^= SYSTEM_XOR_MASK;
|
||||
ID_Check();
|
||||
}
|
||||
@@ -649,7 +650,7 @@ void ID_Init( void )
|
||||
cfg = fopen( va( "%s/.xash_id", home ), "r" );
|
||||
if( cfg )
|
||||
{
|
||||
if( fscanf( cfg, "%016llX", &id ) > 0 )
|
||||
if( fscanf( cfg, "%016"PRIX64, &id ) > 0 )
|
||||
{
|
||||
id ^= SYSTEM_XOR_MASK;
|
||||
ID_Check();
|
||||
@@ -664,7 +665,7 @@ void ID_Init( void )
|
||||
const char *buf = (const char*) FS_LoadFile( ".xash_id", NULL, false );
|
||||
if( buf )
|
||||
{
|
||||
sscanf( buf, "%016llX", &id );
|
||||
sscanf( buf, "%016"PRIX64, &id );
|
||||
id ^= GAME_XOR_MASK;
|
||||
ID_Check();
|
||||
}
|
||||
@@ -680,11 +681,11 @@ void ID_Init( void )
|
||||
Q_snprintf( &id_md5[i*2], sizeof( id_md5 ) - i * 2, "%02hhx", md5[i] );
|
||||
|
||||
#if XASH_ANDROID && !XASH_DEDICATED
|
||||
Android_SaveID( va("%016llX", id^SYSTEM_XOR_MASK ) );
|
||||
Android_SaveID( va("%016"PRIX64, id^SYSTEM_XOR_MASK ) );
|
||||
#elif XASH_WIN32
|
||||
{
|
||||
CHAR Buf[MAX_PATH];
|
||||
sprintf( Buf, "%016llX", id^SYSTEM_XOR_MASK );
|
||||
sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK );
|
||||
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
||||
}
|
||||
#else
|
||||
@@ -699,14 +700,14 @@ void ID_Init( void )
|
||||
cfg = fopen( va( "%s/.xash_id", home ), "w" );
|
||||
if( cfg )
|
||||
{
|
||||
fprintf( cfg, "%016llX", id^SYSTEM_XOR_MASK );
|
||||
fprintf( cfg, "%016"PRIX64, id^SYSTEM_XOR_MASK );
|
||||
fclose( cfg );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
FS_WriteFile( ".xash_id", va("%016llX", id^GAME_XOR_MASK), 16 );
|
||||
FS_WriteFile( ".xash_id", va("%016"PRIX64, id^GAME_XOR_MASK), 16 );
|
||||
#if 0
|
||||
Msg("MD5 id: %s\nRAW id:%016llX\n", id_md5, id );
|
||||
Msg("MD5 id: %s\nRAW id:%016"PRIX64"\n", id_md5, id );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -103,17 +103,18 @@ typedef struct imglib_s
|
||||
#define IMAGE_MAXHEIGHT 8192
|
||||
#define LUMP_MAXWIDTH 1024 // WorldCraft limits
|
||||
#define LUMP_MAXHEIGHT 1024
|
||||
#define PLDECAL_MAXWIDTH 512
|
||||
#define PLDECAL_MAXHEIGHT 512
|
||||
#define PLDECAL_MAXWIDTH 768 // total of ~2mb uncompressed rgba data
|
||||
#define PLDECAL_MAXHEIGHT 768
|
||||
|
||||
enum
|
||||
{
|
||||
LUMP_NORMAL = 0, // no alpha
|
||||
LUMP_MASKED, // 1-bit alpha channel masked texture
|
||||
LUMP_GRADIENT, // gradient image (decals)
|
||||
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
|
||||
LUMP_HALFLIFE, // get predefined half-life palette
|
||||
LUMP_QUAKE1 // get predefined quake palette
|
||||
LUMP_NORMAL = 0, // no alpha
|
||||
LUMP_MASKED, // 1-bit alpha channel masked texture
|
||||
LUMP_GRADIENT, // gradient image (decals)
|
||||
LUMP_EXTENDED, // bmp images have extened palette with alpha-channel
|
||||
LUMP_HALFLIFE, // get predefined half-life palette
|
||||
LUMP_QUAKE1, // get predefined quake palette
|
||||
LUMP_TEXGAMMA, // apply texgamma on top of palette, for half-life mips
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -35,7 +35,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( filesize < sizeof( bhdr ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "Image_LoadBMP: %s have incorrect file size %li should be greater than %li (header)\n", name, filesize, sizeof( bhdr ) );
|
||||
Con_Reportf( S_ERROR "%s: %s have incorrect file size %li should be greater than %zu (header)\n", __func__, name, (long)filesize, sizeof( bhdr ));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -49,13 +49,13 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( memcmp( bhdr.id, "BM", 2 ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadBMP: only Windows-style BMP files supported (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: only Windows-style BMP files supported (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!( bhdr.bitmapHeaderSize == 40 || bhdr.bitmapHeaderSize == 108 || bhdr.bitmapHeaderSize == 124 ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadBMP: %s have non-standard header size %i\n", name, bhdr.bitmapHeaderSize );
|
||||
Con_DPrintf( S_ERROR "%s: %s have non-standard header size %i\n", __func__, name, bhdr.bitmapHeaderSize );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
if( bhdr.fileSize != filesize )
|
||||
{
|
||||
// Sweet Half-Life issues. splash.bmp have bogus filesize
|
||||
Con_Reportf( S_WARN "Image_LoadBMP: %s have incorrect file size %li should be %i\n", name, filesize, bhdr.fileSize );
|
||||
Con_Reportf( S_WARN "%s: %s have incorrect file size %li should be %i\n", __func__, name, (long)filesize, bhdr.fileSize );
|
||||
}
|
||||
|
||||
// bogus compression? Only non-compressed supported.
|
||||
@@ -71,7 +71,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
{
|
||||
if( bhdr.bitsPerPixel != 32 || bhdr.compression != BI_BITFIELDS )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadBMP: only uncompressed BMP files supported (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: only uncompressed BMP files supported (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
estimatedSize = ( buf_p - buffer ) + cbPalBytes;
|
||||
if( filesize < estimatedSize )
|
||||
{
|
||||
Con_Reportf( S_ERROR "Image_LoadBMP: %s have incorrect file size %li should be greater than %li (palette)\n", name, filesize, estimatedSize );
|
||||
Con_Reportf( S_ERROR "%s: %s have incorrect file size %li should be greater than %li (palette)\n", __func__, name, (long)filesize, (long)estimatedSize );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
image.palette = NULL;
|
||||
}
|
||||
|
||||
Con_Reportf( S_ERROR "Image_LoadBMP: %s have incorrect file size %li should be greater than %li (pixels)\n", name, filesize, estimatedSize );
|
||||
Con_Reportf( S_ERROR "%s: %s have incorrect file size %li should be greater than %li (pixels)\n", __func__, name, (long)filesize, (long)estimatedSize );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ static uint Image_DXTCalcSize( const char *name, dds_t *hdr, size_t filesize )
|
||||
|
||||
if( filesize != buffsize ) // main check
|
||||
{
|
||||
Con_DPrintf( S_WARN "Image_LoadDDS: (%s) probably corrupted (%zu should be %lu)\n", name, buffsize, filesize );
|
||||
Con_DPrintf( S_WARN "%s: (%s) probably corrupted (%zu should be %zu)\n", __func__, name, buffsize, filesize );
|
||||
if( buffsize > filesize )
|
||||
return false;
|
||||
}
|
||||
@@ -300,13 +300,13 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( header.dwSize != sizeof( header ) - sizeof( uint )) // size of the structure (minus MagicNum)
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) have corrupted header\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have corrupted header\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header.dsPixelFormat.dwSize != sizeof( dds_pixf_t )) // size of the structure
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) have corrupt pixelformat header\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have corrupt pixelformat header\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( image.type == PF_UNKNOWN )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) has unrecognized type\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) has unrecognized type\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,49 +78,49 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
|
||||
|
||||
if( image.type == PF_UNKNOWN )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 format %d\n", __FUNCTION__, header->vkFormat );
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 format %d\n", __func__, header->vkFormat );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageCompressed( image.type ))
|
||||
{
|
||||
Con_DPrintf( S_WARN "%s: has compressed format, but support is not advertized\n", __FUNCTION__ );
|
||||
Con_DPrintf( S_WARN "%s: has compressed format, but support is not advertized\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->levelCount == 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: file has no mip levels\n", __FUNCTION__ );
|
||||
Con_DPrintf( S_ERROR "%s: file has no mip levels\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->pixelDepth > 1 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 pixelDepth %d\n", __FUNCTION__, header->pixelDepth );
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 pixelDepth %d\n", __func__, header->pixelDepth );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->faceCount > 1 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 faceCount %d\n", __FUNCTION__, header->faceCount );
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 faceCount %d\n", __func__, header->faceCount );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->layerCount > 1 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 layerCount %d\n", __FUNCTION__, header->layerCount );
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 layerCount %d\n", __func__, header->layerCount );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->supercompressionScheme != 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 supercompressionScheme %d\n", __FUNCTION__, header->supercompressionScheme );
|
||||
Con_DPrintf( S_ERROR "%s: unsupported KTX2 supercompressionScheme %d\n", __func__, header->supercompressionScheme );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( header->levelCount * sizeof( ktx2_level_t ) + KTX2_LEVELS_OFFSET > filesize )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: file abruptly ends\n", __FUNCTION__ );
|
||||
Con_DPrintf( S_ERROR "%s: file abruptly ends\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ static qboolean Image_KTX2Parse( const ktx2_header_t *header, const byte *buffer
|
||||
if( mip_size != level.byteLength )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: mip=%d size mismatch read=%d, but computed=%d\n",
|
||||
__FUNCTION__, mip, (int)level.byteLength, mip_size );
|
||||
__func__, mip, (int)level.byteLength, mip_size );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ qboolean Image_LoadKTX2( const char *name, const byte *buffer, fs_offset_t files
|
||||
|
||||
if( memcmp( buffer, KTX2_IDENTIFIER, KTX2_IDENTIFIER_SIZE ) != 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: (%s) has invalid identifier\n", __FUNCTION__, name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) has invalid identifier\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ qboolean Image_LoadKTX2( const char *name, const byte *buffer, fs_offset_t files
|
||||
// If KTX2 to imagelib conversion failed, try passing the file as raw data.
|
||||
// This is useful for ref_vk which can directly support hundreds of formats which we don't convert to pixformat_t here
|
||||
|
||||
Con_DPrintf( S_WARN "%s: (%s) could not be converted to supported imagelib format, passing as raw KTX2 data\n", __FUNCTION__, name );
|
||||
Con_DPrintf( S_WARN "%s: (%s) could not be converted to supported imagelib format, passing as raw KTX2 data\n", __func__, name );
|
||||
// This is a catch-all for ref_vk, which can do this format directly and natively
|
||||
image.type = PF_KTX2_RAW;
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ void Image_Reset( void )
|
||||
image.size = 0;
|
||||
}
|
||||
|
||||
static rgbdata_t *ImagePack( void )
|
||||
static MALLOC_LIKE( FS_FreeImage, 1 ) rgbdata_t *ImagePack( void )
|
||||
{
|
||||
rgbdata_t *pack;
|
||||
|
||||
@@ -360,7 +360,7 @@ load_internal:
|
||||
}
|
||||
|
||||
if( loadname[0] != '#' )
|
||||
Con_Reportf( S_WARN "FS_LoadImage: couldn't load \"%s\"\n", loadname );
|
||||
Con_Reportf( S_WARN "%s: couldn't load \"%s\"\n", __func__, loadname );
|
||||
|
||||
// clear any force flags
|
||||
image.force_flags = 0;
|
||||
@@ -547,7 +547,7 @@ static void Test_CheckImage( const char *name, rgbdata_t *rgb )
|
||||
TASSERT( load->size == rgb->size )
|
||||
TASSERT( memcmp(load->buffer, rgb->buffer, rgb->size ) == 0 )
|
||||
|
||||
Mem_Free( load );
|
||||
FS_FreeImage( load );
|
||||
}
|
||||
|
||||
void Test_RunImagelib( void )
|
||||
|
||||
@@ -63,7 +63,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// check png signature
|
||||
if( memcmp( png_hdr.sign, png_sign, sizeof( png_sign ) ) )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid PNG signature (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Invalid PNG signature (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -73,14 +73,14 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// check IHDR chunk length (valid value - 13)
|
||||
if( png_hdr.ihdr_len != sizeof( png_ihdr_t ) )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid IHDR chunk size %u (%s)\n", png_hdr.ihdr_len, name );
|
||||
Con_DPrintf( S_ERROR "%s: Invalid IHDR chunk size %u (%s)\n", __func__, png_hdr.ihdr_len, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
// check IHDR chunk signature
|
||||
if( memcmp( png_hdr.ihdr_sign, ihdr_sign, sizeof( ihdr_sign ) ) )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: IHDR chunk corrupted (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: IHDR chunk corrupted (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( png_hdr.ihdr_chunk.height == 0 || png_hdr.ihdr_chunk.width == 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid image size %ux%u (%s)\n", png_hdr.ihdr_chunk.width, png_hdr.ihdr_chunk.height, name );
|
||||
Con_DPrintf( S_ERROR "%s: Invalid image size %ux%u (%s)\n", __func__, png_hdr.ihdr_chunk.width, png_hdr.ihdr_chunk.height, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( png_hdr.ihdr_chunk.bitdepth != 8 )
|
||||
{
|
||||
Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit images is supported (%s)\n", name );
|
||||
Con_DPrintf( S_WARN "%s: Only 8-bit images is supported (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,31 +109,31 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|| png_hdr.ihdr_chunk.colortype == PNG_CT_ALPHA
|
||||
|| png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE ) )
|
||||
{
|
||||
Con_DPrintf( S_WARN "Image_LoadPNG: Unknown color type %u (%s)\n", png_hdr.ihdr_chunk.colortype, name );
|
||||
Con_DPrintf( S_WARN "%s: Unknown color type %u (%s)\n", __func__, png_hdr.ihdr_chunk.colortype, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( png_hdr.ihdr_chunk.compression > 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown compression method %u (%s)\n", png_hdr.ihdr_chunk.compression, name );
|
||||
Con_DPrintf( S_ERROR "%s: Unknown compression method %u (%s)\n", __func__, png_hdr.ihdr_chunk.compression, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( png_hdr.ihdr_chunk.filter > 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown filter type %u (%s)\n", png_hdr.ihdr_chunk.filter, name );
|
||||
Con_DPrintf( S_ERROR "%s: Unknown filter type %u (%s)\n", __func__, png_hdr.ihdr_chunk.filter, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( png_hdr.ihdr_chunk.interlace == 1 )
|
||||
{
|
||||
Con_DPrintf( S_WARN "Image_LoadPNG: Adam7 Interlacing not supported (%s)\n", name );
|
||||
Con_DPrintf( S_WARN "%s: Adam7 Interlacing not supported (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( png_hdr.ihdr_chunk.interlace > 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown interlacing type %u (%s)\n", png_hdr.ihdr_chunk.interlace, name );
|
||||
Con_DPrintf( S_ERROR "%s: Unknown interlacing type %u (%s)\n", __func__, png_hdr.ihdr_chunk.interlace, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// check IHDR chunk CRC
|
||||
if( ntohl( png_hdr.ihdr_crc32 ) != crc32_check )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: IHDR chunk has wrong CRC32 sum (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: IHDR chunk has wrong CRC32 sum (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -163,14 +163,14 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( chunk_len > INT_MAX )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Found chunk with wrong size (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Found chunk with wrong size (%s)\n", __func__, name );
|
||||
if( idat_buf ) Mem_Free( idat_buf );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( chunk_len > filesize - ( buf_p - buffer ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Found chunk with size past file size (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Found chunk with size past file size (%s)\n", __func__, name );
|
||||
if( idat_buf ) Mem_Free( idat_buf );
|
||||
return false;
|
||||
}
|
||||
@@ -216,7 +216,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// check chunk CRC
|
||||
if( ntohl( crc32 ) != crc32_check )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Found chunk with wrong CRC32 sum (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Found chunk with wrong CRC32 sum (%s)\n", __func__, name );
|
||||
if( idat_buf ) Mem_Free( idat_buf );
|
||||
return false;
|
||||
}
|
||||
@@ -227,27 +227,27 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( oldsize == 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Couldn't find IDAT chunks (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Couldn't find IDAT chunks (%s)\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE && !pallete )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: PLTE chunk not found (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: PLTE chunk not found (%s)\n", __func__, name );
|
||||
Mem_Free( idat_buf );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !has_iend_chunk )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk not found (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: IEND chunk not found (%s)\n", __func__, name );
|
||||
Mem_Free( idat_buf );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( chunk_len != 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk has wrong size %u (%s)\n", chunk_len, name );
|
||||
Con_DPrintf( S_ERROR "%s: IEND chunk has wrong size %u (%s)\n", __func__, chunk_len, name );
|
||||
Mem_Free( idat_buf );
|
||||
return false;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// uncompress image
|
||||
if( inflateInit2( &stream, MAX_WBITS ) != Z_OK )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: IDAT chunk decompression failed (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: IDAT chunk decompression failed (%s)\n", __func__, name );
|
||||
Mem_Free( uncompressed_buffer );
|
||||
Mem_Free( idat_buf );
|
||||
return false;
|
||||
@@ -311,7 +311,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( ret != Z_OK && ret != Z_STREAM_END )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: IDAT chunk decompression failed (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: IDAT chunk decompression failed (%s)\n", __func__, name );
|
||||
Mem_Free( uncompressed_buffer );
|
||||
return false;
|
||||
}
|
||||
@@ -351,7 +351,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
pixbuf[i] = raw[i] + ( pixbuf[i - pixel_size] >> 1 );
|
||||
break;
|
||||
default:
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Found unknown filter type (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Found unknown filter type (%s)\n", __func__, name );
|
||||
Mem_Free( uncompressed_buffer );
|
||||
Mem_Free( image.rgba );
|
||||
return false;
|
||||
@@ -415,7 +415,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Con_DPrintf( S_ERROR "Image_LoadPNG: Found unknown filter type (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: Found unknown filter type (%s)\n", __func__, name );
|
||||
Mem_Free( uncompressed_buffer );
|
||||
Mem_Free( image.rgba );
|
||||
return false;
|
||||
@@ -650,7 +650,7 @@ qboolean Image_SavePNG( const char *name, rgbdata_t *pix )
|
||||
// compress image
|
||||
if( deflateInit( &stream, Z_BEST_COMPRESSION ) != Z_OK )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_SavePNG: deflateInit failed (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: deflateInit failed (%s)\n", __func__, name );
|
||||
Mem_Free( filtered_buffer );
|
||||
Mem_Free( buffer );
|
||||
return false;
|
||||
@@ -663,7 +663,7 @@ qboolean Image_SavePNG( const char *name, rgbdata_t *pix )
|
||||
|
||||
if( ret != Z_OK && ret != Z_STREAM_END )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_SavePNG: IDAT chunk compression failed (%s)\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: IDAT chunk compression failed (%s)\n", __func__, name );
|
||||
Mem_Free( buffer );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,17 +62,17 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// uncompressed colormapped image
|
||||
if( targa_header.pixel_size != 8 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 8 bit images supported for type 1 and 9\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) Only 8 bit images supported for type 1 and 9\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
if( targa_header.colormap_length != 256 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 8 bit colormaps are supported for type 1 and 9\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) Only 8 bit colormaps are supported for type 1 and 9\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
if( targa_header.colormap_index )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) colormap_index is not supported for type 1 and 9\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) colormap_index is not supported for type 1 and 9\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
if( targa_header.colormap_size == 24 )
|
||||
@@ -97,7 +97,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) only 24 and 32 bit colormaps are supported for type 1 and 9\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) only 24 and 32 bit colormaps are supported for type 1 and 9\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// uncompressed or RLE compressed RGB
|
||||
if( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 32 or 24 bit images supported for type 2 and 10\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) Only 32 or 24 bit images supported for type 2 and 10\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// uncompressed greyscale
|
||||
if( targa_header.pixel_size != 8 && targa_header.pixel_size != 16 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Only 8 bit images supported for type 3 and 11\n", name );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) Only 8 bit images supported for type 3 and 11\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,8 +174,8 @@ byte *Image_Copy( size_t size )
|
||||
{
|
||||
byte *out;
|
||||
|
||||
out = Mem_Malloc( host.imagepool, size );
|
||||
memcpy( out, image.tempbuffer, size );
|
||||
out = Mem_Realloc( host.imagepool, image.tempbuffer, size );
|
||||
image.tempbuffer = NULL;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -293,9 +293,18 @@ static void Image_SetPalette( const byte *pal, uint *d_table )
|
||||
case LUMP_NORMAL:
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
rgba[0] = TextureToGamma( pal[i*3+0] );
|
||||
rgba[1] = TextureToGamma( pal[i*3+1] );
|
||||
rgba[2] = TextureToGamma( pal[i*3+2] );
|
||||
memcpy( rgba, &pal[i * 3], 3 );
|
||||
rgba[3] = 0xFF;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
}
|
||||
break;
|
||||
case LUMP_TEXGAMMA:
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
rgba[0] = TextureToGamma( pal[i * 3 + 0] );
|
||||
rgba[1] = TextureToGamma( pal[i * 3 + 1] );
|
||||
rgba[2] = TextureToGamma( pal[i * 3 + 2] );
|
||||
rgba[3] = 0xFF;
|
||||
memcpy( &uirgba, rgba, sizeof( uirgba ));
|
||||
d_table[i] = uirgba;
|
||||
@@ -1179,7 +1188,7 @@ byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int t
|
||||
return image.tempbuffer;
|
||||
}
|
||||
|
||||
static byte *Image_CreateLumaInternal( byte *fin, int width, int height, int type, int flags )
|
||||
static byte *Image_MakeLuma( byte *fin, int width, int height, int type, int flags )
|
||||
{
|
||||
byte *out;
|
||||
int i;
|
||||
@@ -1197,7 +1206,7 @@ static byte *Image_CreateLumaInternal( byte *fin, int width, int height, int typ
|
||||
break;
|
||||
default:
|
||||
// another formats does ugly result :(
|
||||
Con_Printf( S_ERROR "Image_MakeLuma: unsupported format %s\n", PFDesc[type].name );
|
||||
Con_Printf( S_ERROR "%s: unsupported format %s\n", __func__, PFDesc[type].name );
|
||||
return (byte *)fin;
|
||||
}
|
||||
|
||||
@@ -1374,20 +1383,20 @@ static qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomCol
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float reserved )
|
||||
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved )
|
||||
{
|
||||
rgbdata_t *pic = *pix;
|
||||
qboolean result = true;
|
||||
byte *out;
|
||||
|
||||
// check for buffers
|
||||
if( !pic || !pic->buffer )
|
||||
if( unlikely( !pic || !pic->buffer ))
|
||||
{
|
||||
image.force_flags = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !flags )
|
||||
if( unlikely( !flags ))
|
||||
{
|
||||
// clear any force flags
|
||||
image.force_flags = 0;
|
||||
@@ -1396,7 +1405,7 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
|
||||
|
||||
if( FBitSet( flags, IMAGE_MAKE_LUMA ))
|
||||
{
|
||||
out = Image_CreateLumaInternal( pic->buffer, pic->width, pic->height, pic->type, pic->flags );
|
||||
out = Image_MakeLuma( pic->buffer, pic->width, pic->height, pic->type, pic->flags );
|
||||
if( pic->buffer != out ) memcpy( pic->buffer, image.tempbuffer, pic->size );
|
||||
ClearBits( pic->flags, IMAGE_HAS_LUMA );
|
||||
}
|
||||
@@ -1432,7 +1441,7 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
|
||||
pic->width = w, pic->height = h;
|
||||
pic->size = w * h * PFDesc[pic->type].bpp;
|
||||
Mem_Free( pic->buffer ); // free original image buffer
|
||||
pic->buffer = Image_Copy( pic->size ); // unzone buffer (don't touch image.tempbuffer)
|
||||
pic->buffer = Image_Copy( pic->size ); // unzone buffer
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( filesize != 768 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadPAL: (%s) have invalid size (%ld should be %d)\n", name, filesize, 768 );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
if( Q_strrchr( name, '{' ))
|
||||
{
|
||||
// NOTE: decals with 'blue base' can be interpret as colored decals
|
||||
if( !Image_CheckFlag( IL_LOAD_DECAL ) || ( pal[765] == 0 && pal[766] == 0 && pal[767] == 255 ))
|
||||
if( !Image_CheckFlag( IL_LOAD_DECAL ) || ( pal && pal[765] == 0 && pal[766] == 0 && pal[767] == 255 ))
|
||||
{
|
||||
SetBits( image.flags, IMAGE_ONEBIT_ALPHA );
|
||||
rendermode = LUMP_MASKED;
|
||||
@@ -427,8 +427,18 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
|
||||
if( pal_type == PAL_QUAKE1 )
|
||||
{
|
||||
SetBits( image.flags, IMAGE_QUAKEPAL );
|
||||
rendermode = LUMP_NORMAL;
|
||||
|
||||
// if texture was converted from quake to half-life with no palette changes
|
||||
// then applying texgamma might make it too dark or even outright broken
|
||||
rendermode = LUMP_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// half-life mips need texgamma applied
|
||||
rendermode = LUMP_TEXGAMMA;
|
||||
}
|
||||
}
|
||||
|
||||
Image_GetPaletteLMP( pal, rendermode );
|
||||
@@ -488,37 +498,40 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
|
||||
// check for half-life water texture
|
||||
if( hl_texture && ( mip.name[0] == '!' || !Q_strnicmp( mip.name, "water", 5 )))
|
||||
if( pal != NULL )
|
||||
{
|
||||
// grab the fog color
|
||||
image.fogParams[0] = pal[3*3+0];
|
||||
image.fogParams[1] = pal[3*3+1];
|
||||
image.fogParams[2] = pal[3*3+2];
|
||||
|
||||
// grab the fog density
|
||||
image.fogParams[3] = pal[4*3+0];
|
||||
}
|
||||
else if( hl_texture && ( rendermode == LUMP_GRADIENT ))
|
||||
{
|
||||
// grab the decal color
|
||||
image.fogParams[0] = pal[255*3+0];
|
||||
image.fogParams[1] = pal[255*3+1];
|
||||
image.fogParams[2] = pal[255*3+2];
|
||||
|
||||
// calc the decal reflectivity
|
||||
image.fogParams[3] = VectorAvg( image.fogParams );
|
||||
}
|
||||
else if( pal != NULL )
|
||||
{
|
||||
// calc texture reflectivity
|
||||
for( i = 0; i < 256; i++ )
|
||||
if( hl_texture && ( mip.name[0] == '!' || !Q_strnicmp( mip.name, "water", 5 )))
|
||||
{
|
||||
reflectivity[0] += pal[i*3+0];
|
||||
reflectivity[1] += pal[i*3+1];
|
||||
reflectivity[2] += pal[i*3+2];
|
||||
}
|
||||
// grab the fog color
|
||||
image.fogParams[0] = pal[3*3+0];
|
||||
image.fogParams[1] = pal[3*3+1];
|
||||
image.fogParams[2] = pal[3*3+2];
|
||||
|
||||
VectorDivide( reflectivity, 256, image.fogParams );
|
||||
// grab the fog density
|
||||
image.fogParams[3] = pal[4*3+0];
|
||||
}
|
||||
else if( hl_texture && ( rendermode == LUMP_GRADIENT ))
|
||||
{
|
||||
// grab the decal color
|
||||
image.fogParams[0] = pal[255*3+0];
|
||||
image.fogParams[1] = pal[255*3+1];
|
||||
image.fogParams[2] = pal[255*3+2];
|
||||
|
||||
// calc the decal reflectivity
|
||||
image.fogParams[3] = VectorAvg( image.fogParams );
|
||||
}
|
||||
else
|
||||
{
|
||||
// calc texture reflectivity
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
reflectivity[0] += pal[i*3+0];
|
||||
reflectivity[1] += pal[i*3+1];
|
||||
reflectivity[2] += pal[i*3+2];
|
||||
}
|
||||
|
||||
VectorDivide( reflectivity, 256, image.fogParams );
|
||||
}
|
||||
}
|
||||
|
||||
image.type = PF_INDEXED_32; // 32-bit palete
|
||||
|
||||
@@ -23,9 +23,8 @@ GNU General Public License for more details.
|
||||
#include "build.h"
|
||||
#include "common.h"
|
||||
|
||||
#define E_GAME "XASH3D_GAME" // default env dir to start from
|
||||
#ifndef XASH_GAMEDIR
|
||||
#define XASH_GAMEDIR "valve"
|
||||
#define XASH_GAMEDIR "valve" // !!! Replace with your default (base) game directory !!!
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
@@ -47,12 +46,7 @@ static void Sys_ChangeGame( const char *progname )
|
||||
|
||||
static int Sys_Start( void )
|
||||
{
|
||||
const char *game = getenv( E_GAME );
|
||||
|
||||
if( !game )
|
||||
game = XASH_GAMEDIR;
|
||||
|
||||
Q_strncpy( szGameDir, game, sizeof( szGameDir ));
|
||||
Q_strncpy( szGameDir, XASH_GAMEDIR, sizeof( szGameDir ));
|
||||
|
||||
#if XASH_EMSCRIPTEN
|
||||
#ifdef EMSCRIPTEN_LIB_FS
|
||||
@@ -73,7 +67,7 @@ static int Sys_Start( void )
|
||||
IOS_LaunchDialog();
|
||||
#endif
|
||||
|
||||
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
|
||||
return Host_Main( szArgc, szArgv, szGameDir, 0, Sys_ChangeGame );
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
|
||||
@@ -81,8 +81,8 @@ void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||
const char *COM_OffsetNameForFunction( void *function )
|
||||
{
|
||||
static string sname;
|
||||
Q_snprintf( sname, MAX_STRING, "ofs:%lu", (size_t)((byte*)function - (byte*)svgame.dllFuncs.pfnGameInit) );
|
||||
Con_Reportf( "COM_OffsetNameForFunction %s\n", sname );
|
||||
Q_snprintf( sname, MAX_STRING, "ofs:%zu", ((byte*)function - (byte*)svgame.dllFuncs.pfnGameInit) );
|
||||
Con_Reportf( "%s: %s\n", __func__, sname );
|
||||
return sname;
|
||||
}
|
||||
|
||||
@@ -231,9 +231,9 @@ void COM_GetCommonLibraryPath( ECommonLibraryType eLibType, char *out, size_t si
|
||||
COM_GenerateClientLibraryPath( "menu", out, size );
|
||||
break;
|
||||
case LIBRARY_CLIENT:
|
||||
if( SI.clientlib[0] )
|
||||
if( COM_CheckStringEmpty( host.clientlib ))
|
||||
{
|
||||
Q_strncpy( out, SI.clientlib, size );
|
||||
Q_strncpy( out, host.clientlib, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -241,9 +241,9 @@ void COM_GetCommonLibraryPath( ECommonLibraryType eLibType, char *out, size_t si
|
||||
}
|
||||
break;
|
||||
case LIBRARY_SERVER:
|
||||
if( SI.gamedll[0] )
|
||||
if( COM_CheckStringEmpty( host.gamedll ))
|
||||
{
|
||||
Q_strncpy( out, SI.gamedll, size );
|
||||
Q_strncpy( out, host.gamedll, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -359,7 +359,7 @@ static char *COM_GetItaniumName( const char * const in_name )
|
||||
|
||||
if( i == MAX_NESTED_NAMESPACES )
|
||||
{
|
||||
Con_DPrintf( "%s: too much nested namespaces: %s\n", __FUNCTION__, in_name );
|
||||
Con_DPrintf( "%s: too much nested namespaces: %s\n", __func__, in_name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -373,7 +373,7 @@ static char *COM_GetItaniumName( const char * const in_name )
|
||||
return out_name;
|
||||
|
||||
invalid_format:
|
||||
Con_DPrintf( "%s: invalid format: %s\n", __FUNCTION__, in_name );
|
||||
Con_DPrintf( "%s: invalid format: %s\n", __func__, in_name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ char **COM_ConvertToLocalPlatform( EFunctionMangleType to, const char *from, siz
|
||||
|
||||
if( i == MAX_NESTED_NAMESPACES )
|
||||
{
|
||||
Con_DPrintf( "%s: too much nested namespaces: %s\n", __FUNCTION__, from );
|
||||
Con_DPrintf( "%s: too much nested namespaces: %s\n", __func__, from );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ typedef struct dll_user_s
|
||||
qboolean custom_loader; // a bit who indicated loader type
|
||||
qboolean encrypted; // dll is crypted (some client.dll in HL, CS etc)
|
||||
char dllName[32]; // for debug messages
|
||||
string fullPath, shortPath; // actual dll paths
|
||||
char fullPath[2048];
|
||||
string shortPath; // actual dll paths
|
||||
|
||||
// ordinals stuff, valid only on Win32
|
||||
word *ordinals;
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef struct master_s
|
||||
struct master_s *next;
|
||||
qboolean sent; // TODO: get rid of this internal state
|
||||
qboolean save;
|
||||
qboolean v6only;
|
||||
string address;
|
||||
netadr_t adr; // temporary, rewritten after each send
|
||||
|
||||
@@ -45,7 +46,7 @@ NET_GetMasterHostByName
|
||||
*/
|
||||
static net_gai_state_t NET_GetMasterHostByName( master_t *m )
|
||||
{
|
||||
net_gai_state_t res = NET_StringToAdrNB( m->address, &m->adr );
|
||||
net_gai_state_t res = NET_StringToAdrNB( m->address, &m->adr, m->v6only );
|
||||
|
||||
if( res == NET_EAI_OK )
|
||||
return res;
|
||||
@@ -118,7 +119,7 @@ static void NET_AnnounceToMaster( master_t *m )
|
||||
MSG_WriteBytes( &msg, "q\xFF", 2 );
|
||||
MSG_WriteDword( &msg, m->heartbeat_challenge );
|
||||
|
||||
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &msg ), MSG_GetBuf( &msg ), m->adr );
|
||||
NET_SendPacket( NS_SERVER, MSG_GetNumBytesWritten( &msg ), MSG_GetData( &msg ), m->adr );
|
||||
|
||||
if( sv_verbose_heartbeats.value )
|
||||
{
|
||||
@@ -251,7 +252,7 @@ NET_AddMaster
|
||||
Add master to the list
|
||||
========================
|
||||
*/
|
||||
static void NET_AddMaster( const char *addr, qboolean save )
|
||||
static void NET_AddMaster( const char *addr, qboolean save, qboolean v6only )
|
||||
{
|
||||
master_t *master, *last;
|
||||
|
||||
@@ -261,10 +262,11 @@ static void NET_AddMaster( const char *addr, qboolean save )
|
||||
return;
|
||||
}
|
||||
|
||||
master = Mem_Malloc( host.mempool, sizeof( master_t ) );
|
||||
Q_strncpy( master->address, addr, MAX_STRING );
|
||||
master = Mem_Malloc( host.mempool, sizeof( *master ) );
|
||||
Q_strncpy( master->address, addr, sizeof( master->address ));
|
||||
master->sent = false;
|
||||
master->save = save;
|
||||
master->v6only = v6only;
|
||||
master->next = NULL;
|
||||
master->adr.type = 0;
|
||||
|
||||
@@ -283,7 +285,7 @@ static void NET_AddMaster_f( void )
|
||||
return;
|
||||
}
|
||||
|
||||
NET_AddMaster( Cmd_Argv( 1 ), true ); // save them into config
|
||||
NET_AddMaster( Cmd_Argv( 1 ), true, false ); // save them into config
|
||||
ml.modified = true; // save config
|
||||
}
|
||||
|
||||
@@ -316,15 +318,14 @@ static void NET_ListMasters_f( void )
|
||||
master_t *list;
|
||||
int i;
|
||||
|
||||
Msg( "Master servers\n=============\n" );
|
||||
|
||||
Con_Printf( "Master servers:\n" );
|
||||
|
||||
for( i = 1, list = ml.list; list; i++, list = list->next )
|
||||
{
|
||||
Msg( "%d\t%s", i, list->address );
|
||||
Con_Printf( "%d\t%s", i, list->address );
|
||||
if( list->adr.type != 0 )
|
||||
Msg( "\t%s\n", NET_AdrToString( list->adr ));
|
||||
else Msg( "\n" );
|
||||
Con_Printf( "\t%s\n", NET_AdrToString( list->adr ));
|
||||
else Con_Printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,11 +355,15 @@ static void NET_LoadMasters( void )
|
||||
// format: master <addr>\n
|
||||
while( ( pfile = COM_ParseFile( pfile, token, sizeof( token ) ) ) )
|
||||
{
|
||||
if( !Q_strcmp( token, "master" ) ) // load addr
|
||||
if( !Q_strcmp( token, "master" )) // load addr
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ) );
|
||||
|
||||
NET_AddMaster( token, true );
|
||||
NET_AddMaster( token, true, false );
|
||||
}
|
||||
else if( !Q_strcmp( token, "master6" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ) );
|
||||
NET_AddMaster( token, true, true );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,14 +394,14 @@ void NET_SaveMasters( void )
|
||||
|
||||
if( !f )
|
||||
{
|
||||
Con_Reportf( S_ERROR "Couldn't write xashcomm.lst\n" );
|
||||
Con_Reportf( S_ERROR "Couldn't write xashcomm.lst\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
for( m = ml.list; m; m = m->next )
|
||||
{
|
||||
if( m->save )
|
||||
FS_Printf( f, "master %s\n", m->address );
|
||||
FS_Printf( f, "%s %s\n", m->v6only ? "master6" : "master", m->address );
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
@@ -418,7 +423,10 @@ void NET_InitMasters( void )
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
// keep main master always there
|
||||
NET_AddMaster( MASTERSERVER_ADR, false );
|
||||
NET_AddMaster( MASTERSERVER_ADR_TEST, false );
|
||||
NET_AddMaster( MASTERSERVER_ADR, false, false );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
|
||||
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
|
||||
|
||||
NET_LoadMasters( );
|
||||
}
|
||||
|
||||
241
engine/common/mod_alias.c
Normal file
241
engine/common/mod_alias.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
mod_alias.c - alias model loading
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
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 "common.h"
|
||||
#include "alias.h"
|
||||
#if !XASH_DEDICATED
|
||||
#include "ref_common.h"
|
||||
#endif // XASH_DEDICATED
|
||||
#include "mod_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
static int g_posenum = 0;
|
||||
static const trivertex_t *g_poseverts[MAXALIASFRAMES];
|
||||
|
||||
static const void *Mod_LoadAliasFrame( const daliasframe_t *pdaliasframe, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
|
||||
{
|
||||
const trivertex_t *pinframe;
|
||||
int i;
|
||||
|
||||
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = 1;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pinframe = (const trivertex_t *)(pdaliasframe + 1);
|
||||
|
||||
g_poseverts[g_posenum] = pinframe;
|
||||
g_posenum++;
|
||||
|
||||
pinframe += aliashdr->numverts;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
static const void *Mod_LoadAliasGroup( const daliasgroup_t *pingroup, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
|
||||
{
|
||||
const daliasinterval_t *pin_intervals;
|
||||
const void *ptemp;
|
||||
int i, numframes;
|
||||
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = numframes = pingroup->numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pin_intervals = (const daliasinterval_t *)(pingroup + 1);
|
||||
|
||||
// all the intervals are always equal 0.1 so we don't care about them
|
||||
frame->interval = pin_intervals->interval;
|
||||
pin_intervals += numframes;
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
g_poseverts[g_posenum] = (const trivertex_t *)((const daliasframe_t *)ptemp + 1);
|
||||
ptemp = g_poseverts[g_posenum] + aliashdr->numverts;
|
||||
g_posenum++;
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
static void Mod_CalcAliasBounds( model_t *mod, const aliashdr_t *aliashdr )
|
||||
{
|
||||
int i, j, k;
|
||||
float radius;
|
||||
float dist;
|
||||
vec3_t v;
|
||||
|
||||
ClearBounds( mod->mins, mod->maxs );
|
||||
radius = 0.0f;
|
||||
|
||||
// process verts
|
||||
for( i = 0; i < aliashdr->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < aliashdr->numverts; j++ )
|
||||
{
|
||||
for( k = 0; k < 3; k++ )
|
||||
v[k] = g_poseverts[i][j].v[k] * aliashdr->scale[k] + aliashdr->scale_origin[k];
|
||||
|
||||
AddPointToBounds( v, mod->mins, mod->maxs );
|
||||
dist = DotProduct( v, v );
|
||||
|
||||
if( radius < dist )
|
||||
radius = dist;
|
||||
}
|
||||
}
|
||||
|
||||
mod->radius = sqrt( radius );
|
||||
}
|
||||
|
||||
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype, const aliashdr_t *aliashdr )
|
||||
{
|
||||
int i, size;
|
||||
|
||||
if(( numskins < 1 ) || ( numskins > MAX_SKINS ))
|
||||
Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
|
||||
|
||||
size = aliashdr->skinwidth * aliashdr->skinheight;
|
||||
|
||||
// just skipping textures, renderer will take care of them later
|
||||
for( i = 0; i < numskins; i++ )
|
||||
{
|
||||
if( pskintype->type == ALIAS_SKIN_SINGLE )
|
||||
{
|
||||
const byte *ptexture = (const byte *)&pskintype[1];
|
||||
|
||||
pskintype = (const daliasskintype_t *)( ptexture + size );
|
||||
}
|
||||
else
|
||||
{
|
||||
const daliasskingroup_t *pinskingroup = (const daliasskingroup_t *)&pskintype[1];
|
||||
const daliasskininterval_t *pinskinintervals = (const daliasskininterval_t *)&pinskingroup[1];
|
||||
const byte *ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
|
||||
|
||||
pskintype = (const daliasskintype_t *)( ptexture + size );
|
||||
}
|
||||
}
|
||||
|
||||
return pskintype;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
Mod_LoadAliasModel
|
||||
|
||||
load alias model
|
||||
====================
|
||||
*/
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
{
|
||||
const daliasframetype_t *pframetype;
|
||||
const daliasskintype_t *pskintype;
|
||||
const dtriangle_t *pintriangles;
|
||||
const daliashdr_t *pinmodel;
|
||||
const stvert_t *pinstverts;
|
||||
aliashdr_t *m_pAliasHeader;
|
||||
size_t size;
|
||||
char poolname[MAX_VA_STRING];
|
||||
int i;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
pinmodel = (const daliashdr_t *)buffer;
|
||||
i = pinmodel->version;
|
||||
|
||||
if( i != ALIAS_VERSION )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
|
||||
return; // how is it possible to make that?
|
||||
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
|
||||
mod->mempool = Mem_AllocPool( poolname );
|
||||
|
||||
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
|
||||
mod->cache.data = m_pAliasHeader = Mem_Calloc( mod->mempool, size );
|
||||
|
||||
// endian-adjust and copy the data, starting with the alias model header
|
||||
m_pAliasHeader->numverts = pinmodel->numverts;
|
||||
|
||||
if( m_pAliasHeader->numverts > MAXALIASVERTS )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
|
||||
return;
|
||||
}
|
||||
|
||||
mod->flags = pinmodel->flags; // share effects flags
|
||||
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
|
||||
m_pAliasHeader->numskins = pinmodel->numskins;
|
||||
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
|
||||
m_pAliasHeader->skinheight = pinmodel->skinheight;
|
||||
m_pAliasHeader->numtris = pinmodel->numtris;
|
||||
mod->numframes = m_pAliasHeader->numframes = pinmodel->numframes;
|
||||
m_pAliasHeader->size = pinmodel->size;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
m_pAliasHeader->scale[i] = pinmodel->scale[i];
|
||||
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
|
||||
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
|
||||
}
|
||||
|
||||
// load the skins
|
||||
pskintype = (const daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype, m_pAliasHeader );
|
||||
// will be done at renderer side...
|
||||
|
||||
// load base s and t vertices
|
||||
pinstverts = (const stvert_t *)pskintype;
|
||||
// will be done at renderer side...
|
||||
|
||||
// load triangle lists
|
||||
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
// will be done at renderer side
|
||||
|
||||
// load the frames
|
||||
pframetype = (const daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
|
||||
m_pAliasHeader->pposeverts = g_poseverts; // store the pointer to be accessed by renderer
|
||||
g_posenum = 0;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numframes; i++ )
|
||||
{
|
||||
aliasframetype_t frametype = pframetype->type;
|
||||
|
||||
if( frametype == ALIAS_SINGLE )
|
||||
pframetype = (const daliasframetype_t *)Mod_LoadAliasFrame((const daliasframe_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
|
||||
else pframetype = (const daliasframetype_t *)Mod_LoadAliasGroup(( const daliasgroup_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
|
||||
}
|
||||
|
||||
m_pAliasHeader->numposes = g_posenum;
|
||||
Mod_CalcAliasBounds( mod, m_pAliasHeader );
|
||||
mod->type = mod_alias;
|
||||
|
||||
if( loaded ) *loaded = true; // done
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user