Compare commits
1232
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
300632db86 | ||
|
|
d1776dd641 | ||
|
|
22cee6a2dd | ||
|
|
a2194df273 | ||
|
|
27e20996dd | ||
|
|
b5f16142e5 | ||
|
|
23f1f9e148 | ||
|
|
990f99af5a | ||
|
|
6ca9d86e8f | ||
|
|
fae8b4d49a | ||
|
|
7f2d9dd8eb | ||
|
|
8ae1b3e1e7 | ||
|
|
c77c853c02 | ||
|
|
2b0daba573 | ||
|
|
ba4aa4d37f | ||
|
|
e3f31af5d3 | ||
|
|
bc0bf4e270 | ||
|
|
60c5ad6324 | ||
|
|
e996a00675 | ||
|
|
0be3f0afed | ||
|
|
86bdfa2205 | ||
|
|
56c87e927f | ||
|
|
be54443918 | ||
|
|
676ea8b29c | ||
|
|
d77ff38428 | ||
|
|
d3256ef339 | ||
|
|
3d11742f91 | ||
|
|
a2aa5d1cda | ||
|
|
8860e18026 | ||
|
|
7dba540b97 | ||
|
|
0dd9a5b842 | ||
|
|
e6c3565544 | ||
|
|
8cacba922a | ||
|
|
767396d4ee | ||
|
|
07a51a0d4e | ||
|
|
9f042625d0 | ||
|
|
fc29f4249a | ||
|
|
5ca5ecee85 | ||
|
|
c79d547492 | ||
|
|
f079773195 | ||
|
|
e6ead8b5aa | ||
|
|
9eba6402eb | ||
|
|
f95be3b10c | ||
|
|
2220cc961e | ||
|
|
cfc6b2fee9 | ||
|
|
d188859fc5 | ||
|
|
96a8003448 | ||
|
|
696f702204 | ||
|
|
8b26ce73c2 | ||
|
|
ee5f488aa2 | ||
|
|
3a5cf80e2b | ||
|
|
3e4f7af96a | ||
|
|
a1a483fa27 | ||
|
|
b32f8a4803 | ||
|
|
96ee6dbf8a | ||
|
|
ac07cf95e1 | ||
|
|
8f51e33167 | ||
|
|
8366f371ad | ||
|
|
9b44dfea11 | ||
|
|
7ede8e0924 | ||
|
|
9fe2d9c1cf | ||
|
|
1836ec9d45 | ||
|
|
380d7adc09 | ||
|
|
4109d0df39 | ||
|
|
9cab1e3ab7 | ||
|
|
e9d8bfcdfc | ||
|
|
f134602991 | ||
|
|
b493532ee1 | ||
|
|
84dec75fb8 | ||
|
|
b1094f87c6 | ||
|
|
284b4bfe20 | ||
|
|
b46537ddd5 | ||
|
|
c9446c4d7d | ||
|
|
d4610ab340 | ||
|
|
0016b8ef2f | ||
|
|
72e08f7e44 | ||
|
|
b06cfa5414 | ||
|
|
a7742cae3d | ||
|
|
8a78285659 | ||
|
|
6847c8eec0 | ||
|
|
66790254ac | ||
|
|
86b8a0b16a | ||
|
|
25fced78e8 | ||
|
|
22d11160ba | ||
|
|
8d65b3e94e | ||
|
|
5518544ecd | ||
|
|
af3523bd2d | ||
|
|
8646cca538 | ||
|
|
c7cea1b40b | ||
|
|
58914f71bd | ||
|
|
3841e98c4f | ||
|
|
acd025dba2 | ||
|
|
78c2206628 | ||
|
|
5c47bf8803 | ||
|
|
8e78ee6f57 | ||
|
|
a2da4cc868 | ||
|
|
00e44ad3c3 | ||
|
|
29ba84fc5c | ||
|
|
283f1f012d | ||
|
|
fff17f8043 | ||
|
|
847eaf38f9 | ||
|
|
1d59a329eb | ||
|
|
5689888682 | ||
|
|
a01768525a | ||
|
|
e3d2ddf278 | ||
|
|
b3e48b0ad7 | ||
|
|
6d528b5c55 | ||
|
|
22daf26e3e | ||
|
|
73061969da | ||
|
|
4653530095 | ||
|
|
ef5faaaa4a | ||
|
|
f52ea98eb4 | ||
|
|
d315d4bf53 | ||
|
|
eaef2a46fb | ||
|
|
b0304a89a6 | ||
|
|
a4790f0358 | ||
|
|
d3d5cd8181 | ||
|
|
64be2bc5a0 | ||
|
|
30e476c35e | ||
|
|
88af208cdd | ||
|
|
b64751c1af | ||
|
|
2e158a72e2 | ||
|
|
c8fb05dd4b | ||
|
|
860af1e6cb | ||
|
|
5c1cadb64e | ||
|
|
bfb97a4207 | ||
|
|
7e26691b99 | ||
|
|
ca469a218a | ||
|
|
6052ddaa64 | ||
|
|
0ddc675472 | ||
|
|
9412f687cb | ||
|
|
0e865c0618 | ||
|
|
462b5213d7 | ||
|
|
f52e84730f | ||
|
|
b8873efa0d | ||
|
|
4132b9bd21 | ||
|
|
c0caa9f158 | ||
|
|
7346b0c081 | ||
|
|
6a361e3045 | ||
|
|
61d7519ef5 | ||
|
|
3e1a78703e | ||
|
|
bb195a9b2d | ||
|
|
6f095a064c | ||
|
|
eb334f5fe2 | ||
|
|
ef825d8a94 | ||
|
|
6775898712 | ||
|
|
d3dd82f190 | ||
|
|
95409f7ec7 | ||
|
|
1141a73945 | ||
|
|
176c003658 | ||
|
|
74aafaa72f | ||
|
|
0ac7867b3d | ||
|
|
c1b65f52be | ||
|
|
1d242ee161 | ||
|
|
230e4e3a32 | ||
|
|
7ff4724e28 | ||
|
|
0015d00243 | ||
|
|
5ca8967375 | ||
|
|
4e0c1f97ac | ||
|
|
191c3dabdb | ||
|
|
cd9a28864a | ||
|
|
c2ecb7363c | ||
|
|
e20e272ee1 | ||
|
|
8dc7f78b0f | ||
|
|
c4331c4795 | ||
|
|
d071ecc17c | ||
|
|
7c03276b50 | ||
|
|
ee8b180341 | ||
|
|
5258a1dc85 | ||
|
|
e74d5593a8 | ||
|
|
18285ca751 | ||
|
|
764a04a201 | ||
|
|
1e5a375203 | ||
|
|
3a2504dc18 | ||
|
|
7bc4c10660 | ||
|
|
0fcfead475 | ||
|
|
ab9c1217e4 | ||
|
|
e9f002e9c5 | ||
|
|
a9b6bcf779 | ||
|
|
52e427117c | ||
|
|
312e26a5cf | ||
|
|
f757d5f09b | ||
|
|
a66adcbc88 | ||
|
|
f4f930e8bd | ||
|
|
5200940f2f | ||
|
|
63f8262a57 | ||
|
|
bb9d5e11f1 | ||
|
|
df76b7285c | ||
|
|
e105711678 | ||
|
|
b206858c67 | ||
|
|
bc1b803093 | ||
|
|
6e54e0f6e4 | ||
|
|
e0d2287973 | ||
|
|
7f26803dee | ||
|
|
22cbe23f85 | ||
|
|
8f0c442024 | ||
|
|
02b8e3f7c0 | ||
|
|
7846ff1666 | ||
|
|
3e1e20dbe2 | ||
|
|
eaf441c226 | ||
|
|
942b1d2591 | ||
|
|
710456f871 | ||
|
|
59df217a09 | ||
|
|
ffd7603b17 | ||
|
|
329616c029 | ||
|
|
8723a69a8f | ||
|
|
edddca4857 | ||
|
|
536123ec59 | ||
|
|
db699ed2c3 | ||
|
|
bf9c58b8ed | ||
|
|
8eeec3dc48 | ||
|
|
4a1dd5f519 | ||
|
|
5256edf0e5 | ||
|
|
e9385e6eb6 | ||
|
|
80f7e3092b | ||
|
|
ab06cf4788 | ||
|
|
c2300f7b2b | ||
|
|
ba2915ce4e | ||
|
|
c0b91dd107 | ||
|
|
439986e3fe | ||
|
|
e77ad244ad | ||
|
|
2e3c5e367e | ||
|
|
eb230a45f6 | ||
|
|
5aacf886e1 | ||
|
|
0cae86e2ad | ||
|
|
e7f0a005e2 | ||
|
|
b3c506c69e | ||
|
|
99f741fb3b | ||
|
|
52aa0a5b27 | ||
|
|
b7ac61cbea | ||
|
|
2896e7bd4b | ||
|
|
8a10f4b7a2 | ||
|
|
7619d0d7ff | ||
|
|
2175357e72 | ||
|
|
bd9f126973 | ||
|
|
4260a5b3df | ||
|
|
247fabaaf0 | ||
|
|
a991d327e6 | ||
|
|
c19712dccc | ||
|
|
7d67e851c9 | ||
|
|
7492ee5d2e | ||
|
|
7ea6080689 | ||
|
|
272dbf94e0 | ||
|
|
d96f7ae4ae | ||
|
|
20d4597fa0 | ||
|
|
c5947e2dd7 | ||
|
|
544bd7d4cc | ||
|
|
d1c1cb5f7c | ||
|
|
a1165183c2 | ||
|
|
07520fb26e | ||
|
|
46393d63af | ||
|
|
ccc067a1c6 | ||
|
|
0cd954749c | ||
|
|
916f60b59b | ||
|
|
115d17de01 | ||
|
|
8dfae523a3 | ||
|
|
0532135dc3 | ||
|
|
b28c6d6e4a | ||
|
|
f703b285bb | ||
|
|
749b9dd1bb | ||
|
|
42ff151ae4 | ||
|
|
5ec6f851c9 | ||
|
|
89be7adc80 | ||
|
|
39f9702db4 | ||
|
|
021c390091 | ||
|
|
cec1d4a28b | ||
|
|
38969dde2f | ||
|
|
3061ef9d4c | ||
|
|
e55b7fa70f | ||
|
|
79d04c2d24 | ||
|
|
d11be6fcf4 | ||
|
|
bed417dc62 | ||
|
|
7625ca439e | ||
|
|
6ff5733d7b | ||
|
|
a3117ef272 | ||
|
|
2fdbedfe95 | ||
|
|
5567484a8e | ||
|
|
d79c5bd1dc | ||
|
|
34d2db6d78 | ||
|
|
eceb9008cd | ||
|
|
731245773a | ||
|
|
d4a80ab3d0 | ||
|
|
ce709298cc | ||
|
|
6ab7a6678c | ||
|
|
f62283b595 | ||
|
|
e8058912b8 | ||
|
|
4f800fbd00 | ||
|
|
e367d456e1 | ||
|
|
3025b9b5e0 | ||
|
|
b0075842d1 | ||
|
|
0a10d6022f | ||
|
|
a634da2c0a | ||
|
|
94f0fc58cc | ||
|
|
bf76be5dfa | ||
|
|
a62aeb36d8 | ||
|
|
0d795fc651 | ||
|
|
7441af67a8 | ||
|
|
9077686998 | ||
|
|
d88f07fd31 | ||
|
|
805306bdf0 | ||
|
|
da53fdb50c | ||
|
|
549e5a85cb | ||
|
|
cd75c56ac4 | ||
|
|
82883d8187 | ||
|
|
74f49ec38f | ||
|
|
cb3411481d | ||
|
|
3aad0dff2e | ||
|
|
0510723ac1 | ||
|
|
294a120f14 | ||
|
|
e6313c89bc | ||
|
|
8362b8d226 | ||
|
|
7675472b41 | ||
|
|
c07f84911c | ||
|
|
6f18a50945 | ||
|
|
d5c9ce9125 | ||
|
|
3b4ac1c64d | ||
|
|
717b4ce4fa | ||
|
|
6efc6074cc | ||
|
|
76fa100c1d | ||
|
|
981171f42a | ||
|
|
33ef2ff5c9 | ||
|
|
380d0b9623 | ||
|
|
de27cb8a2f | ||
|
|
ac6c162a13 | ||
|
|
a8021e0d79 | ||
|
|
b52f696d49 | ||
|
|
983e37a0be | ||
|
|
f1e01a3cf6 | ||
|
|
858c3f653c | ||
|
|
4618588494 | ||
|
|
cd3c3fffde | ||
|
|
148b5ea376 | ||
|
|
6f9c197400 | ||
|
|
67ae85b840 | ||
|
|
0f6e8dd311 | ||
|
|
cb86d4d967 | ||
|
|
80fbc25442 | ||
|
|
c1f9fb6c3a | ||
|
|
a46dcd45d7 | ||
|
|
99ff1179cc | ||
|
|
4871dbaaa1 | ||
|
|
832dc259af | ||
|
|
78f4640736 | ||
|
|
0b7831c6df | ||
|
|
73a701f08c | ||
|
|
080405c022 | ||
|
|
58ae7f1cab | ||
|
|
59b1bd3d96 | ||
|
|
4d4979cc98 | ||
|
|
542c515bc1 | ||
|
|
3479e452de | ||
|
|
49ad25d001 | ||
|
|
13c8336c82 | ||
|
|
601186fd6a | ||
|
|
dfadfe37f6 | ||
|
|
b3372ebba2 | ||
|
|
01de453d25 | ||
|
|
64b6c0d0eb | ||
|
|
2f684e0255 | ||
|
|
3a77fcd005 | ||
|
|
06492d18a7 | ||
|
|
0297e974d4 | ||
|
|
354279bc1e | ||
|
|
e0278071cf | ||
|
|
a9bd1ced2e | ||
|
|
8cd397e56f | ||
|
|
7423fd9c98 | ||
|
|
cd75262ad1 | ||
|
|
70f91f8345 | ||
|
|
61a28c290b | ||
|
|
40c2674d49 | ||
|
|
b3d38bd4f1 | ||
|
|
7e199b0c7c | ||
|
|
6af30e8992 | ||
|
|
e7c86713c8 | ||
|
|
7cd480a1a9 | ||
|
|
3f249c2e93 | ||
|
|
36f5200abc | ||
|
|
89325f9995 | ||
|
|
83b3c3ab8f | ||
|
|
02277225d7 | ||
|
|
6f55c3e75a | ||
|
|
56131fd63a | ||
|
|
f65de3bbbb | ||
|
|
44d9551bd6 | ||
|
|
1aab29a958 | ||
|
|
0439d08689 | ||
|
|
618eb254c0 | ||
|
|
e2340363e3 | ||
|
|
a68125a5ee | ||
|
|
3d25938dd7 | ||
|
|
70994cb4b2 | ||
|
|
0d5ef132f3 | ||
|
|
5610aeb917 | ||
|
|
02f8991fb3 | ||
|
|
f53255570d | ||
|
|
543f3440dc | ||
|
|
1a8417951f | ||
|
|
2f68781ff9 | ||
|
|
d29e546678 | ||
|
|
a39943d57d | ||
|
|
c20ac116a8 | ||
|
|
c8f5ef8afb | ||
|
|
1ebef323de | ||
|
|
3b18745bcd | ||
|
|
236579a930 | ||
|
|
9b49b2694d | ||
|
|
62336b60b2 | ||
|
|
917b6d4521 | ||
|
|
fdec003973 | ||
|
|
55b4854cd4 | ||
|
|
6aca18193a | ||
|
|
745b2f0668 | ||
|
|
2b207359f9 | ||
|
|
6121c098c8 | ||
|
|
c15a91dbcc | ||
|
|
f46c58deaa | ||
|
|
c9b7e9f9aa | ||
|
|
6a8c99eef1 | ||
|
|
7025e07e8a | ||
|
|
2ba12008c8 | ||
|
|
ac2bbf16f6 | ||
|
|
d77ebd60cf | ||
|
|
997c7ebbcf | ||
|
|
afe5425163 | ||
|
|
32eadc0ea3 | ||
|
|
e75b244cae | ||
|
|
bb448905ac | ||
|
|
6928ce9cd3 | ||
|
|
b7394ad02e | ||
|
|
eca39b1a51 | ||
|
|
f66e63c690 | ||
|
|
42c2fc61b8 | ||
|
|
24303a5365 | ||
|
|
0ecae8a844 | ||
|
|
9e45f2da9f | ||
|
|
d676886dee | ||
|
|
2d0a0b5a62 | ||
|
|
6fe32b3b49 | ||
|
|
525145f2a3 | ||
|
|
2b8038d700 | ||
|
|
2454c0baae | ||
|
|
0189c5b990 | ||
|
|
c70285dcfc | ||
|
|
f5a392e189 | ||
|
|
cd729f054c | ||
|
|
5f551fa67a | ||
|
|
1e57376cc7 | ||
|
|
4771398e1e | ||
|
|
ee49dfa505 | ||
|
|
20d1551216 | ||
|
|
a3593a5124 | ||
|
|
c7646976fb | ||
|
|
8a10cc982c | ||
|
|
74e546e145 | ||
|
|
5586f7c517 | ||
|
|
fbeeaa4c1e | ||
|
|
48738bbae9 | ||
|
|
7f74948e91 | ||
|
|
a31bb79b78 | ||
|
|
821fcd5be4 | ||
|
|
0c75229250 | ||
|
|
5f67a600fc | ||
|
|
4669c320f6 | ||
|
|
545868da38 | ||
|
|
e154f3edb7 | ||
|
|
393c54fdc2 | ||
|
|
02981cec57 | ||
|
|
6e499c8213 | ||
|
|
9ca1ced6a2 | ||
|
|
6470222a06 | ||
|
|
eedf8b845c | ||
|
|
01c94596a4 | ||
|
|
978d7c0fca | ||
|
|
3bd53b4f61 | ||
|
|
8d9c325000 | ||
|
|
dfe8ae4fd1 | ||
|
|
069d67b24b | ||
|
|
0c926b84bc | ||
|
|
11bdd68d73 | ||
|
|
1beeaf3d4f | ||
|
|
8cc850de97 | ||
|
|
0931794f10 | ||
|
|
3b12883a1b | ||
|
|
e18faf085f | ||
|
|
a98edd42d1 | ||
|
|
c1aa49ef3a | ||
|
|
49a860bc9e | ||
|
|
1b94a30c9f | ||
|
|
5a52fc3657 | ||
|
|
df7680aa73 | ||
|
|
f42a16643c | ||
|
|
96e5dc3fc6 | ||
|
|
6c0eca0eca | ||
|
|
fefff70645 | ||
|
|
18fa18f612 | ||
|
|
b2311e2ea5 | ||
|
|
ee42f09b8d | ||
|
|
e7f5f4a6af | ||
|
|
4d07acd384 | ||
|
|
2c06bb46ea | ||
|
|
3c3bfff0cf | ||
|
|
a86f6d0e64 | ||
|
|
4d54bfa6b4 | ||
|
|
28d1dab18a | ||
|
|
f3d19a860a | ||
|
|
5732e34f50 | ||
|
|
ca94a61acf | ||
|
|
a875c61b5f | ||
|
|
5ec70c9e0d | ||
|
|
4b0373408d | ||
|
|
7f8c4eff39 | ||
|
|
00f152910b | ||
|
|
95fdeb03c3 | ||
|
|
66e9ef9cf6 | ||
|
|
6b3221f1da | ||
|
|
25ad7bcf5e | ||
|
|
9a04a6bdb1 | ||
|
|
1b9fb906e2 | ||
|
|
e23d7ca51b | ||
|
|
92773c2e1b | ||
|
|
776889cfbb | ||
|
|
67163e14e6 | ||
|
|
45f68840ed | ||
|
|
325ae5e977 | ||
|
|
14919c65d9 | ||
|
|
8888e88dc4 | ||
|
|
0533664f90 | ||
|
|
64b824f457 | ||
|
|
b6592d799f | ||
|
|
c89711a863 | ||
|
|
91a1292b12 | ||
|
|
b2d469cb84 | ||
|
|
4f41da34c6 | ||
|
|
f136f2dcaf | ||
|
|
e6df54537a | ||
|
|
e62278859e | ||
|
|
51b91bce6d | ||
|
|
d96a23d4f2 | ||
|
|
98e049b336 | ||
|
|
3c297f5d1d | ||
|
|
d64d196409 | ||
|
|
b1638e79c0 | ||
|
|
13753757d4 | ||
|
|
739e341218 | ||
|
|
fda282604d | ||
|
|
2cd7fa68d6 | ||
|
|
d78a0c87b8 | ||
|
|
88d4abeaf8 | ||
|
|
1c0abbfce6 | ||
|
|
1492e12ca2 | ||
|
|
2b9a39e2eb | ||
|
|
301ae447b4 | ||
|
|
3d47010cbd | ||
|
|
dd0ff999e4 | ||
|
|
05e5c93e91 | ||
|
|
1bd97730ce | ||
|
|
458378be66 | ||
|
|
c01101dbd0 | ||
|
|
f7364111f2 | ||
|
|
f3b84b8670 | ||
|
|
ec11a31d9d | ||
|
|
2271469d1b | ||
|
|
7fe92d87c2 | ||
|
|
6046b8fb79 | ||
|
|
a65239a8af | ||
|
|
746cd5f49c | ||
|
|
75c315ad8a | ||
|
|
c1926c6e25 | ||
|
|
3f8ba353b7 | ||
|
|
39a2152a46 | ||
|
|
ddd967534b | ||
|
|
4d52fe0490 | ||
|
|
264ffa80ce | ||
|
|
258a9c636a | ||
|
|
8015d1827c | ||
|
|
ae10bc6601 | ||
|
|
51c27afcd2 | ||
|
|
e09d4f2cf2 | ||
|
|
7e87f56699 | ||
|
|
ca9150a731 | ||
|
|
5250d819d0 | ||
|
|
d93413a4ae | ||
|
|
bb7f7eff51 | ||
|
|
838e8c7b35 | ||
|
|
bb48a16466 | ||
|
|
a02ff01d84 | ||
|
|
66d27d6ac5 | ||
|
|
5ba82ef0fc | ||
|
|
053b522aff | ||
|
|
4521f80e5a | ||
|
|
f24efc17c1 | ||
|
|
f32d3849e5 | ||
|
|
f2fb064ea6 | ||
|
|
ce5093f91f | ||
|
|
75121588c4 | ||
|
|
1ff0f478d4 | ||
|
|
6c68082359 | ||
|
|
a752d220cc | ||
|
|
ee1bbd5994 | ||
|
|
91368e5656 | ||
|
|
c4c554b420 | ||
|
|
52ec8bf049 | ||
|
|
5c40e02ee6 | ||
|
|
d2a89c5856 | ||
|
|
9ec3f1b89d | ||
|
|
3ab81c764d | ||
|
|
c072ce8f0c | ||
|
|
e44dbd0e77 | ||
|
|
ec12022550 | ||
|
|
e0f670499c | ||
|
|
177cc87985 | ||
|
|
3e387f35e9 | ||
|
|
7037723993 | ||
|
|
b1098d6287 | ||
|
|
be222a16ce | ||
|
|
17f9a3eba6 | ||
|
|
0ee77c0e7d | ||
|
|
b92fa45da7 | ||
|
|
e64c2fc110 | ||
|
|
49a6508888 | ||
|
|
859678536f | ||
|
|
9a5f788807 | ||
|
|
84b3b1d29c | ||
|
|
80eb18a425 | ||
|
|
3e1ab53abd | ||
|
|
18c119b4d5 | ||
|
|
e67a65c0db | ||
|
|
4c878c4963 | ||
|
|
e8fbe0f36c | ||
|
|
243b7e25f8 | ||
|
|
f1a4a08c7f | ||
|
|
c0fa36b9a1 | ||
|
|
835b2d7ced | ||
|
|
13c2381ba7 | ||
|
|
fbc8e899dd | ||
|
|
5ee8c8ce91 | ||
|
|
971793d6a1 | ||
|
|
9d7a905fb1 | ||
|
|
731f002175 | ||
|
|
7e6f3bfd83 | ||
|
|
3e14739b29 | ||
|
|
d7fb6b2892 | ||
|
|
7527f441ae | ||
|
|
5228ee1d91 | ||
|
|
297a98e065 | ||
|
|
727d8afd94 | ||
|
|
c292fba3df | ||
|
|
9954ff55f5 | ||
|
|
fefd84d431 | ||
|
|
b4a7d21b9e | ||
|
|
d03e051611 | ||
|
|
e8c141d775 | ||
|
|
5b45e29533 | ||
|
|
024d094459 | ||
|
|
df977577e2 | ||
|
|
b63b94bc81 | ||
|
|
7e514f5d34 | ||
|
|
cb2de2e5c4 | ||
|
|
f2fedbc3e6 | ||
|
|
8ef686fd21 | ||
|
|
4c96e9a17d | ||
|
|
939bc00b2b | ||
|
|
0b06d3412e | ||
|
|
94f6f60105 | ||
|
|
4bd6bc9683 | ||
|
|
3c59621425 | ||
|
|
a37e2ab26a | ||
|
|
d099febf7b | ||
|
|
b9f82332c8 | ||
|
|
c02c4c6d6a | ||
|
|
17476ec137 | ||
|
|
ee51a68c6f | ||
|
|
0120ce5d7c | ||
|
|
42c6e640fc | ||
|
|
bc571316b9 | ||
|
|
3cc1af9618 | ||
|
|
6957bf504b | ||
|
|
d47dd70141 | ||
|
|
86eb2360db | ||
|
|
c55e350cb2 | ||
|
|
b0fe032b8d | ||
|
|
aa25870fb8 | ||
|
|
a8118ea8f4 | ||
|
|
1a344c1441 | ||
|
|
86a1641ac1 | ||
|
|
10129fa568 | ||
|
|
935a8d36da | ||
|
|
2516a3af8a | ||
|
|
120a265fc3 | ||
|
|
33aebeb727 | ||
|
|
7e06cfb471 | ||
|
|
f2bcff69a9 | ||
|
|
39b7d175b9 | ||
|
|
b9cebe8d87 | ||
|
|
6814cfbcd7 | ||
|
|
2884696024 | ||
|
|
6930046bc6 | ||
|
|
174cbfe3b9 | ||
|
|
611c7633cf | ||
|
|
822d4269c4 | ||
|
|
8fd16efc33 | ||
|
|
ef082d855c | ||
|
|
a5c4739804 | ||
|
|
d1f1a88ffd | ||
|
|
c05f6b7bf3 | ||
|
|
4b5fa26cd6 | ||
|
|
0162d18343 | ||
|
|
b6415818f6 | ||
|
|
e16efbf58b | ||
|
|
46804d0faf | ||
|
|
a81567e2d6 | ||
|
|
217670b54a | ||
|
|
f2e19c0387 | ||
|
|
9799970042 | ||
|
|
ca75d0d765 | ||
|
|
0824e49000 | ||
|
|
c3a98db0ea | ||
|
|
f27685717b | ||
|
|
55034bfa6f | ||
|
|
6f8b420d0d | ||
|
|
2ed7e14a99 | ||
|
|
ee3bcef8ab | ||
|
|
adbcb97515 | ||
|
|
c667723958 | ||
|
|
d94634398e | ||
|
|
f348e58508 | ||
|
|
60f16970ac | ||
|
|
39c5eafafc | ||
|
|
b7f6c223d8 | ||
|
|
bf9a65338b | ||
|
|
5b3ae5eff9 | ||
|
|
f80a8d306b | ||
|
|
9ed9060940 | ||
|
|
5453e60099 | ||
|
|
3de61b69ad | ||
|
|
322a4ed05d | ||
|
|
8f3b4afcf7 | ||
|
|
ebdc6b94fc | ||
|
|
a7218d2e59 | ||
|
|
6d93beac8e | ||
|
|
1fb1309e77 | ||
|
|
5916f40b7a | ||
|
|
5226714bbd | ||
|
|
dabf486a9f | ||
|
|
c78f4407ea | ||
|
|
fae4127ddc | ||
|
|
9cc1497e9e | ||
|
|
cdd64d52eb | ||
|
|
4d319c12f8 | ||
|
|
8fc3e4ab12 | ||
|
|
ed7d68d6a7 | ||
|
|
59820519ce | ||
|
|
767c807a40 | ||
|
|
d25adc1b10 | ||
|
|
35f0067fe5 | ||
|
|
f1b01dd086 | ||
|
|
3df08d64e2 | ||
|
|
f56cc43331 | ||
|
|
b4b37daaf6 | ||
|
|
1f187d24c8 | ||
|
|
5b806a467b | ||
|
|
20d14d5a10 | ||
|
|
043b2df345 | ||
|
|
9ec7feb9ab | ||
|
|
57cf6db4e0 | ||
|
|
61b677c073 | ||
|
|
264e42a4c5 | ||
|
|
251fd660f9 | ||
|
|
6459f53263 | ||
|
|
55c8d93862 | ||
|
|
c6f83f8c14 | ||
|
|
c9eaca0e56 | ||
|
|
6267c17c6b | ||
|
|
616113d384 | ||
|
|
ac738aff10 | ||
|
|
7627bf80b9 | ||
|
|
172abb2710 | ||
|
|
a643c6ef1e | ||
|
|
64bfb0961e | ||
|
|
68d822f50a | ||
|
|
56e3bab02a | ||
|
|
9dd5ab4ebd | ||
|
|
b1ef86de75 | ||
|
|
b4a0d7a5b7 | ||
|
|
e6a93a799a | ||
|
|
4e175f9cd6 | ||
|
|
62e3fe1414 | ||
|
|
eeb7285528 | ||
|
|
0340b62b7c | ||
|
|
5488f60260 | ||
|
|
be7ef860d5 | ||
|
|
9aba700d8c | ||
|
|
7972acf5bf | ||
|
|
430c001d58 | ||
|
|
943777e5d0 | ||
|
|
c086c3b03b | ||
|
|
e517eceb24 | ||
|
|
7fb57a4064 | ||
|
|
888bca13c0 | ||
|
|
8b39e0631d | ||
|
|
d0d0148a58 | ||
|
|
a73b62c5bf | ||
|
|
bee0afd301 | ||
|
|
8f37940f4c | ||
|
|
0fa8d8cb51 | ||
|
|
1f589d0d5d | ||
|
|
ad36745a7c | ||
|
|
99b9860ea5 | ||
|
|
dc5f82cce2 | ||
|
|
dc3050537b | ||
|
|
5acd0dd2d1 | ||
|
|
0d933a1901 | ||
|
|
9f21865caf | ||
|
|
2ba81d3fef | ||
|
|
bcc1c2e658 | ||
|
|
5fa8972ae6 | ||
|
|
96363a0ce3 | ||
|
|
817fa9d9be | ||
|
|
89334bb459 | ||
|
|
0ae2d99599 | ||
|
|
e1199a02ee | ||
|
|
9408a61eb1 | ||
|
|
78d7e1bdfe | ||
|
|
dd44a0aaea | ||
|
|
b3144dd19a | ||
|
|
2722e96fac | ||
|
|
488de0014e | ||
|
|
9c2e0ebd4c | ||
|
|
28cc96cfd0 | ||
|
|
4ab3b15efd | ||
|
|
ff363e3893 | ||
|
|
cd2c10b6dc | ||
|
|
563e981902 | ||
|
|
c3e20d5d12 | ||
|
|
2802486671 | ||
|
|
1507d03c21 | ||
|
|
fbbf193345 | ||
|
|
78e51e6b11 | ||
|
|
be2bbec526 | ||
|
|
a366096ef4 | ||
|
|
c72222f718 | ||
|
|
fba0ec93bf | ||
|
|
86f767e1aa | ||
|
|
7e54192713 | ||
|
|
e76a73e276 | ||
|
|
ccf0490624 | ||
|
|
fe2721e04e | ||
|
|
fdd1a9afef | ||
|
|
abf7aed880 | ||
|
|
d986c7cdc0 | ||
|
|
9d5e994c01 | ||
|
|
6f16fc77b8 | ||
|
|
651dfb796c | ||
|
|
4f2fc17a8f | ||
|
|
7bc019547f | ||
|
|
f8c2629a3e | ||
|
|
b5b4bff2fc | ||
|
|
7054b92a14 | ||
|
|
5856f9a45f | ||
|
|
cec10060c6 | ||
|
|
74a479ab41 | ||
|
|
e51ab09bb1 | ||
|
|
0cd98bc353 | ||
|
|
158f9b0dc7 | ||
|
|
95fe6eaf86 | ||
|
|
40b4859b16 | ||
|
|
e4832f0d08 | ||
|
|
5d5400a9ac | ||
|
|
f439cad46c | ||
|
|
9fe2e8e31a | ||
|
|
92d3fc3d8c | ||
|
|
5d89599799 | ||
|
|
2eb5b5eb67 | ||
|
|
45549a8173 | ||
|
|
d7ebf2edc1 | ||
|
|
a9aed2e557 | ||
|
|
d691a0cf24 | ||
|
|
cbaa959521 | ||
|
|
2f128113b6 | ||
|
|
70251a8b2e | ||
|
|
e332f4e12b | ||
|
|
9a140ff93f | ||
|
|
97ab5dd1b5 | ||
|
|
075b4e92a9 | ||
|
|
f22dcfe03c | ||
|
|
124086419e | ||
|
|
0712db0d29 | ||
|
|
895f7edd12 | ||
|
|
a3c5c0c23a | ||
|
|
f7a3a6c17b | ||
|
|
98bec2580e | ||
|
|
5ca2d469a8 | ||
|
|
b413405876 | ||
|
|
330ff93e3e | ||
|
|
fe08104d18 | ||
|
|
e518605d69 | ||
|
|
9a35085ac3 | ||
|
|
b0cf41de08 | ||
|
|
00c3dc73f3 | ||
|
|
a73cc93d21 | ||
|
|
5a10299074 | ||
|
|
77d243f87f | ||
|
|
fb4f6406c9 | ||
|
|
3133b9b010 | ||
|
|
12723167fc | ||
|
|
2cc22778b5 | ||
|
|
790d3f12a6 | ||
|
|
beb1ab81e0 | ||
|
|
e5126b4c65 | ||
|
|
a2a4df5d06 | ||
|
|
ac0bd9714b | ||
|
|
60226d9195 | ||
|
|
64455b9852 | ||
|
|
96f6cdf677 | ||
|
|
c188491289 | ||
|
|
e9e4d566a5 | ||
|
|
85bedca236 | ||
|
|
d80191df3d | ||
|
|
9137e92c09 | ||
|
|
721dae3892 | ||
|
|
1cdacf69be | ||
|
|
b5b002aa4b | ||
|
|
78f5b513c0 | ||
|
|
0032fcaa66 | ||
|
|
0fba0923c8 | ||
|
|
e0169f6696 | ||
|
|
28217f10cb | ||
|
|
fb28f4bcd0 | ||
|
|
8852256ab6 | ||
|
|
95de453677 | ||
|
|
5ef40e15c4 | ||
|
|
31f223bff5 | ||
|
|
9fce2b1d8e | ||
|
|
a6ceb337b2 | ||
|
|
f4e22cb44c | ||
|
|
ab9750f8b2 | ||
|
|
fe8e0b0e0a | ||
|
|
c2565cf3b7 | ||
|
|
af82971bf5 | ||
|
|
271b52158e | ||
|
|
26c404adee | ||
|
|
f06af54165 | ||
|
|
2a77dfbcd2 | ||
|
|
738fcb6563 | ||
|
|
3d4754d4ad | ||
|
|
b9ea1d1be4 | ||
|
|
b1b0484dae | ||
|
|
20b79784bf | ||
|
|
4baa3358df | ||
|
|
8fe7f8b8d8 | ||
|
|
6996a0db2b | ||
|
|
b89a899c82 | ||
|
|
bbbbb660b3 | ||
|
|
6ba29219e5 | ||
|
|
dd97bdcc2c | ||
|
|
b63e0f08bf | ||
|
|
c5ae9d45ad | ||
|
|
e906a0da8c | ||
|
|
2edfb0aaac | ||
|
|
dc116858a9 | ||
|
|
1a938f8711 | ||
|
|
fc88cd3cb1 | ||
|
|
55205e631b | ||
|
|
a36fa76d21 | ||
|
|
b8d512f5e1 | ||
|
|
d4263b59c6 | ||
|
|
e5e1507dff | ||
|
|
2edf63c5fd | ||
|
|
5ec4b3441e | ||
|
|
dd1757b3c3 | ||
|
|
dda26545e5 | ||
|
|
410ef8ce96 | ||
|
|
ce7cb9cf64 | ||
|
|
31a16375ab | ||
|
|
ec7b47da22 | ||
|
|
0124020ba4 | ||
|
|
28f71d18bd | ||
|
|
fe226c1c8d | ||
|
|
18e20de4d6 | ||
|
|
956d345e17 | ||
|
|
ddfb958647 | ||
|
|
145d0ef37d | ||
|
|
019e3956f7 | ||
|
|
a72daff4ac | ||
|
|
58ce9cd37f | ||
|
|
687bdaff8f | ||
|
|
2143a66ad6 | ||
|
|
74892f1562 | ||
|
|
4a59ac011f | ||
|
|
e0fd2e8f27 | ||
|
|
ba76506773 | ||
|
|
d224827544 | ||
|
|
8d35b5bd11 | ||
|
|
9df28c25d7 | ||
|
|
5f9b2a91fd | ||
|
|
46a46f5e49 | ||
|
|
4bdc495d01 | ||
|
|
e60d5e6aeb | ||
|
|
7c3387755d | ||
|
|
6f04dad428 | ||
|
|
6ed4720df3 | ||
|
|
ac7b454039 | ||
|
|
0af39de346 | ||
|
|
d484979fe8 | ||
|
|
6e87e5c05f | ||
|
|
7633c8e76e | ||
|
|
c78e89c3c1 | ||
|
|
1852aaf332 | ||
|
|
8b4c8f63c0 | ||
|
|
d7b64c18c2 | ||
|
|
09668c972e | ||
|
|
68a0d10443 | ||
|
|
0708e7f8f6 | ||
|
|
1235e989d4 | ||
|
|
3a6808e4d8 | ||
|
|
dbfb034548 | ||
|
|
94d01e9e5a | ||
|
|
5e48b49b7e | ||
|
|
3b0785cae0 | ||
|
|
bd3b46d624 | ||
|
|
1cbe996831 | ||
|
|
18865c44c8 | ||
|
|
ead6ca73e5 | ||
|
|
deb3f6d9c4 | ||
|
|
b1b98c5256 | ||
|
|
4dc2227f23 | ||
|
|
a76f9e11fb | ||
|
|
abeb91a5e4 | ||
|
|
6d5e7cbe08 | ||
|
|
c468c26ad6 | ||
|
|
a0e940c5a9 | ||
|
|
2f1de22cae | ||
|
|
4631282709 | ||
|
|
306ac5243a | ||
|
|
956fe42a6c | ||
|
|
1824bdfe7e | ||
|
|
5f53284cbd | ||
|
|
7a84b71eb2 | ||
|
|
85382cd6c2 | ||
|
|
02a99f1e51 | ||
|
|
fe405df704 | ||
|
|
ac5ee90c9b | ||
|
|
fb6b34e155 | ||
|
|
caa8932c9a | ||
|
|
75611f3bca | ||
|
|
f0f14d8a22 | ||
|
|
98ad6cd23b | ||
|
|
bd80d1cd76 | ||
|
|
5a4670ec2f | ||
|
|
6fd039925a | ||
|
|
cd602ab5e3 | ||
|
|
f59ead54d3 | ||
|
|
4030f1e40d | ||
|
|
b7ac7452f7 | ||
|
|
5dd6867408 | ||
|
|
9d410df287 | ||
|
|
fe8dc36074 | ||
|
|
0cef3fbf27 | ||
|
|
b5d9b18da4 | ||
|
|
dc0ea197cd | ||
|
|
5bf17fc5ae | ||
|
|
33ca5943fa | ||
|
|
edc6591041 | ||
|
|
113ec33743 | ||
|
|
8c297832f6 | ||
|
|
e767b2ff94 | ||
|
|
a1ff408c13 | ||
|
|
440184e83c | ||
|
|
8ee6cad7ea | ||
|
|
edb17b76f0 | ||
|
|
31dc5f335d | ||
|
|
eb68e4c627 | ||
|
|
98e97920ae | ||
|
|
533723cd8b | ||
|
|
9e69afbbd6 | ||
|
|
2dea76dfa1 | ||
|
|
8a8bafb199 | ||
|
|
5a21d8c24d | ||
|
|
5111b4799c | ||
|
|
528bbe0116 | ||
|
|
3030ab8664 | ||
|
|
2698ff1a04 | ||
|
|
084dd1c8dd | ||
|
|
a8392889de | ||
|
|
3bf5edc2b3 | ||
|
|
97be0ff22a | ||
|
|
b43c8c018b | ||
|
|
38a5a4b97b | ||
|
|
73d70b6953 | ||
|
|
6b06733192 | ||
|
|
359146f60b | ||
|
|
0931c6a7e1 | ||
|
|
f2049c5910 | ||
|
|
de76827dd8 | ||
|
|
0cae3ac5a1 | ||
|
|
4fc378d3e2 | ||
|
|
e3e11d233c | ||
|
|
fcfd5c7419 | ||
|
|
be8c498aea | ||
|
|
5528b9ba09 | ||
|
|
c60877b6f2 | ||
|
|
07901946d0 | ||
|
|
705ea18b2a | ||
|
|
3277cc3675 | ||
|
|
c09b7bed34 | ||
|
|
83e633534d | ||
|
|
8a2c299653 | ||
|
|
74dc2ed1f9 | ||
|
|
dc0d6a9b4a | ||
|
|
3f264097a7 | ||
|
|
e0c7b17bd5 | ||
|
|
d43b027c25 | ||
|
|
85963cafe7 | ||
|
|
d4deeb4edd | ||
|
|
c72bfe3685 | ||
|
|
90137f2263 | ||
|
|
d8474cfafa | ||
|
|
493a756aaa | ||
|
|
95d30ba4ec | ||
|
|
dbcb3e6192 | ||
|
|
4228642b53 | ||
|
|
acba87ae46 | ||
|
|
533f17b3b0 | ||
|
|
77de71d79d | ||
|
|
caadb7fa27 | ||
|
|
1dd862f83d | ||
|
|
70bb4930f6 | ||
|
|
852eb5c524 | ||
|
|
3cfc45c4e8 | ||
|
|
db97c2a5b1 | ||
|
|
70993256b9 | ||
|
|
a439c3be3c | ||
|
|
0a060982e3 | ||
|
|
7ffcc176cd | ||
|
|
4a9650df80 | ||
|
|
f1c6f09f98 | ||
|
|
f039c0636e | ||
|
|
a620e1490c | ||
|
|
d682361cfc | ||
|
|
d3f0a14867 | ||
|
|
83393f299a | ||
|
|
bf1285567e | ||
|
|
e315726001 | ||
|
|
2f3e172162 | ||
|
|
d6cf9bd8ae | ||
|
|
5710a35388 | ||
|
|
1156d00538 | ||
|
|
5707354a18 | ||
|
|
155cc4573c | ||
|
|
3288592d30 | ||
|
|
886b683739 | ||
|
|
95cffca5f1 | ||
|
|
85cb592a7e | ||
|
|
13b9deb5ef | ||
|
|
c307c692a0 | ||
|
|
008e98d980 | ||
|
|
b11f597521 | ||
|
|
944c523a49 | ||
|
|
3c365259cc | ||
|
|
98274d4b17 | ||
|
|
12a1cb9e97 | ||
|
|
d273750849 | ||
|
|
75c54c6738 | ||
|
|
ffd72fbb4d | ||
|
|
71dc3d4826 | ||
|
|
b7757d71bf | ||
|
|
55338e731b | ||
|
|
097aa3fa16 | ||
|
|
935d6a7cf5 | ||
|
|
c69d1c7fb8 | ||
|
|
b5152c0c48 | ||
|
|
ed02df113f | ||
|
|
2afdcf54ab | ||
|
|
764fbe7fac | ||
|
|
0c9160ec8b | ||
|
|
33bed487ac | ||
|
|
3e36382b58 | ||
|
|
7ec656db09 | ||
|
|
cf61779b08 | ||
|
|
71600a4f37 | ||
|
|
14320f2155 | ||
|
|
1923368353 | ||
|
|
752bd78de5 | ||
|
|
c4b17855e5 | ||
|
|
a1543f79cb | ||
|
|
d4798ccaa5 | ||
|
|
c2c4ed1fe5 | ||
|
|
614188c82b | ||
|
|
53e98c114a | ||
|
|
73c8246204 | ||
|
|
58d98f8454 | ||
|
|
7605396e84 | ||
|
|
cec339552e | ||
|
|
fc003db139 | ||
|
|
caf434aef2 | ||
|
|
5261873f39 | ||
|
|
421b58f68e | ||
|
|
850dbd62c6 | ||
|
|
2af45da0a8 | ||
|
|
685e8bac22 | ||
|
|
47002f970d | ||
|
|
f6fd395485 | ||
|
|
4f426dafef | ||
|
|
7b6f2863a9 | ||
|
|
834a9bc84d | ||
|
|
7710a1fdb0 | ||
|
|
4abdc29d9e | ||
|
|
a4295d1e93 | ||
|
|
c9ff6be881 | ||
|
|
40a8892cb7 | ||
|
|
933b77e429 | ||
|
|
ccc4386285 | ||
|
|
4364ba46e2 | ||
|
|
d7917a6a9a | ||
|
|
81e30e75c4 | ||
|
|
7a94343dec | ||
|
|
9a77e6b3cc | ||
|
|
a1727cc047 | ||
|
|
5b012b6509 | ||
|
|
c23ffa2ce5 | ||
|
|
ff68383732 | ||
|
|
bce2b2adb6 | ||
|
|
fa8c9a8418 | ||
|
|
f6bb6037f3 | ||
|
|
7fac7c8713 | ||
|
|
bdaef0b0dc | ||
|
|
134cb68396 | ||
|
|
a299533508 | ||
|
|
d4bcbc3771 | ||
|
|
d8264fada7 | ||
|
|
1f636bf7a9 |
@@ -1,11 +1,15 @@
|
||||
# Binaries
|
||||
\.dll$
|
||||
\.dylib$
|
||||
\.exe$
|
||||
\.so$
|
||||
|
||||
# Files generated by Visual Studio
|
||||
\.aps$
|
||||
\.ipch$
|
||||
\.ncb$
|
||||
\.opensdf$
|
||||
\.sdf$
|
||||
\.suo$
|
||||
\.user$
|
||||
|
||||
@@ -13,3 +17,12 @@
|
||||
/CrazyDebug.*
|
||||
/Debug.*
|
||||
/Release.*
|
||||
|
||||
# Files generated by Mac OS X Finder
|
||||
(^|/)\.DS_Store$
|
||||
|
||||
# Files generated by Windows Explorer
|
||||
(^|/)[dD]esktop\.ini$
|
||||
(^|/)[tT]humbs\.db$
|
||||
syntax: glob
|
||||
build/*
|
||||
|
||||
@@ -3,3 +3,4 @@ e6ef5ecdf8d75740ca2685a709bf321f8873bc3b sourcemod-1.1.0
|
||||
e877885fac80be71822641f7a9122cebc9812521 sourcemod-1.1.1
|
||||
b3ffa8a4511c4eadaf533fc790aa6b14f7f0c6ea sourcemod-1.1.2
|
||||
3a73bbf60f34befa9b66be03fa5974b394bb3411 sourcemod-1.2.0
|
||||
78a1f1b1c6fa86fd7691c70ebf48a9fb3dfb3c11 sourcemod-1.5.0
|
||||
|
||||
+499
@@ -0,0 +1,499 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
import sys
|
||||
from ambuild.command import Command
|
||||
from ambuild.command import ShellCommand
|
||||
from ambuild.command import SymlinkCommand
|
||||
|
||||
class ExtractDebugInfoCommand(Command):
|
||||
def __init__(self, binary, outfile):
|
||||
Command.__init__(self)
|
||||
self.binary = binary
|
||||
self.outfile = outfile
|
||||
|
||||
def run(self, runner, job):
|
||||
if AMBuild.cache['debug']:
|
||||
return
|
||||
|
||||
if not self.binary.NeedsRelink(self.outfile):
|
||||
return
|
||||
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
job.AddCommand(ShellCommand('objcopy --only-keep-debug ' + self.outfile + ' ' + self.outfile + '.dbg'))
|
||||
job.AddCommand(ShellCommand('objcopy --strip-debug ' + self.outfile))
|
||||
job.AddCommand(ShellCommand('objcopy --add-gnu-debuglink=' + os.path.basename(self.outfile) + '.dbg ' + self.outfile))
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
job.AddCommand(ShellCommand('dsymutil ' + self.outfile))
|
||||
job.AddCommand(ShellCommand('strip -S ' + self.outfile))
|
||||
|
||||
class SM:
|
||||
def __init__(self):
|
||||
self.compiler = Cpp.Compiler()
|
||||
|
||||
#Build SDK info
|
||||
self.possibleSdks = { }
|
||||
self.possibleSdks['ep1'] = {'sdk': 'HL2SDK', 'ext': '1.ep1', 'def': '1',
|
||||
'name': 'EPISODEONE', 'platform': ['windows', 'linux'],
|
||||
'dir': 'hl2sdk'}
|
||||
self.possibleSdks['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3',
|
||||
'name': 'ORANGEBOX', 'platform': ['windows', 'linux'],
|
||||
'dir': 'hl2sdk-ob'}
|
||||
self.possibleSdks['css'] = {'sdk': 'HL2SDKCSS', 'ext': '2.css', 'def': '6',
|
||||
'name': 'CSS', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-css'}
|
||||
self.possibleSdks['hl2dm'] = {'sdk': 'HL2SDKHL2DM', 'ext': '2.hl2dm', 'def': '7',
|
||||
'name': 'HL2DM', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-hl2dm'}
|
||||
self.possibleSdks['dods'] = {'sdk': 'HL2SDKDODS', 'ext': '2.dods', 'def': '8',
|
||||
'name': 'DODS', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-dods'}
|
||||
self.possibleSdks['tf2'] = {'sdk': 'HL2SDKTF2', 'ext': '2.tf2', 'def': '9',
|
||||
'name': 'TF2', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-tf2'}
|
||||
self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '10',
|
||||
'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-l4d'}
|
||||
self.possibleSdks['nd'] = {'sdk': 'HL2SDKND', 'ext': '2.nd', 'def': '11',
|
||||
'name': 'NUCLEARDAWN', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-nd'}
|
||||
self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '12',
|
||||
'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-l4d2'}
|
||||
self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
|
||||
'name': 'DARKMESSIAH', 'platform': ['windows'],
|
||||
'dir': 'hl2sdk-darkm'}
|
||||
self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '13',
|
||||
'name': 'ALIENSWARM', 'platform': ['windows'],
|
||||
'dir': 'hl2sdk-swarm'}
|
||||
self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4',
|
||||
'name': 'BLOODYGOODTIME', 'platform': ['windows'],
|
||||
'dir': 'hl2sdk-bgt'}
|
||||
self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5',
|
||||
'name': 'EYE', 'platform': ['windows'],
|
||||
'dir': 'hl2sdk-eye'}
|
||||
self.possibleSdks['csgo'] = {'sdk': 'HL2SDKCSGO', 'ext': '2.csgo', 'def': '15',
|
||||
'name': 'CSGO', 'platform': ['windows', 'linux', 'darwin'],
|
||||
'dir': 'hl2sdk-csgo'}
|
||||
# self.possibleSdks['portal2'] = {'sdk': 'HL2SDK-PORTAL2', 'ext': '2.portal2', 'def': '14',
|
||||
# 'name': 'PORTAL2', 'platform': ['windows'],
|
||||
# 'dir': 'hl2sdk-portal'}
|
||||
|
||||
self.sdkInfo = { }
|
||||
|
||||
if AMBuild.mode == 'config':
|
||||
#Detect compilers
|
||||
self.compiler.DetectAll(AMBuild)
|
||||
|
||||
self.hasMySql = AMBuild.options.hasMySql
|
||||
AMBuild.cache.CacheVariable('hasMySql', self.hasMySql)
|
||||
|
||||
AMBuild.cache.CacheVariable('debug', AMBuild.options.debug)
|
||||
|
||||
#Environment variable paths to external headers
|
||||
envvars = { 'MMSOURCE110': 'mmsource-1.10', 'MYSQL5': 'mysql-5.0' }
|
||||
|
||||
#Look for Metamod:Source and MySQL if not disabled
|
||||
for env in envvars:
|
||||
if not self.hasMySql and env == 'MYSQL5':
|
||||
continue
|
||||
path = self.ResolveEnvPath(env, envvars[env])
|
||||
if path == None:
|
||||
raise Exception('Could not find a valid path for {0}'.format(env))
|
||||
AMBuild.cache.CacheVariable(env, path)
|
||||
|
||||
#Look for SDK directories
|
||||
for sdk in self.possibleSdks:
|
||||
#Get list of SDKs to build against or 'all' or 'present'
|
||||
sdkList = AMBuild.options.sdks.split(',')
|
||||
#Build against all supported SDKs?
|
||||
useAll = sdkList[0] == 'all'
|
||||
#Build against supported SDKs that exist?
|
||||
usePresent = sdkList[0] == 'present'
|
||||
|
||||
info = self.possibleSdks[sdk]
|
||||
if AMBuild.target['platform'] in info['platform']:
|
||||
env = info['sdk']
|
||||
dir = info['dir']
|
||||
sdkPath = self.ResolveEnvPath(env, dir)
|
||||
if sdkPath == None:
|
||||
if useAll or sdk in sdkList:
|
||||
raise Exception('Could not find a valid path for {0}'.format(env))
|
||||
else:
|
||||
continue
|
||||
if useAll or usePresent or sdk in sdkList:
|
||||
self.sdkInfo[sdk] = info
|
||||
AMBuild.cache.CacheVariable(env, sdkPath)
|
||||
|
||||
if len(self.sdkInfo) < 1:
|
||||
raise Exception('At least one SDK must be available.')
|
||||
|
||||
AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo)
|
||||
|
||||
#Set up defines
|
||||
cxx = self.compiler.cxx
|
||||
if isinstance(cxx, Cpp.CompatGCC):
|
||||
if isinstance(cxx, Cpp.GCC):
|
||||
self.vendor = 'gcc'
|
||||
elif isinstance(cxx, Cpp.Clang):
|
||||
self.vendor = 'clang'
|
||||
self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
|
||||
self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
|
||||
self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
|
||||
self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
|
||||
self.compiler.AddToListVar('CFLAGS', '-pipe')
|
||||
self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
|
||||
if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang':
|
||||
self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wall')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Werror')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
|
||||
self.compiler.AddToListVar('CFLAGS', '-msse')
|
||||
self.compiler.AddToListVar('CFLAGS', '-g3')
|
||||
self.compiler.AddToListVar('CFLAGS', '-m32')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-m32')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual')
|
||||
if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 7) or \
|
||||
(self.vendor == 'clang' and cxx.majorVersion >= 3):
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor')
|
||||
self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
|
||||
self.compiler.AddToListVar('CDEFINES', 'GNUC')
|
||||
if self.vendor == 'gcc':
|
||||
self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
|
||||
elif isinstance(cxx, Cpp.MSVC):
|
||||
self.vendor = 'msvc'
|
||||
if AMBuild.options.debug == '1':
|
||||
self.compiler.AddToListVar('CFLAGS', '/MTd')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
|
||||
else:
|
||||
self.compiler.AddToListVar('CFLAGS', '/MT')
|
||||
self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
|
||||
self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
|
||||
self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '/GR-')
|
||||
self.compiler.AddToListVar('CFLAGS', '/W3')
|
||||
self.compiler.AddToListVar('CFLAGS', '/nologo')
|
||||
self.compiler.AddToListVar('CFLAGS', '/Zi')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '/TP')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
|
||||
|
||||
#Optimization
|
||||
if AMBuild.options.opt == '1':
|
||||
self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
|
||||
if self.vendor == 'gcc' or self.vendor == 'clang':
|
||||
self.compiler.AddToListVar('CFLAGS', '-O3')
|
||||
elif self.vendor == 'msvc':
|
||||
self.compiler.AddToListVar('CFLAGS', '/Ox')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
|
||||
|
||||
#Debugging
|
||||
if AMBuild.options.debug == '1':
|
||||
self.compiler.AddToListVar('CDEFINES', 'DEBUG')
|
||||
self.compiler.AddToListVar('CDEFINES', '_DEBUG')
|
||||
if self.vendor == 'msvc':
|
||||
self.compiler.AddToListVar('CFLAGS', '/Od')
|
||||
self.compiler.AddToListVar('CFLAGS', '/RTC1')
|
||||
|
||||
#This needs to be after our optimization flags which could otherwise disable it.
|
||||
if self.vendor == 'msvc':
|
||||
# Don't omit frame pointer
|
||||
self.compiler.AddToListVar('CFLAGS', '/Oy-')
|
||||
|
||||
#Platform-specifics
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
self.compiler.AddToListVar('CDEFINES', '_LINUX')
|
||||
self.compiler.AddToListVar('CDEFINES', 'POSIX')
|
||||
if self.vendor == 'gcc':
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
|
||||
if self.vendor == 'clang':
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh')
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
self.compiler.AddToListVar('CDEFINES', 'OSX')
|
||||
self.compiler.AddToListVar('CDEFINES', '_OSX')
|
||||
self.compiler.AddToListVar('CDEFINES', 'POSIX')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386'])
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++')
|
||||
|
||||
# For OS X dylib versioning
|
||||
import re
|
||||
productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r')
|
||||
productContents = productFile.read()
|
||||
productFile.close()
|
||||
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
|
||||
if m == None:
|
||||
self.version = '1.0.0'
|
||||
else:
|
||||
major, minor, release = m.groups()
|
||||
self.version = '{0}.{1}.{2}'.format(major, minor, release)
|
||||
AMBuild.cache.CacheVariable('version', self.version)
|
||||
elif AMBuild.target['platform'] == 'windows':
|
||||
self.compiler.AddToListVar('CDEFINES', 'WIN32')
|
||||
self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
|
||||
|
||||
#Finish up
|
||||
self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
|
||||
self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
|
||||
self.compiler.AddToListVar('CINCLUDES',
|
||||
os.path.join(AMBuild.outputFolder, 'includes'))
|
||||
self.compiler.ToConfig(AMBuild, 'compiler')
|
||||
AMBuild.cache.CacheVariable('vendor', self.vendor)
|
||||
self.targetMap = { }
|
||||
AMBuild.cache.CacheVariable('targetMap', self.targetMap)
|
||||
else:
|
||||
self.sdkInfo = AMBuild.cache['sdkInfo']
|
||||
self.compiler.FromConfig(AMBuild, 'compiler')
|
||||
self.targetMap = AMBuild.cache['targetMap']
|
||||
self.hasMySql = AMBuild.cache['hasMySql']
|
||||
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
|
||||
self.compiler.AddToListVar('RCINCLUDES',
|
||||
os.path.join(AMBuild.outputFolder, 'includes'))
|
||||
self.mmsPath = AMBuild.cache['MMSOURCE110']
|
||||
|
||||
def DefaultCompiler(self):
|
||||
return self.compiler.Clone()
|
||||
|
||||
def JobMatters(self, jobname):
|
||||
file = sys._getframe().f_code.co_filename
|
||||
if AMBuild.mode == 'config':
|
||||
self.targetMap[jobname] = file
|
||||
return True
|
||||
if len(AMBuild.args) == 0:
|
||||
return True
|
||||
if not jobname in AMBuild.args:
|
||||
return False
|
||||
|
||||
def DefaultExtCompiler(self, path):
|
||||
compiler = self.DefaultCompiler()
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
|
||||
return compiler
|
||||
|
||||
def AutoVersion(self, folder, binary):
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
|
||||
binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
|
||||
elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder):
|
||||
binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0'])
|
||||
binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']])
|
||||
else:
|
||||
return
|
||||
|
||||
def ExtractDebugInfo(self, job, binary):
|
||||
src = os.path.join('..', AMBuild.outputFolder, job.workFolder, binary.binaryFile)
|
||||
job.AddCommand(ExtractDebugInfoCommand(binary, src))
|
||||
|
||||
def PreSetupHL2Job(self, job, builder, sdk):
|
||||
info = self.sdkInfo[sdk]
|
||||
sdkPath = AMBuild.cache[info['sdk']]
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
if sdk == 'ep1':
|
||||
staticLibs = os.path.join(sdkPath, 'linux_sdk')
|
||||
else:
|
||||
staticLibs = os.path.join(sdkPath, 'lib', 'linux')
|
||||
workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
|
||||
if sdk in ['css', 'hl2dm', 'dods', 'tf2', 'l4d2']:
|
||||
libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib_srv.so', 'libtier0_srv.so']
|
||||
for lib in libs:
|
||||
link = os.path.join(workFolder, lib)
|
||||
target = os.path.join(staticLibs, lib)
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
job.AddCommand(SymlinkCommand(link, target))
|
||||
elif sdk in ['l4d', 'nd', 'csgo']:
|
||||
libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']
|
||||
if sdk == 'csgo':
|
||||
libs.append('interfaces_i486.a')
|
||||
for lib in libs:
|
||||
link = os.path.join(workFolder, lib)
|
||||
target = os.path.join(staticLibs, lib)
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
job.AddCommand(SymlinkCommand(link, target))
|
||||
else:
|
||||
libs = ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']
|
||||
for lib in libs:
|
||||
link = os.path.join(workFolder, lib)
|
||||
target = os.path.join(staticLibs, lib)
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
job.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
staticLibs = os.path.join(sdkPath, 'lib', 'mac')
|
||||
workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
|
||||
libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib']
|
||||
if sdk == 'csgo':
|
||||
libs.append('interfaces_i486.a')
|
||||
for lib in libs:
|
||||
link = os.path.join(workFolder, lib)
|
||||
target = os.path.join(staticLibs, lib)
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
job.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'windows':
|
||||
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
||||
if sdk in ['swarm', 'csgo']:
|
||||
libs.append('interfaces')
|
||||
for lib in libs:
|
||||
libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
|
||||
builder.RebuildIfNewer(libPath)
|
||||
builder['POSTLINKFLAGS'].append(libPath)
|
||||
|
||||
def PostSetupHL2Job(self, job, builder, sdk):
|
||||
if AMBuild.target['platform'] in ['linux', 'darwin']:
|
||||
builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
|
||||
if sdk == 'csgo':
|
||||
builder.AddObjectFiles(['interfaces_i486.a'])
|
||||
|
||||
def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
|
||||
compiler = self.DefaultExtCompiler(path)
|
||||
|
||||
mms = 'core'
|
||||
if sdk == 'ep1':
|
||||
mms += oldMms
|
||||
|
||||
compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
|
||||
|
||||
info = self.possibleSdks
|
||||
compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
|
||||
|
||||
# We don't build for Portal 2 (yet?, ever?), but using this define in code as
|
||||
# it saves trouble if we ever need to
|
||||
compiler['CDEFINES'].append('SE_PORTAL2=14')
|
||||
|
||||
paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
|
||||
['public', 'tier0'], ['public', 'tier1']]
|
||||
if sdk == 'ep1' or sdk == 'darkm':
|
||||
paths.append(['public', 'dlls'])
|
||||
paths.append(['game_shared'])
|
||||
else:
|
||||
paths.append(['public', 'game', 'server'])
|
||||
paths.append(['public', 'toolframework'])
|
||||
paths.append(['game', 'shared'])
|
||||
paths.append(['common'])
|
||||
|
||||
info = self.sdkInfo[sdk]
|
||||
sdkPath = AMBuild.cache[info['sdk']]
|
||||
|
||||
compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
|
||||
|
||||
if sdk in ['swarm','csgo']:
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
|
||||
else:
|
||||
compiler['CDEFINES'].extend(['COMPILER_GCC'])
|
||||
|
||||
if sdk == 'ep1':
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
staticLibs = os.path.join(sdkPath, 'linux_sdk')
|
||||
else:
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
staticLibs = os.path.join(sdkPath, 'lib', 'linux')
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
staticLibs = os.path.join(sdkPath, 'lib', 'mac')
|
||||
|
||||
for i in paths:
|
||||
compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
|
||||
|
||||
if not noLink:
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['-lm']
|
||||
if sdk in ['css', 'hl2dm', 'dods', 'tf2', 'l4d2']:
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libtier0_srv.so']
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib_srv.so']
|
||||
elif sdk in ['l4d', 'nd', 'csgo']:
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
|
||||
else:
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib']
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib']
|
||||
|
||||
return compiler
|
||||
|
||||
def ResolveEnvPath(self, env, defaultDir):
|
||||
if env in os.environ:
|
||||
path = os.environ[env]
|
||||
if os.path.isdir(path):
|
||||
return path
|
||||
else:
|
||||
head = os.getcwd()
|
||||
oldhead = None
|
||||
while head != None and head != oldhead:
|
||||
path = os.path.join(head, defaultDir)
|
||||
if os.path.isdir(path):
|
||||
return path
|
||||
oldhead = head
|
||||
head, tail = os.path.split(head)
|
||||
return None
|
||||
|
||||
sm = SM()
|
||||
globals = {
|
||||
'SM': sm
|
||||
}
|
||||
|
||||
AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
|
||||
|
||||
FileList = [
|
||||
['loader', 'AMBuilder'],
|
||||
['core', 'AMBuilder'],
|
||||
['core', 'logic', 'AMBuilder'],
|
||||
['extensions', 'bintools', 'AMBuilder'],
|
||||
['extensions', 'clientprefs', 'AMBuilder'],
|
||||
['extensions', 'cstrike', 'AMBuilder'],
|
||||
['extensions', 'curl', 'AMBuilder'],
|
||||
['extensions', 'geoip', 'AMBuilder'],
|
||||
['extensions', 'mysql', 'AMBuilder'],
|
||||
['extensions', 'sdkhooks', 'AMBuilder'],
|
||||
['extensions', 'sdktools', 'AMBuilder'],
|
||||
['extensions', 'topmenus', 'AMBuilder'],
|
||||
['extensions', 'updater', 'AMBuilder'],
|
||||
['extensions', 'sqlite', 'AMBuilder'],
|
||||
['extensions', 'regex', 'AMBuilder'],
|
||||
['extensions', 'tf2', 'AMBuilder'],
|
||||
['sourcepawn', 'jit', 'AMBuilder'],
|
||||
['sourcepawn', 'compiler', 'AMBuilder'],
|
||||
['plugins', 'AMBuilder'],
|
||||
['tools', 'buildbot', 'PackageScript'],
|
||||
['tools', 'buildbot', 'BreakpadSymbols']
|
||||
]
|
||||
|
||||
if not sm.hasMySql:
|
||||
FileList.remove(['extensions', 'mysql', 'AMBuilder'])
|
||||
|
||||
for parts in FileList:
|
||||
AMBuild.Include(os.path.join(*parts), globals)
|
||||
|
||||
@@ -3,4 +3,3 @@ CONFIGURE YOUR IDENTITY FOR MERCURIAL!
|
||||
IF YOU ARE A DEVELOPER WITH PUSH ACCESS, DO IT NOW KPLZTHX.
|
||||
|
||||
http://wiki.alliedmods.net/Mercurial_Tutorial#Identity
|
||||
|
||||
|
||||
+646
@@ -1,5 +1,651 @@
|
||||
SourceMod Changelog
|
||||
|
||||
SourceMod 1.5.1 [2013-09-10]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.5.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated gamedata support for TF2.
|
||||
- Added missing DispatchKeyValue gamedata for HL2 CTF (bug 5114) (peace-maker).
|
||||
- Fixed translations not being loaded if identifier was not two or three characters (fixes Portuguese) (bug 5888).
|
||||
- Fixed runoff voting occurring when receiving the exact number of required votes (bug 5890).
|
||||
- Fixed reserve slot plugin hiding too many slots on Orangebox gamesif SourceTV and/or Replay are present (bug 5499).
|
||||
- Fixed some crashes in TF2 and unexpected behavior in all games with SDKHook_TakeDamage due to uninitialized var.
|
||||
- Fixed attempted triggers from gagged users displaying in chat (bug 5918, r=asherkin).
|
||||
- Fixed errors in Italian translation (Oktober).
|
||||
- Added Norwegian translation (checkster).
|
||||
|
||||
Developer Changes:
|
||||
- Added CS_UpdateClientModel native to CStrike extension for CS:S and CS:GO (bug 5905) (Drifter).
|
||||
- Fixed setting weapon param in SDKHook_TakeDamage overwriting attacker instead of setting weapon (bug 5911) (KyleS)
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.5.0 [2013-08-25]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.5.0_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added support for Counter-Strike: Global Offensive (bug 5299, bug 5579).
|
||||
- Split CS:S, TF2, DoD:S, HL2:DM, and ND to separate binaries (bug 5370, bug 5813).
|
||||
- Added support for runoff voting in mapchooser (bug 4218).
|
||||
- Added option to require Steam validation before granting admin access (bug 4837) (VoiDeD).
|
||||
- Added localization support for many more core and base plugin messages (bug 5120, bug 5146).
|
||||
- Added the ability to override RegConsoleCommand-created commands (bug 5199).
|
||||
- Added support for "fuzzy" (partial) map names in map-related natives and cmds for L4D and later (bug 5599).
|
||||
- Updated Reserved Slots to use max humans as max count (bug 5444).
|
||||
- Added support for custom maxitems on radio menus (bug 5371).
|
||||
- Improved console config editing (bug 5470).
|
||||
- Increased map name buffer sizes in mapchooser to better account for nested maps (bug 5609) (Peace-Maker).
|
||||
- Fixed JIT conflicts with SELinux (bug 5581).
|
||||
- Added logged error when PlayerRunCommand offset lookup fails (bug 5535) (GoD-Tony).
|
||||
- Fixed double print when sending psay to self (bug 5649) (Peace-Maker).
|
||||
- Fixed check against uninitialized string in extension loader (bug 5546) (KyleS).
|
||||
- Fixed possible runtime errors in basetriggers for not-ingame clients (bug 5191) (Peace-Maker).
|
||||
- Check all possible mapcycle paths on newer orangebox games (bug 5719).
|
||||
- Fixed ReadMapList not seeing maps in all valve search paths (bug 5715) (VoiDeD).
|
||||
- Fixed typo in too-many-params native error message (Peace-Maker).
|
||||
- Fixed various issues in clientprefs (bug 5538) (KyleS).
|
||||
- Removed debug printout from PerformGravity (bug 5679) (KyleS).
|
||||
- Fixed broken translating in some plugins and natives (bug 5612) (KyleS).
|
||||
- Fixed issues with COMMAND_FILTER_NO_BOTS and @bots multi-target.
|
||||
- Fixed crash in SDKHooks when throwing bad ent type error on logical ent (KyleS).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added support for CS:GO to the CStrike extension (bug 5299) (Drifter).
|
||||
- Added support for new protobuf usermessages used in newer games (bug 5579, bug 5588, bug 5590, bug 5633).
|
||||
- Added latest SDKHooks version as first-party extension.
|
||||
- Updated SQLite to version 3.7.15.1 (bug 5235).
|
||||
- Added natives for changing team score and mvp stars on CSS/CSGO (bug 5295) (Drifter).
|
||||
- Added global pre and post forwards for client chat (bug 5394) (KyleS).
|
||||
- Added TF2_CanPlayerTeleport forward to the TF2 game extension (bug 5283) (VoiDeD).
|
||||
- Added GetEntityAddress native (bug 5269) (ProdigySim).
|
||||
- Added more parameters to PlayerRunCommand forward (bug 5346) (GoD-Tony).
|
||||
- Added forwards to basecomm plugin (bug 5466) (Drifter).
|
||||
- Added symbol lookup support to gamedata on Windows (bug 5511) (GoD-Tony).
|
||||
- Exposed GetLanguageInfo in ITranslator interface (bug 5249) (VoiDeD).
|
||||
- Increase maximum .sp line length to 4095 characters. (bug 5347) (theY4Kman).
|
||||
- Improved netprop dump output (bug 5471).
|
||||
- Added int64 typename to netprop dumps (bug 5655).
|
||||
- Added GetMaxHumanPlayers native exposing IServerGameClients func (bug 5551).
|
||||
- Added WeaponIDToAlias native to CStrike extension (bug 5460) (KyleS).
|
||||
- Fixed OnLibraryAdded/Removed not being called in all plugins (bug 5431).
|
||||
- Made thread worker processing limits configurable at runtime (bug 5326).
|
||||
- Added support in TF2 ext for detection of player conds >= 64 (bug 5565).
|
||||
- Updated button defines in entity_prop_stocks (bug 5564).
|
||||
- Added GetPlayerResourceEntity to SDKTools to replace old, semi-broken TF2-only version (bug 5491).
|
||||
- Exposed third parameter of TF2's AddCond in TF2_AddCondition (bug 5641) (FlaminSarge).
|
||||
- Added GetSteamAccountID function to IPlayerHelpers and native for sp (bug 5548) (KyleS).
|
||||
- Added ISDKHooks interface with entity listeners (bug 5602) (GoD-Tony).
|
||||
- Added file upload support to webternet extension.
|
||||
- Added more alternative names for TFClass_Heavy (bug 5338) (Afronanny).
|
||||
- Throw error instead of crash when calling SetTeamScore between maps (bug 5718) (KyleS).
|
||||
- Fixed clients not being marked as in kick queue in some cases (bug 5746) (SystematicMania).
|
||||
- Made compile.sh set working dir to own dir (bug 5710) (KyleS).
|
||||
- Added CS_IsValidWeaponID native and validity checks to other natives (bug 5566) (Drifter).
|
||||
- Numerous code documentation fixups (bug 5720) (Tsunami).
|
||||
- Fixed cmd listener callback return behavior to match func doc (bug 5882).
|
||||
|
||||
Internal Changes:
|
||||
|
||||
- Fixed handle misuse in clientprefs plugin (bug 5805) (KyleS).
|
||||
- Removed call to getchar() in debug build of compiler (bug 5626) (KyleS).
|
||||
- Fixed instability issues with cloned handles (bug 5245, bug 5240) (KyleS).
|
||||
- Changed extension unload order to avoid exposing finalization window (bug 5556) (KyleS).
|
||||
- Call OnPluginEnd before finalizer hooks have run (bug 4519).
|
||||
- Fixed potential for reading out of library bounds in MemoryUtils::FindPattern.
|
||||
- Fixed typo in TF2 ext asm.c causing accidental assignment instead of compare.
|
||||
- Overhauled versioning information (bug 5453).
|
||||
- Changed from RemoveEdict to using the Kill input for TF2_RemoveWeapon.
|
||||
- Fixed accidental assignment in each of SDKTools and sp compiler (bug 5745) (KyleS).
|
||||
- Fixed potential deadlock in HandleSystem::TryAndFreeSomeHandles (bug 5665) (KyleS).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.4.7 [2013-02-06]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.7_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM).
|
||||
- Updated gamedata for Left 4 Dead 2, Nuclear Dawn, No More Room in Hell, Zombie Panic Source, CSPromod, GoldenEye Source, Synergy, The Hidden, and PVKII.
|
||||
- Added system to block malware or illegal plugins (bug 5289).
|
||||
- Fixed a potential crash when a bad entity index is passed to certain functions (bug 5539) (KyleS).
|
||||
- Added an error message for when auto plugin configs fail to be created due to write error (bug 5465) (Drifter).
|
||||
- Fixed an issue where a malformed plugin could cause crashes (bug 5478).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new values to the TFCond TF2 conditions enum (bug 5537) (FlaminSarge).
|
||||
- Updated TFHoliday TF2 holidays enum (bug 5526) (Powerlord).
|
||||
- Fixed regression in SourceMod 1.3.0 causing GetEntPropEnt, GetEntDataEnt2, and GameRules_GetPropEnt to possibly return stale (incorrect) entity indexes in place of -1.
|
||||
- Added support for < 32-bit unsigned sign extension to GameRules_GetProp lookup (already in GetEntProp since SM 1.4.0).
|
||||
- Fixed < 32-bit unsigned sign extension in GetEntProp not being applied for array prop elements (bug 5591).
|
||||
- Fixed value size auto-detection in GetEntProp and GameRules_GetProp for ep2v's new SPROP_VARINT sendprops.
|
||||
- Fixed Sort_Random sort type not including first value in array sorting functions (bug 4292) (Peace-Maker).
|
||||
- Fixed GameRules_SetPropVector writing data to unexpected addresses instead of to the gamerules proxy entity (bug 5592) (ProdigySim).
|
||||
- Fixed VoteMenuToAll stock adding bots to list (bug 5253 (VoiDeD).
|
||||
|
||||
----------------------------------------------------------
|
||||
SourceMod 1.4.6 [2012-09-04]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.6_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Fixed extraneous errors resulting from a bug in 1.4.5.
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
SourceMod 1.4.5 [2012-09-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.5_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated Nuclear Dawn, Dino D-Day, and Zombie Panic gamedata.
|
||||
- Added compatibility for running on Metamod:Source 1.9.0.
|
||||
- Fixed very minor memory leaks in CStrike extension (bug 5456) (KyleS).
|
||||
- Fixed crash from plugins accessing netprops too early (bug 5297) (KyleS).
|
||||
- Fixed crash from plugins trying to access nested datadesc members (bug 5446).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new TF2 weapon and custom dmg defines.
|
||||
- Added new TF2 TFHoliday value (bug 5436) (Powerlord).
|
||||
- Fixed IClientListener::InterceptClientConnect not being able to properly block connections (bug 5461) (PimpinJuice).
|
||||
- Fixed PrepSDKCall_SetSignature native not working with symbol names on L4D2 linux (bug 5440).
|
||||
- Fixed resolution of GetProfilerTime native on non-Windows platforms.
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.4 [2012-07-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.4_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated Nuclear Dawn gamedata.
|
||||
- Fixed a crash that could occur when selecting an option on a clientprefs prefab menu (bug 5374).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new TF2 weapon and custom dmg defines.
|
||||
- Added new TF2 TFHoliday value (bug 5364) (Powerlord).
|
||||
- Updated sample extension to properly fill ninvoke with INativeInvoker ptr (bug 5340) (Afronanny).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.3 [2012-06-09]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.3_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Made clientprefs attempt to reconnect to the database on map change (bug 4745).
|
||||
- Log functions now respect sv_logecho (bug 5135).
|
||||
- Fixed client console vote output (bug 5290, bug 5205) (FlaminSarge).
|
||||
- Fixed error when reloading dependant plugins using aliased natives (bug 5302).
|
||||
- Fixed intermittent crash when looking for an invalid signature (bug 5301).
|
||||
- Fixed possible crash when reloading a plugin with an invalid binary (bug 5288).
|
||||
- Exposed extensions list to clients (bug 5221) (VoiDeD).
|
||||
- Fixed intermittent crashes in clientprefs (bug 4660).
|
||||
- Fixed crash when passing an invalid entity reference to ReferenceToEntity (bug 5330).
|
||||
- Fixed cstrike extension crash on shutdown (bug 5328).
|
||||
- Lowered threading API think time to 20ms, making threaded MySQL queries complete faster (bug 4733).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Fixed client serials not being unique on Windows (bug 5285).
|
||||
- Fixed broken SourceTV detection on L4D1 (bug 5216).
|
||||
- Fixed Float negation operator (bug 5292).
|
||||
- Updated TF2 condition defines (bug 5259) (FlaminSarge).
|
||||
- Adding missing SetMenuNoVoteButton native declaration (bug 4522) (GoD-Tony).
|
||||
- Fixed erroneous const-qualification of name param of GetAdminUsername (bug 5267).
|
||||
- Added GetGameTickCount native (bug 5209) (GoD-Tony).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.2 [2011-04-13]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.2_Release_Notes
|
||||
|
||||
User Changes:
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Fixed regression in SourceMod 1.4.0 causing SM to cause load errors on The Ship (bug 5216).
|
||||
- Fixed toggling and player lag issues with sm_drug command (bugs 5217, 5218) (FlaminSarge).
|
||||
|
||||
Developer Changes:
|
||||
- Updated TF2-specific defines and enums (bug 5194).
|
||||
- Fixed StoreToAddress always writing 32 bits and throwing an error (bug 5248) (ProdigySim).
|
||||
- Fixed crash with StoreToAddress if memory wasn't writable (bug 5252) (Dr!fter).
|
||||
- Fixed return value of VoteMenuToAll (bug 5254) (VoiDeD).
|
||||
- Fixed bug in command lower-casing API guarantee
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.1 [2011-12-07]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Added gamedata for Adrenaline Gamer 2 and No More Room in Hell.
|
||||
- Fixed "not connected" error in reserve slots plugin (bug 5158) (ostrel).
|
||||
- Fixed ff trigger output printing to all in triggerer's language (rather than viewer's language) (bug 5161).
|
||||
- Fixed typo in one of basebans ban reasons (bug 5188).
|
||||
- Fixed formatting error in Swedish "Vote Count" phrase (bug 5174).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Fixed sp MaxClients not being updated on map changes after load (bug 5160).
|
||||
- Removed GLIBC_2.7 dependency from spcomp.
|
||||
- Increased buffer for sm_rcon command to fit larger responses (bug 5169).
|
||||
- BaseComm now properly registers a library allowing it to be required by other plugins (bug 5156).
|
||||
- Fixed TFHoliday enum values (bug 5155).
|
||||
- Updated TF2_OnIsHolidayActive ret behavior to match doc (bug 5155).
|
||||
- Added new TF2 deathflag and dmg custom defines (bug 5157).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.4.0 [2011-10-28]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.4.0_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added support for Max OS X (bug 4392).
|
||||
- Added support for Bloody Good Time (bug 4780).
|
||||
- Added support for E.Y.E Divine Cybermancy (bug 5035).
|
||||
- Added gamedata for Nuclear Dawn.
|
||||
- Added gamedata for International Online Soccer: Source (bug 5019).
|
||||
- Added gamedata for Half-Life 2 Capture the Flag (bug 5114).
|
||||
- Updated mapchooser and other base plugins with Nuclear Dawn specific fixes (bug 5117).
|
||||
- Fixed ServerLang value not being read properly on startup (bug 4675).
|
||||
- Added support for aliases in languages.cfg (bug 4858).
|
||||
- Added output display to sm_rcon command (bug 5018).
|
||||
- Flood protection bypass access can now be overridden with command name sm_flood_access (bug 4584).
|
||||
- Added a reset argument to sm cvars command to revset cvar values to default (bug 5043).
|
||||
- Fixed incorrect language identifiers for Chinese (both Trad. and Simplified) and Brazilian Portuguese not matching cl_language values (bug 5067).
|
||||
- Added translation support for Bulgarian (bg).
|
||||
- Fixed incorrect number of slots being hidden for reserve with sm_hideslots on Source 2009 with SourceTV or replay (bug 5094).
|
||||
- sm_hideslots changes now take effect immediately instead of waiting until a client joins or leaves (bug 5094).
|
||||
- Fixed sv_visiblemaxplayers getting stuck at previous max clients in some cases with reserves and SourceTV or replay (bug 5094).
|
||||
- Removed error logging if an optional extension is not found (bug 5112).
|
||||
- Fixed bots with semicolon in name being unkickable (bug 5120).
|
||||
- Changed strings in ice-related funcommands to be translatable (bug 4540).
|
||||
- Changed Bintools extension to use a single build for every engine (bug 4548).
|
||||
|
||||
Developer Changes:
|
||||
- Provided native interface for basecomm (bug 2594).
|
||||
- Client language detection is too late. (bug 3714) (Tony A. "GoD-Tony").
|
||||
- Added ServerCommandEx native to execute server command and retrieve output (bug 3873).
|
||||
- Added ability to update clientprefs cookies values on clients not currently connected (bug 3882) (databomb).
|
||||
- Added library "matchmaking_ds" support to gamedata lookups (bug 4158).
|
||||
- Rooted menu handles to callbacks (bug 4353).
|
||||
- Fixed corner cases with ExplodeString (bug 4629). (Michael "LumiStance").
|
||||
- Fixed return omission with else-after-return (bug 4852).
|
||||
- Added OnConditionAdded and OnConditionRemoved forwards to TF2 extension (bug 4851).
|
||||
- Added new natives and forward to the cstrike extension (bug 4732, bug 4985) (Dr!fter).
|
||||
- Added WaitingForPlayers forwards to the TF2 extension (bug 4704) (CrimsonGT).
|
||||
- Updated and added more TF2 condition, weapon, and damagecustom defines (multiple bug#s).
|
||||
- Fixed TF2_RemoveCondition not always removing conditions (bug 4981).
|
||||
- Fixed MaxClients not being updated correctly in some places with SourceTV or replay active (bug 4986).
|
||||
- Fixed some vars not being marked for init on first compile pass (bug 4643).
|
||||
- Increased symbol name limit to 63 characters (bug 4564) (javalia).
|
||||
- Fixed crash when dynamic arrays run out of memory (bug 4632).
|
||||
- Fixed a crash that could happen from looking up out-of-bounds edict or entity indexes (bug 5080).
|
||||
- Fixed client serials not getting cleared on disconnect (bug 5121).
|
||||
- Added error on declaring arrays that the compiler is too buggy to handle (bug 4977).
|
||||
- Removed reliance on gamedata for multiple SDKTools functions in ep2 and later (bug 4899).
|
||||
- Added InvalidateClient and ReconnectClient natives to SDKTools (bug 4931) (Brian "Afronanny" Simon).
|
||||
- Added ability to lookup and set values on the gamerules class (bug 4983.
|
||||
- BaseComm now uses AddCommandListener for chat hooks (bug 4991).
|
||||
- Fixed shutdown bug in SDKTools (bug 5063).
|
||||
- Fixed MM-enabled extensions continuing to load after failing MM attach (bug 5042).
|
||||
- Added GetDistGainFromSoundLevel native to SDKTools (bug 5066) (javalia).
|
||||
- Added CheckAccess native to check an AdminId's command access (bug 5083).
|
||||
- Fixed GetEntProp not sign-extending unsigned values less than 32 bits (bug 5105).
|
||||
- Fixed crashing when calling CreateEntityByName or CreateFakeClient when no map is running (now errors) (bug 5119).
|
||||
- Fixed erring in kick function (e. bad translation) causing client to become unkickable until disconnect (bug 5120).
|
||||
- Fixed KickClientEx not immediately kicking client if client was in kick queue (bug 5120).
|
||||
- Added IsClientSourceTV and IsClientReplay natives (bug 5124).
|
||||
- Added support for getting and setting individual array elements with Get/Set EntProp functions (bug 4160).
|
||||
- Added support for threaded query handles to SQL_GetInsertId and SQL_GetAffectedRows (bug 4699) (Nephyrin).
|
||||
- Added a GetGameRules function to ISDKTools for extensions to easily get the GameRules class pointer (bug 4707).
|
||||
- Added GetMessageName to IUserMessages (bug 4573) (Zach "theY4Kman" Kanzler)
|
||||
- Added HintTextMsg to IGameHelpers (bug 4950).
|
||||
- Added ProcessTargetString simple filter API (bug 4404).
|
||||
- Moved much functionality from core bins to logic bin (bug 4406, bug 4402).
|
||||
- Fixed bogus asserts in sp compiler (bug 4486, bug 4487).
|
||||
- Greatly improved sp compiler performance (~5x overall speedup) (bug 3820, bug 4493, bug 4495).
|
||||
- Changed entity output detours to use CDetour (bug 4416).
|
||||
- Enhanced nominations API (bug 4677) (CrimsonGT).
|
||||
- Added Linux support for profiling natives (bug 4927).
|
||||
- Added a new ValveCallType that allows for arbitrary |this| parameters, as well as associated features in gamedata and for reading/writing memory (bug 3520) (Downtown1).
|
||||
- Updated TF2 extension to handle Valve's changes to the "holiday" system (bug 5150).
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.3.8 [2011-06-23]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.8_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated support for various games, including Garry's Mod, Zombie Panic, and Dino D-Day.
|
||||
- Added gamedata for Eternal Silence.
|
||||
- Fixed libgcc_s.so.1 load error present on some systems (bug 4876).
|
||||
- Handle leak notices now print to error log (in addition fatal log) (bug 4929).
|
||||
- Translator now properly falls back on bad server language (bug 4861).
|
||||
- Fixed invalid client errors from bad MaxClients value when SourceTV is late-loaded (bug 4881).
|
||||
- Fixed crash on plugin unload when two commands exist with same name, different casing (bug 4698).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Updated TF2 condition defines (bug 4916).
|
||||
- Fixed var names and docs for TF2_MakeBleed native (bug 4928).
|
||||
- Removed compiler double include check (bug 4863).
|
||||
- Fixed plugin compile errors when using GetEntityClassname (bug 4798).
|
||||
|
||||
---------------------------
|
||||
|
||||
SourceMod 1.3.7 [2011-04-15]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.7_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated support for various games, including Zombie Panic, CS ProMod, Empires, and GoldenEye: Source.
|
||||
- Added gamedata for Dino D-Day.
|
||||
- Fix precedence of voice mute flag versus specific client overrides (bug 4826).
|
||||
- Fix mistaken unhooking of voice hooks (bug 4804).
|
||||
- Fixed graphical glitches with funcommands effects in L4D1 (bug 3486).
|
||||
- Fixed bug in nominations that could cause "Unknown command" error (bug 4797).
|
||||
- Removed tv_enable hook to fix rare max client count issue (bug 4791).
|
||||
- Added missing unhooking of ClientConnect in PlayerManager (bug 4749).
|
||||
- Fixed sm_rtv printing "unknown command" (bug 4730).
|
||||
- Fixed voting crash when client console, chat, and SourceTV are enabled (bug 4676).
|
||||
- Fixed CDetour crash in TF2 extension when last plugin using forward is unloaded (bug 4713).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- SetEntProp now marks edict state as changed (bug 4855).
|
||||
- Added GetEntityClassname stock (bug 4798).
|
||||
- Fix compiler hanging when #including a directory (bug 4822).
|
||||
- Added GetEntityFlags and SetEntityFlags natives for better cross-engine compatibility. (bug 4809).
|
||||
- Fixed ClientPrefs natives not being marked optional when REQUIRE_EXTENSIONS not defined (bug 4839).
|
||||
- Changed some instances of LogMessage to LogAction (bug 4649).
|
||||
- Added some new language natives (bug 4613).
|
||||
- Fixed SetTeamScore not updating score on client (bug 2736).
|
||||
- Raised MAXPLAYERS from 64 to 65 (bug 4490).
|
||||
- Added and updated many TF2-specific defines in tf2.inc and tf2_stocks.inc.
|
||||
- Fixed TF2_GetPlayerConditionFlags no longer necessarily returning all set flags (bug 4726).
|
||||
- Fixed profiler flush not clearing, added 'report' and 'clear' (bug 4674).
|
||||
- Fixed GetPlayerDecalFile crash on L4D and L4D2 (bug 4729).
|
||||
- Fixed TF2_OnGetHoliday detour no longer firing under all circumstances (bug 4700).
|
||||
- Added TF2_IsPlayerInDuel native to TF2 extension (bug 4695).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.6 [2010-10-31]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.6_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Left 4 Dead 1 (bug 4681).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Updated TF2 custom kill defines (bug 4682).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.5 [2010-10-17]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.5_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for CS:S, Garry's Mod, DoD:S, TF2, HL2DM.
|
||||
- Added support for Firearms: Source (bug 4537).
|
||||
- Added support for Fistful of Frags (bug 3883).
|
||||
- Added support for Alien Swarm (bug 4530).
|
||||
- Fixed living players hearing dead players if alltalk is disabled while deadtalk is on (bug 4533, thanks Zach Callear).
|
||||
- Fixed timeleft not getting reset on Game_Commencing in CS:S (bug 4557).
|
||||
- Fixed PlayerRunCmd being hooked when not used (bug 3990).
|
||||
- Fixed errors and missing effects caused by missing sprites on L4D2 (bug 4512).
|
||||
- Fixed 'sm plugins' public command skipping plugins in recommended listing (bug 4501).
|
||||
- Fixed corruption with large database.cfg files (bug 4286).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added TF2 object stocks (bug 4536).
|
||||
- Added TF2_MakeBleed native to TF2 ext (bug 4542).
|
||||
- Added support for logical entities in Synergy (bug 4534).
|
||||
- Updated TF2 conditions enum and defines (bug 4526).
|
||||
- Fixed potential crash with IMemUtils::FindPattern on Linux (bug 4554).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.4 [2010-07-18]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.4_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Support for latest TF update (bug 4506).
|
||||
- Support for latest L4D2 update (bug 4509).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added FindFlagChar native (bug 3776).
|
||||
- Added GetConVarDefault native (bug 4502).
|
||||
- Added forward for TF's GetHoliday function (bug 4462).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.3 [2010-06-23]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.3_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added support for CS:S on Orange Box
|
||||
- Added gamedata for Resistance and Liberation (bug 4418).
|
||||
- Updated gamedata for SourceForts, Empires, Obsidian Conflict, Zombie Master.
|
||||
- Fixed memory corruption and leaks with some voice functionality (bug 4415).
|
||||
- Fixed UI bug in sm_motd (bug 4460).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new player condition (TFCond_CritCola, bug 4447).
|
||||
- Fixed clientprefs deleting cookies twice in rare cases (bug 4412).
|
||||
- Fixed OnClientConnected forward not firing for bots (bug 4443).
|
||||
- Fixed sm_dump_datamaps crash (bug 4424).
|
||||
- Fixed switch case comparisons failing with large numbers (bug 4457).
|
||||
- Fixed rare crash in output hooks (bug 4422).
|
||||
- Fixed bug with dynamically sized arrays being sliced (bug 4428).
|
||||
- Fixed SendConVarValue() on TF2, DOD:S, L4D, and L4D2 (bug 4273).
|
||||
- Fixed TF2 natives not being marked optional (bug 4389).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.2 [2010-05-02]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.2_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Support for recent TF, DoD, and L4D2 updates (bug 4356, bug 4361, bug 4371, bug 4374, bug 4375).
|
||||
- Fixed rare crash when replicating cvars to clients (bug 4315).
|
||||
- Lots of extra game support for Insurgency, ZPS, CSProMod, PVKII, and FortressForever (thanks
|
||||
Nicholas "psychonic" hastings).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added TF functions for stunning, conditions, regeneration, and power play (bug 4166, bug 4331).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.1 [2010-02-09]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added extended support for CSProMod (bug 4255).
|
||||
- Fixed client disconnect crash on many third party games (bug 4231).
|
||||
- Improved support for Battlegrounds 2 (bug 4146).
|
||||
- Improved support for Insurgency (bug 4180).
|
||||
- Improved support for Garry's Mod (bug 4230, bug 4268).
|
||||
- Improved support for Synergy (bug 4235).
|
||||
- Updated Day of Defeat support for 20010123 update (bug 4262).
|
||||
- Fixed Webternet extension not loading on Windows 2000 (bug 4234).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Fixed compiler complaints when using |any| tag on array arguments (bug 4274).
|
||||
- Fixed GetClientCookieTime not being exported (bug 4237).
|
||||
- Fixed potential crash in entity handling code (bug 4249).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.0 [2010-01-15]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.0_Release_Notes
|
||||
|
||||
Major Features:
|
||||
* Left 4 Dead 2 support
|
||||
* Non-networked entity support
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added Left 4 Dead 2 support (bug 4075).
|
||||
- Added much richer voting progress feedback (bug 1997).
|
||||
- Improved support for various third-party games (Nicholas "psychonic" Hastings).
|
||||
- Added @spec target (bug 2718).
|
||||
- Added sm_resetcvar command (bug 3636).
|
||||
- Added "motd" chat trigger (bug 2694).
|
||||
- Updated GeoIP to OCT-2009.
|
||||
- Fixed rare map vote error (bug 3905).
|
||||
- Fixed small leak in the nominations plugin (bug 4104).
|
||||
- Fixed last client being excluded from some command effects (bug 3984).
|
||||
- Fixed crashes in plugin [|un|re]loading (bug 4034, bug 4038, bug 4044, bug 4153).
|
||||
- Special target "@me" is now filtered for certain statuses properly (bug 4000).
|
||||
- Improved non-admin to admin chat (bug 3844).
|
||||
- Removed "auto.*" extension folders (bug 3949).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added non-networked entity support (bug 2459).
|
||||
- Added improved random number generator (bug 3831).
|
||||
- Added GetClientCookieTime native (bug 3736).
|
||||
- Added AskPluginLoad2 callback (bug 3716).
|
||||
- Added PlayerRunCmd callback (bug 3289).
|
||||
- Added PointOutsideWorld native (bug 3906).
|
||||
- Added API for "blanket" command hooks (bug 4015).
|
||||
- Added ability to test for SourceMod features (bug 4021).
|
||||
- Added ability to change broadcast status on hooked events (bug 3886).
|
||||
- OnClientCommand no longer receives unconnected clients (bug 3732).
|
||||
- Fixed various bugs in client listening API (bug 3818).
|
||||
- Fixed crash in BanClient (bug 3912).
|
||||
- Fixed various crashes in self-removing callbacks (bug 4059).
|
||||
- Fixed rare HUD text crash on TF (bug 4016).
|
||||
- Fixed OnConfigsExecuted not running on EP1 games with large configs (bug 3828).
|
||||
- Fixed entity output hooks not working (bug 3988).
|
||||
- Gamedata folder matches are now case-insensitive (bug 3913).
|
||||
- Blocked plugins from hooking "sm" command (bug 4013).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.4 [2009-10-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.4_Release_Notes
|
||||
|
||||
- Updated for L4D changes (bugs 4032, 4033, 4035).
|
||||
- Updated GeoLite Country database for GeoIP extension.
|
||||
- Fixed crash when block-loading more than eight plugins (bug 4034).
|
||||
- Fixed rare crash in hudtext code on TF (bug 4016).
|
||||
- Fixed crash when reloading a blocked plugin failed (bug 4038).
|
||||
- Fixed Huntsman not firing critical callback on TF (bug 3927).
|
||||
- Registering the "sm" command no longer has any effect (bug 4013).
|
||||
- Fixed translation bug in extension API (bug 4010).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.3 [2009-08-28]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.3_Release_Notes
|
||||
|
||||
- Fix extension filename lookup. (bug 3975).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.2 [2009-08-28]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.2_Release_Notes
|
||||
|
||||
- Removed auto folders. (bug 3949).
|
||||
- Added PointOutsideWorld native to sdktools. (bug 3906).
|
||||
- Added "motd" chat trigger to basetriggers. (bug 2694).
|
||||
- Added manual extension reloading command to root console menu. (bug 3934)
|
||||
- Fixed 'list' type custom menu entries overwriting admin restrictions. (bug 3783).
|
||||
- Added sm_resetcvar command to basecommands. (bug 3636).
|
||||
- Updated gamedata for DOD:S. (bug 3948).
|
||||
- Updated gamedata for TF2. (bug 3948).
|
||||
- Added new .ep2v build config for valve OB based games. (bug 3948).
|
||||
- Fixed incorrect escaping in clientprefs SQLite queries. (bug 3904)
|
||||
- Updated gamedata for Synergy. (bug 3315).
|
||||
- Upgraded to pcre-7.9 (bug 3923).
|
||||
- Switched Insurgency chat printing to SayText. (bug 3738).
|
||||
- Updated gamedata for Insurgency. (bug 3511).
|
||||
- Updated gamedata for ZM. (bug 3746).
|
||||
- Updated gamedata for Empires. (bug 3500).
|
||||
- Updated gamedata for ZPS. (bug 3877).
|
||||
- Updated gamedata for AoC. (bug 3891).
|
||||
- Fixed RemovePlayerDisguise signature for TF2. (bug 3892).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.1 [2009-05-31]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.1_Release_Notes
|
||||
|
||||
- Updated SDKTools for latest Team Fortress update.
|
||||
- Added L4D handling to GuessSDKVersion() (bug 3842).
|
||||
- Updated Zombie Panic Source offsets (bug 3632).
|
||||
- Fixed crash when clientprefs saw disconnect from 64th client (bug 3821).
|
||||
- Fixed Plugin_Handled acting like a Stop in usermsg hooks (bug 3685).
|
||||
- Fixed early tv_enable causing crashes (bug 3766).
|
||||
- Fixed unhook event crash (bug 3814).
|
||||
- Fixed compiler reading uninitialized strings while processing varargs (bug 3811).
|
||||
- Fixed compiler choosing whether to emit stradjust.pri on dynamic arrays based on uninitialized memory (bug 3810).
|
||||
- Fixed Windows L4D CreateFakeClient signature (bug 3792).
|
||||
- Fixed sm_slap for EP1 games (bug 3768).
|
||||
- Fixed casting problems in TextParsers breaking TrimString for non-ASCII characters (bug 3800).
|
||||
- Fixed OnClientConnect rejectmsg handling, improved doc (bug 3690).
|
||||
- Fixed clientprefs not loading cookies for clients on late load (bug 3735).
|
||||
- Fixed GetCommandFlags on original engine games (bug 3759).
|
||||
- Fixed compiler asserting when returning a string literal (bug 3836).
|
||||
- Fixed compiler erroring when tagging functions for string return (bug 3837).
|
||||
- Fixed compiler not handling constant chained relational operators correctly (bug 3838).
|
||||
- Fixed revote bug and inflexibilities in RedrawClientVoteMenu (bug 3834).
|
||||
- Fixed auto update URL being set too late (bug 3699).
|
||||
- Disabled nextmap in Synergy and Dystopia (bug 3687, bug 3741).
|
||||
- Removed unnecessary SSE optimizations from msvc9 project files (bug 3756).
|
||||
- Removed short-lived tag system (bug 3751).
|
||||
- Removed the alive check from sm_rename. (bug 3698).
|
||||
- Switched FortressForever to Valve menus (bug 3819).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.0 [2009-03-05]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
||||
//any more plugins from being loaded.
|
||||
sm plugins unload_all
|
||||
sm plugins load_unlock
|
||||
sm plugins load basebans.smx
|
||||
sm plugins load basecommands.smx
|
||||
sm plugins load admin-flatfile.smx
|
||||
|
||||
@@ -80,21 +80,21 @@ sm_reserve_type 0
|
||||
sm_reserved_slots 0
|
||||
|
||||
// Specifies whether or not reserved slots will be hidden (subtracted from max
|
||||
// slot count). Valid values are 0 (visible) or 1 (hidden).
|
||||
// slot count). Valid values are 0 (Visible) or 1 (Hidden).
|
||||
// --
|
||||
// Requires: reservedslots.smx
|
||||
// Default: 0
|
||||
sm_hide_slots 0
|
||||
|
||||
// Specifies whether or not non-admins can send messages to admins using
|
||||
// say_team @<message>. Valid values are 0 (disabled) or 1 (enabled)
|
||||
// say_team @<message>. Valid values are 0 (Disabled) or 1 (Enabled)
|
||||
// --
|
||||
// Requires: basechat.smx
|
||||
// Default: 1
|
||||
sm_chat_mode 1
|
||||
|
||||
// Specifies whether or not "timeleft" will automaticly be triggered every
|
||||
// x seconds. Valid values are 0 (disabled) to 1800 seconds.
|
||||
// x seconds. Valid values are 0 (Disabled) to 1800 seconds.
|
||||
// --
|
||||
// Requires: basetriggers.smx
|
||||
// Default: 0
|
||||
@@ -107,3 +107,28 @@ sm_timeleft_interval 0
|
||||
// Requires: basetriggers.smx
|
||||
// Default: 1
|
||||
sm_trigger_show 1
|
||||
|
||||
// Specifies whether or not to display vote progress to clients in the
|
||||
// "hint" box (near the bottom of the screen in most games).
|
||||
// Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_hintbox 0
|
||||
|
||||
// Specifies whether or not to display vote progress to clients in the
|
||||
// chat area. Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_chat 0
|
||||
|
||||
// Specifies whether or not to display vote progress in the server console.
|
||||
// Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_console 0
|
||||
|
||||
// Specifies whether or not to display vote progress to clients in the
|
||||
// client console. Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_client_console 0
|
||||
|
||||
@@ -107,4 +107,22 @@
|
||||
* Currently this will log details about the gamedata updating process.
|
||||
*/
|
||||
"DebugSpew" "no"
|
||||
|
||||
/**
|
||||
* If set to yes, SourceMod will validate steamid auth strings with the Steam backend before giving out admin access.
|
||||
* This can prevent malicious users from impersonating admins with stolen Steam apptickets.
|
||||
* If Steam is down, admins will not be authenticated until Steam comes back up.
|
||||
* This option increases the security of your server, but is still experimental.
|
||||
*/
|
||||
"SteamAuthstringValidation" "no"
|
||||
|
||||
/**
|
||||
* Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
|
||||
* It is STRONGLY advised that this is left enabled, there have been cases in the past with plugins that
|
||||
* allow anyone to delete files on the server, gain full rcon control, etc.
|
||||
*
|
||||
* "yes" - Block malware or illegal plugins from loading (default)
|
||||
* "no" - Warn about malware or illegal plugins loading
|
||||
*/
|
||||
"BlockBadPlugins" "yes"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
{
|
||||
"driver_default" "mysql"
|
||||
|
||||
// When specifying "host", you may use an IP address, a hostname, or a socket file path
|
||||
|
||||
"default"
|
||||
{
|
||||
"driver" "default"
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet:
|
||||
import sys
|
||||
import ambuild.runner as runner
|
||||
|
||||
run = runner.Runner()
|
||||
run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
|
||||
help='Enable debugging symbols')
|
||||
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||
help='Enable optimization')
|
||||
run.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
|
||||
help='Disable building MySQL extension')
|
||||
run.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
||||
help='Build against specified SDKs; valid args are "all", "present", or '
|
||||
'comma-delimited list of engine names (default: %default)')
|
||||
run.Configure(sys.path[0])
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
from ambuild.command import SymlinkCommand
|
||||
|
||||
for i in SM.sdkInfo:
|
||||
sdk = SM.sdkInfo[i]
|
||||
if AMBuild.target['platform'] not in sdk['platform']:
|
||||
continue
|
||||
|
||||
name = 'sourcemod.' + sdk['ext']
|
||||
|
||||
compiler = SM.DefaultHL2Compiler('core', i)
|
||||
|
||||
if i == 'csgo':
|
||||
# Protobuf 2.3 headers have some signed/unsigned compares. I believe that it's fixed in later versions, but Valve.
|
||||
if isinstance(compiler.cxx, Cpp.CompatGCC):
|
||||
compiler.AddToListVar('CFLAGS', '-Wno-sign-compare')
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'common', 'protobuf-2.3.0', 'src'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'public', 'engine', 'protobuf'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache[sdk['sdk']], 'public', 'game', 'shared', 'csgo', 'protobuf'))
|
||||
|
||||
extension = AMBuild.AddJob(name)
|
||||
binary = Cpp.LibraryBuilder(name, AMBuild, extension, compiler)
|
||||
SM.PreSetupHL2Job(extension, binary, i)
|
||||
|
||||
if i == 'csgo':
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
link = os.path.join(os.path.join(AMBuild.outputFolder, extension.workFolder), 'libprotobuf.a')
|
||||
target = os.path.join(os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'linux32', 'release'), 'libprotobuf.a')
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
extension.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'darwin':
|
||||
link = os.path.join(os.path.join(AMBuild.outputFolder, extension.workFolder), 'libprotobuf.a')
|
||||
target = os.path.join(os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'osx32', 'release'), 'libprotobuf.a')
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
extension.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'windows':
|
||||
libPath = os.path.join(AMBuild.cache[sdk['sdk']], 'lib', 'win32', 'release', 'vs2010', 'libprotobuf.lib')
|
||||
binary.RebuildIfNewer(libPath)
|
||||
binary['POSTLINKFLAGS'].append(libPath)
|
||||
|
||||
files = [
|
||||
'AdminCache.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
'MenuStyle_Valve.cpp',
|
||||
'logic_bridge.cpp',
|
||||
'smn_entities.cpp',
|
||||
'sm_stringutil.cpp',
|
||||
'ADTFactory.cpp',
|
||||
'ForwardSys.cpp',
|
||||
'MenuVoting.cpp',
|
||||
'smn_events.cpp',
|
||||
'smn_menus.cpp',
|
||||
'sm_trie.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_hooks.cpp',
|
||||
'NativeInvoker.cpp',
|
||||
'smn_fakenatives.cpp',
|
||||
'smn_nextmap.cpp',
|
||||
'sourcemm_api.cpp',
|
||||
'ChatTriggers.cpp',
|
||||
'NativeOwner.cpp',
|
||||
'smn_filesystem.cpp',
|
||||
'smn_player.cpp',
|
||||
'sourcemod.cpp',
|
||||
'concmd_cleaner.cpp',
|
||||
'HalfLife2.cpp',
|
||||
'NextMap.cpp',
|
||||
'ConCmdManager.cpp',
|
||||
'HandleSys.cpp',
|
||||
'ConVarManager.cpp',
|
||||
'LibrarySys.cpp',
|
||||
'PlayerManager.cpp',
|
||||
'TimerSys.cpp',
|
||||
'CoreConfig.cpp',
|
||||
'Logger.cpp',
|
||||
'PluginInfoDatabase.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'PluginSys.cpp',
|
||||
'smn_console.cpp',
|
||||
'UserMessages.cpp',
|
||||
'Database.cpp',
|
||||
'MenuManager.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_hudtext.cpp',
|
||||
'smn_usermsgs.cpp',
|
||||
'DebugReporter.cpp',
|
||||
'MenuStyle_Base.cpp',
|
||||
'ShareSys.cpp',
|
||||
'smn_database.cpp',
|
||||
'smn_keyvalues.cpp',
|
||||
'smn_vector.cpp',
|
||||
'EventManager.cpp',
|
||||
'MenuStyle_Radio.cpp',
|
||||
'sm_autonatives.cpp',
|
||||
'sm_srvcmds.cpp',
|
||||
'ConsoleDetours.cpp'
|
||||
]
|
||||
|
||||
if i == 'csgo':
|
||||
files.append('smn_protobuf.cpp')
|
||||
else:
|
||||
files.append('smn_bitbuffer.cpp')
|
||||
|
||||
binary.AddSourceFiles('core', files)
|
||||
|
||||
if i == 'csgo':
|
||||
files = [
|
||||
os.path.join('public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join('public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join('public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
binary.AddSourceFiles(AMBuild.cache[sdk['sdk']], files)
|
||||
|
||||
SM.PostSetupHL2Job(extension, binary, i)
|
||||
|
||||
if i == 'csgo':
|
||||
if AMBuild.target['platform'] in ['linux', 'darwin']:
|
||||
binary.AddObjectFiles(['libprotobuf.a'])
|
||||
|
||||
SM.AutoVersion('core', binary)
|
||||
SM.ExtractDebugInfo(extension, binary)
|
||||
binary.SendToJob()
|
||||
|
||||
+2
-2
@@ -1719,7 +1719,7 @@ bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
return g_ConCmds.CheckCommandAccess(client, cmd, bits);
|
||||
return g_ConCmds.CheckClientCommandAccess(client, cmd, bits);
|
||||
}
|
||||
|
||||
unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level)
|
||||
@@ -1794,7 +1794,7 @@ bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool o
|
||||
GetCommandOverride(cmd, Override_Command, &bits);
|
||||
}
|
||||
|
||||
return g_ConCmds.CheckCommandAccess(client, cmd, bits) ? 1 : 0;
|
||||
return g_ConCmds.CheckClientCommandAccess(client, cmd, bits) ? 1 : 0;
|
||||
}
|
||||
|
||||
void iterator_glob_basic_override(Trie *pTrie, const char *key, void **value, void *data)
|
||||
|
||||
+132
-61
@@ -34,8 +34,8 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "ConCmdManager.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "Translator.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
|
||||
* While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
|
||||
@@ -59,13 +59,17 @@ ChatTriggers g_ChatTriggers;
|
||||
bool g_bSupressSilentFails = false;
|
||||
|
||||
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
|
||||
m_bTriggerWasSilent(false), m_ReplyTo(SM_REPLY_CONSOLE)
|
||||
m_ReplyTo(SM_REPLY_CONSOLE)
|
||||
{
|
||||
m_PubTrigger = sm_strdup("!");
|
||||
m_PrivTrigger = sm_strdup("/");
|
||||
m_PubTriggerSize = 1;
|
||||
m_PrivTriggerSize = 1;
|
||||
m_bIsChatTrigger = false;
|
||||
m_bPluginIgnored = false;
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
m_bIsINS = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
ChatTriggers::~ChatTriggers()
|
||||
@@ -109,11 +113,13 @@ void ChatTriggers::OnSourceModAllInitialized()
|
||||
{
|
||||
m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
|
||||
m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
|
||||
m_pOnClientSayCmd = g_Forwards.CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
|
||||
m_pOnClientSayCmd_Post = g_Forwards.CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
|
||||
}
|
||||
|
||||
void ChatTriggers::OnSourceModAllInitialized_Post()
|
||||
{
|
||||
g_pCorePhrases->AddPhraseFile("antiflood.phrases");
|
||||
logicore.AddCorePhraseFile("antiflood.phrases");
|
||||
}
|
||||
|
||||
void ChatTriggers::OnSourceModGameInitialized()
|
||||
@@ -131,23 +137,62 @@ void ChatTriggers::OnSourceModGameInitialized()
|
||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
|
||||
|
||||
if (m_bIsINS)
|
||||
{
|
||||
m_pSay2Cmd = FindCommand("say2");
|
||||
if (m_pSay2Cmd)
|
||||
{
|
||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||
}
|
||||
}
|
||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
m_pSaySquadCmd = FindCommand("say_squad");
|
||||
|
||||
if (m_pSaySquadCmd)
|
||||
{
|
||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ChatTriggers::OnSourceModShutdown()
|
||||
{
|
||||
if (m_pSayTeamCmd)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
||||
}
|
||||
if (m_pSayCmd)
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
||||
}
|
||||
|
||||
if (m_pSayTeamCmd)
|
||||
{
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
if (m_bIsINS && m_pSay2Cmd)
|
||||
{
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||
}
|
||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
if (m_pSaySquadCmd)
|
||||
{
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_Forwards.ReleaseForward(m_pShouldFloodBlock);
|
||||
g_Forwards.ReleaseForward(m_pDidFloodBlock);
|
||||
g_Forwards.ReleaseForward(m_pOnClientSayCmd);
|
||||
g_Forwards.ReleaseForward(m_pOnClientSayCmd_Post);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
@@ -158,24 +203,10 @@ void ChatTriggers::OnSayCommand_Pre()
|
||||
{
|
||||
CCommand command;
|
||||
#endif
|
||||
int client;
|
||||
CPlayer *pPlayer;
|
||||
|
||||
client = g_ConCmds.GetCommandClient();
|
||||
int client = g_ConCmds.GetCommandClient();
|
||||
m_bIsChatTrigger = false;
|
||||
m_bWasFloodedMessage = false;
|
||||
|
||||
/* The server console cannot do this */
|
||||
if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
/* We guarantee the client is connected */
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
m_bPluginIgnored = false;
|
||||
|
||||
const char *args = command.ArgS();
|
||||
|
||||
@@ -184,22 +215,38 @@ void ChatTriggers::OnSayCommand_Pre()
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
/* Save these off for post hook as the command data returned from the engine in older engine versions
|
||||
* can be NULL, despite the data still being there and valid. */
|
||||
m_Arg0Backup = command.Arg(0);
|
||||
m_ArgSBackup = command.ArgS();
|
||||
|
||||
/* The server console cannot do this */
|
||||
if (client == 0)
|
||||
{
|
||||
cell_t res = CallOnClientSayCommand(client);
|
||||
if (res >= Pl_Handled)
|
||||
{
|
||||
m_bPluginIgnored = (res >= Pl_Stop);
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||
|
||||
/* We guarantee the client is connected */
|
||||
if (!pPlayer || !pPlayer->IsConnected())
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
/* Check if we need to block this message from being sent */
|
||||
if (ClientIsFlooding(client))
|
||||
{
|
||||
char buffer[128];
|
||||
|
||||
if (!CoreTranslate(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"%T",
|
||||
2,
|
||||
NULL,
|
||||
"Flooding the server",
|
||||
&client))
|
||||
{
|
||||
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
|
||||
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
|
||||
}
|
||||
|
||||
/* :TODO: we should probably kick people who spam too much. */
|
||||
|
||||
@@ -220,6 +267,13 @@ void ChatTriggers::OnSayCommand_Pre()
|
||||
is_quoted = true;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
if (m_bIsINS && strcmp(m_Arg0Backup, "say2") == 0 && strlen(args) >= 4)
|
||||
{
|
||||
args += 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool is_trigger = false;
|
||||
bool is_silent = false;
|
||||
|
||||
@@ -236,38 +290,28 @@ void ChatTriggers::OnSayCommand_Pre()
|
||||
args = &args[m_PrivTriggerSize];
|
||||
}
|
||||
|
||||
if (!is_trigger)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if this is actually a command!
|
||||
*/
|
||||
if (!PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
|
||||
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
|
||||
{
|
||||
CPlayer *pPlayer;
|
||||
if (is_silent
|
||||
&& g_bSupressSilentFails
|
||||
&& client != 0
|
||||
&& (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
|
||||
&& pPlayer->GetAdminId() != INVALID_ADMIN_ID)
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
RETURN_META(MRES_IGNORED);
|
||||
m_bIsChatTrigger = true;
|
||||
|
||||
/**
|
||||
* We'll execute it in post.
|
||||
*/
|
||||
m_bWillProcessInPost = true;
|
||||
}
|
||||
|
||||
m_bIsChatTrigger = true;
|
||||
cell_t res = CallOnClientSayCommand(client);
|
||||
|
||||
/**
|
||||
* We'll execute it in post.
|
||||
*/
|
||||
m_bWillProcessInPost = true;
|
||||
m_bTriggerWasSilent = is_silent;
|
||||
if (res >= Pl_Handled)
|
||||
{
|
||||
m_bPluginIgnored = (res >= Pl_Stop);
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
/* If we're silent, block */
|
||||
if (is_silent)
|
||||
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
@@ -282,19 +326,33 @@ void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
||||
void ChatTriggers::OnSayCommand_Post()
|
||||
#endif
|
||||
{
|
||||
m_bIsChatTrigger = false;
|
||||
m_bWasFloodedMessage = false;
|
||||
int client = g_ConCmds.GetCommandClient();
|
||||
|
||||
if (m_bWillProcessInPost)
|
||||
{
|
||||
/* Reset this for re-entrancy */
|
||||
m_bWillProcessInPost = false;
|
||||
|
||||
/* Execute the cached command */
|
||||
int client = g_ConCmds.GetCommandClient();
|
||||
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
||||
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
||||
SetReplyTo(old);
|
||||
}
|
||||
|
||||
if (m_bPluginIgnored)
|
||||
{
|
||||
m_bPluginIgnored = false;
|
||||
}
|
||||
else if (!m_bWasFloodedMessage && !m_bIsChatTrigger && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
|
||||
{
|
||||
m_pOnClientSayCmd_Post->PushCell(client);
|
||||
m_pOnClientSayCmd_Post->PushString(m_Arg0Backup);
|
||||
m_pOnClientSayCmd_Post->PushString(m_ArgSBackup);
|
||||
m_pOnClientSayCmd_Post->Execute(NULL);
|
||||
}
|
||||
|
||||
m_bIsChatTrigger = false;
|
||||
m_bWasFloodedMessage = false;
|
||||
}
|
||||
|
||||
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
|
||||
@@ -371,6 +429,19 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_
|
||||
return true;
|
||||
}
|
||||
|
||||
cell_t ChatTriggers::CallOnClientSayCommand(int client)
|
||||
{
|
||||
cell_t res = Pl_Continue;
|
||||
if (!m_bIsChatTrigger && m_pOnClientSayCmd->GetFunctionCount() != 0)
|
||||
{
|
||||
m_pOnClientSayCmd->PushCell(client);
|
||||
m_pOnClientSayCmd->PushString(m_Arg0Backup);
|
||||
m_pOnClientSayCmd->PushString(m_ArgSBackup);
|
||||
m_pOnClientSayCmd->Execute(&res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
|
||||
{
|
||||
unsigned int old = m_ReplyTo;
|
||||
|
||||
+14
-1
@@ -69,21 +69,34 @@ public:
|
||||
private:
|
||||
bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
|
||||
bool ClientIsFlooding(int client);
|
||||
cell_t CallOnClientSayCommand(int client);
|
||||
private:
|
||||
ConCommand *m_pSayCmd;
|
||||
ConCommand *m_pSayTeamCmd;
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
ConCommand *m_pSay2Cmd;
|
||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
ConCommand *m_pSaySquadCmd;
|
||||
#endif
|
||||
char *m_PubTrigger;
|
||||
size_t m_PubTriggerSize;
|
||||
char *m_PrivTrigger;
|
||||
size_t m_PrivTriggerSize;
|
||||
bool m_bWillProcessInPost;
|
||||
bool m_bTriggerWasSilent;
|
||||
bool m_bIsChatTrigger;
|
||||
bool m_bWasFloodedMessage;
|
||||
bool m_bPluginIgnored;
|
||||
unsigned int m_ReplyTo;
|
||||
char m_ToExecute[300];
|
||||
const char *m_Arg0Backup;
|
||||
const char *m_ArgSBackup;
|
||||
IForward *m_pShouldFloodBlock;
|
||||
IForward *m_pDidFloodBlock;
|
||||
IForward *m_pOnClientSayCmd;
|
||||
IForward *m_pOnClientSayCmd_Post;
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
bool m_bIsINS;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern ChatTriggers g_ChatTriggers;
|
||||
|
||||
+47
-92
@@ -34,9 +34,9 @@
|
||||
#include "AdminCache.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "Translator.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "ChatTriggers.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
ConCmdManager g_ConCmds;
|
||||
|
||||
@@ -226,30 +226,38 @@ void ConCmdManager::SetCommandClient(int client)
|
||||
m_CmdClient = client + 1;
|
||||
}
|
||||
|
||||
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
|
||||
return NULL;
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
ConCmdList::iterator ConCmdManager::FindInList(const char *cmd)
|
||||
{
|
||||
List<ConCmdInfo *>::iterator iter = m_CmdList.begin();
|
||||
|
||||
while (iter != m_CmdList.end())
|
||||
{
|
||||
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
|
||||
break;
|
||||
iter++;
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int args, ResultType type)
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
|
||||
if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
|
||||
if ((pInfo = FindInTrie(cmd)) == NULL)
|
||||
{
|
||||
List<ConCmdInfo *>::iterator iter;
|
||||
|
||||
pInfo = NULL;
|
||||
iter = m_CmdList.begin();
|
||||
while (iter != m_CmdList.end())
|
||||
{
|
||||
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
ConCmdList::iterator item = FindInList(cmd);
|
||||
if (item == m_CmdList.end())
|
||||
return type;
|
||||
}
|
||||
pInfo = *item;
|
||||
}
|
||||
|
||||
cell_t result = type;
|
||||
@@ -314,35 +322,20 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
||||
*/
|
||||
const char *cmd = g_HL2.CurrentCommandName();
|
||||
|
||||
ConCmdInfo *pInfo;
|
||||
if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
|
||||
ConCmdInfo *pInfo = FindInTrie(cmd);
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
/* Unfortunately, we now have to do a slow lookup because Valve made client commands
|
||||
* case-insensitive. We can't even use our sortedness.
|
||||
*/
|
||||
if (client == 0 && !engine->IsDedicatedServer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<ConCmdInfo *>::iterator iter;
|
||||
ConCmdList::iterator item = FindInList(cmd);
|
||||
if (item == m_CmdList.end())
|
||||
return;
|
||||
|
||||
pInfo = NULL;
|
||||
iter = m_CmdList.begin();
|
||||
while (iter != m_CmdList.end())
|
||||
{
|
||||
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pInfo = *item;
|
||||
}
|
||||
|
||||
/* This is a hack to prevent say triggers from firing on messages that were
|
||||
@@ -457,7 +450,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
||||
}
|
||||
}
|
||||
|
||||
bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmdflags)
|
||||
bool ConCmdManager::CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags)
|
||||
{
|
||||
if (cmdflags == 0 || client == 0)
|
||||
{
|
||||
@@ -478,7 +471,11 @@ bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmd
|
||||
return false;
|
||||
}
|
||||
|
||||
AdminId adm = player->GetAdminId();
|
||||
return CheckAdminCommandAccess(player->GetAdminId(), cmd, cmdflags);
|
||||
}
|
||||
|
||||
bool ConCmdManager::CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits cmdflags)
|
||||
{
|
||||
if (adm != INVALID_ADMIN_ID)
|
||||
{
|
||||
FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective);
|
||||
@@ -531,7 +528,7 @@ bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmd
|
||||
|
||||
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
|
||||
{
|
||||
if (CheckCommandAccess(client, cmd, pAdmin->eflags))
|
||||
if (CheckClientCommandAccess(client, cmd, pAdmin->eflags))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -540,7 +537,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
|
||||
|
||||
/* If we got here, the command failed... */
|
||||
char buffer[128];
|
||||
if (!CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
|
||||
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
|
||||
{
|
||||
UTIL_Format(buffer, sizeof(buffer), "You do not have access to this command");
|
||||
}
|
||||
@@ -562,44 +559,6 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *description,
|
||||
int flags)
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
|
||||
if (!pInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CmdHook *pHook = new CmdHook();
|
||||
|
||||
pHook->pf = pFunction;
|
||||
if (description && description[0])
|
||||
{
|
||||
pHook->helptext.assign(description);
|
||||
}
|
||||
pInfo->conhooks.push_back(pHook);
|
||||
|
||||
/* Add to the plugin */
|
||||
CmdList *pList;
|
||||
IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
||||
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
|
||||
{
|
||||
pList = new CmdList();
|
||||
pPlugin->SetProperty("CommandList", pList);
|
||||
}
|
||||
PlCmdInfo info;
|
||||
info.pInfo = pInfo;
|
||||
info.type = Cmd_Console;
|
||||
info.pHook = pHook;
|
||||
AddToPlCmdList(pList, info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *group,
|
||||
@@ -661,7 +620,6 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
/* Finally, add the hook */
|
||||
pInfo->conhooks.push_back(pHook);
|
||||
pInfo->admin = *(pHook->pAdmin);
|
||||
pInfo->is_admin_set = true;
|
||||
|
||||
/* Now add to the plugin */
|
||||
CmdList *pList;
|
||||
@@ -806,7 +764,6 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
|
||||
pInfo->admin = *(pHook->pAdmin);
|
||||
}
|
||||
}
|
||||
pInfo->is_admin_set = true;
|
||||
}
|
||||
else if (type == Override_CommandGroup)
|
||||
{
|
||||
@@ -840,7 +797,6 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
|
||||
}
|
||||
}
|
||||
}
|
||||
pInfo->is_admin_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,7 +864,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
|
||||
|
||||
*pFlags = pInfo->admin.eflags;
|
||||
|
||||
return pInfo->is_admin_set;
|
||||
return true;
|
||||
}
|
||||
|
||||
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
|
||||
@@ -916,6 +872,10 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
||||
ConCmdInfo *pInfo;
|
||||
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
|
||||
{
|
||||
ConCmdList::iterator item = FindInList(name);
|
||||
if (item != m_CmdList.end())
|
||||
return *item;
|
||||
|
||||
pInfo = new ConCmdInfo();
|
||||
/* Find the commandopan */
|
||||
ConCommand *pCmd = FindCommand(name);
|
||||
@@ -941,7 +901,6 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
||||
}
|
||||
|
||||
pInfo->pCmd = pCmd;
|
||||
pInfo->is_admin_set = false;
|
||||
|
||||
sm_trie_insert(m_pCmds, name, pInfo);
|
||||
AddToCmdList(pInfo);
|
||||
@@ -994,13 +953,9 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
||||
{
|
||||
type = "server";
|
||||
}
|
||||
else if (cmd.type == Cmd_Console)
|
||||
{
|
||||
type = "console";
|
||||
}
|
||||
else if (cmd.type == Cmd_Admin)
|
||||
{
|
||||
type = "admin";
|
||||
type = (cmd.pInfo->admin.eflags == 0)?"console":"admin";
|
||||
}
|
||||
name = cmd.pInfo->pCmd->GetName();
|
||||
if (cmd.pHook->helptext.size())
|
||||
|
||||
+12
-5
@@ -48,7 +48,6 @@ using namespace SourceHook;
|
||||
enum CmdType
|
||||
{
|
||||
Cmd_Server,
|
||||
Cmd_Console,
|
||||
Cmd_Admin,
|
||||
};
|
||||
|
||||
@@ -89,9 +88,10 @@ struct ConCmdInfo
|
||||
List<CmdHook *> srvhooks; /**< Hooks as a server command */
|
||||
List<CmdHook *> conhooks; /**< Hooks as a console command */
|
||||
AdminCmdInfo admin; /**< Admin info, if any */
|
||||
bool is_admin_set; /**< Whether or not admin info is set */
|
||||
};
|
||||
|
||||
typedef List<ConCmdInfo *> ConCmdList;
|
||||
|
||||
class ConCmdManager :
|
||||
public SMGlobalClass,
|
||||
public IRootConsoleCommand,
|
||||
@@ -117,7 +117,6 @@ public: //IConCommandTracker
|
||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
||||
public:
|
||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
||||
bool AddConsoleCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *group,
|
||||
@@ -128,7 +127,8 @@ public:
|
||||
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
||||
bool LookForSourceModCommand(const char *cmd);
|
||||
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
|
||||
bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
|
||||
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits flags);
|
||||
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
|
||||
private:
|
||||
void InternalDispatch(const CCommand &command);
|
||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
||||
@@ -139,6 +139,12 @@ private:
|
||||
void RemoveConCmds(List<CmdHook *> &cmdlist);
|
||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||
|
||||
// Case insensitive
|
||||
ConCmdList::iterator FindInList(const char *name);
|
||||
|
||||
// Case sensitive
|
||||
ConCmdInfo *FindInTrie(const char *name);
|
||||
public:
|
||||
inline int GetCommandClient()
|
||||
{
|
||||
@@ -151,7 +157,7 @@ public:
|
||||
private:
|
||||
Trie *m_pCmds; /* command lookup */
|
||||
Trie *m_pCmdGrps; /* command group lookup */
|
||||
List<ConCmdInfo *> m_CmdList; /* command list */
|
||||
ConCmdList m_CmdList; /* command list */
|
||||
int m_CmdClient; /* current client */
|
||||
BaseStringTable m_Strings; /* string table */
|
||||
};
|
||||
@@ -159,3 +165,4 @@ private:
|
||||
extern ConCmdManager g_ConCmds;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#ifndef _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
|
||||
#define _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
class ConCommandBaseIterator
|
||||
{
|
||||
public:
|
||||
inline ConCommandBaseIterator() : iter(icvar)
|
||||
{
|
||||
iter.SetFirst();
|
||||
}
|
||||
|
||||
inline bool IsValid()
|
||||
{
|
||||
return iter.IsValid();
|
||||
}
|
||||
|
||||
inline void Next()
|
||||
{
|
||||
iter.Next();
|
||||
}
|
||||
|
||||
inline ConCommandBase *Get()
|
||||
{
|
||||
return iter.Get();
|
||||
}
|
||||
private:
|
||||
ICvar::Iterator iter;
|
||||
};
|
||||
#else
|
||||
class ConCommandBaseIterator
|
||||
{
|
||||
public:
|
||||
inline ConCommandBaseIterator()
|
||||
{
|
||||
iter = icvar->GetCommands();
|
||||
}
|
||||
|
||||
inline bool IsValid()
|
||||
{
|
||||
return iter != NULL;
|
||||
}
|
||||
|
||||
inline void Next()
|
||||
{
|
||||
iter = const_cast<ConCommandBase *>(iter->GetNext());
|
||||
}
|
||||
|
||||
inline ConCommandBase *Get()
|
||||
{
|
||||
return iter;
|
||||
}
|
||||
private:
|
||||
ConCommandBase *iter;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ */
|
||||
|
||||
+83
-13
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,8 +25,6 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "ConVarManager.h"
|
||||
@@ -60,6 +58,40 @@ const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}
|
||||
typedef List<const ConVar *> ConVarList;
|
||||
KTrie<ConVarInfo *> convar_cache;
|
||||
|
||||
class ConVarReentrancyGuard
|
||||
{
|
||||
ConVar *cvar;
|
||||
ConVarReentrancyGuard *up;
|
||||
public:
|
||||
static ConVarReentrancyGuard *chain;
|
||||
|
||||
ConVarReentrancyGuard(ConVar *cvar)
|
||||
: cvar(cvar), up(chain)
|
||||
{
|
||||
chain = this;
|
||||
}
|
||||
|
||||
~ConVarReentrancyGuard()
|
||||
{
|
||||
assert(chain == this);
|
||||
chain = up;
|
||||
}
|
||||
|
||||
static bool IsCvarInChain(ConVar *cvar)
|
||||
{
|
||||
ConVarReentrancyGuard *guard = chain;
|
||||
while (guard != NULL)
|
||||
{
|
||||
if (guard->cvar == cvar)
|
||||
return true;
|
||||
guard = guard->up;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
|
||||
|
||||
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
|
||||
{
|
||||
}
|
||||
@@ -96,6 +128,8 @@ void ConVarManager::OnSourceModAllInitialized()
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
||||
|
||||
g_PluginSys.AddPluginsListener(this);
|
||||
|
||||
/* Add the 'convars' option to the 'sm' console command */
|
||||
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
||||
}
|
||||
@@ -162,6 +196,8 @@ void ConVarManager::OnSourceModShutdown()
|
||||
/* Remove the 'convars' option from the 'sm' console command */
|
||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
||||
|
||||
g_PluginSys.RemovePluginsListener(this);
|
||||
|
||||
/* Remove the 'ConVar' handle type */
|
||||
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
|
||||
}
|
||||
@@ -180,7 +216,7 @@ void ConVarManager::OnSourceModVSPReceived()
|
||||
}
|
||||
|
||||
/* For later MM:S versions, use the updated API, since it's cleaner. */
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
||||
int engine = g_SMAPI->GetSourceEngineBuild();
|
||||
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
||||
{
|
||||
@@ -252,12 +288,23 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
||||
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
ConVarList *pConVarList;
|
||||
List<ConVarQuery>::iterator iter;
|
||||
|
||||
/* If plugin has a convar list, free its memory */
|
||||
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
||||
{
|
||||
delete pConVarList;
|
||||
}
|
||||
|
||||
/* Remove convar queries for this plugin that haven't returned results yet */
|
||||
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
|
||||
{
|
||||
ConVarQuery &query = (*iter);
|
||||
if (query.pCallback->GetParentRuntime() == plugin->GetRuntime())
|
||||
{
|
||||
m_ConVarQueries.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -275,8 +322,15 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
||||
int argcount = command.ArgC();
|
||||
if (argcount >= 3)
|
||||
{
|
||||
bool wantReset = false;
|
||||
|
||||
/* Get plugin index that was passed */
|
||||
const char *arg = command.Arg(2);
|
||||
if (argcount >= 4 && strcmp(arg, "reset") == 0)
|
||||
{
|
||||
wantReset = true;
|
||||
arg = command.Arg(3);
|
||||
}
|
||||
|
||||
/* Get plugin object */
|
||||
CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
|
||||
@@ -301,21 +355,34 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
||||
return;
|
||||
}
|
||||
|
||||
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
||||
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
||||
|
||||
/* Iterate convar list and display each one */
|
||||
if (!wantReset)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
||||
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
||||
}
|
||||
|
||||
/* Iterate convar list and display/reset each one */
|
||||
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
||||
{
|
||||
const ConVar *pConVar = (*iter);
|
||||
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
||||
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter);
|
||||
if (!wantReset)
|
||||
{
|
||||
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
||||
} else {
|
||||
pConVar->Revert();
|
||||
}
|
||||
}
|
||||
|
||||
if (wantReset)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Display usage of subcommand */
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>");
|
||||
}
|
||||
|
||||
Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max)
|
||||
@@ -523,7 +590,8 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
||||
}
|
||||
|
||||
/* If the forward now has 0 functions in it... */
|
||||
if (pForward->GetFunctionCount() == 0)
|
||||
if (pForward->GetFunctionCount() == 0 &&
|
||||
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
|
||||
{
|
||||
/* Free this forward */
|
||||
g_Forwards.ReleaseForward(pForward);
|
||||
@@ -634,6 +702,8 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||
|
||||
if (pForward != NULL)
|
||||
{
|
||||
ConVarReentrancyGuard guard(pConVar);
|
||||
|
||||
/* Now call forwards in plugins that have hooked this */
|
||||
pForward->PushCell(pInfo->handle);
|
||||
pForward->PushString(oldValue);
|
||||
|
||||
@@ -0,0 +1,747 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* On SourceHook v4.3 or lower, there are no DVP hooks. Very sad, right?
|
||||
* Only do this on newer versions. For the older code, we'll do an incredibly
|
||||
* hacky detour.
|
||||
*
|
||||
* The idea of the "non-hacky" (yeah... no) code is that every unique
|
||||
* ConCommand vtable gets its own DVP hook. We watch for unloading and
|
||||
* loading commands to remove stale hooks from SH.
|
||||
*/
|
||||
|
||||
#include "sourcemod.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "Logger.h"
|
||||
#include "compat_wrappers.h"
|
||||
#include "ConsoleDetours.h"
|
||||
#include <IGameConfigs.h>
|
||||
#include "sm_stringutil.h"
|
||||
#include "ConCmdManager.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "ConCommandBaseIterator.h"
|
||||
#include "ShareSys.h"
|
||||
|
||||
#if defined PLATFORM_POSIX
|
||||
# include <dlfcn.h>
|
||||
# include <sys/mman.h>
|
||||
# include <stdint.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if SH_IMPL_VERSION >= 5
|
||||
# if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||
# else
|
||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||
# endif
|
||||
#else
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHVPAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>,bool);
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
# endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
|
||||
#if SH_IMPL_VERSION >= 4
|
||||
|
||||
class GenericCommandHooker : public IConCommandLinkListener
|
||||
{
|
||||
struct HackInfo
|
||||
{
|
||||
void **vtable;
|
||||
int hook;
|
||||
unsigned int refcount;
|
||||
};
|
||||
CVector<HackInfo> vtables;
|
||||
bool enabled;
|
||||
SourceHook::MemFuncInfo dispatch;
|
||||
|
||||
inline void **GetVirtualTable(ConCommandBase *pBase)
|
||||
{
|
||||
return *reinterpret_cast<void***>(reinterpret_cast<char*>(pBase) +
|
||||
dispatch.thisptroffs +
|
||||
dispatch.vtbloffs);
|
||||
}
|
||||
|
||||
inline bool FindVtable(void **ptr, size_t& index)
|
||||
{
|
||||
for (size_t i = 0; i < vtables.size(); i++)
|
||||
{
|
||||
if (vtables[i].vtable == ptr)
|
||||
{
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MakeHookable(ConCommandBase *pBase)
|
||||
{
|
||||
if (!pBase->IsCommand())
|
||||
return;
|
||||
|
||||
ConCommand *cmd = (ConCommand*)pBase;
|
||||
void **vtable = GetVirtualTable(cmd);
|
||||
|
||||
size_t index;
|
||||
if (!FindVtable(vtable, index))
|
||||
{
|
||||
HackInfo hack;
|
||||
hack.vtable = vtable;
|
||||
hack.hook = SH_ADD_VPHOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &GenericCommandHooker::Dispatch), false);
|
||||
hack.refcount = 1;
|
||||
vtables.push_back(hack);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtables[index].refcount++;
|
||||
}
|
||||
}
|
||||
|
||||
# if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void Dispatch(const CCommand& args)
|
||||
# else
|
||||
void Dispatch()
|
||||
# endif
|
||||
{
|
||||
cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand)
|
||||
# if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
, args
|
||||
# endif
|
||||
);
|
||||
if (res >= Pl_Handled)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
void ReparseCommandList()
|
||||
{
|
||||
for (size_t i = 0; i < vtables.size(); i++)
|
||||
vtables[i].refcount = 0;
|
||||
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
|
||||
MakeHookable(iter.Get());
|
||||
CVector<HackInfo>::iterator iter = vtables.begin();
|
||||
while (iter != vtables.end())
|
||||
{
|
||||
if ((*iter).refcount)
|
||||
{
|
||||
iter++;
|
||||
continue;
|
||||
}
|
||||
/* Damn it. This event happens AFTER the plugin has unloaded!
|
||||
* There's two options. Remove the hook now and hope SH's memory
|
||||
* protection will prevent a crash. Otherwise, we can wait until
|
||||
* the server shuts down and more likely crash then.
|
||||
*
|
||||
* This situation only arises if:
|
||||
* 1) Someone has used AddCommandFilter()
|
||||
* 2) ... on a Dark Messiah server (mm:s new api)
|
||||
* 3) ... and another MM:S plugin that uses ConCommands has unloaded.
|
||||
*
|
||||
* Even though the impact is really small, we'll wait until the
|
||||
* server shuts down, so normal operation isn't interrupted.
|
||||
*
|
||||
* See bug 4018.
|
||||
*/
|
||||
iter = vtables.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void UnhookCommand(ConCommandBase *pBase)
|
||||
{
|
||||
if (!pBase->IsCommand())
|
||||
return;
|
||||
|
||||
ConCommand *cmd = (ConCommand*)pBase;
|
||||
void **vtable = GetVirtualTable(cmd);
|
||||
|
||||
size_t index;
|
||||
if (!FindVtable(vtable, index))
|
||||
{
|
||||
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
assert(vtables[index].refcount > 0);
|
||||
vtables[index].refcount--;
|
||||
if (vtables[index].refcount == 0)
|
||||
{
|
||||
SH_REMOVE_HOOK_ID(vtables[index].hook);
|
||||
vtables.erase(vtables.iterAt(index));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
GenericCommandHooker() : enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool Enable()
|
||||
{
|
||||
SourceHook::GetFuncInfo(&ConCommand::Dispatch, dispatch);
|
||||
|
||||
if (dispatch.thisptroffs < 0)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not determine ConCommand layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
|
||||
MakeHookable(iter.Get());
|
||||
|
||||
if (!vtables.size())
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find any cvars!");
|
||||
return false;
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Disable()
|
||||
{
|
||||
for (size_t i = 0; i < vtables.size(); i++)
|
||||
SH_REMOVE_HOOK_ID(vtables[i].hook);
|
||||
vtables.clear();
|
||||
}
|
||||
|
||||
virtual void OnLinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
MakeHookable(pBase);
|
||||
}
|
||||
|
||||
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
if (pBase == NULL)
|
||||
ReparseCommandList();
|
||||
else
|
||||
UnhookCommand(pBase);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* END DVP HOOK VERSION
|
||||
*/
|
||||
|
||||
#else /* SH_IMPL_VERSION >= 4 */
|
||||
|
||||
/**
|
||||
* BEGIN ENGINE DETOUR VERSION
|
||||
*/
|
||||
|
||||
# include <jit/jit_helpers.h>
|
||||
# include <jit/x86/x86_macros.h>
|
||||
|
||||
class GenericCommandHooker
|
||||
{
|
||||
struct Patch
|
||||
{
|
||||
Patch() : applied(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool applied;
|
||||
void *base;
|
||||
unsigned char search[16];
|
||||
size_t search_len;
|
||||
size_t offset;
|
||||
size_t saveat;
|
||||
int regparam;
|
||||
void *detour;
|
||||
};
|
||||
|
||||
Patch ces;
|
||||
Patch cgc;
|
||||
|
||||
public:
|
||||
static void DelayedActivation(void *inparam)
|
||||
{
|
||||
GenericCommandHooker *cdtrs = reinterpret_cast<GenericCommandHooker*>(inparam);
|
||||
/* Safe to re-enter because the frame queue is lock+swapped. */
|
||||
if ((!cdtrs->ces.applied || !cdtrs->cgc.applied) &&
|
||||
g_HL2.PeekCommandStack() != NULL)
|
||||
{
|
||||
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, cdtrs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cdtrs->ces.applied)
|
||||
cdtrs->ApplyPatch(&cdtrs->ces);
|
||||
if (!cdtrs->cgc.applied)
|
||||
cdtrs->ApplyPatch(&cdtrs->cgc);
|
||||
}
|
||||
|
||||
bool Enable()
|
||||
{
|
||||
const char *platform = NULL;
|
||||
# if defined(PLATFORM_WINDOWS)
|
||||
platform = "Windows";
|
||||
# else
|
||||
void *addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
|
||||
Dl_info info;
|
||||
if (!dladdr(addrInBase, &info))
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find engine name");
|
||||
return false;
|
||||
}
|
||||
if (strstr(info.dli_fname, "engine_i486"))
|
||||
{
|
||||
platform = "Linux_486";
|
||||
}
|
||||
else if (strstr(info.dli_fname, "engine_i686"))
|
||||
{
|
||||
platform = "Linux_686";
|
||||
}
|
||||
else if (strstr(info.dli_fname, "engine_amd"))
|
||||
{
|
||||
platform = "Linux_AMD";
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogError("Command filter could not determine engine (%s)", info.dli_fname);
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (!PrepPatch("Cmd_ExecuteString", "CES", platform, &ces))
|
||||
return false;
|
||||
if (!PrepPatch("CGameClient::ExecuteString", "CGC", platform, &cgc))
|
||||
return false;
|
||||
|
||||
if (g_HL2.PeekCommandStack() != NULL)
|
||||
{
|
||||
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
ApplyPatch(&ces);
|
||||
ApplyPatch(&cgc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Disable()
|
||||
{
|
||||
UndoPatch(&ces);
|
||||
UndoPatch(&cgc);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
# if !defined PLATFORM_WINDOWS
|
||||
# define PAGE_READWRITE PROT_READ|PROT_WRITE
|
||||
# define PAGE_EXECUTE_READ PROT_READ|PROT_EXEC
|
||||
|
||||
static inline uintptr_t AddrToPage(uintptr_t address)
|
||||
{
|
||||
return (address & ~(uintptr_t(sysconf(_SC_PAGE_SIZE) - 1)));
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
void Protect(void *addr, size_t length, int prot)
|
||||
{
|
||||
# if defined PLATFORM_WINDOWS
|
||||
DWORD ignore;
|
||||
VirtualProtect(addr, length, prot, &ignore);
|
||||
# else
|
||||
uintptr_t startPage = AddrToPage(uintptr_t(addr));
|
||||
length += (uintptr_t(addr) - startPage);
|
||||
mprotect((void*)startPage, length, prot);
|
||||
# endif
|
||||
}
|
||||
|
||||
void UndoPatch(Patch *patch)
|
||||
{
|
||||
if (!patch->applied || patch->detour == NULL)
|
||||
return;
|
||||
|
||||
g_pSourcePawn->FreePageMemory(patch->detour);
|
||||
|
||||
unsigned char *source = (unsigned char *)patch->base + patch->offset;
|
||||
Protect(source, patch->search_len, PAGE_READWRITE);
|
||||
for (size_t i = 0; i < patch->search_len; i++)
|
||||
source[i] = patch->search[i];
|
||||
Protect(source, patch->search_len, PAGE_EXECUTE_READ);
|
||||
}
|
||||
|
||||
void ApplyPatch(Patch *patch)
|
||||
{
|
||||
assert(!patch->applied);
|
||||
|
||||
size_t length = 0;
|
||||
void *callback = (void*)&ConsoleDetours::Dispatch;
|
||||
|
||||
/* Bogus assignment to make compiler is doing the right thing. */
|
||||
patch->detour = callback;
|
||||
|
||||
/* Assemgle the detour. */
|
||||
JitWriter writer;
|
||||
writer.outbase = NULL;
|
||||
writer.outptr = NULL;
|
||||
do
|
||||
{
|
||||
/* Need a specific register, or value on stack? */
|
||||
if (patch->regparam != -1)
|
||||
IA32_Push_Reg(&writer, patch->regparam);
|
||||
/* Call real function. */
|
||||
IA32_Write_Jump32_Abs(&writer, IA32_Call_Imm32(&writer, 0), callback);
|
||||
/* Restore stack. */
|
||||
if (patch->regparam != -1)
|
||||
IA32_Pop_Reg(&writer, patch->regparam);
|
||||
/* Copy any saved bytes */
|
||||
if (patch->saveat)
|
||||
{
|
||||
for (size_t i = patch->saveat; i < patch->search_len; i++)
|
||||
{
|
||||
writer.write_ubyte(patch->search[i]);
|
||||
}
|
||||
}
|
||||
/* Jump back to the caller. */
|
||||
unsigned char *target = (unsigned char *)patch->base + patch->offset + patch->search_len;
|
||||
IA32_Jump_Imm32_Abs(&writer, target);
|
||||
/* Assemble, if we can. */
|
||||
if (writer.outbase == NULL)
|
||||
{
|
||||
length = writer.outptr - writer.outbase;
|
||||
patch->detour = g_pSourcePawn->AllocatePageMemory(length);
|
||||
if (patch->detour == NULL)
|
||||
{
|
||||
g_Logger.LogError("Ran out of memory!");
|
||||
return;
|
||||
}
|
||||
g_pSourcePawn->SetReadWrite(patch->detour);
|
||||
writer.outbase = (jitcode_t)patch->detour;
|
||||
writer.outptr = writer.outbase;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
g_pSourcePawn->SetReadExecute(patch->detour);
|
||||
|
||||
unsigned char *source = (unsigned char *)patch->base + patch->offset;
|
||||
Protect(source, 6, PAGE_READWRITE);
|
||||
source[0] = 0xFF;
|
||||
source[1] = 0x25;
|
||||
*(void **)&source[2] = &patch->detour;
|
||||
Protect(source, 6, PAGE_EXECUTE_READ);
|
||||
|
||||
patch->applied = true;
|
||||
}
|
||||
|
||||
bool PrepPatch(const char *signature, const char *name, const char *platform, Patch *patch)
|
||||
{
|
||||
/* Get the base address of the function. */
|
||||
if (!g_pGameConf->GetMemSig(signature, &patch->base) || patch->base == NULL)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find signature: %s", signature);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *value;
|
||||
char keyname[255];
|
||||
|
||||
/* Get the verification bytes that will be written over. */
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Patch_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find key: %s", keyname);
|
||||
return false;
|
||||
}
|
||||
patch->search_len = UTIL_DecodeHexString(patch->search, sizeof(patch->search), value);
|
||||
if (patch->search_len < 6)
|
||||
{
|
||||
g_Logger.LogError("Error decoding %s value, or not long enough", keyname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the offset into the function. */
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Offset_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find key: %s", keyname);
|
||||
return false;
|
||||
}
|
||||
patch->offset = atoi(value);
|
||||
if (patch->offset > 20000)
|
||||
{
|
||||
g_Logger.LogError("Command filter %s value is bogus", keyname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the number of bytes to save from what was written over. */
|
||||
patch->saveat = 0;
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Save_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
|
||||
{
|
||||
patch->saveat = atoi(value);
|
||||
if (patch->saveat >= patch->search_len)
|
||||
{
|
||||
g_Logger.LogError("Command filter %s value is too large", keyname);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get register for parameter, if any. */
|
||||
patch->regparam = -1;
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Reg_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
|
||||
{
|
||||
patch->regparam = atoi(value);
|
||||
}
|
||||
|
||||
/* Everything loaded from gamedata, make sure the patch will succeed. */
|
||||
unsigned char *address = (unsigned char *)patch->base + patch->offset;
|
||||
for (size_t i = 0; i < patch->search_len; i++)
|
||||
{
|
||||
if (address[i] != patch->search[i])
|
||||
{
|
||||
g_Logger.LogError("Command filter %s has changed (byte %x is not %x sub-offset %d)",
|
||||
name, address[i], patch->search[i], i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static bool dummy_hook_set = false;
|
||||
void DummyHook()
|
||||
{
|
||||
if (dummy_hook_set)
|
||||
{
|
||||
dummy_hook_set = false;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BEGIN THE ACTUALLY GENERIC CODE.
|
||||
*/
|
||||
|
||||
#define FEATURECAP_COMMANDLISTENER "command listener"
|
||||
|
||||
static GenericCommandHooker s_GenericHooker;
|
||||
ConsoleDetours g_ConsoleDetours;
|
||||
|
||||
ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
|
||||
{
|
||||
}
|
||||
|
||||
void ConsoleDetours::OnSourceModAllInitialized()
|
||||
{
|
||||
m_pForward = g_Forwards.CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
|
||||
Param_String, Param_Cell);
|
||||
g_ShareSys.AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
|
||||
}
|
||||
|
||||
void ConsoleDetours::OnSourceModShutdown()
|
||||
{
|
||||
List<Listener*>::iterator iter = m_Listeners.begin();
|
||||
while (iter != m_Listeners.end())
|
||||
{
|
||||
Listener *listener = (*iter);
|
||||
g_Forwards.ReleaseForward(listener->forward);
|
||||
delete listener;
|
||||
iter = m_Listeners.erase(iter);
|
||||
}
|
||||
|
||||
g_Forwards.ReleaseForward(m_pForward);
|
||||
s_GenericHooker.Disable();
|
||||
}
|
||||
|
||||
FeatureStatus ConsoleDetours::GetFeatureStatus(FeatureType type, const char *name)
|
||||
{
|
||||
return GetStatus();
|
||||
}
|
||||
|
||||
FeatureStatus ConsoleDetours::GetStatus()
|
||||
{
|
||||
if (status == FeatureStatus_Unknown)
|
||||
{
|
||||
status = s_GenericHooker.Enable() ? FeatureStatus_Available : FeatureStatus_Unavailable;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
|
||||
{
|
||||
if (GetStatus() != FeatureStatus_Available)
|
||||
return false;
|
||||
|
||||
if (command == NULL)
|
||||
{
|
||||
m_pForward->AddFunction(fun);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *str = UTIL_ToLowerCase(command);
|
||||
Listener *listener;
|
||||
Listener **plistener = m_CmdLookup.retrieve(str);
|
||||
if (plistener == NULL)
|
||||
{
|
||||
listener = new Listener;
|
||||
listener->forward = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
|
||||
Param_String, Param_Cell);
|
||||
m_CmdLookup.insert(str, listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
listener = *plistener;
|
||||
}
|
||||
listener->forward->AddFunction(fun);
|
||||
delete [] str;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
|
||||
{
|
||||
if (command == NULL)
|
||||
{
|
||||
return m_pForward->RemoveFunction(fun);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *str = UTIL_ToLowerCase(command);
|
||||
Listener *listener;
|
||||
Listener **plistener = m_CmdLookup.retrieve(str);
|
||||
delete [] str;
|
||||
if (plistener == NULL)
|
||||
return false;
|
||||
listener = *plistener;
|
||||
return listener->forward->RemoveFunction(fun);
|
||||
}
|
||||
}
|
||||
|
||||
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
|
||||
{
|
||||
char name[255];
|
||||
const char *realname = args.Arg(0);
|
||||
size_t len = strlen(realname);
|
||||
|
||||
// Disallow command strings that are too long, for now.
|
||||
if (len >= sizeof(name) - 1)
|
||||
return Pl_Continue;
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (realname[i] >= 'A' && realname[i] <= 'Z')
|
||||
name[i] = tolower(realname[i]);
|
||||
else
|
||||
name[i] = realname[i];
|
||||
}
|
||||
name[len] = '\0';
|
||||
|
||||
cell_t result = Pl_Continue;
|
||||
m_pForward->PushCell(client);
|
||||
m_pForward->PushString(name);
|
||||
m_pForward->PushCell(args.ArgC() - 1);
|
||||
m_pForward->Execute(&result, NULL);
|
||||
|
||||
/* Don't let plugins block this. */
|
||||
if (strcmp(name, "sm") == 0)
|
||||
result = Pl_Continue;
|
||||
|
||||
if (result >= Pl_Handled)
|
||||
return result;
|
||||
|
||||
Listener **plistener = m_CmdLookup.retrieve(name);
|
||||
if (plistener == NULL)
|
||||
return result;
|
||||
Listener *listener = *plistener;
|
||||
if (listener->forward->GetFunctionCount() == 0)
|
||||
return result;
|
||||
|
||||
cell_t result2 = Pl_Continue;
|
||||
listener->forward->PushCell(client);
|
||||
listener->forward->PushString(name);
|
||||
listener->forward->PushCell(args.ArgC() - 1);
|
||||
listener->forward->Execute(&result2, NULL);
|
||||
|
||||
if (result2 > result)
|
||||
result = result2;
|
||||
|
||||
/* "sm" should not have flown through the above. */
|
||||
assert(strcmp(name, "sm") != 0 || result == Pl_Continue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
cell_t ConsoleDetours::Dispatch(ConCommand *pBase, const CCommand& args)
|
||||
{
|
||||
#else
|
||||
cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
|
||||
{
|
||||
CCommand args;
|
||||
#endif
|
||||
g_HL2.PushCommandStack(&args);
|
||||
cell_t res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), args);
|
||||
g_HL2.PopCommandStack();
|
||||
|
||||
#if SH_IMPL_VERSION < 4
|
||||
if (res >= Pl_Handled)
|
||||
{
|
||||
/* See bug 4020 - we can't optimize this because looking at the vtable
|
||||
* is probably more expensive, since there's no SH_GET_ORIG_VFNPTR_ENTRY.
|
||||
*/
|
||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
|
||||
dummy_hook_set = true;
|
||||
pBase->Dispatch();
|
||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure the command gets invoked. See bug 4019 on making this better. */
|
||||
pBase->Dispatch();
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#ifndef _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||
#define _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "ForwardSys.h"
|
||||
#include <sm_trie_tpl.h>
|
||||
|
||||
class ConsoleDetours :
|
||||
public SMGlobalClass,
|
||||
public IFeatureProvider
|
||||
{
|
||||
friend class PlayerManager;
|
||||
friend class GenericCommandHooker;
|
||||
|
||||
struct Listener
|
||||
{
|
||||
IChangeableForward *forward;
|
||||
};
|
||||
public:
|
||||
ConsoleDetours();
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IFeatureProvider
|
||||
FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
|
||||
public:
|
||||
bool AddListener(IPluginFunction *fun, const char *command);
|
||||
bool RemoveListener(IPluginFunction *fun, const char *command);
|
||||
private:
|
||||
cell_t InternalDispatch(int client, const CCommand& args);
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
|
||||
#else
|
||||
static cell_t Dispatch(ConCommand *pBase);
|
||||
#endif
|
||||
public:
|
||||
FeatureStatus GetStatus();
|
||||
bool IsEnabled()
|
||||
{
|
||||
return status == FeatureStatus_Available;
|
||||
}
|
||||
private:
|
||||
FeatureStatus status;
|
||||
IChangeableForward *m_pForward;
|
||||
KTrie<Listener*> m_CmdLookup;
|
||||
List<Listener*> m_Listeners;
|
||||
};
|
||||
|
||||
extern ConsoleDetours g_ConsoleDetours;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_ */
|
||||
|
||||
+47
-15
@@ -34,7 +34,7 @@
|
||||
#include "sourcemod.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "sm_version.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include "sm_stringutil.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "Logger.h"
|
||||
@@ -68,7 +68,11 @@ void Hook_ExecDispatchPre(const CCommand &cmd)
|
||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||
void Hook_ExecDispatchPre()
|
||||
#else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
void Hook_ExecDispatchPre()
|
||||
#endif
|
||||
@@ -103,11 +107,7 @@ void CheckAndFinalizeConfigs()
|
||||
{
|
||||
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
g_PendingInternalPush = true;
|
||||
#else
|
||||
SM_InternalCmdTrigger();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,17 +193,30 @@ void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &comma
|
||||
|
||||
if (res == ConfigResult_Reject)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\" (%s)", option, value, error);
|
||||
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error);
|
||||
} else if (res == ConfigResult_Ignore) {
|
||||
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
||||
} else {
|
||||
g_RootMenu.ConsolePrint("Config option \"%s\" successfully set to \"%s.\"", option, value);
|
||||
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" successfully set to \"%s\".", option, value);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (argcount >= 3) {
|
||||
const char *option = command.Arg(2);
|
||||
|
||||
const char *value = GetCoreConfigValue(option);
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
||||
} else {
|
||||
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> [value]");
|
||||
}
|
||||
|
||||
void CoreConfig::Initialize()
|
||||
@@ -214,14 +227,28 @@ void CoreConfig::Initialize()
|
||||
/* Try to get command line value of core config convar */
|
||||
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
||||
|
||||
/* If sm_corecfgfile not specified on command line, use default value */
|
||||
if (!corecfg)
|
||||
/* If sm_corecfgfile is on the command line, use that
|
||||
* If sm_corecfgfile isn't there, check sm_basepath on the command line and build the path off that
|
||||
* If sm_basepath isn't there, just use the default path for the cfg
|
||||
*/
|
||||
if (corecfg)
|
||||
{
|
||||
corecfg = sm_corecfgfile.GetDefault();
|
||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *basepath = icvar->GetCommandLineValue("sm_basepath");
|
||||
|
||||
/* Format path to config file */
|
||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
||||
/* Format path to config file */
|
||||
if (basepath)
|
||||
{
|
||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset cached key values */
|
||||
m_KeyValues.clear();
|
||||
@@ -381,7 +408,7 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||
FILE *fp = fopen(file, "wt");
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SVN_FULL_VERSION);
|
||||
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SM_VERSION_STRING);
|
||||
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
||||
fprintf(fp, "\n\n");
|
||||
|
||||
@@ -438,6 +465,11 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||
can_create = false;
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
|
||||
return can_create;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
-32
@@ -37,7 +37,7 @@
|
||||
#include "Logger.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include <stdlib.h>
|
||||
#include "ThreadSupport.h"
|
||||
#include <IThreader.h>
|
||||
|
||||
#define DBPARSE_LEVEL_NONE 0
|
||||
#define DBPARSE_LEVEL_MAIN 1
|
||||
@@ -47,7 +47,7 @@ DBManager g_DBMan;
|
||||
static bool s_OneTimeThreaderErrorMsg = false;
|
||||
|
||||
DBManager::DBManager()
|
||||
: m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
|
||||
: m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ void DBManager::OnSourceModShutdown()
|
||||
m_pQueueLock->DestroyThis();
|
||||
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
||||
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
||||
ClearConfigs();
|
||||
}
|
||||
|
||||
unsigned int DBManager::GetInterfaceVersion()
|
||||
@@ -133,13 +134,20 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
|
||||
void DBManager::ReadSMC_ParseStart()
|
||||
{
|
||||
m_confs.clear();
|
||||
ClearConfigs();
|
||||
m_ParseLevel = 0;
|
||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||
m_StrTab.Reset();
|
||||
m_DefDriver.clear();
|
||||
}
|
||||
|
||||
void DBManager::ClearConfigs()
|
||||
{
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
delete (*iter);
|
||||
m_confs.clear();
|
||||
}
|
||||
|
||||
ConfDbInfo s_CurInfo;
|
||||
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
@@ -159,7 +167,7 @@ SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *nam
|
||||
}
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||
s_CurInfo = ConfDbInfo();
|
||||
s_CurInfo.name = m_StrTab.AddString(name);
|
||||
s_CurInfo.name = name;
|
||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||
m_ParseLevel++;
|
||||
@@ -186,16 +194,16 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
{
|
||||
if (strcmp(value, "default") != 0)
|
||||
{
|
||||
s_CurInfo.driver = m_StrTab.AddString(value);
|
||||
s_CurInfo.driver = value;
|
||||
}
|
||||
} else if (strcmp(key, "database") == 0) {
|
||||
s_CurInfo.database = m_StrTab.AddString(value);
|
||||
s_CurInfo.database = value;
|
||||
} else if (strcmp(key, "host") == 0) {
|
||||
s_CurInfo.host = m_StrTab.AddString(value);
|
||||
s_CurInfo.host = value;
|
||||
} else if (strcmp(key, "user") == 0) {
|
||||
s_CurInfo.user = m_StrTab.AddString(value);
|
||||
s_CurInfo.user = value;
|
||||
} else if (strcmp(key, "pass") == 0) {
|
||||
s_CurInfo.pass = m_StrTab.AddString(value);
|
||||
s_CurInfo.pass = value;
|
||||
} else if (strcmp(key, "timeout") == 0) {
|
||||
s_CurInfo.info.maxTimeout = atoi(value);
|
||||
} else if (strcmp(key, "port") == 0) {
|
||||
@@ -206,13 +214,6 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
#define ASSIGN_VAR(var) \
|
||||
if (s_CurInfo.var == -1) { \
|
||||
s_CurInfo.info.var = ""; \
|
||||
} else { \
|
||||
s_CurInfo.info.var = m_StrTab.GetString(s_CurInfo.var); \
|
||||
}
|
||||
|
||||
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
@@ -223,17 +224,26 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
||||
{
|
||||
/* Set all of the info members to either a blank string
|
||||
* or the string pointer from the string table.
|
||||
*/
|
||||
ASSIGN_VAR(driver);
|
||||
ASSIGN_VAR(database);
|
||||
ASSIGN_VAR(host);
|
||||
ASSIGN_VAR(user);
|
||||
ASSIGN_VAR(pass);
|
||||
ConfDbInfo *cdb = new ConfDbInfo();
|
||||
|
||||
cdb->name = s_CurInfo.name;
|
||||
cdb->driver = s_CurInfo.driver;
|
||||
cdb->host = s_CurInfo.host;
|
||||
cdb->user = s_CurInfo.user;
|
||||
cdb->pass = s_CurInfo.pass;
|
||||
cdb->database = s_CurInfo.database;
|
||||
cdb->realDriver = s_CurInfo.realDriver;
|
||||
cdb->info.maxTimeout = s_CurInfo.info.maxTimeout;
|
||||
cdb->info.port = s_CurInfo.info.port;
|
||||
|
||||
cdb->info.driver = cdb->driver.c_str();
|
||||
cdb->info.database = cdb->database.c_str();
|
||||
cdb->info.host = cdb->host.c_str();
|
||||
cdb->info.user = cdb->user.c_str();
|
||||
cdb->info.pass = cdb->pass.c_str();
|
||||
|
||||
/* Save it.. */
|
||||
m_confs.push_back(s_CurInfo);
|
||||
m_confs.push_back(cdb);
|
||||
|
||||
/* Go up one level */
|
||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||
@@ -244,7 +254,6 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
#undef ASSIGN_VAR
|
||||
|
||||
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
@@ -333,10 +342,10 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
||||
}
|
||||
|
||||
/* Make sure NOTHING references this! */
|
||||
List<ConfDbInfo>::iterator iter;
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
{
|
||||
ConfDbInfo &db = (*iter);
|
||||
ConfDbInfo &db = *(*iter);
|
||||
if (db.realDriver == pDriver)
|
||||
{
|
||||
db.realDriver = NULL;
|
||||
@@ -448,12 +457,12 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
||||
|
||||
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
|
||||
{
|
||||
List<ConfDbInfo>::iterator iter;
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
{
|
||||
ConfDbInfo &conf = (*iter);
|
||||
if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
|
||||
ConfDbInfo &conf = *(*iter);
|
||||
if (conf.name == name)
|
||||
{
|
||||
return &conf;
|
||||
}
|
||||
|
||||
+9
-10
@@ -47,16 +47,15 @@ using namespace SourceHook;
|
||||
|
||||
struct ConfDbInfo
|
||||
{
|
||||
ConfDbInfo() : name(-1), driver(-1), host(-1), user(-1), pass(-1),
|
||||
database(-1), realDriver(NULL)
|
||||
ConfDbInfo() : realDriver(NULL)
|
||||
{
|
||||
}
|
||||
int name;
|
||||
int driver;
|
||||
int host;
|
||||
int user;
|
||||
int pass;
|
||||
int database;
|
||||
String name;
|
||||
String driver;
|
||||
String host;
|
||||
String user;
|
||||
String pass;
|
||||
String database;
|
||||
IDBDriver *realDriver;
|
||||
DatabaseInfo info;
|
||||
};
|
||||
@@ -121,6 +120,7 @@ public:
|
||||
return m_DatabaseType;
|
||||
}
|
||||
private:
|
||||
void ClearConfigs();
|
||||
void KillWorkerThread();
|
||||
private:
|
||||
CVector<IDBDriver *> m_drivers;
|
||||
@@ -134,11 +134,10 @@ private:
|
||||
IMutex *m_pQueueLock; /* Queue safety lock */
|
||||
IMutex *m_pThinkLock; /* Think-queue lock */
|
||||
|
||||
List<ConfDbInfo> m_confs;
|
||||
List<ConfDbInfo *> m_confs;
|
||||
HandleType_t m_DriverType;
|
||||
HandleType_t m_DatabaseType;
|
||||
String m_DefDriver;
|
||||
BaseStringTable m_StrTab;
|
||||
char m_Filename[PLATFORM_MAX_PATH];
|
||||
unsigned int m_ParseLevel;
|
||||
unsigned int m_ParseState;
|
||||
|
||||
@@ -56,11 +56,16 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
|
||||
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[512];
|
||||
|
||||
va_start(ap, message);
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
|
||||
GenerateErrorVA(ctx, func_idx, err, message, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
|
||||
{
|
||||
char buffer[512];
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
|
||||
|
||||
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
||||
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||
|
||||
@@ -46,6 +46,7 @@ public: // IDebugListener
|
||||
void OnDebugSpew(const char *msg, ...);
|
||||
public:
|
||||
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
||||
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
|
||||
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
||||
private:
|
||||
int _GetPluginIndex(IPluginContext *ctx);
|
||||
|
||||
+36
-3
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -42,6 +42,20 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
|
||||
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
||||
typedef List<EventHook *> EventHookList;
|
||||
|
||||
class EventForwardFilter : public IForwardFilter
|
||||
{
|
||||
EventInfo *pEventInfo;
|
||||
public:
|
||||
EventForwardFilter(EventInfo *pEventInfo) : pEventInfo(pEventInfo)
|
||||
{
|
||||
}
|
||||
|
||||
void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
|
||||
{
|
||||
params[2].val = pEventInfo->bDontBroadcast ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
EventManager::EventManager() : m_EventType(0)
|
||||
{
|
||||
/* Create an event lookup trie */
|
||||
@@ -147,6 +161,13 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
int EventManager::GetEventDebugID()
|
||||
{
|
||||
return EVENT_DEBUG_ID_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
||||
{
|
||||
EventHook *pHook;
|
||||
@@ -327,6 +348,7 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name,
|
||||
|
||||
pInfo->pEvent = pEvent;
|
||||
pInfo->pOwner = pContext->GetIdentity();
|
||||
pInfo->bDontBroadcast = false;
|
||||
|
||||
return pInfo;
|
||||
}
|
||||
@@ -365,6 +387,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
IChangeableForward *pForward;
|
||||
const char *name;
|
||||
cell_t res = Pl_Continue;
|
||||
bool broadcast = bDontBroadcast;
|
||||
|
||||
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
|
||||
if (!pEvent)
|
||||
@@ -390,10 +413,16 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||
|
||||
info.bDontBroadcast = bDontBroadcast;
|
||||
|
||||
EventForwardFilter filter(&info);
|
||||
|
||||
pForward->PushCell(hndl);
|
||||
pForward->PushString(name);
|
||||
pForward->PushCell(bDontBroadcast);
|
||||
pForward->Execute(&res, NULL);
|
||||
pForward->Execute(&res, &filter);
|
||||
|
||||
broadcast = info.bDontBroadcast;
|
||||
|
||||
g_HandleSys.FreeHandle(hndl, &sec);
|
||||
}
|
||||
@@ -414,6 +443,9 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
m_EventStack.push(NULL);
|
||||
}
|
||||
|
||||
if (broadcast != bDontBroadcast)
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast));
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||
}
|
||||
|
||||
@@ -441,6 +473,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
{
|
||||
if (pHook->postCopy)
|
||||
{
|
||||
info.bDontBroadcast = bDontBroadcast;
|
||||
info.pEvent = m_EventCopies.front();
|
||||
info.pOwner = NULL;
|
||||
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||
|
||||
+5
-1
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -53,6 +53,7 @@ struct EventInfo
|
||||
}
|
||||
IGameEvent *pEvent;
|
||||
IdentityToken_t *pOwner;
|
||||
bool bDontBroadcast;
|
||||
};
|
||||
|
||||
struct EventHook
|
||||
@@ -104,6 +105,9 @@ public: // IPluginsListener
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
public: // IGameEventListener2
|
||||
void FireGameEvent(IGameEvent *pEvent);
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
int GetEventDebugID();
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Get the 'GameEvent' handle type ID.
|
||||
|
||||
+354
-50
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
CExtensionManager g_Extensions;
|
||||
IdentityType_t g_ExtType;
|
||||
@@ -49,6 +50,9 @@ void CExtension::Initialize(const char *filename, const char *path)
|
||||
m_bFullyLoaded = false;
|
||||
m_File.assign(filename);
|
||||
m_Path.assign(path);
|
||||
char real_name[PLATFORM_MAX_PATH];
|
||||
g_LibSys.GetFileFromPath(real_name, sizeof(real_name), m_Path.c_str());
|
||||
m_RealFile.assign(real_name);
|
||||
}
|
||||
|
||||
CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filename, const char *path)
|
||||
@@ -57,6 +61,42 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
|
||||
m_pAPI = pAPI;
|
||||
}
|
||||
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#define GAMEFIX "2.l4d"
|
||||
#elif SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||
#define GAMEFIX "2.l4d2"
|
||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
#define GAMEFIX "2.nd"
|
||||
#elif SOURCE_ENGINE == SE_ALIENSWARM
|
||||
#define GAMEFIX "2.swarm"
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
||||
#define GAMEFIX "2.ep2"
|
||||
#elif SOURCE_ENGINE == SE_BLOODYGOODTIME
|
||||
#define GAMEFIX "2.bgt"
|
||||
#elif SOURCE_ENGINE == SE_EYE
|
||||
#define GAMEFIX "2.eye"
|
||||
#elif SOURCE_ENGINE == SE_CSS
|
||||
#define GAMEFIX "2.css"
|
||||
#elif SOURCE_ENGINE == SE_HL2DM
|
||||
#define GAMEFIX "2.hl2dm"
|
||||
#elif SOURCE_ENGINE == SE_DODS
|
||||
#define GAMEFIX "2.dods"
|
||||
#elif SOURCE_ENGINE == SE_TF2
|
||||
#define GAMEFIX "2.tf2"
|
||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
#define GAMEFIX "2.darkm"
|
||||
#elif SOURCE_ENGINE == SE_PORTAL2
|
||||
#define GAMEFIX "2.portal2"
|
||||
#elif SOURCE_ENGINE == SE_CSGO
|
||||
#define GAMEFIX "2.csgo"
|
||||
#else
|
||||
#define GAMEFIX "2.ep1"
|
||||
#endif //(SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2)
|
||||
#else //METAMOD_PLAPI_VERSION
|
||||
#define GAMEFIX "1.ep1"
|
||||
#endif //METAMOD_PLAPI_VERSION
|
||||
|
||||
CLocalExtension::CLocalExtension(const char *filename)
|
||||
{
|
||||
m_PlId = 0;
|
||||
@@ -64,31 +104,68 @@ CLocalExtension::CLocalExtension(const char *filename)
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
/* Special case for new bintools binary */
|
||||
if (strcmp(filename, "bintools.ext") == 0)
|
||||
{
|
||||
goto normal;
|
||||
}
|
||||
|
||||
/* Zeroth, see if there is an engine specific build in the new place. */
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s." GAMEFIX "." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
if (g_LibSys.IsPathFile(path))
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM
|
||||
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
if (g_LibSys.IsPathFile(path))
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
if (g_LibSys.IsPathFile(path))
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* First see if there is an engine specific build! */
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
"extensions/auto.2.l4d/%s",
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
||||
"extensions/auto.2.ep2/%s",
|
||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
"extensions/auto.2.darkm/%s",
|
||||
#else
|
||||
"extensions/auto.2.ep1/%s",
|
||||
#endif //SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#else //METAMOD_PLAPI_VERSION
|
||||
"extensions/auto.1.ep1/%s",
|
||||
#endif //METAMOD_PLAPI_VERSION
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/auto." GAMEFIX "/%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
/* Try the "normal" version */
|
||||
if (!g_LibSys.IsPathFile(path))
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "extensions/%s", filename);
|
||||
normal:
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
}
|
||||
|
||||
found:
|
||||
Initialize(filename, path);
|
||||
}
|
||||
|
||||
@@ -145,6 +222,28 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
|
||||
{
|
||||
bool already;
|
||||
m_PlId = g_pMMPlugins->Load(m_Path.c_str(), g_PLID, already, error, maxlength);
|
||||
|
||||
// Check the plugin didn't refuse load
|
||||
Pl_Status status;
|
||||
|
||||
#ifndef METAMOD_PLAPI_VERSION
|
||||
const char *file;
|
||||
PluginId source;
|
||||
#endif
|
||||
|
||||
if (!m_PlId || (
|
||||
#ifndef METAMOD_PLAPI_VERSION
|
||||
g_pMMPlugins->Query(m_PlId, file, status, source)
|
||||
#else
|
||||
g_pMMPlugins->Query(m_PlId, NULL, &status, NULL)
|
||||
#endif
|
||||
&& status < Pl_Paused))
|
||||
{
|
||||
m_pLib->CloseLibrary();
|
||||
m_pLib = NULL;
|
||||
m_pAPI = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CExtension::Load(error, maxlength))
|
||||
@@ -187,6 +286,23 @@ void CLocalExtension::Unload()
|
||||
}
|
||||
}
|
||||
|
||||
bool CRemoteExtension::Reload(char *error, size_t maxlength)
|
||||
{
|
||||
snprintf(error, maxlength, "Remote extensions do not support reloading");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CLocalExtension::Reload(char *error, size_t maxlength)
|
||||
{
|
||||
if (m_pLib == NULL) // FIXME: just load it instead?
|
||||
return false;
|
||||
|
||||
m_pAPI->OnExtensionUnload();
|
||||
Unload();
|
||||
|
||||
return Load(error, maxlength);
|
||||
}
|
||||
|
||||
bool CRemoteExtension::IsExternal()
|
||||
{
|
||||
return true;
|
||||
@@ -291,7 +407,12 @@ IExtensionInterface *CExtension::GetAPI()
|
||||
|
||||
const char *CExtension::GetFilename()
|
||||
{
|
||||
return m_File.c_str();
|
||||
return m_RealFile.c_str();
|
||||
}
|
||||
|
||||
const char *CExtension::GetPath() const
|
||||
{
|
||||
return m_Path.c_str();
|
||||
}
|
||||
|
||||
IdentityToken_t *CExtension::GetIdentity()
|
||||
@@ -494,7 +615,7 @@ void CExtensionManager::TryAutoload()
|
||||
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
len = UTIL_Format(file, sizeof(file), "%s", lfile);
|
||||
strcpy(&file[len - 9], ".ext." PLATFORM_LIB_EXT);
|
||||
strcpy(&file[len - 9], ".ext");
|
||||
|
||||
LoadAutoExtension(file);
|
||||
|
||||
@@ -502,13 +623,16 @@ void CExtensionManager::TryAutoload()
|
||||
}
|
||||
}
|
||||
|
||||
IExtension *CExtensionManager::LoadAutoExtension(const char *path)
|
||||
IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOnMissing)
|
||||
{
|
||||
if (!strstr(path, "." PLATFORM_LIB_EXT))
|
||||
/* Remove platform extension if it's there. Compat hack. */
|
||||
const char *ext = g_LibSys.GetFileExtension(path);
|
||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
{
|
||||
char newpath[PLATFORM_MAX_PATH];
|
||||
g_LibSys.PathFormat(newpath, sizeof(newpath), "%s.%s", path, PLATFORM_LIB_EXT);
|
||||
return LoadAutoExtension(newpath);
|
||||
char path2[PLATFORM_MAX_PATH];
|
||||
UTIL_Format(path2, sizeof(path2), "%s", path);
|
||||
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||
return LoadAutoExtension(path2, bErrorOnMissing);
|
||||
}
|
||||
|
||||
IExtension *pAlready;
|
||||
@@ -527,7 +651,11 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path)
|
||||
|
||||
if (!p->Load(error, sizeof(error)) || !p->IsLoaded())
|
||||
{
|
||||
g_Logger.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
|
||||
if (bErrorOnMissing || g_LibSys.IsPathFile(p->GetPath()))
|
||||
{
|
||||
g_Logger.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
|
||||
}
|
||||
|
||||
p->SetError(error);
|
||||
}
|
||||
|
||||
@@ -546,24 +674,12 @@ IExtension *CExtensionManager::FindExtensionByFile(const char *file)
|
||||
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
|
||||
{
|
||||
pExt = (*iter);
|
||||
char short_file[PLATFORM_MAX_PATH];
|
||||
g_LibSys.GetFileFromPath(short_file, sizeof(short_file), pExt->GetFilename());
|
||||
if (strcmp(lookup, short_file) == 0)
|
||||
if (pExt->IsSameFile(lookup))
|
||||
{
|
||||
return pExt;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got no results, test if there was a platform extension.
|
||||
* If not, add one.
|
||||
*/
|
||||
if (!strstr(file, "." PLATFORM_LIB_EXT))
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
UTIL_Format(path, sizeof(path), "%s.%s", file, PLATFORM_LIB_EXT);
|
||||
return FindExtensionByFile(path);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -601,6 +717,16 @@ IExtension *CExtensionManager::FindExtensionByName(const char *ext)
|
||||
|
||||
IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
/* Remove platform extension if it's there. Compat hack. */
|
||||
const char *ext = g_LibSys.GetFileExtension(file);
|
||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
{
|
||||
char path2[PLATFORM_MAX_PATH];
|
||||
UTIL_Format(path2, sizeof(path2), "%s", file);
|
||||
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||
return LoadExtension(path2, error, maxlength);
|
||||
}
|
||||
|
||||
IExtension *pAlready;
|
||||
if ((pAlready=FindExtensionByFile(file)) != NULL)
|
||||
{
|
||||
@@ -710,6 +836,13 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Tell it to unload */
|
||||
if (pExt->IsLoaded())
|
||||
{
|
||||
IExtensionInterface *pAPI = pExt->GetAPI();
|
||||
pAPI->OnExtensionUnload();
|
||||
}
|
||||
|
||||
/* First remove us from internal lists */
|
||||
g_ShareSys.RemoveInterfaces(_pExt);
|
||||
m_Libs.remove(pExt);
|
||||
@@ -733,7 +866,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
s_iter != pExt->m_Libraries.end();
|
||||
s_iter++)
|
||||
{
|
||||
g_PluginSys.OnLibraryAction((*s_iter).c_str(), false, true);
|
||||
g_PluginSys.OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed);
|
||||
}
|
||||
|
||||
/* Notify and/or unload all dependencies */
|
||||
@@ -804,13 +937,6 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell it to unload */
|
||||
if (pExt->IsLoaded())
|
||||
{
|
||||
IExtensionInterface *pAPI = pExt->GetAPI();
|
||||
pAPI->OnExtensionUnload();
|
||||
}
|
||||
|
||||
pExt->Unload();
|
||||
delete pExt;
|
||||
|
||||
@@ -909,11 +1035,42 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (strcmp(cmd, "load") == 0)
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts load <file>");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *filename = command.Arg(3);
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
char error[256];
|
||||
|
||||
UTIL_Format(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
|
||||
!strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
|
||||
|
||||
if (FindExtensionByFile(path) != NULL)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s is already loaded.", path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LoadExtension(path, error, sizeof(error)))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Loaded extension %s successfully.", path);
|
||||
} else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s failed to load: %s", path, error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (strcmp(cmd, "info") == 0)
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -921,7 +1078,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
unsigned int id = atoi(sId);
|
||||
if (id <= 0)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -998,7 +1155,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm unload <#> [code]");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts unload <#> [code]");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1111,14 +1268,148 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "reload") == 0)
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts reload <#>");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *arg = command.Arg(3);
|
||||
unsigned int num = atoi(arg);
|
||||
CExtension *pExt = FindByOrder(num);
|
||||
|
||||
if (!pExt)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pExt->IsLoaded())
|
||||
{
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
char error[255];
|
||||
|
||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
||||
|
||||
if (pExt->Reload(error, sizeof(error)))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s is now reloaded.", filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s failed to reload: %s", filename, error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s is not loaded.", pExt->GetFilename());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
g_RootMenu.ConsolePrint("SourceMod Extensions Menu:");
|
||||
g_RootMenu.DrawGenericOption("info", "Extra extension information");
|
||||
g_RootMenu.DrawGenericOption("list", "List extensions");
|
||||
g_RootMenu.DrawGenericOption("load", "Load an extension");
|
||||
g_RootMenu.DrawGenericOption("reload", "Reload an extension");
|
||||
g_RootMenu.DrawGenericOption("unload", "Unload an extension");
|
||||
}
|
||||
|
||||
void CExtensionManager::ListExtensionsToClient(CPlayer *player, const CCommand &args)
|
||||
{
|
||||
char buffer[256];
|
||||
int numExtensions = m_Libs.size();
|
||||
edict_t *edict = player->GetEdict();
|
||||
unsigned int id = 0;
|
||||
unsigned int start = 0;
|
||||
|
||||
if (!numExtensions)
|
||||
{
|
||||
ClientConsolePrint(edict, "[SM] No extensions found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.ArgC() > 2)
|
||||
{
|
||||
start = atoi(args.Arg(2));
|
||||
}
|
||||
|
||||
CExtension *ext;
|
||||
SourceHook::List<CExtension *>::iterator iter;
|
||||
|
||||
for (iter = m_Libs.begin();
|
||||
iter != m_Libs.end();
|
||||
iter++)
|
||||
{
|
||||
ext = (*iter);
|
||||
|
||||
char error[255];
|
||||
if (!ext->IsRunning(error, sizeof(error)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
id++;
|
||||
if (id < start)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id - start > 10)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
IExtensionInterface *api = ext->GetAPI();
|
||||
|
||||
const char *name = api->GetExtensionName();
|
||||
const char *version = api->GetExtensionVerString();
|
||||
const char *author = api->GetExtensionAuthor();
|
||||
const char *description = api->GetExtensionDescription();
|
||||
|
||||
size_t len = UTIL_Format(buffer, sizeof(buffer), " \"%s\"", name);
|
||||
|
||||
if (version != NULL && IS_STR_FILLED(version))
|
||||
{
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", version);
|
||||
}
|
||||
|
||||
if (author != NULL && IS_STR_FILLED(author))
|
||||
{
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", author);
|
||||
}
|
||||
|
||||
if (description != NULL && IS_STR_FILLED(description))
|
||||
{
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, ": %s", description);
|
||||
}
|
||||
|
||||
|
||||
ClientConsolePrint(edict, "%s", buffer);
|
||||
}
|
||||
|
||||
while (iter != m_Libs.end())
|
||||
{
|
||||
char error[255];
|
||||
if ((*iter)->IsRunning(error, sizeof(error)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter != m_Libs.end())
|
||||
{
|
||||
ClientConsolePrint(edict, "To see more, type \"sm exts %d\"", id);
|
||||
}
|
||||
}
|
||||
|
||||
CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr)
|
||||
{
|
||||
if (ptr->type == g_ExtType)
|
||||
@@ -1141,7 +1432,7 @@ void CExtensionManager::AddLibrary(IExtension *pSource, const char *library)
|
||||
{
|
||||
CExtension *pExt = (CExtension *)pSource;
|
||||
pExt->AddLibrary(library);
|
||||
g_PluginSys.OnLibraryAction(library, false, false);
|
||||
g_PluginSys.OnLibraryAction(library, LibraryAction_Added);
|
||||
}
|
||||
|
||||
bool CExtensionManager::LibraryExists(const char *library)
|
||||
@@ -1210,3 +1501,16 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CLocalExtension::IsSameFile(const char *file)
|
||||
{
|
||||
/* Only care about the shortened name. */
|
||||
return strcmp(file, m_File.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CRemoteExtension::IsSameFile(const char *file)
|
||||
{
|
||||
/* :TODO: this could be better, but no one uses this API anyway. */
|
||||
return strcmp(file, m_Path.c_str()) == 0;
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -45,6 +45,8 @@
|
||||
#include "PluginSys.h"
|
||||
#include "NativeOwner.h"
|
||||
|
||||
class CPlayer;
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourceHook;
|
||||
|
||||
@@ -66,6 +68,7 @@ public:
|
||||
public: //IExtension
|
||||
IExtensionInterface *GetAPI();
|
||||
const char *GetFilename();
|
||||
const char *GetPath() const;
|
||||
IdentityToken_t *GetIdentity();
|
||||
ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
|
||||
bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
|
||||
@@ -83,6 +86,8 @@ public:
|
||||
virtual bool Load(char *error, size_t maxlength);
|
||||
virtual bool IsLoaded() =0;
|
||||
virtual void Unload() =0;
|
||||
virtual bool Reload(char *error, size_t maxlength) =0;
|
||||
virtual bool IsSameFile(const char* file) =0;
|
||||
protected:
|
||||
void Initialize(const char *filename, const char *path);
|
||||
bool PerformAPICheck(char *error, size_t maxlength);
|
||||
@@ -92,6 +97,7 @@ protected:
|
||||
IdentityToken_t *m_pIdentToken;
|
||||
IExtensionInterface *m_pAPI;
|
||||
String m_File;
|
||||
String m_RealFile;
|
||||
String m_Path;
|
||||
String m_Error;
|
||||
List<IfaceInfo> m_Deps; /** Dependencies */
|
||||
@@ -110,7 +116,9 @@ public:
|
||||
bool Load(char *error, size_t maxlength);
|
||||
bool IsLoaded();
|
||||
void Unload();
|
||||
bool Reload(char *error, size_t maxlength);
|
||||
bool IsExternal();
|
||||
bool IsSameFile(const char *file);
|
||||
private:
|
||||
PluginId m_PlId;
|
||||
ILibrary *m_pLib;
|
||||
@@ -124,7 +132,9 @@ public:
|
||||
bool Load(char *error, size_t maxlength);
|
||||
bool IsLoaded();
|
||||
void Unload();
|
||||
bool Reload(char *error, size_t maxlength);
|
||||
bool IsExternal();
|
||||
bool IsSameFile(const char *file);
|
||||
};
|
||||
|
||||
class CExtensionManager :
|
||||
@@ -156,7 +166,7 @@ public: //IPluginsListener
|
||||
public: //IRootConsoleCommand
|
||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||
public:
|
||||
IExtension *LoadAutoExtension(const char *path);
|
||||
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
|
||||
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
|
||||
void AddInterface(IExtension *pOwner, SMInterface *pInterface);
|
||||
void BindChildPlugin(IExtension *pParent, CPlugin *pPlugin);
|
||||
@@ -167,6 +177,8 @@ public:
|
||||
bool LibraryExists(const char *library);
|
||||
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
|
||||
public:
|
||||
void ListExtensionsToClient(CPlayer *player, const CCommand &args);
|
||||
public:
|
||||
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
|
||||
void Shutdown();
|
||||
|
||||
+14
-8
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -255,6 +255,7 @@ CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int nu
|
||||
}
|
||||
|
||||
CForward *pForward = g_Forwards.ForwardMake();
|
||||
pForward->m_IterGuard = NULL;
|
||||
pForward->m_curparam = 0;
|
||||
pForward->m_ExecType = et;
|
||||
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
||||
@@ -294,7 +295,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
cell_t high_result = 0;
|
||||
cell_t low_result = 0;
|
||||
int err;
|
||||
unsigned int failed=0, success=0;
|
||||
unsigned int success=0;
|
||||
unsigned int num_params = m_curparam;
|
||||
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||
FwdParamInfo *param;
|
||||
@@ -304,10 +305,15 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
memcpy(temp_info, m_params, sizeof(m_params));
|
||||
m_curparam = 0;
|
||||
|
||||
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
||||
FuncIteratorGuard guard(&m_IterGuard, &iter);
|
||||
|
||||
while (iter != m_functions.end())
|
||||
{
|
||||
func = (*iter);
|
||||
|
||||
if (filter)
|
||||
filter->Preprocess(func, temp_info);
|
||||
|
||||
for (unsigned int i=0; i<num_params; i++)
|
||||
{
|
||||
int err = SP_ERROR_PARAM;
|
||||
@@ -359,11 +365,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
}
|
||||
|
||||
/* Call the function and deal with the return value. */
|
||||
if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
|
||||
{
|
||||
failed++;
|
||||
}
|
||||
else
|
||||
if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE)
|
||||
{
|
||||
success++;
|
||||
switch (m_ExecType)
|
||||
@@ -403,6 +405,9 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!guard.Triggered())
|
||||
iter++;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -682,6 +687,7 @@ bool CForward::RemoveFunction(IPluginFunction *func)
|
||||
{
|
||||
if ((*iter) == func)
|
||||
{
|
||||
m_IterGuard->FixIteratorChain(iter);
|
||||
found = true;
|
||||
lst->erase(iter);
|
||||
break;
|
||||
|
||||
@@ -61,6 +61,58 @@ struct FwdParamInfo
|
||||
ParamType pushedas;
|
||||
};
|
||||
|
||||
class SourceMod::IForwardFilter
|
||||
{
|
||||
public:
|
||||
virtual void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class FuncIteratorGuard
|
||||
{
|
||||
bool triggered;
|
||||
FuncIteratorGuard **pprev;
|
||||
FuncIter *iter;
|
||||
FuncIteratorGuard *next;
|
||||
public:
|
||||
FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter)
|
||||
: triggered(false), pprev(pprev), iter(iter), next(*pprev)
|
||||
{
|
||||
*pprev = this;
|
||||
}
|
||||
|
||||
~FuncIteratorGuard()
|
||||
{
|
||||
*pprev = next;
|
||||
}
|
||||
|
||||
inline bool Triggered()
|
||||
{
|
||||
bool t = triggered;
|
||||
triggered = false;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should not read from |this| before the NULL check, because FwdSys
|
||||
* can call (NULL)->FixIteratorChain().
|
||||
*/
|
||||
void FixIteratorChain(FuncIter &other)
|
||||
{
|
||||
FuncIteratorGuard *guard = this;
|
||||
while (guard != NULL)
|
||||
{
|
||||
if (*guard->iter == other)
|
||||
{
|
||||
*(guard->iter) = ++(*(guard->iter));
|
||||
guard->triggered = true;
|
||||
}
|
||||
guard = guard->next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CForward : public IChangeableForward
|
||||
{
|
||||
public: //ICallable
|
||||
@@ -103,6 +155,7 @@ protected:
|
||||
*/
|
||||
mutable List<IPluginFunction *> m_functions;
|
||||
mutable List<IPluginFunction *> m_paused;
|
||||
FuncIteratorGuard *m_IterGuard;
|
||||
|
||||
/* Type and name information */
|
||||
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
||||
|
||||
+578
-16
@@ -35,12 +35,45 @@
|
||||
#include "UserMessages.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "GameConfigs.h"
|
||||
#include <IGameConfigs.h>
|
||||
#include <compat_wrappers.h>
|
||||
#include <Logger.h>
|
||||
#include "LibrarySys.h"
|
||||
#include "logic_bridge.h"
|
||||
#include <tier0/mem.h>
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <cstrike15_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef ICommandLine *(*FakeGetCommandLine)();
|
||||
|
||||
#if defined _WIN32
|
||||
#define TIER0_NAME "tier0.dll"
|
||||
#define VSTDLIB_NAME "vstdlib.dll"
|
||||
#elif defined __APPLE__
|
||||
#define TIER0_NAME "libtier0.dylib"
|
||||
#define VSTDLIB_NAME "libvstdlib.dylib"
|
||||
#elif defined __linux__
|
||||
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||
#define TIER0_NAME "libtier0_srv.so"
|
||||
#define VSTDLIB_NAME "libvstdlib_srv.so"
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#define TIER0_NAME "libtier0.so"
|
||||
#define VSTDLIB_NAME "libvstdlib.so"
|
||||
#else
|
||||
#define TIER0_NAME "tier0_i486.so"
|
||||
#define VSTDLIB_NAME "vstdlib_i486.so"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CHalfLife2 g_HL2;
|
||||
ConVar *sv_lan = NULL;
|
||||
|
||||
static void *g_EntList = NULL;
|
||||
static int entInfoOffset = -1;
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
template<>
|
||||
@@ -92,14 +125,16 @@ CHalfLife2::~CHalfLife2()
|
||||
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
|
||||
#endif
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||
bool is_original_engine = false;
|
||||
#endif
|
||||
|
||||
void CHalfLife2::OnSourceModStartup(bool late)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
|
||||
/* The Ship currently is the only known game to use an older version of the engine */
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
||||
#else
|
||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
||||
@@ -123,7 +158,137 @@ void CHalfLife2::OnSourceModAllInitialized()
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION
|
||||
void CHalfLife2::OnSourceModAllInitialized_Post()
|
||||
{
|
||||
InitLogicalEntData();
|
||||
InitCommandLine();
|
||||
}
|
||||
|
||||
void CHalfLife2::InitLogicalEntData()
|
||||
{
|
||||
char *addr = NULL;
|
||||
|
||||
/*
|
||||
* gEntList and/or g_pEntityList
|
||||
*
|
||||
* First try to lookup pointer directly for platforms with symbols.
|
||||
* If symbols aren't present (Windows or stripped Linux/Mac),
|
||||
* attempt find via LevelShutdown + offset
|
||||
*/
|
||||
if (g_pGameConf->GetMemSig("gEntList", (void **)&addr))
|
||||
{
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
if (!addr)
|
||||
{
|
||||
// Key exists so notify if lookup fails, but try other method.
|
||||
g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
g_EntList = reinterpret_cast<void *>(addr);
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (!g_EntList)
|
||||
{
|
||||
if (!g_pGameConf->GetMemSig("LevelShutdown", (void **)&addr))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (LevelShutdown) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
g_Logger.LogError("Failed lookup of LevelShutdown - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
int offset;
|
||||
if (!g_pGameConf->GetOffset("gEntList", &offset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
||||
}
|
||||
|
||||
if (!g_EntList)
|
||||
{
|
||||
g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CHalfLife2::InitCommandLine()
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
char error[256];
|
||||
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "../bin/" TIER0_NAME);
|
||||
|
||||
if (!g_LibSys.IsPathFile(path))
|
||||
{
|
||||
g_Logger.LogError("Could not find path for: " TIER0_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
ILibrary *lib = g_LibSys.OpenLibrary(path, error, sizeof(error));
|
||||
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine_Tier0");
|
||||
|
||||
/* '_Tier0' dropped on Alien Swarm version */
|
||||
if (m_pGetCommandLine == NULL)
|
||||
{
|
||||
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
|
||||
}
|
||||
|
||||
if (m_pGetCommandLine == NULL)
|
||||
{
|
||||
/* We probably have a Ship engine. */
|
||||
lib->CloseLibrary();
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "../bin/" VSTDLIB_NAME);
|
||||
if (!g_LibSys.IsPathFile(path))
|
||||
{
|
||||
g_Logger.LogError("Could not find path for: " VSTDLIB_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((lib = g_LibSys.OpenLibrary(path, error, sizeof(error))) == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not load %s: %s", path, error);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
|
||||
|
||||
if (m_pGetCommandLine == NULL)
|
||||
{
|
||||
g_Logger.LogError("Could not locate any command line functionality");
|
||||
}
|
||||
|
||||
lib->CloseLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
ICommandLine *CHalfLife2::GetValveCommandLine()
|
||||
{
|
||||
if (!m_pGetCommandLine)
|
||||
return NULL;
|
||||
|
||||
return ((FakeGetCommandLine)((FakeGetCommandLine *)m_pGetCommandLine))();
|
||||
}
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||
bool CHalfLife2::IsOriginalEngine()
|
||||
{
|
||||
return is_original_engine;
|
||||
@@ -172,8 +337,13 @@ bool UTIL_FindInSendTable(SendTable *pTable,
|
||||
return false;
|
||||
}
|
||||
|
||||
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
|
||||
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name, bool *isNested)
|
||||
{
|
||||
if (isNested)
|
||||
{
|
||||
*isNested = false;
|
||||
}
|
||||
|
||||
while (pMap)
|
||||
{
|
||||
for (int i=0; i<pMap->dataNumFields; i++)
|
||||
@@ -188,10 +358,21 @@ typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
|
||||
}
|
||||
if (pMap->dataDesc[i].td)
|
||||
{
|
||||
typedescription_t *_td;
|
||||
if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
|
||||
if (isNested)
|
||||
{
|
||||
return _td;
|
||||
*isNested = (UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL) != NULL);
|
||||
if (*isNested)
|
||||
{
|
||||
return NULL;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else { // Use the old behaviour, we dont want to spring this on extensions - even if they're doing bad things.
|
||||
typedescription_t *_td;
|
||||
if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL)) != NULL)
|
||||
{
|
||||
return _td;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,6 +465,11 @@ SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
|
||||
}
|
||||
|
||||
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
|
||||
{
|
||||
return this->FindInDataMap(pMap, offset, NULL);
|
||||
}
|
||||
|
||||
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested)
|
||||
{
|
||||
typedescription_t *td = NULL;
|
||||
DataMapTrie &val = m_Maps[pMap];
|
||||
@@ -294,7 +480,7 @@ typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset
|
||||
}
|
||||
if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
|
||||
{
|
||||
if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
|
||||
if ((td = UTIL_FindInDataMap(pMap, offset, isNested)) != NULL)
|
||||
{
|
||||
sm_trie_insert(val.trie, offset, td);
|
||||
}
|
||||
@@ -326,7 +512,9 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
|
||||
|
||||
bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
bf_write *pBitBuf = NULL;
|
||||
#endif
|
||||
cell_t players[] = {client};
|
||||
|
||||
if (dest == HUD_PRINTTALK)
|
||||
@@ -339,7 +527,18 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
char buffer[192];
|
||||
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_SayText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pMsg->set_ent_idx(0);
|
||||
pMsg->set_text(buffer);
|
||||
pMsg->set_chat(false);
|
||||
#else
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -347,6 +546,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
pBitBuf->WriteByte(0);
|
||||
pBitBuf->WriteString(buffer);
|
||||
pBitBuf->WriteByte(1);
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
@@ -354,13 +554,29 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
}
|
||||
}
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_TextMsg *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Client tries to read all 5 'params' and will crash if less
|
||||
pMsg->set_msg_dst(dest);
|
||||
pMsg->add_params(msg);
|
||||
pMsg->add_params("");
|
||||
pMsg->add_params("");
|
||||
pMsg->add_params("");
|
||||
pMsg->add_params("");
|
||||
#else
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pBitBuf->WriteByte(dest);
|
||||
pBitBuf->WriteString(msg);
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
@@ -369,10 +585,20 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
|
||||
bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
{
|
||||
bf_write *pBitBuf = NULL;
|
||||
cell_t players[] = {client};
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_HintText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pMsg->set_text(msg);
|
||||
#else
|
||||
bf_write *pBitBuf = NULL;
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -383,6 +609,38 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
pBitBuf->WriteByte(1);
|
||||
}
|
||||
pBitBuf->WriteString(msg);
|
||||
#endif
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_HintText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pMsg->set_text(msg);
|
||||
#else
|
||||
bf_write *pBitBuf = NULL;
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *pre_byte = g_pGameConf->GetKeyValue("HintTextPreByte");
|
||||
if (pre_byte != NULL && strcmp(pre_byte, "yes") == 0)
|
||||
{
|
||||
pBitBuf->WriteByte(1);
|
||||
}
|
||||
pBitBuf->WriteString(msg);
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
@@ -390,15 +648,23 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
|
||||
bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
|
||||
{
|
||||
bf_write *pBitBuf = NULL;
|
||||
KeyValues *SubKey = NULL;
|
||||
int count = 0;
|
||||
cell_t players[] = {client};
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_VGUIMenu *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bf_write *pBitBuf = NULL;
|
||||
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data)
|
||||
{
|
||||
@@ -411,6 +677,18 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
SubKey = data->GetFirstSubKey();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pMsg->set_name(name);
|
||||
pMsg->set_show(show);
|
||||
|
||||
while (SubKey)
|
||||
{
|
||||
CCSUsrMsg_VGUIMenu_Subkey *key = pMsg->add_subkeys();
|
||||
key->set_name(SubKey->GetName());
|
||||
key->set_str(SubKey->GetString());
|
||||
SubKey = SubKey->GetNextKey();
|
||||
}
|
||||
#else
|
||||
pBitBuf->WriteString(name);
|
||||
pBitBuf->WriteByte((show) ? 1 : 0);
|
||||
pBitBuf->WriteByte(count);
|
||||
@@ -420,6 +698,8 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
pBitBuf->WriteString(SubKey->GetString());
|
||||
SubKey = SubKey->GetNextKey();
|
||||
}
|
||||
#endif
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
@@ -474,7 +754,7 @@ bool CHalfLife2::IsLANServer()
|
||||
|
||||
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
|
||||
{
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
||||
#else
|
||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
||||
@@ -551,6 +831,14 @@ const char *CHalfLife2::CurrentCommandName()
|
||||
|
||||
void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
|
||||
{
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||
if (!pPlayer || !pPlayer->IsConnected() || pPlayer->IsInKickQueue())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pPlayer->MarkAsBeingKicked();
|
||||
|
||||
DelayedKickInfo kick;
|
||||
|
||||
kick.client = client;
|
||||
@@ -599,7 +887,10 @@ edict_t *CHalfLife2::GetHandleEntity(CBaseHandle &hndl)
|
||||
edict_t *pStoredEdict;
|
||||
CBaseEntity *pStoredEntity;
|
||||
|
||||
pStoredEdict = GetEntity(index, &pStoredEntity);
|
||||
if (!IndexToAThings(index, &pStoredEntity, &pStoredEdict))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pStoredEdict == NULL || pStoredEntity == NULL)
|
||||
{
|
||||
@@ -642,3 +933,274 @@ void CHalfLife2::ServerCommand(const char *buffer)
|
||||
{
|
||||
engine->ServerCommand(buffer);
|
||||
}
|
||||
|
||||
cell_t CHalfLife2::EntityToReference(CBaseEntity *pEntity)
|
||||
{
|
||||
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
|
||||
CBaseHandle hndl = pUnknown->GetRefEHandle();
|
||||
return (hndl.ToInt() | (1<<31));
|
||||
}
|
||||
|
||||
CBaseEntity *CHalfLife2::ReferenceToEntity(cell_t entRef)
|
||||
{
|
||||
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CEntInfo *pInfo = NULL;
|
||||
|
||||
if (entRef & (1<<31))
|
||||
{
|
||||
/* Proper ent reference */
|
||||
int hndlValue = entRef & ~(1<<31);
|
||||
CBaseHandle hndl(hndlValue);
|
||||
|
||||
pInfo = LookupEntity(hndl.GetEntryIndex());
|
||||
if (!pInfo || pInfo->m_SerialNumber != hndl.GetSerialNumber())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Old style index only */
|
||||
pInfo = LookupEntity(entRef);
|
||||
}
|
||||
|
||||
if (!pInfo)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnk = static_cast<IServerUnknown *>(pInfo->m_pEntity);
|
||||
if (pUnk)
|
||||
{
|
||||
return pUnk->GetBaseEntity();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the CEntInfo pointer from g_EntList for a given entity index
|
||||
*/
|
||||
CEntInfo *CHalfLife2::LookupEntity(int entIndex)
|
||||
{
|
||||
// Make sure that our index is within the bounds of the global ent array
|
||||
if (entIndex < 0 || entIndex >= NUM_ENT_ENTRIES)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_EntList || entInfoOffset == -1)
|
||||
{
|
||||
/* Attempt to use engine interface instead */
|
||||
static CEntInfo tempInfo;
|
||||
tempInfo.m_pNext = NULL;
|
||||
tempInfo.m_pPrev = NULL;
|
||||
|
||||
edict_t *pEdict = PEntityOfEntIndex(entIndex);
|
||||
|
||||
if (!pEdict)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnk = pEdict->GetUnknown();
|
||||
|
||||
if (!pUnk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tempInfo.m_pEntity = pUnk;
|
||||
tempInfo.m_SerialNumber = pUnk->GetRefEHandle().GetSerialNumber();
|
||||
|
||||
return &tempInfo;
|
||||
}
|
||||
|
||||
CEntInfo *pArray = (CEntInfo *)(((unsigned char *)g_EntList) + entInfoOffset);
|
||||
return &pArray[entIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
SERIAL_MASK = 0x7fff (15 bits)
|
||||
|
||||
#define MAX_EDICT_BITS 11
|
||||
#define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 1)
|
||||
m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS);
|
||||
|
||||
Top 5 bits of a handle are unused.
|
||||
Bit 31 - Our 'reference' flag indicator
|
||||
*/
|
||||
|
||||
cell_t CHalfLife2::IndexToReference(int entIndex)
|
||||
{
|
||||
CBaseEntity *pEnt = ReferenceToEntity(entIndex);
|
||||
if (!pEnt)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
return EntityToReference(pEnt);
|
||||
}
|
||||
|
||||
int CHalfLife2::ReferenceToIndex(cell_t entRef)
|
||||
{
|
||||
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
if (entRef & (1<<31))
|
||||
{
|
||||
/* Proper ent reference */
|
||||
int hndlValue = entRef & ~(1<<31);
|
||||
CBaseHandle hndl(hndlValue);
|
||||
|
||||
CEntInfo *pInfo = LookupEntity(hndl.GetEntryIndex());
|
||||
|
||||
if (pInfo->m_SerialNumber != hndl.GetSerialNumber())
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
return hndl.GetEntryIndex();
|
||||
}
|
||||
|
||||
return entRef;
|
||||
}
|
||||
|
||||
cell_t CHalfLife2::EntityToBCompatRef(CBaseEntity *pEntity)
|
||||
{
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
|
||||
CBaseHandle hndl = pUnknown->GetRefEHandle();
|
||||
|
||||
if (hndl == INVALID_EHANDLE_INDEX)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
if (hndl.GetEntryIndex() >= MAX_EDICTS)
|
||||
{
|
||||
return (hndl.ToInt() | (1<<31));
|
||||
}
|
||||
else
|
||||
{
|
||||
return hndl.GetEntryIndex();
|
||||
}
|
||||
}
|
||||
|
||||
cell_t CHalfLife2::ReferenceToBCompatRef(cell_t entRef)
|
||||
{
|
||||
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
int hndlValue = entRef & ~(1<<31);
|
||||
CBaseHandle hndl(hndlValue);
|
||||
|
||||
if (hndl.GetEntryIndex() < MAX_EDICTS)
|
||||
{
|
||||
return hndl.GetEntryIndex();
|
||||
}
|
||||
|
||||
return entRef;
|
||||
}
|
||||
|
||||
void *CHalfLife2::GetGlobalEntityList()
|
||||
{
|
||||
return g_EntList;
|
||||
}
|
||||
|
||||
int CHalfLife2::GetSendPropOffset(SendProp *prop)
|
||||
{
|
||||
return prop->GetOffset();
|
||||
}
|
||||
|
||||
const char *CHalfLife2::GetEntityClassname(edict_t * pEdict)
|
||||
{
|
||||
if (pEdict == NULL || pEdict->IsFree())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnk = pEdict->GetUnknown();
|
||||
if (pUnk == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CBaseEntity * pEntity = pUnk->GetBaseEntity();
|
||||
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GetEntityClassname(pEntity);
|
||||
}
|
||||
|
||||
const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
|
||||
{
|
||||
static int offset = -1;
|
||||
if (offset == -1)
|
||||
{
|
||||
datamap_t *pMap = GetDataMap(pEntity);
|
||||
typedescription_t *pDesc = FindInDataMap(pMap, "m_iClassname");
|
||||
offset = GetTypeDescOffs(pDesc);
|
||||
}
|
||||
|
||||
return *(const char **)(((unsigned char *)pEntity) + offset);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
static bool ResolveFuzzyMapName(const char *fuzzyName, char *outFullname, int size)
|
||||
{
|
||||
static ConCommand *pHelperCmd = g_pCVar->FindCommand("changelevel");
|
||||
if (!pHelperCmd || !pHelperCmd->CanAutoComplete())
|
||||
return false;
|
||||
|
||||
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
|
||||
|
||||
CUtlVector<CUtlString> results;
|
||||
pHelperCmd->AutoCompleteSuggest(fuzzyName, results);
|
||||
if (results.Count() == 0)
|
||||
return false;
|
||||
|
||||
// Results come back as you'd see in autocomplete. (ie. "changelevel fullmapnamehere"),
|
||||
// so skip ahead to start of map path/name
|
||||
|
||||
// Like the engine, we're only going to deal with the first match.
|
||||
|
||||
strncopy(outFullname, &results[0][helperCmdLen + 1], size);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CHalfLife2::IsMapValid(const char *map)
|
||||
{
|
||||
if (!map || !map[0])
|
||||
return false;
|
||||
|
||||
bool ret = engine->IsMapValid(map);
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
if (!ret)
|
||||
{
|
||||
static char szFuzzyName[PLATFORM_MAX_PATH];
|
||||
if (ResolveFuzzyMapName(map, szFuzzyName, sizeof(szFuzzyName)))
|
||||
{
|
||||
ret = engine->IsMapValid(szFuzzyName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
+41
-2
@@ -43,6 +43,11 @@
|
||||
#include <KeyValues.h>
|
||||
#include <server_class.h>
|
||||
#include <datamap.h>
|
||||
#include <ihandleentity.h>
|
||||
#include <tier0/icommandline.h>
|
||||
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||
#include <string_t.h>
|
||||
#endif
|
||||
|
||||
class CCommand;
|
||||
|
||||
@@ -86,6 +91,20 @@ struct DelayedKickInfo
|
||||
char buffer[384];
|
||||
};
|
||||
|
||||
// copy from game/shared/entitylist_base.h
|
||||
class CEntInfo
|
||||
{
|
||||
public:
|
||||
IHandleEntity *m_pEntity;
|
||||
int m_SerialNumber;
|
||||
CEntInfo *m_pPrev;
|
||||
CEntInfo *m_pNext;
|
||||
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||
string_t m_iName;
|
||||
string_t m_iClassName;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CHalfLife2 :
|
||||
public SMGlobalClass,
|
||||
public IGameHelpers
|
||||
@@ -96,6 +115,7 @@ public:
|
||||
public:
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModAllInitialized_Post();
|
||||
/*void OnSourceModAllShutdown();*/
|
||||
public: //IGameHelpers
|
||||
SendProp *FindInSendTable(const char *classname, const char *offset);
|
||||
@@ -103,9 +123,11 @@ public: //IGameHelpers
|
||||
datamap_t *GetDataMap(CBaseEntity *pEntity);
|
||||
ServerClass *FindServerClass(const char *classname);
|
||||
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
|
||||
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested);
|
||||
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
||||
bool TextMsg(int client, int dest, const char *msg);
|
||||
bool HintTextMsg(int client, const char *msg);
|
||||
bool HintTextMsg(cell_t *players, int count, const char *msg);
|
||||
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
||||
bool IsLANServer();
|
||||
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||
@@ -115,6 +137,19 @@ public: //IGameHelpers
|
||||
void SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt);
|
||||
const char *GetCurrentMap();
|
||||
void ServerCommand(const char *buffer);
|
||||
CBaseEntity *ReferenceToEntity(cell_t entRef);
|
||||
cell_t EntityToReference(CBaseEntity *pEntity);
|
||||
cell_t IndexToReference(int entIndex);
|
||||
int ReferenceToIndex(cell_t entRef);
|
||||
cell_t ReferenceToBCompatRef(cell_t entRef);
|
||||
CEntInfo *LookupEntity(int entIndex);
|
||||
cell_t EntityToBCompatRef(CBaseEntity *pEntity);
|
||||
void *GetGlobalEntityList();
|
||||
int GetSendPropOffset(SendProp *prop);
|
||||
ICommandLine *GetValveCommandLine();
|
||||
const char *GetEntityClassname(edict_t *pEdict);
|
||||
const char *GetEntityClassname(CBaseEntity *pEntity);
|
||||
bool IsMapValid(const char *map);
|
||||
public:
|
||||
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
||||
void ProcessFakeCliCmdQueue();
|
||||
@@ -125,11 +160,14 @@ public:
|
||||
const char *CurrentCommandName();
|
||||
void AddDelayedKick(int client, int userid, const char *msg);
|
||||
void ProcessDelayedKicks();
|
||||
#if !defined METAMOD_PLAPI_VERSION
|
||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||
bool IsOriginalEngine();
|
||||
#endif
|
||||
private:
|
||||
DataTableInfo *_FindServerClass(const char *classname);
|
||||
private:
|
||||
void InitLogicalEntData();
|
||||
void InitCommandLine();
|
||||
private:
|
||||
Trie *m_pClasses;
|
||||
List<DataTableInfo *> m_Tables;
|
||||
@@ -142,10 +180,11 @@ private:
|
||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||
CStack<CachedCommandInfo> m_CommandStack;
|
||||
Queue<DelayedKickInfo> m_DelayedKicks;
|
||||
void *m_pGetCommandLine;
|
||||
};
|
||||
|
||||
extern CHalfLife2 g_HL2;
|
||||
|
||||
edict_t *GetEntity(cell_t num, CBaseEntity **pData);
|
||||
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
||||
|
||||
+91
-41
@@ -579,6 +579,7 @@ HandleError HandleSystem::CloneHandle(QHandle *pHandle, unsigned int index, Hand
|
||||
}
|
||||
|
||||
pNewHandle->clone = index;
|
||||
pNewHandle->object = NULL;
|
||||
pHandle->refcount++;
|
||||
|
||||
*newhandle = new_handle;
|
||||
@@ -620,8 +621,53 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, Iden
|
||||
return CloneHandle(pHandle, index, newhandle, newOwner);
|
||||
}
|
||||
|
||||
Handle_t HandleSystem::FastCloneHandle(QHandle *pHandle, unsigned int index)
|
||||
{
|
||||
if (pHandle->clone)
|
||||
return FastCloneHandle(&m_Handles[pHandle->clone], pHandle->clone);
|
||||
|
||||
Handle_t hndl;
|
||||
if (CloneHandle(pHandle, index, &hndl, g_pCoreIdent) != HandleError_None)
|
||||
return BAD_HANDLE;
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
Handle_t HandleSystem::FastCloneHandle(Handle_t hndl)
|
||||
{
|
||||
QHandle *pHandle;
|
||||
unsigned int index;
|
||||
|
||||
GetHandleUnchecked(hndl, pHandle, index);
|
||||
|
||||
return FastCloneHandle(pHandle, index);
|
||||
}
|
||||
|
||||
void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
unsigned int serial = (hndl >> 16);
|
||||
#endif
|
||||
index = (hndl & HANDLESYS_HANDLE_MASK);
|
||||
|
||||
assert(index != 0 && index <= m_HandleTail && index < HANDLESYS_MAX_HANDLES);
|
||||
|
||||
pHandle = &m_Handles[index];
|
||||
|
||||
assert(pHandle->set && pHandle->set != HandleSet_Freed);
|
||||
assert(pHandle->serial == serial);
|
||||
}
|
||||
|
||||
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
||||
{
|
||||
if (pHandle->is_destroying)
|
||||
{
|
||||
/* Someone tried to free this recursively.
|
||||
* We'll just ignore this safely.
|
||||
*/
|
||||
return HandleError_None;
|
||||
}
|
||||
|
||||
QHandleType *pType = &m_Types[pHandle->type];
|
||||
|
||||
if (pHandle->clone)
|
||||
@@ -636,6 +682,7 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
||||
pMaster = &m_Handles[master];
|
||||
|
||||
/* Release the clone now */
|
||||
pHandle->is_destroying = true;
|
||||
ReleasePrimHandle(index);
|
||||
|
||||
/* Decrement the master's reference count */
|
||||
@@ -644,20 +691,27 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
||||
/* Type should be the same but do this anyway... */
|
||||
pType = &m_Types[pMaster->type];
|
||||
pMaster->is_destroying = true;
|
||||
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
||||
if (pMaster->object)
|
||||
{
|
||||
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
||||
}
|
||||
ReleasePrimHandle(master);
|
||||
}
|
||||
} else if (pHandle->set == HandleSet_Identity) {
|
||||
/* If we're an identity, skip all this stuff!
|
||||
* NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
|
||||
*/
|
||||
pHandle->is_destroying = true;
|
||||
ReleasePrimHandle(index);
|
||||
} else {
|
||||
/* Decrement, free if necessary */
|
||||
if (--pHandle->refcount == 0)
|
||||
{
|
||||
pHandle->is_destroying = true;
|
||||
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
||||
if (pHandle->object)
|
||||
{
|
||||
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
||||
}
|
||||
ReleasePrimHandle(index);
|
||||
} else {
|
||||
/* We must be cloned, so mark ourselves as freed */
|
||||
@@ -690,14 +744,6 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSec
|
||||
return HandleError_Access;
|
||||
}
|
||||
|
||||
if (pHandle->is_destroying)
|
||||
{
|
||||
/* Someone tried to free this recursively.
|
||||
* We'll just ignore this safely.
|
||||
*/
|
||||
return HandleError_None;
|
||||
}
|
||||
|
||||
return FreeHandle(pHandle, index);
|
||||
}
|
||||
|
||||
@@ -756,6 +802,9 @@ void HandleSystem::UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index)
|
||||
assert(pHandle->owner == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
pHandle->owner = NULL;
|
||||
|
||||
/* Note that since 0 is an invalid handle, if any of these links are 0,
|
||||
* the data can still be set.
|
||||
*/
|
||||
@@ -880,29 +929,9 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pHandle->clone)
|
||||
{
|
||||
/* Get parent */
|
||||
QHandle *pOther = &m_Handles[pHandle->clone];
|
||||
if (--pOther->refcount == 0)
|
||||
{
|
||||
/* Free! */
|
||||
dispatch->OnHandleDestroy(type, pOther->object);
|
||||
ReleasePrimHandle(pHandle->clone);
|
||||
}
|
||||
/* Unlink ourselves since we don't have a reference count */
|
||||
ReleasePrimHandle(i);
|
||||
} else {
|
||||
/* If it's not a clone, we still have to check the reference count.
|
||||
* Either way, we'll be destroyed eventually because the handle types do not change.
|
||||
*/
|
||||
if (--pHandle->refcount == 0)
|
||||
{
|
||||
/* Free! */
|
||||
dispatch->OnHandleDestroy(type, pHandle->object);
|
||||
ReleasePrimHandle(i);
|
||||
}
|
||||
}
|
||||
|
||||
FreeHandle(pHandle, i);
|
||||
|
||||
if (pType->opened == 0)
|
||||
{
|
||||
break;
|
||||
@@ -950,14 +979,17 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
|
||||
return true;
|
||||
}
|
||||
|
||||
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
||||
g_Logger.LogFatal(message, ##__VA_ARGS__); \
|
||||
g_Logger.LogError(message, ##__VA_ARGS__);
|
||||
|
||||
bool HandleSystem::TryAndFreeSomeHandles()
|
||||
{
|
||||
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
|
||||
IPlugin *highest_owner = NULL;
|
||||
unsigned int highest_handle_count = 0;
|
||||
|
||||
/* Search all plugins */
|
||||
while (pl_iter->MorePlugins())
|
||||
for (IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator(); pl_iter->MorePlugins(); pl_iter->NextPlugin())
|
||||
{
|
||||
IPlugin *plugin = pl_iter->GetPlugin();
|
||||
IdentityToken_t *identity = plugin->GetIdentity();
|
||||
@@ -986,8 +1018,6 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
||||
highest_owner = plugin;
|
||||
highest_handle_count = handle_count;
|
||||
}
|
||||
|
||||
pl_iter->NextPlugin();
|
||||
}
|
||||
|
||||
if (highest_owner == NULL || highest_handle_count == 0)
|
||||
@@ -995,9 +1025,9 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
||||
return false;
|
||||
}
|
||||
|
||||
g_Logger.LogFatal("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
|
||||
g_Logger.LogFatal("[SM] Unloading plugin to free %d handles.", highest_handle_count);
|
||||
g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
||||
HANDLE_LOG_VERY_BAD("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
|
||||
HANDLE_LOG_VERY_BAD("[SM] Unloading plugin to free %d handles.", highest_handle_count);
|
||||
HANDLE_LOG_VERY_BAD("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
||||
|
||||
highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
|
||||
|
||||
@@ -1054,12 +1084,32 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
|
||||
const char *type = "ANON";
|
||||
QHandleType *pType = &m_Types[m_Handles[i].type];
|
||||
unsigned int size = 0;
|
||||
unsigned int parentIdx;
|
||||
bool bresult;
|
||||
if (pType->nameIdx != -1)
|
||||
{
|
||||
type = m_strtab->GetString(pType->nameIdx);
|
||||
}
|
||||
|
||||
if ((parentIdx = m_Handles[i].clone) != 0)
|
||||
{
|
||||
if (m_Handles[parentIdx].refcount > 0)
|
||||
{
|
||||
size = 0;
|
||||
bresult = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[parentIdx].type, m_Handles[parentIdx].object, &size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size);
|
||||
}
|
||||
|
||||
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|
||||
|| !pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size))
|
||||
|| !bresult)
|
||||
{
|
||||
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
|
||||
}
|
||||
|
||||
@@ -160,6 +160,9 @@ public: //IHandleSystem
|
||||
HandleError *err);
|
||||
|
||||
void Dump(HANDLE_REPORTER rep);
|
||||
|
||||
/* Bypasses security checks. */
|
||||
Handle_t FastCloneHandle(Handle_t hndl);
|
||||
protected:
|
||||
/**
|
||||
* Decodes a handle with sanity and security checking.
|
||||
@@ -170,6 +173,9 @@ protected:
|
||||
unsigned int *index,
|
||||
bool ignoreFree=false);
|
||||
|
||||
Handle_t FastCloneHandle(QHandle *pHandle, unsigned int index);
|
||||
void GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index);
|
||||
|
||||
/**
|
||||
* Creates a basic handle and sets its reference count to 1.
|
||||
* Does not do any type or security checking.
|
||||
@@ -222,4 +228,27 @@ private:
|
||||
|
||||
extern HandleSystem g_HandleSys;
|
||||
|
||||
struct AutoHandleRooter
|
||||
{
|
||||
public:
|
||||
AutoHandleRooter(Handle_t hndl)
|
||||
{
|
||||
if (hndl != BAD_HANDLE)
|
||||
this->hndl = g_HandleSys.FastCloneHandle(hndl);
|
||||
else
|
||||
this->hndl = BAD_HANDLE;
|
||||
}
|
||||
|
||||
~AutoHandleRooter()
|
||||
{
|
||||
if (hndl != BAD_HANDLE)
|
||||
{
|
||||
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
|
||||
g_HandleSys.FreeHandle(hndl, &sec);
|
||||
}
|
||||
}
|
||||
private:
|
||||
Handle_t hndl;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||
|
||||
+2
-2
@@ -241,7 +241,7 @@ bool LibrarySystem::IsPathDirectory(const char *path)
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
#elif defined PLATFORM_POSIX
|
||||
struct stat s;
|
||||
|
||||
if (stat(path, &s) != 0)
|
||||
@@ -410,7 +410,7 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
|
||||
size_t length = strlen(path);
|
||||
|
||||
for (size_t i = length - 1;
|
||||
i >= 0 && i <= length - 1;
|
||||
i <= length - 1;
|
||||
i--)
|
||||
{
|
||||
if (path[i] == '/'
|
||||
|
||||
+20
-9
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "Logger.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "TimerSys.h"
|
||||
#include "sm_version.h"
|
||||
#include <sourcemod_version.h>
|
||||
|
||||
Logger g_Logger;
|
||||
|
||||
@@ -149,7 +149,7 @@ void Logger::_NewMapFile()
|
||||
} else {
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SVN_FULL_VERSION);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SM_VERSION_STRING);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
@@ -265,6 +265,8 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||
return;
|
||||
}
|
||||
|
||||
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
|
||||
|
||||
char buffer[3072];
|
||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
@@ -275,7 +277,11 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
||||
|
||||
if (!sv_logecho || sv_logecho->GetBool())
|
||||
{
|
||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
@@ -356,7 +362,7 @@ void Logger::LogMessage(const char *vafmt, ...)
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SVN_FULL_VERSION);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SM_VERSION_STRING);
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
@@ -378,6 +384,14 @@ print_error:
|
||||
}
|
||||
|
||||
void Logger::LogError(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogErrorEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
@@ -408,10 +422,7 @@ void Logger::LogError(const char *vafmt, ...)
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
va_end(ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
void DisableLogging();
|
||||
void LogMessage(const char *msg, ...);
|
||||
void LogError(const char *msg, ...);
|
||||
void LogErrorEx(const char *msg, va_list ap);
|
||||
void LogFatal(const char *msg, ...);
|
||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
||||
|
||||
+107
-42
@@ -2,31 +2,33 @@
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
SMSDK = ..
|
||||
SRCDS_BASE = ~/srcds
|
||||
HL2SDK_ORIG = ../../hl2sdk
|
||||
HL2SDK_OB = ../../hl2sdk-ob
|
||||
HL2SDK_CSS = ../../hl2sdk-css
|
||||
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve
|
||||
HL2SDK_L4D = ../../hl2sdk-l4d
|
||||
MMSOURCE17 = ../../mmsource-1.7
|
||||
HL2SDK_L4D2 = ../../hl2sdk-l4d2
|
||||
HL2SDK_CSGO = ../../hl2sdk-csgo
|
||||
MMSOURCE = ../../mmsource-central
|
||||
|
||||
#####################################
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
#####################################
|
||||
|
||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
||||
Database.cpp DebugReporter.cpp EventManager.cpp HalfLife2.cpp Logger.cpp \
|
||||
PlayerManager.cpp TimerSys.cpp UserMessages.cpp \
|
||||
sm_autonatives.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
|
||||
frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp PhraseCollection.cpp NextMap.cpp \
|
||||
NativeOwner.cpp
|
||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp smn_maplists.cpp \
|
||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp \
|
||||
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
|
||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp \
|
||||
frame_hooks.cpp concmd_cleaner.cpp NextMap.cpp \
|
||||
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp
|
||||
OBJECTS += smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
||||
smn_database.cpp smn_entities.cpp smn_events.cpp \
|
||||
smn_fakenatives.cpp smn_filesystem.cpp smn_halflife.cpp \
|
||||
smn_keyvalues.cpp smn_player.cpp \
|
||||
smn_usermsgs.cpp smn_menus.cpp smn_vector.cpp \
|
||||
smn_hudtext.cpp smn_nextmap.cpp
|
||||
OBJECTS += ExtensionSys.cpp \
|
||||
ForwardSys.cpp \
|
||||
HandleSys.cpp \
|
||||
@@ -35,7 +37,6 @@ OBJECTS += ExtensionSys.cpp \
|
||||
PluginSys.cpp \
|
||||
ShareSys.cpp \
|
||||
NativeInvoker.cpp
|
||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
||||
|
||||
##############################################
|
||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||
@@ -48,53 +49,119 @@ CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
|
||||
CPP = gcc
|
||||
|
||||
override ENGSET = false
|
||||
|
||||
ifneq (,$(filter original orangebox css orangeboxvalve left4dead left4dead2 csgo,$(ENGINE)))
|
||||
override ENGSET = true
|
||||
endif
|
||||
|
||||
ifeq "$(ENGINE)" "original"
|
||||
HL2SDK = $(HL2SDK_ORIG)
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/linux_sdk
|
||||
CFLAGS += -DSOURCE_ENGINE=1
|
||||
METAMOD = $(MMSOURCE17)/core-legacy
|
||||
METAMOD = $(MMSOURCE)/core-legacy
|
||||
INCLUDE += -I$(HL2SDK)/public/dlls
|
||||
SRCDS = $(SRCDS_BASE)
|
||||
BINARY = sourcemod.1.ep1.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "orangebox"
|
||||
HL2SDK = $(HL2SDK_OB)
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=3
|
||||
METAMOD = $(MMSOURCE17)/core
|
||||
METAMOD = $(MMSOURCE)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
SRCDS = $(SRCDS_BASE)/orangebox
|
||||
BINARY = sourcemod.2.ep2.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "css"
|
||||
HL2SDK = $(HL2SDK_CSS)
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=6
|
||||
METAMOD = $(MMSOURCE)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
BINARY = sourcemod.2.css.so
|
||||
endif
|
||||
ifeq "$(ENGINE)" "orangeboxvalve"
|
||||
HL2SDK = $(HL2SDK_OB_VALVE)
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=7
|
||||
METAMOD = $(MMSOURCE)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
BINARY = sourcemod.2.ep2v.so
|
||||
endif
|
||||
ifeq "$(ENGINE)" "left4dead"
|
||||
HL2SDK = $(HL2SDK_L4D)
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=4
|
||||
METAMOD = $(MMSOURCE17)/core
|
||||
CFLAGS += -DSOURCE_ENGINE=8
|
||||
METAMOD = $(MMSOURCE)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
SRCDS = $(SRCDS_BASE)/l4d
|
||||
BINARY = sourcemod.2.l4d.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "left4dead2"
|
||||
HL2SDK = $(HL2SDK_L4D2)
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=9
|
||||
METAMOD = $(MMSOURCE)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
BINARY = sourcemod.2.l4d2.so
|
||||
endif
|
||||
ifeq "$(ENGINE)" "csgo"
|
||||
HL2SDK = $(HL2SDK_CSGO)
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=12
|
||||
METAMOD = $(MMSOURCE)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
BINARY = sourcemod.2.csgo.so
|
||||
endif
|
||||
|
||||
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_LEFT4DEAD=4
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
|
||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so \
|
||||
tier0_i486.so -lpthread -static-libgcc
|
||||
OS := $(shell uname -s)
|
||||
|
||||
ifeq "$(OS)" "Darwin"
|
||||
LIB_EXT = dylib
|
||||
HL2LIB = $(HL2SDK)/lib/mac
|
||||
else
|
||||
LIB_EXT = so
|
||||
ifeq "$(ENGINE)" "original"
|
||||
HL2LIB = $(HL2SDK)/linux_sdk
|
||||
else
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter original orangebox left4dead,$(ENGINE)))
|
||||
LIB_SUFFIX = _i486.$(LIB_EXT)
|
||||
else
|
||||
LIB_PREFIX = lib
|
||||
ifneq (,$(filter orangeboxvalve css,$(ENGINE)))
|
||||
ifneq "$(OS)" "Darwin"
|
||||
LIB_SUFFIX = _srv.$(LIB_EXT)
|
||||
else
|
||||
LIB_SUFFIX = .$(LIB_EXT)
|
||||
endif
|
||||
else
|
||||
LIB_SUFFIX = .$(LIB_EXT)
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \
|
||||
-DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \
|
||||
-DSE_PORTAL2=11 -DSE_CSGO=12
|
||||
|
||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) \
|
||||
$(LIB_PREFIX)tier0$(LIB_SUFFIX) -static-libgcc
|
||||
|
||||
ifeq "$(ENGINE)" "csgo"
|
||||
LINK += $(HL2LIB)/interfaces_i486.a
|
||||
endif
|
||||
|
||||
INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \
|
||||
-I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \
|
||||
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
|
||||
|
||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
||||
CFLAGS += -D_LINUX -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
|
||||
-Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32
|
||||
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
||||
-Wno-uninitialized -Wno-unused -Wno-switch -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H \
|
||||
-DSM_DEFAULT_THREADER -m32 -DCOMPILER_GCC
|
||||
CPPFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -fno-threadsafe-statics -fno-exceptions -fno-rtti
|
||||
|
||||
################################################
|
||||
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
||||
@@ -124,15 +191,15 @@ $(BIN_DIR)/%.o: %.c
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all: check
|
||||
mkdir -p $(BIN_DIR)/systems
|
||||
mkdir -p $(BIN_DIR)/thread
|
||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
|
||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
|
||||
mkdir -p $(BIN_DIR)
|
||||
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX)
|
||||
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX)
|
||||
$(MAKE) -f Makefile sourcemod
|
||||
|
||||
check:
|
||||
if [ "$(ENGSET)" = "false" ]; then \
|
||||
echo "You must supply ENGINE=left4dead or ENGINE=orangebox or ENGINE=original"; \
|
||||
echo "You must supply one of the following values for ENGINE:"; \
|
||||
echo "csgo, left4dead2, left4dead, orangeboxvalve, css, orangebox, or original"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@@ -146,6 +213,4 @@ default: all
|
||||
|
||||
clean: check
|
||||
rm -rf $(BIN_DIR)/*.o
|
||||
rm -rf $(BIN_DIR)/systems/*.o
|
||||
rm -rf $(BIN_DIR)/thread/*.o
|
||||
rm -rf $(BIN_DIR)/$(BINARY)
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "MemoryUtils.h"
|
||||
#include "ShareSys.h"
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <string.h>
|
||||
#include <elf.h>
|
||||
#endif
|
||||
|
||||
MemoryUtils g_MemUtils;
|
||||
|
||||
#if 0
|
||||
MemoryUtils::MemoryUtils()
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
|
||||
m_PageSize = info.dwPageSize;
|
||||
|
||||
#elif defined PLATFORM_POSIX
|
||||
|
||||
m_PageSize = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void MemoryUtils::OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
|
||||
{
|
||||
DynLibInfo lib;
|
||||
bool found;
|
||||
char *ptr, *end;
|
||||
|
||||
memset(&lib, 0, sizeof(DynLibInfo));
|
||||
|
||||
if (!GetLibraryInfo(libPtr, lib))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = reinterpret_cast<char *>(lib.baseAddress);
|
||||
end = ptr + lib.memorySize;
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
found = true;
|
||||
for (register size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return ptr;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
{
|
||||
unsigned long baseAddr;
|
||||
|
||||
if (libPtr == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *pe;
|
||||
IMAGE_FILE_HEADER *file;
|
||||
IMAGE_OPTIONAL_HEADER *opt;
|
||||
|
||||
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
baseAddr = reinterpret_cast<unsigned long>(info.AllocationBase);
|
||||
|
||||
/* All this is for our insane sanity checks :o */
|
||||
dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr);
|
||||
pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew);
|
||||
file = &pe->FileHeader;
|
||||
opt = &pe->OptionalHeader;
|
||||
|
||||
/* Check PE magic and signature */
|
||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library */
|
||||
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Finally, we can do this */
|
||||
lib.memorySize = opt->SizeOfImage;
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
Dl_info info;
|
||||
Elf32_Ehdr *file;
|
||||
Elf32_Phdr *phdr;
|
||||
uint16_t phdrCount;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info.dli_fbase || !info.dli_fname)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = reinterpret_cast<unsigned long>(info.dli_fbase);
|
||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
||||
|
||||
/* Check ELF magic */
|
||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF version */
|
||||
if (file->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library/shared object */
|
||||
if (file->e_type != ET_DYN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
phdrCount = file->e_phnum;
|
||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
||||
|
||||
/* Add up the memory sizes of segments marked as PT_LOAD as those are the only ones that should be in memory */
|
||||
for (uint16_t i = 0; i < phdrCount; i++)
|
||||
{
|
||||
Elf32_Phdr &hdr = phdr[i];
|
||||
|
||||
if (hdr.p_type == PT_LOAD)
|
||||
{
|
||||
lib.memorySize += hdr.p_memsz;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
|
||||
|
||||
return true;
|
||||
}
|
||||
+32
-6
@@ -41,7 +41,7 @@
|
||||
#include "ShareSys.h"
|
||||
#include "HandleSys.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "Translator.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
MenuManager g_Menus;
|
||||
VoteMenuHandler s_VoteHandler;
|
||||
@@ -231,6 +231,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
||||
unsigned int pgn = menu->GetPagination();
|
||||
unsigned int maxItems = style->GetMaxPageItems();
|
||||
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
|
||||
bool novoteButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_NOVOTE) == MENUFLAG_BUTTON_NOVOTE;
|
||||
|
||||
if (pgn != MENU_NO_PAGINATION)
|
||||
{
|
||||
@@ -241,6 +242,11 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
||||
maxItems--;
|
||||
}
|
||||
|
||||
if (novoteButton)
|
||||
{
|
||||
maxItems--;
|
||||
}
|
||||
|
||||
/* This is very not allowed! */
|
||||
if (maxItems < 2)
|
||||
{
|
||||
@@ -436,6 +442,20 @@ skip_search:
|
||||
/* Draw the item according to the order */
|
||||
menu_slots_t *slots = md.slots;
|
||||
unsigned int position = 0; /* Keep track of the last position */
|
||||
|
||||
if (novoteButton)
|
||||
{
|
||||
char text[50];
|
||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
|
||||
{
|
||||
UTIL_Format(text, sizeof(text), "No Vote");
|
||||
}
|
||||
ItemDrawInfo dr(text, 0);
|
||||
position = panel->DrawItem(dr);
|
||||
slots[position].type = ItemSel_Exit;
|
||||
position++;
|
||||
}
|
||||
|
||||
if (order == ItemOrder_Ascending)
|
||||
{
|
||||
md.item_on_page = drawItems[0].position;
|
||||
@@ -586,7 +606,7 @@ skip_search:
|
||||
{
|
||||
if (exitBackButton)
|
||||
{
|
||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
||||
{
|
||||
UTIL_Format(text, sizeof(text), "Back");
|
||||
}
|
||||
@@ -596,7 +616,7 @@ skip_search:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
||||
{
|
||||
UTIL_Format(text, sizeof(text), "Previous");
|
||||
}
|
||||
@@ -617,7 +637,7 @@ skip_search:
|
||||
/* NEXT */
|
||||
if (displayNext || canDrawDisabled)
|
||||
{
|
||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
||||
{
|
||||
UTIL_Format(text, sizeof(text), "Next");
|
||||
}
|
||||
@@ -648,7 +668,7 @@ skip_search:
|
||||
/* EXIT */
|
||||
if (exitButton)
|
||||
{
|
||||
if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
||||
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
||||
{
|
||||
UTIL_Format(text, sizeof(text), "Exit");
|
||||
}
|
||||
@@ -798,5 +818,11 @@ bool MenuManager::IsClientInVotePool(int client)
|
||||
|
||||
bool MenuManager::RedrawClientVoteMenu(int client)
|
||||
{
|
||||
return s_VoteHandler.RedrawToClient(client);
|
||||
return RedrawClientVoteMenu2(client, true);
|
||||
}
|
||||
|
||||
bool MenuManager::RedrawClientVoteMenu2(int client, bool revote)
|
||||
{
|
||||
return s_VoteHandler.RedrawToClient(client, revote);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
unsigned int GetRemainingVoteDelay();
|
||||
bool IsClientInVotePool(int client);
|
||||
bool RedrawClientVoteMenu(int client);
|
||||
bool RedrawClientVoteMenu2(int client, bool revote);
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
||||
|
||||
+13
-1
@@ -322,15 +322,24 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
||||
if (pCollideable)
|
||||
{
|
||||
const Vector & pos = pCollideable->GetCollisionOrigin();
|
||||
|
||||
enginesound->EmitSound(filter,
|
||||
client,
|
||||
CHAN_AUTO,
|
||||
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||
sound,
|
||||
-1,
|
||||
#endif
|
||||
sound,
|
||||
VOL_NORM,
|
||||
ATTN_NORM,
|
||||
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
PITCH_NORM,
|
||||
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2
|
||||
0,
|
||||
#endif
|
||||
&pos);
|
||||
}
|
||||
}
|
||||
@@ -377,6 +386,9 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
||||
RemoveClientFromWatch(client);
|
||||
}
|
||||
|
||||
Handle_t hndl = menu ? menu->GetHandle() : BAD_HANDLE;
|
||||
AutoHandleRooter ahr(hndl);
|
||||
|
||||
if (cancel)
|
||||
{
|
||||
mh->OnMenuCancel(menu, client, reason);
|
||||
|
||||
@@ -32,11 +32,20 @@
|
||||
#include "MenuStyle_Radio.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "UserMessages.h"
|
||||
#include "GameConfigs.h"
|
||||
#include <IGameConfigs.h>
|
||||
#include "PlayerManager.h"
|
||||
#if defined MENU_DEBUG
|
||||
#include "Logger.h"
|
||||
#endif
|
||||
#include "logic_bridge.h"
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
extern const char *g_RadioNumTable[];
|
||||
CRadioStyle g_RadioMenuStyle;
|
||||
@@ -44,6 +53,14 @@ int g_ShowMenuId = -1;
|
||||
bool g_bRadioInit = false;
|
||||
unsigned int g_RadioMenuTimeout = 0;
|
||||
|
||||
// back, next, exit
|
||||
#define MAX_PAGINATION_OPTIONS 3
|
||||
|
||||
#define MAX_MENUSLOT_KEYS 10
|
||||
|
||||
static unsigned int s_RadioMaxPageItems = MAX_MENUSLOT_KEYS;
|
||||
|
||||
|
||||
CRadioStyle::CRadioStyle()
|
||||
{
|
||||
m_players = new CRadioMenuPlayer[256+1];
|
||||
@@ -89,6 +106,18 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
||||
g_RadioMenuTimeout = 0;
|
||||
}
|
||||
|
||||
const char *items = g_pGameConf->GetKeyValue("RadioMenuMaxPageItems");
|
||||
if (items != NULL)
|
||||
{
|
||||
int value = atoi(items);
|
||||
|
||||
// Only override the mostly-safe default if it's a sane value
|
||||
if (value > MAX_PAGINATION_OPTIONS && value <= MAX_MENUSLOT_KEYS)
|
||||
{
|
||||
s_RadioMaxPageItems = value;
|
||||
}
|
||||
}
|
||||
|
||||
g_Menus.AddStyle(this);
|
||||
g_Menus.SetDefaultStyle(this);
|
||||
|
||||
@@ -134,13 +163,22 @@ static unsigned int g_last_holdtime = 0;
|
||||
static unsigned int g_last_client_count = 0;
|
||||
static int g_last_clients[256];
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
|
||||
#else
|
||||
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||
#endif
|
||||
{
|
||||
int count = pFilter->GetRecipientCount();
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
||||
#else
|
||||
bf_read br(bf->GetBasePointer(), 3);
|
||||
|
||||
br.ReadWord();
|
||||
int c = br.ReadChar();
|
||||
#endif
|
||||
|
||||
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
||||
|
||||
@@ -188,7 +226,7 @@ IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwn
|
||||
|
||||
unsigned int CRadioStyle::GetMaxPageItems()
|
||||
{
|
||||
return 10;
|
||||
return s_RadioMaxPageItems;
|
||||
}
|
||||
|
||||
const char *CRadioStyle::GetStyleName()
|
||||
@@ -306,7 +344,7 @@ unsigned int CRadioDisplay::GetCurrentKey()
|
||||
|
||||
bool CRadioDisplay::SetCurrentKey(unsigned int key)
|
||||
{
|
||||
if (key < m_NextPos || m_NextPos > 10)
|
||||
if (key < m_NextPos || m_NextPos > s_RadioMaxPageItems)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -342,7 +380,7 @@ void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
|
||||
|
||||
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
|
||||
{
|
||||
if (m_NextPos > 10 || !CanDrawItem(item.style))
|
||||
if (m_NextPos > s_RadioMaxPageItems || !CanDrawItem(item.style))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -451,6 +489,15 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
||||
}
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
// If or when we need to support multiple games per engine with this, we can switch to reflection
|
||||
// TODO: find what happens past 240 on CS:GO
|
||||
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
msg->set_bits_valid_slots(display_keys);
|
||||
msg->set_display_time(time);
|
||||
msg->set_menu_string(ptr);
|
||||
g_UserMsgs.EndMessage();
|
||||
#else
|
||||
while (true)
|
||||
{
|
||||
if (len > 240)
|
||||
@@ -458,7 +505,8 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
save = ptr[240];
|
||||
ptr[240] = '\0';
|
||||
}
|
||||
bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
|
||||
bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
buffer->WriteWord(display_keys);
|
||||
buffer->WriteChar(time ? time : -1);
|
||||
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
||||
@@ -475,6 +523,7 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
display_last_refresh = gpGlobals->curtime;
|
||||
}
|
||||
@@ -510,6 +559,7 @@ unsigned int CRadioDisplay::GetApproxMemUsage()
|
||||
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
||||
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
|
||||
{
|
||||
m_Pagination = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
|
||||
}
|
||||
|
||||
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
||||
@@ -550,6 +600,17 @@ bool CRadioMenu::DisplayAtItem(int client,
|
||||
time);
|
||||
}
|
||||
|
||||
bool CRadioMenu::SetPagination(unsigned int itemsPerPage)
|
||||
{
|
||||
const unsigned int maxPerPage = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
|
||||
if (itemsPerPage > maxPerPage)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CBaseMenu::SetPagination(itemsPerPage);
|
||||
}
|
||||
|
||||
void CRadioMenu::Cancel_Finally()
|
||||
{
|
||||
g_RadioMenuStyle.CancelMenu(this);
|
||||
|
||||
+11
-2
@@ -37,7 +37,7 @@
|
||||
#include "MenuStyle_Base.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <IUserMessages.h>
|
||||
#include "UserMessages.h"
|
||||
#include "sm_fastlink.h"
|
||||
#include <sh_stack.h>
|
||||
#include <compat_wrappers.h>
|
||||
@@ -65,7 +65,11 @@ private:
|
||||
class CRadioStyle :
|
||||
public BaseMenuStyle,
|
||||
public SMGlobalClass,
|
||||
public IUserMessageListener
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
public IProtobufUserMessageListener
|
||||
#else
|
||||
public IBitBufUserMessageListener
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
CRadioStyle();
|
||||
@@ -84,7 +88,11 @@ public: //IMenuStyle
|
||||
unsigned int GetMaxPageItems();
|
||||
unsigned int GetApproxMemUsage();
|
||||
public: //IUserMessageListener
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
void OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter);
|
||||
#else
|
||||
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
||||
#endif
|
||||
void OnUserMessageSent(int msg_id);
|
||||
public:
|
||||
bool IsSupported();
|
||||
@@ -142,6 +150,7 @@ public:
|
||||
unsigned int time,
|
||||
unsigned int start_item,
|
||||
IMenuHandler *alt_handler/* =NULL */);
|
||||
bool SetPagination(unsigned int itemsPerPage);
|
||||
void Cancel_Finally();
|
||||
unsigned int GetApproxMemUsage();
|
||||
};
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "MenuStyle_Valve.h"
|
||||
#include "Translator.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "ConCmdManager.h"
|
||||
|
||||
|
||||
+220
-10
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -34,9 +34,56 @@
|
||||
#include "MenuVoting.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include <sourcemod.h>
|
||||
#include <Logger.h>
|
||||
#include <HalfLife2.h>
|
||||
#include <mathlib.h>
|
||||
#include <const.h>
|
||||
#include <ITranslator.h>
|
||||
#include "logic_bridge.h"
|
||||
|
||||
float g_next_vote = 0.0f;
|
||||
|
||||
#define VOTE_NOT_VOTING -2
|
||||
#define VOTE_PENDING -1
|
||||
|
||||
ConVar sm_vote_hintbox("sm_vote_progress_hintbox",
|
||||
"0",
|
||||
0,
|
||||
"Show current vote progress in a hint box",
|
||||
true,
|
||||
0.0,
|
||||
true,
|
||||
1.0);
|
||||
|
||||
ConVar sm_vote_chat("sm_vote_progress_chat",
|
||||
"0",
|
||||
0,
|
||||
"Show current vote progress as chat messages",
|
||||
true,
|
||||
0.0,
|
||||
true,
|
||||
1.0);
|
||||
|
||||
ConVar sm_vote_console("sm_vote_progress_console",
|
||||
"0",
|
||||
0,
|
||||
"Show current vote progress as console messages",
|
||||
true,
|
||||
0.0,
|
||||
true,
|
||||
1.0);
|
||||
|
||||
ConVar sm_vote_client_console("sm_vote_progress_client_console",
|
||||
"0",
|
||||
0,
|
||||
"Show current vote progress as console messages to clients",
|
||||
true,
|
||||
0.0,
|
||||
true,
|
||||
1.0);
|
||||
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
|
||||
#else
|
||||
@@ -117,7 +164,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
||||
* newly connected client is not allowed to vote.
|
||||
*/
|
||||
int item;
|
||||
if ((item = m_ClientVotes[client]) >= -1)
|
||||
if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
|
||||
{
|
||||
if (item >= 0)
|
||||
{
|
||||
@@ -125,7 +172,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
||||
assert(m_Votes[item] > 0);
|
||||
m_Votes[item]--;
|
||||
}
|
||||
m_ClientVotes[client] = -2;
|
||||
m_ClientVotes[client] = VOTE_NOT_VOTING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,13 +236,13 @@ bool VoteMenuHandler::IsClientInVotePool(int client)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_ClientVotes[client] > -2);
|
||||
return (m_ClientVotes[client] > VOTE_NOT_VOTING);
|
||||
}
|
||||
|
||||
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
||||
{
|
||||
if (!IsClientInVotePool(client)
|
||||
|| m_ClientVotes[client] == -1)
|
||||
|| m_ClientVotes[client] == VOTE_PENDING)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -205,7 +252,7 @@ bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VoteMenuHandler::RedrawToClient(int client)
|
||||
bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
|
||||
{
|
||||
unsigned int time_limit;
|
||||
|
||||
@@ -214,6 +261,20 @@ bool VoteMenuHandler::RedrawToClient(int client)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_ClientVotes[client] >= 0)
|
||||
{
|
||||
if ((m_VoteFlags & VOTEFLAG_NO_REVOTES) == VOTEFLAG_NO_REVOTES || !revotes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert((unsigned)m_ClientVotes[client] < m_Items);
|
||||
assert(m_Votes[m_ClientVotes[client]] > 0);
|
||||
m_Votes[m_ClientVotes[client]]--;
|
||||
m_ClientVotes[client] = VOTE_PENDING;
|
||||
m_Revoting[client] = true;
|
||||
m_NumVotes--;
|
||||
}
|
||||
|
||||
if (m_nMenuTime == MENU_TIME_FOREVER)
|
||||
{
|
||||
time_limit = m_nMenuTime;
|
||||
@@ -247,7 +308,8 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
||||
/* Mark all clients as not voting */
|
||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
||||
{
|
||||
m_ClientVotes[i] = -2;
|
||||
m_ClientVotes[i] = VOTE_NOT_VOTING;
|
||||
m_Revoting[i] = false;
|
||||
}
|
||||
|
||||
m_Items = menu->GetItemCount();
|
||||
@@ -291,6 +353,8 @@ void VoteMenuHandler::StartVoting()
|
||||
|
||||
m_pHandler->OnMenuVoteStart(m_pCurMenu);
|
||||
|
||||
m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
|
||||
/* By now we know how many clients were set.
|
||||
* If there are none, we should end IMMEDIATELY.
|
||||
*/
|
||||
@@ -298,6 +362,8 @@ void VoteMenuHandler::StartVoting()
|
||||
{
|
||||
EndVoting();
|
||||
}
|
||||
|
||||
m_TotalClients = m_Clients;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::DecrementPlayerCount()
|
||||
@@ -334,6 +400,11 @@ void VoteMenuHandler::EndVoting()
|
||||
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
||||
}
|
||||
|
||||
if (m_displayTimer)
|
||||
{
|
||||
g_Timers.KillTimer(m_displayTimer);
|
||||
}
|
||||
|
||||
if (m_bCancelled)
|
||||
{
|
||||
/* If we were cancelled, don't bother tabulating anything.
|
||||
@@ -380,7 +451,7 @@ void VoteMenuHandler::EndVoting()
|
||||
/* Build the client list */
|
||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
||||
{
|
||||
if (m_ClientVotes[i] >= -1)
|
||||
if (m_ClientVotes[i] >= VOTE_PENDING)
|
||||
{
|
||||
client_vote[vote.num_clients].client = i;
|
||||
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
||||
@@ -424,7 +495,7 @@ void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason
|
||||
|
||||
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
||||
{
|
||||
m_ClientVotes[client] = -1;
|
||||
m_ClientVotes[client] = VOTE_PENDING;
|
||||
m_pHandler->OnMenuDisplay(menu, client, display);
|
||||
}
|
||||
|
||||
@@ -446,6 +517,58 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
|
||||
m_ClientVotes[client] = item;
|
||||
m_Votes[item]++;
|
||||
m_NumVotes++;
|
||||
|
||||
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool() || sm_vote_client_console.GetBool())
|
||||
{
|
||||
static char buffer[1024];
|
||||
ItemDrawInfo dr;
|
||||
menu->GetItemInfo(item, &dr);
|
||||
|
||||
if (sm_vote_console.GetBool())
|
||||
{
|
||||
int target = SOURCEMOD_SERVER_LANGUAGE;
|
||||
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
|
||||
&target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||
Engine_LogPrintWrapper(buffer);
|
||||
}
|
||||
|
||||
if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
|
||||
{
|
||||
int maxclients = g_Players.GetMaxClients();
|
||||
for (int i=1; i<=maxclients; i++)
|
||||
{
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
|
||||
assert(pPlayer);
|
||||
|
||||
if (pPlayer->IsInGame() && !pPlayer->IsFakeClient())
|
||||
{
|
||||
if (m_Revoting[client])
|
||||
{
|
||||
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote",
|
||||
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||
}
|
||||
else
|
||||
{
|
||||
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
|
||||
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||
}
|
||||
|
||||
if (sm_vote_chat.GetBool())
|
||||
{
|
||||
g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
|
||||
}
|
||||
|
||||
if (sm_vote_client_console.GetBool())
|
||||
{
|
||||
ClientConsolePrint(pPlayer->GetEdict(), buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildVoteLeaders();
|
||||
DrawHintProgress();
|
||||
}
|
||||
|
||||
m_pHandler->OnMenuSelect(menu, client, item);
|
||||
@@ -468,6 +591,9 @@ void VoteMenuHandler::InternalReset()
|
||||
m_NumVotes = 0;
|
||||
m_bCancelled = false;
|
||||
m_pHandler = NULL;
|
||||
m_leaderList[0] = '\0';
|
||||
m_displayTimer = NULL;
|
||||
m_TotalClients = 0;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::CancelVoting()
|
||||
@@ -489,3 +615,87 @@ bool VoteMenuHandler::IsCancelling()
|
||||
{
|
||||
return m_bCancelled;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::DrawHintProgress()
|
||||
{
|
||||
if (!sm_vote_hintbox.GetBool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static char buffer[1024];
|
||||
|
||||
float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
|
||||
if (timeRemaining < 0)
|
||||
{
|
||||
timeRemaining = 0.0;
|
||||
}
|
||||
|
||||
int iTimeRemaining = RoundFloatToInt(timeRemaining);
|
||||
|
||||
int maxclients = g_Players.GetMaxClients();
|
||||
for (int i=1; i<=maxclients; i++)
|
||||
{
|
||||
if (g_Players.GetPlayerByIndex(i)->IsInGame())
|
||||
{
|
||||
logicore.CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count",
|
||||
&i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
|
||||
g_HL2.HintTextMsg(i, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoteMenuHandler::BuildVoteLeaders()
|
||||
{
|
||||
if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menu_vote_result_t vote;
|
||||
menu_vote_result_t::menu_item_vote_t item_vote[256];
|
||||
|
||||
memset(&vote, 0, sizeof(vote));
|
||||
|
||||
/* Build the item list */
|
||||
for (unsigned int i=0; i<m_Items; i++)
|
||||
{
|
||||
if (m_Votes[i] > 0)
|
||||
{
|
||||
item_vote[vote.num_items].count = m_Votes[i];
|
||||
item_vote[vote.num_items].item = i;
|
||||
vote.num_votes += m_Votes[i];
|
||||
vote.num_items++;
|
||||
}
|
||||
}
|
||||
vote.item_list = item_vote;
|
||||
assert(vote.num_votes);
|
||||
|
||||
/* Sort the item list descending */
|
||||
qsort(item_vote,
|
||||
vote.num_items,
|
||||
sizeof(menu_vote_result_t::menu_item_vote_t),
|
||||
SortVoteItems);
|
||||
|
||||
/* Take the top 3 (if applicable) and draw them */
|
||||
int len = 0;
|
||||
for (unsigned int i=0; i<vote.num_items && i<3; i++)
|
||||
{
|
||||
int curItem = vote.item_list[i].item;
|
||||
ItemDrawInfo dr;
|
||||
m_pCurMenu->GetItemInfo(curItem, &dr);
|
||||
len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
|
||||
{
|
||||
DrawHintProgress();
|
||||
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
|
||||
{
|
||||
m_displayTimer = NULL;
|
||||
}
|
||||
|
||||
+14
-2
@@ -36,6 +36,7 @@
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <sh_vector.h>
|
||||
#include "sm_globals.h"
|
||||
#include <TimerSys.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
@@ -43,7 +44,8 @@ using namespace SourceMod;
|
||||
class VoteMenuHandler :
|
||||
public IMenuHandler,
|
||||
public SMGlobalClass,
|
||||
public IClientListener
|
||||
public IClientListener,
|
||||
public ITimedEvent
|
||||
{
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
@@ -61,6 +63,9 @@ public: //IMenuHandler
|
||||
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
||||
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
|
||||
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
|
||||
public: //ITimedEvent
|
||||
ResultType OnTimer(ITimer *pTimer, void *pData);
|
||||
void OnTimerEnd(ITimer *pTimer, void *pData);
|
||||
public:
|
||||
bool StartVote(IBaseMenu *menu,
|
||||
unsigned int num_clients,
|
||||
@@ -74,7 +79,7 @@ public:
|
||||
unsigned int GetRemainingVoteDelay();
|
||||
bool IsClientInVotePool(int client);
|
||||
bool GetClientVoteChoice(int client, unsigned int *pItem);
|
||||
bool RedrawToClient(int client);
|
||||
bool RedrawToClient(int client, bool revote);
|
||||
private:
|
||||
void Reset(IMenuHandler *mh);
|
||||
void DecrementPlayerCount();
|
||||
@@ -85,9 +90,12 @@ private:
|
||||
unsigned int time,
|
||||
unsigned int flags);
|
||||
void StartVoting();
|
||||
void DrawHintProgress();
|
||||
void BuildVoteLeaders();
|
||||
private:
|
||||
IMenuHandler *m_pHandler;
|
||||
unsigned int m_Clients;
|
||||
unsigned int m_TotalClients;
|
||||
unsigned int m_Items;
|
||||
CVector<unsigned int> m_Votes;
|
||||
IBaseMenu *m_pCurMenu;
|
||||
@@ -99,6 +107,10 @@ private:
|
||||
float m_fStartTime;
|
||||
unsigned int m_nMenuTime;
|
||||
int m_ClientVotes[256+1];
|
||||
bool m_Revoting[256+1];
|
||||
char m_leaderList[1024];
|
||||
ITimer *m_displayTimer;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
||||
|
||||
|
||||
+8
-3
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "NextMap.h"
|
||||
#include "Logger.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "sourcehook.h"
|
||||
@@ -49,7 +50,11 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &)
|
||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||
#else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
|
||||
@@ -105,7 +110,7 @@ const char *NextMapManager::GetNextMap()
|
||||
|
||||
bool NextMapManager::SetNextMap(const char *map)
|
||||
{
|
||||
if (!engine->IsMapValid(map))
|
||||
if (!g_HL2.IsMapValid(map))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -129,7 +134,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
||||
|
||||
const char *newmap = sm_nextmap.GetString();
|
||||
|
||||
if (newmap[0] == 0 || !engine->IsMapValid(newmap))
|
||||
if (newmap[0] == 0 || !g_HL2.IsMapValid(newmap))
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
+325
-78
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -39,22 +39,23 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "CoreConfig.h"
|
||||
#include "TimerSys.h"
|
||||
#include "Translator.h"
|
||||
#include "Logger.h"
|
||||
#include "ChatTriggers.h"
|
||||
#include "HalfLife2.h"
|
||||
#include <inetchannel.h>
|
||||
#include <iclient.h>
|
||||
#include "GameConfigs.h"
|
||||
#include <IGameConfigs.h>
|
||||
#include "ExtensionSys.h"
|
||||
#include "sm_version.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include "ConsoleDetours.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
PlayerManager g_Players;
|
||||
bool g_OnMapStarted = false;
|
||||
IForward *PreAdminCheck = NULL;
|
||||
IForward *PostAdminCheck = NULL;
|
||||
IForward *PostAdminFilter = NULL;
|
||||
IForward *OnClientConnected = NULL;
|
||||
|
||||
const unsigned int *g_NumPlayersToAuth = NULL;
|
||||
int lifestate_offset = -1;
|
||||
List<ICommandTargetProcessor *> target_processors;
|
||||
@@ -75,7 +76,11 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &)
|
||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||
#else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
|
||||
@@ -108,6 +113,11 @@ PlayerManager::PlayerManager()
|
||||
m_FirstPass = false;
|
||||
m_maxClients = 0;
|
||||
|
||||
m_SourceTVUserId = -1;
|
||||
m_ReplayUserId = -1;
|
||||
|
||||
m_bAuthstringValidation = false; // don't use steam auth by default... yet
|
||||
|
||||
m_UserIdLookUp = new int[USHRT_MAX+1];
|
||||
memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1));
|
||||
}
|
||||
@@ -137,6 +147,7 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
ParamType p2[] = {Param_Cell};
|
||||
|
||||
m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_LowEvent, 3, p1);
|
||||
m_clconnect_post = g_Forwards.CreateForward("OnClientConnected", ET_Ignore, 1, p2);
|
||||
m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
|
||||
m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
|
||||
m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
|
||||
@@ -145,7 +156,6 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
|
||||
m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
|
||||
m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
|
||||
OnClientConnected = g_Forwards.CreateForward("OnClientConnected", ET_Ignore, 1, p2);
|
||||
|
||||
PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
|
||||
PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
|
||||
@@ -154,8 +164,6 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
m_bIsListenServer = !engine->IsDedicatedServer();
|
||||
m_ListenClient = 0;
|
||||
|
||||
g_ConVarManager.AddConVarChangeListener("tv_enable", this);
|
||||
|
||||
ConCommand *pCmd = FindCommand("maxplayers");
|
||||
if (pCmd != NULL)
|
||||
{
|
||||
@@ -167,6 +175,7 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
void PlayerManager::OnSourceModShutdown()
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
|
||||
@@ -176,6 +185,7 @@ void PlayerManager::OnSourceModShutdown()
|
||||
|
||||
/* Release forwards */
|
||||
g_Forwards.ReleaseForward(m_clconnect);
|
||||
g_Forwards.ReleaseForward(m_clconnect_post);
|
||||
g_Forwards.ReleaseForward(m_clputinserver);
|
||||
g_Forwards.ReleaseForward(m_cldisconnect);
|
||||
g_Forwards.ReleaseForward(m_cldisconnect_post);
|
||||
@@ -184,7 +194,6 @@ void PlayerManager::OnSourceModShutdown()
|
||||
g_Forwards.ReleaseForward(m_clauth);
|
||||
g_Forwards.ReleaseForward(m_onActivate);
|
||||
g_Forwards.ReleaseForward(m_onActivate2);
|
||||
g_Forwards.ReleaseForward(OnClientConnected);
|
||||
|
||||
g_Forwards.ReleaseForward(PreAdminCheck);
|
||||
g_Forwards.ReleaseForward(PostAdminCheck);
|
||||
@@ -192,8 +201,6 @@ void PlayerManager::OnSourceModShutdown()
|
||||
|
||||
delete [] m_Players;
|
||||
|
||||
g_ConVarManager.RemoveConVarChangeListener("tv_enable", this);
|
||||
|
||||
if (maxplayersCmd != NULL)
|
||||
{
|
||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, maxplayersCmd, CmdMaxplayersCallback, true);
|
||||
@@ -224,16 +231,43 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
return ConfigResult_Accept;
|
||||
} else if (strcmp( key, "SteamAuthstringValidation" ) == 0) {
|
||||
if (strcasecmp(value, "yes") == 0)
|
||||
{
|
||||
m_bAuthstringValidation = true;
|
||||
} else if ( strcasecmp(value, "no") == 0) {
|
||||
m_bAuthstringValidation = false;
|
||||
} else {
|
||||
UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
|
||||
void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
{
|
||||
static ConVar *tv_enable = icvar->FindVar("tv_enable");
|
||||
#if SOURCE_ENGINE == SE_TF2
|
||||
static ConVar *replay_enable = icvar->FindVar("replay_enable");
|
||||
#endif
|
||||
|
||||
// clientMax will not necessarily be correct here (such as on late SourceTV enable)
|
||||
m_maxClients = gpGlobals->maxClients;
|
||||
|
||||
ICommandLine *commandLine = g_HL2.GetValveCommandLine();
|
||||
m_bIsSourceTVActive = (tv_enable && tv_enable->GetBool() && (!commandLine || commandLine->FindParm("-nohltv") == 0));
|
||||
m_bIsReplayActive = false;
|
||||
#if SOURCE_ENGINE == SE_TF2
|
||||
m_bIsReplayActive = (replay_enable && replay_enable->GetBool());
|
||||
#endif
|
||||
m_PlayersSinceActive = 0;
|
||||
|
||||
if (!m_FirstPass)
|
||||
{
|
||||
/* Initialize all players */
|
||||
m_maxClients = clientMax;
|
||||
|
||||
m_PlayerCount = 0;
|
||||
m_Players = new CPlayer[ABSOLUTE_PLAYER_LIMIT + 1];
|
||||
m_AuthQueue = new unsigned int[ABSOLUTE_PLAYER_LIMIT + 1];
|
||||
@@ -242,10 +276,13 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl
|
||||
memset(m_AuthQueue, 0, sizeof(unsigned int) * (ABSOLUTE_PLAYER_LIMIT + 1));
|
||||
|
||||
g_NumPlayersToAuth = &m_AuthQueue[0];
|
||||
|
||||
g_PluginSys.SyncMaxClients(clientMax);
|
||||
}
|
||||
g_Extensions.CallOnCoreMapStart(pEdictList, edictCount, clientMax);
|
||||
|
||||
g_PluginSys.SyncMaxClients(m_maxClients);
|
||||
|
||||
g_OnMapStarted = true;
|
||||
|
||||
g_Extensions.CallOnCoreMapStart(pEdictList, edictCount, m_maxClients);
|
||||
m_onActivate->Execute(NULL);
|
||||
m_onActivate2->Execute(NULL);
|
||||
|
||||
@@ -254,12 +291,10 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl
|
||||
{
|
||||
if ((*iter)->GetClientListenerVersion() >= 5)
|
||||
{
|
||||
(*iter)->OnServerActivated(clientMax);
|
||||
(*iter)->OnServerActivated(m_maxClients);
|
||||
}
|
||||
}
|
||||
|
||||
g_OnMapStarted = true;
|
||||
|
||||
SMGlobalClass *cls = SMGlobalClass::head;
|
||||
while (cls)
|
||||
{
|
||||
@@ -332,11 +367,18 @@ void PlayerManager::RunAuthChecks()
|
||||
{
|
||||
pPlayer = &m_Players[m_AuthQueue[i]];
|
||||
authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict);
|
||||
pPlayer->SetAuthString(authstr);
|
||||
|
||||
if (!pPlayer->IsAuthStringValidated())
|
||||
{
|
||||
continue; // we're using steam auth, and steam doesn't know about this player yet so we can't do anything about them for now
|
||||
}
|
||||
|
||||
if (authstr && authstr[0] != '\0'
|
||||
&& (strcmp(authstr, "STEAM_ID_PENDING") != 0))
|
||||
{
|
||||
/* Set authorization */
|
||||
pPlayer->Authorize(authstr);
|
||||
pPlayer->Authorize();
|
||||
|
||||
/* Mark as removed from queue */
|
||||
unsigned int client = m_AuthQueue[i];
|
||||
@@ -405,7 +447,23 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
{
|
||||
int client = IndexOfEdict(pEntity);
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
++m_PlayersSinceActive;
|
||||
|
||||
pPlayer->Initialize(pszName, pszAddress, pEntity);
|
||||
|
||||
/* Get the client's language */
|
||||
if (m_QueryLang)
|
||||
{
|
||||
const char *name;
|
||||
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
|
||||
{
|
||||
unsigned int langid;
|
||||
pPlayer->m_LangId = (translator->GetLanguageByName(name, &langid)) ? langid : translator->GetServerLanguage();
|
||||
} else {
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
List<IClientListener *>::iterator iter;
|
||||
IClientListener *pListener = NULL;
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
@@ -413,13 +471,12 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
pListener = (*iter);
|
||||
if (!pListener->InterceptClientConnect(client, reject, maxrejectlen))
|
||||
{
|
||||
return false;
|
||||
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
||||
}
|
||||
}
|
||||
|
||||
cell_t res = 1;
|
||||
|
||||
pPlayer->Initialize(pszName, pszAddress, pEntity);
|
||||
m_clconnect->PushCell(client);
|
||||
m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
||||
m_clconnect->PushCell(maxrejectlen);
|
||||
@@ -461,7 +518,7 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
|
||||
pListener->OnClientConnected(client);
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,8 +530,8 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
|
||||
}
|
||||
|
||||
cell_t res;
|
||||
OnClientConnected->PushCell(client);
|
||||
OnClientConnected->Execute(&res, NULL);
|
||||
m_clconnect_post->PushCell(client);
|
||||
m_clconnect_post->Execute(&res, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -496,8 +553,70 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
/* Run manual connection routines */
|
||||
char error[255];
|
||||
const char *authid = engine->GetPlayerNetworkIDString(pEntity);
|
||||
pPlayer->Authorize(authid);
|
||||
pPlayer->SetAuthString(authid);
|
||||
pPlayer->Authorize();
|
||||
pPlayer->m_bFakeClient = true;
|
||||
|
||||
/*
|
||||
* While we're already filtered to just bots, we'll do other checks to
|
||||
* make sure that the requisite services are enabled and that the bots
|
||||
* have joined at the expected time.
|
||||
*
|
||||
* Checking playerinfo's IsHLTV and IsReplay would be better and less
|
||||
* error-prone but will always show false until later in the frame,
|
||||
* after PutInServer and Activate, and we want it now!
|
||||
*
|
||||
* These checks are hairy as hell due to differences between engines and games.
|
||||
*
|
||||
* Most engines use "Replay" and "SourceTV" as bot names for these when they're
|
||||
* created. EP2V, CSS and Nuclear Dawn (but not L4D2) differ from this by now using
|
||||
* replay_/tv_name directly when creating the bot(s). To complicate it slightly
|
||||
* further, the cvar can be empty and the engine's fallback to "unnamed" will be used.
|
||||
* We can maybe just rip out the name checks at some point and rely solely on whether
|
||||
* they're enabled and the join order.
|
||||
*/
|
||||
|
||||
// This doesn't actually get incremented until OnClientConnect. Fake it to check.
|
||||
int newCount = m_PlayersSinceActive + 1;
|
||||
|
||||
int userId = engine->GetPlayerUserId(pEntity);
|
||||
#if (SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_NUCLEARDAWN || SOURCE_ENGINE == SE_LEFT4DEAD2)
|
||||
static ConVar *tv_name = icvar->FindVar("tv_name");
|
||||
#endif
|
||||
#if SOURCE_ENGINE == SE_TF2
|
||||
static ConVar *replay_name = icvar->FindVar("replay_name");
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_TF2
|
||||
if (m_bIsReplayActive && newCount == 1
|
||||
&& (m_ReplayUserId == userId
|
||||
|| (replay_name && strcmp(playername, replay_name->GetString()) == 0) || (replay_name && replay_name->GetString()[0] == 0 && strcmp(playername, "unnamed") == 0)
|
||||
)
|
||||
)
|
||||
{
|
||||
pPlayer->m_bIsReplay = true;
|
||||
m_ReplayUserId = userId;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_bIsSourceTVActive
|
||||
&& ((!m_bIsReplayActive && newCount == 1)
|
||||
|| (m_bIsReplayActive && newCount == 2))
|
||||
&& (m_SourceTVUserId == userId
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
|| strcmp(playername, "GOTV") == 0
|
||||
#elif (SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_NUCLEARDAWN)
|
||||
|| (tv_name && strcmp(playername, tv_name->GetString()) == 0) || (tv_name && tv_name->GetString()[0] == 0 && strcmp(playername, "unnamed") == 0)
|
||||
#else
|
||||
|| strcmp(playername, "SourceTV") == 0
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
pPlayer->m_bIsSourceTV = true;
|
||||
m_SourceTVUserId = userId;
|
||||
}
|
||||
|
||||
if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error)))
|
||||
{
|
||||
/* :TODO: kick the bot if it's rejected */
|
||||
@@ -515,6 +634,11 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cell_t res;
|
||||
m_clconnect_post->PushCell(client);
|
||||
m_clconnect_post->Execute(&res, NULL);
|
||||
|
||||
/* Now do authorization */
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
@@ -536,19 +660,6 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
pPlayer->m_Info = playerinfo->GetPlayerInfo(pEntity);
|
||||
}
|
||||
|
||||
/* Get the client's language */
|
||||
if (m_QueryLang)
|
||||
{
|
||||
const char *name;
|
||||
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
|
||||
{
|
||||
unsigned int langid;
|
||||
pPlayer->m_LangId = (g_Translator.GetLanguageByName(name, &langid)) ? langid : g_Translator.GetServerLanguage();
|
||||
} else {
|
||||
pPlayer->m_LangId = g_Translator.GetServerLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
pPlayer->Connect();
|
||||
m_PlayerCount++;
|
||||
|
||||
@@ -682,23 +793,30 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
g_PluginSys.ListPluginsToClient(pPlayer, args);
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (args.ArgC() > 1 && strcmp(args.Arg(1), "exts") == 0)
|
||||
{
|
||||
g_Extensions.ListExtensionsToClient(pPlayer, args);
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (args.ArgC() > 1 && strcmp(args.Arg(1), "credits") == 0)
|
||||
{
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod would not be possible without:");
|
||||
ClientConsolePrint(pEntity,
|
||||
" David \"BAILOPAN\" Anderson, Matt \"pRED\" Woodrow");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Scott \"DS\" Ehlert, Fyren");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Nicholas \"psychonic\" Hastings, Asher \"asherkin\" Baker");
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod would not be possible without:");
|
||||
ClientConsolePrint(pEntity,
|
||||
" David \"BAILOPAN\" Anderson, Borja \"faluco\" Ferrer");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Scott \"Damaged Soul\" Ehlert, Matt \"pRED\" Woodrow");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Michael \"ferret\" McKoy, Pavol \"PM OnoTo\" Marko");
|
||||
" Borja \"faluco\" Ferrer, Pavol \"PM OnoTo\" Marko");
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod is open source under the GNU General Public License.");
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod %s, by AlliedModders LLC", SVN_FULL_VERSION);
|
||||
"SourceMod %s, by AlliedModders LLC", SM_VERSION_STRING);
|
||||
ClientConsolePrint(pEntity,
|
||||
"To see running plugins, type \"sm plugins\"");
|
||||
ClientConsolePrint(pEntity,
|
||||
@@ -725,10 +843,27 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
}
|
||||
}
|
||||
|
||||
if (g_ConsoleDetours.IsEnabled())
|
||||
{
|
||||
cell_t res2 = g_ConsoleDetours.InternalDispatch(client, args);
|
||||
if (res2 >= Pl_Stop)
|
||||
{
|
||||
g_HL2.PopCommandStack();
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (res2 > res)
|
||||
{
|
||||
res = res2;
|
||||
}
|
||||
}
|
||||
|
||||
cell_t res2 = Pl_Continue;
|
||||
m_clcommand->PushCell(client);
|
||||
m_clcommand->PushCell(argcount);
|
||||
m_clcommand->Execute(&res2, NULL);
|
||||
if (pPlayer->IsInGame())
|
||||
{
|
||||
m_clcommand->PushCell(client);
|
||||
m_clcommand->PushCell(argcount);
|
||||
m_clcommand->Execute(&res2, NULL);
|
||||
}
|
||||
|
||||
if (res2 > res)
|
||||
{
|
||||
@@ -774,6 +909,19 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
|
||||
const char *old_name = pPlayer->m_Name.c_str();
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
const char *networkid_force;
|
||||
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
||||
{
|
||||
unsigned int accountId = pPlayer->GetSteamAccountID();
|
||||
g_Logger.LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
|
||||
|
||||
pPlayer->Kick("NetworkID spoofing detected.");
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(old_name, new_name) != 0)
|
||||
{
|
||||
AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
|
||||
@@ -781,7 +929,9 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
{
|
||||
if (!CheckSetAdminName(client, pPlayer, id))
|
||||
{
|
||||
pPlayer->Kick("Your name is reserved by SourceMod; set your password to use it.");
|
||||
char kickMsg[128];
|
||||
logicore.CoreTranslate(kickMsg, sizeof(kickMsg), "%T", 2, NULL, "Name Reserved", &client);
|
||||
pPlayer->Kick(kickMsg);
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
} else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
|
||||
@@ -809,6 +959,17 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Notify Extensions */
|
||||
List<IClientListener *>::iterator iter;
|
||||
IClientListener *pListener = NULL;
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
pListener = (*iter);
|
||||
if (pListener->GetClientListenerVersion() >= 13)
|
||||
{
|
||||
pListener->OnClientSettingsChanged(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PlayerManager::GetMaxClients()
|
||||
@@ -1098,11 +1259,12 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!pTarget->IsConnected() || !pTarget->IsAuthorized())
|
||||
if (!pTarget->IsConnected())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (strcmp(pTarget->GetAuthString(), new_pattern) == 0)
|
||||
const char *authstr = pTarget->GetAuthString(false); // We want to make it easy for people to be kicked/banned, so don't require validation for command targets.
|
||||
if (authstr && strcmp(authstr, new_pattern) == 0)
|
||||
{
|
||||
if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags))
|
||||
== COMMAND_TARGET_VALID)
|
||||
@@ -1153,10 +1315,18 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
|
||||
if (strcmp(info->pattern, "@me") == 0 && info->admin != 0)
|
||||
{
|
||||
info->targets[0] = info->admin;
|
||||
info->num_targets = 1;
|
||||
strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
|
||||
info->target_name_style = COMMAND_TARGETNAME_RAW;
|
||||
info->reason = FilterCommandTarget(pAdmin, pAdmin, info->flags);
|
||||
if (info->reason == COMMAND_TARGET_VALID)
|
||||
{
|
||||
info->targets[0] = info->admin;
|
||||
info->num_targets = 1;
|
||||
strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
|
||||
info->target_name_style = COMMAND_TARGETNAME_RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->num_targets = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1204,7 +1374,7 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
if ((info->flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS)
|
||||
{
|
||||
info->num_targets = 0;
|
||||
info->reason = COMMAND_FILTER_NO_BOTS;
|
||||
info->reason = COMMAND_TARGET_NOT_HUMAN;
|
||||
return;
|
||||
}
|
||||
strncopy(info->target_name, "all bots", info->target_name_maxlength);
|
||||
@@ -1270,7 +1440,7 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stristr(pTarget->GetName(), info->pattern) != NULL)
|
||||
if (logicore.stristr(pTarget->GetName(), info->pattern) != NULL)
|
||||
{
|
||||
if (found_client)
|
||||
{
|
||||
@@ -1308,18 +1478,6 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnConVarChanged( ConVar *pConVar, const char *oldValue, float flOldValue )
|
||||
{
|
||||
if (pConVar->GetBool() && !atoi(oldValue))
|
||||
{
|
||||
MaxPlayersChanged(gpGlobals->maxClients + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxPlayersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnSourceModMaxPlayersChanged( int newvalue )
|
||||
{
|
||||
m_maxClients = newvalue;
|
||||
@@ -1411,10 +1569,15 @@ CPlayer::CPlayer()
|
||||
m_TempAdmin = false;
|
||||
m_Info = NULL;
|
||||
m_bAdminCheckSignalled = false;
|
||||
m_UserId = -1;
|
||||
m_bIsInKickQueue = false;
|
||||
m_LastPassword.clear();
|
||||
m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||
m_bFakeClient = false;
|
||||
m_bIsSourceTV = false;
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
m_SteamAccountID = 0;
|
||||
}
|
||||
|
||||
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
@@ -1424,7 +1587,7 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
m_Ip.assign(ip);
|
||||
m_pEdict = pEntity;
|
||||
m_iIndex = IndexOfEdict(pEntity);
|
||||
m_LangId = g_Translator.GetServerLanguage();
|
||||
m_LangId = translator->GetServerLanguage();
|
||||
|
||||
m_Serial.bits.index = m_iIndex;
|
||||
m_Serial.bits.serial = g_PlayerSerialCount++;
|
||||
@@ -1460,17 +1623,22 @@ void CPlayer::Connect()
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::Authorize(const char *steamid)
|
||||
void CPlayer::SetAuthString(const char *steamid)
|
||||
{
|
||||
if (m_IsAuthorized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_IsAuthorized = true;
|
||||
m_AuthID.assign(steamid);
|
||||
}
|
||||
|
||||
// Ensure a valid AuthString is set before calling.
|
||||
void CPlayer::Authorize()
|
||||
{
|
||||
m_IsAuthorized = true;
|
||||
}
|
||||
|
||||
void CPlayer::Disconnect()
|
||||
{
|
||||
DumpAdmin(false);
|
||||
@@ -1486,6 +1654,10 @@ void CPlayer::Disconnect()
|
||||
m_UserId = -1;
|
||||
m_bIsInKickQueue = false;
|
||||
m_bFakeClient = false;
|
||||
m_bIsSourceTV = false;
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
m_SteamAccountID = 0;
|
||||
}
|
||||
|
||||
void CPlayer::SetName(const char *name)
|
||||
@@ -1508,11 +1680,45 @@ const char *CPlayer::GetIPAddress()
|
||||
return m_Ip.c_str();
|
||||
}
|
||||
|
||||
const char *CPlayer::GetAuthString()
|
||||
const char *CPlayer::GetAuthString(bool validated)
|
||||
{
|
||||
if (validated && !IsAuthStringValidated())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_AuthID.c_str();
|
||||
}
|
||||
|
||||
unsigned int CPlayer::GetSteamAccountID(bool validated)
|
||||
{
|
||||
if (IsFakeClient() || (validated && !IsAuthStringValidated()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_SteamAccountID != 0)
|
||||
{
|
||||
return m_SteamAccountID;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||
const char * pAuth = GetAuthString();
|
||||
/* STEAM_0:1:123123 | STEAM_ID_LAN | STEAM_ID_PENDING */
|
||||
if (pAuth && (strlen(pAuth) > 10) && pAuth[8] != '_')
|
||||
{
|
||||
m_SteamAccountID = (atoi(&pAuth[8]) | (atoi(&pAuth[10]) << 1));
|
||||
}
|
||||
#else
|
||||
unsigned long long *steamId = (unsigned long long *)engine->GetClientSteamID(m_pEdict);
|
||||
if (steamId)
|
||||
{
|
||||
m_SteamAccountID = (*steamId & 0xFFFFFFFF);
|
||||
}
|
||||
#endif
|
||||
return m_SteamAccountID;
|
||||
}
|
||||
|
||||
edict_t *CPlayer::GetEdict()
|
||||
{
|
||||
return m_pEdict;
|
||||
@@ -1538,6 +1744,18 @@ bool CPlayer::IsAuthorized()
|
||||
return m_IsAuthorized;
|
||||
}
|
||||
|
||||
bool CPlayer::IsAuthStringValidated()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
if (g_Players.m_bAuthstringValidation && !g_HL2.IsLANServer())
|
||||
{
|
||||
return engine->IsClientFullyAuthenticated(m_pEdict);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IPlayerInfo *CPlayer::GetPlayerInfo()
|
||||
{
|
||||
if (m_pEdict->GetUnknown())
|
||||
@@ -1553,6 +1771,16 @@ bool CPlayer::IsFakeClient()
|
||||
return m_bFakeClient;
|
||||
}
|
||||
|
||||
bool CPlayer::IsSourceTV() const
|
||||
{
|
||||
return m_bIsSourceTV;
|
||||
}
|
||||
|
||||
bool CPlayer::IsReplay() const
|
||||
{
|
||||
return m_bIsReplay;
|
||||
}
|
||||
|
||||
void CPlayer::SetAdminId(AdminId id, bool temporary)
|
||||
{
|
||||
if (!m_IsConnected)
|
||||
@@ -1588,8 +1816,22 @@ void CPlayer::Kick(const char *str)
|
||||
{
|
||||
MarkAsBeingKicked();
|
||||
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
|
||||
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
pClient->Disconnect("%s", str);
|
||||
if (pNetChan == NULL)
|
||||
{
|
||||
/* What does this even mean? Hell if I know. */
|
||||
int userid = GetUserId();
|
||||
if (userid > 0)
|
||||
{
|
||||
char buffer[255];
|
||||
UTIL_Format(buffer, sizeof(buffer), "kickid %d %s\n", userid, str);
|
||||
engine->ServerCommand(buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
pClient->Disconnect("%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::Authorize_Post()
|
||||
@@ -1731,6 +1973,11 @@ unsigned int CPlayer::GetLanguageId()
|
||||
return m_LangId;
|
||||
}
|
||||
|
||||
void CPlayer::SetLanguageId(unsigned int id)
|
||||
{
|
||||
m_LangId = id;
|
||||
}
|
||||
|
||||
int CPlayer::GetUserId()
|
||||
{
|
||||
if (m_UserId == -1)
|
||||
|
||||
+21
-8
@@ -56,7 +56,7 @@ union serial_t
|
||||
uint32_t value;
|
||||
struct
|
||||
{
|
||||
uint8_t index;
|
||||
uint32_t index : 8;
|
||||
uint32_t serial : 24;
|
||||
} bits;
|
||||
};
|
||||
@@ -69,25 +69,29 @@ public:
|
||||
public:
|
||||
const char *GetName();
|
||||
const char *GetIPAddress();
|
||||
const char *GetAuthString();
|
||||
const char *GetAuthString(bool validated = true);
|
||||
unsigned int GetSteamAccountID(bool validated = true);
|
||||
edict_t *GetEdict();
|
||||
bool IsInGame();
|
||||
bool WasCountedAsInGame();
|
||||
bool IsConnected();
|
||||
bool IsAuthorized();
|
||||
bool IsFakeClient();
|
||||
bool IsSourceTV() const;
|
||||
bool IsReplay() const;
|
||||
void SetAdminId(AdminId id, bool temporary);
|
||||
AdminId GetAdminId();
|
||||
void Kick(const char *str);
|
||||
bool IsInKickQueue();
|
||||
IPlayerInfo *GetPlayerInfo();
|
||||
unsigned int GetLanguageId();
|
||||
void SetLanguageId(unsigned int id);
|
||||
int GetUserId();
|
||||
bool RunAdminCacheChecks();
|
||||
void NotifyPostAdminChecks();
|
||||
unsigned int GetSerial();
|
||||
public:
|
||||
void DoBasicAdminChecks();
|
||||
bool IsInKickQueue();
|
||||
void MarkAsBeingKicked();
|
||||
int GetLifeState();
|
||||
private:
|
||||
@@ -96,9 +100,11 @@ private:
|
||||
void Disconnect();
|
||||
void SetName(const char *name);
|
||||
void DumpAdmin(bool deleting);
|
||||
void Authorize(const char *auth);
|
||||
void SetAuthString(const char *auth);
|
||||
void Authorize();
|
||||
void Authorize_Post();
|
||||
void DoPostConnectAuthorization();
|
||||
bool IsAuthStringValidated();
|
||||
private:
|
||||
bool m_IsConnected;
|
||||
bool m_IsInGame;
|
||||
@@ -118,13 +124,15 @@ private:
|
||||
unsigned int m_LangId;
|
||||
int m_UserId;
|
||||
bool m_bFakeClient;
|
||||
bool m_bIsSourceTV;
|
||||
bool m_bIsReplay;
|
||||
serial_t m_Serial;
|
||||
unsigned int m_SteamAccountID;
|
||||
};
|
||||
|
||||
class PlayerManager :
|
||||
public SMGlobalClass,
|
||||
public IPlayerManager,
|
||||
public IConVarChangeListener
|
||||
public IPlayerManager
|
||||
{
|
||||
friend class CPlayer;
|
||||
public:
|
||||
@@ -169,8 +177,6 @@ public: //IPlayerManager
|
||||
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||
void ProcessCommandTarget(cmd_target_info_t *info);
|
||||
int GetClientFromSerial(unsigned int serial);
|
||||
public: // IConVarChangeListener
|
||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||
public:
|
||||
inline int MaxClients()
|
||||
{
|
||||
@@ -197,6 +203,7 @@ private:
|
||||
private:
|
||||
List<IClientListener *> m_hooks;
|
||||
IForward *m_clconnect;
|
||||
IForward *m_clconnect_post;
|
||||
IForward *m_cldisconnect;
|
||||
IForward *m_cldisconnect_post;
|
||||
IForward *m_clputinserver;
|
||||
@@ -209,12 +216,18 @@ private:
|
||||
int *m_UserIdLookUp;
|
||||
int m_maxClients;
|
||||
int m_PlayerCount;
|
||||
int m_PlayersSinceActive;
|
||||
bool m_FirstPass;
|
||||
unsigned int *m_AuthQueue;
|
||||
String m_PassInfoVar;
|
||||
bool m_QueryLang;
|
||||
bool m_bAuthstringValidation; // are we validating admins with steam before authorizing?
|
||||
bool m_bIsListenServer;
|
||||
int m_ListenClient;
|
||||
bool m_bIsSourceTVActive;
|
||||
bool m_bIsReplayActive;
|
||||
int m_SourceTVUserId;
|
||||
int m_ReplayUserId;
|
||||
};
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
|
||||
@@ -276,7 +276,7 @@ SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
m_infodb_size *= 2;
|
||||
}
|
||||
int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
|
||||
int newidx = memtab->CreateMem(m_infodb_size * sizeof(int), (void **)&table);
|
||||
if (m_infodb != -1)
|
||||
{
|
||||
void *oldtable = (int *)memtab->GetAddress(m_infodb);
|
||||
|
||||
+195
-137
@@ -37,7 +37,6 @@
|
||||
#include "ForwardSys.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "sourcemod.h"
|
||||
#include "TextParsers.h"
|
||||
#include "Logger.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include "sm_srvcmds.h"
|
||||
@@ -45,7 +44,7 @@
|
||||
#include "ConCmdManager.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "CoreConfig.h"
|
||||
#include "Translator.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
CPluginManager g_PluginSys;
|
||||
HandleType_t g_PluginType = 0;
|
||||
@@ -57,17 +56,18 @@ CPlugin::CPlugin(const char *file)
|
||||
|
||||
m_type = PluginType_Private;
|
||||
m_status = Plugin_Uncompiled;
|
||||
m_bSilentlyFailed = false;
|
||||
m_serial = ++MySerial;
|
||||
m_pRuntime = NULL;
|
||||
m_errormsg[256] = '\0';
|
||||
snprintf(m_filename, sizeof(m_filename), "%s", file);
|
||||
m_errormsg[sizeof(m_errormsg) - 1] = '\0';
|
||||
UTIL_Format(m_filename, sizeof(m_filename), "%s", file);
|
||||
m_handle = 0;
|
||||
m_ident = NULL;
|
||||
m_pProps = sm_trie_create();
|
||||
m_FakeNativesMissing = false;
|
||||
m_LibraryMissing = false;
|
||||
m_bGotAllLoaded = false;
|
||||
m_pPhrases = g_Translator.CreatePhraseCollection();
|
||||
m_pPhrases = translator->CreatePhraseCollection();
|
||||
m_MaxClientsVar = NULL;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Unable to open file");
|
||||
UTIL_Format(error, maxlength, "Unable to open file");
|
||||
}
|
||||
pPlugin->m_status = Plugin_BadLoad;
|
||||
return pPlugin;
|
||||
@@ -210,7 +210,7 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, error_fmt);
|
||||
vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
|
||||
UTIL_FormatArgs(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (m_pRuntime != NULL)
|
||||
@@ -372,7 +372,7 @@ void CPlugin::Call_OnAllPluginsLoaded()
|
||||
pFunction->Execute(&result);
|
||||
}
|
||||
|
||||
if (g_OnMapStarted)
|
||||
if (g_SourceMod.IsMapRunning())
|
||||
{
|
||||
if ((pFunction = m_pRuntime->GetFunctionByName("OnMapStart")) != NULL)
|
||||
{
|
||||
@@ -386,22 +386,27 @@ void CPlugin::Call_OnAllPluginsLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
||||
APLRes CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
||||
{
|
||||
if (m_status != Plugin_Created)
|
||||
{
|
||||
return false;
|
||||
return APLRes_Failure;
|
||||
}
|
||||
|
||||
m_status = Plugin_Loaded;
|
||||
|
||||
int err;
|
||||
cell_t result;
|
||||
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad");
|
||||
bool haveNewAPL = false;
|
||||
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad2");
|
||||
|
||||
if (!pFunction)
|
||||
if (pFunction)
|
||||
{
|
||||
return true;
|
||||
haveNewAPL = true;
|
||||
}
|
||||
else if (!(pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad")))
|
||||
{
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
pFunction->PushCell(m_handle);
|
||||
@@ -410,15 +415,21 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
||||
pFunction->PushCell(maxlength);
|
||||
if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE)
|
||||
{
|
||||
return false;
|
||||
return APLRes_Failure;
|
||||
}
|
||||
|
||||
if (!result || m_status != Plugin_Loaded)
|
||||
if (haveNewAPL)
|
||||
{
|
||||
return false;
|
||||
return (APLRes)result;
|
||||
}
|
||||
else if (result)
|
||||
{
|
||||
return APLRes_Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return APLRes_Failure;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *CPlugin::GetPluginStructure()
|
||||
@@ -470,6 +481,11 @@ PluginStatus CPlugin::GetStatus()
|
||||
return m_status;
|
||||
}
|
||||
|
||||
bool CPlugin::IsSilentlyFailed()
|
||||
{
|
||||
return m_bSilentlyFailed;
|
||||
}
|
||||
|
||||
bool CPlugin::IsDebugging()
|
||||
{
|
||||
if (m_pRuntime == NULL)
|
||||
@@ -480,14 +496,19 @@ bool CPlugin::IsDebugging()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPlugin::LibraryActions(bool dropping)
|
||||
void CPlugin::SetSilentlyFailed(bool sf)
|
||||
{
|
||||
m_bSilentlyFailed = sf;
|
||||
}
|
||||
|
||||
void CPlugin::LibraryActions(LibraryAction action)
|
||||
{
|
||||
List<String>::iterator iter;
|
||||
for (iter = m_Libraries.begin();
|
||||
iter != m_Libraries.end();
|
||||
iter++)
|
||||
{
|
||||
g_PluginSys.OnLibraryAction((*iter).c_str(), true, dropping);
|
||||
g_PluginSys.OnLibraryAction((*iter).c_str(), action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,7 +523,7 @@ bool CPlugin::SetPauseState(bool paused)
|
||||
|
||||
if (paused)
|
||||
{
|
||||
LibraryActions(true);
|
||||
LibraryActions(LibraryAction_Removed);
|
||||
}
|
||||
|
||||
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginPauseChange");
|
||||
@@ -526,7 +547,7 @@ bool CPlugin::SetPauseState(bool paused)
|
||||
|
||||
if (!paused)
|
||||
{
|
||||
LibraryActions(false);
|
||||
LibraryActions(LibraryAction_Added);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -768,6 +789,8 @@ CPluginManager::CPluginManager()
|
||||
m_AllPluginsLoaded = false;
|
||||
m_MyIdent = NULL;
|
||||
m_LoadingLocked = false;
|
||||
|
||||
m_bBlockBadPlugins = true;
|
||||
}
|
||||
|
||||
CPluginManager::~CPluginManager()
|
||||
@@ -851,7 +874,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
if (localpath == NULL)
|
||||
{
|
||||
/* If no path yet, don't add a former slash */
|
||||
snprintf(new_local, sizeof(new_local), "%s", dir->GetEntryName());
|
||||
UTIL_Format(new_local, sizeof(new_local), "%s", dir->GetEntryName());
|
||||
} else {
|
||||
g_LibSys.PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName());
|
||||
}
|
||||
@@ -866,7 +889,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
char plugin[PLATFORM_MAX_PATH];
|
||||
if (localpath == NULL)
|
||||
{
|
||||
snprintf(plugin, sizeof(plugin), "%s", name);
|
||||
UTIL_Format(plugin, sizeof(plugin), "%s", name);
|
||||
} else {
|
||||
g_LibSys.PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name);
|
||||
}
|
||||
@@ -965,7 +988,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
|
||||
UTIL_Format(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
|
||||
}
|
||||
co->Abort();
|
||||
co = NULL;
|
||||
@@ -984,11 +1007,14 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
pPlugin->m_pRuntime = g_pSourcePawn2->LoadPlugin(co, fullpath, &err);
|
||||
if (pPlugin->m_pRuntime == NULL)
|
||||
{
|
||||
snprintf(error,
|
||||
maxlength,
|
||||
"Unable to load plugin (error %d: %s)",
|
||||
err,
|
||||
g_pSourcePawn2->GetErrorString(err));
|
||||
if (error)
|
||||
{
|
||||
UTIL_Format(error,
|
||||
maxlength,
|
||||
"Unable to load plugin (error %d: %s)",
|
||||
err,
|
||||
g_pSourcePawn2->GetErrorString(err));
|
||||
}
|
||||
pPlugin->m_status = Plugin_BadLoad;
|
||||
}
|
||||
else
|
||||
@@ -999,25 +1025,74 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Format(error, maxlength, "%s", pPlugin->m_errormsg);
|
||||
if (error)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "%s", pPlugin->m_errormsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pPlugin->GetStatus() == Plugin_Created)
|
||||
{
|
||||
unsigned char *pCodeHash = pPlugin->m_pRuntime->GetCodeHash();
|
||||
|
||||
char codeHashBuf[40];
|
||||
UTIL_Format(codeHashBuf, 40, "plugin_");
|
||||
for (int i = 0; i < 16; i++)
|
||||
UTIL_Format(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]);
|
||||
|
||||
const char *bulletinUrl = g_pGameConf->GetKeyValue(codeHashBuf);
|
||||
if (bulletinUrl != NULL)
|
||||
{
|
||||
if (m_bBlockBadPlugins)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
if (bulletinUrl[0] != '\0')
|
||||
{
|
||||
UTIL_Format(error, maxlength, "Known malware detected and blocked. See %s for more info", bulletinUrl);
|
||||
} else {
|
||||
UTIL_Format(error, maxlength, "Possible malware or illegal plugin detected and blocked");
|
||||
}
|
||||
}
|
||||
pPlugin->m_status = Plugin_BadLoad;
|
||||
} else {
|
||||
if (bulletinUrl[0] != '\0')
|
||||
{
|
||||
g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
|
||||
} else {
|
||||
g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadRes loadFailure = LoadRes_Failure;
|
||||
/* Get the status */
|
||||
if (pPlugin->GetStatus() == Plugin_Created)
|
||||
{
|
||||
/* First native pass - add anything from Core */
|
||||
g_ShareSys.BindNativesToPlugin(pPlugin, true);
|
||||
pPlugin->InitIdentity();
|
||||
if (pPlugin->Call_AskPluginLoad(error, maxlength))
|
||||
APLRes result = pPlugin->Call_AskPluginLoad(error, maxlength);
|
||||
switch (result)
|
||||
{
|
||||
case APLRes_Success:
|
||||
/* Autoload any modules */
|
||||
LoadOrRequireExtensions(pPlugin, 1, error, maxlength);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case APLRes_Failure:
|
||||
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||
loadFailure = LoadRes_Failure;
|
||||
break;
|
||||
case APLRes_SilentFailure:
|
||||
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||
loadFailure = LoadRes_SilentFailure;
|
||||
pPlugin->SetSilentlyFailed(true);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1105,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
*_plugin = pPlugin;
|
||||
}
|
||||
|
||||
return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : LoadRes_Failure;
|
||||
return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : loadFailure;
|
||||
}
|
||||
|
||||
IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t maxlength, bool *wasloaded)
|
||||
@@ -1053,13 +1128,16 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
|
||||
|
||||
if (res == LoadRes_NeverLoad)
|
||||
{
|
||||
if (m_LoadingLocked)
|
||||
if (error)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "There is a global plugin loading lock in effect");
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Format(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
|
||||
if (m_LoadingLocked)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "There is a global plugin loading lock in effect");
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Format(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1088,14 +1166,14 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
|
||||
|
||||
if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
|
||||
{
|
||||
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s", plugin, error);
|
||||
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
|
||||
pl->SetErrorState(
|
||||
pl->GetStatus() == Plugin_BadLoad ? Plugin_BadLoad : Plugin_Failed,
|
||||
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
|
||||
"%s",
|
||||
error);
|
||||
}
|
||||
|
||||
if (res == LoadRes_Successful || res == LoadRes_Failure)
|
||||
if (res == LoadRes_Successful || res == LoadRes_Failure || res == LoadRes_SilentFailure)
|
||||
{
|
||||
AddPlugin(pl);
|
||||
}
|
||||
@@ -1189,7 +1267,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Fatal error during initializing plugin load");
|
||||
UTIL_Format(error, maxlength, "Fatal error during initializing plugin load");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1222,7 +1300,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Could not find required plugin \"%s\"", name);
|
||||
UTIL_Format(error, maxlength, "Could not find required plugin \"%s\"", name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1273,7 +1351,8 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
|
||||
if (ext->autoload)
|
||||
{
|
||||
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
|
||||
g_Extensions.LoadAutoExtension(path);
|
||||
bool bErrorOnMissing = ext->required ? true : false;
|
||||
g_Extensions.LoadAutoExtension(path, bErrorOnMissing);
|
||||
}
|
||||
}
|
||||
else if (pass == 2)
|
||||
@@ -1293,7 +1372,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
|
||||
UTIL_Format(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1361,7 +1440,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Native \"%s\" was not found", native->name);
|
||||
UTIL_Format(error, maxlength, "Native \"%s\" was not found", native->name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1416,7 +1495,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
|
||||
s_iter != pPlugin->m_Libraries.end();
|
||||
s_iter++)
|
||||
{
|
||||
OnLibraryAction((*s_iter).c_str(), true, false);
|
||||
OnLibraryAction((*s_iter).c_str(), LibraryAction_Added);
|
||||
}
|
||||
|
||||
/* :TODO: optimize? does this even matter? */
|
||||
@@ -1468,7 +1547,9 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (native->status == SP_NATIVE_UNBOUND && !(native->flags & SP_NTVFLAG_OPTIONAL))
|
||||
if (native->status == SP_NATIVE_UNBOUND
|
||||
&& native->name[0] != '@'
|
||||
&& !(native->flags & SP_NTVFLAG_OPTIONAL))
|
||||
{
|
||||
pPlugin->SetErrorState(Plugin_Error, "Native not found: %s", native->name);
|
||||
return;
|
||||
@@ -1516,7 +1597,7 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
|
||||
s_iter != pPlugin->m_Libraries.end();
|
||||
s_iter++)
|
||||
{
|
||||
OnLibraryAction((*s_iter).c_str(), true, true);
|
||||
OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed);
|
||||
}
|
||||
|
||||
List<IPluginsListener *>::iterator iter;
|
||||
@@ -1524,14 +1605,15 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
|
||||
|
||||
if (pPlugin->GetStatus() <= Plugin_Error)
|
||||
{
|
||||
/* Notify plugin */
|
||||
pPlugin->Call_OnPluginEnd();
|
||||
|
||||
/* Notify listeners of unloading */
|
||||
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
|
||||
{
|
||||
pListener = (*iter);
|
||||
pListener->OnPluginUnloaded(pPlugin);
|
||||
}
|
||||
/* Notify plugin */
|
||||
pPlugin->Call_OnPluginEnd();
|
||||
}
|
||||
|
||||
pPlugin->DropEverything();
|
||||
@@ -1832,6 +1914,9 @@ void CPluginManager::OnSourceModAllInitialized()
|
||||
g_RootMenu.AddRootConsoleCommand("plugins", "Manage Plugins", this);
|
||||
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
|
||||
m_pOnLibraryAdded = g_Forwards.CreateForward("OnLibraryAdded", ET_Ignore, 1, NULL, Param_String);
|
||||
m_pOnLibraryRemoved = g_Forwards.CreateForward("OnLibraryRemoved", ET_Ignore, 1, NULL, Param_String);
|
||||
}
|
||||
|
||||
void CPluginManager::OnSourceModShutdown()
|
||||
@@ -1843,6 +1928,30 @@ void CPluginManager::OnSourceModShutdown()
|
||||
g_HandleSys.RemoveType(g_PluginType, m_MyIdent);
|
||||
g_ShareSys.DestroyIdentType(g_PluginIdent);
|
||||
g_ShareSys.DestroyIdentity(m_MyIdent);
|
||||
|
||||
g_Forwards.ReleaseForward(m_pOnLibraryAdded);
|
||||
g_Forwards.ReleaseForward(m_pOnLibraryRemoved);
|
||||
}
|
||||
|
||||
ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength)
|
||||
{
|
||||
if (strcmp(key, "BlockBadPlugins") == 0) {
|
||||
if (strcasecmp(value, "yes") == 0)
|
||||
{
|
||||
m_bBlockBadPlugins = true;
|
||||
} else if (strcasecmp(value, "no") == 0) {
|
||||
m_bBlockBadPlugins = false;
|
||||
} else {
|
||||
UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
|
||||
void CPluginManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -1951,7 +2060,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
assert(pl->GetStatus() != Plugin_Created);
|
||||
int len = 0;
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
if (pl->GetStatus() != Plugin_Running)
|
||||
if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed())
|
||||
{
|
||||
len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetStatus()));
|
||||
|
||||
@@ -1967,6 +2076,8 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
}
|
||||
if (pl->GetStatus() < Plugin_Created)
|
||||
{
|
||||
if (pl->IsSilentlyFailed())
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " Disabled:");
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
if (IS_STR_FILLED(info->version))
|
||||
{
|
||||
@@ -2015,7 +2126,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(filename) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", filename, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", filename, ext);
|
||||
|
||||
IPlugin *pl = LoadPlugin(pluginfile, false, PluginType_MapUpdated, error, sizeof(error), &wasloaded);
|
||||
|
||||
@@ -2062,7 +2173,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
@@ -2152,7 +2263,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
@@ -2223,6 +2334,15 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
g_RootMenu.ConsolePrint(" Timestamp: %s", pl->m_DateTime);
|
||||
}
|
||||
|
||||
unsigned char *pCodeHash = pl->m_pRuntime->GetCodeHash();
|
||||
unsigned char *pDataHash = pl->m_pRuntime->GetDataHash();
|
||||
|
||||
char combinedHash[33];
|
||||
for (int i = 0; i < 16; i++)
|
||||
UTIL_Format(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]);
|
||||
|
||||
g_RootMenu.ConsolePrint(" Hash: %s", combinedHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2273,7 +2393,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
@@ -2284,7 +2404,10 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
|
||||
char name[PLATFORM_MAX_PATH];
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
if (pl->GetStatus() <= Plugin_Paused)
|
||||
strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
else
|
||||
strcpy(name, pl->GetFilename());
|
||||
|
||||
if (ReloadPlugin(pl))
|
||||
{
|
||||
@@ -2434,83 +2557,18 @@ CPlugin *CPluginManager::GetPluginFromIdentity(IdentityToken_t *pToken)
|
||||
return (CPlugin *)(pToken->ptr);
|
||||
}
|
||||
|
||||
void CPluginManager::OnLibraryAction(const char *lib, bool is_a_plugin, bool drop)
|
||||
void CPluginManager::OnLibraryAction(const char *lib, LibraryAction action)
|
||||
{
|
||||
List<CPlugin *>::iterator iter;
|
||||
|
||||
struct _pl
|
||||
switch (action)
|
||||
{
|
||||
cell_t name;
|
||||
cell_t file;
|
||||
cell_t required;
|
||||
} *plc;
|
||||
|
||||
struct _ext
|
||||
{
|
||||
cell_t name;
|
||||
cell_t file;
|
||||
cell_t autoload;
|
||||
cell_t required;
|
||||
} *ext;
|
||||
|
||||
const char *name = drop ? "OnLibraryRemoved" : "OnLibraryAdded";
|
||||
|
||||
for (iter=m_plugins.begin();
|
||||
iter!=m_plugins.end();
|
||||
iter++)
|
||||
{
|
||||
CPlugin *pl = (*iter);
|
||||
if (pl->GetStatus() != Plugin_Running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
IPluginContext *pContext = pl->GetBaseContext();
|
||||
IPluginFunction *pf = pContext->GetFunctionByName(name);
|
||||
if (!pf)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uint32_t num_vars = pContext->GetPubVarsNum();
|
||||
for (uint32_t i=0; i<num_vars; i++)
|
||||
{
|
||||
sp_pubvar_t *pubvar;
|
||||
if (pContext->GetPubvarByIndex(i, &pubvar) != SP_ERROR_NONE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (is_a_plugin && strncmp(pubvar->name, "__pl_", 5) == 0)
|
||||
{
|
||||
plc = (_pl *)pubvar->offs;
|
||||
if (plc->required)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
char *str;
|
||||
pContext->LocalToString(plc->name, &str);
|
||||
if (strcmp(str, lib) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pf->PushString(lib);
|
||||
pf->Execute(NULL);
|
||||
}
|
||||
else if (!is_a_plugin && strncmp(pubvar->name, "__ext_", 6) == 0)
|
||||
{
|
||||
ext = (_ext *)pubvar->offs;
|
||||
if (ext->required)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
char *str;
|
||||
pContext->LocalToString(ext->name, &str);
|
||||
if (strcmp(str, lib) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pf->PushString(lib);
|
||||
pf->Execute(NULL);
|
||||
}
|
||||
}
|
||||
case LibraryAction_Removed:
|
||||
m_pOnLibraryRemoved->PushString(lib);
|
||||
m_pOnLibraryRemoved->Execute(NULL);
|
||||
break;
|
||||
case LibraryAction_Added:
|
||||
m_pOnLibraryAdded->PushString(lib);
|
||||
m_pOnLibraryAdded->Execute(NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2701,6 +2759,6 @@ void CPluginManager::ListPluginsToClient(CPlayer *player, const CCommand &args)
|
||||
/* Do we actually have more plugins? */
|
||||
if (iter != m_plugins.end())
|
||||
{
|
||||
ClientConsolePrint(e, "To see more, type \"sm plugins %d\"", id + 1);
|
||||
ClientConsolePrint(e, "To see more, type \"sm plugins %d\"", id);
|
||||
}
|
||||
}
|
||||
|
||||
+35
-6
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -47,14 +47,17 @@
|
||||
#include "sm_trie.h"
|
||||
#include "sourcemod.h"
|
||||
#include <IRootConsoleMenu.h>
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_ALIENSWARM
|
||||
#include "convar_sm_swarm.h"
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
#include "convar_sm_l4d.h"
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
||||
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
#include "convar_sm_ob.h"
|
||||
#else
|
||||
#include "convar_sm.h"
|
||||
#endif
|
||||
#include "ITranslator.h"
|
||||
#include "IGameConfigs.h"
|
||||
#include "NativeOwner.h"
|
||||
#include "ShareSys.h"
|
||||
|
||||
@@ -117,9 +120,23 @@ enum LoadRes
|
||||
LoadRes_Successful,
|
||||
LoadRes_AlreadyLoaded,
|
||||
LoadRes_Failure,
|
||||
LoadRes_SilentFailure,
|
||||
LoadRes_NeverLoad
|
||||
};
|
||||
|
||||
enum APLRes
|
||||
{
|
||||
APLRes_Success,
|
||||
APLRes_Failure,
|
||||
APLRes_SilentFailure
|
||||
};
|
||||
|
||||
enum LibraryAction
|
||||
{
|
||||
LibraryAction_Removed,
|
||||
LibraryAction_Added
|
||||
};
|
||||
|
||||
struct AutoConfig
|
||||
{
|
||||
String autocfg;
|
||||
@@ -146,6 +163,8 @@ public:
|
||||
const char *GetFilename();
|
||||
bool IsDebugging();
|
||||
PluginStatus GetStatus();
|
||||
bool IsSilentlyFailed();
|
||||
void SetSilentlyFailed(bool sf);
|
||||
const sm_plugininfo_t *GetPublicInfo();
|
||||
bool SetPauseState(bool paused);
|
||||
unsigned int GetSerial();
|
||||
@@ -183,7 +202,7 @@ public:
|
||||
*
|
||||
* If the error buffer is NULL, the error message is cached locally.
|
||||
*/
|
||||
bool Call_AskPluginLoad(char *error, size_t maxlength);
|
||||
APLRes Call_AskPluginLoad(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Calls the OnPluginStart function.
|
||||
@@ -237,7 +256,7 @@ public:
|
||||
{
|
||||
m_Libraries.push_back(name);
|
||||
}
|
||||
void LibraryActions(bool dropping);
|
||||
void LibraryActions(LibraryAction action);
|
||||
void SyncMaxClients(int max_clients);
|
||||
protected:
|
||||
bool UpdateInfo();
|
||||
@@ -247,6 +266,7 @@ private:
|
||||
PluginType m_type;
|
||||
char m_filename[PLATFORM_MAX_PATH];
|
||||
PluginStatus m_status;
|
||||
bool m_bSilentlyFailed;
|
||||
unsigned int m_serial;
|
||||
sm_plugininfo_t m_info;
|
||||
char m_errormsg[256];
|
||||
@@ -313,6 +333,7 @@ public: //IPluginManager
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
|
||||
void OnSourceModMaxPlayersChanged(int newvalue);
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
@@ -388,7 +409,7 @@ public:
|
||||
|
||||
void Shutdown();
|
||||
|
||||
void OnLibraryAction(const char *lib, bool is_a_plugin, bool drop);
|
||||
void OnLibraryAction(const char *lib, LibraryAction action);
|
||||
|
||||
bool LibraryExists(const char *lib);
|
||||
|
||||
@@ -457,8 +478,16 @@ private:
|
||||
List<FakeNative *> m_Natives;
|
||||
|
||||
bool m_LoadingLocked;
|
||||
|
||||
// Config
|
||||
bool m_bBlockBadPlugins;
|
||||
|
||||
// Forwards
|
||||
IForward *m_pOnLibraryAdded;
|
||||
IForward *m_pOnLibraryRemoved;
|
||||
};
|
||||
|
||||
extern CPluginManager g_PluginSys;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
||||
|
||||
|
||||
@@ -527,3 +527,85 @@ NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name
|
||||
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name)
|
||||
{
|
||||
if (m_caps.retrieve(name) != NULL)
|
||||
return;
|
||||
|
||||
Capability cap;
|
||||
cap.ext = myself;
|
||||
cap.provider = provider;
|
||||
|
||||
m_caps.insert(name, cap);
|
||||
}
|
||||
|
||||
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name)
|
||||
{
|
||||
Capability *pCap = m_caps.retrieve(name);
|
||||
if (pCap == NULL)
|
||||
return;
|
||||
|
||||
if (pCap->ext != myself || pCap->provider != provider)
|
||||
return;
|
||||
|
||||
m_caps.remove(name);
|
||||
}
|
||||
|
||||
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature,
|
||||
const char *name)
|
||||
{
|
||||
switch (feature)
|
||||
{
|
||||
case FeatureType_Native:
|
||||
return TestNative(pRuntime, name);
|
||||
case FeatureType_Capability:
|
||||
return TestCap(name);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FeatureStatus_Unknown;
|
||||
}
|
||||
|
||||
FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (pRuntime->FindNativeByName(name, &index) == SP_ERROR_NONE)
|
||||
{
|
||||
sp_native_t *native;
|
||||
if (pRuntime->GetNativeByIndex(index, &native) == SP_ERROR_NONE)
|
||||
{
|
||||
if (native->status == SP_NATIVE_BOUND)
|
||||
return FeatureStatus_Available;
|
||||
else
|
||||
return FeatureStatus_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
NativeEntry *entry = FindNative(name);
|
||||
if (entry == NULL)
|
||||
return FeatureStatus_Unknown;
|
||||
|
||||
if ((entry->replacement.owner != NULL || entry->owner != NULL) &&
|
||||
(entry->replacement.func != NULL || entry->func != NULL))
|
||||
{
|
||||
return FeatureStatus_Available;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FeatureStatus_Unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
FeatureStatus ShareSystem::TestCap(const char *name)
|
||||
{
|
||||
Capability *cap = m_caps.retrieve(name);
|
||||
if (cap == NULL)
|
||||
return FeatureStatus_Unknown;
|
||||
|
||||
return cap->provider->GetFeatureStatus(FeatureType_Capability, name);
|
||||
}
|
||||
|
||||
+15
-1
@@ -87,7 +87,13 @@ struct NativeEntry
|
||||
FakeNative *fake;
|
||||
};
|
||||
|
||||
class ShareSystem :
|
||||
struct Capability
|
||||
{
|
||||
IExtension *ext;
|
||||
IFeatureProvider *provider;
|
||||
};
|
||||
|
||||
class ShareSystem :
|
||||
public IShareSys,
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch
|
||||
@@ -110,6 +116,10 @@ public: //IShareSys
|
||||
void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload);
|
||||
void RegisterLibrary(IExtension *myself, const char *name);
|
||||
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
||||
void AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name);
|
||||
void DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name);
|
||||
public: //SMGlobalClass
|
||||
/* Pre-empt in case anything tries to register idents early */
|
||||
void Initialize();
|
||||
@@ -119,6 +129,9 @@ public: //IHandleTypeDispatch
|
||||
public:
|
||||
IdentityToken_t *CreateCoreIdentity();
|
||||
void RemoveInterfaces(IExtension *pExtension);
|
||||
FeatureStatus TestFeature(IPluginRuntime *pRuntime, FeatureType feature, const char *name);
|
||||
FeatureStatus TestNative(IPluginRuntime *pRuntime, const char *name);
|
||||
FeatureStatus TestCap(const char *name);
|
||||
public:
|
||||
inline IdentityToken_t *GetIdentRoot()
|
||||
{
|
||||
@@ -143,6 +156,7 @@ private:
|
||||
HandleType_t m_IfaceType;
|
||||
IdentityType_t m_CoreType;
|
||||
KTrie<NativeEntry *> m_NtvCache;
|
||||
KTrie<Capability> m_caps;
|
||||
};
|
||||
|
||||
extern ShareSystem g_ShareSys;
|
||||
|
||||
+1
-1
@@ -78,11 +78,11 @@ public: //ITimerSystem
|
||||
float GetTickedTime();
|
||||
void NotifyOfGameStart(float offset /* = 0.0f */);
|
||||
bool GetMapTimeLeft(float *pTime);
|
||||
IMapTimer *GetMapTimer();
|
||||
public:
|
||||
void RunFrame();
|
||||
void RemoveMapChangeTimers();
|
||||
void GameFrame(bool simulating);
|
||||
IMapTimer *GetMapTimer();
|
||||
private:
|
||||
List<ITimer *> m_SingleTimers;
|
||||
List<ITimer *> m_LoopTimers;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+304
-43
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -32,18 +32,32 @@
|
||||
#include "UserMessages.h"
|
||||
#include "sm_stringutil.h"
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <cstrike15_usermessage_helpers.h>
|
||||
#endif
|
||||
|
||||
UserMessages g_UserMsgs;
|
||||
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
|
||||
#else
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
|
||||
#else
|
||||
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
||||
#endif
|
||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
||||
#endif // ==SE_CSGO
|
||||
|
||||
UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
||||
UserMessages::UserMessages()
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
: m_InterceptBuffer(m_pBase, 2500)
|
||||
{
|
||||
m_Names = sm_trie_create();
|
||||
#else
|
||||
: m_InterceptBuffer(NULL)
|
||||
{
|
||||
#endif
|
||||
m_HookCount = 0;
|
||||
m_InExec = false;
|
||||
m_InHook = false;
|
||||
@@ -53,7 +67,9 @@ UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
||||
|
||||
UserMessages::~UserMessages()
|
||||
{
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
sm_trie_destroy(m_Names);
|
||||
#endif
|
||||
|
||||
CStack<ListenerInfo *>::iterator iter;
|
||||
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
||||
@@ -65,8 +81,10 @@ UserMessages::~UserMessages()
|
||||
|
||||
void UserMessages::OnSourceModStartup(bool late)
|
||||
{
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
/* -1 means SourceMM was unable to get the user message list */
|
||||
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void UserMessages::OnSourceModAllInitialized()
|
||||
@@ -78,16 +96,25 @@ void UserMessages::OnSourceModAllShutdown()
|
||||
{
|
||||
if (m_HookCount)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
||||
#endif
|
||||
}
|
||||
m_HookCount = 0;
|
||||
}
|
||||
|
||||
int UserMessages::GetMessageIndex(const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// Can split this per engine and/or game later
|
||||
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
||||
#else
|
||||
int msgid;
|
||||
|
||||
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
|
||||
@@ -118,10 +145,19 @@ int UserMessages::GetMessageIndex(const char *msg)
|
||||
}
|
||||
|
||||
return msgid;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
||||
if (!pszName)
|
||||
return false;
|
||||
|
||||
strncopy(buffer, pszName, maxlength);
|
||||
return true;
|
||||
#else
|
||||
if (m_FallbackSearch)
|
||||
{
|
||||
int size;
|
||||
@@ -137,10 +173,14 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||
bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return NULL;
|
||||
#else
|
||||
bf_write *buffer;
|
||||
|
||||
if (m_InExec || m_InHook)
|
||||
@@ -168,13 +208,13 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
||||
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
||||
#else
|
||||
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
||||
#endif
|
||||
} else {
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
|
||||
#else
|
||||
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
||||
@@ -182,6 +222,75 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#endif // USE_PROTOBUF_USERMESSAGES
|
||||
}
|
||||
|
||||
google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
|
||||
{
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
return NULL;
|
||||
#else
|
||||
protobuf::Message *buffer;
|
||||
|
||||
if (m_InExec || m_InHook)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (msg_id < 0 || msg_id >= 255)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_CurId = msg_id;
|
||||
m_CellRecFilter.Initialize(players, playersNum);
|
||||
|
||||
m_CurFlags = flags;
|
||||
if (m_CurFlags & USERMSG_INITMSG)
|
||||
{
|
||||
m_CellRecFilter.SetToInit(true);
|
||||
}
|
||||
if (m_CurFlags & USERMSG_RELIABLE)
|
||||
{
|
||||
m_CellRecFilter.SetToReliable(true);
|
||||
}
|
||||
|
||||
m_InExec = true;
|
||||
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
// direct message creation, return buffer "from engine". keep track
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
|
||||
buffer = m_FakeEngineBuffer;
|
||||
} else {
|
||||
char messageName[32];
|
||||
if (!GetMessageName(msg_id, messageName, sizeof(messageName)))
|
||||
{
|
||||
m_InExec = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
|
||||
switch (m_FakeMetaRes)
|
||||
{
|
||||
case MRES_IGNORED:
|
||||
case MRES_HANDLED:
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
|
||||
buffer = m_FakeEngineBuffer;
|
||||
break;
|
||||
|
||||
case MRES_OVERRIDE:
|
||||
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
|
||||
// fallthrough
|
||||
case MRES_SUPERCEDE:
|
||||
buffer = msg;
|
||||
break;
|
||||
}
|
||||
|
||||
OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#endif // USE_PROTOBUF_USERMESSAGES
|
||||
}
|
||||
|
||||
bool UserMessages::EndMessage()
|
||||
@@ -191,12 +300,37 @@ bool UserMessages::EndMessage()
|
||||
return false;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||
delete m_FakeEngineBuffer;
|
||||
m_FakeEngineBuffer = NULL;
|
||||
} else {
|
||||
OnMessageEnd_Pre();
|
||||
|
||||
switch (m_FakeMetaRes)
|
||||
{
|
||||
case MRES_IGNORED:
|
||||
case MRES_HANDLED:
|
||||
case MRES_OVERRIDE:
|
||||
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||
delete m_FakeEngineBuffer;
|
||||
m_FakeEngineBuffer = NULL;
|
||||
break;
|
||||
//case MRES_SUPERCEDE:
|
||||
}
|
||||
|
||||
OnMessageEnd_Post();
|
||||
}
|
||||
#else
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
ENGINE_CALL(MessageEnd)();
|
||||
} else {
|
||||
engine->MessageEnd();
|
||||
}
|
||||
#endif // SE_CSGO
|
||||
|
||||
m_InExec = false;
|
||||
m_CurFlags = 0;
|
||||
@@ -205,31 +339,60 @@ bool UserMessages::EndMessage()
|
||||
return true;
|
||||
}
|
||||
|
||||
UserMessageType UserMessages::GetUserMessageType() const
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return UM_Protobuf;
|
||||
#else
|
||||
return UM_BitBuf;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::HookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept)
|
||||
{
|
||||
return InternalHook(msg_id, pListener, intercept, true);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
|
||||
#else
|
||||
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept)
|
||||
{
|
||||
return InternalUnhook(msg_id, pListener, intercept, true);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
|
||||
#else
|
||||
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
return InternalHook(msg_id, pListener, intercept, false);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||
#else
|
||||
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
return InternalUnhook(msg_id, pListener, intercept, false);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||
#else
|
||||
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#else
|
||||
bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#endif
|
||||
{
|
||||
if (msg_id < 0 || msg_id >= 255)
|
||||
{
|
||||
@@ -252,10 +415,15 @@ bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, boo
|
||||
|
||||
if (!m_HookCount++)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
|
||||
#else
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intercept)
|
||||
@@ -268,7 +436,11 @@ bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, boo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#else
|
||||
bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
#endif
|
||||
{
|
||||
MsgList *pList;
|
||||
MsgIter iter;
|
||||
@@ -309,14 +481,69 @@ void UserMessages::_DecRefCounter()
|
||||
{
|
||||
if (--m_HookCount == 0)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||
{
|
||||
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
{
|
||||
int size = msg.ByteSize();
|
||||
uint8 *data = (uint8 *)stackalloc(size);
|
||||
msg.SerializePartialToArray(data, size);
|
||||
m_InterceptBuffer->ParsePartialFromArray(data, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
|
||||
}
|
||||
|
||||
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||
|
||||
OnMessageEnd_Pre();
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||
{
|
||||
OnMessageEnd_Post();
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#define UM_RETURN_META_VALUE(res, val) \
|
||||
m_FakeMetaRes = res; \
|
||||
return val;
|
||||
|
||||
#define UM_RETURN_META(res) \
|
||||
m_FakeMetaRes = res; \
|
||||
return;
|
||||
#else
|
||||
#define UM_RETURN_META_VALUE(res, val) \
|
||||
RETURN_META_VALUE(res, val)
|
||||
|
||||
#define UM_RETURN_META(res) \
|
||||
RETURN_META(res)
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#else
|
||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
|
||||
@@ -329,7 +556,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
||||
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
||||
{
|
||||
m_InHook = false;
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
m_CurId = msg_type;
|
||||
@@ -339,14 +566,23 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
||||
|
||||
if (!is_intercept_empty)
|
||||
{
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
if (m_InterceptBuffer)
|
||||
delete m_InterceptBuffer;
|
||||
m_InterceptBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
|
||||
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
|
||||
#else
|
||||
m_InterceptBuffer.Reset();
|
||||
RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
||||
UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#else
|
||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
|
||||
@@ -354,19 +590,26 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
m_OrigBuffer = m_InterceptBuffer;
|
||||
else
|
||||
m_OrigBuffer = m_FakeEngineBuffer;
|
||||
#else
|
||||
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
|
||||
#endif
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
void UserMessages::OnMessageEnd_Post()
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
UM_RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
MsgList *pList;
|
||||
@@ -434,7 +677,7 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
UM_RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
MsgList *pList;
|
||||
@@ -450,7 +693,11 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
{
|
||||
pInfo = (*iter);
|
||||
pInfo->IsHooked = true;
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
|
||||
#else
|
||||
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
|
||||
#endif
|
||||
|
||||
intercepted = true;
|
||||
|
||||
@@ -496,16 +743,13 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
{
|
||||
goto supercede;
|
||||
}
|
||||
|
||||
if (intercepted)
|
||||
if (!handled && intercepted)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
||||
#else
|
||||
bf_write *engine_bfw;
|
||||
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
|
||||
#else
|
||||
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
|
||||
@@ -513,29 +757,46 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
||||
ENGINE_CALL(MessageEnd)();
|
||||
#endif // SE_CSGO
|
||||
}
|
||||
|
||||
pList = &m_msgHooks[m_CurId];
|
||||
for (iter=pList->begin(); iter!=pList->end(); )
|
||||
{
|
||||
pInfo = (*iter);
|
||||
pInfo->IsHooked = true;
|
||||
pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
int size = m_OrigBuffer->ByteSize();
|
||||
uint8 *data = (uint8 *)stackalloc(size);
|
||||
m_OrigBuffer->SerializePartialToArray(data, size);
|
||||
protobuf::Message *pTempMsg = g_Cstrike15UsermessageHelpers.GetPrototype(m_CurId)->New();
|
||||
pTempMsg->ParsePartialFromArray(data, size);
|
||||
#else
|
||||
bf_write *pTempMsg = m_OrigBuffer;
|
||||
#endif
|
||||
|
||||
if (pInfo->KillMe)
|
||||
pList = &m_msgHooks[m_CurId];
|
||||
for (iter=pList->begin(); iter!=pList->end(); )
|
||||
{
|
||||
iter = pList->erase(iter);
|
||||
m_FreeListeners.push(pInfo);
|
||||
_DecRefCounter();
|
||||
continue;
|
||||
pInfo = (*iter);
|
||||
pInfo->IsHooked = true;
|
||||
pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter);
|
||||
|
||||
if (pInfo->KillMe)
|
||||
{
|
||||
iter = pList->erase(iter);
|
||||
m_FreeListeners.push(pInfo);
|
||||
_DecRefCounter();
|
||||
continue;
|
||||
}
|
||||
|
||||
pInfo->IsHooked = false;
|
||||
iter++;
|
||||
}
|
||||
|
||||
pInfo->IsHooked = false;
|
||||
iter++;
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
delete pTempMsg;
|
||||
#endif
|
||||
}
|
||||
|
||||
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||
supercede:
|
||||
m_BlockEndPost = true;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
UM_RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
+52
-7
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -36,16 +36,35 @@
|
||||
#include <IUserMessages.h>
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_trie.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "CellRecipientFilter.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#define USE_PROTOBUF_USERMESSAGES
|
||||
#endif
|
||||
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <netmessages.pb.h>
|
||||
|
||||
using namespace google;
|
||||
#else
|
||||
#include <bitbuf.h>
|
||||
#endif
|
||||
|
||||
#define INVALID_MESSAGE_ID -1
|
||||
|
||||
struct ListenerInfo
|
||||
{
|
||||
IUserMessageListener *Callback;
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
IProtobufUserMessageListener *Callback;
|
||||
#else
|
||||
IBitBufUserMessageListener *Callback;
|
||||
#endif
|
||||
bool IsHooked;
|
||||
bool KillMe;
|
||||
bool IsNew;
|
||||
@@ -70,7 +89,8 @@ public: //IUserMessages
|
||||
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
||||
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||
bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||
bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||
google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
|
||||
bool EndMessage();
|
||||
bool HookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
@@ -78,8 +98,17 @@ public: //IUserMessages
|
||||
bool UnhookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept=false);
|
||||
UserMessageType GetUserMessageType() const;
|
||||
public:
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
#else
|
||||
@@ -89,24 +118,40 @@ public:
|
||||
void OnMessageEnd_Pre();
|
||||
void OnMessageEnd_Post();
|
||||
private:
|
||||
bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
#else
|
||||
bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
#endif
|
||||
void _DecRefCounter();
|
||||
private:
|
||||
List<ListenerInfo *> m_msgHooks[255];
|
||||
List<ListenerInfo *> m_msgIntercepts[255];
|
||||
CStack<ListenerInfo *> m_FreeListeners;
|
||||
unsigned char m_pBase[2500];
|
||||
IRecipientFilter *m_CurRecFilter;
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
unsigned char m_pBase[2500];
|
||||
bf_write m_InterceptBuffer;
|
||||
bf_write *m_OrigBuffer;
|
||||
bf_read m_ReadBuffer;
|
||||
#else
|
||||
// The engine used to provide this. Now we track it.
|
||||
protobuf::Message *m_OrigBuffer;
|
||||
protobuf::Message *m_FakeEngineBuffer;
|
||||
META_RES m_FakeMetaRes;
|
||||
|
||||
protobuf::Message *m_InterceptBuffer;
|
||||
#endif
|
||||
size_t m_HookCount;
|
||||
bool m_InHook;
|
||||
bool m_BlockEndPost;
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
bool m_FallbackSearch;
|
||||
|
||||
Trie *m_Names;
|
||||
#endif
|
||||
CellRecipientFilter m_CellRecFilter;
|
||||
bool m_InExec;
|
||||
int m_CurFlags;
|
||||
|
||||
+31
-2
@@ -39,6 +39,9 @@
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
#else
|
||||
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
#endif
|
||||
|
||||
using namespace SourceHook;
|
||||
@@ -51,29 +54,55 @@ struct ConCommandInfo
|
||||
};
|
||||
|
||||
List<ConCommandInfo *> tracked_bases;
|
||||
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
|
||||
|
||||
ConCommandBase *FindConCommandBase(const char *name);
|
||||
|
||||
class ConCommandCleaner : public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#else
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
||||
}
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LinkConCommandBase(ConCommandBase *pBase)
|
||||
{
|
||||
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||
while (listener)
|
||||
{
|
||||
listener->OnLinkConCommand(pBase);
|
||||
listener = listener->next;
|
||||
}
|
||||
}
|
||||
|
||||
void UnlinkConCommandBase(ConCommandBase *pBase)
|
||||
{
|
||||
ConCommandInfo *pInfo;
|
||||
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
||||
|
||||
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||
while (listener)
|
||||
{
|
||||
listener->OnUnlinkConCommand(pBase);
|
||||
listener = listener->next;
|
||||
}
|
||||
|
||||
if (pBase)
|
||||
{
|
||||
while (iter != tracked_bases.end())
|
||||
|
||||
@@ -42,4 +42,26 @@ void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
|
||||
|
||||
class IConCommandLinkListener
|
||||
{
|
||||
friend class ConCommandCleaner;
|
||||
|
||||
static IConCommandLinkListener *head;
|
||||
IConCommandLinkListener *next;
|
||||
public:
|
||||
IConCommandLinkListener()
|
||||
{
|
||||
next = head;
|
||||
head = this;
|
||||
}
|
||||
|
||||
virtual void OnLinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CONCMD_TRACKER_H_
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FORCEINLINE_CVAR FORCEINLINE
|
||||
#elif _LINUX
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
#define FORCEINLINE_CVAR inline
|
||||
#else
|
||||
#error "implement me"
|
||||
@@ -386,6 +386,9 @@ public:
|
||||
virtual void SetValue( const char *value );
|
||||
virtual void SetValue( float value );
|
||||
virtual void SetValue( int value );
|
||||
#if SOURCE_ENGINE >= SE_NUCLEARDAWN
|
||||
virtual void SetValue( Color value );
|
||||
#endif
|
||||
|
||||
// Reset to default value
|
||||
void Revert( void );
|
||||
@@ -401,6 +404,9 @@ private:
|
||||
// For CVARs marked FCVAR_NEVER_AS_STRING
|
||||
virtual void InternalSetFloatValue( float fNewValue );
|
||||
virtual void InternalSetIntValue( int nValue );
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD2
|
||||
virtual void InternalSetColorValue( Color value );
|
||||
#endif
|
||||
|
||||
virtual bool ClampValue( float& value );
|
||||
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FORCEINLINE_CVAR FORCEINLINE
|
||||
#elif _LINUX
|
||||
#elif defined _LINUX || defined __APPLE__
|
||||
#define FORCEINLINE_CVAR inline
|
||||
#else
|
||||
#error "implement me"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@
|
||||
#include "PlayerManager.h"
|
||||
#include "CoreConfig.h"
|
||||
#include <sm_queue.h>
|
||||
#include "ThreadSupport.h"
|
||||
#include <IThreader.h>
|
||||
|
||||
static IMutex *frame_mutex;
|
||||
static Queue<FrameAction> *frame_queue;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
|
||||
compiler = SM.DefaultCompiler()
|
||||
base = AMBuild.sourceFolder
|
||||
compiler['CXXINCLUDES'].append(os.path.join(SM.mmsPath, 'core', 'sourcehook'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(base, 'core', 'logic'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(base, 'public'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'sourcepawn'))
|
||||
compiler['CDEFINES'].append('SM_DEFAULT_THREADER')
|
||||
compiler['CDEFINES'].append('SM_LOGIC')
|
||||
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
compiler['POSTLINKFLAGS'].append('-lpthread')
|
||||
if AMBuild.target['platform'] == 'darwin':
|
||||
compiler['CFLAGS'].extend(['-Wno-deprecated-declarations'])
|
||||
compiler['POSTLINKFLAGS'].extend(['-framework', 'CoreServices'])
|
||||
|
||||
extension = AMBuild.AddJob('sourcemod.logic')
|
||||
binary = Cpp.LibraryBuilder('sourcemod.logic', AMBuild, extension, compiler)
|
||||
files = [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
'smn_sorting.cpp',
|
||||
'smn_maplists.cpp',
|
||||
'smn_adt_stack.cpp',
|
||||
'thread/ThreadWorker.cpp',
|
||||
'thread/BaseWorker.cpp',
|
||||
'ThreadSupport.cpp',
|
||||
'smn_float.cpp',
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'Profiler.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
'MemoryUtils.cpp',
|
||||
'smn_admin.cpp',
|
||||
'smn_banning.cpp',
|
||||
'stringutil.cpp',
|
||||
'Translator.cpp',
|
||||
'PhraseCollection.cpp',
|
||||
'smn_lang.cpp',
|
||||
'smn_string.cpp',
|
||||
'smn_handles.cpp',
|
||||
'smn_datapacks.cpp',
|
||||
'smn_gameconfigs.cpp',
|
||||
'GameConfigs.cpp',
|
||||
'sm_crc32.cpp',
|
||||
'smn_profiler.cpp'
|
||||
]
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
files.append('thread/WinThreads.cpp')
|
||||
else:
|
||||
files.append('thread/PosixThreads.cpp')
|
||||
binary.AddSourceFiles('core/logic', files)
|
||||
SM.AutoVersion('core/logic', binary)
|
||||
SM.ExtractDebugInfo(extension, binary)
|
||||
binary.SendToJob()
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
|
||||
#define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <IHandleSys.h>
|
||||
|
||||
class AutoHandleRooter
|
||||
{
|
||||
public:
|
||||
AutoHandleRooter(Handle_t hndl)
|
||||
{
|
||||
if (hndl != BAD_HANDLE)
|
||||
this->hndl = handlesys->FastCloneHandle(hndl);
|
||||
else
|
||||
this->hndl = BAD_HANDLE;
|
||||
}
|
||||
|
||||
~AutoHandleRooter()
|
||||
{
|
||||
if (hndl != BAD_HANDLE)
|
||||
{
|
||||
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
|
||||
handlesys->FreeHandle(hndl, &sec);
|
||||
}
|
||||
}
|
||||
|
||||
Handle_t getHandle()
|
||||
{
|
||||
return hndl;
|
||||
}
|
||||
private:
|
||||
Handle_t hndl;
|
||||
};
|
||||
|
||||
class AutoHandleCloner
|
||||
{
|
||||
Handle_t original;
|
||||
HandleSecurity sec;
|
||||
AutoHandleRooter ahr;
|
||||
public:
|
||||
AutoHandleCloner(Handle_t original, HandleSecurity sec)
|
||||
: original(original), sec(sec), ahr(original)
|
||||
{
|
||||
}
|
||||
|
||||
~AutoHandleCloner()
|
||||
{
|
||||
if (original != BAD_HANDLE)
|
||||
{
|
||||
handlesys->FreeHandle(original, &sec);
|
||||
}
|
||||
}
|
||||
|
||||
Handle_t getClone()
|
||||
{
|
||||
return ahr.getHandle();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_ */
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CELLARRAY_H_
|
||||
#define _INCLUDE_SOURCEMOD_CELLARRAY_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -204,3 +207,6 @@ private:
|
||||
size_t m_AllocSize;
|
||||
size_t m_Size;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_CELLARRAY_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,14 +32,12 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
||||
#define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <IGameConfigs.h>
|
||||
#include <ITextParsers.h>
|
||||
#include <sh_list.h>
|
||||
#include "sm_trie.h"
|
||||
#include "sm_globals.h"
|
||||
#include "sm_memtable.h"
|
||||
#include "sm_trie_tpl.h"
|
||||
#include "ThreadSupport.h"
|
||||
#include <sm_trie_tpl.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourceHook;
|
||||
@@ -52,11 +50,13 @@ class CGameConfig :
|
||||
{
|
||||
friend class GameConfigManager;
|
||||
public:
|
||||
CGameConfig(const char *file);
|
||||
CGameConfig(const char *file, const char *engine = NULL);
|
||||
~CGameConfig();
|
||||
public:
|
||||
bool Reparse(char *error, size_t maxlength);
|
||||
bool EnterFile(const char *file, char *error, size_t maxlength);
|
||||
void SetBaseEngine(const char *engine);
|
||||
void SetParseEngine(const char *engine);
|
||||
public: //ITextListener_SMC
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
@@ -66,6 +66,7 @@ public: //IGameConfig
|
||||
bool GetOffset(const char *key, int *value);
|
||||
SendProp *GetSendProp(const char *key);
|
||||
bool GetMemSig(const char *key, void **addr);
|
||||
bool GetAddress(const char *key, void **addr);
|
||||
public:
|
||||
void IncRefCount();
|
||||
unsigned int DecRefCount();
|
||||
@@ -73,10 +74,10 @@ private:
|
||||
BaseStringTable *m_pStrings;
|
||||
char m_File[PLATFORM_MAX_PATH];
|
||||
char m_CurFile[PLATFORM_MAX_PATH];
|
||||
Trie *m_pOffsets;
|
||||
Trie *m_pProps;
|
||||
Trie *m_pKeys;
|
||||
Trie *m_pSigs;
|
||||
KTrie<int> m_Offsets;
|
||||
KTrie<SendProp *> m_Props;
|
||||
KTrie<int> m_Keys;
|
||||
KTrie<void *> m_Sigs;
|
||||
unsigned int m_RefCount;
|
||||
/* Parse states */
|
||||
int m_ParseState;
|
||||
@@ -94,6 +95,26 @@ private:
|
||||
/* Custom Sections */
|
||||
unsigned int m_CustomLevel;
|
||||
ITextListener_SMC *m_CustomHandler;
|
||||
|
||||
/* Support for reading Addresses */
|
||||
struct AddressConf
|
||||
{
|
||||
char signatureName[64];
|
||||
int readCount;
|
||||
int read[8];
|
||||
|
||||
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
|
||||
|
||||
AddressConf() {}
|
||||
};
|
||||
|
||||
char m_Address[64];
|
||||
char m_AddressSignature[64];
|
||||
int m_AddressReadCount;
|
||||
int m_AddressRead[8];
|
||||
KTrie<AddressConf> *m_pAddresses;
|
||||
const char *m_pEngine;
|
||||
const char *m_pBaseEngine;
|
||||
};
|
||||
|
||||
class GameConfigManager :
|
||||
@@ -119,7 +140,7 @@ public: //SMGlobalClass
|
||||
void OnSourceModAllShutdown();
|
||||
private:
|
||||
List<CGameConfig *> m_cfgs;
|
||||
Trie *m_pLookup;
|
||||
KTrie<CGameConfig *> m_Lookup;
|
||||
public:
|
||||
KTrie<ITextListener_SMC *> m_customHandlers;
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
# (C)2004-2008 SourceMod Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
SMSDK = ../..
|
||||
MMSOURCE17 = ../../../mmsource-1.7
|
||||
|
||||
#####################################
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
#####################################
|
||||
|
||||
BINARY = sourcemod.logic.so
|
||||
|
||||
OBJECTS = \
|
||||
common_logic.cpp \
|
||||
smn_adt_array.cpp \
|
||||
smn_sorting.cpp \
|
||||
smn_maplists.cpp \
|
||||
smn_adt_stack.cpp \
|
||||
thread/ThreadWorker.cpp \
|
||||
thread/BaseWorker.cpp \
|
||||
thread/PosixThreads.cpp \
|
||||
ThreadSupport.cpp \
|
||||
smn_float.cpp \
|
||||
TextParsers.cpp \
|
||||
smn_textparse.cpp \
|
||||
smn_adt_trie.cpp \
|
||||
Profiler.cpp \
|
||||
smn_functions.cpp \
|
||||
sm_crc32.cpp \
|
||||
smn_timers.cpp \
|
||||
MemoryUtils.cpp \
|
||||
smn_admin.cpp \
|
||||
smn_banning.cpp \
|
||||
stringutil.cpp \
|
||||
Translator.cpp \
|
||||
PhraseCollection.cpp \
|
||||
smn_lang.cpp \
|
||||
smn_string.cpp \
|
||||
smn_handles.cpp \
|
||||
smn_datapacks.cpp \
|
||||
smn_gameconfigs.cpp \
|
||||
GameConfigs.cpp \
|
||||
smn_players.cpp \
|
||||
smn_profiler.cpp
|
||||
|
||||
##############################################
|
||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||
##############################################
|
||||
|
||||
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
|
||||
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
|
||||
C_GCC4_FLAGS = -fvisibility=hidden
|
||||
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
|
||||
CPP = gcc
|
||||
|
||||
LINK += -lpthread -static-libgcc
|
||||
|
||||
INCLUDE += -I. -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
|
||||
|
||||
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
|
||||
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
|
||||
-Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32 \
|
||||
-DSM_LOGIC
|
||||
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
||||
|
||||
################################################
|
||||
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
|
||||
################################################
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
BIN_DIR = Debug
|
||||
CFLAGS += $(C_DEBUG_FLAGS)
|
||||
else
|
||||
BIN_DIR = Release
|
||||
CFLAGS += $(C_OPT_FLAGS)
|
||||
endif
|
||||
|
||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||
ifeq "$(GCC_VERSION)" "4"
|
||||
CFLAGS += $(C_GCC4_FLAGS)
|
||||
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
||||
endif
|
||||
|
||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||
|
||||
$(BIN_DIR)/%.o: %.c
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)/thread
|
||||
$(MAKE) -f Makefile sourcemod
|
||||
|
||||
sourcemod: $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o $(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) -f Makefile all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf $(BIN_DIR)/*.o
|
||||
rm -rf $(BIN_DIR)/thread/*.o
|
||||
rm -rf $(BIN_DIR)/$(BINARY)
|
||||
@@ -0,0 +1,612 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#include "MemoryUtils.h"
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <fcntl.h>
|
||||
#include <link.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_APPLE
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach-o/dyld_images.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/nlist.h>
|
||||
|
||||
/* Define things from 10.6 SDK for older SDKs */
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
struct task_dyld_info
|
||||
{
|
||||
mach_vm_address_t all_image_info_addr;
|
||||
mach_vm_size_t all_image_info_size;
|
||||
};
|
||||
typedef struct task_dyld_info task_dyld_info_data_t;
|
||||
#define TASK_DYLD_INFO 17
|
||||
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
|
||||
#endif // MAC_OS_X_VERSION_10_6
|
||||
#endif // PLATFORM_APPLE
|
||||
|
||||
MemoryUtils g_MemUtils;
|
||||
|
||||
MemoryUtils::MemoryUtils()
|
||||
{
|
||||
#ifdef PLATFORM_APPLE
|
||||
|
||||
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
|
||||
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);
|
||||
|
||||
/* Get pointer to struct that describes all loaded mach-o images in process */
|
||||
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
|
||||
{
|
||||
task_dyld_info_data_t dyld_info;
|
||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
||||
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct nlist list[2];
|
||||
memset(list, 0, sizeof(list));
|
||||
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
|
||||
nlist("/usr/lib/dyld", list);
|
||||
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
MemoryUtils::~MemoryUtils()
|
||||
{
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
for (size_t i = 0; i < m_SymTables.size(); i++)
|
||||
{
|
||||
delete m_SymTables[i];
|
||||
}
|
||||
m_SymTables.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryUtils::OnSourceModAllInitialized()
|
||||
{
|
||||
sharesys->AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
|
||||
{
|
||||
DynLibInfo lib;
|
||||
bool found;
|
||||
char *ptr, *end;
|
||||
|
||||
memset(&lib, 0, sizeof(DynLibInfo));
|
||||
|
||||
if (!GetLibraryInfo(libPtr, lib))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = reinterpret_cast<char *>(lib.baseAddress);
|
||||
end = ptr + lib.memorySize - len;
|
||||
|
||||
while (ptr < end)
|
||||
{
|
||||
found = true;
|
||||
for (register size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return ptr;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
return GetProcAddress((HMODULE)handle, symbol);
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
struct link_map *dlmap;
|
||||
struct stat dlstat;
|
||||
int dlfile;
|
||||
uintptr_t map_base;
|
||||
Elf32_Ehdr *file_hdr;
|
||||
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
||||
Elf32_Sym *symtab;
|
||||
const char *shstrtab, *strtab;
|
||||
uint16_t section_count;
|
||||
uint32_t symbol_count;
|
||||
LibSymbolTable *libtable;
|
||||
SymbolTable *table;
|
||||
Symbol *symbol_entry;
|
||||
|
||||
dlmap = (struct link_map *)handle;
|
||||
symtab_hdr = NULL;
|
||||
strtab_hdr = NULL;
|
||||
table = NULL;
|
||||
|
||||
/* See if we already have a symbol table for this library */
|
||||
for (size_t i = 0; i < m_SymTables.size(); i++)
|
||||
{
|
||||
libtable = m_SymTables[i];
|
||||
if (libtable->lib_base == dlmap->l_addr)
|
||||
{
|
||||
table = &libtable->table;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a symbol table for this library, then create one */
|
||||
if (table == NULL)
|
||||
{
|
||||
libtable = new LibSymbolTable();
|
||||
libtable->table.Initialize();
|
||||
libtable->lib_base = dlmap->l_addr;
|
||||
libtable->last_pos = 0;
|
||||
table = &libtable->table;
|
||||
m_SymTables.push_back(libtable);
|
||||
}
|
||||
|
||||
/* See if the symbol is already cached in our table */
|
||||
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
|
||||
if (symbol_entry != NULL)
|
||||
{
|
||||
return symbol_entry->address;
|
||||
}
|
||||
|
||||
/* If symbol isn't in our table, then we have open the actual library */
|
||||
dlfile = open(dlmap->l_name, O_RDONLY);
|
||||
if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
|
||||
{
|
||||
close(dlfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Map library file into memory */
|
||||
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
||||
map_base = (uintptr_t)file_hdr;
|
||||
if (file_hdr == MAP_FAILED)
|
||||
{
|
||||
close(dlfile);
|
||||
return NULL;
|
||||
}
|
||||
close(dlfile);
|
||||
|
||||
if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
|
||||
{
|
||||
munmap(file_hdr, dlstat.st_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
|
||||
section_count = file_hdr->e_shnum;
|
||||
/* Get ELF section header string table */
|
||||
shstrtab_hdr = §ions[file_hdr->e_shstrndx];
|
||||
shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);
|
||||
|
||||
/* Iterate sections while looking for ELF symbol table and string table */
|
||||
for (uint16_t i = 0; i < section_count; i++)
|
||||
{
|
||||
Elf32_Shdr &hdr = sections[i];
|
||||
const char *section_name = shstrtab + hdr.sh_name;
|
||||
|
||||
if (strcmp(section_name, ".symtab") == 0)
|
||||
{
|
||||
symtab_hdr = &hdr;
|
||||
}
|
||||
else if (strcmp(section_name, ".strtab") == 0)
|
||||
{
|
||||
strtab_hdr = &hdr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Uh oh, we don't have a symbol table or a string table */
|
||||
if (symtab_hdr == NULL || strtab_hdr == NULL)
|
||||
{
|
||||
munmap(file_hdr, dlstat.st_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
|
||||
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
|
||||
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
|
||||
|
||||
/* Iterate symbol table starting from the position we were at last time */
|
||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||
{
|
||||
Elf32_Sym &sym = symtab[i];
|
||||
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
|
||||
const char *sym_name = strtab + sym.st_name;
|
||||
Symbol *cur_sym;
|
||||
|
||||
/* Skip symbols that are undefined or do not refer to functions or objects */
|
||||
if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Caching symbols as we go along */
|
||||
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value));
|
||||
if (strcmp(symbol, sym_name) == 0)
|
||||
{
|
||||
symbol_entry = cur_sym;
|
||||
libtable->last_pos = ++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
munmap(file_hdr, dlstat.st_size);
|
||||
return symbol_entry ? symbol_entry->address : NULL;
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
uintptr_t dlbase, linkedit_addr;
|
||||
uint32_t image_count;
|
||||
struct mach_header *file_hdr;
|
||||
struct load_command *loadcmds;
|
||||
struct segment_command *linkedit_hdr;
|
||||
struct symtab_command *symtab_hdr;
|
||||
struct nlist *symtab;
|
||||
const char *strtab;
|
||||
uint32_t loadcmd_count;
|
||||
uint32_t symbol_count;
|
||||
LibSymbolTable *libtable;
|
||||
SymbolTable *table;
|
||||
Symbol *symbol_entry;
|
||||
|
||||
dlbase = 0;
|
||||
image_count = m_ImageList->infoArrayCount;
|
||||
linkedit_hdr = NULL;
|
||||
symtab_hdr = NULL;
|
||||
table = NULL;
|
||||
|
||||
/* Loop through mach-o images in process.
|
||||
* We can skip index 0 since that is just the executable.
|
||||
*/
|
||||
for (uint32_t i = 1; i < image_count; i++)
|
||||
{
|
||||
const struct dyld_image_info &info = m_ImageList->infoArray[i];
|
||||
|
||||
/* "Load" each one until we get a matching handle */
|
||||
void *h = dlopen(info.imageFilePath, RTLD_NOLOAD);
|
||||
if (h == handle)
|
||||
{
|
||||
dlbase = (uintptr_t)info.imageLoadAddress;
|
||||
dlclose(h);
|
||||
break;
|
||||
}
|
||||
|
||||
dlclose(h);
|
||||
}
|
||||
|
||||
if (!dlbase)
|
||||
{
|
||||
/* Uh oh, we couldn't find a matching handle */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* See if we already have a symbol table for this library */
|
||||
for (size_t i = 0; i < m_SymTables.size(); i++)
|
||||
{
|
||||
libtable = m_SymTables[i];
|
||||
if (libtable->lib_base == dlbase)
|
||||
{
|
||||
table = &libtable->table;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a symbol table for this library, then create one */
|
||||
if (table == NULL)
|
||||
{
|
||||
libtable = new LibSymbolTable();
|
||||
libtable->table.Initialize();
|
||||
libtable->lib_base = dlbase;
|
||||
libtable->last_pos = 0;
|
||||
table = &libtable->table;
|
||||
m_SymTables.push_back(libtable);
|
||||
}
|
||||
|
||||
/* See if the symbol is already cached in our table */
|
||||
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
|
||||
if (symbol_entry != NULL)
|
||||
{
|
||||
return symbol_entry->address;
|
||||
}
|
||||
|
||||
/* If symbol isn't in our table, then we have to locate it in memory */
|
||||
|
||||
file_hdr = (struct mach_header *)dlbase;
|
||||
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
|
||||
loadcmd_count = file_hdr->ncmds;
|
||||
|
||||
/* Loop through load commands until we find the ones for the symbol table */
|
||||
for (uint32_t i = 0; i < loadcmd_count; i++)
|
||||
{
|
||||
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
|
||||
{
|
||||
struct segment_command *seg = (struct segment_command *)loadcmds;
|
||||
if (strcmp(seg->segname, "__LINKEDIT") == 0)
|
||||
{
|
||||
linkedit_hdr = seg;
|
||||
if (symtab_hdr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (loadcmds->cmd == LC_SYMTAB)
|
||||
{
|
||||
symtab_hdr = (struct symtab_command *)loadcmds;
|
||||
if (linkedit_hdr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load commands are not of a fixed size which is why we add the size */
|
||||
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
||||
}
|
||||
|
||||
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
|
||||
{
|
||||
/* Uh oh, no symbol table */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
|
||||
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
||||
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
|
||||
symbol_count = symtab_hdr->nsyms;
|
||||
|
||||
/* Iterate symbol table starting from the position we were at last time */
|
||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||
{
|
||||
struct nlist &sym = symtab[i];
|
||||
/* Ignore the prepended underscore on all symbols, so +1 here */
|
||||
const char *sym_name = strtab + sym.n_un.n_strx + 1;
|
||||
Symbol *cur_sym;
|
||||
|
||||
/* Skip symbols that are undefined */
|
||||
if (sym.n_sect == NO_SECT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Caching symbols as we go along */
|
||||
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlbase + sym.n_value));
|
||||
if (strcmp(symbol, sym_name) == 0)
|
||||
{
|
||||
symbol_entry = cur_sym;
|
||||
libtable->last_pos = ++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return symbol_entry ? symbol_entry->address : NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
{
|
||||
uintptr_t baseAddr;
|
||||
|
||||
if (libPtr == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *pe;
|
||||
IMAGE_FILE_HEADER *file;
|
||||
IMAGE_OPTIONAL_HEADER *opt;
|
||||
|
||||
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
baseAddr = reinterpret_cast<uintptr_t>(info.AllocationBase);
|
||||
|
||||
/* All this is for our insane sanity checks :o */
|
||||
dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr);
|
||||
pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew);
|
||||
file = &pe->FileHeader;
|
||||
opt = &pe->OptionalHeader;
|
||||
|
||||
/* Check PE magic and signature */
|
||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library */
|
||||
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Finally, we can do this */
|
||||
lib.memorySize = opt->SizeOfImage;
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
Dl_info info;
|
||||
Elf32_Ehdr *file;
|
||||
Elf32_Phdr *phdr;
|
||||
uint16_t phdrCount;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info.dli_fbase || !info.dli_fname)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
|
||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
||||
|
||||
/* Check ELF magic */
|
||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF version */
|
||||
if (file->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library/shared object */
|
||||
if (file->e_type != ET_DYN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
phdrCount = file->e_phnum;
|
||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
||||
|
||||
for (uint16_t i = 0; i < phdrCount; i++)
|
||||
{
|
||||
Elf32_Phdr &hdr = phdr[i];
|
||||
|
||||
/* We only really care about the segment with executable code */
|
||||
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
|
||||
{
|
||||
/* From glibc, elf/dl-load.c:
|
||||
* c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1)
|
||||
* & ~(GLRO(dl_pagesize) - 1));
|
||||
*
|
||||
* In glibc, the segment file size is aligned up to the nearest page size and
|
||||
* added to the virtual address of the segment. We just want the size here.
|
||||
*/
|
||||
lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
Dl_info info;
|
||||
struct mach_header *file;
|
||||
struct segment_command *seg;
|
||||
uint32_t cmd_count;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info.dli_fbase || !info.dli_fname)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = (uintptr_t)info.dli_fbase;
|
||||
file = (struct mach_header *)baseAddr;
|
||||
|
||||
/* Check Mach-O magic */
|
||||
if (file->magic != MH_MAGIC)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture (32-bit/x86) */
|
||||
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library */
|
||||
if (file->filetype != MH_DYLIB)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd_count = file->ncmds;
|
||||
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header));
|
||||
|
||||
/* Add up memory sizes of mapped segments */
|
||||
for (uint32_t i = 0; i < cmd_count; i++)
|
||||
{
|
||||
if (seg->cmd == LC_SEGMENT)
|
||||
{
|
||||
lib.memorySize += seg->vmsize;
|
||||
}
|
||||
|
||||
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,34 +25,64 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
||||
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <IMemoryUtils.h>
|
||||
#include "sm_globals.h"
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
#include <sh_vector.h>
|
||||
#include "sm_symtable.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
#endif
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
#ifdef PLATFORM_APPLE
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
struct DynLibInfo
|
||||
{
|
||||
void *baseAddress;
|
||||
size_t memorySize;
|
||||
};
|
||||
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
struct LibSymbolTable
|
||||
{
|
||||
SymbolTable table;
|
||||
uintptr_t lib_base;
|
||||
uint32_t last_pos;
|
||||
};
|
||||
#endif
|
||||
|
||||
class MemoryUtils :
|
||||
public IMemoryUtils,
|
||||
public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
MemoryUtils();
|
||||
~MemoryUtils();
|
||||
public: // SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
public: // IMemoryUtils
|
||||
void *FindPattern(const void *libPtr, const char *pattern, size_t len);
|
||||
private:
|
||||
void *ResolveSymbol(void *handle, const char *symbol);
|
||||
public:
|
||||
bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
private:
|
||||
CVector<LibSymbolTable *> m_SymTables;
|
||||
#ifdef PLATFORM_APPLE
|
||||
struct dyld_all_image_infos *m_ImageList;
|
||||
SInt32 m_OSXMajor;
|
||||
SInt32 m_OSXMinor;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
extern MemoryUtils g_MemUtils;
|
||||
@@ -0,0 +1,399 @@
|
||||
// MersenneTwister.h
|
||||
// Mersenne Twister random number generator -- a C++ class MTRand
|
||||
// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
|
||||
// Richard J. Wagner v1.0 15 May 2003 [email protected]
|
||||
|
||||
// The Mersenne Twister is an algorithm for generating random numbers. It
|
||||
// was designed with consideration of the flaws in various other generators.
|
||||
// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
|
||||
// are far greater. The generator is also fast; it avoids multiplication and
|
||||
// division, and it benefits from caches and pipelines. For more information
|
||||
// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
|
||||
|
||||
// Reference
|
||||
// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
|
||||
// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
|
||||
// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
|
||||
|
||||
// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
// Copyright (C) 2000 - 2003, Richard J. Wagner
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The names of its contributors may not be used to endorse or promote
|
||||
// products derived from this software without specific prior written
|
||||
// permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The original code included the following notice:
|
||||
//
|
||||
// When you use this, send an email to: [email protected]
|
||||
// with an appropriate reference to your work.
|
||||
//
|
||||
// It would be nice to CC: [email protected] and [email protected]
|
||||
// when you write.
|
||||
|
||||
#ifndef MERSENNETWISTER_H
|
||||
#define MERSENNETWISTER_H
|
||||
|
||||
// Not thread safe (unless auto-initialization is avoided and each thread has
|
||||
// its own MTRand object)
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
class MTRand {
|
||||
// Data
|
||||
public:
|
||||
typedef unsigned long uint32; // unsigned integer type, at least 32 bits
|
||||
|
||||
enum { N = 624 }; // length of state vector
|
||||
enum { SAVE = N + 1 }; // length of array for save()
|
||||
|
||||
protected:
|
||||
enum { M = 397 }; // period parameter
|
||||
|
||||
uint32 state[N]; // internal state
|
||||
uint32 *pNext; // next value to get from state
|
||||
int left; // number of values left before reload needed
|
||||
|
||||
|
||||
//Methods
|
||||
public:
|
||||
MTRand( const uint32& oneSeed ); // initialize with a simple uint32
|
||||
MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
|
||||
MTRand(); // auto-initialize with /dev/urandom or time() and clock()
|
||||
|
||||
// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
|
||||
// values together, otherwise the generator state can be learned after
|
||||
// reading 624 consecutive values.
|
||||
|
||||
// Access to 32-bit random numbers
|
||||
double rand(); // real number in [0,1]
|
||||
double rand( const double& n ); // real number in [0,n]
|
||||
double randExc(); // real number in [0,1)
|
||||
double randExc( const double& n ); // real number in [0,n)
|
||||
double randDblExc(); // real number in (0,1)
|
||||
double randDblExc( const double& n ); // real number in (0,n)
|
||||
uint32 randInt(); // integer in [0,2^32-1]
|
||||
uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
|
||||
double operator()() { return rand(); } // same as rand()
|
||||
|
||||
// Access to 53-bit random numbers (capacity of IEEE double precision)
|
||||
double rand53(); // real number in [0,1)
|
||||
|
||||
// Access to nonuniform random number distributions
|
||||
double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
|
||||
|
||||
// Re-seeding functions with same behavior as initializers
|
||||
void seed( const uint32 oneSeed );
|
||||
void seed( uint32 *const bigSeed, const uint32 seedLength = N );
|
||||
void seed();
|
||||
|
||||
// Saving and loading generator state
|
||||
void save( uint32* saveArray ) const; // to array of size SAVE
|
||||
void load( uint32 *const loadArray ); // from such array
|
||||
protected:
|
||||
void initialize( const uint32 oneSeed );
|
||||
void reload();
|
||||
uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
|
||||
uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
|
||||
uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
|
||||
uint32 mixBits( const uint32& u, const uint32& v ) const
|
||||
{ return hiBit(u) | loBits(v); }
|
||||
uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
|
||||
{ return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
|
||||
static uint32 hash( time_t t, clock_t c );
|
||||
};
|
||||
|
||||
|
||||
inline MTRand::MTRand( const uint32& oneSeed )
|
||||
{ seed(oneSeed); }
|
||||
|
||||
inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
|
||||
{ seed(bigSeed,seedLength); }
|
||||
|
||||
inline MTRand::MTRand()
|
||||
{ seed(); }
|
||||
|
||||
inline double MTRand::rand()
|
||||
{ return double(randInt()) * (1.0/4294967295.0); }
|
||||
|
||||
inline double MTRand::rand( const double& n )
|
||||
{ return rand() * n; }
|
||||
|
||||
inline double MTRand::randExc()
|
||||
{ return double(randInt()) * (1.0/4294967296.0); }
|
||||
|
||||
inline double MTRand::randExc( const double& n )
|
||||
{ return randExc() * n; }
|
||||
|
||||
inline double MTRand::randDblExc()
|
||||
{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
|
||||
|
||||
inline double MTRand::randDblExc( const double& n )
|
||||
{ return randDblExc() * n; }
|
||||
|
||||
inline double MTRand::rand53()
|
||||
{
|
||||
uint32 a = randInt() >> 5, b = randInt() >> 6;
|
||||
return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
|
||||
}
|
||||
|
||||
inline double MTRand::randNorm( const double& mean, const double& variance )
|
||||
{
|
||||
// Return a real number from a normal (Gaussian) distribution with given
|
||||
// mean and variance by Box-Muller method
|
||||
double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
|
||||
double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
|
||||
return mean + r * cos(phi);
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::randInt()
|
||||
{
|
||||
// Pull a 32-bit integer from the generator state
|
||||
// Every other access function simply transforms the numbers extracted here
|
||||
|
||||
if( left == 0 ) reload();
|
||||
--left;
|
||||
|
||||
register uint32 s1;
|
||||
s1 = *pNext++;
|
||||
s1 ^= (s1 >> 11);
|
||||
s1 ^= (s1 << 7) & 0x9d2c5680UL;
|
||||
s1 ^= (s1 << 15) & 0xefc60000UL;
|
||||
return ( s1 ^ (s1 >> 18) );
|
||||
}
|
||||
|
||||
inline MTRand::uint32 MTRand::randInt( const uint32& n )
|
||||
{
|
||||
// Find which bits are used in n
|
||||
// Optimized by Magnus Jonsson ([email protected])
|
||||
uint32 used = n;
|
||||
used |= used >> 1;
|
||||
used |= used >> 2;
|
||||
used |= used >> 4;
|
||||
used |= used >> 8;
|
||||
used |= used >> 16;
|
||||
|
||||
// Draw numbers until one is found in [0,n]
|
||||
uint32 i;
|
||||
do
|
||||
i = randInt() & used; // toss unused bits to shorten search
|
||||
while( i > n );
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::seed( const uint32 oneSeed )
|
||||
{
|
||||
// Seed the generator with a simple uint32
|
||||
initialize(oneSeed);
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
|
||||
{
|
||||
// Seed the generator with an array of uint32's
|
||||
// There are 2^19937-1 possible initial states. This function allows
|
||||
// all of those to be accessed by providing at least 19937 bits (with a
|
||||
// default seed length of N = 624 uint32's). Any bits above the lower 32
|
||||
// in each element are discarded.
|
||||
// Just call seed() if you want to get array from /dev/urandom
|
||||
initialize(19650218UL);
|
||||
register int i = 1;
|
||||
register uint32 j = 0;
|
||||
register int k = ( N > seedLength ? N : seedLength );
|
||||
for( ; k; --k )
|
||||
{
|
||||
state[i] =
|
||||
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
|
||||
state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
|
||||
state[i] &= 0xffffffffUL;
|
||||
++i; ++j;
|
||||
if( i >= N ) { state[0] = state[N-1]; i = 1; }
|
||||
if( j >= seedLength ) j = 0;
|
||||
}
|
||||
for( k = N - 1; k; --k )
|
||||
{
|
||||
state[i] =
|
||||
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
|
||||
state[i] -= i;
|
||||
state[i] &= 0xffffffffUL;
|
||||
++i;
|
||||
if( i >= N ) { state[0] = state[N-1]; i = 1; }
|
||||
}
|
||||
state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
|
||||
reload();
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::seed()
|
||||
{
|
||||
// Seed the generator with an array from /dev/urandom if available
|
||||
// Otherwise use a hash of time() and clock() values
|
||||
|
||||
// First try getting an array from /dev/urandom
|
||||
FILE* urandom = fopen( "/dev/urandom", "rb" );
|
||||
if( urandom )
|
||||
{
|
||||
uint32 bigSeed[N];
|
||||
register uint32 *s = bigSeed;
|
||||
register int i = N;
|
||||
register bool success = true;
|
||||
while( success && i-- )
|
||||
success = fread( s++, sizeof(uint32), 1, urandom );
|
||||
fclose(urandom);
|
||||
if( success ) { seed( bigSeed, N ); return; }
|
||||
}
|
||||
|
||||
// Was not successful, so use time() and clock() instead
|
||||
seed( hash( time(NULL), clock() ) );
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::initialize( const uint32 seed )
|
||||
{
|
||||
// Initialize generator state with seed
|
||||
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
|
||||
// In previous versions, most significant bits (MSBs) of the seed affect
|
||||
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
|
||||
register uint32 *s = state;
|
||||
register uint32 *r = state;
|
||||
register int i = 1;
|
||||
*s++ = seed & 0xffffffffUL;
|
||||
for( ; i < N; ++i )
|
||||
{
|
||||
*s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::reload()
|
||||
{
|
||||
// Generate N new values in state
|
||||
// Made clearer and faster by Matthew Bellew ([email protected])
|
||||
register uint32 *p = state;
|
||||
register int i;
|
||||
for( i = N - M; i--; ++p )
|
||||
*p = twist( p[M], p[0], p[1] );
|
||||
for( i = M; --i; ++p )
|
||||
*p = twist( p[M-N], p[0], p[1] );
|
||||
*p = twist( p[M-N], p[0], state[0] );
|
||||
|
||||
left = N, pNext = state;
|
||||
}
|
||||
|
||||
|
||||
inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
|
||||
{
|
||||
// Get a uint32 from t and c
|
||||
// Better than uint32(x) in case x is floating point in [0,1]
|
||||
// Based on code by Lawrence Kirby ([email protected])
|
||||
|
||||
static uint32 differ = 0; // guarantee time-based seeds will change
|
||||
|
||||
uint32 h1 = 0;
|
||||
unsigned char *p = (unsigned char *) &t;
|
||||
for( size_t i = 0; i < sizeof(t); ++i )
|
||||
{
|
||||
h1 *= UCHAR_MAX + 2U;
|
||||
h1 += p[i];
|
||||
}
|
||||
uint32 h2 = 0;
|
||||
p = (unsigned char *) &c;
|
||||
for( size_t j = 0; j < sizeof(c); ++j )
|
||||
{
|
||||
h2 *= UCHAR_MAX + 2U;
|
||||
h2 += p[j];
|
||||
}
|
||||
return ( h1 + differ++ ) ^ h2;
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::save( uint32* saveArray ) const
|
||||
{
|
||||
register uint32 *sa = saveArray;
|
||||
register const uint32 *s = state;
|
||||
register int i = N;
|
||||
for( ; i--; *sa++ = *s++ ) {}
|
||||
*sa = left;
|
||||
}
|
||||
|
||||
|
||||
inline void MTRand::load( uint32 *const loadArray )
|
||||
{
|
||||
register uint32 *s = state;
|
||||
register uint32 *la = loadArray;
|
||||
register int i = N;
|
||||
for( ; i--; *s++ = *la++ ) {}
|
||||
left = *la;
|
||||
pNext = &state[N-left];
|
||||
}
|
||||
|
||||
#endif // MERSENNETWISTER_H
|
||||
|
||||
// Change log:
|
||||
//
|
||||
// v0.1 - First release on 15 May 2000
|
||||
// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
|
||||
// - Translated from C to C++
|
||||
// - Made completely ANSI compliant
|
||||
// - Designed convenient interface for initialization, seeding, and
|
||||
// obtaining numbers in default or user-defined ranges
|
||||
// - Added automatic seeding from /dev/urandom or time() and clock()
|
||||
// - Provided functions for saving and loading generator state
|
||||
//
|
||||
// v0.2 - Fixed bug which reloaded generator one step too late
|
||||
//
|
||||
// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
|
||||
//
|
||||
// v0.4 - Removed trailing newline in saved generator format to be consistent
|
||||
// with output format of built-in types
|
||||
//
|
||||
// v0.5 - Improved portability by replacing static const int's with enum's and
|
||||
// clarifying return values in seed(); suggested by Eric Heimburg
|
||||
// - Removed MAXINT constant; use 0xffffffffUL instead
|
||||
//
|
||||
// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
|
||||
// - Changed integer [0,n] generator to give better uniformity
|
||||
//
|
||||
// v0.7 - Fixed operator precedence ambiguity in reload()
|
||||
// - Added access for real numbers in (0,1) and (0,n)
|
||||
//
|
||||
// v0.8 - Included time.h header to properly support time_t and clock_t
|
||||
//
|
||||
// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
|
||||
// - Allowed for seeding with arrays of any length
|
||||
// - Added access for real numbers in [0,1) with 53-bit resolution
|
||||
// - Added access for real numbers from normal (Gaussian) distributions
|
||||
// - Increased overall speed by optimizing twist()
|
||||
// - Doubled speed of integer [0,n] generation
|
||||
// - Fixed out-of-range number generation on 64-bit machines
|
||||
// - Improved portability by substituting literal constants for long enum's
|
||||
// - Changed license from GNU LGPL to BSD
|
||||
@@ -29,9 +29,9 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "common_logic.h"
|
||||
#include "PhraseCollection.h"
|
||||
#include "Translator.h"
|
||||
#include "sm_stringutil.h"
|
||||
|
||||
CPhraseCollection::CPhraseCollection()
|
||||
{
|
||||
@@ -54,7 +54,7 @@ IPhraseFile *CPhraseCollection::AddPhraseFile(const char *filename)
|
||||
char full_name[PLATFORM_MAX_PATH];
|
||||
|
||||
/* No compat shim here. The user should have read the doc. */
|
||||
UTIL_Format(full_name, sizeof(full_name), "%s.txt", filename);
|
||||
smcore.Format(full_name, sizeof(full_name), "%s.txt", filename);
|
||||
|
||||
fid = g_Translator.FindOrAddPhraseFile(full_name);
|
||||
pFile = g_Translator.GetFileByIndex(fid);
|
||||
@@ -113,7 +113,7 @@ bool CPhraseCollection::FormatString(char *buffer,
|
||||
unsigned int arg;
|
||||
|
||||
arg = 0;
|
||||
if (!gnprintf(buffer, maxlength, format, this, params, numparams, arg, pOutLength, pFailPhrase))
|
||||
if (!smcore.gnprintf(buffer, maxlength, format, this, params, numparams, arg, pOutLength, pFailPhrase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -30,13 +30,13 @@
|
||||
*/
|
||||
|
||||
#include "Profiler.h"
|
||||
#include "PluginSys.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "Logger.h"
|
||||
#include <ISourceMod.h>
|
||||
#if defined PLATFORM_POSIX
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <IPluginSys.h>
|
||||
#include "stringutil.h"
|
||||
|
||||
ProfileEngine g_Profiler;
|
||||
IProfiler *sm_profiler = &g_Profiler;
|
||||
@@ -314,43 +314,74 @@ void ProfileEngine::Clear()
|
||||
|
||||
void ProfileEngine::OnSourceModAllInitialized()
|
||||
{
|
||||
g_RootMenu.AddRootConsoleCommand("profiler", "Profiler commands", this);
|
||||
rootmenu->AddRootConsoleCommand2("profiler", "Profiler commands", this);
|
||||
}
|
||||
|
||||
void ProfileEngine::OnSourceModShutdown()
|
||||
{
|
||||
g_RootMenu.RemoveRootConsoleCommand("profiler", this);
|
||||
rootmenu->RemoveRootConsoleCommand("profiler", this);
|
||||
}
|
||||
|
||||
void ProfileEngine::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
||||
void ProfileEngine::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command)
|
||||
{
|
||||
if (command.ArgC() >= 3)
|
||||
if (command->ArgC() >= 3)
|
||||
{
|
||||
if (strcmp(command.Arg(2), "flush") == 0)
|
||||
if (strcmp(command->Arg(2), "flush") == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[256];
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateReport(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
Clear();
|
||||
|
||||
g_RootMenu.ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (strcmp(command->Arg(2), "report") == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[256];
|
||||
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateReport(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
return;
|
||||
}
|
||||
else if (strcmp(command->Arg(2), "clear") == 0)
|
||||
{
|
||||
Clear();
|
||||
|
||||
rootmenu->ConsolePrint("Profiler statistics cleared.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_RootMenu.ConsolePrint("Profiler commands:");
|
||||
g_RootMenu.DrawGenericOption("flush", "Flushes statistics to disk and starts over");
|
||||
rootmenu->ConsolePrint("Profiler commands:");
|
||||
rootmenu->DrawGenericOption("flush", "Flushes statistics to disk and starts over");
|
||||
rootmenu->DrawGenericOption("report", "Flushes statistics to disk");
|
||||
rootmenu->DrawGenericOption("clear", "Clears statistics");
|
||||
}
|
||||
|
||||
bool ProfileEngine::GenerateReport(FILE *fp)
|
||||
@@ -388,8 +419,8 @@ void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *nam
|
||||
ar = report->GetReport(i);
|
||||
|
||||
strncopy(new_name, ar->atom_name, sizeof(new_name));
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "<");
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", ">");
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "<", true);
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", ">", true);
|
||||
|
||||
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
|
||||
new_name,
|
||||
@@ -438,20 +469,20 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
|
||||
|
||||
if (atom.atom_type == SP_PROF_NATIVES)
|
||||
{
|
||||
strncopy(full_name, atom.name, sizeof(full_name));
|
||||
smcore.strncopy(full_name, atom.name, sizeof(full_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
CPlugin *pl;
|
||||
IPlugin *pl;
|
||||
const char *file;
|
||||
|
||||
file = "unknown";
|
||||
if ((pl = g_PluginSys.GetPluginByCtx(atom.ctx)) != NULL)
|
||||
if ((pl = pluginsys->FindPluginByContext(atom.ctx)) != NULL)
|
||||
{
|
||||
file = pl->GetFilename();
|
||||
}
|
||||
|
||||
UTIL_Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
|
||||
smcore.Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
|
||||
}
|
||||
|
||||
atom_time = CalcAtomTime(atom);
|
||||
@@ -460,7 +491,7 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
|
||||
{
|
||||
report = new prof_atom_report_t;
|
||||
|
||||
strncopy(report->atom_name, full_name, sizeof(report->atom_name));
|
||||
smcore.strncopy(report->atom_name, full_name, sizeof(report->atom_name));
|
||||
report->max_time = atom_time;
|
||||
report->min_time = atom_time;
|
||||
report->num_calls = 1;
|
||||
@@ -38,8 +38,8 @@
|
||||
#include <sh_vector.h>
|
||||
#include <sh_stack.h>
|
||||
#include <stdio.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "common_logic.h"
|
||||
#include <IRootConsoleMenu.h>
|
||||
|
||||
using namespace SourcePawn;
|
||||
using namespace SourceHook;
|
||||
@@ -103,7 +103,7 @@ public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IRootConsoleCommand
|
||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command);
|
||||
public: //IProfiler
|
||||
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native);
|
||||
void OnNativeEnd() ;
|
||||
@@ -126,6 +126,6 @@ private:
|
||||
prof_point_t m_ProfStart;
|
||||
};
|
||||
|
||||
extern ProfileEngine g_Profiler;
|
||||
extern IProfiler *sm_profiler;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
||||
@@ -36,9 +36,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "TextParsers.h"
|
||||
#include "ShareSys.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "LibrarySys.h"
|
||||
#include <ILibrarySys.h>
|
||||
|
||||
TextParsers g_TextParser;
|
||||
ITextParsers *textparsers = &g_TextParser;
|
||||
@@ -71,7 +69,7 @@ TextParsers::TextParsers()
|
||||
|
||||
void TextParsers::OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
sharesys->AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
unsigned int TextParsers::GetUTF8CharBytes(const char *stream)
|
||||
@@ -135,8 +133,8 @@ SMCError TextParsers::ParseSMCFile(const char *file,
|
||||
states->line = 0;
|
||||
states->col = 0;
|
||||
}
|
||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
||||
UTIL_Format(buffer, maxsize, "File could not be opened: %s", error);
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
smcore.Format(buffer, maxsize, "File could not be opened: %s", error);
|
||||
return SMCError_StreamOpen;
|
||||
}
|
||||
|
||||
@@ -145,7 +143,7 @@ SMCError TextParsers::ParseSMCFile(const char *file,
|
||||
fclose(fp);
|
||||
|
||||
errstr = GetSMCErrorString(result);
|
||||
UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
smcore.Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -196,7 +194,7 @@ SMCError TextParsers::ParseSMCStream(const char *stream,
|
||||
result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states);
|
||||
|
||||
const char *errstr = GetSMCErrorString(result);
|
||||
UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
smcore.Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -874,7 +872,7 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
|
||||
ptr = save_ptr;
|
||||
|
||||
/* Lastly, strip ending whitespace off */
|
||||
for (size_t i=len-1; i>=0 && i<len; i--)
|
||||
for (size_t i=len-1; i<len; i--)
|
||||
{
|
||||
if (g_ws_chartable[(unsigned char)ptr[i]])
|
||||
{
|
||||
@@ -33,7 +33,7 @@
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
|
||||
#include <ITextParsers.h>
|
||||
#include "sm_globals.h"
|
||||
#include "common_logic.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -28,10 +28,9 @@
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sm_platform.h>
|
||||
#include "ThreadSupport.h"
|
||||
#include "sm_globals.h"
|
||||
#include "ShareSys.h"
|
||||
#include "common_logic.h"
|
||||
|
||||
#if defined PLATFORM_POSIX
|
||||
#include "thread/PosixThreads.h"
|
||||
@@ -47,6 +46,7 @@ class RegThreadStuff : public SMGlobalClass
|
||||
public:
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, g_pThreader);
|
||||
sharesys->AddInterface(NULL, g_pThreader);
|
||||
}
|
||||
} s_RegThreadStuff;
|
||||
|
||||
@@ -29,22 +29,24 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <sm_platform.h>
|
||||
#include "Translator.h"
|
||||
#include "Logger.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "sourcemod.h"
|
||||
#include "PlayerManager.h"
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <ISourceMod.h>
|
||||
#include <ILibrarySys.h>
|
||||
#include "PhraseCollection.h"
|
||||
#include "ShareSys.h"
|
||||
#include "stringutil.h"
|
||||
|
||||
Translator g_Translator;
|
||||
IPhraseCollection *g_pCorePhrases = NULL;
|
||||
unsigned int g_pCorePhraseID = 0;
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
struct trans_t
|
||||
{
|
||||
int stridx;
|
||||
@@ -67,15 +69,10 @@ CPhraseFile::CPhraseFile(Translator *pTranslator, const char *file)
|
||||
m_LangCount = pTranslator->GetLanguageCount();
|
||||
m_File.assign(file);
|
||||
m_pTranslator = pTranslator;
|
||||
m_pPhraseLookup = NULL;
|
||||
}
|
||||
|
||||
CPhraseFile::~CPhraseFile()
|
||||
{
|
||||
if (m_pPhraseLookup)
|
||||
{
|
||||
sm_trie_destroy(m_pPhraseLookup);
|
||||
}
|
||||
}
|
||||
|
||||
void CPhraseFile::ParseError(const char *message, ...)
|
||||
@@ -99,20 +96,16 @@ void CPhraseFile::ParseWarning(const char *message, ...)
|
||||
|
||||
if (!m_FileLogged)
|
||||
{
|
||||
g_Logger.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
|
||||
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
|
||||
m_FileLogged = true;
|
||||
}
|
||||
|
||||
g_Logger.LogError("[SM] %s", buffer);
|
||||
smcore.LogError("[SM] %s", buffer);
|
||||
}
|
||||
|
||||
void CPhraseFile::ReparseFile()
|
||||
{
|
||||
if (m_pPhraseLookup)
|
||||
{
|
||||
sm_trie_destroy(m_pPhraseLookup);
|
||||
}
|
||||
m_pPhraseLookup = sm_trie_create();
|
||||
m_PhraseLookup.clear();
|
||||
|
||||
m_LangCount = m_pTranslator->GetLanguageCount();
|
||||
|
||||
@@ -123,19 +116,19 @@ void CPhraseFile::ReparseFile()
|
||||
|
||||
SMCError err;
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "translations/%s", m_File.c_str());
|
||||
g_pSM->BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "translations/%s", m_File.c_str());
|
||||
|
||||
//backwards compatibility shim
|
||||
/* :HACKHACK: Change .cfg/.txt and vice versa for compatibility */
|
||||
if (!g_LibSys.PathExists(path))
|
||||
if (!libsys->PathExists(path))
|
||||
{
|
||||
if (m_File.compare("common.cfg") == 0)
|
||||
{
|
||||
UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt");
|
||||
UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt", true);
|
||||
} else if (strstr(path, ".cfg")) {
|
||||
UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt");
|
||||
UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt", true);
|
||||
} else if (strstr(path, ".txt")) {
|
||||
UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg");
|
||||
UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg", true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,8 +142,8 @@ void CPhraseFile::ReparseFile()
|
||||
msg = m_ParseError.c_str();
|
||||
}
|
||||
|
||||
g_Logger.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
||||
g_Logger.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
|
||||
smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
|
||||
}
|
||||
|
||||
const char *code;
|
||||
@@ -161,7 +154,7 @@ void CPhraseFile::ReparseFile()
|
||||
continue;
|
||||
}
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"translations/%s/%s",
|
||||
@@ -169,7 +162,7 @@ void CPhraseFile::ReparseFile()
|
||||
m_File.c_str());
|
||||
|
||||
/* Speculatively load these. */
|
||||
if (!g_LibSys.PathExists(path))
|
||||
if (!libsys->PathExists(path))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -182,10 +175,10 @@ void CPhraseFile::ReparseFile()
|
||||
msg = m_ParseError.c_str();
|
||||
}
|
||||
|
||||
g_Logger.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
|
||||
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
|
||||
code,
|
||||
m_File.c_str());
|
||||
g_Logger.LogError("[SM] Error (line %d, column %d): %s",
|
||||
smcore.LogError("[SM] Error (line %d, column %d): %s",
|
||||
states.line,
|
||||
states.col,
|
||||
msg);
|
||||
@@ -217,17 +210,17 @@ SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
m_ParseState = PPS_InPhrase;
|
||||
recognized = true;
|
||||
|
||||
void *value;
|
||||
if (sm_trie_retrieve(m_pPhraseLookup, name, &value))
|
||||
int *pvalue;
|
||||
if ((pvalue = m_PhraseLookup.retrieve(name)) != NULL)
|
||||
{
|
||||
m_CurPhrase = reinterpret_cast<int>(value);
|
||||
m_CurPhrase = *pvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
phrase_t *pPhrase;
|
||||
|
||||
m_CurPhrase = m_pMemory->CreateMem(sizeof(phrase_t), (void **)&pPhrase);
|
||||
sm_trie_insert(m_pPhraseLookup, name, reinterpret_cast<void *>(m_CurPhrase));
|
||||
m_PhraseLookup.insert(name, m_CurPhrase);
|
||||
|
||||
/* Initialize new phrase */
|
||||
trans_t *pTrans;
|
||||
@@ -486,13 +479,6 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = strlen(key);
|
||||
if (len < 2 || len > 3)
|
||||
{
|
||||
ParseWarning("Ignoring translation to invalid language \"%s\" on line %d.", key, states->line);
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
unsigned int lang;
|
||||
if (!m_pTranslator->GetLanguageByCode(key, &lang))
|
||||
{
|
||||
@@ -505,7 +491,7 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
/* See how many bytes we need for this string, then allocate.
|
||||
* NOTE: THIS SHOULD GUARANTEE THAT WE DO NOT NEED TO NEED TO SIZE CHECK
|
||||
*/
|
||||
len = strlen(value) + pPhrase->fmt_bytes + 1;
|
||||
size_t len = strlen(value) + pPhrase->fmt_bytes + 1;
|
||||
char *out_buf;
|
||||
int out_idx;
|
||||
|
||||
@@ -639,9 +625,7 @@ SMCResult CPhraseFile::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
if (m_ParseState == PPS_InPhrase)
|
||||
{
|
||||
if (m_CurPhrase == -1 && m_LastPhraseString.size())
|
||||
{
|
||||
sm_trie_delete(m_pPhraseLookup, m_LastPhraseString.c_str());
|
||||
}
|
||||
m_PhraseLookup.remove(m_LastPhraseString.c_str());
|
||||
m_CurPhrase = -1;
|
||||
m_ParseState = PPS_Phrases;
|
||||
m_LastPhraseString.assign("");
|
||||
@@ -658,9 +642,7 @@ void CPhraseFile::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
/* Check to see if we have any dangling phrases that weren't completed, and scrap them */
|
||||
if ((halted || failed) && m_LastPhraseString.size())
|
||||
{
|
||||
sm_trie_delete(m_pPhraseLookup, m_LastPhraseString.c_str());
|
||||
}
|
||||
m_PhraseLookup.remove(m_LastPhraseString.c_str());
|
||||
}
|
||||
|
||||
TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_id, Translation *pTrans)
|
||||
@@ -670,13 +652,11 @@ TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_i
|
||||
return Trans_BadLanguage;
|
||||
}
|
||||
|
||||
void *object;
|
||||
if (!sm_trie_retrieve(m_pPhraseLookup, szPhrase, &object))
|
||||
{
|
||||
int *pvalue;
|
||||
if ((pvalue = m_PhraseLookup.retrieve(szPhrase)) == NULL)
|
||||
return Trans_BadPhrase;
|
||||
}
|
||||
|
||||
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(reinterpret_cast<int>(object));
|
||||
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(*pvalue);
|
||||
trans_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl);
|
||||
|
||||
trans = &trans[lang_id];
|
||||
@@ -705,7 +685,6 @@ const char *CPhraseFile::GetFilename()
|
||||
Translator::Translator() : m_ServerLang(SOURCEMOD_LANGUAGE_ENGLISH)
|
||||
{
|
||||
m_pStringTab = new BaseStringTable(2048);
|
||||
m_pLCodeLookup = sm_trie_create();
|
||||
strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||
}
|
||||
|
||||
@@ -721,8 +700,6 @@ Translator::~Translator()
|
||||
delete m_Languages[i];
|
||||
}
|
||||
|
||||
sm_trie_destroy(m_pLCodeLookup);
|
||||
|
||||
delete m_pStringTab;
|
||||
}
|
||||
|
||||
@@ -739,13 +716,13 @@ ConfigResult Translator::OnSourceModConfigChanged(const char *key,
|
||||
unsigned int index;
|
||||
if (!GetLanguageByCode(value, &index))
|
||||
{
|
||||
UTIL_Format(error, maxlength, "Language code \"%s\" is not registered", value);
|
||||
smcore.Format(error, maxlength, "Language code \"%s\" is not registered", value);
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
m_ServerLang = index;
|
||||
} else {
|
||||
strncopy(m_InitialLang, value, sizeof(m_InitialLang));
|
||||
smcore.strncopy(m_InitialLang, value, sizeof(m_InitialLang));
|
||||
}
|
||||
|
||||
return ConfigResult_Accept;
|
||||
@@ -758,7 +735,7 @@ void Translator::OnSourceModLevelChange(const char *mapName)
|
||||
{
|
||||
/* Refresh language stuff */
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
|
||||
RebuildLanguageDatabase(path);
|
||||
}
|
||||
|
||||
@@ -766,10 +743,16 @@ void Translator::OnSourceModAllInitialized()
|
||||
{
|
||||
AddLanguage("en", "English");
|
||||
|
||||
const char* lang = smcore.GetCoreConfigValue("ServerLang");
|
||||
if (lang)
|
||||
{
|
||||
strncpy(m_InitialLang, lang, sizeof(m_InitialLang));
|
||||
}
|
||||
|
||||
g_pCorePhrases = CreatePhraseCollection();
|
||||
g_pCorePhrases->AddPhraseFile("core.phrases");
|
||||
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
sharesys->AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
void Translator::OnSourceModShutdown()
|
||||
@@ -779,43 +762,38 @@ void Translator::OnSourceModShutdown()
|
||||
|
||||
bool Translator::GetLanguageByCode(const char *code, unsigned int *index)
|
||||
{
|
||||
void *_index;
|
||||
unsigned int *pindex;
|
||||
|
||||
if (!sm_trie_retrieve(m_pLCodeLookup, code, &_index))
|
||||
{
|
||||
if ((pindex = m_LCodeLookup.retrieve(code)) == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index)
|
||||
{
|
||||
*index = reinterpret_cast<unsigned int>(_index);
|
||||
}
|
||||
*index = *pindex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Translator::GetLanguageByName(const char *name, unsigned int *index)
|
||||
{
|
||||
CVector<Language *>::iterator iter;
|
||||
unsigned int id = 0;
|
||||
|
||||
for (iter=m_Languages.begin(); iter!=m_Languages.end(); iter++, id++)
|
||||
char lower[256];
|
||||
size_t len = strlen(name);
|
||||
if (len > 255) len = 255;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (strcasecmp(m_pStringTab->GetString((*iter)->m_FullName), name) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (name[i] >= 'A' && name[i] <= 'Z')
|
||||
lower[i] = tolower(name[i]);
|
||||
else
|
||||
lower[i] = name[i];
|
||||
}
|
||||
lower[len] = '\0';
|
||||
|
||||
if (iter == m_Languages.end())
|
||||
{
|
||||
unsigned int *pIndex;
|
||||
|
||||
if ((pIndex = m_LAliases.retrieve(lower)) == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index)
|
||||
{
|
||||
*index = id;
|
||||
}
|
||||
*index = *pIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -853,8 +831,8 @@ unsigned int Translator::FindOrAddPhraseFile(const char *phrase_file)
|
||||
void Translator::RebuildLanguageDatabase(const char *lang_header_file)
|
||||
{
|
||||
/* Erase everything we have */
|
||||
sm_trie_destroy(m_pLCodeLookup);
|
||||
m_pLCodeLookup = sm_trie_create();
|
||||
m_LCodeLookup.clear();
|
||||
m_LAliases.clear();
|
||||
m_pStringTab->Reset();
|
||||
|
||||
for (size_t i=0; i<m_Languages.size(); i++)
|
||||
@@ -874,25 +852,27 @@ void Translator::RebuildLanguageDatabase(const char *lang_header_file)
|
||||
str_err = m_CustomError.c_str();
|
||||
}
|
||||
|
||||
g_Logger.LogError("[SM] Failed to parse language header file: \"%s\"", lang_header_file);
|
||||
g_Logger.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", lang_header_file);
|
||||
smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
|
||||
}
|
||||
|
||||
void *serverLang;
|
||||
unsigned int *pServerLang;
|
||||
|
||||
if (!sm_trie_retrieve(m_pLCodeLookup, m_InitialLang, &serverLang))
|
||||
if ((pServerLang = m_LCodeLookup.retrieve(m_InitialLang)) == NULL)
|
||||
{
|
||||
g_Logger.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
|
||||
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
|
||||
|
||||
strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||
}
|
||||
|
||||
m_ServerLang = reinterpret_cast<unsigned int>(serverLang);
|
||||
else
|
||||
{
|
||||
m_ServerLang = *pServerLang;
|
||||
}
|
||||
|
||||
if (!m_Languages.size())
|
||||
{
|
||||
g_Logger.LogError("[SM] Fatal error, no languages found! Translation will not work.");
|
||||
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work.");
|
||||
}
|
||||
|
||||
for (size_t i=0; i<m_Files.size(); i++)
|
||||
@@ -919,7 +899,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
|
||||
|
||||
if (!m_InLanguageSection)
|
||||
{
|
||||
g_Logger.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
@@ -934,14 +914,6 @@ SMCResult Translator::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
|
||||
SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||
{
|
||||
size_t len = strlen(key);
|
||||
|
||||
if (len < 2 || len > 3)
|
||||
{
|
||||
g_Logger.LogError("[SM] Warning encountered parsing languages.cfg file.");
|
||||
g_Logger.LogError("[SM] Invalid language code \"%s\" is being ignored.", key);
|
||||
}
|
||||
|
||||
AddLanguage(key, value);
|
||||
|
||||
return SMCResult_Continue;
|
||||
@@ -949,20 +921,40 @@ SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
|
||||
bool Translator::AddLanguage(const char *langcode, const char *description)
|
||||
{
|
||||
if (sm_trie_retrieve(m_pLCodeLookup, langcode, NULL))
|
||||
char lower[256];
|
||||
size_t len = strlen(description);
|
||||
if (len > 255) len = 255;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
return false;
|
||||
if (description[i] >= 'A' && description[i] <= 'Z')
|
||||
lower[i] = tolower(description[i]);
|
||||
else
|
||||
lower[i] = description[i];
|
||||
}
|
||||
lower[len] = '\0';
|
||||
|
||||
Language *pLanguage = new Language;
|
||||
unsigned int idx = m_Languages.size();
|
||||
if (m_LAliases.retrieve(lower))
|
||||
return false;
|
||||
|
||||
UTIL_Format(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode);
|
||||
pLanguage->m_FullName = m_pStringTab->AddString(description);
|
||||
unsigned int idx;
|
||||
if (unsigned int *pIdx = m_LCodeLookup.retrieve(langcode))
|
||||
{
|
||||
idx = *pIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
Language *pLanguage = new Language;
|
||||
idx = m_Languages.size();
|
||||
|
||||
sm_trie_insert(m_pLCodeLookup, langcode, reinterpret_cast<void *>(idx));
|
||||
smcore.Format(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode);
|
||||
pLanguage->m_CanonicalName = m_pStringTab->AddString(lower);
|
||||
|
||||
m_Languages.push_back(pLanguage);
|
||||
m_LCodeLookup.insert(langcode, idx);
|
||||
|
||||
m_Languages.push_back(pLanguage);
|
||||
}
|
||||
|
||||
m_LAliases.insert(lower, idx);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -984,7 +976,7 @@ unsigned int Translator::GetServerLanguage()
|
||||
|
||||
unsigned int Translator::GetClientLanguage(int client)
|
||||
{
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
|
||||
return pPlayer->GetLanguageId();
|
||||
}
|
||||
|
||||
@@ -1002,7 +994,7 @@ bool Translator::GetLanguageInfo(unsigned int number, const char **code, const c
|
||||
}
|
||||
if (name)
|
||||
{
|
||||
*name = m_pStringTab->GetString(l->m_FullName);
|
||||
*name = m_pStringTab->GetString(l->m_CanonicalName);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1025,20 +1017,16 @@ IPhraseCollection *Translator::CreatePhraseCollection()
|
||||
|
||||
int Translator::SetGlobalTarget(int index)
|
||||
{
|
||||
return g_SourceMod.SetGlobalTarget(index);
|
||||
return g_pSM->SetGlobalTarget(index);
|
||||
}
|
||||
|
||||
int Translator::GetGlobalTarget() const
|
||||
{
|
||||
return g_SourceMod.GetGlobalTarget();
|
||||
return g_pSM->GetGlobalTarget();
|
||||
}
|
||||
|
||||
bool CoreTranslate(char *buffer,
|
||||
size_t maxlength,
|
||||
const char *format,
|
||||
unsigned int numparams,
|
||||
size_t *pOutLength,
|
||||
...)
|
||||
bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned int numparams,
|
||||
size_t *pOutLength, ...)
|
||||
{
|
||||
va_list ap;
|
||||
unsigned int i;
|
||||
@@ -1068,11 +1056,11 @@ bool CoreTranslate(char *buffer,
|
||||
{
|
||||
if (fail_phrase != NULL)
|
||||
{
|
||||
g_Logger.LogError("[SM] Could not find core phrase: %s", fail_phrase);
|
||||
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogError("[SM] Unknown fatal error while translating a core phrase.");
|
||||
smcore.LogError("[SM] Unknown fatal error while translating a core phrase.");
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1093,7 +1081,7 @@ bool Translator::FormatString(char *buffer,
|
||||
unsigned int arg;
|
||||
|
||||
arg = 0;
|
||||
if (!gnprintf(buffer, maxlength, format, pPhrases, params, numparams, arg, pOutLength, pFailPhrase))
|
||||
if (!smcore.gnprintf(buffer, maxlength, format, pPhrases, params, numparams, arg, pOutLength, pFailPhrase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -32,17 +32,14 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_H_
|
||||
#define _INCLUDE_SOURCEMOD_TRANSLATOR_H_
|
||||
|
||||
#include "sm_trie.h"
|
||||
#include "common_logic.h"
|
||||
#include <sm_trie_tpl.h>
|
||||
#include <sh_string.h>
|
||||
#include <sh_vector.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_memtable.h"
|
||||
#include "ITextParsers.h"
|
||||
#include <ITranslator.h>
|
||||
|
||||
#define MAX_TRANSLATE_PARAMS 32
|
||||
#define CORELANG_ENGLISH 0
|
||||
|
||||
/* :TODO: write a templatized version of tries? */
|
||||
|
||||
using namespace SourceHook;
|
||||
@@ -58,7 +55,7 @@ enum PhraseParseState
|
||||
struct Language
|
||||
{
|
||||
char m_code2[4];
|
||||
int m_FullName;
|
||||
int m_CanonicalName;
|
||||
};
|
||||
|
||||
class CPhraseFile :
|
||||
@@ -82,7 +79,7 @@ private:
|
||||
void ParseError(const char *message, ...);
|
||||
void ParseWarning(const char *message, ...);
|
||||
private:
|
||||
Trie *m_pPhraseLookup;
|
||||
KTrie<int> m_PhraseLookup;
|
||||
String m_File;
|
||||
Translator *m_pTranslator;
|
||||
PhraseParseState m_ParseState;
|
||||
@@ -122,7 +119,6 @@ public:
|
||||
unsigned int FindOrAddPhraseFile(const char *phrase_file);
|
||||
BaseStringTable *GetStringTable();
|
||||
unsigned int GetLanguageCount();
|
||||
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
|
||||
bool GetLanguageByCode(const char *code, unsigned int *index);
|
||||
bool GetLanguageByName(const char *name, unsigned int *index);
|
||||
CPhraseFile *GetFileByIndex(unsigned int index);
|
||||
@@ -149,13 +145,15 @@ public: //ITranslator
|
||||
unsigned int numparams,
|
||||
size_t *pOutLength,
|
||||
const char **pFailPhrase);
|
||||
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
|
||||
private:
|
||||
bool AddLanguage(const char *langcode, const char *description);
|
||||
private:
|
||||
CVector<Language *> m_Languages;
|
||||
CVector<CPhraseFile *> m_Files;
|
||||
BaseStringTable *m_pStringTab;
|
||||
Trie *m_pLCodeLookup;
|
||||
KTrie<unsigned int> m_LCodeLookup;
|
||||
KTrie<unsigned int> m_LAliases;
|
||||
bool m_InLanguageSection;
|
||||
String m_CustomError;
|
||||
unsigned int m_ServerLang;
|
||||
@@ -175,3 +173,4 @@ extern unsigned int g_pCorePhraseID;
|
||||
extern Translator g_Translator;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TRANSLATOR_H_
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <sm_platform.h>
|
||||
#include <string.h>
|
||||
#include "common_logic.h"
|
||||
#include "TextParsers.h"
|
||||
#include "Profiler.h"
|
||||
#include "sm_crc32.h"
|
||||
#include "MemoryUtils.h"
|
||||
#include "stringutil.h"
|
||||
#include "ThreadSupport.h"
|
||||
#include "Translator.h"
|
||||
#include "GameConfigs.h"
|
||||
|
||||
sm_core_t smcore;
|
||||
IHandleSys *handlesys;
|
||||
IdentityToken_t *g_pCoreIdent;
|
||||
SMGlobalClass *SMGlobalClass::head = NULL;
|
||||
ISourceMod *g_pSM;
|
||||
ILibrarySys *libsys;
|
||||
ITextParsers *textparser = &g_TextParser;
|
||||
IVEngineServer *engine;
|
||||
IShareSys *sharesys;
|
||||
IRootConsole *rootmenu;
|
||||
IPluginManager *pluginsys;
|
||||
IForwardManager *forwardsys;
|
||||
ITimerSystem *timersys;
|
||||
ServerGlobals serverGlobals;
|
||||
IPlayerManager *playerhelpers;
|
||||
IAdminSystem *adminsys;
|
||||
IGameHelpers *gamehelpers;
|
||||
|
||||
static void AddCorePhraseFile(const char *filename)
|
||||
{
|
||||
g_pCorePhrases->AddPhraseFile(filename);
|
||||
}
|
||||
|
||||
static IGameConfig *GetCoreGameConfig()
|
||||
{
|
||||
return g_pGameConf;
|
||||
}
|
||||
|
||||
static sm_logic_t logic =
|
||||
{
|
||||
NULL,
|
||||
g_pThreader,
|
||||
sm_profiler,
|
||||
&g_Translator,
|
||||
stristr,
|
||||
CoreTranslate,
|
||||
AddCorePhraseFile,
|
||||
UTIL_ReplaceAll,
|
||||
UTIL_ReplaceEx,
|
||||
UTIL_DecodeHexString,
|
||||
GetCoreGameConfig
|
||||
};
|
||||
|
||||
static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
|
||||
{
|
||||
logic.head = SMGlobalClass::head;
|
||||
|
||||
memcpy(&smcore, core, sizeof(sm_core_t));
|
||||
memcpy(_logic, &logic, sizeof(sm_logic_t));
|
||||
memcpy(&serverGlobals, core->serverGlobals, sizeof(ServerGlobals));
|
||||
|
||||
handlesys = core->handlesys;
|
||||
libsys = core->libsys;
|
||||
engine = core->engine;
|
||||
g_pCoreIdent = core->core_ident;
|
||||
g_pSM = core->sm;
|
||||
sharesys = core->sharesys;
|
||||
rootmenu = core->rootmenu;
|
||||
pluginsys = core->pluginsys;
|
||||
forwardsys = core->forwardsys;
|
||||
timersys = core->timersys;
|
||||
playerhelpers = core->playerhelpers;
|
||||
adminsys = core->adminsys;
|
||||
gamehelpers = core->gamehelpers;
|
||||
}
|
||||
|
||||
PLATFORM_EXTERN_C ITextParsers *get_textparsers()
|
||||
{
|
||||
return &g_TextParser;
|
||||
}
|
||||
|
||||
PLATFORM_EXTERN_C LogicInitFunction logic_load(uint32_t magic)
|
||||
{
|
||||
if (magic != SM_LOGIC_MAGIC)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return logic_init;
|
||||
}
|
||||
|
||||
void CoreNativesToAdd::OnSourceModAllInitialized()
|
||||
{
|
||||
smcore.AddNatives(m_NativeList);
|
||||
}
|
||||
|
||||
/* Overload a few things to prevent libstdc++ linking */
|
||||
#if defined __linux__ || defined __APPLE__
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
|
||||
#define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
|
||||
|
||||
#include <IHandleSys.h>
|
||||
|
||||
#include "../sm_globals.h"
|
||||
#include "intercom.h"
|
||||
|
||||
extern sm_core_t smcore;
|
||||
extern IHandleSys *handlesys;
|
||||
extern ISourceMod *g_pSM;
|
||||
extern ILibrarySys *libsys;
|
||||
extern ITextParsers *textparser;
|
||||
extern IVEngineServer *engine;
|
||||
extern IShareSys *sharesys;
|
||||
extern IRootConsole *rootmenu;
|
||||
extern IPluginManager *pluginsys;
|
||||
extern IForwardManager *forwardsys;
|
||||
extern ITimerSystem *timersys;
|
||||
extern ServerGlobals serverGlobals;
|
||||
extern IPlayerManager *playerhelpers;
|
||||
extern IAdminSystem *adminsys;
|
||||
extern IGameHelpers *gamehelpers;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <IShareSys.h>
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
|
||||
#define _INCLUDE_SOURCEMOD_INTERCOM_H_
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
/**
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 18)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
#else
|
||||
class IVEngineServer_Logic
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual bool IsMapValid(const char *map) = 0;
|
||||
virtual void ServerCommand(const char *cmd) = 0;
|
||||
};
|
||||
|
||||
typedef int FileFindHandle_t;
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IFileSystem
|
||||
#else
|
||||
class IFileSystem_Logic
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
|
||||
virtual const char *FindNext(FileFindHandle_t handle) = 0;
|
||||
virtual void FindClose(FileFindHandle_t handle) = 0;
|
||||
};
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
class ISourceMod;
|
||||
class ILibrarySys;
|
||||
class ITextParsers;
|
||||
class IThreader;
|
||||
class IRootConsole;
|
||||
class IPluginManager;
|
||||
class IForwardManager;
|
||||
class ITimerSystem;
|
||||
class IPlayerManager;
|
||||
class IAdminSystem;
|
||||
class IGameHelpers;
|
||||
class IPhraseCollection;
|
||||
class ITranslator;
|
||||
class IGameConfig;
|
||||
}
|
||||
|
||||
class IVEngineServer;
|
||||
class IFileSystem;
|
||||
class ConVar;
|
||||
|
||||
struct ServerGlobals
|
||||
{
|
||||
const double *universalTime;
|
||||
float *interval_per_tick;
|
||||
float *frametime;
|
||||
};
|
||||
|
||||
struct sm_core_t
|
||||
{
|
||||
/* Objects */
|
||||
IHandleSys *handlesys;
|
||||
IdentityToken_t *core_ident;
|
||||
ISourceMod *sm;
|
||||
ILibrarySys *libsys;
|
||||
IVEngineServer *engine;
|
||||
IFileSystem *filesystem;
|
||||
IShareSys *sharesys;
|
||||
IRootConsole *rootmenu;
|
||||
IPluginManager *pluginsys;
|
||||
IForwardManager *forwardsys;
|
||||
ITimerSystem *timersys;
|
||||
IPlayerManager *playerhelpers;
|
||||
IAdminSystem *adminsys;
|
||||
IGameHelpers *gamehelpers;
|
||||
/* Functions */
|
||||
void (*AddNatives)(sp_nativeinfo_t* nlist);
|
||||
ConVar * (*FindConVar)(const char*);
|
||||
unsigned int (*strncopy)(char*, const char*, size_t);
|
||||
char * (*TrimWhitespace)(char *, size_t &);
|
||||
void (*LogError)(const char*, ...);
|
||||
const char * (*GetCvarString)(ConVar*);
|
||||
size_t (*Format)(char*, size_t, const char*, ...);
|
||||
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
|
||||
unsigned int, unsigned int &, size_t *, const char **);
|
||||
size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *);
|
||||
bool (*GetGameName)(char *buffer, size_t maxlength);
|
||||
const char * (*GetGameDescription)();
|
||||
const char * (*GetSourceEngineName)();
|
||||
bool (*SymbolsAreHidden)();
|
||||
const char * (*GetCoreConfigValue)(const char*);
|
||||
/* Data */
|
||||
ServerGlobals *serverGlobals;
|
||||
void * serverFactory;
|
||||
void * engineFactory;
|
||||
void * matchmakingDSFactory;
|
||||
};
|
||||
|
||||
struct sm_logic_t
|
||||
{
|
||||
SMGlobalClass *head;
|
||||
IThreader *threader;
|
||||
IProfiler *profiler;
|
||||
ITranslator *translator;
|
||||
const char *(*stristr)(const char *, const char *);
|
||||
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
|
||||
void (*AddCorePhraseFile)(const char *filename);
|
||||
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
|
||||
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
|
||||
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
|
||||
IGameConfig * (*GetCoreGameConfig)();
|
||||
};
|
||||
|
||||
typedef void (*LogicInitFunction)(const sm_core_t *core, sm_logic_t *logic);
|
||||
typedef LogicInitFunction (*LogicLoadFunction)(uint32_t magic);
|
||||
typedef ITextParsers *(*GetITextParsers)();
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_INTERCOM_H_ */
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logic", "logic.vcxproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}</ProjectGuid>
|
||||
<RootNamespace>jitx86</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">sourcemod.logic</TargetName>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">sourcemod.logic</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..;$(MMSOURCE19)\core\sourcehook;..\..\..\public;..\..\..\public\sourcepawn;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_DEFAULT_THREADER;SM_LOGIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
|
||||
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\public</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>IF NOT "%SMOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%SMOUTDIR%\bin"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..;$(MMSOURCE19)\core\sourcehook;..\..\..\public;..\..\..\public\sourcepawn;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_LOGIC;SM_DEFAULT_THREADER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
|
||||
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
<ResourceCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\public</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>IF NOT "%SMOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%SMOUTDIR%\bin"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\common_logic.cpp" />
|
||||
<ClCompile Include="..\GameConfigs.cpp" />
|
||||
<ClCompile Include="..\MemoryUtils.cpp" />
|
||||
<ClCompile Include="..\PhraseCollection.cpp" />
|
||||
<ClCompile Include="..\Profiler.cpp" />
|
||||
<ClCompile Include="..\sm_crc32.cpp" />
|
||||
<ClCompile Include="..\smn_admin.cpp" />
|
||||
<ClCompile Include="..\smn_adt_array.cpp" />
|
||||
<ClCompile Include="..\smn_adt_stack.cpp" />
|
||||
<ClCompile Include="..\smn_adt_trie.cpp" />
|
||||
<ClCompile Include="..\smn_banning.cpp" />
|
||||
<ClCompile Include="..\smn_datapacks.cpp" />
|
||||
<ClCompile Include="..\smn_float.cpp" />
|
||||
<ClCompile Include="..\smn_functions.cpp" />
|
||||
<ClCompile Include="..\smn_gameconfigs.cpp" />
|
||||
<ClCompile Include="..\smn_handles.cpp" />
|
||||
<ClCompile Include="..\smn_lang.cpp" />
|
||||
<ClCompile Include="..\smn_maplists.cpp" />
|
||||
<ClCompile Include="..\smn_players.cpp" />
|
||||
<ClCompile Include="..\smn_sorting.cpp" />
|
||||
<ClCompile Include="..\smn_string.cpp" />
|
||||
<ClCompile Include="..\smn_textparse.cpp" />
|
||||
<ClCompile Include="..\smn_timers.cpp" />
|
||||
<ClCompile Include="..\stringutil.cpp" />
|
||||
<ClCompile Include="..\TextParsers.cpp" />
|
||||
<ClCompile Include="..\ThreadSupport.cpp" />
|
||||
<ClCompile Include="..\Translator.cpp" />
|
||||
<ClCompile Include="..\thread\BaseWorker.cpp" />
|
||||
<ClCompile Include="..\thread\ThreadWorker.cpp" />
|
||||
<ClCompile Include="..\thread\WinThreads.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\public\sm_platform.h" />
|
||||
<ClInclude Include="..\..\..\public\sm_trie_tpl.h" />
|
||||
<ClInclude Include="..\..\..\public\sourcemod_version.h" />
|
||||
<ClInclude Include="..\AutoHandleRooter.h" />
|
||||
<ClInclude Include="..\CellArray.h" />
|
||||
<ClInclude Include="..\common_logic.h" />
|
||||
<ClInclude Include="..\GameConfigs.h" />
|
||||
<ClInclude Include="..\intercom.h" />
|
||||
<ClInclude Include="..\MemoryUtils.h" />
|
||||
<ClInclude Include="..\MersenneTwister.h" />
|
||||
<ClInclude Include="..\PhraseCollection.h" />
|
||||
<ClInclude Include="..\Profiler.h" />
|
||||
<ClInclude Include="..\sm_crc32.h" />
|
||||
<ClInclude Include="..\sm_memtable.h" />
|
||||
<ClInclude Include="..\sm_symtable.h" />
|
||||
<ClInclude Include="..\stringutil.h" />
|
||||
<ClInclude Include="..\TextParsers.h" />
|
||||
<ClInclude Include="..\ThreadSupport.h" />
|
||||
<ClInclude Include="..\thread\BaseWorker.h" />
|
||||
<ClInclude Include="..\thread\ThreadWorker.h" />
|
||||
<ClInclude Include="..\thread\WinThreads.h" />
|
||||
<ClInclude Include="..\Translator.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\version.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,194 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Threads">
|
||||
<UniqueIdentifier>{67c1ebce-c1f8-4d2c-9ef4-33f0ef6343e9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Threads\Header Files">
|
||||
<UniqueIdentifier>{c6e2ebb3-4869-4453-9b83-e49f70cb8a05}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Threads\Source Files">
|
||||
<UniqueIdentifier>{e6d8a9af-1c1b-4f0c-ae06-a9ebd5cd32e4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Natives">
|
||||
<UniqueIdentifier>{126462f2-e517-4854-8a94-759e56787536}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\common_logic.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\GameConfigs.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\MemoryUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\PhraseCollection.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Profiler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\sm_crc32.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\stringutil.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\TextParsers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\ThreadSupport.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Translator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\thread\BaseWorker.cpp">
|
||||
<Filter>Threads\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\thread\ThreadWorker.cpp">
|
||||
<Filter>Threads\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\thread\WinThreads.cpp">
|
||||
<Filter>Threads\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_admin.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_timers.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_adt_array.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_adt_stack.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_adt_trie.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_banning.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_datapacks.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_float.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_functions.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_gameconfigs.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_handles.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_lang.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_maplists.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_players.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_sorting.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_string.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\smn_textparse.cpp">
|
||||
<Filter>Natives</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\CellArray.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common_logic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\intercom.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Profiler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\TextParsers.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ThreadSupport.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\thread\BaseWorker.h">
|
||||
<Filter>Threads\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\thread\ThreadWorker.h">
|
||||
<Filter>Threads\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\thread\WinThreads.h">
|
||||
<Filter>Threads\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\AutoHandleRooter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\GameConfigs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\MemoryUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\MersenneTwister.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\PhraseCollection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\sm_crc32.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\sm_memtable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\sm_symtable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\stringutil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Translator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\sm_trie_tpl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\sourcemod_version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\public\sm_platform.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\version.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logic", "logic.vcproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Regular → Executable
+154
-63
@@ -2,9 +2,9 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="tf2"
|
||||
ProjectGUID="{B3E797CF-4E77-4C9D-B8A8-7589B6902206}"
|
||||
RootNamespace="tf2"
|
||||
Name="logic"
|
||||
ProjectGUID="{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
RootNamespace="jitx86"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
@@ -17,7 +17,7 @@
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug - Orange Box|Win32"
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
@@ -41,8 +41,8 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(MMSOURCE17)\core";"$(MMSOURCE17)\core\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD"
|
||||
AdditionalIncludeDirectories="..;"$(MMSOURCE17)\core\sourcehook";..\..\..\public;..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_DEFAULT_THREADER;SM_LOGIC"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
@@ -64,9 +64,9 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDKOB)\lib\public\tier0.lib" "$(HL2SDKOB)\lib\public\tier1.lib""
|
||||
OutputFile="$(OutDir)\game.tf2.ext.dll"
|
||||
OutputFile="$(OutDir)\sourcemod.logic.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
@@ -96,7 +96,7 @@
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Orange Box|Win32"
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
@@ -121,8 +121,8 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;..\sdk;..\..\..\public;..\..\..\public\extensions;..\..\..\public\sourcepawn;"$(HL2SDKOB)";"$(HL2SDKOB)\public";"$(HL2SDKOB)\public\engine";"$(HL2SDKOB)\public\game\server";"$(HL2SDKOB)\public\tier0";"$(HL2SDKOB)\public\tier1";"$(MMSOURCE17)\core";"$(MMSOURCE17)\core\sourcehook""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;CSTRIKE_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;ORANGEBOX_BUILD"
|
||||
AdditionalIncludeDirectories="..;"$(MMSOURCE17)\core\sourcehook";..\..\..\public;..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_LOGIC;SM_DEFAULT_THREADER"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
RuntimeTypeInfo="false"
|
||||
@@ -142,9 +142,9 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies=""$(HL2SDKOB)\lib\public\tier0.lib" "$(HL2SDKOB)\lib\public\tier1.lib""
|
||||
OutputFile="$(OutDir)\game.tf2.ext.dll"
|
||||
OutputFile="$(OutDir)\sourcemod.logic.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
@@ -185,23 +185,111 @@
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\criticals.cpp"
|
||||
RelativePath="..\common_logic.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\extension.cpp"
|
||||
RelativePath="..\GameConfigs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\natives.cpp"
|
||||
RelativePath="..\MemoryUtils.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\RegNatives.cpp"
|
||||
RelativePath="..\PhraseCollection.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\util.cpp"
|
||||
RelativePath="..\Profiler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sm_crc32.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_admin.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_adt_array.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_adt_stack.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_adt_trie.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_banning.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_datapacks.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_float.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_functions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_gameconfigs.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_handles.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_lang.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_maplists.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_players.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_sorting.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_string.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_textparse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_timers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\stringutil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\TextParsers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ThreadSupport.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Translator.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@@ -211,19 +299,31 @@
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\criticals.h"
|
||||
RelativePath="..\CellArray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\extension.h"
|
||||
RelativePath="..\common_logic.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\RegNatives.h"
|
||||
RelativePath="..\intercom.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\util.h"
|
||||
RelativePath="..\Profiler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\svn_version.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\TextParsers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ThreadSupport.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@@ -233,54 +333,45 @@
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\version.rc"
|
||||
RelativePath="..\svn_version.tpl"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="SourceMod SDK"
|
||||
UniqueIdentifier="{31958233-BB2D-4e41-A8F9-CE8A4684F436}"
|
||||
Name="Threads"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_config.h"
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_ext.cpp"
|
||||
<File
|
||||
RelativePath="..\thread\BaseWorker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\ThreadWorker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\WinThreads.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sdk\smsdk_ext.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="CDetour"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\CDetour\detourhelpers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\CDetour\detours.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\CDetour\detours.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="asm"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\asm\asm.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\asm\asm.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\BaseWorker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\ThreadWorker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\WinThreads.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,8 +25,6 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "sm_crc32.h"
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -25,8 +25,6 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CRC32_H_
|
||||
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
|
||||
#define _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
class BaseMemTable
|
||||
{
|
||||
public:
|
||||
BaseMemTable(unsigned int init_size)
|
||||
{
|
||||
membase = (unsigned char *)malloc(init_size);
|
||||
size = init_size;
|
||||
tail = 0;
|
||||
}
|
||||
~BaseMemTable()
|
||||
{
|
||||
free(membase);
|
||||
membase = NULL;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Allocates 'size' bytes of memory.
|
||||
* Optionally outputs the address through 'addr'.
|
||||
* Returns an index >= 0 on success, < 0 on failure.
|
||||
*/
|
||||
int CreateMem(unsigned int addsize, void **addr)
|
||||
{
|
||||
int idx = (int)tail;
|
||||
|
||||
while (tail + addsize >= size) {
|
||||
size *= 2;
|
||||
membase = (unsigned char *)realloc(membase, size);
|
||||
}
|
||||
|
||||
tail += addsize;
|
||||
if (addr)
|
||||
*addr = (void *)&membase[idx];
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an index into the memory table, returns its address.
|
||||
* Returns NULL if invalid.
|
||||
*/
|
||||
void *GetAddress(int index)
|
||||
{
|
||||
if (index < 0 || (unsigned int)index >= tail)
|
||||
return NULL;
|
||||
return &membase[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scraps the memory table. For caching purposes, the memory
|
||||
* is not freed, however subsequent calls to CreateMem() will
|
||||
* begin at the first index again.
|
||||
*/
|
||||
void Reset()
|
||||
{
|
||||
tail = 0;
|
||||
}
|
||||
|
||||
inline unsigned int GetMemUsage()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
inline unsigned int GetActualMemUsed()
|
||||
{
|
||||
return tail;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char *membase;
|
||||
unsigned int size;
|
||||
unsigned int tail;
|
||||
};
|
||||
|
||||
class BaseStringTable
|
||||
{
|
||||
public:
|
||||
BaseStringTable(unsigned int init_size) : m_table(init_size)
|
||||
{
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* Adds a string to the string table and returns its index.
|
||||
*/
|
||||
int AddString(const char *string)
|
||||
{
|
||||
size_t len = strlen(string) + 1;
|
||||
int idx;
|
||||
char *addr;
|
||||
|
||||
idx = m_table.CreateMem(len, (void **)&addr);
|
||||
strcpy(addr, string);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an index into the string table, returns the associated string.
|
||||
*/
|
||||
inline const char *GetString(int str)
|
||||
{
|
||||
return (const char *)m_table.GetAddress(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scraps the string table. For caching purposes, the memory
|
||||
* is not freed, however subsequent calls to AddString() will
|
||||
* begin at the first index again.
|
||||
*/
|
||||
void Reset()
|
||||
{
|
||||
m_table.Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent BaseMemTable that this string table uses.
|
||||
*/
|
||||
inline BaseMemTable *GetMemTable()
|
||||
{
|
||||
return &m_table;
|
||||
}
|
||||
private:
|
||||
BaseMemTable m_table;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
|
||||
#define _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define KESTRING_TABLE_START_SIZE 65536
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
size_t length;
|
||||
uint32_t hash;
|
||||
void *address;
|
||||
Symbol *tbl_next;
|
||||
|
||||
inline char *buffer()
|
||||
{
|
||||
return reinterpret_cast<char *>(this + 1);
|
||||
}
|
||||
};
|
||||
|
||||
class SymbolTable
|
||||
{
|
||||
public:
|
||||
~SymbolTable()
|
||||
{
|
||||
for (uint32_t i = 0; i < nbuckets; i++)
|
||||
{
|
||||
Symbol *sym = buckets[i];
|
||||
while (sym != NULL)
|
||||
{
|
||||
Symbol *next = sym->tbl_next;
|
||||
free(sym);
|
||||
sym = next;
|
||||
}
|
||||
}
|
||||
free(buckets);
|
||||
}
|
||||
|
||||
bool Initialize()
|
||||
{
|
||||
buckets = (Symbol **)malloc(sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
|
||||
if (buckets == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memset(buckets, 0, sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
|
||||
|
||||
nbuckets = KESTRING_TABLE_START_SIZE;
|
||||
nused = 0;
|
||||
bucketmask = KESTRING_TABLE_START_SIZE - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline uint32_t HashString(const char *data, size_t len)
|
||||
{
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
uint32_t hash = len, tmp;
|
||||
int rem;
|
||||
|
||||
if (len <= 0 || data == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rem = len & 3;
|
||||
len >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;len > 0; len--) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2 * sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof (uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
|
||||
#undef get16bits
|
||||
}
|
||||
|
||||
Symbol **FindSymbolBucket(const char *str, size_t len, uint32_t hash)
|
||||
{
|
||||
uint32_t bucket = hash & bucketmask;
|
||||
Symbol **pkvs = &buckets[bucket];
|
||||
|
||||
Symbol *kvs = *pkvs;
|
||||
while (kvs != NULL)
|
||||
{
|
||||
if (len == kvs->length && memcmp(str, kvs->buffer(), len * sizeof(char)) == 0)
|
||||
{
|
||||
return pkvs;
|
||||
}
|
||||
pkvs = &kvs->tbl_next;
|
||||
kvs = *pkvs;
|
||||
}
|
||||
|
||||
return pkvs;
|
||||
}
|
||||
|
||||
void ResizeSymbolTable()
|
||||
{
|
||||
uint32_t xnbuckets = nbuckets * 2;
|
||||
Symbol **xbuckets = (Symbol **)malloc(sizeof(Symbol *) * xnbuckets);
|
||||
if (xbuckets == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memset(xbuckets, 0, sizeof(Symbol *) * xnbuckets);
|
||||
uint32_t xbucketmask = xnbuckets - 1;
|
||||
for (uint32_t i = 0; i < nbuckets; i++)
|
||||
{
|
||||
Symbol *sym = buckets[i];
|
||||
while (sym != NULL)
|
||||
{
|
||||
Symbol *next = sym->tbl_next;
|
||||
uint32_t bucket = sym->hash & xbucketmask;
|
||||
sym->tbl_next = xbuckets[bucket];
|
||||
xbuckets[bucket] = sym;
|
||||
sym = next;
|
||||
}
|
||||
}
|
||||
free(buckets);
|
||||
buckets = xbuckets;
|
||||
nbuckets = xnbuckets;
|
||||
bucketmask = xbucketmask;
|
||||
}
|
||||
|
||||
Symbol *FindSymbol(const char *str, size_t len)
|
||||
{
|
||||
uint32_t hash = HashString(str, len);
|
||||
Symbol **pkvs = FindSymbolBucket(str, len, hash);
|
||||
return *pkvs;
|
||||
}
|
||||
|
||||
Symbol *InternSymbol(const char* str, size_t len, void *address)
|
||||
{
|
||||
uint32_t hash = HashString(str, len);
|
||||
Symbol **pkvs = FindSymbolBucket(str, len, hash);
|
||||
if (*pkvs != NULL)
|
||||
{
|
||||
return *pkvs;
|
||||
}
|
||||
|
||||
Symbol *kvs = (Symbol *)malloc(sizeof(Symbol) + sizeof(char) * (len + 1));
|
||||
kvs->length = len;
|
||||
kvs->hash = hash;
|
||||
kvs->address = address;
|
||||
kvs->tbl_next = NULL;
|
||||
memcpy(kvs + 1, str, sizeof(char) * (len + 1));
|
||||
*pkvs = kvs;
|
||||
nused++;
|
||||
|
||||
if (nused > nbuckets && nbuckets <= INT_MAX / 2)
|
||||
{
|
||||
ResizeSymbolTable();
|
||||
}
|
||||
|
||||
return kvs;
|
||||
}
|
||||
private:
|
||||
uint32_t nbuckets;
|
||||
uint32_t nused;
|
||||
uint32_t bucketmask;
|
||||
Symbol **buckets;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
|
||||
@@ -29,13 +29,15 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "AdminCache.h"
|
||||
#include "ForwardSys.h"
|
||||
#include "common_logic.h"
|
||||
#include <IAdminSystem.h>
|
||||
#include <IForwardSys.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
static cell_t DumpAdminCache(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
g_Admins.DumpAdminCache((AdminCachePart)params[1], (params[2] == 1) ? true : false);
|
||||
adminsys->DumpAdminCache((AdminCachePart)params[1], (params[2] == 1) ? true : false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -44,7 +46,7 @@ static cell_t AddCommandOverride(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
|
||||
pContext->LocalToString(params[1], &str);
|
||||
g_Admins.AddCommandOverride(str, (OverrideType)params[2], (AdminFlag)params[3]);
|
||||
adminsys->AddCommandOverride(str, (OverrideType)params[2], (AdminFlag)params[3]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -56,7 +58,7 @@ static cell_t GetCommandOverride(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
pContext->LocalToString(params[1], &cmd);
|
||||
|
||||
if (!g_Admins.GetCommandOverride(cmd, (OverrideType)params[2], &flags))
|
||||
if (!adminsys->GetCommandOverride(cmd, (OverrideType)params[2], &flags))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -75,7 +77,7 @@ static cell_t UnsetCommandOverride(IPluginContext *pContext, const cell_t *param
|
||||
|
||||
pContext->LocalToString(params[1], &cmd);
|
||||
|
||||
g_Admins.UnsetCommandOverride(cmd, (OverrideType)params[2]);
|
||||
adminsys->UnsetCommandOverride(cmd, (OverrideType)params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -86,7 +88,7 @@ static cell_t CreateAdmGroup(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
pContext->LocalToString(params[1], &str);
|
||||
|
||||
return g_Admins.AddGroup(str);
|
||||
return adminsys->AddGroup(str);
|
||||
}
|
||||
|
||||
static cell_t FindAdmGroup(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -95,7 +97,7 @@ static cell_t FindAdmGroup(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
pContext->LocalToString(params[1], &str);
|
||||
|
||||
return g_Admins.FindGroupByName(str);
|
||||
return adminsys->FindGroupByName(str);
|
||||
}
|
||||
|
||||
static cell_t SetAdmGroupAddFlag(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -104,7 +106,7 @@ static cell_t SetAdmGroupAddFlag(IPluginContext *pContext, const cell_t *params)
|
||||
AdminFlag flag = (AdminFlag)params[2];
|
||||
bool enabled = params[3] ? 1 : 0;
|
||||
|
||||
g_Admins.SetGroupAddFlag(id, flag, enabled);
|
||||
adminsys->SetGroupAddFlag(id, flag, enabled);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -114,7 +116,7 @@ static cell_t GetAdmGroupAddFlag(IPluginContext *pContext, const cell_t *params)
|
||||
GroupId id = (GroupId)params[1];
|
||||
AdminFlag flag = (AdminFlag)params[2];
|
||||
|
||||
return g_Admins.GetGroupAddFlag(id, flag) ? 1 : 0;
|
||||
return adminsys->GetGroupAddFlag(id, flag) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t SetAdmGroupImmunity(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -123,7 +125,7 @@ static cell_t SetAdmGroupImmunity(IPluginContext *pContext, const cell_t *params
|
||||
ImmunityType type = (ImmunityType)params[2];
|
||||
bool enabled = params[3] ? 1 : 0;
|
||||
|
||||
g_Admins.SetGroupGenericImmunity(id, type, enabled);
|
||||
adminsys->SetGroupGenericImmunity(id, type, enabled);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -133,7 +135,7 @@ static cell_t GetAdmGroupImmunity(IPluginContext *pContext, const cell_t *params
|
||||
GroupId id = (GroupId)params[1];
|
||||
ImmunityType type = (ImmunityType)params[2];
|
||||
|
||||
return g_Admins.GetGroupGenericImmunity(id, type) ? 1 : 0;
|
||||
return adminsys->GetGroupGenericImmunity(id, type) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t SetAdmGroupImmuneFrom(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -141,7 +143,7 @@ static cell_t SetAdmGroupImmuneFrom(IPluginContext *pContext, const cell_t *para
|
||||
GroupId id = (GroupId)params[1];
|
||||
GroupId other_id = (GroupId)params[2];
|
||||
|
||||
g_Admins.AddGroupImmunity(id, other_id);
|
||||
adminsys->AddGroupImmunity(id, other_id);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -150,14 +152,14 @@ static cell_t GetAdmGroupImmuneCount(IPluginContext *pContext, const cell_t *par
|
||||
{
|
||||
GroupId id = (GroupId)params[1];
|
||||
|
||||
return g_Admins.GetGroupImmunityCount(id);
|
||||
return adminsys->GetGroupImmunityCount(id);
|
||||
}
|
||||
|
||||
static cell_t GetAdmGroupImmuneFrom(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GroupId id = (GroupId)params[1];
|
||||
|
||||
return g_Admins.GetGroupImmunity(id, params[2]);
|
||||
return adminsys->GetGroupImmunity(id, params[2]);
|
||||
}
|
||||
|
||||
static cell_t AddAdmGroupCmdOverride(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -169,7 +171,7 @@ static cell_t AddAdmGroupCmdOverride(IPluginContext *pContext, const cell_t *par
|
||||
|
||||
pContext->LocalToString(params[2], &cmd);
|
||||
|
||||
g_Admins.AddGroupCommandOverride(id, cmd, type, rule);
|
||||
adminsys->AddGroupCommandOverride(id, cmd, type, rule);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -183,7 +185,7 @@ static cell_t GetAdmGroupCmdOverride(IPluginContext *pContext, const cell_t *par
|
||||
|
||||
pContext->LocalToString(params[2], &cmd);
|
||||
|
||||
if (!g_Admins.GetGroupCommandOverride(id, cmd, type, &rule))
|
||||
if (!adminsys->GetGroupCommandOverride(id, cmd, type, &rule))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -198,7 +200,7 @@ static cell_t GetAdmGroupCmdOverride(IPluginContext *pContext, const cell_t *par
|
||||
static cell_t GetAdmGroupAddFlags(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
GroupId id = (GroupId)params[1];
|
||||
return g_Admins.GetGroupAddFlags(id);
|
||||
return adminsys->GetGroupAddFlags(id);
|
||||
}
|
||||
|
||||
static cell_t RegisterAuthIdentType(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -206,7 +208,7 @@ static cell_t RegisterAuthIdentType(IPluginContext *pContext, const cell_t *para
|
||||
char *type;
|
||||
pContext->LocalToString(params[1], &type);
|
||||
|
||||
g_Admins.RegisterAuthIdentType(type);
|
||||
adminsys->RegisterAuthIdentType(type);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -221,14 +223,14 @@ static cell_t CreateAdmin(IPluginContext *pContext, const cell_t *params)
|
||||
admin = NULL;
|
||||
}
|
||||
|
||||
return g_Admins.CreateAdmin(admin);
|
||||
return adminsys->CreateAdmin(admin);
|
||||
}
|
||||
|
||||
static cell_t GetAdminUsername(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
AdminId id = params[1];
|
||||
size_t written;
|
||||
const char *name = g_Admins.GetAdminName(id);
|
||||
const char *name = adminsys->GetAdminName(id);
|
||||
|
||||
if (!name)
|
||||
{
|
||||
@@ -248,7 +250,7 @@ static cell_t BindAdminIdentity(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[2], &auth);
|
||||
pContext->LocalToString(params[3], &ident);
|
||||
|
||||
return g_Admins.BindAdminIdentity(id, auth, ident);
|
||||
return adminsys->BindAdminIdentity(id, auth, ident);
|
||||
}
|
||||
|
||||
static cell_t SetAdminFlag(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -257,7 +259,7 @@ static cell_t SetAdminFlag(IPluginContext *pContext, const cell_t *params)
|
||||
AdminFlag flag = (AdminFlag)params[2];
|
||||
bool enabled = params[3] ? true : false;
|
||||
|
||||
g_Admins.SetAdminFlag(id, flag, enabled);
|
||||
adminsys->SetAdminFlag(id, flag, enabled);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -268,7 +270,7 @@ static cell_t GetAdminFlag(IPluginContext *pContext, const cell_t *params)
|
||||
AdminFlag flag = (AdminFlag)params[2];
|
||||
AccessMode mode = (AccessMode)params[3];
|
||||
|
||||
return g_Admins.GetAdminFlag(id, flag, mode);
|
||||
return adminsys->GetAdminFlag(id, flag, mode);
|
||||
}
|
||||
|
||||
static cell_t GetAdminFlags(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -276,7 +278,7 @@ static cell_t GetAdminFlags(IPluginContext *pContext, const cell_t *params)
|
||||
AdminId id = params[1];
|
||||
AccessMode mode = (AccessMode)params[2];
|
||||
|
||||
return g_Admins.GetAdminFlags(id, mode);
|
||||
return adminsys->GetAdminFlags(id, mode);
|
||||
}
|
||||
|
||||
static cell_t AdminInheritGroup(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -284,14 +286,14 @@ static cell_t AdminInheritGroup(IPluginContext *pContext, const cell_t *params)
|
||||
AdminId id = params[1];
|
||||
GroupId gid = params[2];
|
||||
|
||||
return g_Admins.AdminInheritGroup(id, gid);
|
||||
return adminsys->AdminInheritGroup(id, gid);
|
||||
}
|
||||
|
||||
static cell_t GetAdminGroupCount(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
AdminId id = params[1];
|
||||
|
||||
return g_Admins.GetAdminGroupCount(id);
|
||||
return adminsys->GetAdminGroupCount(id);
|
||||
}
|
||||
|
||||
static cell_t GetAdminGroup(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -301,7 +303,7 @@ static cell_t GetAdminGroup(IPluginContext *pContext, const cell_t *params)
|
||||
const char *name;
|
||||
GroupId gid;
|
||||
|
||||
if ((gid=g_Admins.GetAdminGroup(id, index, &name)) == INVALID_GROUP_ID)
|
||||
if ((gid=adminsys->GetAdminGroup(id, index, &name)) == INVALID_GROUP_ID)
|
||||
{
|
||||
return gid;
|
||||
}
|
||||
@@ -323,7 +325,7 @@ static cell_t SetAdminPassword(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
pContext->LocalToString(params[2], &password);
|
||||
|
||||
g_Admins.SetAdminPassword(id, password);
|
||||
adminsys->SetAdminPassword(id, password);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -331,7 +333,7 @@ static cell_t SetAdminPassword(IPluginContext *pContext, const cell_t *params)
|
||||
static cell_t GetAdminPassword(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
AdminId id = params[1];
|
||||
const char *password = g_Admins.GetAdminPassword(id);
|
||||
const char *password = adminsys->GetAdminPassword(id);
|
||||
|
||||
if (!password)
|
||||
{
|
||||
@@ -350,14 +352,14 @@ static cell_t FindAdminByIdentity(IPluginContext *pContext, const cell_t *params
|
||||
pContext->LocalToString(params[1], &auth);
|
||||
pContext->LocalToString(params[2], &ident);
|
||||
|
||||
return g_Admins.FindAdminByIdentity(auth, ident);
|
||||
return adminsys->FindAdminByIdentity(auth, ident);
|
||||
}
|
||||
|
||||
static cell_t RemoveAdmin(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
AdminId id = params[1];
|
||||
|
||||
return g_Admins.InvalidateAdmin(id);
|
||||
return adminsys->InvalidateAdmin(id);
|
||||
}
|
||||
|
||||
static cell_t FlagBitsToBitArray(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -365,7 +367,7 @@ static cell_t FlagBitsToBitArray(IPluginContext *pContext, const cell_t *params)
|
||||
FlagBits bits = (FlagBits)params[1];
|
||||
bool array[AdminFlags_TOTAL];
|
||||
cell_t *addr;
|
||||
unsigned int numWr = g_Admins.FlagBitsToBitArray(bits, array, AdminFlags_TOTAL);
|
||||
unsigned int numWr = adminsys->FlagBitsToBitArray(bits, array, AdminFlags_TOTAL);
|
||||
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
@@ -391,7 +393,7 @@ static cell_t FlagBitArrayToBits(IPluginContext *pContext, const cell_t *params)
|
||||
array[i] = addr[i] ? true : false;
|
||||
}
|
||||
|
||||
return g_Admins.FlagBitArrayToBits(array, num);
|
||||
return adminsys->FlagBitArrayToBits(array, num);
|
||||
}
|
||||
|
||||
static cell_t FlagArrayToBits(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -401,7 +403,7 @@ static cell_t FlagArrayToBits(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (sizeof(AdminFlag) == sizeof(cell_t))
|
||||
{
|
||||
return g_Admins.FlagArrayToBits((const AdminFlag *)addr, params[2]);
|
||||
return adminsys->FlagArrayToBits((const AdminFlag *)addr, params[2]);
|
||||
} else {
|
||||
AdminFlag flags[AdminFlags_TOTAL];
|
||||
unsigned int num = ((unsigned)params[2] > AdminFlags_TOTAL ? AdminFlags_TOTAL : params[2]);
|
||||
@@ -410,7 +412,7 @@ static cell_t FlagArrayToBits(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
flags[i] = (AdminFlag)addr[i];
|
||||
}
|
||||
return g_Admins.FlagArrayToBits(flags, num);
|
||||
return adminsys->FlagArrayToBits(flags, num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,11 +423,11 @@ static cell_t FlagBitsToArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (sizeof(AdminFlag) == sizeof(cell_t))
|
||||
{
|
||||
return g_Admins.FlagBitsToArray(params[1], (AdminFlag *)addr, params[3]);
|
||||
return adminsys->FlagBitsToArray(params[1], (AdminFlag *)addr, params[3]);
|
||||
} else {
|
||||
AdminFlag flags[AdminFlags_TOTAL];
|
||||
unsigned int num = ((unsigned)params[2] > AdminFlags_TOTAL ? AdminFlags_TOTAL : params[2]);
|
||||
num = g_Admins.FlagBitsToArray(params[1], flags, num);
|
||||
num = adminsys->FlagBitsToArray(params[1], flags, num);
|
||||
|
||||
for (unsigned int i=0; i<num; i++)
|
||||
{
|
||||
@@ -438,36 +440,36 @@ static cell_t FlagBitsToArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
static cell_t CanAdminTarget(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Admins.CanAdminTarget(params[1], params[2]) ? 1 : 0;
|
||||
return adminsys->CanAdminTarget(params[1], params[2]) ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t CreateAuthMethod(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *name;
|
||||
pContext->LocalToString(params[1], &name);
|
||||
g_Admins.RegisterAuthIdentType(name);
|
||||
adminsys->RegisterAuthIdentType(name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t SetAdmGroupImmunityLevel(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Admins.SetGroupImmunityLevel(params[1], params[2]);
|
||||
return adminsys->SetGroupImmunityLevel(params[1], params[2]);
|
||||
}
|
||||
|
||||
static cell_t GetAdmGroupImmunityLevel(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Admins.GetGroupImmunityLevel(params[1]);
|
||||
return adminsys->GetGroupImmunityLevel(params[1]);
|
||||
}
|
||||
|
||||
static cell_t SetAdminImmunityLevel(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Admins.SetAdminImmunityLevel(params[1], params[2]);
|
||||
return adminsys->SetAdminImmunityLevel(params[1], params[2]);
|
||||
}
|
||||
|
||||
static cell_t GetAdminImmunityLevel(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return g_Admins.GetAdminImmunityLevel(params[1]);
|
||||
return adminsys->GetAdminImmunityLevel(params[1]);
|
||||
}
|
||||
|
||||
static cell_t FindFlagByName(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -479,7 +481,7 @@ static cell_t FindFlagByName(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
AdminFlag admflag;
|
||||
if (!g_Admins.FindFlag(flag, &admflag))
|
||||
if (!adminsys->FindFlag(flag, &admflag))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -495,7 +497,7 @@ static cell_t FindFlagByChar(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
AdminFlag admflag;
|
||||
if (!g_Admins.FindFlag((char)params[1], &admflag))
|
||||
if (!adminsys->FindFlag((char)params[1], &admflag))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -505,6 +507,22 @@ static cell_t FindFlagByChar(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t FindFlagChar(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
char flagchar;
|
||||
if (!adminsys->FindFlagChar((AdminFlag)params[1], &flagchar))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*addr = (cell_t)flagchar;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t ReadFlagString(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
char *flag;
|
||||
@@ -514,7 +532,7 @@ static cell_t ReadFlagString(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToPhysAddr(params[2], &addr);
|
||||
|
||||
const char *end = flag;
|
||||
FlagBits bits = g_Admins.ReadFlagString(flag, &end);
|
||||
FlagBits bits = adminsys->ReadFlagString(flag, &end);
|
||||
|
||||
*addr = end - flag;
|
||||
|
||||
@@ -561,6 +579,7 @@ REGISTER_NATIVES(adminNatives)
|
||||
{"CreateAuthMethod", CreateAuthMethod},
|
||||
{"FindFlagByName", FindFlagByName},
|
||||
{"FindFlagByChar", FindFlagByChar},
|
||||
{"FindFlagChar", FindFlagChar},
|
||||
{"ReadFlagString", ReadFlagString},
|
||||
{"GetAdmGroupImmunityLevel",GetAdmGroupImmunityLevel},
|
||||
{"SetAdmGroupImmunityLevel",SetAdmGroupImmunityLevel},
|
||||
@@ -30,10 +30,8 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "common_logic.h"
|
||||
#include "CellArray.h"
|
||||
#include "HandleSys.h"
|
||||
|
||||
HandleType_t htCellArray;
|
||||
|
||||
@@ -44,11 +42,11 @@ class CellArrayHelpers :
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
htCellArray = handlesys->CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
}
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
|
||||
handlesys->RemoveType(htCellArray, g_pCoreIdent);
|
||||
}
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -78,7 +76,7 @@ static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
|
||||
array->resize(params[2]);
|
||||
}
|
||||
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete array;
|
||||
@@ -93,7 +91,7 @@ static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -110,7 +108,7 @@ static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -130,7 +128,7 @@ static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -145,7 +143,7 @@ static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -168,7 +166,7 @@ static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -183,7 +181,7 @@ static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
pContext->LocalToString(params[2], &str);
|
||||
|
||||
strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
|
||||
return (cell_t)(array->size() - 1);
|
||||
}
|
||||
@@ -194,7 +192,7 @@ static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -226,7 +224,7 @@ static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -265,7 +263,7 @@ static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -291,7 +289,7 @@ static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -324,7 +322,7 @@ static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -363,7 +361,7 @@ static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -380,7 +378,7 @@ static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
pContext->LocalToString(params[3], &str);
|
||||
|
||||
return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
return smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
}
|
||||
|
||||
static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -389,7 +387,7 @@ static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -422,7 +420,7 @@ static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -445,7 +443,7 @@ static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -468,7 +466,7 @@ static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -496,7 +494,7 @@ static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -504,7 +502,7 @@ static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
CellArray *array = oldArray->clone();
|
||||
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete array;
|
||||
@@ -519,7 +517,7 @@ static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -546,7 +544,7 @@ static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user