Compare commits
2679
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34b5caf464 | ||
|
|
ecae5b0479 | ||
|
|
1ab9dc141f | ||
|
|
6a8529460f | ||
|
|
c63e2b318f | ||
|
|
c4a3c421ff | ||
|
|
cb3d03d699 | ||
|
|
faad5ff3ea | ||
|
|
cc02c00fd4 | ||
|
|
2bedba3f2c | ||
|
|
369f96ddfb | ||
|
|
ab1fb8309e | ||
|
|
5e9f27fe6d | ||
|
|
b8e4510f7e | ||
|
|
0d69ce8b9a | ||
|
|
a66f93b64b | ||
|
|
702ac32bc0 | ||
|
|
97c9cc9b23 | ||
|
|
f38f097396 | ||
|
|
b10edfa86f | ||
|
|
cf92376962 | ||
|
|
92d8d96cd9 | ||
|
|
ce7a98dffa | ||
|
|
f3af8539d2 | ||
|
|
35e12b16ba | ||
|
|
6e9c95034e | ||
|
|
34968def58 | ||
|
|
4800732c00 | ||
|
|
7d7bf38941 | ||
|
|
5c13a0bc69 | ||
|
|
3e63e611c2 | ||
|
|
c3598d8e71 | ||
|
|
f57097651b | ||
|
|
a5450aad18 | ||
|
|
0a4a06d9e1 | ||
|
|
dd51da519d | ||
|
|
c79f52e2c9 | ||
|
|
c4279da3b2 | ||
|
|
3923177037 | ||
|
|
80a0e24b66 | ||
|
|
75d770ba0f | ||
|
|
d9e6daa006 | ||
|
|
f08b60bc98 | ||
|
|
4d98fc2a3d | ||
|
|
0b4ec459d3 | ||
|
|
65269551f9 | ||
|
|
47b0022331 | ||
|
|
7df2b28fe0 | ||
|
|
7df1069613 | ||
|
|
7585acaeef | ||
|
|
dfcf953131 | ||
|
|
cb31a65807 | ||
|
|
6123c5e013 | ||
|
|
cb73b935ec | ||
|
|
76e8e7e50c | ||
|
|
40d049e1f6 | ||
|
|
48012ccf08 | ||
|
|
80ceb149b0 | ||
|
|
1ef60a13d0 | ||
|
|
e8e40d126e | ||
|
|
c7033827f5 | ||
|
|
ff27214615 | ||
|
|
7b45e963d5 | ||
|
|
96965ef7cd | ||
|
|
8f7ce184fb | ||
|
|
4bed0a2893 | ||
|
|
6ab2e23d9d | ||
|
|
dd27de8d85 | ||
|
|
8c79a6df33 | ||
|
|
e8111f3c0a | ||
|
|
a038181193 | ||
|
|
52fe916311 | ||
|
|
d01d7b1879 | ||
|
|
d8406a3efc | ||
|
|
d74204aded | ||
|
|
77be859667 | ||
|
|
71193c67b2 | ||
|
|
cc1493aa66 | ||
|
|
43946e6b6f | ||
|
|
5776909b13 | ||
|
|
048c227fcc | ||
|
|
95ab81f0db | ||
|
|
2fb01e412e | ||
|
|
6e9b4bf276 | ||
|
|
b344e81816 | ||
|
|
fec133bee6 | ||
|
|
594cc249ef | ||
|
|
0967035dd0 | ||
|
|
7e93cf8f6b | ||
|
|
7f20a7b6bb | ||
|
|
a9de6ed52c | ||
|
|
f0f50aa7bb | ||
|
|
36fab677a0 | ||
|
|
6c0d2a3743 | ||
|
|
e71eb5f704 | ||
|
|
4532b8a38d | ||
|
|
a089235b21 | ||
|
|
9f9f2baae2 | ||
|
|
49a643f411 | ||
|
|
8d7e8b2a85 | ||
|
|
848bc927a0 | ||
|
|
18d0f2a140 | ||
|
|
91a796b24d | ||
|
|
7e7544e036 | ||
|
|
9d676ed440 | ||
|
|
bad5252ee3 | ||
|
|
a2951b9ea8 | ||
|
|
f98cd68341 | ||
|
|
45b9573348 | ||
|
|
7553106eee | ||
|
|
5cf73385c5 | ||
|
|
7a96467045 | ||
|
|
86c1660ee9 | ||
|
|
8e4836f83a | ||
|
|
00c09584c7 | ||
|
|
7677e8af79 | ||
|
|
69cb941fa4 | ||
|
|
17a7d4802d | ||
|
|
0b2610e3b3 | ||
|
|
51a02652d8 | ||
|
|
e7870da5ff | ||
|
|
a697e81427 | ||
|
|
5f8288dc70 | ||
|
|
feb5050df1 | ||
|
|
0d79b7a542 | ||
|
|
e4328f9211 | ||
|
|
70518a8e49 | ||
|
|
6ac897f9f3 | ||
|
|
ec9791b183 | ||
|
|
d5c267b291 | ||
|
|
3de533a73e | ||
|
|
f1f135adb6 | ||
|
|
91077fdc91 | ||
|
|
f250461648 | ||
|
|
6a98e40643 | ||
|
|
36c342fc7b | ||
|
|
39ff3f9993 | ||
|
|
7026e68b06 | ||
|
|
25ea80890d | ||
|
|
2379c76b03 | ||
|
|
e6d8416f0e | ||
|
|
cb16a78681 | ||
|
|
2930fb1963 | ||
|
|
d7b49f7706 | ||
|
|
695fc802a9 | ||
|
|
c37dbe131e | ||
|
|
88af898285 | ||
|
|
cd106a7eb6 | ||
|
|
975fc93e1f | ||
|
|
6c37a5d9f3 | ||
|
|
7b59b7f384 | ||
|
|
0ca218931a | ||
|
|
1d9f769a42 | ||
|
|
083edcedc7 | ||
|
|
fb5c3c86da | ||
|
|
3c89f2b1c2 | ||
|
|
4c7cf6ce06 | ||
|
|
195104487e | ||
|
|
39993c7019 | ||
|
|
897aa42135 | ||
|
|
abdf7d5b07 | ||
|
|
9f8f879590 | ||
|
|
db14d2d00a | ||
|
|
a0f3410f3b | ||
|
|
4159e1a177 | ||
|
|
4f7b0ff487 | ||
|
|
891ebe4480 | ||
|
|
859be35b34 | ||
|
|
88c452581b | ||
|
|
b0ccc87638 | ||
|
|
1e6843f8db | ||
|
|
76a589f689 | ||
|
|
e7621ad8a7 | ||
|
|
c4232510a1 | ||
|
|
e2878d3df8 | ||
|
|
5cb10441d7 | ||
|
|
6ee42dc7fe | ||
|
|
e0f6544c86 | ||
|
|
ab68e70998 | ||
|
|
8be1feadc1 | ||
|
|
beb3f8c1d4 | ||
|
|
35784c018d | ||
|
|
dc4c3f2f1a | ||
|
|
9ff6cdef8c | ||
|
|
dbc881143b | ||
|
|
556d5e0949 | ||
|
|
6456b937be | ||
|
|
05d8622ea9 | ||
|
|
f1387c892e | ||
|
|
cae5d48d31 | ||
|
|
d83d72fd88 | ||
|
|
ff42e854bb | ||
|
|
a462feee61 | ||
|
|
5eef4bccd3 | ||
|
|
609fa50763 | ||
|
|
7868767dde | ||
|
|
6ac013376f | ||
|
|
cfde247ef7 | ||
|
|
ac11eb8910 | ||
|
|
cd0d31805c | ||
|
|
cf617a4d20 | ||
|
|
84de0f6b85 | ||
|
|
914a0a7fc1 | ||
|
|
f82420b601 | ||
|
|
5193b70ada | ||
|
|
4b2b50a3df | ||
|
|
9ed3a55ade | ||
|
|
53a8d5ac30 | ||
|
|
b4144d2cff | ||
|
|
5bbcc7322c | ||
|
|
3f81397a84 | ||
|
|
c744b39c6d | ||
|
|
1a97d37215 | ||
|
|
2bc7e4736f | ||
|
|
5681b99fd8 | ||
|
|
9a5efc2de2 | ||
|
|
692af52ea7 | ||
|
|
ee51295d22 | ||
|
|
3c7a08afc2 | ||
|
|
ed9ca9e943 | ||
|
|
fbaa3a804f | ||
|
|
9f0308530c | ||
|
|
2e89d91a86 | ||
|
|
e20e4677df | ||
|
|
97c581f72c | ||
|
|
c079a3b58a | ||
|
|
c6de58aa05 | ||
|
|
4fd0e3acd8 | ||
|
|
3145daa46a | ||
|
|
3c52840dd8 | ||
|
|
8ed66980c0 | ||
|
|
365da7fef6 | ||
|
|
9af5023a8f | ||
|
|
878201c631 | ||
|
|
e65d11f4de | ||
|
|
1a89edec47 | ||
|
|
1143b3f56f | ||
|
|
1b4017c6b7 | ||
|
|
15224c6df5 | ||
|
|
e831757313 | ||
|
|
a47388ff76 | ||
|
|
71f4f36f8c | ||
|
|
a4e387331a | ||
|
|
defdc617b3 | ||
|
|
61b6a32631 | ||
|
|
1fdf1c0264 | ||
|
|
32f019c70c | ||
|
|
9c62e94239 | ||
|
|
b4ff034ac2 | ||
|
|
6b27a7fe46 | ||
|
|
adc9569e23 | ||
|
|
4cd6c37ab5 | ||
|
|
f15234e4f8 | ||
|
|
29ff05bd62 | ||
|
|
e9b4a6e96c | ||
|
|
530078b3ae | ||
|
|
5149205109 | ||
|
|
55b77a1925 | ||
|
|
bc5691c4b6 | ||
|
|
0513f93f9d | ||
|
|
b5decd8a50 | ||
|
|
b1901da79f | ||
|
|
6f47b1a89d | ||
|
|
cec703a059 | ||
|
|
217eb68455 | ||
|
|
f0d6fd1912 | ||
|
|
b0061ece62 | ||
|
|
0b6603ab2b | ||
|
|
09546b0d2a | ||
|
|
799ee7b9c6 | ||
|
|
b0b28b7a6e | ||
|
|
bbe7a9dd6a | ||
|
|
ecec7dbef3 | ||
|
|
d66a7b0ee0 | ||
|
|
61c4d2b805 | ||
|
|
73d8072693 | ||
|
|
c64edf31fc | ||
|
|
cb32e3d8f9 | ||
|
|
e69e9eddc7 | ||
|
|
aa85a1866e | ||
|
|
623925a1cf | ||
|
|
b6792a2c8c | ||
|
|
7248ad9aba | ||
|
|
d44b8aa853 | ||
|
|
f8d6ecbc02 | ||
|
|
bd76558b94 | ||
|
|
63451b7b6b | ||
|
|
edc42800ba | ||
|
|
0608d47219 | ||
|
|
5efb5068cd | ||
|
|
14f31006c1 | ||
|
|
90c8440f17 | ||
|
|
c3e9d7de41 | ||
|
|
9badb14c3a | ||
|
|
655994cd09 | ||
|
|
217ca928d5 | ||
|
|
fdae6cf1b0 | ||
|
|
e708cdf28c | ||
|
|
2d616a5995 | ||
|
|
563dd617af | ||
|
|
2c399ec441 | ||
|
|
57067d38fe | ||
|
|
2f6b64e92e | ||
|
|
00b06313c9 | ||
|
|
2b015a1d5b | ||
|
|
010220ea25 | ||
|
|
95a56972a1 | ||
|
|
a8ff00bc34 | ||
|
|
9abac06e85 | ||
|
|
ee595978f8 | ||
|
|
49d769282b | ||
|
|
451c90b932 | ||
|
|
9215ddcf8a | ||
|
|
fb0fd0c6d2 | ||
|
|
9c1902b0e3 | ||
|
|
cf8d05ae98 | ||
|
|
8c513faad5 | ||
|
|
6e8d9ff788 | ||
|
|
0e6cbf989e | ||
|
|
d6bbb765c1 | ||
|
|
b411b60ed7 | ||
|
|
692cafa784 | ||
|
|
6600a8c60b | ||
|
|
cebede3a79 | ||
|
|
db756f482b | ||
|
|
cd349946e8 | ||
|
|
b4156a19c3 | ||
|
|
b3e2647dc4 | ||
|
|
e9f0d1f513 | ||
|
|
21cae97820 | ||
|
|
74989d925e | ||
|
|
b402d77ff9 | ||
|
|
8431925577 | ||
|
|
22e8b53029 | ||
|
|
aa75fd24d8 | ||
|
|
f8f4cebe9e | ||
|
|
7d7db6d5bb | ||
|
|
38bbb8580f | ||
|
|
8a7af5ba0d | ||
|
|
a98d277cf3 | ||
|
|
3c6dd2cb79 | ||
|
|
5b96047ce8 | ||
|
|
692f597808 | ||
|
|
10f878d8c7 | ||
|
|
8987a34078 | ||
|
|
ba99d0154b | ||
|
|
977bf4d583 | ||
|
|
06efa7c52b | ||
|
|
84d58ff421 | ||
|
|
c679b97e5f | ||
|
|
b99ab3d1d2 | ||
|
|
ce6b993954 | ||
|
|
e95c2ba0b9 | ||
|
|
ab6971656b | ||
|
|
01fc010719 | ||
|
|
37c84448a9 | ||
|
|
d259be7b1f | ||
|
|
9be71eea2f | ||
|
|
a4d841655b | ||
|
|
162c69bfda | ||
|
|
c5f496670d | ||
|
|
53a0acc2e3 | ||
|
|
75d950e4b0 | ||
|
|
5abd9edf62 | ||
|
|
e00e879af5 | ||
|
|
8476832dc2 | ||
|
|
0ab8f4a1bd | ||
|
|
79f825cc44 | ||
|
|
f351e20de3 | ||
|
|
925d514224 | ||
|
|
36cc7610a1 | ||
|
|
06d2017a95 | ||
|
|
0da68844a5 | ||
|
|
1f6733562d | ||
|
|
4093fa0588 | ||
|
|
39c82d6ea0 | ||
|
|
03c7a9d5f3 | ||
|
|
65b32b8ced | ||
|
|
41f74d1a5c | ||
|
|
13e65a73a4 | ||
|
|
dc1234ddfb | ||
|
|
5d8f5c890d | ||
|
|
e2eabc7a96 | ||
|
|
a33977c71c | ||
|
|
9de1a1ddfa | ||
|
|
7dcdaf0319 | ||
|
|
b3d64d1121 | ||
|
|
52ff6fd5f8 | ||
|
|
af7b8cd9a3 | ||
|
|
b0ee5ce485 | ||
|
|
4a65e38d54 | ||
|
|
097d2d902c | ||
|
|
9d15512f3b | ||
|
|
3bbb48ce9e | ||
|
|
a709307fab | ||
|
|
06c73813ca | ||
|
|
5acc7209b2 | ||
|
|
9fe11f9c36 | ||
|
|
fb734e4124 | ||
|
|
7c1fb6e5b9 | ||
|
|
40d03f78cf | ||
|
|
7f8c6a9fd6 | ||
|
|
832187be31 | ||
|
|
a2f8f1e70d | ||
|
|
3f3343e945 | ||
|
|
4e077402e5 | ||
|
|
ad5740f8a7 | ||
|
|
310f77d96a | ||
|
|
121c3973d6 | ||
|
|
17212616d7 | ||
|
|
876ba3bef5 | ||
|
|
9a0918a354 | ||
|
|
cfad3b26ca | ||
|
|
a55b000273 | ||
|
|
b69b0de234 | ||
|
|
6d320163a1 | ||
|
|
ae21f29ad9 | ||
|
|
f82224eba0 | ||
|
|
c2cfe60102 | ||
|
|
75e622e879 | ||
|
|
9c19f6efb7 | ||
|
|
58995fc829 | ||
|
|
54ed1807c0 | ||
|
|
e1a820dcf9 | ||
|
|
b749bbf42b | ||
|
|
bdbc3c3b58 | ||
|
|
b83810b986 | ||
|
|
462b543816 | ||
|
|
29ddb9f4d9 | ||
|
|
398b05afed | ||
|
|
f0e4fe66ba | ||
|
|
fa057e76f3 | ||
|
|
47906fbcb7 | ||
|
|
5df8c9290f | ||
|
|
1938be9e28 | ||
|
|
839e292819 | ||
|
|
056f64ad40 | ||
|
|
c13a0a2e7a | ||
|
|
1cf12085fc | ||
|
|
d9946b49c4 | ||
|
|
c5ca58a95b | ||
|
|
591255c793 | ||
|
|
2ea5e6d090 | ||
|
|
e01fc5e697 | ||
|
|
0775976165 | ||
|
|
d2f719171d | ||
|
|
c9c147a814 | ||
|
|
31aa230cba | ||
|
|
880be015ae | ||
|
|
96d6cf8def | ||
|
|
66dd3f08b1 | ||
|
|
2175e561cc | ||
|
|
35191745ca | ||
|
|
661af1c5e2 | ||
|
|
bd1ee1f805 | ||
|
|
9e926bdb1d | ||
|
|
edab49c4ef | ||
|
|
bbbbc8b311 | ||
|
|
d5c1111fda | ||
|
|
26a76365f4 | ||
|
|
3a20ae16e1 | ||
|
|
e0746e1ab8 | ||
|
|
24c623c2fa | ||
|
|
5e1d207eae | ||
|
|
3e15966c3e | ||
|
|
ff54fb431f | ||
|
|
1ba6b2653a | ||
|
|
1d1b5d1c6d | ||
|
|
9027d15211 | ||
|
|
5bde264c43 | ||
|
|
67a2fe3751 | ||
|
|
e3cb33bbda | ||
|
|
3174fb7d19 | ||
|
|
1836f69cf0 | ||
|
|
985b7831cf | ||
|
|
fbc851ceae | ||
|
|
55bf8ec095 | ||
|
|
39e955c412 | ||
|
|
f8c065c182 | ||
|
|
ed6fe7519a | ||
|
|
d808d6d8a5 | ||
|
|
b471109c08 | ||
|
|
9978b07956 | ||
|
|
1b3ff094fa | ||
|
|
75ce4c395a | ||
|
|
427e93c573 | ||
|
|
46327563f2 | ||
|
|
3308f0644c | ||
|
|
cb128162e6 | ||
|
|
f9f4c7dcd6 | ||
|
|
2dae228f10 | ||
|
|
b917c540aa | ||
|
|
67ce8aff61 | ||
|
|
ba927964c8 | ||
|
|
435f2b8e39 | ||
|
|
a25f9010cc | ||
|
|
4500964394 | ||
|
|
3da646f913 | ||
|
|
140436c2cb | ||
|
|
0e677fb3a2 | ||
|
|
4dc5d0e12f | ||
|
|
a260e92266 | ||
|
|
9a86be24a7 | ||
|
|
e620d973f4 | ||
|
|
7ad43a5b11 | ||
|
|
124ede82b3 | ||
|
|
da9debda67 | ||
|
|
1c40d77b14 | ||
|
|
f1b0c29815 | ||
|
|
b261dde858 | ||
|
|
88fdec6dd5 | ||
|
|
e8ce238eb7 | ||
|
|
404b1c5ed0 | ||
|
|
dde1deb6bc | ||
|
|
c80e0a964f | ||
|
|
d9f23a8af2 | ||
|
|
fd9e657196 | ||
|
|
693c4024d6 | ||
|
|
d7eee4191f | ||
|
|
b8c61f89fa | ||
|
|
d05feabcd6 | ||
|
|
c30b7c111f | ||
|
|
f6255c72d1 | ||
|
|
cd68567ce3 | ||
|
|
e6f39eb9b6 | ||
|
|
2c1a398292 | ||
|
|
0f52f6931b | ||
|
|
51dc097266 | ||
|
|
8e99b342a4 | ||
|
|
bc51c3e5b1 | ||
|
|
d5177fdc74 | ||
|
|
80eba57e6b | ||
|
|
3985dd639a | ||
|
|
3000445af9 | ||
|
|
0235d57625 | ||
|
|
77c7b312ea | ||
|
|
3850765759 | ||
|
|
0b8e2fd5c9 | ||
|
|
ebe9ee8114 | ||
|
|
a8ab617ee9 | ||
|
|
414440589e | ||
|
|
544b6d94aa | ||
|
|
0144062126 | ||
|
|
db1b7a8067 | ||
|
|
a9905ec95e | ||
|
|
7e2afacf34 | ||
|
|
2b6257e94e | ||
|
|
d14b5fe00b | ||
|
|
04bb2d1066 | ||
|
|
3b9037397a | ||
|
|
ea3e602835 | ||
|
|
96e971084a | ||
|
|
9bf78a96cc | ||
|
|
ba55ef0b2e | ||
|
|
0c00f7393c | ||
|
|
1824826474 | ||
|
|
57e1c7d55f | ||
|
|
e489b4a570 | ||
|
|
83dc7f0855 | ||
|
|
90a2d1bb39 | ||
|
|
da650606e3 | ||
|
|
bc789d7c1a | ||
|
|
5999b50e10 | ||
|
|
e5428a3c27 | ||
|
|
cf39bc97a5 | ||
|
|
4d43374fde | ||
|
|
dac42ee272 | ||
|
|
f7991185ba | ||
|
|
5954f15989 | ||
|
|
4d2eb7af30 | ||
|
|
50083048f6 | ||
|
|
dab2932550 | ||
|
|
a8cebbe3fd | ||
|
|
d6a6194e68 | ||
|
|
c373527851 | ||
|
|
de8726ab73 | ||
|
|
94d33a4ef1 | ||
|
|
d79b41e4a7 | ||
|
|
754a6e1177 | ||
|
|
b972ea4781 | ||
|
|
45856816c1 | ||
|
|
582162460f | ||
|
|
e970c36419 | ||
|
|
c48cc0afdc | ||
|
|
3d6d4f5464 | ||
|
|
61bc6ec825 | ||
|
|
6f0f6676db | ||
|
|
fc240d4dfa | ||
|
|
6dc0861740 | ||
|
|
45cabd756c | ||
|
|
5fc854ab4f | ||
|
|
caa3343dea | ||
|
|
3ac43497b9 | ||
|
|
74f1b800c2 | ||
|
|
7d431e55df | ||
|
|
575962569f | ||
|
|
01ef0e93aa | ||
|
|
439f4f6f0e | ||
|
|
00b1f33725 | ||
|
|
1204eec8ac | ||
|
|
f3ac8f6649 | ||
|
|
7db280a666 | ||
|
|
a4b7ad0d42 | ||
|
|
2b88905b40 | ||
|
|
ef5263ef9e | ||
|
|
9206512c38 | ||
|
|
82e16db275 | ||
|
|
97fc093eef | ||
|
|
b9cd424186 | ||
|
|
6af85409f1 | ||
|
|
86c699dd36 | ||
|
|
3d4e1ffd64 | ||
|
|
b39fcebe65 | ||
|
|
04129a0841 | ||
|
|
a7658f013e | ||
|
|
2822bf7a65 | ||
|
|
87ccd272ee | ||
|
|
18275ce2c9 | ||
|
|
5935070dfa | ||
|
|
8391c83121 | ||
|
|
4255ee105f | ||
|
|
e3c45bd1f7 | ||
|
|
449617474b | ||
|
|
ce542ac5f6 | ||
|
|
d0e18ed0ba | ||
|
|
70952282f0 | ||
|
|
bf325b72f1 | ||
|
|
f031ad23f6 | ||
|
|
9e56725406 | ||
|
|
ad543c909c | ||
|
|
36b8b81914 | ||
|
|
5d76ffef88 | ||
|
|
37316fed84 | ||
|
|
ecd568510d | ||
|
|
5ec9cf7089 | ||
|
|
aad1b5dc9f | ||
|
|
1b13f0a2ec | ||
|
|
29108ea8ad | ||
|
|
0e167ee85b | ||
|
|
8fe6d09613 | ||
|
|
fa0df413f4 | ||
|
|
1a8be6344a | ||
|
|
fff8455903 | ||
|
|
80d94e1aa3 | ||
|
|
a36c266e7d | ||
|
|
636c100b6b | ||
|
|
28f85aae7f | ||
|
|
dfa11f64ef | ||
|
|
3f92d2f300 | ||
|
|
cc0bf88a5f | ||
|
|
b3c0b964b5 | ||
|
|
4661e5a10b | ||
|
|
220a35b492 | ||
|
|
351142f93f | ||
|
|
29bc273e58 | ||
|
|
b96e0c8713 | ||
|
|
7e0c0d79bc | ||
|
|
1f88f1f3f6 | ||
|
|
69d8b1c30d | ||
|
|
5a5d8d2d07 | ||
|
|
0e25540a89 | ||
|
|
21169f4e9a | ||
|
|
1fbed9f7d0 | ||
|
|
c230cf5aab | ||
|
|
2d65ed352e | ||
|
|
5fa81d4273 | ||
|
|
5ec32bdd2f | ||
|
|
d39aa10da1 | ||
|
|
0d763052fb | ||
|
|
ee62e33dd0 | ||
|
|
a22de48e40 | ||
|
|
7b5708a8b4 | ||
|
|
71c1767790 | ||
|
|
5fb0115d06 | ||
|
|
c8e6128720 | ||
|
|
55583540a8 | ||
|
|
9b5d0228be | ||
|
|
325d05b59c | ||
|
|
d1500dc99b | ||
|
|
157c8d5e54 | ||
|
|
0533b5cefc | ||
|
|
7816085868 | ||
|
|
178a5f0645 | ||
|
|
dfb8527e50 | ||
|
|
0a581154d1 | ||
|
|
efabf18162 | ||
|
|
56737ac523 | ||
|
|
702885ebb2 | ||
|
|
a12b83de59 | ||
|
|
3b83356825 | ||
|
|
c2aad7a71d | ||
|
|
ef4edc6ff1 | ||
|
|
614967ccc1 | ||
|
|
e8dc1480eb | ||
|
|
8fb87df0f0 | ||
|
|
bb7cfd2493 | ||
|
|
1b19622ab8 | ||
|
|
68ab7e2e3e | ||
|
|
157a286d1b | ||
|
|
0eb199a9a8 | ||
|
|
77a928cef9 | ||
|
|
290388159a | ||
|
|
d0551a3ede | ||
|
|
1e0d0429d0 | ||
|
|
37ad913086 | ||
|
|
3755ad7515 | ||
|
|
369e141ea8 | ||
|
|
39c9e69d8a | ||
|
|
30be1ea16e | ||
|
|
a450361956 | ||
|
|
df48ad6b61 | ||
|
|
264de34c31 | ||
|
|
70444b46b9 | ||
|
|
a79e552ab4 | ||
|
|
1b5faef097 | ||
|
|
fe61f583e6 | ||
|
|
4031ad354b | ||
|
|
46b9ae4174 | ||
|
|
c0d1aaa8a0 | ||
|
|
a963427967 | ||
|
|
d5ec523584 | ||
|
|
c0c3fceaad | ||
|
|
c52d7c9126 | ||
|
|
6cb67a19e7 | ||
|
|
9b5ca124ab | ||
|
|
4a0a509dd8 | ||
|
|
6f2184901d | ||
|
|
201e5e59da | ||
|
|
2cb5778cfa | ||
|
|
006016322b | ||
|
|
4191856034 | ||
|
|
97f7b4f59f | ||
|
|
ea441b3d70 | ||
|
|
045ee262a8 | ||
|
|
502c6f0dae | ||
|
|
bc31dfbbd1 | ||
|
|
a1319f4231 | ||
|
|
ce365abab6 | ||
|
|
48a623f062 | ||
|
|
a727dfb3b0 | ||
|
|
52ba76fcb2 | ||
|
|
70e29d4f20 | ||
|
|
08d83eb8da | ||
|
|
eacff1f0b4 | ||
|
|
4806d71ca2 | ||
|
|
085b87dd02 | ||
|
|
35cd7eb2be | ||
|
|
ec716f0c58 | ||
|
|
0d97198f88 | ||
|
|
2c7537b4cd | ||
|
|
e364937353 | ||
|
|
877ef76540 | ||
|
|
519e8c5fcd | ||
|
|
305d53f094 | ||
|
|
5625ad76b9 | ||
|
|
4c722bf623 | ||
|
|
8fe22c33bf | ||
|
|
d866c061a3 | ||
|
|
f8fed31918 | ||
|
|
e487007960 | ||
|
|
b46f2d1527 | ||
|
|
e162fb0e80 | ||
|
|
91ea3ba090 | ||
|
|
e84f6e4afd | ||
|
|
9b65900df0 | ||
|
|
9659340d7f | ||
|
|
63175aa3cb | ||
|
|
986aa2a477 | ||
|
|
07d7a8eeff | ||
|
|
3c9e84d380 | ||
|
|
0f62a8ec2f | ||
|
|
4e7a9cf30b | ||
|
|
5077703400 | ||
|
|
77fef18590 | ||
|
|
6ce00034a2 | ||
|
|
ed6d8521e6 | ||
|
|
d24c751eef | ||
|
|
54012523bc | ||
|
|
5286f43133 | ||
|
|
ca1e9a2976 | ||
|
|
5951cbf7b9 | ||
|
|
e2b519a21e | ||
|
|
cf0401fea7 | ||
|
|
14a8f4a728 | ||
|
|
3e41d9b794 | ||
|
|
148867bf47 | ||
|
|
ef6c454137 | ||
|
|
093f8cb89b | ||
|
|
707e820af6 | ||
|
|
0c7696da65 | ||
|
|
9e540eb1c4 | ||
|
|
306828480f | ||
|
|
42b415952b | ||
|
|
e155e258cb | ||
|
|
6f45794574 | ||
|
|
1d30f00806 | ||
|
|
52e9ec10bf | ||
|
|
8da56ff98c | ||
|
|
d44e334524 | ||
|
|
e814e65fcb | ||
|
|
c2f7d600aa | ||
|
|
5d942265f9 | ||
|
|
6b07625192 | ||
|
|
19b56361b9 | ||
|
|
7d93eba321 | ||
|
|
7b42aba5ea | ||
|
|
be4ac7ca61 | ||
|
|
28e25ea718 | ||
|
|
b2e6e6155f | ||
|
|
f5e1ff3f1f | ||
|
|
3fda82b5f8 | ||
|
|
822a4896da | ||
|
|
7f2bf03d7e | ||
|
|
1e8a6e878d | ||
|
|
5f0a55057e | ||
|
|
7814acb9f8 | ||
|
|
b296af6fe4 | ||
|
|
14b9902f6d | ||
|
|
f2d54b7728 | ||
|
|
8950a693db | ||
|
|
fd3b9095ba | ||
|
|
030e1b9130 | ||
|
|
a040c237bc | ||
|
|
a62fafd4ed | ||
|
|
666703e8cf | ||
|
|
52cd52ca54 | ||
|
|
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 | ||
|
|
e2a6ae9ecc | ||
|
|
eb64e66e9f | ||
|
|
6a24b049cb | ||
|
|
1112dfffb3 | ||
|
|
3304bc2f3a | ||
|
|
4d2bee192f | ||
|
|
2d4fb8a463 | ||
|
|
56c5012bef | ||
|
|
47002f970d | ||
|
|
f6fd395485 | ||
|
|
4f426dafef | ||
|
|
7b6f2863a9 | ||
|
|
834a9bc84d | ||
|
|
7710a1fdb0 | ||
|
|
bd97bdd378 | ||
|
|
211c5dcfcd | ||
|
|
2cdf1897b9 | ||
|
|
bf8c57c669 | ||
|
|
7fd6b308f8 | ||
|
|
6908c0f1d0 | ||
|
|
f74380b3e9 | ||
|
|
4abdc29d9e | ||
|
|
5096aef6e7 | ||
|
|
d9f5801a68 | ||
|
|
462e03d150 | ||
|
|
6aded88e14 | ||
|
|
74a25097b2 | ||
|
|
2c190f502f | ||
|
|
0122686541 | ||
|
|
187c0a9bf7 | ||
|
|
a4295d1e93 | ||
|
|
9def5e57de | ||
|
|
3d573c08a1 | ||
|
|
c9ff6be881 | ||
|
|
40a8892cb7 | ||
|
|
e1bb10d859 | ||
|
|
569f4646a0 | ||
|
|
16756e550f | ||
|
|
933b77e429 | ||
|
|
3ac9ecb4b7 | ||
|
|
ccc4386285 | ||
|
|
4364ba46e2 | ||
|
|
d7917a6a9a | ||
|
|
81e30e75c4 | ||
|
|
7a94343dec | ||
|
|
3ee6bae4ba | ||
|
|
9a77e6b3cc | ||
|
|
a1727cc047 | ||
|
|
5b012b6509 | ||
|
|
c23ffa2ce5 | ||
|
|
ff68383732 | ||
|
|
bce2b2adb6 | ||
|
|
fa8c9a8418 | ||
|
|
2e176b8b8d | ||
|
|
f6bb6037f3 | ||
|
|
7fac7c8713 | ||
|
|
bdaef0b0dc | ||
|
|
5b21fc89fc | ||
|
|
bc7b90a1b4 | ||
|
|
134cb68396 | ||
|
|
c0ee2ce345 | ||
|
|
a299533508 | ||
|
|
d4bcbc3771 | ||
|
|
2c7555366f | ||
|
|
d8264fada7 | ||
|
|
72da49415e | ||
|
|
8e744ec5f7 | ||
|
|
7372b66680 | ||
|
|
8dfbcf5a9f | ||
|
|
01ff2cca0c | ||
|
|
e981c2b43f | ||
|
|
1f636bf7a9 | ||
|
|
68bc33ef4d | ||
|
|
a7e447a3f5 | ||
|
|
096a04b3e4 | ||
|
|
86e600000d | ||
|
|
a0128d9b7c | ||
|
|
65996254c6 | ||
|
|
a85031be53 | ||
|
|
8509f0857a | ||
|
|
b24c75b400 | ||
|
|
d372e789a4 | ||
|
|
d9f7e4c9e0 | ||
|
|
e6ea726b69 | ||
|
|
98c1a18e57 | ||
|
|
e04d2a4a10 | ||
|
|
96a3671bb6 | ||
|
|
0c028ca9d0 | ||
|
|
64124447d5 | ||
|
|
037ea592ab | ||
|
|
6ebbb48f9f | ||
|
|
2e8a53ff34 | ||
|
|
f104438802 | ||
|
|
eb25650e26 | ||
|
|
c4cba5254c | ||
|
|
c90dda908a | ||
|
|
6aca0a8bfc | ||
|
|
864376e7ba | ||
|
|
71794fe511 | ||
|
|
c69989c56f | ||
|
|
cc91beece7 | ||
|
|
0d6c6bdb58 | ||
|
|
e234b1537c | ||
|
|
407e58604f | ||
|
|
2c3bf7dd23 | ||
|
|
5e6417eac0 | ||
|
|
a4db34a419 | ||
|
|
8c493576cc | ||
|
|
110a0d98fa | ||
|
|
449b52e5a4 | ||
|
|
d0fda1f919 | ||
|
|
79ea33beda | ||
|
|
fef5bd321c | ||
|
|
6c7a763b76 | ||
|
|
78fa1c9995 | ||
|
|
3623ee3ce8 | ||
|
|
ba28da5fdc | ||
|
|
c2b7bd10ec | ||
|
|
35ab37c76c | ||
|
|
c968dfa113 | ||
|
|
09b24e45f9 | ||
|
|
8541040bb9 | ||
|
|
8ae003046c | ||
|
|
fc7f9ac6e9 | ||
|
|
7dcc7ea99c | ||
|
|
4590015ed6 | ||
|
|
79f9dc61a4 | ||
|
|
3fac7d027a | ||
|
|
10ba5809d2 | ||
|
|
792204bd06 | ||
|
|
f19cb010a0 | ||
|
|
ca3df3bd50 | ||
|
|
db43487b5a | ||
|
|
38c37b8160 | ||
|
|
44a04e6167 | ||
|
|
9d6a9eb615 | ||
|
|
27070af1b9 | ||
|
|
32d2d4107d | ||
|
|
75ebac822d | ||
|
|
bd9fab6cf5 | ||
|
|
d75f8f11e1 | ||
|
|
47900db414 | ||
|
|
aec3469c03 | ||
|
|
b61542242c | ||
|
|
13c1fd09c4 | ||
|
|
fddb69e49e | ||
|
|
ed51d5cf84 | ||
|
|
3d7b0db114 | ||
|
|
9e445a5adf | ||
|
|
97e25c37de | ||
|
|
16033c1307 | ||
|
|
15d64b8486 | ||
|
|
5d06aa3c8c | ||
|
|
e276223b61 | ||
|
|
71b48fad0f | ||
|
|
a3fade1c1d | ||
|
|
6530f47b2d | ||
|
|
3ab1ef139f | ||
|
|
36bd6423c2 | ||
|
|
ffd8ff099a | ||
|
|
178347f9f1 | ||
|
|
e194f89b25 | ||
|
|
3bfc70aa3b | ||
|
|
93a6a0f211 | ||
|
|
cef6a2e389 | ||
|
|
4f5764e4a5 | ||
|
|
21770ff10f | ||
|
|
2b97461f54 | ||
|
|
0cf5f4ae2a | ||
|
|
7b6dcfce87 | ||
|
|
f9d472847c | ||
|
|
d69d97402b | ||
|
|
643c39690f | ||
|
|
6048144310 | ||
|
|
94303ea9a0 | ||
|
|
a017e4820a | ||
|
|
50e1c5ba1f | ||
|
|
c5ec369388 | ||
|
|
7d3ebce7d1 | ||
|
|
52826342fc | ||
|
|
29b357a2f6 | ||
|
|
747ed1e59a | ||
|
|
992c05b6aa | ||
|
|
f4a5457941 | ||
|
|
7167a807bf | ||
|
|
22675ba2e7 | ||
|
|
80602b011d | ||
|
|
abea8e2195 | ||
|
|
9075aecb18 | ||
|
|
6e9ac875d7 | ||
|
|
100ecb12e9 | ||
|
|
57b4701e57 | ||
|
|
fffc211989 | ||
|
|
5a0528de26 | ||
|
|
fb8f46ea45 | ||
|
|
a8e1a4f2fd | ||
|
|
157f050f89 | ||
|
|
3653f56331 | ||
|
|
e31cbbfe21 | ||
|
|
bc3491c5bd | ||
|
|
9a7c25047d | ||
|
|
7cef8b7363 | ||
|
|
e449b8384c | ||
|
|
9514c12982 | ||
|
|
489d6c5a65 | ||
|
|
ccc59ecdaf | ||
|
|
d2ce50f989 | ||
|
|
14e409adb4 | ||
|
|
4a0f639e89 | ||
|
|
32c5925652 | ||
|
|
4c91dd8621 | ||
|
|
f641aa92f5 | ||
|
|
3bdc8583e5 | ||
|
|
4e37900d93 | ||
|
|
c676ecc026 | ||
|
|
db760dc29b | ||
|
|
0fbb87e3b2 | ||
|
|
29996d0133 | ||
|
|
7807f3e31a | ||
|
|
e246d14a6b | ||
|
|
a34a27be65 | ||
|
|
e1d2b88c23 | ||
|
|
f96ca17f17 | ||
|
|
50580498c4 | ||
|
|
a21e688c96 | ||
|
|
4b1deee7e1 | ||
|
|
bf5fefe84f | ||
|
|
5c92b0d154 | ||
|
|
2b7ccf6625 | ||
|
|
004d450844 | ||
|
|
7705e88b57 | ||
|
|
3f250ba42d | ||
|
|
1b8bb4e049 | ||
|
|
1577fab93a | ||
|
|
181fe74b09 | ||
|
|
34b8d00548 | ||
|
|
0a6cbadcd8 | ||
|
|
701fef1ba4 | ||
|
|
cdd78b2ec3 | ||
|
|
ba04132142 | ||
|
|
ddc42bedf5 | ||
|
|
ea84302e28 | ||
|
|
a7a08a7d4e | ||
|
|
0a33a25a7d | ||
|
|
2c9622ea52 | ||
|
|
08e2fc8deb | ||
|
|
ebed45a0f6 | ||
|
|
d3c279fd05 | ||
|
|
e69ed4b0da | ||
|
|
4daca3c5ba | ||
|
|
cb41fa6de4 | ||
|
|
dc758ead10 | ||
|
|
1fe38c7473 | ||
|
|
5564c38a2f | ||
|
|
2a853a23d7 | ||
|
|
37da98c9bb | ||
|
|
5a5172be57 | ||
|
|
58ec9a4f38 | ||
|
|
b7477fc321 | ||
|
|
88afac51f0 | ||
|
|
2bb3e5fd6b | ||
|
|
dd338d40f3 | ||
|
|
1cc8440900 | ||
|
|
47cf8f4233 | ||
|
|
eedfd2d70d | ||
|
|
4e88626d65 | ||
|
|
a1b91ac136 | ||
|
|
4bbd74b702 | ||
|
|
1d07d24054 | ||
|
|
0a0fd0c64a | ||
|
|
a7c6fc12d8 | ||
|
|
48f0a49f9b | ||
|
|
b63d714a06 | ||
|
|
7bdcea5814 | ||
|
|
f418f38589 | ||
|
|
7d3e32b65f | ||
|
|
52377b509b | ||
|
|
14152bb7ba | ||
|
|
d51aaec97d | ||
|
|
ea3fe754f4 | ||
|
|
04354a809c | ||
|
|
3cf30f5e62 | ||
|
|
7ff0129f36 | ||
|
|
b684d3aad7 | ||
|
|
f164419baa | ||
|
|
f20603ad06 | ||
|
|
bac975331d | ||
|
|
dcccfbd26a | ||
|
|
4baf847062 | ||
|
|
90a44ea6c8 | ||
|
|
fef83838f9 | ||
|
|
1422a9abe3 | ||
|
|
2fc0520895 | ||
|
|
7b1adfe00b | ||
|
|
28e1568eb7 | ||
|
|
0a6eac7c27 | ||
|
|
ecaced40f2 | ||
|
|
984a2d26f4 | ||
|
|
f85bb7e490 | ||
|
|
321443450a | ||
|
|
25a0a192a2 | ||
|
|
843ff25de4 | ||
|
|
4563c00deb | ||
|
|
7a38e5584c | ||
|
|
e26ce2b457 | ||
|
|
9c1e45d97c | ||
|
|
c2756c731f | ||
|
|
d6fc82f8fa | ||
|
|
2acf1b08d5 | ||
|
|
6ffd39ac77 | ||
|
|
9ae456b9d1 | ||
|
|
5bbeddc134 | ||
|
|
373fbb6ca3 | ||
|
|
d1405f2ab3 | ||
|
|
2ff9b0aada | ||
|
|
43f5d71724 | ||
|
|
41b61ed36f | ||
|
|
31e30faace | ||
|
|
ff7a2c6b73 | ||
|
|
acea705df8 | ||
|
|
7e3f9ada31 | ||
|
|
0a956115eb | ||
|
|
30174c07de | ||
|
|
8e5c7713fc | ||
|
|
7b45342955 | ||
|
|
2f0965c14b | ||
|
|
c1c5d2656c | ||
|
|
af2af91300 | ||
|
|
c880919466 | ||
|
|
b1646accb9 | ||
|
|
00bb796db2 | ||
|
|
6c1259f6e6 | ||
|
|
a04521b55a | ||
|
|
c8b3c82a12 | ||
|
|
c1c8a4c988 | ||
|
|
335febca34 | ||
|
|
e191d446a7 | ||
|
|
412ad74aad | ||
|
|
e70fc299ac | ||
|
|
b3b972caf7 | ||
|
|
c25017e1a4 | ||
|
|
be1d12f94f | ||
|
|
3c18289465 | ||
|
|
ed29c837fa | ||
|
|
8d78c74554 | ||
|
|
e48bba5b4d | ||
|
|
547f7aecc1 | ||
|
|
67ba04bcee | ||
|
|
a1d84347ed | ||
|
|
253109d1c9 | ||
|
|
c0c9fc3267 | ||
|
|
918bec36d9 | ||
|
|
7b8cd751e1 | ||
|
|
849c4a70ae | ||
|
|
c231375e19 | ||
|
|
d8babe2a71 | ||
|
|
4e88a5a431 | ||
|
|
a6579c7bcb | ||
|
|
5a2f8afd33 | ||
|
|
3c12db8637 | ||
|
|
07cbe39552 | ||
|
|
974f31c149 | ||
|
|
4a1c565b62 | ||
|
|
32f9c46424 | ||
|
|
34d2d7760b | ||
|
|
2f36e3b231 | ||
|
|
b0d6e39035 | ||
|
|
b7a2f221f2 | ||
|
|
6d2bb90f51 | ||
|
|
fa1336623f | ||
|
|
2b65e2496d | ||
|
|
4953b1d889 | ||
|
|
ed75da0f85 | ||
|
|
ff7cb43f6a | ||
|
|
dc3b4a57cc | ||
|
|
7009e755fe | ||
|
|
bba2cfc6f7 | ||
|
|
759c76e188 | ||
|
|
db5a0be4ca | ||
|
|
29e57e77f7 | ||
|
|
f50c7469ca | ||
|
|
d9af295a29 | ||
|
|
4147bf7444 | ||
|
|
99e304d6b5 | ||
|
|
4e7000368f | ||
|
|
04b7b7b9ff | ||
|
|
2534fd1ce2 | ||
|
|
e10dd226ff | ||
|
|
b016623fb5 | ||
|
|
49d14111e2 | ||
|
|
f0a11d3cb7 | ||
|
|
168f42323b | ||
|
|
64e7d0b737 | ||
|
|
2e8c0c8f7d | ||
|
|
8f555543cc | ||
|
|
88a71ddad4 | ||
|
|
02e31bb576 | ||
|
|
32f7bec6c8 | ||
|
|
a935e6f90d | ||
|
|
f4dba84ae5 | ||
|
|
5cb4acf590 | ||
|
|
e83526aa63 | ||
|
|
04021ed8b1 | ||
|
|
31a4f40c9a | ||
|
|
4001b0f804 | ||
|
|
a838276ec2 | ||
|
|
6192efc078 | ||
|
|
4517031861 | ||
|
|
187ff255bd | ||
|
|
dec172f0e1 | ||
|
|
a0107299f3 | ||
|
|
bbbc2ce22c | ||
|
|
def0a8a0d6 | ||
|
|
46095d797c | ||
|
|
5687a7ba90 | ||
|
|
556c03babf | ||
|
|
09ea2e13aa | ||
|
|
ef62e3d665 | ||
|
|
fb2f0795c5 | ||
|
|
fb44b51d26 | ||
|
|
8680d07e0a | ||
|
|
9d8445b693 | ||
|
|
5de80c03db | ||
|
|
c5df0bf58f | ||
|
|
8c1502278b | ||
|
|
08e3e3b53d | ||
|
|
86591356b0 | ||
|
|
f62cf04f91 | ||
|
|
cf621eaf10 | ||
|
|
b8214a80c2 | ||
|
|
f79c9eec82 | ||
|
|
8fcecf3dec | ||
|
|
326e8ee205 | ||
|
|
bda56bf33f | ||
|
|
7439f15d7e | ||
|
|
7a4967abc9 | ||
|
|
6749545991 | ||
|
|
124c3f4575 | ||
|
|
56b77a536f | ||
|
|
e175cce776 | ||
|
|
097f42a01c | ||
|
|
bcf1b092ae | ||
|
|
d707ea0de5 | ||
|
|
2c107e3601 | ||
|
|
29d1246b8d | ||
|
|
514fc7dfe8 | ||
|
|
0691bca512 | ||
|
|
e1f8a0fd68 | ||
|
|
e141cf74d5 | ||
|
|
9ca1ca62ea | ||
|
|
99d27b979d | ||
|
|
681747d02c | ||
|
|
1ec936daf6 | ||
|
|
8eb6d9ccf5 | ||
|
|
d3394453ff | ||
|
|
5caeebf807 | ||
|
|
d6a9cb427f | ||
|
|
cb4b1dce71 | ||
|
|
e6c5adfa24 | ||
|
|
444896104f | ||
|
|
e2791a3702 | ||
|
|
16ed584e39 | ||
|
|
d6a0cb8992 | ||
|
|
f99b82b53a | ||
|
|
32b7e2df98 | ||
|
|
0137219fb8 | ||
|
|
51f914fb30 | ||
|
|
f85eeb2adb | ||
|
|
6b213a9caf | ||
|
|
35f31b0f1a | ||
|
|
56a68f4dfd | ||
|
|
6e930f6048 | ||
|
|
4fc7fce4fd | ||
|
|
f27202202b | ||
|
|
deb7a123a6 | ||
|
|
9ef7dca666 | ||
|
|
fe4e39a2dd | ||
|
|
4951dccded | ||
|
|
58870a30fb | ||
|
|
05e18833ac | ||
|
|
08c2a087d8 | ||
|
|
05c8681336 | ||
|
|
bf5ee181fa | ||
|
|
094acb1039 | ||
|
|
93944e7f4b | ||
|
|
1251093ec1 | ||
|
|
c951a6ca7c | ||
|
|
70a594f354 | ||
|
|
9b03490b1a | ||
|
|
edb7b49c25 | ||
|
|
0c1c984eaf | ||
|
|
b595047fdf | ||
|
|
2c25c09420 | ||
|
|
f6b088c2e6 | ||
|
|
1cf87d4ad9 | ||
|
|
0aad4353cf | ||
|
|
7875fe1acd | ||
|
|
95aca7b61b | ||
|
|
e52e3c4639 | ||
|
|
eee77228e6 | ||
|
|
2b0cc7b4ea | ||
|
|
eaccf6f90b | ||
|
|
a01848c774 | ||
|
|
ea748cfdbd | ||
|
|
401c6b445d | ||
|
|
3c0b289694 | ||
|
|
8182bdb476 | ||
|
|
ae7e5a6a4b | ||
|
|
50eb77926e | ||
|
|
bd24893837 | ||
|
|
dad66c9204 | ||
|
|
9292e0f816 | ||
|
|
4d48fc7ae5 | ||
|
|
463cfb0015 | ||
|
|
3ed5d1e8d7 | ||
|
|
e64e2534eb | ||
|
|
67e28d7475 | ||
|
|
64b8049d70 | ||
|
|
dd75e88cbb | ||
|
|
c75d607a00 | ||
|
|
8126aa6bb8 | ||
|
|
846caf1298 | ||
|
|
c2917a8dd4 | ||
|
|
9e443cfdd3 | ||
|
|
b743af8a72 | ||
|
|
8a4c96b252 | ||
|
|
0392e55ef7 | ||
|
|
fa5ee3287f | ||
|
|
e1882f97a1 | ||
|
|
1a156deca5 | ||
|
|
5668f23b50 | ||
|
|
232f344c41 | ||
|
|
79cf4e07eb | ||
|
|
f9b294d89e | ||
|
|
a88d7c1cdc | ||
|
|
85760603b7 | ||
|
|
ea1f5e86c0 | ||
|
|
b1072d3b09 | ||
|
|
81632dda97 | ||
|
|
80fdbcf8c7 | ||
|
|
bd2361c8ae | ||
|
|
c9a81c0651 | ||
|
|
aa096f2385 | ||
|
|
53acb70260 | ||
|
|
6ef4c4b3ad | ||
|
|
4ac38946f2 | ||
|
|
af54ae6af7 | ||
|
|
2c23544b29 | ||
|
|
5351bbec71 | ||
|
|
492c913aa9 | ||
|
|
31dd23fbd9 | ||
|
|
3f38171d8c | ||
|
|
307adb34ab | ||
|
|
8a4af4d22f | ||
|
|
2e7b6b5ba5 | ||
|
|
9a02cb9dc8 | ||
|
|
43c085eea3 | ||
|
|
6a834ffef7 | ||
|
|
86c8ec847a | ||
|
|
2df2b791d8 | ||
|
|
0e1ae4d85b | ||
|
|
3d96f8f127 | ||
|
|
2cc809be0c | ||
|
|
d2d2578314 | ||
|
|
76b51aed07 | ||
|
|
d0cbd943f1 | ||
|
|
c67a3cd749 | ||
|
|
bf0354dbb9 | ||
|
|
bc4f24e94d | ||
|
|
73203fb7b3 | ||
|
|
89c49c3976 | ||
|
|
89a56ac3e1 | ||
|
|
3cc5bebfa9 | ||
|
|
f9cfe7e9da | ||
|
|
5c58f8c97b | ||
|
|
bb9f31e555 | ||
|
|
ce57617744 | ||
|
|
77a7bf385b | ||
|
|
52d2a1797d | ||
|
|
111a3a7169 | ||
|
|
a513a2a6f8 | ||
|
|
f3f46fc126 | ||
|
|
3cff457c6d | ||
|
|
853b080aa4 | ||
|
|
261023800e | ||
|
|
7314d81947 | ||
|
|
d530d0c726 | ||
|
|
b01dd0798c | ||
|
|
968045ae62 | ||
|
|
4106620928 | ||
|
|
ac9b9f8c2a | ||
|
|
cdf54a3db1 | ||
|
|
8a5d833c89 | ||
|
|
57bba6d83f | ||
|
|
2c08bb3a96 | ||
|
|
6d4938f6b5 | ||
|
|
7104e187cc | ||
|
|
2fc7a017e1 | ||
|
|
e0a69507a0 | ||
|
|
29de57d415 | ||
|
|
42359a243a | ||
|
|
81e40c32c8 | ||
|
|
350044c9a8 | ||
|
|
bc1bb2cba2 | ||
|
|
6079c927ad | ||
|
|
42f61acc45 | ||
|
|
bc8c9ba691 | ||
|
|
6e59d8ae5c | ||
|
|
749177d0b3 | ||
|
|
4a32aff158 | ||
|
|
ac68a441ee | ||
|
|
119592eefe | ||
|
|
72a1fb06d0 | ||
|
|
8a7ced18de | ||
|
|
06c8f3a093 | ||
|
|
22aa6561b5 | ||
|
|
9ac54e5fb2 | ||
|
|
2c94b1268a | ||
|
|
46ce91c4f7 | ||
|
|
953da3f6e0 | ||
|
|
076b5191c9 | ||
|
|
20d12fad9f | ||
|
|
b18bd78c51 | ||
|
|
c3492f0192 | ||
|
|
d595e020cd | ||
|
|
5b4f98b354 | ||
|
|
6e2ac7376e | ||
|
|
1a86604d99 | ||
|
|
049f63e6fd | ||
|
|
3aea76cfb3 | ||
|
|
3b4c800baa | ||
|
|
ca9b2784bd | ||
|
|
df83dbc04e | ||
|
|
81af704f58 | ||
|
|
627e4fd115 | ||
|
|
044ee841f2 | ||
|
|
c93d05f622 | ||
|
|
c824afc61e | ||
|
|
3d015908d9 | ||
|
|
bff2b0a95d | ||
|
|
c9b320d645 | ||
|
|
29ee014a94 | ||
|
|
aa73e41f29 | ||
|
|
0a829027eb | ||
|
|
9c7249a1e9 | ||
|
|
d9357d5224 | ||
|
|
73a20de2ff | ||
|
|
8cd8228251 | ||
|
|
02faa8fbd6 | ||
|
|
79485eef38 | ||
|
|
b2d25f2a77 | ||
|
|
e794883b1f | ||
|
|
2a11739e86 | ||
|
|
dea6b06e2c | ||
|
|
13cf254f08 | ||
|
|
531c359fb9 | ||
|
|
9550e55160 | ||
|
|
40e0857a29 | ||
|
|
47fa9d9464 | ||
|
|
d827c0fd2d | ||
|
|
c16afc9cd3 | ||
|
|
a18b1e0790 | ||
|
|
80b2ea646a | ||
|
|
f7613f80f1 | ||
|
|
b90386276f | ||
|
|
8ad5d61878 | ||
|
|
b2fbd9691d | ||
|
|
0fac3fd74e | ||
|
|
3342a84cf4 | ||
|
|
21359ea17e | ||
|
|
a7cc2609e1 | ||
|
|
9023afff0d | ||
|
|
f388b0612b | ||
|
|
c7dbacc134 | ||
|
|
d88ba02fde | ||
|
|
6e91780e73 | ||
|
|
77ff2c40bd | ||
|
|
aee95b6c74 | ||
|
|
f1ef53cdff | ||
|
|
9a7c884c21 | ||
|
|
c7418e70ba | ||
|
|
1e70b04f48 | ||
|
|
1adb549a8d | ||
|
|
35eb2f2ce5 | ||
|
|
2030ef9114 | ||
|
|
c5330c73b7 | ||
|
|
7a968cb33c | ||
|
|
a2aa6b0daf | ||
|
|
8df36003a8 | ||
|
|
f226e6d70b | ||
|
|
394424c52f | ||
|
|
5c6a2868d9 | ||
|
|
62047b6d0d | ||
|
|
5e721623a0 | ||
|
|
90b739ae48 | ||
|
|
7262dd5e79 | ||
|
|
f41aefc525 | ||
|
|
0c22ab3972 | ||
|
|
221e7d48a7 | ||
|
|
21c0466b3d | ||
|
|
47f8d0eef5 | ||
|
|
d0286c1391 | ||
|
|
eac0e274a6 | ||
|
|
af05dbbcdf | ||
|
|
ac256a6c24 | ||
|
|
0771411eac | ||
|
|
e6de7c0c2d | ||
|
|
8d021c6caf | ||
|
|
9487f9d631 | ||
|
|
678cb82ec0 | ||
|
|
c4c8948d95 | ||
|
|
1e1f0de4ec | ||
|
|
84bde330cd | ||
|
|
e63a5cd3dc | ||
|
|
6c38c9264e | ||
|
|
946834b868 | ||
|
|
726aa68be9 | ||
|
|
16bdac4635 | ||
|
|
d014010a99 | ||
|
|
07915461e9 | ||
|
|
e24f15e7df | ||
|
|
90d4fed4a9 | ||
|
|
101d2359de | ||
|
|
046ce18e8b | ||
|
|
883e77bc60 | ||
|
|
6d2a3a7964 | ||
|
|
2fbd32cd1a | ||
|
|
800838d76a | ||
|
|
93b2edde8c | ||
|
|
a483ec5dc5 | ||
|
|
c42a26bb66 | ||
|
|
75a77c1925 | ||
|
|
c473d75d3d | ||
|
|
0c5e4b5a2f | ||
|
|
dcb9efa131 | ||
|
|
70301419b1 | ||
|
|
ad37496d34 | ||
|
|
472e9969d9 | ||
|
|
e1aba62c15 | ||
|
|
3a061aa38d | ||
|
|
d5f5239eeb | ||
|
|
8ba1d5e333 | ||
|
|
e618900688 | ||
|
|
ec69b34cbb | ||
|
|
430a860927 | ||
|
|
f08ce7f62f | ||
|
|
13e8cf9ed8 | ||
|
|
53d11eae63 | ||
|
|
72b6510e61 | ||
|
|
ea189849de | ||
|
|
8a2c175420 | ||
|
|
544ed79284 | ||
|
|
222b543adb | ||
|
|
2bec3aaa49 | ||
|
|
50c50a8f6c | ||
|
|
f0f44687b6 | ||
|
|
f295c6f4fd | ||
|
|
b455ac4f4e | ||
|
|
3d349378ad | ||
|
|
b865f96886 | ||
|
|
10bd6c298e | ||
|
|
4d3d51b5dd | ||
|
|
51d5f79f1e | ||
|
|
9b4bdd05b5 | ||
|
|
a0b05dc624 | ||
|
|
79fb305722 | ||
|
|
fbe46934a4 | ||
|
|
b9bd1b1037 | ||
|
|
b9aac380d4 | ||
|
|
127c89de4e | ||
|
|
251cced1f8 | ||
|
|
02931c94cf | ||
|
|
3a14544385 | ||
|
|
33b2847ec3 | ||
|
|
a3d5a0151d | ||
|
|
97c26eee3c | ||
|
|
cc3c16c079 | ||
|
|
c5af41d983 | ||
|
|
3bcd296d99 | ||
|
|
83a1ebcf0f | ||
|
|
8ba6d5cbba | ||
|
|
bb85c5eda2 | ||
|
|
a64894bbe4 | ||
|
|
50760d853f | ||
|
|
62b08e923c | ||
|
|
2f41af814e | ||
|
|
d28eca4bb3 | ||
|
|
306be48027 | ||
|
|
4ad308897f | ||
|
|
f6b6dff4c0 | ||
|
|
3ba7c63862 | ||
|
|
20112fe6cc | ||
|
|
3f49d29274 | ||
|
|
0601988e80 | ||
|
|
9eb41bc475 | ||
|
|
7cd5c96087 |
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"project_id" : "sourcemod",
|
||||||
|
"conduit_uri" : "https://phabricator.alliedmods.net/",
|
||||||
|
"history.immutable" : false
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
# Binaries
|
||||||
|
*.dll
|
||||||
|
*.dylib
|
||||||
|
*.exe
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Files generated by Visual Studio
|
||||||
|
*.aps
|
||||||
|
*.ipch
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
CrazyDebug*/
|
||||||
|
Debug*/
|
||||||
|
Release*/
|
||||||
|
LIB-Release/
|
||||||
|
LIB-Debug/
|
||||||
|
|
||||||
|
# Files generated by Mac OS X Finder
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Files generated by Windows Explorer
|
||||||
|
[Dd]esktop.ini
|
||||||
|
[Tt]humbs.db
|
||||||
|
|
||||||
|
# AMBuild build directories
|
||||||
|
build/
|
||||||
|
obj-*/
|
||||||
|
*~
|
||||||
|
*.rej
|
||||||
|
*.orig
|
||||||
|
*.smx
|
||||||
|
*.swp
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- clang
|
||||||
|
before_script:
|
||||||
|
- sudo apt-get update -qq
|
||||||
|
- sudo apt-get install -y g++-multilib libc6-dev-i386 lib32stdc++6 lib32z1-dev
|
||||||
|
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
|
||||||
|
script:
|
||||||
|
- mkdir build && cd build
|
||||||
|
- python ../configure.py --enable-optimize --sdks=episode1,tf2,l4d2,csgo,dota
|
||||||
|
- ambuild
|
||||||
+514
@@ -0,0 +1,514 @@
|
|||||||
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
|
import os, sys
|
||||||
|
|
||||||
|
class SDK(object):
|
||||||
|
def __init__(self, sdk, ext, aDef, name, platform, dir):
|
||||||
|
self.folder = 'hl2sdk-' + dir
|
||||||
|
self.envvar = sdk
|
||||||
|
self.ext = ext
|
||||||
|
self.code = aDef
|
||||||
|
self.define = name
|
||||||
|
self.platform = platform
|
||||||
|
self.name = dir
|
||||||
|
self.path = None # Actual path
|
||||||
|
|
||||||
|
WinOnly = ['windows']
|
||||||
|
WinLinux = ['windows', 'linux']
|
||||||
|
WinLinuxMac = ['windows', 'linux', 'mac']
|
||||||
|
|
||||||
|
PossibleSDKs = {
|
||||||
|
'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
|
||||||
|
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
|
||||||
|
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
|
||||||
|
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
|
||||||
|
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
|
||||||
|
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'),
|
||||||
|
'tf2': SDK('HL2SDKTF2', '2.tf2', '10', 'TF2', WinLinuxMac, 'tf2'),
|
||||||
|
'l4d': SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
|
||||||
|
'nucleardawn': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
|
||||||
|
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '14', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
|
||||||
|
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
|
||||||
|
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '15', 'ALIENSWARM', WinOnly, 'swarm'),
|
||||||
|
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
|
||||||
|
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
|
||||||
|
'csgo': SDK('HL2SDKCSGO', '2.csgo', '19', 'CSGO', WinLinuxMac, 'csgo'),
|
||||||
|
'dota': SDK('HL2SDKDOTA', '2.dota', '20', 'DOTA', WinLinuxMac, 'dota'),
|
||||||
|
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '16', 'PORTAL2', [], 'portal2'),
|
||||||
|
'blade': SDK('HL2SDKBLADE', '2.blade', '17', 'BLADE', WinLinux, 'blade'),
|
||||||
|
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '18', 'INSURGENCY', WinLinuxMac, 'insurgency'),
|
||||||
|
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '13', 'CONTAGION', WinOnly, 'contagion'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def ResolveEnvPath(env, folder):
|
||||||
|
if env in os.environ:
|
||||||
|
path = os.environ[env]
|
||||||
|
if os.path.isdir(path):
|
||||||
|
return path
|
||||||
|
return None
|
||||||
|
|
||||||
|
head = os.getcwd()
|
||||||
|
oldhead = None
|
||||||
|
while head != None and head != oldhead:
|
||||||
|
path = os.path.join(head, folder)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
return path
|
||||||
|
oldhead = head
|
||||||
|
head, tail = os.path.split(head)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def Normalize(path):
|
||||||
|
return os.path.abspath(os.path.normpath(path))
|
||||||
|
|
||||||
|
class SMConfig(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.sdks = {}
|
||||||
|
self.binaries = []
|
||||||
|
self.extensions = []
|
||||||
|
self.generated_headers = None
|
||||||
|
self.mms_root = None
|
||||||
|
self.mysql_root = None
|
||||||
|
self.spcomp = None
|
||||||
|
self.smx_files = {}
|
||||||
|
self.versionlib = None
|
||||||
|
|
||||||
|
def use_auto_versioning(self):
|
||||||
|
return builder.backend == 'amb2'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tag(self):
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
return 'Debug'
|
||||||
|
return 'Release'
|
||||||
|
|
||||||
|
def detectProductVersion(self):
|
||||||
|
builder.AddConfigureFile('product.version')
|
||||||
|
|
||||||
|
# For OS X dylib versioning
|
||||||
|
import re
|
||||||
|
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
|
||||||
|
productContents = fp.read()
|
||||||
|
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
|
||||||
|
if m == None:
|
||||||
|
self.productVersion = '1.0.0'
|
||||||
|
else:
|
||||||
|
major, minor, release = m.groups()
|
||||||
|
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
|
||||||
|
|
||||||
|
def detectSDKs(self):
|
||||||
|
sdk_list = builder.options.sdks.split(',')
|
||||||
|
use_all = sdk_list[0] == 'all'
|
||||||
|
use_present = sdk_list[0] == 'present'
|
||||||
|
|
||||||
|
for sdk_name in PossibleSDKs:
|
||||||
|
sdk = PossibleSDKs[sdk_name]
|
||||||
|
if builder.target_platform in sdk.platform:
|
||||||
|
if builder.options.hl2sdk_root:
|
||||||
|
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
|
||||||
|
else:
|
||||||
|
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
|
||||||
|
if sdk_path is None or not os.path.isdir(sdk_path):
|
||||||
|
if use_all or sdk_name in sdk_list:
|
||||||
|
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
|
||||||
|
continue
|
||||||
|
if use_all or use_present or sdk_name in sdk_list:
|
||||||
|
sdk.path = Normalize(sdk_path)
|
||||||
|
self.sdks[sdk_name] = sdk
|
||||||
|
|
||||||
|
if len(self.sdks) < 1:
|
||||||
|
raise Exception('At least one SDK must be available.')
|
||||||
|
|
||||||
|
|
||||||
|
if builder.options.mms_path:
|
||||||
|
self.mms_root = builder.options.mms_path
|
||||||
|
else:
|
||||||
|
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
|
||||||
|
if not self.mms_root:
|
||||||
|
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
|
||||||
|
if not self.mms_root:
|
||||||
|
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
|
||||||
|
|
||||||
|
if not self.mms_root or not os.path.isdir(self.mms_root):
|
||||||
|
raise Exception('Could not find a source copy of Metamod:Source')
|
||||||
|
self.mms_root = Normalize(self.mms_root)
|
||||||
|
|
||||||
|
if builder.options.hasMySql:
|
||||||
|
if builder.options.mysql_path:
|
||||||
|
self.mysql_root = builder.options.mysql_path
|
||||||
|
else:
|
||||||
|
for i in range(7):
|
||||||
|
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
|
||||||
|
if self.mysql_root:
|
||||||
|
break
|
||||||
|
if not self.mysql_root or not os.path.isdir(self.mysql_root):
|
||||||
|
raise Exception('Could not find a path to MySQL!')
|
||||||
|
self.mysql_root = Normalize(self.mysql_root)
|
||||||
|
|
||||||
|
def configure(self):
|
||||||
|
builder.AddConfigureFile('pushbuild.txt')
|
||||||
|
|
||||||
|
cxx = builder.DetectCompilers()
|
||||||
|
|
||||||
|
if cxx.like('gcc'):
|
||||||
|
cxx.defines += [
|
||||||
|
'stricmp=strcasecmp',
|
||||||
|
'_stricmp=strcasecmp',
|
||||||
|
'_snprintf=snprintf',
|
||||||
|
'_vsnprintf=vsnprintf',
|
||||||
|
'HAVE_STDINT_H',
|
||||||
|
'GNUC',
|
||||||
|
]
|
||||||
|
cxx.cflags += [
|
||||||
|
'-pipe',
|
||||||
|
'-fno-strict-aliasing',
|
||||||
|
'-Wall',
|
||||||
|
'-Werror',
|
||||||
|
'-Wno-uninitialized',
|
||||||
|
'-Wno-unused',
|
||||||
|
'-Wno-switch',
|
||||||
|
'-Wno-format',
|
||||||
|
'-Wno-format-security',
|
||||||
|
'-msse',
|
||||||
|
'-m32',
|
||||||
|
]
|
||||||
|
|
||||||
|
have_gcc = cxx.vendor == 'gcc'
|
||||||
|
have_clang = cxx.vendor == 'clang'
|
||||||
|
if have_clang or (have_gcc and cxx.version >= '4'):
|
||||||
|
cxx.cflags += ['-fvisibility=hidden']
|
||||||
|
cxx.cxxflags += ['-fvisibility-inlines-hidden']
|
||||||
|
if have_clang or (have_gcc and cxx.version >= '4.6'):
|
||||||
|
cxx.cflags += ['-Wno-narrowing']
|
||||||
|
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
|
||||||
|
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
||||||
|
|
||||||
|
cxx.linkflags += ['-m32']
|
||||||
|
cxx.cxxflags += [
|
||||||
|
'-fno-exceptions',
|
||||||
|
'-fno-threadsafe-statics',
|
||||||
|
'-Wno-non-virtual-dtor',
|
||||||
|
'-Wno-overloaded-virtual',
|
||||||
|
]
|
||||||
|
|
||||||
|
if have_gcc:
|
||||||
|
cxx.cflags += ['-mfpmath=sse']
|
||||||
|
elif cxx.vendor == 'msvc':
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
cxx.cflags += ['/MTd']
|
||||||
|
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
|
||||||
|
else:
|
||||||
|
cxx.cflags += ['/MT']
|
||||||
|
cxx.defines += [
|
||||||
|
'_CRT_SECURE_NO_DEPRECATE',
|
||||||
|
'_CRT_SECURE_NO_WARNINGS',
|
||||||
|
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||||
|
'_ITERATOR_DEBUG_LEVEL=0',
|
||||||
|
]
|
||||||
|
cxx.cflags += [
|
||||||
|
'/W3',
|
||||||
|
]
|
||||||
|
cxx.cxxflags += [
|
||||||
|
'/EHsc',
|
||||||
|
'/GR-',
|
||||||
|
'/TP',
|
||||||
|
]
|
||||||
|
cxx.linkflags += [
|
||||||
|
'/MACHINE:X86',
|
||||||
|
'/SUBSYSTEM:WINDOWS',
|
||||||
|
'kernel32.lib',
|
||||||
|
'user32.lib',
|
||||||
|
'gdi32.lib',
|
||||||
|
'winspool.lib',
|
||||||
|
'comdlg32.lib',
|
||||||
|
'advapi32.lib',
|
||||||
|
'shell32.lib',
|
||||||
|
'ole32.lib',
|
||||||
|
'oleaut32.lib',
|
||||||
|
'uuid.lib',
|
||||||
|
'odbc32.lib',
|
||||||
|
'odbccp32.lib',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Optimization
|
||||||
|
if builder.options.opt == '1':
|
||||||
|
cxx.defines += ['NDEBUG']
|
||||||
|
if cxx.like('gcc'):
|
||||||
|
cxx.cflags += ['-O3']
|
||||||
|
elif cxx.like('msvc'):
|
||||||
|
cxx.cflags += ['/Ox']
|
||||||
|
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
|
||||||
|
|
||||||
|
# Debugging
|
||||||
|
if builder.options.debug == '1':
|
||||||
|
cxx.defines += ['DEBUG', '_DEBUG']
|
||||||
|
if cxx.like('msvc'):
|
||||||
|
cxx.cflags += ['/Od', '/RTC1']
|
||||||
|
if cxx.version >= 1600:
|
||||||
|
cxx.cflags += ['/d2Zi+']
|
||||||
|
|
||||||
|
# This needs to be after our optimization flags which could otherwise disable it.
|
||||||
|
if cxx.vendor == 'msvc':
|
||||||
|
# Don't omit the frame pointer.
|
||||||
|
cxx.cflags += ['/Oy-']
|
||||||
|
|
||||||
|
# Platform-specifics
|
||||||
|
if builder.target_platform == 'linux':
|
||||||
|
cxx.defines += ['_LINUX', 'POSIX']
|
||||||
|
if cxx.vendor == 'gcc':
|
||||||
|
cxx.linkflags += ['-static-libgcc']
|
||||||
|
elif cxx.vendor == 'clang':
|
||||||
|
cxx.linkflags += ['-lgcc_eh']
|
||||||
|
elif builder.target_platform == 'mac':
|
||||||
|
cxx.defines += ['OSX', '_OSX', 'POSIX']
|
||||||
|
cxx.cflags += ['-mmacosx-version-min=10.5']
|
||||||
|
cxx.linkflags += [
|
||||||
|
'-mmacosx-version-min=10.5',
|
||||||
|
'-arch', 'i386',
|
||||||
|
'-lstdc++',
|
||||||
|
'-stdlib=libstdc++',
|
||||||
|
]
|
||||||
|
cxx.cxxflags += ['-stdlib=libstdc++']
|
||||||
|
elif builder.target_platform == 'windows':
|
||||||
|
cxx.defines += ['WIN32', '_WINDOWS']
|
||||||
|
|
||||||
|
# Finish up.
|
||||||
|
cxx.defines += [
|
||||||
|
'SOURCEMOD_BUILD',
|
||||||
|
'SM_USE_VERSIONLIB',
|
||||||
|
]
|
||||||
|
if self.use_auto_versioning():
|
||||||
|
cxx.defines += ['SM_GENERATED_BUILD']
|
||||||
|
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
|
||||||
|
cxx.includes += [os.path.join(builder.sourcePath, 'versionlib')]
|
||||||
|
|
||||||
|
def AddVersioning(self, binary):
|
||||||
|
if builder.target_platform == 'windows':
|
||||||
|
binary.sources += ['version.rc']
|
||||||
|
binary.compiler.rcdefines += [
|
||||||
|
'BINARY_NAME="{0}"'.format(binary.outputFile),
|
||||||
|
'RC_COMPILE',
|
||||||
|
]
|
||||||
|
if self.use_auto_versioning():
|
||||||
|
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
|
||||||
|
elif builder.target_platform == 'mac':
|
||||||
|
if binary.type == 'library':
|
||||||
|
binary.compiler.postlink += [
|
||||||
|
'-compatibility_version', '1.0.0',
|
||||||
|
'-current_version', self.productVersion
|
||||||
|
]
|
||||||
|
if self.use_auto_versioning():
|
||||||
|
binary.compiler.linkflags += [self.versionlib]
|
||||||
|
binary.compiler.sourcedeps += SM.generated_headers
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def Library(self, context, name):
|
||||||
|
binary = context.compiler.Library(name)
|
||||||
|
return self.AddVersioning(binary)
|
||||||
|
|
||||||
|
def Program(self, context, name):
|
||||||
|
binary = context.compiler.Program(name)
|
||||||
|
return self.AddVersioning(binary)
|
||||||
|
|
||||||
|
def ConfigureForExtension(self, context, compiler):
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(context.currentSourcePath),
|
||||||
|
os.path.join(context.currentSourcePath, 'sdk'),
|
||||||
|
os.path.join(builder.sourcePath, 'public'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'extensions'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
|
]
|
||||||
|
return compiler
|
||||||
|
|
||||||
|
def ExtLibrary(self, context, name):
|
||||||
|
binary = context.compiler.Library(name)
|
||||||
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
|
return self.AddVersioning(binary)
|
||||||
|
|
||||||
|
def ConfigureForHL2(self, binary, sdk):
|
||||||
|
compiler = binary.compiler
|
||||||
|
|
||||||
|
if sdk.name == 'episode1':
|
||||||
|
mms_path = os.path.join(self.mms_root, 'core-legacy')
|
||||||
|
else:
|
||||||
|
mms_path = os.path.join(self.mms_root, 'core')
|
||||||
|
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(mms_path),
|
||||||
|
os.path.join(mms_path, 'sourcehook'),
|
||||||
|
]
|
||||||
|
|
||||||
|
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
|
||||||
|
compiler.defines += defines
|
||||||
|
|
||||||
|
paths = [
|
||||||
|
['public'],
|
||||||
|
['public', 'engine'],
|
||||||
|
['public', 'mathlib'],
|
||||||
|
['public', 'vstdlib'],
|
||||||
|
['public', 'tier0'],
|
||||||
|
['public', 'tier1']
|
||||||
|
]
|
||||||
|
if sdk.name == 'episode1' or sdk.name == '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'])
|
||||||
|
|
||||||
|
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
|
||||||
|
|
||||||
|
if sdk.name == 'sdk2013' and compiler.like('gcc'):
|
||||||
|
# The 2013 SDK already has these in public/tier0/basetypes.h
|
||||||
|
compiler.defines.remove('stricmp=strcasecmp')
|
||||||
|
compiler.defines.remove('_stricmp=strcasecmp')
|
||||||
|
compiler.defines.remove('_snprintf=snprintf')
|
||||||
|
compiler.defines.remove('_vsnprintf=vsnprintf')
|
||||||
|
|
||||||
|
if compiler.like('msvc'):
|
||||||
|
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
|
||||||
|
else:
|
||||||
|
compiler.defines += ['COMPILER_GCC']
|
||||||
|
|
||||||
|
# For everything after Swarm, this needs to be defined for entity networking
|
||||||
|
# to work properly with sendprop value changes.
|
||||||
|
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
|
||||||
|
compiler.defines += ['NETWORK_VARS_ENABLED']
|
||||||
|
|
||||||
|
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']:
|
||||||
|
if builder.target_platform in ['linux', 'mac']:
|
||||||
|
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
|
||||||
|
|
||||||
|
if sdk.name == 'csgo' and builder.target_platform == 'linux':
|
||||||
|
compiler.linkflags += ['-lstdc++']
|
||||||
|
|
||||||
|
for path in paths:
|
||||||
|
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
|
||||||
|
|
||||||
|
if builder.target_platform == 'linux':
|
||||||
|
if sdk.name == 'episode1':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'linux_sdk')
|
||||||
|
elif sdk.name == 'sdk2013':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
|
||||||
|
else:
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
|
||||||
|
elif builder.target_platform == 'mac':
|
||||||
|
if sdk.name == 'sdk2013':
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
|
||||||
|
else:
|
||||||
|
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
|
||||||
|
|
||||||
|
if builder.target_platform in ['linux', 'mac']:
|
||||||
|
if sdk.name == 'sdk2013':
|
||||||
|
compiler.postlink += [
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
compiler.postlink += [
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
|
||||||
|
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
|
||||||
|
]
|
||||||
|
|
||||||
|
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
|
||||||
|
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
|
||||||
|
|
||||||
|
self.AddVersioning(binary)
|
||||||
|
|
||||||
|
dynamic_libs = []
|
||||||
|
if builder.target_platform == 'linux':
|
||||||
|
compiler.linkflags[0:0] = ['-lm']
|
||||||
|
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'nucleardawn', 'l4d2']:
|
||||||
|
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
|
||||||
|
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
|
||||||
|
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
|
||||||
|
else:
|
||||||
|
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
|
||||||
|
elif builder.target_platform == 'mac':
|
||||||
|
compiler.linkflags.append('-liconv')
|
||||||
|
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
|
||||||
|
elif builder.target_platform == 'windows':
|
||||||
|
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
||||||
|
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
|
||||||
|
libs.append('interfaces')
|
||||||
|
for lib in libs:
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
|
||||||
|
compiler.linkflags.append(compiler.Dep(lib_path))
|
||||||
|
|
||||||
|
for library in dynamic_libs:
|
||||||
|
source_path = os.path.join(lib_folder, library)
|
||||||
|
output_path = os.path.join(binary.localFolder, library)
|
||||||
|
|
||||||
|
def make_linker(source_path, output_path):
|
||||||
|
def link(context, binary):
|
||||||
|
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
|
||||||
|
return output
|
||||||
|
return link
|
||||||
|
|
||||||
|
linker = make_linker(source_path, output_path)
|
||||||
|
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
|
||||||
|
|
||||||
|
return binary
|
||||||
|
|
||||||
|
def HL2Library(self, context, name, sdk):
|
||||||
|
binary = context.compiler.Library(name)
|
||||||
|
self.ConfigureForExtension(context, binary.compiler)
|
||||||
|
return self.ConfigureForHL2(binary, sdk)
|
||||||
|
|
||||||
|
def HL2Project(self, context, name):
|
||||||
|
project = context.compiler.LibraryProject(name)
|
||||||
|
self.ConfigureForExtension(context, project.compiler)
|
||||||
|
return project
|
||||||
|
|
||||||
|
def HL2Config(self, project, name, sdk):
|
||||||
|
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
|
||||||
|
return self.ConfigureForHL2(binary, sdk)
|
||||||
|
|
||||||
|
SM = SMConfig()
|
||||||
|
SM.detectProductVersion()
|
||||||
|
SM.detectSDKs()
|
||||||
|
SM.configure()
|
||||||
|
|
||||||
|
if SM.use_auto_versioning():
|
||||||
|
SM.generated_headers = builder.RunScript(
|
||||||
|
'tools/buildbot/Versioning',
|
||||||
|
{ 'SM': SM }
|
||||||
|
)
|
||||||
|
SM.versionlib = builder.RunScript(
|
||||||
|
'versionlib/AMBuilder',
|
||||||
|
{ 'SM': SM }
|
||||||
|
)
|
||||||
|
|
||||||
|
BuildScripts = [
|
||||||
|
'loader/AMBuilder',
|
||||||
|
'core/AMBuilder',
|
||||||
|
'core/logic/AMBuilder',
|
||||||
|
'extensions/bintools/AMBuilder',
|
||||||
|
'extensions/clientprefs/AMBuilder',
|
||||||
|
'extensions/curl/AMBuilder',
|
||||||
|
'extensions/cstrike/AMBuilder',
|
||||||
|
'extensions/geoip/AMBuilder',
|
||||||
|
'extensions/mysql/AMBuilder',
|
||||||
|
'extensions/regex/AMBuilder',
|
||||||
|
'extensions/sdkhooks/AMBuilder',
|
||||||
|
'extensions/sdktools/AMBuilder',
|
||||||
|
'extensions/sqlite/AMBuilder',
|
||||||
|
'extensions/tf2/AMBuilder',
|
||||||
|
'extensions/topmenus/AMBuilder',
|
||||||
|
'extensions/updater/AMBuilder',
|
||||||
|
'sourcepawn/compiler/AMBuilder',
|
||||||
|
'sourcepawn/jit/AMBuilder',
|
||||||
|
]
|
||||||
|
|
||||||
|
if builder.backend == 'amb2':
|
||||||
|
BuildScripts += [
|
||||||
|
'plugins/AMBuilder',
|
||||||
|
'tools/buildbot/PackageScript',
|
||||||
|
]
|
||||||
|
|
||||||
|
builder.RunBuildScripts(BuildScripts, { 'SM': SM })
|
||||||
|
|
||||||
|
if builder.options.breakpad_dump:
|
||||||
|
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM })
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Contributing
|
||||||
|
------------
|
||||||
|
|
||||||
|
Please visit [our wiki](https://wiki.alliedmods.net/Contributing_to_SourceMod) for information on how to contribute to Sourcemod.
|
||||||
|
|
||||||
|
As a sidenote, [Travis](https://travis-ci.org/alliedmodders/sourcemod) will automatically build your PR to make sure it compiles on Linux.
|
||||||
-21
@@ -1,21 +0,0 @@
|
|||||||
We now use svn:keywords "Id" on all .c/.cpp/.h/.sp/.inc files. Please make sure your client is configured properly.
|
|
||||||
|
|
||||||
WINDOWS:
|
|
||||||
Open your Application Data folder.
|
|
||||||
Windows XP/2000: C:\Documents and Settings\<user>\Application Data
|
|
||||||
Windows Vista: C:\Users\<user>\AppData\Roaming
|
|
||||||
|
|
||||||
Now go to Subversion. Open the "config" file with a text editor.
|
|
||||||
|
|
||||||
LINUX:
|
|
||||||
Open ~/.subversion/config with your favorite text editor.
|
|
||||||
|
|
||||||
Under [miscellany], uncomment this line:
|
|
||||||
# enable-auto-props = yes
|
|
||||||
|
|
||||||
Under [auto-props], add these lines:
|
|
||||||
*.c = svn:keywords=Id
|
|
||||||
*.cpp = svn:keywords=Id
|
|
||||||
*.h = svn:keywords=Id
|
|
||||||
*.sp = svn:keywords=Id
|
|
||||||
*.inc = svn:keywords=Id
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
SourceMod
|
||||||
|
=========
|
||||||
|
|
||||||
|
General
|
||||||
|
-------
|
||||||
|
- [SourceMod website](http://www.sourcemod.net): Source Engine scripting and server administration
|
||||||
|
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=52): Discussion forum including plugin/extension development
|
||||||
|
- [General documentation](https://wiki.alliedmods.net/Category:SourceMod_Documentation): Miscellaneous information about SourceMod
|
||||||
|
- [Latest release](http://www.sourcemod.net/downloads.php): The latest stable SourceMod release
|
||||||
|
- [Build snapshots](http://www.sourcemod.net/snapshots.php): Builds of recent development versions
|
||||||
|
|
||||||
|
Development
|
||||||
|
-----------
|
||||||
|
- [Issue tracker](https://bugs.alliedmods.net): Issues that require back and forth communication
|
||||||
|
- [Building SourceMod](https://wiki.alliedmods.net/Building_SourceMod): Instructions on how to build SourceMod itself using [AMBuild](https://github.com/alliedmodders/ambuild)
|
||||||
|
- [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language
|
||||||
|
- [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
|
||||||
+1104
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
|||||||
|
// Custom admin menu commands.
|
||||||
|
// For more information:
|
||||||
|
//
|
||||||
|
// http://wiki.alliedmods.net/Custom_Admin_Menu_%28SourceMod%29
|
||||||
|
//
|
||||||
|
// Note: This file must be in Valve KeyValues format (no multiline comments)
|
||||||
|
//
|
||||||
|
|
||||||
|
"Commands"
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/* Add group options to be added to 'group' or 'groupplayer' type submenus
|
||||||
|
* The left side is the name that will show in the menu, right is the command that will be fired
|
||||||
|
*
|
||||||
|
* For more information: http://wiki.alliedmods.net/Custom_Admin_Menu_%28SourceMod%29
|
||||||
|
*/
|
||||||
|
|
||||||
|
Groups
|
||||||
|
{
|
||||||
|
"All" "@all"
|
||||||
|
"Bots" "@bots"
|
||||||
|
"Alive" "@alive"
|
||||||
|
"Dead" "@dead"
|
||||||
|
"Humans" "@humans"
|
||||||
|
"Current aim" "@aim"
|
||||||
|
|
||||||
|
/* You can enable these if you are using Counter-Strike Source and running the cstrike extension */
|
||||||
|
// "Terrorists" "@t"
|
||||||
|
// "Counter-Terrorists" "@ct"
|
||||||
|
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
// "@Full Admins"
|
// "@Full Admins"
|
||||||
//
|
//
|
||||||
// You can also specify immunity values. Two examples:
|
// You can also specify immunity values. Two examples:
|
||||||
// "83:abcdefg" //Immunity is 83, flags are abcefgh
|
// "83:abcdefgh" //Immunity is 83, flags are abcdefgh
|
||||||
// "6:@Full Admins" //Immunity is 6, group is "Full Admins"
|
// "6:@Full Admins" //Immunity is 6, group is "Full Admins"
|
||||||
//
|
//
|
||||||
// Immunity values can be any number. An admin cannot target an admin with
|
// Immunity values can be any number. An admin cannot target an admin with
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Examples: (do not put // in front of real lines, as // means 'comment')
|
// Examples: (do not put // in front of real lines, as // means 'comment')
|
||||||
//
|
//
|
||||||
// "STEAM_0:1:16" "bce" //kick, ban, slay for this steam ID, no immunity
|
// "STEAM_0:1:16" "bce" //generic, kick, unban for this steam ID, no immunity
|
||||||
// "!127.0.0.1" "99:z" //all permissions for this ip, immunity value is 99
|
// "!127.0.0.1" "99:z" //all permissions for this ip, immunity value is 99
|
||||||
// "BAILOPAN" "abc" "Gab3n" //name BAILOPAN, password "Gab3n": gets reservation, kick, ban
|
// "BAILOPAN" "abc" "Gab3n" //name BAILOPAN, password "Gab3n": gets reservation, generic, kick
|
||||||
//
|
//
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
"banreasons"
|
||||||
|
{
|
||||||
|
"Abusive" "Abusive"
|
||||||
|
"Racism" "Racism"
|
||||||
|
"General cheating/exploits" "General cheating/exploits"
|
||||||
|
"Wallhack" "Wallhack"
|
||||||
|
"Aimbot" "Aimbot"
|
||||||
|
"Speedhacking" "Speedhacking"
|
||||||
|
"Mic spamming" "Mic spamming"
|
||||||
|
"Admin disrespect" "Admin disrespect"
|
||||||
|
"Camping" "Camping"
|
||||||
|
"Team killing" "Team killing"
|
||||||
|
"Unacceptable Spray" "Unacceptable Spray"
|
||||||
|
"Breaking Server Rules" "Breaking Server Rules"
|
||||||
|
"Other" "Other"
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
||||||
//any more plugins from being loaded.
|
//any more plugins from being loaded.
|
||||||
sm plugins unload_all
|
sm plugins unload_all
|
||||||
|
sm plugins load_unlock
|
||||||
sm plugins load basebans.smx
|
sm plugins load basebans.smx
|
||||||
sm plugins load basecommands.smx
|
sm plugins load basecommands.smx
|
||||||
sm plugins load admin-flatfile.smx
|
sm plugins load admin-flatfile.smx
|
||||||
|
|||||||
@@ -80,21 +80,21 @@ sm_reserve_type 0
|
|||||||
sm_reserved_slots 0
|
sm_reserved_slots 0
|
||||||
|
|
||||||
// Specifies whether or not reserved slots will be hidden (subtracted from max
|
// 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
|
// Requires: reservedslots.smx
|
||||||
// Default: 0
|
// Default: 0
|
||||||
sm_hide_slots 0
|
sm_hide_slots 0
|
||||||
|
|
||||||
// Specifies whether or not non-admins can send messages to admins using
|
// 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
|
// Requires: basechat.smx
|
||||||
// Default: 1
|
// Default: 1
|
||||||
sm_chat_mode 1
|
sm_chat_mode 1
|
||||||
|
|
||||||
// Specifies whether or not "timeleft" will automaticly be triggered every
|
// 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
|
// Requires: basetriggers.smx
|
||||||
// Default: 0
|
// Default: 0
|
||||||
@@ -107,3 +107,28 @@ sm_timeleft_interval 0
|
|||||||
// Requires: basetriggers.smx
|
// Requires: basetriggers.smx
|
||||||
// Default: 1
|
// Default: 1
|
||||||
sm_trigger_show 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
|
||||||
|
|||||||
+53
-8
@@ -4,14 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
"Core"
|
"Core"
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Relative path to SourceMod's base directory. This is relative to the game/mod directory.
|
|
||||||
* Only change this if you have installed SourceMod in a non-default location.
|
|
||||||
*
|
|
||||||
* The default value is "addons/sourcemod"
|
|
||||||
*/
|
|
||||||
"BasePath" "addons/sourcemod"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This option determines if SourceMod logging is enabled.
|
* This option determines if SourceMod logging is enabled.
|
||||||
*
|
*
|
||||||
@@ -88,4 +80,57 @@
|
|||||||
* "off" - Translate using default server's language
|
* "off" - Translate using default server's language
|
||||||
*/
|
*/
|
||||||
"AllowClLanguageVar" "On"
|
"AllowClLanguageVar" "On"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or Disables SourceMod's automatic gamedata updating.
|
||||||
|
*
|
||||||
|
* The default value is "no". A value of "yes" will block the Auto Updater.
|
||||||
|
*/
|
||||||
|
"DisableAutoUpdate" "no"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to yes, a successful gamedata update will attempt to restart SourceMod.
|
||||||
|
* SourceMod is unloaded and reloaded, and the map is changed to the current map.
|
||||||
|
* Since gamedata updates occur when the server loads, impact should be minimal.
|
||||||
|
* But to be safe, this option is disabled by default.
|
||||||
|
*/
|
||||||
|
"ForceRestartAfterUpdate" "no"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL to use for retrieving update information.
|
||||||
|
* SSL is not yet supported.
|
||||||
|
*/
|
||||||
|
"AutoUpdateURL" "http://update.sourcemod.net/update/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show debug spew.
|
||||||
|
* 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" "yes"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a plugin takes too long to execute, hanging or freezing the game server in the process,
|
||||||
|
* SourceMod will attempt to terminate that plugin after the specified timeout length has
|
||||||
|
* passed. You can disable this feature by setting the value to "0".
|
||||||
|
*/
|
||||||
|
"SlowScriptTimeout" "8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
{
|
{
|
||||||
"driver_default" "mysql"
|
"driver_default" "mysql"
|
||||||
|
|
||||||
|
// When specifying "host", you may use an IP address, a hostname, or a socket file path
|
||||||
|
|
||||||
"default"
|
"default"
|
||||||
{
|
{
|
||||||
"driver" "default"
|
"driver" "default"
|
||||||
@@ -18,4 +20,15 @@
|
|||||||
"driver" "sqlite"
|
"driver" "sqlite"
|
||||||
"database" "sourcemod-local"
|
"database" "sourcemod-local"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"clientprefs"
|
||||||
|
{
|
||||||
|
"driver" "sqlite"
|
||||||
|
"host" "localhost"
|
||||||
|
"database" "clientprefs-sqlite"
|
||||||
|
"user" "root"
|
||||||
|
"pass" ""
|
||||||
|
//"timeout" "0"
|
||||||
|
//"port" "0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,4 @@
|
|||||||
"Languages"
|
"Languages"
|
||||||
{
|
{
|
||||||
"en" "English"
|
"en" "English"
|
||||||
"es" "Español"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,8 @@
|
|||||||
"target" "default"
|
"target" "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For the "randomcycle" plugin */
|
/* For the "nominations" plugin */
|
||||||
"rockthevote"
|
"nominations"
|
||||||
{
|
{
|
||||||
"target" "default"
|
"target" "default"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
/**
|
|
||||||
* Each sub-section of "Plugins" should have a title which specifies a plugin filename.
|
|
||||||
* Filenames have a wildcard of *. Appending .smx is not required.
|
|
||||||
* If the filename has no explicit path, it will be patched to any sub-path in the plugins folder.
|
|
||||||
*
|
|
||||||
* Available properties for plugins are:
|
|
||||||
* "pause" - Whether or not the plugin should load paused - "yes" or "no" (default)
|
|
||||||
* "lifetime" - Lifetime of the plugin. Options:
|
|
||||||
* "mapsync" - Plugins should be reloaded on mapchange if changed (default)
|
|
||||||
* "global" - Plugin will never be unloaded or updated
|
|
||||||
* "blockload" - Plugin will always be blocked from loading. Implicit (automatic) loads
|
|
||||||
* produce no error, but explicit (manual) loads will show an error message.
|
|
||||||
* (Options are one of "yes" or "no")
|
|
||||||
*
|
|
||||||
* You can also have an "Options" section declaring options to pass onto the JIT:
|
|
||||||
* "debug" - Whether or not to load the plugin in debug mode
|
|
||||||
* "profile" - Bit flags for profiling level. Add flags together to reach a value.
|
|
||||||
* WARNING: Profiler is _ALPHA_ software! Use it at your own risk for
|
|
||||||
* development cycles only (not production setups).
|
|
||||||
* See the wiki article "SourceMod Profiler" for more information.
|
|
||||||
* 1 - Profile natives
|
|
||||||
* 2 - Profile callbacks
|
|
||||||
* 4 - Profile internal plugin function calls
|
|
||||||
*/
|
|
||||||
|
|
||||||
"Plugins"
|
|
||||||
{
|
|
||||||
"*"
|
|
||||||
{
|
|
||||||
"pause" "no"
|
|
||||||
"lifetime" "mapsync"
|
|
||||||
|
|
||||||
"Options"
|
|
||||||
{
|
|
||||||
"debug" "no"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
CREATE TABLE sm_cookies
|
||||||
|
(
|
||||||
|
id INTEGER unsigned NOT NULL auto_increment,
|
||||||
|
name varchar(30) NOT NULL UNIQUE,
|
||||||
|
description varchar(255),
|
||||||
|
access INTEGER,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE sm_cookie_cache
|
||||||
|
(
|
||||||
|
player varchar(65) NOT NULL,
|
||||||
|
cookie_id int(10) NOT NULL,
|
||||||
|
value varchar(100),
|
||||||
|
timestamp int NOT NULL,
|
||||||
|
PRIMARY KEY (player, cookie_id)
|
||||||
|
);
|
||||||
Binary file not shown.
@@ -0,0 +1,16 @@
|
|||||||
|
CREATE TABLE sm_cookies
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name varchar(30) NOT NULL UNIQUE,
|
||||||
|
description varchar(255),
|
||||||
|
access INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE sm_cookie_cache
|
||||||
|
(
|
||||||
|
player varchar(65) NOT NULL,
|
||||||
|
cookie_id int(10) NOT NULL,
|
||||||
|
value varchar(100),
|
||||||
|
timestamp int,
|
||||||
|
PRIMARY KEY (player, cookie_id)
|
||||||
|
);
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# vim: set ts=2 sw=2 tw=99 noet:
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
from ambuild2 import run
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
import ambuild
|
||||||
|
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
|
||||||
|
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
|
||||||
|
except:
|
||||||
|
sys.stderr.write('AMBuild must be installed to build this project.\n')
|
||||||
|
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
run = run.PrepareBuild(sourcePath=sys.path[0])
|
||||||
|
run.default_build_folder = 'obj-' + run.target_platform
|
||||||
|
run.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
|
||||||
|
help='Root search folder for HL2SDKs')
|
||||||
|
run.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None,
|
||||||
|
help='Path to MySQL 5')
|
||||||
|
run.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
|
||||||
|
help='Path to Metamod:Source')
|
||||||
|
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.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
||||||
|
default=False, help='Dump and upload breakpad symbols')
|
||||||
|
run.Configure()
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
|
import os
|
||||||
|
|
||||||
|
project = SM.HL2Project(builder, 'sourcemod')
|
||||||
|
project.sources += [
|
||||||
|
'MenuStyle_Valve.cpp',
|
||||||
|
'logic_bridge.cpp',
|
||||||
|
'smn_entities.cpp',
|
||||||
|
'sm_stringutil.cpp',
|
||||||
|
'MenuVoting.cpp',
|
||||||
|
'smn_events.cpp',
|
||||||
|
'smn_menus.cpp',
|
||||||
|
'CDataPack.cpp',
|
||||||
|
'frame_hooks.cpp',
|
||||||
|
'smn_nextmap.cpp',
|
||||||
|
'sourcemm_api.cpp',
|
||||||
|
'ChatTriggers.cpp',
|
||||||
|
'smn_player.cpp',
|
||||||
|
'sourcemod.cpp',
|
||||||
|
'concmd_cleaner.cpp',
|
||||||
|
'HalfLife2.cpp',
|
||||||
|
'NextMap.cpp',
|
||||||
|
'ConCmdManager.cpp',
|
||||||
|
'ConVarManager.cpp',
|
||||||
|
'LibrarySys.cpp',
|
||||||
|
'PlayerManager.cpp',
|
||||||
|
'TimerSys.cpp',
|
||||||
|
'CoreConfig.cpp',
|
||||||
|
'Logger.cpp',
|
||||||
|
'smn_halflife.cpp',
|
||||||
|
'smn_console.cpp',
|
||||||
|
'UserMessages.cpp',
|
||||||
|
'MenuManager.cpp',
|
||||||
|
'smn_core.cpp',
|
||||||
|
'smn_hudtext.cpp',
|
||||||
|
'smn_usermsgs.cpp',
|
||||||
|
'MenuStyle_Base.cpp',
|
||||||
|
'smn_keyvalues.cpp',
|
||||||
|
'smn_vector.cpp',
|
||||||
|
'EventManager.cpp',
|
||||||
|
'MenuStyle_Radio.cpp',
|
||||||
|
'sm_autonatives.cpp',
|
||||||
|
'sm_srvcmds.cpp',
|
||||||
|
'ConsoleDetours.cpp'
|
||||||
|
]
|
||||||
|
|
||||||
|
for sdk_name in SM.sdks:
|
||||||
|
sdk = SM.sdks[sdk_name]
|
||||||
|
binary_name = 'sourcemod.' + sdk.ext
|
||||||
|
|
||||||
|
binary = SM.HL2Config(project, binary_name, sdk)
|
||||||
|
compiler = binary.compiler
|
||||||
|
|
||||||
|
if sdk.name == 'csgo':
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||||
|
]
|
||||||
|
elif sdk.name == 'dota':
|
||||||
|
compiler.cxxincludes += [
|
||||||
|
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
|
||||||
|
]
|
||||||
|
|
||||||
|
if builder.target_platform == 'linux':
|
||||||
|
compiler.postlink += ['-lpthread', '-lrt']
|
||||||
|
|
||||||
|
if sdk.name == 'csgo' or sdk.name == 'dota':
|
||||||
|
if builder.target_platform == 'linux':
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||||
|
elif builder.target_platform == 'mac':
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||||
|
elif builder.target_platform == 'windows':
|
||||||
|
msvc_ver = compiler.version
|
||||||
|
vs_year = ''
|
||||||
|
if msvc_ver == 1800:
|
||||||
|
vs_year = '2013'
|
||||||
|
elif msvc_ver == 1700:
|
||||||
|
vs_year = '2012'
|
||||||
|
elif msvc_ver == 1600:
|
||||||
|
vs_year = '2010'
|
||||||
|
else:
|
||||||
|
raise Exception('Cannot find libprotobuf for MSVC version "' + compiler.version + '"')
|
||||||
|
|
||||||
|
if 'DEBUG' in compiler.defines:
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||||
|
else:
|
||||||
|
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||||
|
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||||
|
|
||||||
|
if sdk.name in ['csgo', 'dota']:
|
||||||
|
binary.sources += ['smn_protobuf.cpp']
|
||||||
|
else:
|
||||||
|
binary.sources += ['smn_bitbuffer.cpp']
|
||||||
|
|
||||||
|
if sdk.name == 'csgo':
|
||||||
|
binary.sources += [
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||||
|
]
|
||||||
|
elif sdk.name == 'dota':
|
||||||
|
binary.sources += [
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'network_connection.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'ai_activity.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessages.pb.cc'),
|
||||||
|
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessage_helpers.cpp'),
|
||||||
|
]
|
||||||
|
|
||||||
|
SM.binaries += builder.Add(project)
|
||||||
|
|
||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "CDataPack.h"
|
#include "CDataPack.h"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -44,7 +44,11 @@ public: //IRecipientFilter
|
|||||||
bool IsReliable() const;
|
bool IsReliable() const;
|
||||||
bool IsInitMessage() const;
|
bool IsInitMessage() const;
|
||||||
int GetRecipientCount() const;
|
int GetRecipientCount() const;
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
CEntityIndex GetRecipientIndex(int slot) const;
|
||||||
|
#else
|
||||||
int GetRecipientIndex(int slot) const;
|
int GetRecipientIndex(int slot) const;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
void Initialize(const cell_t *ptr, size_t count);
|
void Initialize(const cell_t *ptr, size_t count);
|
||||||
void SetToReliable(bool isreliable);
|
void SetToReliable(bool isreliable);
|
||||||
@@ -79,13 +83,27 @@ inline int CellRecipientFilter::GetRecipientCount() const
|
|||||||
return m_Size;
|
return m_Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
inline CEntityIndex CellRecipientFilter::GetRecipientIndex(int slot) const
|
||||||
|
#else
|
||||||
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
if ((slot < 0) || (slot >= GetRecipientCount()))
|
if ((slot < 0) || (slot >= GetRecipientCount()))
|
||||||
{
|
{
|
||||||
return -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
return static_cast<int>(m_Players[slot]);
|
else
|
||||||
|
{
|
||||||
|
ret = static_cast<int>(m_Players[slot]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
return CEntityIndex(ret);
|
||||||
|
#else
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
|
||||||
|
|||||||
+228
-148
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,39 +34,40 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "ConCmdManager.h"
|
#include "ConCmdManager.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "Translator.h"
|
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include "sourcemod.h"
|
||||||
|
|
||||||
/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
* While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
|
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
||||||
* can technically be compiled against any MM:S version after 1.4.2.
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
*/
|
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||||
#if defined ORANGEBOX_BUILD
|
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
|
||||||
#else
|
#else
|
||||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
# if SH_IMPL_VERSION >= 4
|
||||||
#if SH_IMPL_VERSION >= 5
|
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
|
# else
|
||||||
#elif SH_IMPL_VERSION == 4
|
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||||
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
# endif
|
||||||
#elif SH_IMPL_VERSION == 3
|
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||||
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
#endif
|
||||||
#endif //SH_IMPL_VERSION
|
|
||||||
#endif //ORANGEBOX_BUILD
|
|
||||||
|
|
||||||
ChatTriggers g_ChatTriggers;
|
ChatTriggers g_ChatTriggers;
|
||||||
bool g_bSupressSilentFails = false;
|
bool g_bSupressSilentFails = false;
|
||||||
CPhraseFile *g_pFloodPhrases = NULL;
|
|
||||||
|
|
||||||
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
|
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
|
||||||
m_bTriggerWasSilent(false), m_ReplyTo(SM_REPLY_CONSOLE)
|
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL)
|
||||||
{
|
{
|
||||||
m_PubTrigger = sm_strdup("!");
|
m_PubTrigger = sm_strdup("!");
|
||||||
m_PrivTrigger = sm_strdup("/");
|
m_PrivTrigger = sm_strdup("/");
|
||||||
m_PubTriggerSize = 1;
|
m_PubTriggerSize = 1;
|
||||||
m_PrivTriggerSize = 1;
|
m_PrivTriggerSize = 1;
|
||||||
m_bIsChatTrigger = false;
|
m_bIsChatTrigger = false;
|
||||||
|
m_bPluginIgnored = true;
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
m_bIsINS = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatTriggers::~ChatTriggers()
|
ChatTriggers::~ChatTriggers()
|
||||||
@@ -75,6 +76,8 @@ ChatTriggers::~ChatTriggers()
|
|||||||
m_PubTrigger = NULL;
|
m_PubTrigger = NULL;
|
||||||
delete [] m_PrivTrigger;
|
delete [] m_PrivTrigger;
|
||||||
m_PrivTrigger = NULL;
|
m_PrivTrigger = NULL;
|
||||||
|
delete [] m_ArgSBackup;
|
||||||
|
m_ArgSBackup = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
||||||
@@ -108,76 +111,94 @@ ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
|
|||||||
|
|
||||||
void ChatTriggers::OnSourceModAllInitialized()
|
void ChatTriggers::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
|
m_pShouldFloodBlock = forwardsys->CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
|
||||||
m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
|
m_pDidFloodBlock = forwardsys->CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
|
||||||
|
m_pOnClientSayCmd = forwardsys->CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
|
||||||
|
m_pOnClientSayCmd_Post = forwardsys->CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModAllInitialized_Post()
|
void ChatTriggers::OnSourceModAllInitialized_Post()
|
||||||
{
|
{
|
||||||
unsigned int file_id;
|
logicore.AddCorePhraseFile("antiflood.phrases");
|
||||||
|
|
||||||
file_id = g_Translator.FindOrAddPhraseFile("antiflood.phrases.txt");
|
|
||||||
g_pFloodPhrases = g_Translator.GetFileByIndex(file_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatTriggers::OnSourceModGameInitialized()
|
void ChatTriggers::OnSourceModGameInitialized()
|
||||||
{
|
{
|
||||||
unsigned int total = 2;
|
m_pSayCmd = FindCommand("say");
|
||||||
ConCommandBase *pCmd = icvar->GetCommands();
|
m_pSayTeamCmd = FindCommand("say_team");
|
||||||
const char *name;
|
|
||||||
while (pCmd)
|
|
||||||
{
|
|
||||||
if (pCmd->IsCommand())
|
|
||||||
{
|
|
||||||
name = pCmd->GetName();
|
|
||||||
if (!m_pSayCmd && strcmp(name, "say") == 0)
|
|
||||||
{
|
|
||||||
m_pSayCmd = (ConCommand *)pCmd;
|
|
||||||
if (--total == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (!m_pSayTeamCmd && strcmp(name, "say_team") == 0) {
|
|
||||||
m_pSayTeamCmd = (ConCommand *)pCmd;
|
|
||||||
if (--total == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pCmd = const_cast<ConCommandBase *>(pCmd->GetNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_pSayCmd)
|
if (m_pSayCmd)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||||
}
|
}
|
||||||
if (m_pSayTeamCmd)
|
if (m_pSayTeamCmd)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||||
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(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()
|
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)
|
if (m_pSayCmd)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
|
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
|
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Forwards.ReleaseForward(m_pShouldFloodBlock);
|
if (m_pSayTeamCmd)
|
||||||
g_Forwards.ReleaseForward(m_pDidFloodBlock);
|
{
|
||||||
|
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
|
||||||
|
|
||||||
|
forwardsys->ReleaseForward(m_pShouldFloodBlock);
|
||||||
|
forwardsys->ReleaseForward(m_pDidFloodBlock);
|
||||||
|
forwardsys->ReleaseForward(m_pOnClientSayCmd);
|
||||||
|
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
|
||||||
|
{
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
|
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
@@ -185,49 +206,106 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
{
|
{
|
||||||
CCommand command;
|
CCommand command;
|
||||||
#endif
|
#endif
|
||||||
int client;
|
int client = g_ConCmds.GetCommandClient();
|
||||||
CPlayer *pPlayer;
|
|
||||||
|
|
||||||
client = g_ConCmds.GetCommandClient();
|
|
||||||
m_bIsChatTrigger = false;
|
m_bIsChatTrigger = false;
|
||||||
m_bWasFloodedMessage = false;
|
m_bWasFloodedMessage = false;
|
||||||
|
m_bPluginIgnored = true;
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *args = command.ArgS();
|
const char *args = command.ArgS();
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
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);
|
||||||
|
size_t len = strlen(args);
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
if (m_bIsINS)
|
||||||
|
{
|
||||||
|
if (strcmp(m_Arg0Backup, "say2") == 0 && len >= 4)
|
||||||
|
{
|
||||||
|
args += 4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The first pair of quotes are stripped from client say commands, but not console ones.
|
||||||
|
* We do not want the forwards to differ from what is displayed.
|
||||||
|
* So only strip the first pair of quotes from client say commands. */
|
||||||
|
bool is_quoted = false;
|
||||||
|
|
||||||
|
if (
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
!m_bIsINS &&
|
||||||
|
#endif
|
||||||
|
client != 0 && args[0] == '"' && args[len-1] == '"')
|
||||||
|
{
|
||||||
|
/* The server normally won't display empty say commands, but in this case it does.
|
||||||
|
* I don't think it's desired so let's block it. */
|
||||||
|
if (len <= 2)
|
||||||
|
{
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
args++;
|
||||||
|
len--;
|
||||||
|
is_quoted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some? engines strip the last quote when printing the string to chat.
|
||||||
|
* This results in having a double-quoted message passed to the OnClientSayCommand ("message") forward,
|
||||||
|
* but losing the last quote in the OnClientSayCommand_Post ("message) forward.
|
||||||
|
* To compensate this, we copy the args into our own buffer where the engine won't mess with
|
||||||
|
* and strip the quotes. */
|
||||||
|
delete [] m_ArgSBackup;
|
||||||
|
m_ArgSBackup = new char[CCommand::MaxCommandLength()+1];
|
||||||
|
memcpy(m_ArgSBackup, args, len+1);
|
||||||
|
|
||||||
|
/* Strip the quotes from the argument */
|
||||||
|
if (is_quoted)
|
||||||
|
{
|
||||||
|
if (m_ArgSBackup[len-1] == '"')
|
||||||
|
{
|
||||||
|
m_ArgSBackup[--len] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The server console cannot do this */
|
||||||
|
if (client == 0)
|
||||||
|
{
|
||||||
|
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
||||||
|
{
|
||||||
|
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 */
|
/* Check if we need to block this message from being sent */
|
||||||
if (ClientIsFlooding(client))
|
if (ClientIsFlooding(client))
|
||||||
{
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
|
|
||||||
/* :TODO: log an error? */
|
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
|
||||||
if (g_Translator.CoreTransEx(g_pFloodPhrases,
|
|
||||||
client,
|
|
||||||
buffer,
|
|
||||||
sizeof(buffer),
|
|
||||||
"Flooding the server",
|
|
||||||
NULL,
|
|
||||||
NULL)
|
|
||||||
!= Trans_Okay)
|
|
||||||
{
|
|
||||||
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
|
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
|
||||||
}
|
|
||||||
|
|
||||||
/* :TODO: we should probably kick people who spam too much. */
|
/* :TODO: we should probably kick people who spam too much. */
|
||||||
|
|
||||||
@@ -240,62 +318,41 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle quoted string sets */
|
|
||||||
bool is_quoted = false;
|
|
||||||
if (args[0] == '"')
|
|
||||||
{
|
|
||||||
args++;
|
|
||||||
is_quoted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_trigger = false;
|
bool is_trigger = false;
|
||||||
bool is_silent = false;
|
bool is_silent = false;
|
||||||
|
|
||||||
/* Check for either trigger */
|
/* Check for either trigger */
|
||||||
if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
|
if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0)
|
||||||
{
|
{
|
||||||
is_trigger = true;
|
is_trigger = true;
|
||||||
args = &args[m_PubTriggerSize];
|
args = &m_ArgSBackup[m_PubTriggerSize];
|
||||||
}
|
}
|
||||||
else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0)
|
else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0)
|
||||||
{
|
{
|
||||||
is_trigger = true;
|
is_trigger = true;
|
||||||
is_silent = true;
|
is_silent = true;
|
||||||
args = &args[m_PrivTriggerSize];
|
args = &m_ArgSBackup[m_PrivTriggerSize];
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_trigger)
|
|
||||||
{
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if this is actually a command!
|
* Test if this is actually a command!
|
||||||
*/
|
*/
|
||||||
if (!PreProcessTrigger(engine->PEntityOfEntIndex(client), args, is_quoted))
|
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args))
|
||||||
{
|
{
|
||||||
CPlayer *pPlayer;
|
m_bIsChatTrigger = true;
|
||||||
if (is_silent
|
|
||||||
&& g_bSupressSilentFails
|
/**
|
||||||
&& client != 0
|
* We'll execute it in post.
|
||||||
&& (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
|
*/
|
||||||
&& pPlayer->GetAdminId() != INVALID_ADMIN_ID)
|
m_bWillProcessInPost = true;
|
||||||
{
|
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
|
||||||
}
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bIsChatTrigger = true;
|
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
|
||||||
|
{
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
if (CallOnClientSayCommand(client) >= Pl_Handled)
|
||||||
* We'll execute it in post.
|
|
||||||
*/
|
|
||||||
m_bWillProcessInPost = true;
|
|
||||||
m_bTriggerWasSilent = is_silent;
|
|
||||||
|
|
||||||
/* If we're silent, block */
|
|
||||||
if (is_silent)
|
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
@@ -304,28 +361,44 @@ void ChatTriggers::OnSayCommand_Pre()
|
|||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
||||||
#else
|
#else
|
||||||
void ChatTriggers::OnSayCommand_Post()
|
void ChatTriggers::OnSayCommand_Post()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
m_bIsChatTrigger = false;
|
int client = g_ConCmds.GetCommandClient();
|
||||||
m_bWasFloodedMessage = false;
|
|
||||||
if (m_bWillProcessInPost)
|
if (m_bWillProcessInPost)
|
||||||
{
|
{
|
||||||
/* Reset this for re-entrancy */
|
/* Reset this for re-entrancy */
|
||||||
m_bWillProcessInPost = false;
|
m_bWillProcessInPost = false;
|
||||||
|
|
||||||
/* Execute the cached command */
|
/* Execute the cached command */
|
||||||
int client = g_ConCmds.GetCommandClient();
|
|
||||||
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
||||||
serverpluginhelpers->ClientCommand(engine->PEntityOfEntIndex(client), m_ToExecute);
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
engine->ClientCommand(client, "%s", m_ToExecute);
|
||||||
|
#else
|
||||||
|
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
||||||
|
#endif
|
||||||
SetReplyTo(old);
|
SetReplyTo(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_bPluginIgnored && 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)
|
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
||||||
{
|
{
|
||||||
/* Extract a command. This is kind of sloppy. */
|
/* Extract a command. This is kind of sloppy. */
|
||||||
char cmd_buf[64];
|
char cmd_buf[64];
|
||||||
@@ -367,12 +440,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepended = true;
|
prepended = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if we need to do extra string manipulation */
|
/* See if we need to do extra string manipulation */
|
||||||
if (is_quoted || prepended)
|
if (prepended)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
@@ -383,15 +456,6 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_
|
|||||||
} else {
|
} else {
|
||||||
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we need to strip a quote */
|
|
||||||
if (is_quoted)
|
|
||||||
{
|
|
||||||
if (m_ToExecute[len-1] == '"')
|
|
||||||
{
|
|
||||||
m_ToExecute[--len] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
|
||||||
}
|
}
|
||||||
@@ -399,6 +463,22 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cell_t ChatTriggers::CallOnClientSayCommand(int client)
|
||||||
|
{
|
||||||
|
cell_t res = Pl_Continue;
|
||||||
|
if (m_pOnClientSayCmd->GetFunctionCount() != 0)
|
||||||
|
{
|
||||||
|
m_pOnClientSayCmd->PushCell(client);
|
||||||
|
m_pOnClientSayCmd->PushString(m_Arg0Backup);
|
||||||
|
m_pOnClientSayCmd->PushString(m_ArgSBackup);
|
||||||
|
m_pOnClientSayCmd->Execute(&res);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bPluginIgnored = (res >= Pl_Stop);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
|
unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
|
||||||
{
|
{
|
||||||
unsigned int old = m_ReplyTo;
|
unsigned int old = m_ReplyTo;
|
||||||
|
|||||||
+20
-4
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -54,7 +54,10 @@ public: //SMGlobalClass
|
|||||||
char *error,
|
char *error,
|
||||||
size_t maxlength);
|
size_t maxlength);
|
||||||
private: //ConCommand
|
private: //ConCommand
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void OnSayCommand_Pre(const CCommandContext &, const CCommand &command);
|
||||||
|
void OnSayCommand_Post(const CCommandContext &, const CCommand &command);
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void OnSayCommand_Pre(const CCommand &command);
|
void OnSayCommand_Pre(const CCommand &command);
|
||||||
void OnSayCommand_Post(const CCommand &command);
|
void OnSayCommand_Post(const CCommand &command);
|
||||||
#else
|
#else
|
||||||
@@ -67,23 +70,36 @@ public:
|
|||||||
bool IsChatTrigger();
|
bool IsChatTrigger();
|
||||||
bool WasFloodedMessage();
|
bool WasFloodedMessage();
|
||||||
private:
|
private:
|
||||||
bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
|
bool PreProcessTrigger(edict_t *pEdict, const char *args);
|
||||||
bool ClientIsFlooding(int client);
|
bool ClientIsFlooding(int client);
|
||||||
|
cell_t CallOnClientSayCommand(int client);
|
||||||
private:
|
private:
|
||||||
ConCommand *m_pSayCmd;
|
ConCommand *m_pSayCmd;
|
||||||
ConCommand *m_pSayTeamCmd;
|
ConCommand *m_pSayTeamCmd;
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
ConCommand *m_pSay2Cmd;
|
||||||
|
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||||
|
ConCommand *m_pSaySquadCmd;
|
||||||
|
#endif
|
||||||
char *m_PubTrigger;
|
char *m_PubTrigger;
|
||||||
size_t m_PubTriggerSize;
|
size_t m_PubTriggerSize;
|
||||||
char *m_PrivTrigger;
|
char *m_PrivTrigger;
|
||||||
size_t m_PrivTriggerSize;
|
size_t m_PrivTriggerSize;
|
||||||
bool m_bWillProcessInPost;
|
bool m_bWillProcessInPost;
|
||||||
bool m_bTriggerWasSilent;
|
|
||||||
bool m_bIsChatTrigger;
|
bool m_bIsChatTrigger;
|
||||||
bool m_bWasFloodedMessage;
|
bool m_bWasFloodedMessage;
|
||||||
|
bool m_bPluginIgnored;
|
||||||
unsigned int m_ReplyTo;
|
unsigned int m_ReplyTo;
|
||||||
char m_ToExecute[300];
|
char m_ToExecute[300];
|
||||||
|
const char *m_Arg0Backup;
|
||||||
|
char *m_ArgSBackup;
|
||||||
IForward *m_pShouldFloodBlock;
|
IForward *m_pShouldFloodBlock;
|
||||||
IForward *m_pDidFloodBlock;
|
IForward *m_pDidFloodBlock;
|
||||||
|
IForward *m_pOnClientSayCmd;
|
||||||
|
IForward *m_pOnClientSayCmd_Post;
|
||||||
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
|
bool m_bIsINS;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ChatTriggers g_ChatTriggers;
|
extern ChatTriggers g_ChatTriggers;
|
||||||
|
|||||||
+256
-558
File diff suppressed because it is too large
Load Diff
+57
-34
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,71 +34,90 @@
|
|||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "ForwardSys.h"
|
#include <IForwardSys.h>
|
||||||
#include "sm_trie.h"
|
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
#include <IAdminSystem.h>
|
#include <IAdminSystem.h>
|
||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
#include <am-utility.h>
|
||||||
|
#include <am-inlinelist.h>
|
||||||
|
#include <am-linkedlist.h>
|
||||||
|
#include <am-refcounting.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
enum CmdType
|
struct CmdHook;
|
||||||
|
struct ConCmdInfo;
|
||||||
|
|
||||||
|
struct CommandGroup : public ke::Refcounted<CommandGroup>
|
||||||
{
|
{
|
||||||
Cmd_Server,
|
ke::LinkedList<CmdHook *> hooks;
|
||||||
Cmd_Console,
|
|
||||||
Cmd_Admin,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AdminCmdInfo
|
struct AdminCmdInfo
|
||||||
{
|
{
|
||||||
AdminCmdInfo()
|
AdminCmdInfo(const ke::Ref<CommandGroup> &group, FlagBits flags)
|
||||||
|
: group(group),
|
||||||
|
flags(flags),
|
||||||
|
eflags(0)
|
||||||
{
|
{
|
||||||
cmdGrpId = -1;
|
|
||||||
flags = 0;
|
|
||||||
eflags = 0;
|
|
||||||
}
|
}
|
||||||
int cmdGrpId; /* index into cmdgroup string table */
|
ke::Ref<CommandGroup> group;
|
||||||
FlagBits flags; /* default flags */
|
FlagBits flags; /* default flags */
|
||||||
FlagBits eflags; /* effective flags */
|
FlagBits eflags; /* effective flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmdHook
|
struct CmdHook : public ke::InlineListNode<CmdHook>
|
||||||
{
|
{
|
||||||
CmdHook()
|
enum Type {
|
||||||
|
Server,
|
||||||
|
Client
|
||||||
|
};
|
||||||
|
|
||||||
|
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
|
||||||
|
: type(type),
|
||||||
|
info(cmd),
|
||||||
|
pf(fun),
|
||||||
|
helptext(description)
|
||||||
{
|
{
|
||||||
pf = NULL;
|
|
||||||
pAdmin = NULL;
|
|
||||||
}
|
}
|
||||||
IPluginFunction *pf; /* function hook */
|
|
||||||
String helptext; /* help text */
|
Type type;
|
||||||
AdminCmdInfo *pAdmin; /* admin requirements, if any */
|
ConCmdInfo *info;
|
||||||
|
IPluginFunction *pf; /* function hook */
|
||||||
|
ke::AString helptext; /* help text */
|
||||||
|
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef ke::InlineList<CmdHook> CmdHookList;
|
||||||
|
|
||||||
struct ConCmdInfo
|
struct ConCmdInfo
|
||||||
{
|
{
|
||||||
ConCmdInfo()
|
ConCmdInfo()
|
||||||
{
|
{
|
||||||
sourceMod = false;
|
sourceMod = false;
|
||||||
pCmd = NULL;
|
pCmd = NULL;
|
||||||
|
eflags = 0;
|
||||||
}
|
}
|
||||||
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
||||||
ConCommand *pCmd; /**< Pointer to the command itself */
|
ConCommand *pCmd; /**< Pointer to the command itself */
|
||||||
List<CmdHook *> srvhooks; /**< Hooks as a server command */
|
CmdHookList hooks; /**< Hook list */
|
||||||
List<CmdHook *> conhooks; /**< Hooks as a console command */
|
FlagBits eflags; /**< Effective admin flags */
|
||||||
AdminCmdInfo admin; /**< Admin info, if any */
|
|
||||||
bool is_admin_set; /**< Whether or not admin info is set */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef List<ConCmdInfo *> ConCmdList;
|
||||||
|
|
||||||
class ConCmdManager :
|
class ConCmdManager :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IRootConsoleCommand,
|
public IRootConsoleCommand,
|
||||||
public IPluginsListener,
|
public IPluginsListener,
|
||||||
public IConCommandTracker
|
public IConCommandTracker
|
||||||
{
|
{
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
friend void CommandCallback(const CCommand &command);
|
friend void CommandCallback(const CCommand &command);
|
||||||
#else
|
#else
|
||||||
friend void CommandCallback();
|
friend void CommandCallback();
|
||||||
@@ -117,7 +136,6 @@ public: //IConCommandTracker
|
|||||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
||||||
public:
|
public:
|
||||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
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,
|
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *group,
|
const char *group,
|
||||||
@@ -128,7 +146,6 @@ public:
|
|||||||
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
||||||
bool LookForSourceModCommand(const char *cmd);
|
bool LookForSourceModCommand(const char *cmd);
|
||||||
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
|
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
|
||||||
bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
|
|
||||||
private:
|
private:
|
||||||
void InternalDispatch(const CCommand &command);
|
void InternalDispatch(const CCommand &command);
|
||||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
||||||
@@ -136,9 +153,13 @@ private:
|
|||||||
void SetCommandClient(int client);
|
void SetCommandClient(int client);
|
||||||
void AddToCmdList(ConCmdInfo *info);
|
void AddToCmdList(ConCmdInfo *info);
|
||||||
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
|
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
|
||||||
void RemoveConCmds(List<CmdHook *> &cmdlist);
|
|
||||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
|
||||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
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:
|
public:
|
||||||
inline int GetCommandClient()
|
inline int GetCommandClient()
|
||||||
{
|
{
|
||||||
@@ -149,13 +170,15 @@ public:
|
|||||||
return m_CmdList;
|
return m_CmdList;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Trie *m_pCmds; /* command lookup */
|
typedef StringHashMap<ke::Ref<CommandGroup> > GroupMap;
|
||||||
Trie *m_pCmdGrps; /* command group lookup */
|
|
||||||
List<ConCmdInfo *> m_CmdList; /* command list */
|
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
|
||||||
|
GroupMap m_CmdGrps; /* command group map */
|
||||||
|
ConCmdList m_CmdList; /* command list */
|
||||||
int m_CmdClient; /* current client */
|
int m_CmdClient; /* current client */
|
||||||
BaseStringTable m_Strings; /* string table */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConCmdManager g_ConCmds;
|
extern ConCmdManager g_ConCmds;
|
||||||
|
|
||||||
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
#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_ */
|
||||||
|
|
||||||
+198
-78
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -25,38 +25,69 @@
|
|||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sm_srvcmds.h"
|
#include "sm_srvcmds.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <sm_trie_tpl.h>
|
#include <sm_namehashset.h>
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
ConVarManager g_ConVarManager;
|
ConVarManager g_ConVarManager;
|
||||||
|
|
||||||
#if !defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
||||||
#else
|
#else
|
||||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
|
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
|
||||||
|
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
|
||||||
|
#elif SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
||||||
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
||||||
typedef List<const ConVar *> ConVarList;
|
typedef List<const ConVar *> ConVarList;
|
||||||
KTrie<ConVarInfo *> convar_cache;
|
NameHashSet<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)
|
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
|
||||||
{
|
{
|
||||||
@@ -76,7 +107,7 @@ void ConVarManager::OnSourceModStartup(bool late)
|
|||||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||||
|
|
||||||
/* Create the 'ConVar' handle type */
|
/* Create the 'ConVar' handle type */
|
||||||
m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
m_ConVarType = handlesys->CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnSourceModAllInitialized()
|
void ConVarManager::OnSourceModAllInitialized()
|
||||||
@@ -84,15 +115,23 @@ void ConVarManager::OnSourceModAllInitialized()
|
|||||||
/**
|
/**
|
||||||
* Episode 2 has this function by default, but the older versions do not.
|
* Episode 2 has this function by default, but the older versions do not.
|
||||||
*/
|
*/
|
||||||
#if !defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||||
if (g_SMAPI->GetGameDLLVersion() >= 6)
|
if (g_SMAPI->GetGameDLLVersion() >= 6)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
||||||
m_bIsDLLQueryHooked = true;
|
m_bIsDLLQueryHooked = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
g_Players.AddClientListener(this);
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
|
||||||
|
#else
|
||||||
|
SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scripts->AddPluginsListener(this);
|
||||||
|
|
||||||
/* Add the 'convars' option to the 'sm' console command */
|
/* Add the 'convars' option to the 'sm' console command */
|
||||||
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
||||||
@@ -110,10 +149,10 @@ void ConVarManager::OnSourceModShutdown()
|
|||||||
|
|
||||||
iter = m_ConVars.erase(iter);
|
iter = m_ConVars.erase(iter);
|
||||||
|
|
||||||
g_HandleSys.FreeHandle(pInfo->handle, &sec);
|
handlesys->FreeHandle(pInfo->handle, &sec);
|
||||||
if (pInfo->pChangeForward != NULL)
|
if (pInfo->pChangeForward != NULL)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(pInfo->pChangeForward);
|
forwardsys->ReleaseForward(pInfo->pChangeForward);
|
||||||
}
|
}
|
||||||
if (pInfo->sourceMod)
|
if (pInfo->sourceMod)
|
||||||
{
|
{
|
||||||
@@ -141,25 +180,37 @@ void ConVarManager::OnSourceModShutdown()
|
|||||||
}
|
}
|
||||||
convar_cache.clear();
|
convar_cache.clear();
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
/* Unhook things */
|
/* Unhook things */
|
||||||
if (m_bIsDLLQueryHooked)
|
if (m_bIsDLLQueryHooked)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
SH_REMOVE_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
||||||
m_bIsDLLQueryHooked = false;
|
m_bIsDLLQueryHooked = false;
|
||||||
}
|
}
|
||||||
else if (m_bIsVSPQueryHooked)
|
else if (m_bIsVSPQueryHooked)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
#if SOURCE_ENGINE != SE_DOTA
|
||||||
|
SH_REMOVE_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
||||||
|
#endif
|
||||||
m_bIsVSPQueryHooked = false;
|
m_bIsVSPQueryHooked = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
g_Players.RemoveClientListener(this);
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
|
||||||
|
#else
|
||||||
|
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Remove the 'convars' option from the 'sm' console command */
|
/* Remove the 'convars' option from the 'sm' console command */
|
||||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
||||||
|
|
||||||
|
scripts->RemovePluginsListener(this);
|
||||||
|
|
||||||
/* Remove the 'ConVar' handle type */
|
/* Remove the 'ConVar' handle type */
|
||||||
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
|
handlesys->RemoveType(m_ConVarType, g_pCoreIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,7 +227,7 @@ void ConVarManager::OnSourceModVSPReceived()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* For later MM:S versions, use the updated API, since it's cleaner. */
|
/* 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();
|
int engine = g_SMAPI->GetSourceEngineBuild();
|
||||||
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
||||||
{
|
{
|
||||||
@@ -189,22 +240,15 @@ void ConVarManager::OnSourceModVSPReceived()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
#if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA
|
||||||
|
SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
|
||||||
m_bIsVSPQueryHooked = true;
|
m_bIsVSPQueryHooked = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
||||||
{
|
{
|
||||||
ConVarInfo **pLookup = convar_cache.retrieve(name);
|
return convar_cache.retrieve(name, pVar);
|
||||||
if (pLookup != NULL)
|
|
||||||
{
|
|
||||||
*pVar = *pLookup;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
|
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
|
||||||
@@ -223,7 +267,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
|||||||
convar_cache.remove(name);
|
convar_cache.remove(name);
|
||||||
|
|
||||||
/* Now make sure no plugins are referring to this pointer */
|
/* Now make sure no plugins are referring to this pointer */
|
||||||
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
|
IPluginIterator *pl_iter = scripts->GetPluginIterator();
|
||||||
while (pl_iter->MorePlugins())
|
while (pl_iter->MorePlugins())
|
||||||
{
|
{
|
||||||
IPlugin *pl = pl_iter->GetPlugin();
|
IPlugin *pl = pl_iter->GetPlugin();
|
||||||
@@ -239,19 +283,51 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free resources */
|
/* Free resources */
|
||||||
g_HandleSys.FreeHandle(pInfo->handle, &sec);
|
handlesys->FreeHandle(pInfo->handle, &sec);
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
ConVarList *pConVarList;
|
ConVarList *pConVarList;
|
||||||
|
List<ConVarQuery>::iterator iter;
|
||||||
|
|
||||||
/* If plugin has a convar list, free its memory */
|
/* If plugin has a convar list, free its memory */
|
||||||
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
||||||
{
|
{
|
||||||
delete pConVarList;
|
delete pConVarList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IPluginRuntime * pRuntime = plugin->GetRuntime();
|
||||||
|
|
||||||
|
/* Remove convar queries for this plugin that haven't returned results yet */
|
||||||
|
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
|
||||||
|
{
|
||||||
|
ConVarQuery &query = (*iter);
|
||||||
|
if (query.pCallback->GetParentRuntime() == pRuntime)
|
||||||
|
{
|
||||||
|
iter = m_ConVarQueries.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConVarManager::OnClientDisconnected(int client)
|
||||||
|
{
|
||||||
|
/* Remove convar queries for this client that haven't returned results yet */
|
||||||
|
for (List<ConVarQuery>::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
|
||||||
|
{
|
||||||
|
ConVarQuery &query = (*iter);
|
||||||
|
if (query.client == client)
|
||||||
|
{
|
||||||
|
iter = m_ConVarQueries.erase(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||||
@@ -269,11 +345,18 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
int argcount = command.ArgC();
|
int argcount = command.ArgC();
|
||||||
if (argcount >= 3)
|
if (argcount >= 3)
|
||||||
{
|
{
|
||||||
|
bool wantReset = false;
|
||||||
|
|
||||||
/* Get plugin index that was passed */
|
/* Get plugin index that was passed */
|
||||||
const char *arg = command.Arg(2);
|
const char *arg = command.Arg(2);
|
||||||
|
if (argcount >= 4 && strcmp(arg, "reset") == 0)
|
||||||
|
{
|
||||||
|
wantReset = true;
|
||||||
|
arg = command.Arg(3);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get plugin object */
|
/* Get plugin object */
|
||||||
CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
|
IPlugin *plugin = scripts->FindPluginByConsoleArg(arg);
|
||||||
|
|
||||||
if (!plugin)
|
if (!plugin)
|
||||||
{
|
{
|
||||||
@@ -295,21 +378,34 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
if (!wantReset)
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
{
|
||||||
|
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
|
||||||
/* Iterate convar list and display each one */
|
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate convar list and display/reset each one */
|
||||||
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
|
||||||
{
|
{
|
||||||
const ConVar *pConVar = (*iter);
|
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter);
|
||||||
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display usage of subcommand */
|
/* 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)
|
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)
|
||||||
@@ -341,7 +437,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
|||||||
pInfo->pVar = pConVar;
|
pInfo->pVar = pConVar;
|
||||||
|
|
||||||
/* If we don't, then create a new handle from the convar */
|
/* If we don't, then create a new handle from the convar */
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||||
if (hndl == BAD_HANDLE)
|
if (hndl == BAD_HANDLE)
|
||||||
{
|
{
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
@@ -359,17 +455,10 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To prevent creating a convar that has the same name as a console command... ugh */
|
/* Prevent creating a convar that has the same name as a console command */
|
||||||
ConCommandBase *pBase = icvar->GetCommands();
|
if (FindCommand(name))
|
||||||
|
|
||||||
while (pBase)
|
|
||||||
{
|
{
|
||||||
if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
|
return BAD_HANDLE;
|
||||||
{
|
|
||||||
return BAD_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and initialize ConVarInfo structure */
|
/* Create and initialize ConVarInfo structure */
|
||||||
@@ -379,7 +468,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
|||||||
pInfo->pChangeForward = NULL;
|
pInfo->pChangeForward = NULL;
|
||||||
|
|
||||||
/* Create a handle from the new convar */
|
/* Create a handle from the new convar */
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||||
if (hndl == BAD_HANDLE)
|
if (hndl == BAD_HANDLE)
|
||||||
{
|
{
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
@@ -408,7 +497,13 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
ConVarInfo *pInfo;
|
ConVarInfo *pInfo;
|
||||||
Handle_t hndl;
|
Handle_t hndl;
|
||||||
|
|
||||||
/* Search for convar */
|
/* Check convar cache to find out if we already have a handle */
|
||||||
|
if (convar_cache_lookup(name, &pInfo))
|
||||||
|
{
|
||||||
|
return pInfo->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Couldn't find it in cache, so search for it */
|
||||||
pConVar = icvar->FindVar(name);
|
pConVar = icvar->FindVar(name);
|
||||||
|
|
||||||
/* If it doesn't exist, then return an invalid handle */
|
/* If it doesn't exist, then return an invalid handle */
|
||||||
@@ -417,12 +512,6 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
return BAD_HANDLE;
|
return BAD_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point, the convar exists. So, find out if we already have a handle */
|
|
||||||
if (convar_cache_lookup(name, &pInfo))
|
|
||||||
{
|
|
||||||
return pInfo->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create and initialize ConVarInfo structure */
|
/* Create and initialize ConVarInfo structure */
|
||||||
pInfo = new ConVarInfo();
|
pInfo = new ConVarInfo();
|
||||||
pInfo->sourceMod = false;
|
pInfo->sourceMod = false;
|
||||||
@@ -430,7 +519,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
pInfo->pVar = pConVar;
|
pInfo->pVar = pConVar;
|
||||||
|
|
||||||
/* If we don't have a handle, then create a new one */
|
/* If we don't have a handle, then create a new one */
|
||||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||||
if (hndl == BAD_HANDLE)
|
if (hndl == BAD_HANDLE)
|
||||||
{
|
{
|
||||||
delete pInfo;
|
delete pInfo;
|
||||||
@@ -488,7 +577,7 @@ void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction
|
|||||||
/* If forward does not exist, create it */
|
/* If forward does not exist, create it */
|
||||||
if (!pForward)
|
if (!pForward)
|
||||||
{
|
{
|
||||||
pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
|
pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
|
||||||
pInfo->pChangeForward = pForward;
|
pInfo->pChangeForward = pForward;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,10 +613,11 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the forward now has 0 functions in it... */
|
/* If the forward now has 0 functions in it... */
|
||||||
if (pForward->GetFunctionCount() == 0)
|
if (pForward->GetFunctionCount() == 0 &&
|
||||||
|
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
|
||||||
{
|
{
|
||||||
/* Free this forward */
|
/* Free this forward */
|
||||||
g_Forwards.ReleaseForward(pForward);
|
forwardsys->ReleaseForward(pForward);
|
||||||
pInfo->pChangeForward = NULL;
|
pInfo->pChangeForward = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -535,24 +625,35 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
|||||||
|
|
||||||
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
|
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
|
||||||
{
|
{
|
||||||
QueryCvarCookie_t cookie;
|
QueryCvarCookie_t cookie = 0;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
|
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
|
||||||
if (m_bIsDLLQueryHooked)
|
if (m_bIsDLLQueryHooked)
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
cookie = engine->StartQueryCvarValue(CEntityIndex(IndexOfEdict(pPlayer)), name);
|
||||||
|
#else
|
||||||
cookie = engine->StartQueryCvarValue(pPlayer, name);
|
cookie = engine->StartQueryCvarValue(pPlayer, name);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#if SOURCE_ENGINE != SE_DOTA
|
||||||
else if (m_bIsVSPQueryHooked)
|
else if (m_bIsVSPQueryHooked)
|
||||||
{
|
{
|
||||||
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
|
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return InvalidQueryCvarCookie;
|
return InvalidQueryCvarCookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConVarQuery query = {cookie, pCallback, hndl};
|
if (pCallback != NULL)
|
||||||
m_ConVarQueries.push_back(query);
|
{
|
||||||
|
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
|
||||||
|
m_ConVarQueries.push_back(query);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
@@ -564,7 +665,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
|
|||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
const char *orig = pConVar->GetName();
|
const char *orig = pConVar->GetName();
|
||||||
|
|
||||||
IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||||
|
|
||||||
/* Check plugin for an existing convar list */
|
/* Check plugin for an existing convar list */
|
||||||
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
||||||
@@ -595,7 +696,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
||||||
#else
|
#else
|
||||||
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||||
@@ -623,7 +724,7 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
|||||||
i != pInfo->changeListeners.end();
|
i != pInfo->changeListeners.end();
|
||||||
i++)
|
i++)
|
||||||
{
|
{
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
|
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
|
||||||
#else
|
#else
|
||||||
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
|
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
|
||||||
@@ -633,6 +734,8 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
|||||||
|
|
||||||
if (pForward != NULL)
|
if (pForward != NULL)
|
||||||
{
|
{
|
||||||
|
ConVarReentrancyGuard guard(pConVar);
|
||||||
|
|
||||||
/* Now call forwards in plugins that have hooked this */
|
/* Now call forwards in plugins that have hooked this */
|
||||||
pForward->PushCell(pInfo->handle);
|
pForward->PushCell(pInfo->handle);
|
||||||
pForward->PushString(oldValue);
|
pForward->PushString(oldValue);
|
||||||
@@ -646,8 +749,20 @@ bool ConVarManager::IsQueryingSupported()
|
|||||||
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
|
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||||
|
#else
|
||||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||||
|
#endif // SE_DOTA
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
IPluginFunction *pCallback = NULL;
|
IPluginFunction *pCallback = NULL;
|
||||||
cell_t value = 0;
|
cell_t value = 0;
|
||||||
List<ConVarQuery>::iterator iter;
|
List<ConVarQuery>::iterator iter;
|
||||||
@@ -668,7 +783,11 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
|
|||||||
cell_t ret;
|
cell_t ret;
|
||||||
|
|
||||||
pCallback->PushCell(cookie);
|
pCallback->PushCell(cookie);
|
||||||
pCallback->PushCell(engine->IndexOfEdict(pPlayer));
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
pCallback->PushCell(player.Get());
|
||||||
|
#else
|
||||||
|
pCallback->PushCell(IndexOfEdict(pPlayer));
|
||||||
|
#endif
|
||||||
pCallback->PushCell(result);
|
pCallback->PushCell(result);
|
||||||
pCallback->PushString(cvarName);
|
pCallback->PushString(cvarName);
|
||||||
|
|
||||||
@@ -687,13 +806,14 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
|
|||||||
m_ConVarQueries.erase(iter);
|
m_ConVarQueries.erase(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
|
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
|
||||||
{
|
{
|
||||||
ConVarInfo *pInfo;
|
ConVarInfo *pInfo;
|
||||||
HandleError error;
|
HandleError error;
|
||||||
|
|
||||||
if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
|
if ((error = handlesys->ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-4
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -39,8 +39,15 @@
|
|||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
|
#include <IPlayerHelpers.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DARKMESSIAH
|
||||||
|
class EQueryCvarValueStatus;
|
||||||
|
typedef int QueryCvarCookie_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
@@ -60,6 +67,11 @@ struct ConVarInfo
|
|||||||
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
||||||
ConVar *pVar; /**< The actual convar */
|
ConVar *pVar; /**< The actual convar */
|
||||||
List<IConVarChangeListener *> changeListeners;
|
List<IConVarChangeListener *> changeListeners;
|
||||||
|
|
||||||
|
static inline bool matches(const char *name, const ConVarInfo *info)
|
||||||
|
{
|
||||||
|
return strcmp(name, info->pVar->GetName()) == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,6 +82,7 @@ struct ConVarQuery
|
|||||||
QueryCvarCookie_t cookie; /**< Cookie that identifies query */
|
QueryCvarCookie_t cookie; /**< Cookie that identifies query */
|
||||||
IPluginFunction *pCallback; /**< Function that will be called when query is finished */
|
IPluginFunction *pCallback; /**< Function that will be called when query is finished */
|
||||||
cell_t value; /**< Optional value passed to query function */
|
cell_t value; /**< Optional value passed to query function */
|
||||||
|
cell_t client; /**< Only used for cleaning up on client disconnection */
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConVarManager :
|
class ConVarManager :
|
||||||
@@ -77,7 +90,8 @@ class ConVarManager :
|
|||||||
public IHandleTypeDispatch,
|
public IHandleTypeDispatch,
|
||||||
public IPluginsListener,
|
public IPluginsListener,
|
||||||
public IRootConsoleCommand,
|
public IRootConsoleCommand,
|
||||||
public IConCommandTracker
|
public IConCommandTracker,
|
||||||
|
public IClientListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConVarManager();
|
ConVarManager();
|
||||||
@@ -96,6 +110,8 @@ public: //IRootConsoleCommand
|
|||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||||
public: //IConCommandTracker
|
public: //IConCommandTracker
|
||||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
|
||||||
|
public: //IClientListener
|
||||||
|
void OnClientDisconnected(int client);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a convar and return a handle to it.
|
* Create a convar and return a handle to it.
|
||||||
@@ -140,7 +156,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Static callback that Valve's ConVar object executes when the convar's value changes.
|
* Static callback that Valve's ConVar object executes when the convar's value changes.
|
||||||
*/
|
*/
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||||
#else
|
#else
|
||||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
||||||
@@ -149,8 +165,13 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Callback for when StartQueryCvarValue() has finished.
|
* Callback for when StartQueryCvarValue() has finished.
|
||||||
*/
|
*/
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result,
|
||||||
|
const char *cvarName, const char *cvarValue);
|
||||||
|
#elif SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
|
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
|
||||||
const char *cvarName, const char *cvarValue);
|
const char *cvarName, const char *cvarValue);
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
HandleType_t m_ConVarType;
|
HandleType_t m_ConVarType;
|
||||||
List<ConVarInfo *> m_ConVars;
|
List<ConVarInfo *> m_ConVars;
|
||||||
|
|||||||
@@ -0,0 +1,739 @@
|
|||||||
|
/**
|
||||||
|
* 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 "logic_bridge.h"
|
||||||
|
#include <am-utility.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_DOTA
|
||||||
|
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
||||||
|
# elif 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_DOTA
|
||||||
|
void Dispatch(const CCommandContext &context, const CCommand& args)
|
||||||
|
# elif 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 = forwardsys->CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
|
||||||
|
Param_String, Param_Cell);
|
||||||
|
sharesys->AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleDetours::OnSourceModShutdown()
|
||||||
|
{
|
||||||
|
for (StringHashMap<IChangeableForward *>::iterator iter = m_Listeners.iter();
|
||||||
|
!iter.empty();
|
||||||
|
iter.next())
|
||||||
|
{
|
||||||
|
forwardsys->ReleaseForward(iter->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
forwardsys->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
|
||||||
|
{
|
||||||
|
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
|
||||||
|
IChangeableForward *forward;
|
||||||
|
if (!m_Listeners.retrieve(str, &forward))
|
||||||
|
{
|
||||||
|
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
|
||||||
|
Param_String, Param_Cell);
|
||||||
|
m_Listeners.insert(str, forward);
|
||||||
|
}
|
||||||
|
forward->AddFunction(fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
|
||||||
|
{
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
return m_pForward->RemoveFunction(fun);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
|
||||||
|
IChangeableForward *forward;
|
||||||
|
if (!m_Listeners.retrieve(str, &forward))
|
||||||
|
return false;
|
||||||
|
return 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;
|
||||||
|
|
||||||
|
IChangeableForward *forward;
|
||||||
|
if (!m_Listeners.retrieve(name, &forward))
|
||||||
|
return result;
|
||||||
|
if (forward->GetFunctionCount() == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
cell_t result2 = Pl_Continue;
|
||||||
|
forward->PushCell(client);
|
||||||
|
forward->PushString(name);
|
||||||
|
forward->PushCell(args.ArgC() - 1);
|
||||||
|
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(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
|
||||||
|
dummy_hook_set = true;
|
||||||
|
pBase->Dispatch();
|
||||||
|
SH_REMOVE_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Make sure the command gets invoked. See bug 4019 on making this better. */
|
||||||
|
pBase->Dispatch();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -28,85 +28,51 @@
|
|||||||
*
|
*
|
||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||||
|
|
||||||
#include <string.h>
|
#include "sm_globals.h"
|
||||||
#include <malloc.h>
|
#include "sourcemm_api.h"
|
||||||
#include "sm_memtable.h"
|
#include <IForwardSys.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
BaseMemTable::BaseMemTable(unsigned int init_size)
|
class ConsoleDetours :
|
||||||
|
public SMGlobalClass,
|
||||||
|
public IFeatureProvider
|
||||||
{
|
{
|
||||||
membase = (unsigned char *)malloc(init_size);
|
friend class PlayerManager;
|
||||||
size = init_size;
|
friend class GenericCommandHooker;
|
||||||
tail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseMemTable::~BaseMemTable()
|
public:
|
||||||
{
|
ConsoleDetours();
|
||||||
free(membase);
|
public: //SMGlobalClass
|
||||||
membase = NULL;
|
void OnSourceModAllInitialized();
|
||||||
}
|
void OnSourceModShutdown();
|
||||||
|
public: //IFeatureProvider
|
||||||
int BaseMemTable::CreateMem(unsigned int addsize, void **addr)
|
FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
|
||||||
{
|
public:
|
||||||
int idx = (int)tail;
|
bool AddListener(IPluginFunction *fun, const char *command);
|
||||||
|
bool RemoveListener(IPluginFunction *fun, const char *command);
|
||||||
while (tail + addsize >= size)
|
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()
|
||||||
{
|
{
|
||||||
size *= 2;
|
return status == FeatureStatus_Available;
|
||||||
membase = (unsigned char *)realloc(membase, size);
|
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
FeatureStatus status;
|
||||||
|
IChangeableForward *m_pForward;
|
||||||
|
StringHashMap<IChangeableForward *> m_Listeners;
|
||||||
|
};
|
||||||
|
|
||||||
tail += addsize;
|
extern ConsoleDetours g_ConsoleDetours;
|
||||||
|
|
||||||
if (addr)
|
#endif /* _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_ */
|
||||||
{
|
|
||||||
*addr = (void *)&membase[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *BaseMemTable::GetAddress(int index)
|
|
||||||
{
|
|
||||||
if (index < 0 || (unsigned int)index >= tail)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &membase[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseMemTable::Reset()
|
|
||||||
{
|
|
||||||
tail = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseStringTable::BaseStringTable(unsigned int init_size) : m_table(init_size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseStringTable::~BaseStringTable()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int BaseStringTable::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*const char *BaseStringTable::GetString(int str)
|
|
||||||
{
|
|
||||||
return (const char *)m_table.GetAddress(str);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void BaseStringTable::Reset()
|
|
||||||
{
|
|
||||||
m_table.Reset();
|
|
||||||
}
|
|
||||||
+197
-31
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,41 +34,153 @@
|
|||||||
#include "sourcemod.h"
|
#include "sourcemod.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_srvcmds.h"
|
#include "sm_srvcmds.h"
|
||||||
#include "sm_version.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "LibrarySys.h"
|
#include "LibrarySys.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "PluginSys.h"
|
#include "frame_hooks.h"
|
||||||
#include "ForwardSys.h"
|
#include "logic_bridge.h"
|
||||||
|
#include <sourcemod_version.h>
|
||||||
|
|
||||||
#ifdef PLATFORM_WINDOWS
|
#ifdef PLATFORM_WINDOWS
|
||||||
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
|
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||||
ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
|
ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IForward *g_pOnServerCfg = NULL;
|
IForward *g_pOnServerCfg = NULL;
|
||||||
IForward *g_pOnConfigsExecuted = NULL;
|
IForward *g_pOnConfigsExecuted = NULL;
|
||||||
|
IForward *g_pOnAutoConfigsBuffered = NULL;
|
||||||
CoreConfig g_CoreConfig;
|
CoreConfig g_CoreConfig;
|
||||||
bool g_bConfigsExecd = false;
|
bool g_bConfigsExecd = false;
|
||||||
|
bool g_bServerExecd = false;
|
||||||
|
bool g_bGotServerStart = false;
|
||||||
|
bool g_bGotTrigger = false;
|
||||||
|
ConCommand *g_pExecPtr = NULL;
|
||||||
|
ConVar *g_ServerCfgFile = NULL;
|
||||||
|
|
||||||
|
void CheckAndFinalizeConfigs();
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
||||||
|
void Hook_ExecDispatchPre(const CCommandContext &context, const CCommand &cmd)
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||||
|
void Hook_ExecDispatchPre(const CCommand &cmd)
|
||||||
|
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||||
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||||
|
void Hook_ExecDispatchPre()
|
||||||
|
#else
|
||||||
|
# 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
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||||
|
CCommand cmd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *arg = cmd.Arg(1);
|
||||||
|
|
||||||
|
if (!g_bServerExecd && arg != NULL && strcmp(arg, g_ServerCfgFile->GetString()) == 0)
|
||||||
|
{
|
||||||
|
g_bGotTrigger = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void Hook_ExecDispatchPost(const CCommandContext &context, const CCommand &cmd)
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
void Hook_ExecDispatchPost(const CCommand &cmd)
|
||||||
|
#else
|
||||||
|
void Hook_ExecDispatchPost()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (g_bGotTrigger)
|
||||||
|
{
|
||||||
|
g_bGotTrigger = false;
|
||||||
|
g_bServerExecd = true;
|
||||||
|
CheckAndFinalizeConfigs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckAndFinalizeConfigs()
|
||||||
|
{
|
||||||
|
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
|
||||||
|
{
|
||||||
|
g_PendingInternalPush = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CoreConfig::OnSourceModAllInitialized()
|
void CoreConfig::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
|
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
|
||||||
g_pOnServerCfg = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
|
||||||
g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
|
||||||
|
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreConfig::CoreConfig()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreConfig::~CoreConfig()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::OnSourceModShutdown()
|
void CoreConfig::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
g_RootMenu.RemoveRootConsoleCommand("config", this);
|
g_RootMenu.RemoveRootConsoleCommand("config", this);
|
||||||
g_Forwards.ReleaseForward(g_pOnServerCfg);
|
forwardsys->ReleaseForward(g_pOnServerCfg);
|
||||||
g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
|
forwardsys->ReleaseForward(g_pOnConfigsExecuted);
|
||||||
|
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered);
|
||||||
|
|
||||||
|
if (g_pExecPtr != NULL)
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false);
|
||||||
|
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true);
|
||||||
|
g_pExecPtr = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::OnSourceModLevelChange(const char *mapName)
|
void CoreConfig::OnSourceModLevelChange(const char *mapName)
|
||||||
{
|
{
|
||||||
|
static bool already_checked = false;
|
||||||
|
|
||||||
|
if (!already_checked)
|
||||||
|
{
|
||||||
|
if (engine->IsDedicatedServer())
|
||||||
|
{
|
||||||
|
g_ServerCfgFile = icvar->FindVar("servercfgfile");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_ServerCfgFile = icvar->FindVar("lservercfgfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_ServerCfgFile != NULL)
|
||||||
|
{
|
||||||
|
g_pExecPtr = FindCommand("exec");
|
||||||
|
if (g_pExecPtr != NULL)
|
||||||
|
{
|
||||||
|
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false);
|
||||||
|
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_ServerCfgFile = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
already_checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
g_bConfigsExecd = false;
|
g_bConfigsExecd = false;
|
||||||
|
g_bServerExecd = false;
|
||||||
|
g_bGotServerStart = false;
|
||||||
|
g_bGotTrigger = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
||||||
@@ -85,17 +197,30 @@ void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &comma
|
|||||||
|
|
||||||
if (res == ConfigResult_Reject)
|
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) {
|
} else if (res == ConfigResult_Ignore) {
|
||||||
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
|
||||||
} else {
|
} 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
|
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> [value]");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreConfig::Initialize()
|
void CoreConfig::Initialize()
|
||||||
@@ -106,14 +231,31 @@ void CoreConfig::Initialize()
|
|||||||
/* Try to get command line value of core config convar */
|
/* Try to get command line value of core config convar */
|
||||||
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
||||||
|
|
||||||
/* If sm_corecfgfile not specified on command line, use default value */
|
/* If sm_corecfgfile is on the command line, use that
|
||||||
if (!corecfg)
|
* 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 */
|
||||||
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Format path to config file */
|
/* Reset cached key values */
|
||||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
m_KeyValues.clear();
|
||||||
|
|
||||||
/* Parse config file */
|
/* Parse config file */
|
||||||
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
|
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
|
||||||
@@ -153,9 +295,20 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
|
|||||||
pBase = pBase->m_pGlobalClassNext;
|
pBase = pBase->m_pGlobalClassNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ke::AString vstr(value);
|
||||||
|
m_KeyValues.replace(option, ke::Move(vstr));
|
||||||
|
|
||||||
return ConfigResult_Ignore;
|
return ConfigResult_Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *CoreConfig::GetCoreConfigValue(const char *key)
|
||||||
|
{
|
||||||
|
StringHashMap<ke::AString>::Result r = m_KeyValues.find(key);
|
||||||
|
if (!r.found())
|
||||||
|
return NULL;
|
||||||
|
return r->value.chars();
|
||||||
|
}
|
||||||
|
|
||||||
bool SM_AreConfigsExecuted()
|
bool SM_AreConfigsExecuted()
|
||||||
{
|
{
|
||||||
return g_bConfigsExecd;
|
return g_bConfigsExecd;
|
||||||
@@ -165,12 +318,12 @@ inline bool IsPathSepChar(char c)
|
|||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
return (c == '\\' || c == '/');
|
return (c == '\\' || c == '/');
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_LINUX || defined PLATFORM_POSIX
|
||||||
return (c == '/');
|
return (c == '/');
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||||
{
|
{
|
||||||
bool will_create = false;
|
bool will_create = false;
|
||||||
|
|
||||||
@@ -257,7 +410,7 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
FILE *fp = fopen(file, "wt");
|
FILE *fp = fopen(file, "wt");
|
||||||
if (fp)
|
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", SOURCEMOD_VERSION);
|
||||||
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
||||||
fprintf(fp, "\n\n");
|
fprintf(fp, "\n\n");
|
||||||
|
|
||||||
@@ -314,6 +467,11 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
|||||||
can_create = false;
|
can_create = false;
|
||||||
fclose(fp);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,10 +502,10 @@ void SM_DoSingleExecFwds(IPluginContext *ctx)
|
|||||||
|
|
||||||
void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
||||||
{
|
{
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
IPluginIterator *iter = scripts->GetPluginIterator();
|
||||||
while (iter->MorePlugins())
|
while (iter->MorePlugins())
|
||||||
{
|
{
|
||||||
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
|
IPlugin *plugin = iter->GetPlugin();
|
||||||
if (plugin->GetSerial() == serial)
|
if (plugin->GetSerial() == serial)
|
||||||
{
|
{
|
||||||
SM_DoSingleExecFwds(plugin->GetBaseContext());
|
SM_DoSingleExecFwds(plugin->GetBaseContext());
|
||||||
@@ -360,7 +518,7 @@ void SM_ConfigsExecuted_Plugin(unsigned int serial)
|
|||||||
|
|
||||||
void SM_ExecuteForPlugin(IPluginContext *ctx)
|
void SM_ExecuteForPlugin(IPluginContext *ctx)
|
||||||
{
|
{
|
||||||
CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
|
SMPlugin *plugin = scripts->FindPluginByContext(ctx->GetContext());
|
||||||
|
|
||||||
unsigned int num = plugin->GetConfigCount();
|
unsigned int num = plugin->GetConfigCount();
|
||||||
if (!num)
|
if (!num)
|
||||||
@@ -382,28 +540,27 @@ void SM_ExecuteForPlugin(IPluginContext *ctx)
|
|||||||
|
|
||||||
void SM_ExecuteAllConfigs()
|
void SM_ExecuteAllConfigs()
|
||||||
{
|
{
|
||||||
if (g_bConfigsExecd)
|
if (g_bGotServerStart)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
|
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
|
||||||
|
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
AutoPluginList plugins(scripts);
|
||||||
while (iter->MorePlugins())
|
for (size_t i = 0; i < plugins->size(); i++)
|
||||||
{
|
{
|
||||||
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
|
SMPlugin *plugin = plugins->at(i);
|
||||||
unsigned int num = plugin->GetConfigCount();
|
unsigned int num = plugin->GetConfigCount();
|
||||||
bool can_create = true;
|
bool can_create = true;
|
||||||
for (unsigned int i=0; i<num; i++)
|
for (unsigned int i=0; i<num; i++)
|
||||||
{
|
{
|
||||||
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
|
||||||
}
|
}
|
||||||
iter->NextPlugin();
|
|
||||||
}
|
}
|
||||||
iter->Release();
|
|
||||||
|
|
||||||
engine->ServerCommand("sm internal 1\n");
|
g_bGotServerStart = true;
|
||||||
|
CheckAndFinalizeConfigs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SM_ConfigsExecuted_Global()
|
void SM_ConfigsExecuted_Global()
|
||||||
@@ -418,3 +575,12 @@ void SM_ConfigsExecuted_Global()
|
|||||||
g_pOnServerCfg->Execute(NULL);
|
g_pOnServerCfg->Execute(NULL);
|
||||||
g_pOnConfigsExecuted->Execute(NULL);
|
g_pOnConfigsExecuted->Execute(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SM_InternalCmdTrigger()
|
||||||
|
{
|
||||||
|
/* Order is important here. We need to buffer things before we send the command out. */
|
||||||
|
g_pOnAutoConfigsBuffered->Execute(NULL);
|
||||||
|
engine->ServerCommand("sm internal 1\n");
|
||||||
|
g_PendingInternalPush = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -35,6 +35,8 @@
|
|||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include <ITextParsers.h>
|
#include <ITextParsers.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
@@ -43,6 +45,9 @@ class CoreConfig :
|
|||||||
public ITextListener_SMC,
|
public ITextListener_SMC,
|
||||||
public IRootConsoleCommand
|
public IRootConsoleCommand
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
CoreConfig();
|
||||||
|
~CoreConfig();
|
||||||
public: // SMGlobalClass
|
public: // SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
@@ -56,11 +61,14 @@ public:
|
|||||||
* Initializes CoreConfig by reading from core.cfg file
|
* Initializes CoreConfig by reading from core.cfg file
|
||||||
*/
|
*/
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
const char *GetCoreConfigValue(const char *key);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Sets configuration option by notifying SourceMod components that rely on core.cfg
|
* Sets configuration option by notifying SourceMod components that rely on core.cfg
|
||||||
*/
|
*/
|
||||||
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
|
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
|
||||||
|
private:
|
||||||
|
StringHashMap<ke::AString> m_KeyValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool SM_AreConfigsExecuted();
|
extern bool SM_AreConfigsExecuted();
|
||||||
@@ -68,6 +76,7 @@ extern void SM_ExecuteAllConfigs();
|
|||||||
extern void SM_ExecuteForPlugin(IPluginContext *ctx);
|
extern void SM_ExecuteForPlugin(IPluginContext *ctx);
|
||||||
extern void SM_ConfigsExecuted_Global();
|
extern void SM_ConfigsExecuted_Global();
|
||||||
extern void SM_ConfigsExecuted_Plugin(unsigned int serial);
|
extern void SM_ConfigsExecuted_Plugin(unsigned int serial);
|
||||||
|
extern void SM_InternalCmdTrigger();
|
||||||
|
|
||||||
extern CoreConfig g_CoreConfig;
|
extern CoreConfig g_CoreConfig;
|
||||||
|
|
||||||
|
|||||||
+110
-56
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -29,12 +29,74 @@
|
|||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "Tlhelp32.h"
|
#include "Tlhelp32.h"
|
||||||
#include "LibrarySys.h"
|
#include "LibrarySys.h"
|
||||||
#include "minidump.h"
|
#include "minidump.h"
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
|
||||||
|
bool HookImportAddrTable(BYTE *base, const char *func, DWORD hookfunc, char *err, size_t maxlength)
|
||||||
|
{
|
||||||
|
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)base;
|
||||||
|
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
|
{
|
||||||
|
UTIL_Format(err, maxlength, "%s", "Could not detect valid DOS signature");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
|
||||||
|
if (nt->Signature != IMAGE_NT_SIGNATURE)
|
||||||
|
{
|
||||||
|
UTIL_Format(err, maxlength, "%s", "Could not detect valid NT signature");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_IMPORT_DESCRIPTOR *desc =
|
||||||
|
(IMAGE_IMPORT_DESCRIPTOR *)
|
||||||
|
(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||||
|
if (base == (BYTE *)desc)
|
||||||
|
{
|
||||||
|
UTIL_Format(err, maxlength, "%s", "Could not find IAT");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool entryFound = false;
|
||||||
|
while (desc->Name)
|
||||||
|
{
|
||||||
|
if (desc->FirstThunk != 0)
|
||||||
|
{
|
||||||
|
IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
|
||||||
|
DWORD *iat = (DWORD *)(base + desc->FirstThunk);
|
||||||
|
while (data->u1.Function)
|
||||||
|
{
|
||||||
|
if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
|
||||||
|
{
|
||||||
|
IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
|
||||||
|
if (strcmp((char *)import->Name, func) == 0)
|
||||||
|
{
|
||||||
|
DWORD oldprot, oldprot2;
|
||||||
|
VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
|
||||||
|
*iat = hookfunc;
|
||||||
|
VirtualProtect(iat, 4, oldprot, &oldprot2);
|
||||||
|
entryFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data++;
|
||||||
|
iat++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entryFound)
|
||||||
|
{
|
||||||
|
UTIL_Format(err, maxlength, "Could not find IAT entry for %s", func);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
WINAPI
|
WINAPI
|
||||||
@@ -62,6 +124,24 @@ FARPROC WINAPI GetProcAddress2(HMODULE hModule, LPCSTR lpProcName)
|
|||||||
return GetProcAddress(hModule, lpProcName);
|
return GetProcAddress(hModule, lpProcName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HMODULE WINAPI LoadLibraryEx2(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
HMODULE lib = LoadLibraryEx(lpFileName, hFile, dwFlags);
|
||||||
|
|
||||||
|
/* Steam.dll seems to get loaded using an abs path, thus the use of stristr() */
|
||||||
|
if (stristr(lpFileName, "steam.dll"))
|
||||||
|
{
|
||||||
|
char err[64];
|
||||||
|
if (!HookImportAddrTable((BYTE *)lib, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
|
||||||
|
{
|
||||||
|
Error("[SM] %s in steam.dll\n", err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
class CrazyWindowsDebugger : public SMGlobalClass
|
class CrazyWindowsDebugger : public SMGlobalClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -69,6 +149,9 @@ public:
|
|||||||
{
|
{
|
||||||
HANDLE hModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
HANDLE hModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
|
||||||
MODULEENTRY32 me32;
|
MODULEENTRY32 me32;
|
||||||
|
BYTE *engine = NULL;
|
||||||
|
BYTE *steam = NULL;
|
||||||
|
char err[64];
|
||||||
|
|
||||||
me32.dwSize = sizeof(MODULEENTRY32);
|
me32.dwSize = sizeof(MODULEENTRY32);
|
||||||
|
|
||||||
@@ -77,69 +160,40 @@ public:
|
|||||||
Error("Could not initialize crazy debugger!");
|
Error("Could not initialize crazy debugger!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (strcasecmp(me32.szModule, "steam.dll") == 0)
|
if (strcasecmp(me32.szModule, "engine.dll") == 0)
|
||||||
{
|
{
|
||||||
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)me32.modBaseAddr;
|
engine = me32.modBaseAddr;
|
||||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
|
}
|
||||||
{
|
else if (strcasecmp(me32.szModule, "steam.dll") == 0)
|
||||||
Error("[SM] Could not detect steam.dll with valid DOS signature");
|
{
|
||||||
}
|
steam = me32.modBaseAddr;
|
||||||
char *base = (char *)dos;
|
|
||||||
IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
|
|
||||||
if (nt->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
|
||||||
Error("[SM] Could not detect steam.dll with valid NT signature");
|
|
||||||
}
|
|
||||||
IMAGE_IMPORT_DESCRIPTOR *desc =
|
|
||||||
(IMAGE_IMPORT_DESCRIPTOR *)
|
|
||||||
(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
|
||||||
if (base == (char *)desc)
|
|
||||||
{
|
|
||||||
Error("[SM] Could not find the steam.dll IAT");
|
|
||||||
}
|
|
||||||
while (desc->Name)
|
|
||||||
{
|
|
||||||
if (desc->FirstThunk != 0)
|
|
||||||
{
|
|
||||||
IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
|
|
||||||
DWORD *iat = (DWORD *)(base + desc->FirstThunk);
|
|
||||||
while (data->u1.Function)
|
|
||||||
{
|
|
||||||
if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
|
|
||||||
{
|
|
||||||
IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
|
|
||||||
if (strcmp((char *)import->Name, "GetProcAddress") == 0)
|
|
||||||
{
|
|
||||||
DWORD oldprot, oldprot2;
|
|
||||||
VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
|
|
||||||
*iat = (DWORD)GetProcAddress2;
|
|
||||||
VirtualProtect(iat, 4, oldprot, &oldprot2);
|
|
||||||
found = true;
|
|
||||||
goto _end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data++;
|
|
||||||
iat++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (Module32Next(hModuleList, &me32));
|
} while (Module32Next(hModuleList, &me32));
|
||||||
|
|
||||||
_end:
|
CloseHandle(hModuleList);
|
||||||
|
|
||||||
if (!found)
|
/* This really should not happen, but ... */
|
||||||
|
if (!engine)
|
||||||
{
|
{
|
||||||
Error("Could not find steam.dll's GetProcAddress IAT entry");
|
Error("[SM] Could not find engine.dll\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(hModuleList);
|
/* Steam.dll isn't loaded yet */
|
||||||
|
if (!steam)
|
||||||
|
{
|
||||||
|
if (!HookImportAddrTable(engine, "LoadLibraryExA", (DWORD)LoadLibraryEx2, err, sizeof(err)))
|
||||||
|
{
|
||||||
|
Error("[SM] %s in engine.dll)\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!HookImportAddrTable(steam, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
|
||||||
|
{
|
||||||
|
Error("[SM] %s in steam.dll)\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} s_CrazyDebugger;
|
} s_CrazyDebugger;
|
||||||
#endif
|
|
||||||
|
|||||||
+109
-52
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -30,10 +30,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "EventManager.h"
|
#include "EventManager.h"
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
EventManager g_EventManager;
|
EventManager g_EventManager;
|
||||||
|
|
||||||
@@ -42,16 +40,26 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
|
|||||||
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
||||||
typedef List<EventHook *> EventHookList;
|
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)
|
EventManager::EventManager() : m_EventType(0)
|
||||||
{
|
{
|
||||||
/* Create an event lookup trie */
|
|
||||||
m_EventHooks = sm_trie_create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventManager::~EventManager()
|
EventManager::~EventManager()
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_EventHooks);
|
|
||||||
|
|
||||||
/* Free memory used by EventInfo structs if any */
|
/* Free memory used by EventInfo structs if any */
|
||||||
CStack<EventInfo *>::iterator iter;
|
CStack<EventInfo *>::iterator iter;
|
||||||
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
|
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
|
||||||
@@ -65,8 +73,8 @@ EventManager::~EventManager()
|
|||||||
void EventManager::OnSourceModAllInitialized()
|
void EventManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
/* Add a hook for IGameEventManager2::FireEvent() */
|
/* Add a hook for IGameEventManager2::FireEvent() */
|
||||||
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
|
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
||||||
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
|
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true);
|
||||||
|
|
||||||
HandleAccess sec;
|
HandleAccess sec;
|
||||||
|
|
||||||
@@ -76,17 +84,17 @@ void EventManager::OnSourceModAllInitialized()
|
|||||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||||
|
|
||||||
/* Create the 'GameEvent' handle type */
|
/* Create the 'GameEvent' handle type */
|
||||||
m_EventType = g_HandleSys.CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
m_EventType = handlesys->CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::OnSourceModShutdown()
|
void EventManager::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
/* Remove hook for IGameEventManager2::FireEvent() */
|
/* Remove hook for IGameEventManager2::FireEvent() */
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
|
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
|
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true);
|
||||||
|
|
||||||
/* Remove the 'GameEvent' handle type */
|
/* Remove the 'GameEvent' handle type */
|
||||||
g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
|
handlesys->RemoveType(m_EventType, g_pCoreIdent);
|
||||||
|
|
||||||
/* Remove ourselves as listener for events */
|
/* Remove ourselves as listener for events */
|
||||||
gameevents->RemoveListener(this);
|
gameevents->RemoveListener(this);
|
||||||
@@ -124,12 +132,12 @@ void EventManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
{
|
{
|
||||||
if (pHook->pPreHook)
|
if (pHook->pPreHook)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(pHook->pPreHook);
|
forwardsys->ReleaseForward(pHook->pPreHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pHook->pPostHook)
|
if (pHook->pPostHook)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(pHook->pPostHook);
|
forwardsys->ReleaseForward(pHook->pPostHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pHook;
|
delete pHook;
|
||||||
@@ -147,6 +155,13 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
|||||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||||
|
int EventManager::GetEventDebugID()
|
||||||
|
{
|
||||||
|
return EVENT_DEBUG_ID_INIT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
||||||
{
|
{
|
||||||
EventHook *pHook;
|
EventHook *pHook;
|
||||||
@@ -163,10 +178,10 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If a hook structure does not exist... */
|
/* If a hook structure does not exist... */
|
||||||
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
|
if (!m_EventHooks.retrieve(name, &pHook))
|
||||||
{
|
{
|
||||||
EventHookList *pHookList;
|
EventHookList *pHookList;
|
||||||
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
|
||||||
|
|
||||||
/* Check plugin for an existing EventHook list */
|
/* Check plugin for an existing EventHook list */
|
||||||
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
|
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
|
||||||
@@ -181,24 +196,27 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
if (mode == EventHookMode_Pre)
|
if (mode == EventHookMode_Pre)
|
||||||
{
|
{
|
||||||
/* Create forward for a pre hook */
|
/* Create forward for a pre hook */
|
||||||
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
|
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
|
||||||
/* Add to forward list */
|
/* Add to forward list */
|
||||||
pHook->pPreHook->AddFunction(pFunction);
|
pHook->pPreHook->AddFunction(pFunction);
|
||||||
} else {
|
} else {
|
||||||
/* Create forward for a post hook */
|
/* Create forward for a post hook */
|
||||||
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
||||||
/* Should we copy data from a pre hook to the post hook? */
|
/* Should we copy data from a pre hook to the post hook? */
|
||||||
pHook->postCopy = (mode == EventHookMode_Post);
|
pHook->postCopy = (mode == EventHookMode_Post);
|
||||||
/* Add to forward list */
|
/* Add to forward list */
|
||||||
pHook->pPostHook->AddFunction(pFunction);
|
pHook->pPostHook->AddFunction(pFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cache the name for post hooks */
|
||||||
|
pHook->name = name;
|
||||||
|
|
||||||
/* Increase reference count */
|
/* Increase reference count */
|
||||||
pHook->refCount++;
|
pHook->refCount++;
|
||||||
|
|
||||||
/* Add hook structure to hook lists */
|
/* Add hook structure to hook lists */
|
||||||
pHookList->push_back(pHook);
|
pHookList->push_back(pHook);
|
||||||
sm_trie_insert(m_EventHooks, name, pHook);
|
m_EventHooks.insert(name, pHook);
|
||||||
|
|
||||||
return EventHookErr_Okay;
|
return EventHookErr_Okay;
|
||||||
}
|
}
|
||||||
@@ -210,7 +228,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
/* Create pre hook forward if necessary */
|
/* Create pre hook forward if necessary */
|
||||||
if (!pHook->pPreHook)
|
if (!pHook->pPreHook)
|
||||||
{
|
{
|
||||||
pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
|
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add plugin function to forward list */
|
/* Add plugin function to forward list */
|
||||||
@@ -219,7 +237,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
|||||||
/* Create post hook forward if necessary */
|
/* Create post hook forward if necessary */
|
||||||
if (!pHook->pPostHook)
|
if (!pHook->pPostHook)
|
||||||
{
|
{
|
||||||
pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If postCopy is false, then we may want to set it to true */
|
/* If postCopy is false, then we may want to set it to true */
|
||||||
@@ -244,7 +262,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
IChangeableForward **pEventForward;
|
IChangeableForward **pEventForward;
|
||||||
|
|
||||||
/* If hook does not exist at all */
|
/* If hook does not exist at all */
|
||||||
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
|
if (!m_EventHooks.retrieve(name, &pHook))
|
||||||
{
|
{
|
||||||
return EventHookErr_NotActive;
|
return EventHookErr_NotActive;
|
||||||
}
|
}
|
||||||
@@ -266,7 +284,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
/* If forward's list contains 0 functions now, free it */
|
/* If forward's list contains 0 functions now, free it */
|
||||||
if ((*pEventForward)->GetFunctionCount() == 0)
|
if ((*pEventForward)->GetFunctionCount() == 0)
|
||||||
{
|
{
|
||||||
g_Forwards.ReleaseForward(*pEventForward);
|
forwardsys->ReleaseForward(*pEventForward);
|
||||||
*pEventForward = NULL;
|
*pEventForward = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +294,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
/* If reference count is now 0, free hook structure */
|
/* If reference count is now 0, free hook structure */
|
||||||
|
|
||||||
EventHookList *pHookList;
|
EventHookList *pHookList;
|
||||||
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
|
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
|
||||||
|
|
||||||
/* Get plugin's event hook list */
|
/* Get plugin's event hook list */
|
||||||
if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
|
if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
|
||||||
@@ -294,7 +312,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
|||||||
pHookList->remove(pHook);
|
pHookList->remove(pHook);
|
||||||
|
|
||||||
/* Delete entry in trie */
|
/* Delete entry in trie */
|
||||||
sm_trie_delete(m_EventHooks, name);
|
m_EventHooks.remove(name);
|
||||||
|
|
||||||
/* And finally free structure memory */
|
/* And finally free structure memory */
|
||||||
delete pHook;
|
delete pHook;
|
||||||
@@ -321,6 +339,7 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name,
|
|||||||
|
|
||||||
pInfo->pEvent = pEvent;
|
pInfo->pEvent = pEvent;
|
||||||
pInfo->pOwner = pContext->GetIdentity();
|
pInfo->pOwner = pContext->GetIdentity();
|
||||||
|
pInfo->bDontBroadcast = false;
|
||||||
|
|
||||||
return pInfo;
|
return pInfo;
|
||||||
}
|
}
|
||||||
@@ -359,33 +378,49 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
IChangeableForward *pForward;
|
IChangeableForward *pForward;
|
||||||
const char *name;
|
const char *name;
|
||||||
cell_t res = Pl_Continue;
|
cell_t res = Pl_Continue;
|
||||||
|
bool broadcast = bDontBroadcast;
|
||||||
/* Get the event name, we're going to need this for passing to post hooks */
|
|
||||||
name = pEvent->GetName();
|
|
||||||
|
|
||||||
m_EventNames.push(name);
|
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
|
||||||
|
if (!pEvent)
|
||||||
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
|
|
||||||
{
|
{
|
||||||
|
RETURN_META_VALUE(MRES_IGNORED, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
name = pEvent->GetName();
|
||||||
|
|
||||||
|
if (m_EventHooks.retrieve(name, &pHook))
|
||||||
|
{
|
||||||
|
/* Push the event onto the event stack. The reference count is increased to make sure
|
||||||
|
* the structure is not garbage collected in between now and the post hook.
|
||||||
|
*/
|
||||||
|
pHook->refCount++;
|
||||||
|
m_EventStack.push(pHook);
|
||||||
|
|
||||||
pForward = pHook->pPreHook;
|
pForward = pHook->pPreHook;
|
||||||
|
|
||||||
if (pForward)
|
if (pForward)
|
||||||
{
|
{
|
||||||
EventInfo info = { pEvent, NULL };
|
EventInfo info(pEvent, NULL);
|
||||||
|
HandleSecurity sec(NULL, g_pCoreIdent);
|
||||||
|
Handle_t hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||||
|
|
||||||
|
info.bDontBroadcast = bDontBroadcast;
|
||||||
|
|
||||||
|
EventForwardFilter filter(&info);
|
||||||
|
|
||||||
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
|
||||||
pForward->PushCell(hndl);
|
pForward->PushCell(hndl);
|
||||||
pForward->PushString(name);
|
pForward->PushString(name);
|
||||||
pForward->PushCell(bDontBroadcast);
|
pForward->PushCell(bDontBroadcast);
|
||||||
pForward->Execute(&res, NULL);
|
pForward->Execute(&res, &filter);
|
||||||
|
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
broadcast = info.bDontBroadcast;
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
|
||||||
|
handlesys->FreeHandle(hndl, &sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pHook->postCopy)
|
if (pHook->postCopy)
|
||||||
{
|
{
|
||||||
pHook->pEventCopy = gameevents->DuplicateEvent(pEvent);
|
m_EventCopies.push(gameevents->DuplicateEvent(pEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
@@ -394,6 +429,13 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_EventStack.push(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (broadcast != bDontBroadcast)
|
||||||
|
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast));
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
@@ -401,32 +443,38 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
/* IGameEventManager2::FireEvent post hook */
|
/* IGameEventManager2::FireEvent post hook */
|
||||||
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
||||||
{
|
{
|
||||||
IGameEvent *pEventCopy = NULL;
|
|
||||||
EventHook *pHook;
|
EventHook *pHook;
|
||||||
|
EventInfo info;
|
||||||
IChangeableForward *pForward;
|
IChangeableForward *pForward;
|
||||||
const char *name;
|
|
||||||
Handle_t hndl = 0;
|
Handle_t hndl = 0;
|
||||||
|
|
||||||
name = m_EventNames.front();
|
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
|
||||||
|
if (!pEvent)
|
||||||
|
{
|
||||||
|
RETURN_META_VALUE(MRES_IGNORED, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
|
pHook = m_EventStack.front();
|
||||||
|
|
||||||
|
if (pHook != NULL)
|
||||||
{
|
{
|
||||||
pForward = pHook->pPostHook;
|
pForward = pHook->pPostHook;
|
||||||
|
|
||||||
if (pForward)
|
if (pForward)
|
||||||
{
|
{
|
||||||
EventInfo info = { pHook->pEventCopy, NULL };
|
|
||||||
|
|
||||||
if (pHook->postCopy)
|
if (pHook->postCopy)
|
||||||
{
|
{
|
||||||
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
info.bDontBroadcast = bDontBroadcast;
|
||||||
|
info.pEvent = m_EventCopies.front();
|
||||||
|
info.pOwner = NULL;
|
||||||
|
hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||||
|
|
||||||
pForward->PushCell(hndl);
|
pForward->PushCell(hndl);
|
||||||
} else {
|
} else {
|
||||||
pForward->PushCell(BAD_HANDLE);
|
pForward->PushCell(BAD_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pForward->PushString(name);
|
pForward->PushString(pHook->name.chars());
|
||||||
pForward->PushCell(bDontBroadcast);
|
pForward->PushCell(bDontBroadcast);
|
||||||
pForward->Execute(NULL);
|
pForward->Execute(NULL);
|
||||||
|
|
||||||
@@ -434,16 +482,25 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
|||||||
{
|
{
|
||||||
/* Free handle */
|
/* Free handle */
|
||||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
HandleSecurity sec(NULL, g_pCoreIdent);
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
handlesys->FreeHandle(hndl, &sec);
|
||||||
|
|
||||||
/* Free event structure */
|
/* Free event structure */
|
||||||
gameevents->FreeEvent(pEventCopy);
|
gameevents->FreeEvent(info.pEvent);
|
||||||
pHook->pEventCopy = NULL;
|
m_EventCopies.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Decrement reference count, check if a delayed delete is needed */
|
||||||
|
if (--pHook->refCount == 0)
|
||||||
|
{
|
||||||
|
assert(pHook->pPostHook == NULL);
|
||||||
|
assert(pHook->pPreHook == NULL);
|
||||||
|
m_EventHooks.remove(pHook->name.chars());
|
||||||
|
delete pHook;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_EventNames.pop();
|
m_EventStack.pop();
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-7
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_trie.h"
|
#include <sm_namehashset.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
@@ -45,8 +45,15 @@ using namespace SourceHook;
|
|||||||
|
|
||||||
struct EventInfo
|
struct EventInfo
|
||||||
{
|
{
|
||||||
|
EventInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
EventInfo(IGameEvent *ev, IdentityToken_t *owner) : pEvent(ev), pOwner(owner)
|
||||||
|
{
|
||||||
|
}
|
||||||
IGameEvent *pEvent;
|
IGameEvent *pEvent;
|
||||||
IdentityToken_t *pOwner;
|
IdentityToken_t *pOwner;
|
||||||
|
bool bDontBroadcast;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventHook
|
struct EventHook
|
||||||
@@ -56,14 +63,18 @@ struct EventHook
|
|||||||
pPreHook = NULL;
|
pPreHook = NULL;
|
||||||
pPostHook = NULL;
|
pPostHook = NULL;
|
||||||
postCopy = false;
|
postCopy = false;
|
||||||
pEventCopy = NULL;
|
|
||||||
refCount = 0;
|
refCount = 0;
|
||||||
}
|
}
|
||||||
IChangeableForward *pPreHook;
|
IChangeableForward *pPreHook;
|
||||||
IChangeableForward *pPostHook;
|
IChangeableForward *pPostHook;
|
||||||
bool postCopy;
|
bool postCopy;
|
||||||
IGameEvent *pEventCopy;
|
|
||||||
unsigned int refCount;
|
unsigned int refCount;
|
||||||
|
ke::AString name;
|
||||||
|
|
||||||
|
static inline bool matches(const char *name, const EventHook *hook)
|
||||||
|
{
|
||||||
|
return strcmp(name, hook->name.chars()) == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EventHookMode
|
enum EventHookMode
|
||||||
@@ -99,6 +110,9 @@ public: // IPluginsListener
|
|||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
public: // IGameEventListener2
|
public: // IGameEventListener2
|
||||||
void FireGameEvent(IGameEvent *pEvent);
|
void FireGameEvent(IGameEvent *pEvent);
|
||||||
|
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
|
||||||
|
int GetEventDebugID();
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Get the 'GameEvent' handle type ID.
|
* Get the 'GameEvent' handle type ID.
|
||||||
@@ -118,9 +132,10 @@ private: // IGameEventManager2 hooks
|
|||||||
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
|
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
|
||||||
private:
|
private:
|
||||||
HandleType_t m_EventType;
|
HandleType_t m_EventType;
|
||||||
Trie *m_EventHooks;
|
NameHashSet<EventHook *> m_EventHooks;
|
||||||
CStack<EventInfo *> m_FreeEvents;
|
CStack<EventInfo *> m_FreeEvents;
|
||||||
CStack<const char *> m_EventNames;
|
CStack<EventHook *> m_EventStack;
|
||||||
|
CStack<IGameEvent *> m_EventCopies;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EventManager g_EventManager;
|
extern EventManager g_EventManager;
|
||||||
|
|||||||
+855
-85
File diff suppressed because it is too large
Load Diff
+99
-13
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -35,12 +35,21 @@
|
|||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sh_tinyhash.h>
|
#include <sh_tinyhash.h>
|
||||||
#include <sm_trie_tpl.h>
|
#include <am-utility.h>
|
||||||
#include "sm_trie.h"
|
#include <am-hashmap.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
#include <sm_namehashset.h>
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
#include "sm_queue.h"
|
#include "sm_queue.h"
|
||||||
#include <IGameHelpers.h>
|
#include <IGameHelpers.h>
|
||||||
#include <KeyValues.h>
|
#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;
|
class CCommand;
|
||||||
|
|
||||||
@@ -52,16 +61,38 @@ using namespace SourceMod;
|
|||||||
|
|
||||||
struct DataTableInfo
|
struct DataTableInfo
|
||||||
{
|
{
|
||||||
|
struct SendPropPolicy
|
||||||
|
{
|
||||||
|
static inline bool matches(const char *name, const sm_sendprop_info_t &info)
|
||||||
|
{
|
||||||
|
return strcmp(name, info.prop->GetName()) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool matches(const char *name, const DataTableInfo *info)
|
||||||
|
{
|
||||||
|
return strcmp(name, info->sc->GetName()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTableInfo(ServerClass *sc)
|
||||||
|
: sc(sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ServerClass *sc;
|
ServerClass *sc;
|
||||||
KTrie<sm_sendprop_info_t> lookup;
|
NameHashSet<sm_sendprop_info_t, SendPropPolicy> lookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DataMapTrie
|
struct DataMapCachePolicy
|
||||||
{
|
{
|
||||||
DataMapTrie() : trie(NULL) {}
|
static inline bool matches(const char *name, const sm_datatable_info_t &info)
|
||||||
Trie *trie;
|
{
|
||||||
|
return strcmp(name, info.prop->fieldName) == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
|
||||||
|
|
||||||
struct DelayedFakeCliCmd
|
struct DelayedFakeCliCmd
|
||||||
{
|
{
|
||||||
String cmd;
|
String cmd;
|
||||||
@@ -72,11 +103,32 @@ struct DelayedFakeCliCmd
|
|||||||
struct CachedCommandInfo
|
struct CachedCommandInfo
|
||||||
{
|
{
|
||||||
const CCommand *args;
|
const CCommand *args;
|
||||||
#if !defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||||
char cmd[300];
|
char cmd[300];
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DelayedKickInfo
|
||||||
|
{
|
||||||
|
int userid;
|
||||||
|
int client;
|
||||||
|
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) && (SOURCE_ENGINE != SE_DOTA)
|
||||||
|
string_t m_iName;
|
||||||
|
string_t m_iClassName;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
class CHalfLife2 :
|
class CHalfLife2 :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IGameHelpers
|
public IGameHelpers
|
||||||
@@ -87,6 +139,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
void OnSourceModStartup(bool late);
|
void OnSourceModStartup(bool late);
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
|
void OnSourceModAllInitialized_Post();
|
||||||
/*void OnSourceModAllShutdown();*/
|
/*void OnSourceModAllShutdown();*/
|
||||||
public: //IGameHelpers
|
public: //IGameHelpers
|
||||||
SendProp *FindInSendTable(const char *classname, const char *offset);
|
SendProp *FindInSendTable(const char *classname, const char *offset);
|
||||||
@@ -94,11 +147,33 @@ public: //IGameHelpers
|
|||||||
datamap_t *GetDataMap(CBaseEntity *pEntity);
|
datamap_t *GetDataMap(CBaseEntity *pEntity);
|
||||||
ServerClass *FindServerClass(const char *classname);
|
ServerClass *FindServerClass(const char *classname);
|
||||||
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
|
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
|
||||||
|
bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable);
|
||||||
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
||||||
bool TextMsg(int client, int dest, const char *msg);
|
bool TextMsg(int client, int dest, const char *msg);
|
||||||
bool HintTextMsg(int client, 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 ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
||||||
bool IsLANServer();
|
bool IsLANServer();
|
||||||
|
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||||
|
edict_t *EdictOfIndex(int index);
|
||||||
|
int IndexOfEdict(edict_t *pEnt);
|
||||||
|
edict_t *GetHandleEntity(CBaseHandle &hndl);
|
||||||
|
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:
|
public:
|
||||||
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
||||||
void ProcessFakeCliCmdQueue();
|
void ProcessFakeCliCmdQueue();
|
||||||
@@ -107,23 +182,34 @@ public:
|
|||||||
void PopCommandStack();
|
void PopCommandStack();
|
||||||
const CCommand *PeekCommandStack();
|
const CCommand *PeekCommandStack();
|
||||||
const char *CurrentCommandName();
|
const char *CurrentCommandName();
|
||||||
#if !defined METAMOD_PLAPI_VERSION
|
void AddDelayedKick(int client, int userid, const char *msg);
|
||||||
|
void ProcessDelayedKicks();
|
||||||
|
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||||
bool IsOriginalEngine();
|
bool IsOriginalEngine();
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
DataTableInfo *_FindServerClass(const char *classname);
|
DataTableInfo *_FindServerClass(const char *classname);
|
||||||
private:
|
private:
|
||||||
Trie *m_pClasses;
|
void InitLogicalEntData();
|
||||||
List<DataTableInfo *> m_Tables;
|
void InitCommandLine();
|
||||||
THash<datamap_t *, DataMapTrie> m_Maps;
|
private:
|
||||||
|
typedef ke::HashMap<datamap_t *, DataMapCache *, ke::PointerPolicy<datamap_t> > DataTableMap;
|
||||||
|
|
||||||
|
NameHashSet<DataTableInfo *> m_Classes;
|
||||||
|
DataTableMap m_Maps;
|
||||||
int m_MsgTextMsg;
|
int m_MsgTextMsg;
|
||||||
int m_HinTextMsg;
|
int m_HinTextMsg;
|
||||||
|
int m_SayTextMsg;
|
||||||
int m_VGUIMenu;
|
int m_VGUIMenu;
|
||||||
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
||||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||||
CStack<CachedCommandInfo> m_CommandStack;
|
CStack<CachedCommandInfo> m_CommandStack;
|
||||||
|
Queue<DelayedKickInfo> m_DelayedKicks;
|
||||||
|
void *m_pGetCommandLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CHalfLife2 g_HL2;
|
extern CHalfLife2 g_HL2;
|
||||||
|
|
||||||
|
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -138,7 +138,7 @@ bool CDirectory::IsEntryDirectory()
|
|||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_POSIX
|
||||||
char temppath[PLATFORM_MAX_PATH];
|
char temppath[PLATFORM_MAX_PATH];
|
||||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||||
return g_LibSys.IsPathDirectory(temppath);
|
return g_LibSys.IsPathDirectory(temppath);
|
||||||
@@ -160,7 +160,7 @@ const char *CDirectory::GetEntryName()
|
|||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
return m_fd.cFileName;
|
return m_fd.cFileName;
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_POSIX
|
||||||
return ep ? ep->d_name : "";
|
return ep ? ep->d_name : "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ bool CDirectory::IsValid()
|
|||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
return (m_dir != INVALID_HANDLE_VALUE);
|
return (m_dir != INVALID_HANDLE_VALUE);
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_POSIX
|
||||||
return (m_dir != NULL);
|
return (m_dir != NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ bool LibrarySystem::IsPathFile(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_POSIX
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
if (stat(path, &s) != 0)
|
if (stat(path, &s) != 0)
|
||||||
@@ -241,7 +241,7 @@ bool LibrarySystem::IsPathDirectory(const char *path)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined PLATFORM_LINUX
|
#elif defined PLATFORM_POSIX
|
||||||
struct stat s;
|
struct stat s;
|
||||||
|
|
||||||
if (stat(path, &s) != 0)
|
if (stat(path, &s) != 0)
|
||||||
@@ -272,25 +272,53 @@ IDirectory *LibrarySystem::OpenDirectory(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LibrarySystem::GetPlatformError(char *error, size_t maxlength)
|
void LibrarySystem::GetPlatformError(char *error, size_t maxlength)
|
||||||
|
{
|
||||||
|
#if defined PLATFORM_WINDOWS
|
||||||
|
return GetPlatformErrorEx(GetLastError(), error, maxlength);
|
||||||
|
#elif defined PLATFORM_POSIX
|
||||||
|
return GetPlatformErrorEx(errno, error, maxlength);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
if (error && maxlength)
|
if (error && maxlength)
|
||||||
{
|
{
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
DWORD dw = GetLastError();
|
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
FormatMessageA(
|
NULL,
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
(DWORD)code,
|
||||||
NULL,
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
dw,
|
(LPSTR)error,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
maxlength,
|
||||||
(LPSTR)error,
|
NULL) == 0)
|
||||||
maxlength,
|
{
|
||||||
NULL);
|
UTIL_Format(error, maxlength, "error code %08x", code);
|
||||||
|
}
|
||||||
|
#elif defined PLATFORM_LINUX
|
||||||
|
const char *ae = strerror_r(code, error, maxlength);
|
||||||
|
if (ae != error)
|
||||||
|
{
|
||||||
|
UTIL_Format(error, maxlength, "%s", ae);
|
||||||
|
}
|
||||||
#elif defined PLATFORM_POSIX
|
#elif defined PLATFORM_POSIX
|
||||||
snprintf(error, maxlength, "%s", strerror(errno));
|
strerror_r(code, error, maxlength);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibrarySystem::GetLoaderError(char *buffer, size_t maxlength)
|
||||||
|
{
|
||||||
|
#if defined PLATFORM_WINDOWS
|
||||||
|
GetPlatformError(buffer, maxlength);
|
||||||
|
#elif defined PLATFORM_POSIX
|
||||||
|
if (buffer != NULL && maxlength)
|
||||||
|
{
|
||||||
|
strncopy(buffer, dlerror(), maxlength);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void LibrarySystem::CloseDirectory(IDirectory *dir)
|
void LibrarySystem::CloseDirectory(IDirectory *dir)
|
||||||
{
|
{
|
||||||
delete dir;
|
delete dir;
|
||||||
@@ -301,20 +329,16 @@ ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxle
|
|||||||
LibraryHandle lib;
|
LibraryHandle lib;
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
lib = LoadLibraryA(path);
|
lib = LoadLibraryA(path);
|
||||||
if (!lib)
|
|
||||||
{
|
|
||||||
GetPlatformError(error, maxlength);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#elif defined PLATFORM_POSIX
|
#elif defined PLATFORM_POSIX
|
||||||
lib = dlopen(path, RTLD_NOW);
|
lib = dlopen(path, RTLD_NOW);
|
||||||
if (!lib)
|
|
||||||
{
|
|
||||||
GetPlatformError(error, maxlength);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (lib == NULL)
|
||||||
|
{
|
||||||
|
GetLoaderError(error, maxlength);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return new CLibrary(lib);
|
return new CLibrary(lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,21 +368,26 @@ size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
|
|||||||
|
|
||||||
const char *LibrarySystem::GetFileExtension(const char *filename)
|
const char *LibrarySystem::GetFileExtension(const char *filename)
|
||||||
{
|
{
|
||||||
size_t end = strlen(filename) - 1;
|
size_t len, end;
|
||||||
|
|
||||||
for (size_t i = end; i >= 0; i--)
|
len = strlen(filename);
|
||||||
|
|
||||||
|
/* Minimum string length for filename with ext would be 3; example: a.a */
|
||||||
|
if (len < 3)
|
||||||
{
|
{
|
||||||
if (i > end)
|
return NULL;
|
||||||
{
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
end = len - 1;
|
||||||
|
|
||||||
|
for (size_t i = end; i <= end; i--)
|
||||||
|
{
|
||||||
if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
|
if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename[i] == '.' && i != end)
|
if (filename[i] == '.' && i != end && i != 0)
|
||||||
{
|
{
|
||||||
return &filename[++i];
|
return &filename[++i];
|
||||||
}
|
}
|
||||||
@@ -381,7 +410,7 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
|
|||||||
size_t length = strlen(path);
|
size_t length = strlen(path);
|
||||||
|
|
||||||
for (size_t i = length - 1;
|
for (size_t i = length - 1;
|
||||||
i >= 0 && i <= length - 1;
|
i <= length - 1;
|
||||||
i--)
|
i--)
|
||||||
{
|
{
|
||||||
if (path[i] == '/'
|
if (path[i] == '/'
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -90,11 +90,13 @@ public:
|
|||||||
bool IsPathFile(const char *path);
|
bool IsPathFile(const char *path);
|
||||||
bool IsPathDirectory(const char *path);
|
bool IsPathDirectory(const char *path);
|
||||||
void GetPlatformError(char *error, size_t maxlength);
|
void GetPlatformError(char *error, size_t maxlength);
|
||||||
|
void GetPlatformErrorEx(int code, char *error, size_t maxlength);
|
||||||
size_t PathFormat(char *buffer, size_t len, const char *fmt, ...);
|
size_t PathFormat(char *buffer, size_t len, const char *fmt, ...);
|
||||||
const char *GetFileExtension(const char *filename);
|
const char *GetFileExtension(const char *filename);
|
||||||
bool CreateFolder(const char *path);
|
bool CreateFolder(const char *path);
|
||||||
size_t GetFileFromPath(char *buffer, size_t maxlength, const char *path);
|
size_t GetFileFromPath(char *buffer, size_t maxlength, const char *path);
|
||||||
bool FileTime(const char *path, FileTimeType type, time_t *pTime);
|
bool FileTime(const char *path, FileTimeType type, time_t *pTime);
|
||||||
|
void GetLoaderError(char *buffer, size_t maxlength);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern LibrarySystem g_LibSys;
|
extern LibrarySystem g_LibSys;
|
||||||
+92
-24
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,12 +34,15 @@
|
|||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "systems/LibrarySys.h"
|
#include "LibrarySys.h"
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "sm_version.h"
|
#include "logic_bridge.h"
|
||||||
|
#include <sourcemod_version.h>
|
||||||
|
|
||||||
Logger g_Logger;
|
Logger g_Logger;
|
||||||
|
|
||||||
|
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* :TODO: This should be creating the log folder if it doesn't exist
|
* :TODO: This should be creating the log folder if it doesn't exist
|
||||||
*/
|
*/
|
||||||
@@ -91,14 +94,27 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
|||||||
return ConfigResult_Ignore;
|
return ConfigResult_Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void HookLogPrint(const char *message)
|
||||||
|
{
|
||||||
|
g_in_game_log_hook = true;
|
||||||
|
bool stopped = logicore.OnLogPrint(message);
|
||||||
|
g_in_game_log_hook = false;
|
||||||
|
|
||||||
|
if (stopped)
|
||||||
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::OnSourceModStartup(bool late)
|
void Logger::OnSourceModStartup(bool late)
|
||||||
{
|
{
|
||||||
InitLogger(m_Mode);
|
InitLogger(m_Mode);
|
||||||
|
|
||||||
|
SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::OnSourceModAllShutdown()
|
void Logger::OnSourceModAllShutdown()
|
||||||
{
|
{
|
||||||
CloseLogger();
|
CloseLogger();
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::OnSourceModLevelChange(const char *mapName)
|
void Logger::OnSourceModLevelChange(const char *mapName)
|
||||||
@@ -149,7 +165,7 @@ void Logger::_NewMapFile()
|
|||||||
} else {
|
} else {
|
||||||
char date[32];
|
char date[32];
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
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, SOURCEMOD_VERSION);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +212,8 @@ void Logger::InitLogger(LoggingMode mode)
|
|||||||
time_t t;
|
time_t t;
|
||||||
GetAdjustedTime(&t);
|
GetAdjustedTime(&t);
|
||||||
tm *curtime = localtime(&t);
|
tm *curtime = localtime(&t);
|
||||||
m_CurDay = curtime->tm_mday;
|
m_NrmCurDay = curtime->tm_mday;
|
||||||
|
m_ErrCurDay = curtime->tm_mday;
|
||||||
|
|
||||||
char _filename[256];
|
char _filename[256];
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||||
@@ -245,6 +262,19 @@ void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
|
||||||
|
{
|
||||||
|
if (!m_Active)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
|
LogToFileOnlyEx(fp, msg, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||||
{
|
{
|
||||||
if (!m_Active)
|
if (!m_Active)
|
||||||
@@ -252,6 +282,32 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
|
||||||
|
|
||||||
|
char buffer[3072];
|
||||||
|
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||||
|
|
||||||
|
char date[32];
|
||||||
|
time_t t;
|
||||||
|
GetAdjustedTime(&t);
|
||||||
|
tm *curtime = localtime(&t);
|
||||||
|
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||||
|
|
||||||
|
fprintf(fp, "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)
|
||||||
|
{
|
||||||
|
if (!m_Active)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char buffer[3072];
|
char buffer[3072];
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||||
|
|
||||||
@@ -262,10 +318,18 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
|||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||||
|
|
||||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||||
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
|
fflush(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::LogMessage(const char *vafmt, ...)
|
void Logger::LogMessage(const char *vafmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, vafmt);
|
||||||
|
LogMessageEx(vafmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
||||||
{
|
{
|
||||||
if (!m_Active)
|
if (!m_Active)
|
||||||
{
|
{
|
||||||
@@ -274,10 +338,7 @@ void Logger::LogMessage(const char *vafmt, ...)
|
|||||||
|
|
||||||
if (m_Mode == LoggingMode_Game)
|
if (m_Mode == LoggingMode_Game)
|
||||||
{
|
{
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
_PrintToGameLog(vafmt, ap);
|
_PrintToGameLog(vafmt, ap);
|
||||||
va_end(ap);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,12 +366,12 @@ void Logger::LogMessage(const char *vafmt, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (m_CurDay != curtime->tm_mday)
|
if (m_NrmCurDay != curtime->tm_mday)
|
||||||
{
|
{
|
||||||
char _filename[256];
|
char _filename[256];
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||||
m_NrmFileName.assign(_filename);
|
m_NrmFileName.assign(_filename);
|
||||||
m_CurDay = curtime->tm_mday;
|
m_NrmCurDay = curtime->tm_mday;
|
||||||
m_DailyPrintHdr = true;
|
m_DailyPrintHdr = true;
|
||||||
}
|
}
|
||||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||||
@@ -323,12 +384,9 @@ void Logger::LogMessage(const char *vafmt, ...)
|
|||||||
char date[32];
|
char date[32];
|
||||||
m_DailyPrintHdr = false;
|
m_DailyPrintHdr = false;
|
||||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
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, SOURCEMOD_VERSION);
|
||||||
}
|
}
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
LogToOpenFileEx(fp, vafmt, ap);
|
||||||
va_end(ap);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
} else {
|
} else {
|
||||||
goto print_error;
|
goto print_error;
|
||||||
@@ -345,6 +403,14 @@ print_error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Logger::LogError(const char *vafmt, ...)
|
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)
|
if (!m_Active)
|
||||||
{
|
{
|
||||||
@@ -355,12 +421,12 @@ void Logger::LogError(const char *vafmt, ...)
|
|||||||
GetAdjustedTime(&t);
|
GetAdjustedTime(&t);
|
||||||
tm *curtime = localtime(&t);
|
tm *curtime = localtime(&t);
|
||||||
|
|
||||||
if (curtime->tm_mday != m_CurDay)
|
if (curtime->tm_mday != m_ErrCurDay)
|
||||||
{
|
{
|
||||||
char _filename[256];
|
char _filename[256];
|
||||||
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||||
m_ErrFileName.assign(_filename);
|
m_ErrFileName.assign(_filename);
|
||||||
m_CurDay = curtime->tm_mday;
|
m_ErrCurDay = curtime->tm_mday;
|
||||||
m_ErrMapStart = false;
|
m_ErrMapStart = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,10 +441,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);
|
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;
|
m_ErrMapStart = true;
|
||||||
}
|
}
|
||||||
va_list ap;
|
|
||||||
va_start(ap, vafmt);
|
|
||||||
LogToOpenFileEx(fp, vafmt, ap);
|
LogToOpenFileEx(fp, vafmt, ap);
|
||||||
va_end(ap);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -482,13 +545,20 @@ void Logger::DisableLogging()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Logger::LogFatal(const char *msg, ...)
|
void Logger::LogFatal(const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
|
LogFatalEx(msg, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::LogFatalEx(const char *msg, va_list ap)
|
||||||
{
|
{
|
||||||
/* :TODO: make this print all pretty-like
|
/* :TODO: make this print all pretty-like
|
||||||
* In fact, the pretty log printing function should be abstracted.
|
* In fact, the pretty log printing function should be abstracted.
|
||||||
* It's already implemented twice which is bad.
|
* It's already implemented twice which is bad.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
char path[PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
||||||
@@ -497,9 +567,7 @@ void Logger::LogFatal(const char *msg, ...)
|
|||||||
if (fp)
|
if (fp)
|
||||||
{
|
{
|
||||||
m_Active = true;
|
m_Active = true;
|
||||||
va_start(ap, msg);
|
|
||||||
LogToOpenFileEx(fp, msg, ap);
|
LogToOpenFileEx(fp, msg, ap);
|
||||||
va_end(ap);
|
|
||||||
m_Active = false;
|
m_Active = false;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -74,10 +74,16 @@ public:
|
|||||||
void EnableLogging();
|
void EnableLogging();
|
||||||
void DisableLogging();
|
void DisableLogging();
|
||||||
void LogMessage(const char *msg, ...);
|
void LogMessage(const char *msg, ...);
|
||||||
|
void LogMessageEx(const char *msg, va_list ap);
|
||||||
void LogError(const char *msg, ...);
|
void LogError(const char *msg, ...);
|
||||||
|
void LogErrorEx(const char *msg, va_list ap);
|
||||||
void LogFatal(const char *msg, ...);
|
void LogFatal(const char *msg, ...);
|
||||||
|
void LogFatalEx(const char *msg, va_list ap);
|
||||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
||||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
||||||
|
/* This version does not print to console, and is thus thread-safe */
|
||||||
|
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
||||||
|
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
||||||
void MapChange(const char *mapname);
|
void MapChange(const char *mapname);
|
||||||
const char *GetLogFileName(LogType type) const;
|
const char *GetLogFileName(LogType type) const;
|
||||||
LoggingMode GetLoggingMode() const;
|
LoggingMode GetLoggingMode() const;
|
||||||
@@ -90,7 +96,8 @@ private:
|
|||||||
String m_ErrFileName;
|
String m_ErrFileName;
|
||||||
String m_CurMapName;
|
String m_CurMapName;
|
||||||
LoggingMode m_Mode;
|
LoggingMode m_Mode;
|
||||||
int m_CurDay;
|
int m_NrmCurDay;
|
||||||
|
int m_ErrCurDay;
|
||||||
bool m_ErrMapStart;
|
bool m_ErrMapStart;
|
||||||
bool m_Active;
|
bool m_Active;
|
||||||
bool m_DelayedStart;
|
bool m_DelayedStart;
|
||||||
|
|||||||
+171
-88
@@ -1,133 +1,216 @@
|
|||||||
#(C)2004-2008 Metamod:Source Development Team
|
# (C)2004-2008 SourceMod Development Team
|
||||||
# Makefile written by David "BAILOPAN" Anderson
|
# Makefile written by David "BAILOPAN" Anderson
|
||||||
|
|
||||||
#Local paths
|
SMSDK = ..
|
||||||
HL2SDK_ORIG = ../../hl2sdk
|
HL2SDK_ORIG = ../../hl2sdk
|
||||||
HL2SDK_OB = ../../hl2sdk-ob
|
HL2SDK_OB = ../../hl2sdk-ob
|
||||||
SOURCEMM14 = ../../sourcemm-1.4
|
HL2SDK_CSS = ../../hl2sdk-css
|
||||||
SOURCEMM16 = ../../sourcemm-1.6
|
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve
|
||||||
SRCDS_BASE = ~/srcds
|
HL2SDK_L4D = ../../hl2sdk-l4d
|
||||||
SMSDK = ..
|
HL2SDK_L4D2 = ../../hl2sdk-l4d2
|
||||||
|
HL2SDK_CSGO = ../../hl2sdk-csgo
|
||||||
#Project options
|
MMSOURCE = ../../mmsource-central
|
||||||
OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing
|
|
||||||
GCC4_FLAGS = -fvisibility=hidden
|
|
||||||
GCC4_CPP_FLAGS = -fvisibility-inlines-hidden
|
|
||||||
DEBUG_FLAGS = -g -ggdb3
|
|
||||||
CPP = gcc-4.1
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||||
|
#####################################
|
||||||
|
|
||||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
||||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
Database.cpp DebugReporter.cpp EventManager.cpp HalfLife2.cpp Logger.cpp \
|
||||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
PlayerManager.cpp TimerSys.cpp UserMessages.cpp \
|
||||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.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 \
|
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 \
|
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp \
|
||||||
frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp
|
frame_hooks.cpp concmd_cleaner.cpp NextMap.cpp \
|
||||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp
|
||||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
OBJECTS += smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
||||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
smn_database.cpp smn_entities.cpp smn_events.cpp \
|
||||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp smn_maplists.cpp \
|
smn_fakenatives.cpp smn_filesystem.cpp smn_halflife.cpp \
|
||||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
smn_keyvalues.cpp smn_player.cpp \
|
||||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp \
|
smn_usermsgs.cpp smn_menus.cpp smn_vector.cpp \
|
||||||
smn_adt_trie.cpp smn_hudtext.cpp
|
smn_hudtext.cpp smn_nextmap.cpp
|
||||||
OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
|
OBJECTS += ExtensionSys.cpp \
|
||||||
systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
|
ForwardSys.cpp \
|
||||||
systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_function.cpp
|
HandleSys.cpp \
|
||||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
LibrarySys.cpp \
|
||||||
OBJECTS_C = zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
|
PluginInfoDatabase.cpp \
|
||||||
zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
|
PluginSys.cpp \
|
||||||
zlib/uncompr.c zlib/zutil.c
|
ShareSys.cpp \
|
||||||
OBJECTS_SM16 = vm/sp_vm_engine.cpp
|
NativeInvoker.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
|
||||||
|
|
||||||
|
override ENGSET = false
|
||||||
|
|
||||||
|
ifneq (,$(filter original orangebox css orangeboxvalve left4dead left4dead2 csgo,$(ENGINE)))
|
||||||
|
override ENGSET = true
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq "$(ENGINE)" "original"
|
ifeq "$(ENGINE)" "original"
|
||||||
HL2SDK = $(HL2SDK_ORIG)
|
HL2SDK = $(HL2SDK_ORIG)
|
||||||
HL2PUB = $(HL2SDK_ORIG)/public
|
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
HL2LIB = $(HL2SDK)/linux_sdk
|
||||||
METAMOD = $(SOURCEMM14)
|
CFLAGS += -DSOURCE_ENGINE=1
|
||||||
INCLUDE += -I$(HL2PUB)/dlls
|
METAMOD = $(MMSOURCE)/core-legacy
|
||||||
SRCDS = $(SRCDS_BASE)
|
INCLUDE += -I$(HL2SDK)/public/dlls
|
||||||
BINARY = sourcemod.1.ep1.so
|
BINARY = sourcemod.1.ep1.so
|
||||||
endif
|
endif
|
||||||
ifeq "$(ENGINE)" "orangebox"
|
ifeq "$(ENGINE)" "orangebox"
|
||||||
HL2SDK = $(HL2SDK_OB)
|
HL2SDK = $(HL2SDK_OB)
|
||||||
HL2PUB = $(HL2SDK_OB)/public
|
HL2LIB = $(HL2SDK)/lib/linux
|
||||||
HL2LIB = $(HL2SDK)/linux_sdk
|
CFLAGS += -DSOURCE_ENGINE=3
|
||||||
CFLAGS += -DORANGEBOX_BUILD
|
METAMOD = $(MMSOURCE)/core
|
||||||
METAMOD = $(SOURCEMM16)
|
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||||
INCLUDE += -I$(HL2PUB)/game/server
|
|
||||||
SRCDS = $(SRCDS_BASE)/orangebox
|
|
||||||
BINARY = sourcemod.2.ep2.so
|
BINARY = sourcemod.2.ep2.so
|
||||||
endif
|
endif
|
||||||
ifeq "$(BINARY)" ""
|
ifeq "$(ENGINE)" "css"
|
||||||
echo "You must supply ENGINE=orangebox or ENGINE=original"
|
HL2SDK = $(HL2SDK_CSS)
|
||||||
false
|
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)
|
||||||
|
HL2LIB = $(HL2SDK)/lib/linux
|
||||||
|
CFLAGS += -DSOURCE_ENGINE=8
|
||||||
|
METAMOD = $(MMSOURCE)/core
|
||||||
|
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||||
|
BINARY = sourcemod.2.l4d.so
|
||||||
|
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
|
endif
|
||||||
|
|
||||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so \
|
HL2PUB = $(HL2SDK)/public
|
||||||
tier0_i486.so -lpthread -static-libgcc
|
|
||||||
|
|
||||||
INCLUDE_SMSDK = -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions
|
OS := $(shell uname -s)
|
||||||
|
|
||||||
INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \
|
ifeq "$(OS)" "Darwin"
|
||||||
-I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook -I$(METAMOD)/sourcemm \
|
LIB_EXT = dylib
|
||||||
-I$(HL2PUB)/mathlib -Isystems $(INCLUDE_SMSDK)
|
HL2LIB = $(HL2SDK)/lib/mac
|
||||||
|
else
|
||||||
|
LIB_EXT = so
|
||||||
|
ifeq "$(ENGINE)" "original"
|
||||||
|
HL2LIB = $(HL2SDK)/linux_sdk
|
||||||
|
else
|
||||||
|
HL2LIB = $(HL2SDK)/lib/linux
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
SM16_INCLUDE = -I. -I.. -I$(SOURCEMM16)/sourcehook $(INCLUDE_SMSDK)
|
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 -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 -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 ###
|
||||||
|
################################################
|
||||||
|
|
||||||
ifeq "$(DEBUG)" "true"
|
ifeq "$(DEBUG)" "true"
|
||||||
BIN_DIR = Debug.$(ENGINE)
|
BIN_DIR = Debug.$(ENGINE)
|
||||||
CFLAGS += $(DEBUG_FLAGS)
|
CFLAGS += $(C_DEBUG_FLAGS)
|
||||||
else
|
else
|
||||||
BIN_DIR = Release.$(ENGINE)
|
BIN_DIR = Release.$(ENGINE)
|
||||||
CFLAGS += $(OPT_FLAGS)
|
CFLAGS += $(C_OPT_FLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
|
||||||
|
|
||||||
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \
|
|
||||||
-Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \
|
|
||||||
-Dstrcmpi=strcasecmp -Wall -Wno-uninitialized -Werror -mfpmath=sse -msse \
|
|
||||||
-DSOURCEMOD_BUILD -DSM_DEFAULT_THREADER -m32
|
|
||||||
CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
ifeq "$(GCC_VERSION)" "4"
|
ifeq "$(GCC_VERSION)" "4"
|
||||||
CFLAGS += $(GCC4_FLAGS)
|
CFLAGS += $(C_GCC4_FLAGS)
|
||||||
CPPFLAGS += $(GCC4_CPP_FLAGS)
|
CPPFLAGS += $(CPP_GCC4_FLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.ox)
|
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
|
||||||
OBJ_LINUX_C := $(OBJECTS_C:%.c=$(BIN_DIR)/%.oc)
|
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
||||||
OBJ_LINUX_SM16 := $(OBJECTS_SM16:%.cpp=$(BIN_DIR)/%.ok)
|
|
||||||
|
|
||||||
$(BIN_DIR)/%.ox: %.cpp
|
$(BIN_DIR)/%.o: %.cpp
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(BIN_DIR)/%.oc: %.c
|
$(BIN_DIR)/%.o: %.c
|
||||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(BIN_DIR)/%.ok: %.cpp
|
all: check
|
||||||
$(CPP) $(SM16_INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
mkdir -p $(BIN_DIR)
|
||||||
|
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX)
|
||||||
all:
|
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX)
|
||||||
mkdir -p $(BIN_DIR)/systems
|
|
||||||
mkdir -p $(BIN_DIR)/vm
|
|
||||||
mkdir -p $(BIN_DIR)/zlib
|
|
||||||
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
|
|
||||||
$(MAKE) -f Makefile sourcemod
|
$(MAKE) -f Makefile sourcemod
|
||||||
|
|
||||||
sourcemod: $(OBJ_LINUX) $(OBJ_LINUX_C) $(OBJ_LINUX_SM16)
|
check:
|
||||||
$(CPP) $(OBJ_LINUX) $(OBJ_LINUX_C) $(OBJ_LINUX_SM16) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
if [ "$(ENGSET)" = "false" ]; then \
|
||||||
|
echo "You must supply one of the following values for ENGINE:"; \
|
||||||
|
echo "csgo, left4dead2, left4dead, orangeboxvalve, css, orangebox, or original"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
sourcemod: check $(OBJ_LINUX)
|
||||||
|
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
|
||||||
|
|
||||||
|
debug:
|
||||||
|
$(MAKE) -f Makefile all DEBUG=true
|
||||||
|
|
||||||
default: all
|
default: all
|
||||||
|
|
||||||
clean:
|
clean: check
|
||||||
rm -rf $(BIN_DIR)/*.ox
|
rm -rf $(BIN_DIR)/*.o
|
||||||
rm -rf $(BIN_DIR)/systems/*.ox
|
|
||||||
rm -rf $(BIN_DIR)/zlib/*.oc
|
|
||||||
rm -rf $(BIN_DIR)/vm/*.ox
|
|
||||||
rm -rf $(BIN_DIR)/thread/*.ox
|
|
||||||
rm -rf $(BIN_DIR)/$(BINARY)
|
rm -rf $(BIN_DIR)/$(BINARY)
|
||||||
|
|
||||||
|
|||||||
@@ -1,220 +0,0 @@
|
|||||||
/**
|
|
||||||
* vim: set ts=4 :
|
|
||||||
* =============================================================================
|
|
||||||
* SourceMod
|
|
||||||
* Copyright (C) 2004-2007 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;
|
|
||||||
}
|
|
||||||
+64
-17
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -38,9 +38,8 @@
|
|||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
MenuManager g_Menus;
|
MenuManager g_Menus;
|
||||||
VoteMenuHandler s_VoteHandler;
|
VoteMenuHandler s_VoteHandler;
|
||||||
@@ -55,24 +54,24 @@ MenuManager::MenuManager()
|
|||||||
|
|
||||||
void MenuManager::OnSourceModAllInitialized()
|
void MenuManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
|
|
||||||
HandleAccess access;
|
HandleAccess access;
|
||||||
g_HandleSys.InitAccessDefaults(NULL, &access);
|
handlesys->InitAccessDefaults(NULL, &access);
|
||||||
|
|
||||||
/* Deny cloning to menus */
|
/* Deny cloning to menus */
|
||||||
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
||||||
m_MenuType = g_HandleSys.CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
m_MenuType = handlesys->CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
||||||
|
|
||||||
/* Also deny deletion to styles */
|
/* Also deny deletion to styles */
|
||||||
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
|
||||||
m_StyleType = g_HandleSys.CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
m_StyleType = handlesys->CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuManager::OnSourceModAllShutdown()
|
void MenuManager::OnSourceModAllShutdown()
|
||||||
{
|
{
|
||||||
g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
|
handlesys->RemoveType(m_MenuType, g_pCoreIdent);
|
||||||
g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
|
handlesys->RemoveType(m_StyleType, g_pCoreIdent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
|
void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||||
@@ -111,7 +110,7 @@ Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
|
|||||||
return BAD_HANDLE;
|
return BAD_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
|
return handlesys->CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
||||||
@@ -121,7 +120,7 @@ Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
|
|||||||
return BAD_HANDLE;
|
return BAD_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_HandleSys.CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
|
return handlesys->CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
||||||
@@ -131,7 +130,7 @@ HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
|
|||||||
sec.pIdentity = g_pCoreIdent;
|
sec.pIdentity = g_pCoreIdent;
|
||||||
sec.pOwner = NULL;
|
sec.pOwner = NULL;
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(handle, m_MenuType, &sec, (void **)menu);
|
return handlesys->ReadHandle(handle, m_MenuType, &sec, (void **)menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
||||||
@@ -141,7 +140,7 @@ HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
|
|||||||
sec.pIdentity = g_pCoreIdent;
|
sec.pIdentity = g_pCoreIdent;
|
||||||
sec.pOwner = g_pCoreIdent;
|
sec.pOwner = g_pCoreIdent;
|
||||||
|
|
||||||
return g_HandleSys.ReadHandle(handle, m_StyleType, &sec, (void **)style);
|
return handlesys->ReadHandle(handle, m_StyleType, &sec, (void **)style);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuManager::SetDefaultStyle(IMenuStyle *style)
|
bool MenuManager::SetDefaultStyle(IMenuStyle *style)
|
||||||
@@ -230,6 +229,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
unsigned int pgn = menu->GetPagination();
|
unsigned int pgn = menu->GetPagination();
|
||||||
unsigned int maxItems = style->GetMaxPageItems();
|
unsigned int maxItems = style->GetMaxPageItems();
|
||||||
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
|
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)
|
if (pgn != MENU_NO_PAGINATION)
|
||||||
{
|
{
|
||||||
@@ -240,6 +240,11 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
|
|||||||
maxItems--;
|
maxItems--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (novoteButton)
|
||||||
|
{
|
||||||
|
maxItems--;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is very not allowed! */
|
/* This is very not allowed! */
|
||||||
if (maxItems < 2)
|
if (maxItems < 2)
|
||||||
{
|
{
|
||||||
@@ -435,6 +440,20 @@ skip_search:
|
|||||||
/* Draw the item according to the order */
|
/* Draw the item according to the order */
|
||||||
menu_slots_t *slots = md.slots;
|
menu_slots_t *slots = md.slots;
|
||||||
unsigned int position = 0; /* Keep track of the last position */
|
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)
|
if (order == ItemOrder_Ascending)
|
||||||
{
|
{
|
||||||
md.item_on_page = drawItems[0].position;
|
md.item_on_page = drawItems[0].position;
|
||||||
@@ -585,14 +604,20 @@ skip_search:
|
|||||||
{
|
{
|
||||||
if (exitBackButton)
|
if (exitBackButton)
|
||||||
{
|
{
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Back", NULL);
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
|
||||||
|
{
|
||||||
|
UTIL_Format(text, sizeof(text), "Back");
|
||||||
|
}
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
dr.style = ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
slots[position].type = ItemSel_ExitBack;
|
slots[position].type = ItemSel_ExitBack;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Previous", NULL);
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
|
||||||
|
{
|
||||||
|
UTIL_Format(text, sizeof(text), "Previous");
|
||||||
|
}
|
||||||
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
slots[position].type = ItemSel_Back;
|
slots[position].type = ItemSel_Back;
|
||||||
@@ -610,7 +635,10 @@ skip_search:
|
|||||||
/* NEXT */
|
/* NEXT */
|
||||||
if (displayNext || canDrawDisabled)
|
if (displayNext || canDrawDisabled)
|
||||||
{
|
{
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Next", NULL);
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
|
||||||
|
{
|
||||||
|
UTIL_Format(text, sizeof(text), "Next");
|
||||||
|
}
|
||||||
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
slots[position].type = ItemSel_Next;
|
slots[position].type = ItemSel_Next;
|
||||||
@@ -638,7 +666,10 @@ skip_search:
|
|||||||
/* EXIT */
|
/* EXIT */
|
||||||
if (exitButton)
|
if (exitButton)
|
||||||
{
|
{
|
||||||
CorePlayerTranslate(client, text, sizeof(text), "Exit", NULL);
|
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
|
||||||
|
{
|
||||||
|
UTIL_Format(text, sizeof(text), "Exit");
|
||||||
|
}
|
||||||
dr.style = ITEMDRAW_CONTROL;
|
dr.style = ITEMDRAW_CONTROL;
|
||||||
position = panel->DrawItem(dr);
|
position = panel->DrawItem(dr);
|
||||||
slots[position].type = ItemSel_Exit;
|
slots[position].type = ItemSel_Exit;
|
||||||
@@ -777,3 +808,19 @@ unsigned int MenuManager::GetRemainingVoteDelay()
|
|||||||
{
|
{
|
||||||
return s_VoteHandler.GetRemainingVoteDelay();
|
return s_VoteHandler.GetRemainingVoteDelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MenuManager::IsClientInVotePool(int client)
|
||||||
|
{
|
||||||
|
return s_VoteHandler.IsClientInVotePool(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MenuManager::RedrawClientVoteMenu(int client)
|
||||||
|
{
|
||||||
|
return RedrawClientVoteMenu2(client, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MenuManager::RedrawClientVoteMenu2(int client, bool revote)
|
||||||
|
{
|
||||||
|
return s_VoteHandler.RedrawToClient(client, revote);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -37,7 +37,6 @@
|
|||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -89,6 +88,9 @@ public:
|
|||||||
bool IsVoteInProgress();
|
bool IsVoteInProgress();
|
||||||
void CancelVoting();
|
void CancelVoting();
|
||||||
unsigned int GetRemainingVoteDelay();
|
unsigned int GetRemainingVoteDelay();
|
||||||
|
bool IsClientInVotePool(int client);
|
||||||
|
bool RedrawClientVoteMenu(int client);
|
||||||
|
bool RedrawClientVoteMenu2(int client, bool revote);
|
||||||
public: //IHandleTypeDispatch
|
public: //IHandleTypeDispatch
|
||||||
void OnHandleDestroy(HandleType_t type, void *object);
|
void OnHandleDestroy(HandleType_t type, void *object);
|
||||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
||||||
|
|||||||
+39
-48
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,11 +34,12 @@
|
|||||||
#include "MenuStyle_Base.h"
|
#include "MenuStyle_Base.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "MenuManager.h"
|
#include "MenuManager.h"
|
||||||
#include "HandleSys.h"
|
|
||||||
#include "CellRecipientFilter.h"
|
#include "CellRecipientFilter.h"
|
||||||
#if defined MENU_DEBUG
|
#if defined MENU_DEBUG
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
#include "AutoHandleRooter.h"
|
||||||
|
|
||||||
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
|
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
|
||||||
{
|
{
|
||||||
@@ -314,7 +315,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|||||||
|
|
||||||
if (sound != NULL)
|
if (sound != NULL)
|
||||||
{
|
{
|
||||||
edict_t *pEdict = engine->PEntityOfEntIndex(client);
|
edict_t *pEdict = PEntityOfEntIndex(client);
|
||||||
if (pEdict)
|
if (pEdict)
|
||||||
{
|
{
|
||||||
ICollideable *pCollideable = pEdict->GetCollideable();
|
ICollideable *pCollideable = pEdict->GetCollideable();
|
||||||
@@ -322,15 +323,24 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|||||||
if (pCollideable)
|
if (pCollideable)
|
||||||
{
|
{
|
||||||
const Vector & pos = pCollideable->GetCollisionOrigin();
|
const Vector & pos = pCollideable->GetCollisionOrigin();
|
||||||
|
|
||||||
enginesound->EmitSound(filter,
|
enginesound->EmitSound(filter,
|
||||||
client,
|
client,
|
||||||
CHAN_AUTO,
|
CHAN_AUTO,
|
||||||
|
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||||
|
sound,
|
||||||
|
-1,
|
||||||
|
#endif
|
||||||
sound,
|
sound,
|
||||||
VOL_NORM,
|
VOL_NORM,
|
||||||
ATTN_NORM,
|
ATTN_NORM,
|
||||||
|
#if SOURCE_ENGINE >= SE_PORTAL2
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
0,
|
0,
|
||||||
PITCH_NORM,
|
PITCH_NORM,
|
||||||
|
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
&pos);
|
&pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,6 +387,9 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
|||||||
RemoveClientFromWatch(client);
|
RemoveClientFromWatch(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handle_t hndl = menu ? menu->GetHandle() : BAD_HANDLE;
|
||||||
|
AutoHandleRooter ahr(hndl);
|
||||||
|
|
||||||
if (cancel)
|
if (cancel)
|
||||||
{
|
{
|
||||||
mh->OnMenuCancel(menu, client, reason);
|
mh->OnMenuCancel(menu, client, reason);
|
||||||
@@ -591,7 +604,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
|
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
|
||||||
m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
|
m_pStyle(pStyle), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
|
||||||
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
|
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
|
||||||
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
|
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
|
||||||
{
|
{
|
||||||
@@ -614,94 +627,74 @@ Handle_t CBaseMenu::GetHandle()
|
|||||||
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
||||||
{
|
{
|
||||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
||||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
&& m_items.length() >= m_pStyle->GetMaxPageItems())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CItem item;
|
CItem item;
|
||||||
|
|
||||||
item.infoString = m_Strings.AddString(info);
|
item.info = info;
|
||||||
if (draw.display)
|
if (draw.display)
|
||||||
{
|
item.display = new ke::AString(draw.display);
|
||||||
item.displayString = m_Strings.AddString(draw.display);
|
|
||||||
}
|
|
||||||
item.style = draw.style;
|
item.style = draw.style;
|
||||||
|
|
||||||
m_items.push_back(item);
|
m_items.append(ke::Move(item));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
||||||
{
|
{
|
||||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
if (m_Pagination == (unsigned)MENU_NO_PAGINATION &&
|
||||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
m_items.length() >= m_pStyle->GetMaxPageItems())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position >= m_items.size())
|
if (position >= m_items.length())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
CItem item;
|
CItem item;
|
||||||
item.infoString = m_Strings.AddString(info);
|
item.info = info;
|
||||||
if (draw.display)
|
if (draw.display)
|
||||||
{
|
item.display = new ke::AString(draw.display);
|
||||||
item.displayString = m_Strings.AddString(draw.display);
|
|
||||||
}
|
|
||||||
item.style = draw.style;
|
item.style = draw.style;
|
||||||
|
|
||||||
CVector<CItem>::iterator iter = m_items.iterAt(position);
|
m_items.insert(position, ke::Move(item));
|
||||||
m_items.insert(iter, item);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBaseMenu::RemoveItem(unsigned int position)
|
bool CBaseMenu::RemoveItem(unsigned int position)
|
||||||
{
|
{
|
||||||
if (position >= m_items.size())
|
if (position >= m_items.length())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
m_items.erase(m_items.iterAt(position));
|
|
||||||
|
|
||||||
if (m_items.size() == 0)
|
|
||||||
{
|
|
||||||
m_Strings.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
m_items.remove(position);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBaseMenu::RemoveAllItems()
|
void CBaseMenu::RemoveAllItems()
|
||||||
{
|
{
|
||||||
m_items.clear();
|
m_items.clear();
|
||||||
m_Strings.Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
|
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
|
||||||
{
|
{
|
||||||
if (position >= m_items.size())
|
if (position >= m_items.length())
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (draw)
|
if (draw)
|
||||||
{
|
{
|
||||||
draw->display = m_Strings.GetString(m_items[position].displayString);
|
draw->display = m_items[position].display->chars();
|
||||||
draw->style = m_items[position].style;
|
draw->style = m_items[position].style;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_Strings.GetString(m_items[position].infoString);
|
return m_items[position].info.chars();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CBaseMenu::GetItemCount()
|
unsigned int CBaseMenu::GetItemCount()
|
||||||
{
|
{
|
||||||
return m_items.size();
|
return m_items.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
||||||
@@ -734,12 +727,12 @@ IMenuStyle *CBaseMenu::GetDrawStyle()
|
|||||||
|
|
||||||
void CBaseMenu::SetDefaultTitle(const char *message)
|
void CBaseMenu::SetDefaultTitle(const char *message)
|
||||||
{
|
{
|
||||||
m_Title.assign(message);
|
m_Title = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CBaseMenu::GetDefaultTitle()
|
const char *CBaseMenu::GetDefaultTitle()
|
||||||
{
|
{
|
||||||
return m_Title.c_str();
|
return m_Title.chars();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBaseMenu::Cancel()
|
void CBaseMenu::Cancel()
|
||||||
@@ -806,7 +799,7 @@ void CBaseMenu::InternalDelete()
|
|||||||
|
|
||||||
m_hHandle = BAD_HANDLE;
|
m_hHandle = BAD_HANDLE;
|
||||||
m_bDeleting = true;
|
m_bDeleting = true;
|
||||||
g_HandleSys.FreeHandle(hndl, &sec);
|
handlesys->FreeHandle(hndl, &sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pHandler->OnMenuDestroy(this);
|
m_pHandler->OnMenuDestroy(this);
|
||||||
@@ -831,7 +824,5 @@ IMenuHandler *CBaseMenu::GetHandler()
|
|||||||
|
|
||||||
unsigned int CBaseMenu::GetBaseMemUsage()
|
unsigned int CBaseMenu::GetBaseMemUsage()
|
||||||
{
|
{
|
||||||
return m_Title.size()
|
return m_Title.length() + (m_items.length() * sizeof(CItem));
|
||||||
+ m_Strings.GetMemTable()->GetMemUsage()
|
|
||||||
+ (m_items.size() * sizeof(CItem));
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-13
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,29 +34,45 @@
|
|||||||
|
|
||||||
#include <IMenuManager.h>
|
#include <IMenuManager.h>
|
||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <sh_string.h>
|
#include <am-string.h>
|
||||||
#include <sh_vector.h>
|
#include <am-vector.h>
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
using namespace SourceHook;
|
|
||||||
|
|
||||||
class CItem
|
class CItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CItem()
|
CItem()
|
||||||
{
|
{
|
||||||
infoString = -1;
|
|
||||||
displayString = -1;
|
|
||||||
style = 0;
|
style = 0;
|
||||||
access = 0;
|
access = 0;
|
||||||
}
|
}
|
||||||
|
CItem(ke::Moveable<CItem> other)
|
||||||
|
: info(ke::Move(other->info)),
|
||||||
|
display(ke::Move(other->display))
|
||||||
|
{
|
||||||
|
style = other->style;
|
||||||
|
access = other->access;
|
||||||
|
}
|
||||||
|
CItem & operator =(ke::Moveable<CItem> other)
|
||||||
|
{
|
||||||
|
info = ke::Move(other->info);
|
||||||
|
display = ke::Move(other->display);
|
||||||
|
style = other->style;
|
||||||
|
access = other->access;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int infoString;
|
ke::AString info;
|
||||||
int displayString;
|
ke::AutoPtr<ke::AString> display;
|
||||||
unsigned int style;
|
unsigned int style;
|
||||||
unsigned int access;
|
unsigned int access;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CItem(const CItem &other) KE_DELETE;
|
||||||
|
CItem &operator =(const CItem &other) KE_DELETE;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CBaseMenuPlayer
|
class CBaseMenuPlayer
|
||||||
@@ -139,11 +155,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
void InternalDelete();
|
void InternalDelete();
|
||||||
protected:
|
protected:
|
||||||
String m_Title;
|
ke::AString m_Title;
|
||||||
IMenuStyle *m_pStyle;
|
IMenuStyle *m_pStyle;
|
||||||
BaseStringTable m_Strings;
|
|
||||||
unsigned int m_Pagination;
|
unsigned int m_Pagination;
|
||||||
CVector<CItem> m_items;
|
ke::Vector<CItem> m_items;
|
||||||
bool m_bShouldDelete;
|
bool m_bShouldDelete;
|
||||||
bool m_bCancelling;
|
bool m_bCancelling;
|
||||||
IdentityToken_t *m_pOwner;
|
IdentityToken_t *m_pOwner;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,11 +32,20 @@
|
|||||||
#include "MenuStyle_Radio.h"
|
#include "MenuStyle_Radio.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "UserMessages.h"
|
#include "UserMessages.h"
|
||||||
#include "GameConfigs.h"
|
#include <IGameConfigs.h>
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#if defined MENU_DEBUG
|
#if defined MENU_DEBUG
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#endif
|
#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[];
|
extern const char *g_RadioNumTable[];
|
||||||
CRadioStyle g_RadioMenuStyle;
|
CRadioStyle g_RadioMenuStyle;
|
||||||
@@ -44,6 +53,14 @@ int g_ShowMenuId = -1;
|
|||||||
bool g_bRadioInit = false;
|
bool g_bRadioInit = false;
|
||||||
unsigned int g_RadioMenuTimeout = 0;
|
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()
|
CRadioStyle::CRadioStyle()
|
||||||
{
|
{
|
||||||
m_players = new CRadioMenuPlayer[256+1];
|
m_players = new CRadioMenuPlayer[256+1];
|
||||||
@@ -89,6 +106,18 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
|||||||
g_RadioMenuTimeout = 0;
|
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.AddStyle(this);
|
||||||
g_Menus.SetDefaultStyle(this);
|
g_Menus.SetDefaultStyle(this);
|
||||||
|
|
||||||
@@ -109,7 +138,11 @@ void CRadioStyle::OnSourceModShutdown()
|
|||||||
|
|
||||||
bool CRadioStyle::IsSupported()
|
bool CRadioStyle::IsSupported()
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
return (g_ShowMenuId != -1);
|
return (g_ShowMenuId != -1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
|
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
|
||||||
@@ -134,13 +167,23 @@ static unsigned int g_last_holdtime = 0;
|
|||||||
static unsigned int g_last_client_count = 0;
|
static unsigned int g_last_client_count = 0;
|
||||||
static int g_last_clients[256];
|
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)
|
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE != SE_DOTA
|
||||||
int count = pFilter->GetRecipientCount();
|
int count = pFilter->GetRecipientCount();
|
||||||
|
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
||||||
|
#else
|
||||||
bf_read br(bf->GetBasePointer(), 3);
|
bf_read br(bf->GetBasePointer(), 3);
|
||||||
|
|
||||||
br.ReadWord();
|
br.ReadWord();
|
||||||
int c = br.ReadChar();
|
int c = br.ReadChar();
|
||||||
|
#endif
|
||||||
|
|
||||||
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
|
||||||
|
|
||||||
@@ -148,6 +191,7 @@ void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFil
|
|||||||
{
|
{
|
||||||
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
|
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRadioStyle::OnUserMessageSent(int msg_id)
|
void CRadioStyle::OnUserMessageSent(int msg_id)
|
||||||
@@ -188,7 +232,7 @@ IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwn
|
|||||||
|
|
||||||
unsigned int CRadioStyle::GetMaxPageItems()
|
unsigned int CRadioStyle::GetMaxPageItems()
|
||||||
{
|
{
|
||||||
return 10;
|
return s_RadioMaxPageItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CRadioStyle::GetStyleName()
|
const char *CRadioStyle::GetStyleName()
|
||||||
@@ -306,7 +350,7 @@ unsigned int CRadioDisplay::GetCurrentKey()
|
|||||||
|
|
||||||
bool CRadioDisplay::SetCurrentKey(unsigned int key)
|
bool CRadioDisplay::SetCurrentKey(unsigned int key)
|
||||||
{
|
{
|
||||||
if (key < m_NextPos || m_NextPos > 10)
|
if (key < m_NextPos || m_NextPos > s_RadioMaxPageItems)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -342,7 +386,7 @@ void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
|
|||||||
|
|
||||||
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
|
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
|
||||||
{
|
{
|
||||||
if (m_NextPos > 10 || !CanDrawItem(item.style))
|
if (m_NextPos > s_RadioMaxPageItems || !CanDrawItem(item.style))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -435,7 +479,8 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
|||||||
|
|
||||||
void CRadioMenuPlayer::Radio_Refresh()
|
void CRadioMenuPlayer::Radio_Refresh()
|
||||||
{
|
{
|
||||||
cell_t players[1] = {m_index};
|
#if SOURCE_ENGINE != SE_DOTA
|
||||||
|
cell_t players[1] = { (cell_t)m_index };
|
||||||
char *ptr = display_pkt;
|
char *ptr = display_pkt;
|
||||||
char save = 0;
|
char save = 0;
|
||||||
size_t len = display_len;
|
size_t len = display_len;
|
||||||
@@ -451,6 +496,15 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
if (len > 240)
|
if (len > 240)
|
||||||
@@ -458,7 +512,8 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
save = ptr[240];
|
save = ptr[240];
|
||||||
ptr[240] = '\0';
|
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->WriteWord(display_keys);
|
||||||
buffer->WriteChar(time ? time : -1);
|
buffer->WriteChar(time ? time : -1);
|
||||||
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
buffer->WriteByte( (len > 240) ? 1 : 0 );
|
||||||
@@ -475,8 +530,10 @@ void CRadioMenuPlayer::Radio_Refresh()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
display_last_refresh = gpGlobals->curtime;
|
display_last_refresh = gpGlobals->curtime;
|
||||||
|
#endif // !DOTA
|
||||||
}
|
}
|
||||||
|
|
||||||
int CRadioDisplay::GetAmountRemaining()
|
int CRadioDisplay::GetAmountRemaining()
|
||||||
@@ -510,6 +567,7 @@ unsigned int CRadioDisplay::GetApproxMemUsage()
|
|||||||
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
|
||||||
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
|
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
|
||||||
{
|
{
|
||||||
|
m_Pagination = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
||||||
@@ -550,6 +608,17 @@ bool CRadioMenu::DisplayAtItem(int client,
|
|||||||
time);
|
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()
|
void CRadioMenu::Cancel_Finally()
|
||||||
{
|
{
|
||||||
g_RadioMenuStyle.CancelMenu(this);
|
g_RadioMenuStyle.CancelMenu(this);
|
||||||
|
|||||||
+12
-3
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
#include "MenuStyle_Base.h"
|
#include "MenuStyle_Base.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <IUserMessages.h>
|
#include "UserMessages.h"
|
||||||
#include "sm_fastlink.h"
|
#include "sm_fastlink.h"
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <compat_wrappers.h>
|
#include <compat_wrappers.h>
|
||||||
@@ -65,7 +65,11 @@ private:
|
|||||||
class CRadioStyle :
|
class CRadioStyle :
|
||||||
public BaseMenuStyle,
|
public BaseMenuStyle,
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IUserMessageListener
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
public IProtobufUserMessageListener
|
||||||
|
#else
|
||||||
|
public IBitBufUserMessageListener
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRadioStyle();
|
CRadioStyle();
|
||||||
@@ -84,7 +88,11 @@ public: //IMenuStyle
|
|||||||
unsigned int GetMaxPageItems();
|
unsigned int GetMaxPageItems();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
public: //IUserMessageListener
|
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);
|
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
|
||||||
|
#endif
|
||||||
void OnUserMessageSent(int msg_id);
|
void OnUserMessageSent(int msg_id);
|
||||||
public:
|
public:
|
||||||
bool IsSupported();
|
bool IsSupported();
|
||||||
@@ -142,6 +150,7 @@ public:
|
|||||||
unsigned int time,
|
unsigned int time,
|
||||||
unsigned int start_item,
|
unsigned int start_item,
|
||||||
IMenuHandler *alt_handler/* =NULL */);
|
IMenuHandler *alt_handler/* =NULL */);
|
||||||
|
bool SetPagination(unsigned int itemsPerPage);
|
||||||
void Cancel_Finally();
|
void Cancel_Finally();
|
||||||
unsigned int GetApproxMemUsage();
|
unsigned int GetApproxMemUsage();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,7 +32,6 @@
|
|||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "Translator.h"
|
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "ConCmdManager.h"
|
#include "ConCmdManager.h"
|
||||||
|
|
||||||
@@ -66,16 +65,20 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
|
|||||||
|
|
||||||
void ValveMenuStyle::OnSourceModAllInitialized()
|
void ValveMenuStyle::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE != SE_DOTA
|
||||||
g_Players.AddClientListener(this);
|
g_Players.AddClientListener(this);
|
||||||
SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
||||||
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValveMenuStyle::OnSourceModShutdown()
|
void ValveMenuStyle::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE != SE_DOTA
|
||||||
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
|
||||||
g_Players.RemoveClientListener(this);
|
g_Players.RemoveClientListener(this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
||||||
@@ -88,7 +91,7 @@ void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client = engine->IndexOfEdict(pEdict);
|
int client = IndexOfEdict(pEdict);
|
||||||
if (client < 1 || client > 256)
|
if (client < 1 || client > 256)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -325,7 +328,7 @@ void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int ti
|
|||||||
m_pKv->SetInt("time", time ? time : 200);
|
m_pKv->SetInt("time", time ? time : 200);
|
||||||
|
|
||||||
SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
|
SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
|
||||||
engine->PEntityOfEntIndex(client),
|
PEntityOfEntIndex(client),
|
||||||
DIALOG_MENU,
|
DIALOG_MENU,
|
||||||
m_pKv,
|
m_pKv,
|
||||||
vsp_interface);
|
vsp_interface);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
|||||||
+305
-17
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,10 +34,57 @@
|
|||||||
#include "MenuVoting.h"
|
#include "MenuVoting.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
#include "sourcemm_api.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;
|
float g_next_vote = 0.0f;
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
#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);
|
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
|
||||||
#else
|
#else
|
||||||
void OnVoteDelayChange(ConVar *cvar, const char *value);
|
void OnVoteDelayChange(ConVar *cvar, const char *value);
|
||||||
@@ -52,7 +99,7 @@ ConVar sm_vote_delay("sm_vote_delay",
|
|||||||
0.0,
|
0.0,
|
||||||
OnVoteDelayChange);
|
OnVoteDelayChange);
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
|
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
|
||||||
#else
|
#else
|
||||||
void OnVoteDelayChange(ConVar *cvar, const char *value)
|
void OnVoteDelayChange(ConVar *cvar, const char *value)
|
||||||
@@ -113,14 +160,19 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wipe out their vote if they had one */
|
/* Wipe out their vote if they had one. We have to make sure the the the
|
||||||
|
* newly connected client is not allowed to vote.
|
||||||
|
*/
|
||||||
int item;
|
int item;
|
||||||
if ((item = m_ClientVotes[client]) >= 0)
|
if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
|
||||||
{
|
{
|
||||||
assert((unsigned)item < m_Items);
|
if (item >= 0)
|
||||||
assert(m_Votes[item] > 0);
|
{
|
||||||
m_Votes[item]--;
|
assert((unsigned)item < m_Items);
|
||||||
m_ClientVotes[client] = -1;
|
assert(m_Votes[item] > 0);
|
||||||
|
m_Votes[item]--;
|
||||||
|
}
|
||||||
|
m_ClientVotes[client] = VOTE_NOT_VOTING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,18 +181,28 @@ bool VoteMenuHandler::IsVoteInProgress()
|
|||||||
return (m_pCurMenu != NULL);
|
return (m_pCurMenu != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags/* =0 */)
|
bool VoteMenuHandler::StartVote(IBaseMenu *menu,
|
||||||
|
unsigned int num_clients,
|
||||||
|
int clients[],
|
||||||
|
unsigned int max_time,
|
||||||
|
unsigned int flags/* =0 */)
|
||||||
{
|
{
|
||||||
if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
|
if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: we can use game time and not universal time because
|
||||||
|
* if we're voting then players are in-game.
|
||||||
|
*/
|
||||||
|
|
||||||
float fVoteDelay = sm_vote_delay.GetFloat();
|
float fVoteDelay = sm_vote_delay.GetFloat();
|
||||||
if (fVoteDelay < 1.0)
|
if (fVoteDelay < 1.0)
|
||||||
{
|
{
|
||||||
g_next_vote = 0.0;
|
g_next_vote = 0.0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* This little trick breaks for infinite votes!
|
/* This little trick breaks for infinite votes!
|
||||||
* However, we just ignore that since those 1) shouldn't exist and
|
* However, we just ignore that since those 1) shouldn't exist and
|
||||||
* 2) people must be checking IsVoteInProgress() beforehand anyway.
|
* 2) people must be checking IsVoteInProgress() beforehand anyway.
|
||||||
@@ -148,8 +210,15 @@ bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int c
|
|||||||
g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
|
g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_fStartTime = gpGlobals->curtime;
|
||||||
|
m_nMenuTime = max_time;
|
||||||
|
|
||||||
for (unsigned int i=0; i<num_clients; i++)
|
for (unsigned int i=0; i<num_clients; i++)
|
||||||
{
|
{
|
||||||
|
if (clients[i] < 1 || clients[i] > 256)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
menu->Display(clients[i], max_time, this);
|
menu->Display(clients[i], max_time, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,6 +227,72 @@ bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int c
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VoteMenuHandler::IsClientInVotePool(int client)
|
||||||
|
{
|
||||||
|
if (client < 1
|
||||||
|
|| client > g_Players.MaxClients()
|
||||||
|
|| m_pCurMenu == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (m_ClientVotes[client] > VOTE_NOT_VOTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
||||||
|
{
|
||||||
|
if (!IsClientInVotePool(client)
|
||||||
|
|| m_ClientVotes[client] == VOTE_PENDING)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pItem = m_ClientVotes[client];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
|
||||||
|
{
|
||||||
|
unsigned int time_limit;
|
||||||
|
|
||||||
|
if (!IsClientInVotePool(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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_limit = (int)((float)m_nMenuTime - (gpGlobals->curtime - m_fStartTime));
|
||||||
|
|
||||||
|
/* Make sure this doesn't round to zero */
|
||||||
|
if (time_limit == MENU_TIME_FOREVER)
|
||||||
|
{
|
||||||
|
time_limit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_pCurMenu->Display(client, time_limit, this);
|
||||||
|
}
|
||||||
|
|
||||||
bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
||||||
IMenuHandler *handler,
|
IMenuHandler *handler,
|
||||||
unsigned int time,
|
unsigned int time,
|
||||||
@@ -173,7 +308,8 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
|||||||
/* Mark all clients as not voting */
|
/* Mark all clients as not voting */
|
||||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
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();
|
m_Items = menu->GetItemCount();
|
||||||
@@ -187,7 +323,9 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
|||||||
m_Votes[i] = 0;
|
m_Votes[i] = 0;
|
||||||
}
|
}
|
||||||
m_Votes.resize(m_Items, 0);
|
m_Votes.resize(m_Items, 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (unsigned int i=0; i<m_Items; i++)
|
for (unsigned int i=0; i<m_Items; i++)
|
||||||
{
|
{
|
||||||
m_Votes[i] = 0;
|
m_Votes[i] = 0;
|
||||||
@@ -215,6 +353,8 @@ void VoteMenuHandler::StartVoting()
|
|||||||
|
|
||||||
m_pHandler->OnMenuVoteStart(m_pCurMenu);
|
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.
|
/* By now we know how many clients were set.
|
||||||
* If there are none, we should end IMMEDIATELY.
|
* If there are none, we should end IMMEDIATELY.
|
||||||
*/
|
*/
|
||||||
@@ -222,6 +362,8 @@ void VoteMenuHandler::StartVoting()
|
|||||||
{
|
{
|
||||||
EndVoting();
|
EndVoting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_TotalClients = m_Clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoteMenuHandler::DecrementPlayerCount()
|
void VoteMenuHandler::DecrementPlayerCount()
|
||||||
@@ -252,10 +394,17 @@ void VoteMenuHandler::EndVoting()
|
|||||||
if (fVoteDelay < 1.0)
|
if (fVoteDelay < 1.0)
|
||||||
{
|
{
|
||||||
g_next_vote = 0.0;
|
g_next_vote = 0.0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_displayTimer)
|
||||||
|
{
|
||||||
|
g_Timers.KillTimer(m_displayTimer);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_bCancelled)
|
if (m_bCancelled)
|
||||||
{
|
{
|
||||||
/* If we were cancelled, don't bother tabulating anything.
|
/* If we were cancelled, don't bother tabulating anything.
|
||||||
@@ -302,7 +451,7 @@ void VoteMenuHandler::EndVoting()
|
|||||||
/* Build the client list */
|
/* Build the client list */
|
||||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
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].client = i;
|
||||||
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
||||||
@@ -346,7 +495,7 @@ void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason
|
|||||||
|
|
||||||
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
||||||
{
|
{
|
||||||
m_ClientVotes[client] = -1;
|
m_ClientVotes[client] = VOTE_PENDING;
|
||||||
m_pHandler->OnMenuDisplay(menu, client, display);
|
m_pHandler->OnMenuDisplay(menu, client, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,6 +517,58 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
|
|||||||
m_ClientVotes[client] = item;
|
m_ClientVotes[client] = item;
|
||||||
m_Votes[item]++;
|
m_Votes[item]++;
|
||||||
m_NumVotes++;
|
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);
|
m_pHandler->OnMenuSelect(menu, client, item);
|
||||||
@@ -390,6 +591,9 @@ void VoteMenuHandler::InternalReset()
|
|||||||
m_NumVotes = 0;
|
m_NumVotes = 0;
|
||||||
m_bCancelled = false;
|
m_bCancelled = false;
|
||||||
m_pHandler = NULL;
|
m_pHandler = NULL;
|
||||||
|
m_leaderList[0] = '\0';
|
||||||
|
m_displayTimer = NULL;
|
||||||
|
m_TotalClients = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoteMenuHandler::CancelVoting()
|
void VoteMenuHandler::CancelVoting()
|
||||||
@@ -411,3 +615,87 @@ bool VoteMenuHandler::IsCancelling()
|
|||||||
{
|
{
|
||||||
return m_bCancelled;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
+19
-2
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <IPlayerHelpers.h>
|
#include <IPlayerHelpers.h>
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
|
#include <TimerSys.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -43,7 +44,8 @@ using namespace SourceMod;
|
|||||||
class VoteMenuHandler :
|
class VoteMenuHandler :
|
||||||
public IMenuHandler,
|
public IMenuHandler,
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IClientListener
|
public IClientListener,
|
||||||
|
public ITimedEvent
|
||||||
{
|
{
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
@@ -61,6 +63,9 @@ public: //IMenuHandler
|
|||||||
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
||||||
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
|
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);
|
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:
|
public:
|
||||||
bool StartVote(IBaseMenu *menu,
|
bool StartVote(IBaseMenu *menu,
|
||||||
unsigned int num_clients,
|
unsigned int num_clients,
|
||||||
@@ -72,6 +77,9 @@ public:
|
|||||||
IBaseMenu *GetCurrentMenu();
|
IBaseMenu *GetCurrentMenu();
|
||||||
bool IsCancelling();
|
bool IsCancelling();
|
||||||
unsigned int GetRemainingVoteDelay();
|
unsigned int GetRemainingVoteDelay();
|
||||||
|
bool IsClientInVotePool(int client);
|
||||||
|
bool GetClientVoteChoice(int client, unsigned int *pItem);
|
||||||
|
bool RedrawToClient(int client, bool revote);
|
||||||
private:
|
private:
|
||||||
void Reset(IMenuHandler *mh);
|
void Reset(IMenuHandler *mh);
|
||||||
void DecrementPlayerCount();
|
void DecrementPlayerCount();
|
||||||
@@ -82,9 +90,12 @@ private:
|
|||||||
unsigned int time,
|
unsigned int time,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
void StartVoting();
|
void StartVoting();
|
||||||
|
void DrawHintProgress();
|
||||||
|
void BuildVoteLeaders();
|
||||||
private:
|
private:
|
||||||
IMenuHandler *m_pHandler;
|
IMenuHandler *m_pHandler;
|
||||||
unsigned int m_Clients;
|
unsigned int m_Clients;
|
||||||
|
unsigned int m_TotalClients;
|
||||||
unsigned int m_Items;
|
unsigned int m_Items;
|
||||||
CVector<unsigned int> m_Votes;
|
CVector<unsigned int> m_Votes;
|
||||||
IBaseMenu *m_pCurMenu;
|
IBaseMenu *m_pCurMenu;
|
||||||
@@ -93,7 +104,13 @@ private:
|
|||||||
unsigned int m_NumVotes;
|
unsigned int m_NumVotes;
|
||||||
unsigned int m_VoteTime;
|
unsigned int m_VoteTime;
|
||||||
unsigned int m_VoteFlags;
|
unsigned int m_VoteFlags;
|
||||||
|
float m_fStartTime;
|
||||||
|
unsigned int m_nMenuTime;
|
||||||
int m_ClientVotes[256+1];
|
int m_ClientVotes[256+1];
|
||||||
|
bool m_Revoting[256+1];
|
||||||
|
char m_leaderList[1024];
|
||||||
|
ITimer *m_displayTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
/**
|
||||||
|
* 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 "NextMap.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "HalfLife2.h"
|
||||||
|
#include "sourcemm_api.h"
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
#include "sourcehook.h"
|
||||||
|
#include "sm_srvcmds.h"
|
||||||
|
|
||||||
|
NextMapManager g_NextMap;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *);
|
||||||
|
#else
|
||||||
|
SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
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
|
||||||
|
# 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
|
||||||
|
|
||||||
|
ConCommand *changeLevelCmd = NULL;
|
||||||
|
|
||||||
|
ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY);
|
||||||
|
|
||||||
|
bool g_forcedChange = false;
|
||||||
|
|
||||||
|
void NextMapManager::OnSourceModAllInitialized_Post()
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
|
#else
|
||||||
|
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ConCommand *pCmd = FindCommand("changelevel");
|
||||||
|
if (pCmd != NULL)
|
||||||
|
{
|
||||||
|
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdChangeLevelCallback), false);
|
||||||
|
changeLevelCmd = pCmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextMapManager::OnSourceModShutdown()
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
|
#else
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (changeLevelCmd != NULL)
|
||||||
|
{
|
||||||
|
SH_REMOVE_HOOK(ConCommand, Dispatch, changeLevelCmd, SH_STATIC(CmdChangeLevelCallback), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceHook::List<MapChangeData *>::iterator iter;
|
||||||
|
iter = m_mapHistory.begin();
|
||||||
|
|
||||||
|
while (iter != m_mapHistory.end())
|
||||||
|
{
|
||||||
|
delete (MapChangeData *)*iter;
|
||||||
|
iter = m_mapHistory.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *NextMapManager::GetNextMap()
|
||||||
|
{
|
||||||
|
return sm_nextmap.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NextMapManager::SetNextMap(const char *map)
|
||||||
|
{
|
||||||
|
if (!g_HL2.IsMapValid(map))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sm_nextmap.SetValue(map);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
void NextMapManager::HookChangeLevel(const char *map, const char *unknown)
|
||||||
|
#else
|
||||||
|
void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (g_forcedChange)
|
||||||
|
{
|
||||||
|
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *newmap = sm_nextmap.GetString();
|
||||||
|
|
||||||
|
if (newmap[0] == 0 || !g_HL2.IsMapValid(newmap))
|
||||||
|
{
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_Logger.LogMessage("[SM] Changed map to \"%s\"", newmap);
|
||||||
|
|
||||||
|
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
||||||
|
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
|
||||||
|
#else
|
||||||
|
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown, video, bLongLoading));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextMapManager::OnSourceModLevelChange( const char *mapName )
|
||||||
|
{
|
||||||
|
/* Skip the first 'mapchange' when the server starts up */
|
||||||
|
if (m_tempChangeInfo.startTime != 0)
|
||||||
|
{
|
||||||
|
if (strcmp(mapName, m_tempChangeInfo.m_mapName) == 0)
|
||||||
|
{
|
||||||
|
/* The map change was as we expected */
|
||||||
|
m_mapHistory.push_back(new MapChangeData(lastMap, m_tempChangeInfo.m_changeReason, m_tempChangeInfo.startTime));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something intercepted the mapchange */
|
||||||
|
char newReason[255];
|
||||||
|
UTIL_Format(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason);
|
||||||
|
m_mapHistory.push_back(new MapChangeData(lastMap, newReason, m_tempChangeInfo.startTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Should this be customizable? */
|
||||||
|
if (m_mapHistory.size() > 20)
|
||||||
|
{
|
||||||
|
SourceHook::List<MapChangeData *>::iterator iter;
|
||||||
|
iter = m_mapHistory.begin();
|
||||||
|
|
||||||
|
delete (MapChangeData *)*iter;
|
||||||
|
|
||||||
|
m_mapHistory.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_tempChangeInfo.m_mapName[0] ='\0';
|
||||||
|
m_tempChangeInfo.m_changeReason[0] = '\0';
|
||||||
|
m_tempChangeInfo.startTime = time(NULL);
|
||||||
|
UTIL_Format(lastMap, sizeof(lastMap), "%s", mapName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
|
||||||
|
{
|
||||||
|
/* Store the mapname and reason */
|
||||||
|
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), "%s", mapName);
|
||||||
|
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "%s", changeReason);
|
||||||
|
|
||||||
|
/* Change level and skip our hook */
|
||||||
|
g_forcedChange = true;
|
||||||
|
engine->ChangeLevel(mapName, NULL);
|
||||||
|
g_forcedChange = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NextMapManager::NextMapManager()
|
||||||
|
{
|
||||||
|
m_tempChangeInfo = MapChangeData();
|
||||||
|
m_mapHistory = SourceHook::List<MapChangeData *>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command)
|
||||||
|
{
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
void CmdChangeLevelCallback(const CCommand &command)
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
void CmdChangeLevelCallback()
|
||||||
|
{
|
||||||
|
CCommand command;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (command.ArgC() < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
|
||||||
|
{
|
||||||
|
UTIL_Format(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
|
||||||
|
UTIL_Format(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
|
||||||
|
}
|
||||||
|
}
|
||||||
+107
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* 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_NEXTMAP_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_NEXTMAP_H_
|
||||||
|
|
||||||
|
#include "sm_globals.h"
|
||||||
|
#include "eiface.h"
|
||||||
|
#include "sh_list.h"
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
|
||||||
|
struct MapChangeData
|
||||||
|
{
|
||||||
|
MapChangeData(const char *mapName, const char *changeReason, time_t time)
|
||||||
|
{
|
||||||
|
UTIL_Format(m_mapName, sizeof(m_mapName), mapName);
|
||||||
|
UTIL_Format(m_changeReason, sizeof(m_changeReason), changeReason);
|
||||||
|
startTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapChangeData()
|
||||||
|
{
|
||||||
|
m_mapName[0] = '\0';
|
||||||
|
m_changeReason[0] = '\0';
|
||||||
|
startTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char m_mapName[PLATFORM_MAX_PATH];
|
||||||
|
char m_changeReason[100];
|
||||||
|
time_t startTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
void CmdChangeLevelCallback(const CCommand &command);
|
||||||
|
#else
|
||||||
|
void CmdChangeLevelCallback();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class NextMapManager : public SMGlobalClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NextMapManager();
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
friend void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
friend void CmdChangeLevelCallback(const CCommand &command);
|
||||||
|
#else
|
||||||
|
friend void CmdChangeLevelCallback();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void OnSourceModAllInitialized_Post();
|
||||||
|
void OnSourceModShutdown();
|
||||||
|
void OnSourceModLevelChange(const char *mapName);
|
||||||
|
|
||||||
|
const char *GetNextMap();
|
||||||
|
bool SetNextMap(const char *map);
|
||||||
|
|
||||||
|
void ForceChangeLevel(const char *mapName, const char* changeReason);
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||||
|
void HookChangeLevel(const char *map, const char *unknown);
|
||||||
|
#else
|
||||||
|
void HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
SourceHook::List<MapChangeData *> m_mapHistory;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MapChangeData m_tempChangeInfo;
|
||||||
|
char lastMap[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern NextMapManager g_NextMap;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_NEXTMAP_H_
|
||||||
+1111
-187
File diff suppressed because it is too large
Load Diff
+82
-8
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
|
#include "ConVarManager.h"
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
@@ -50,6 +51,16 @@ using namespace SourceHook;
|
|||||||
|
|
||||||
#define MIN_API_FOR_ADMINCALLS 7
|
#define MIN_API_FOR_ADMINCALLS 7
|
||||||
|
|
||||||
|
union serial_t
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t index : 8;
|
||||||
|
uint32_t serial : 24;
|
||||||
|
} bits;
|
||||||
|
};
|
||||||
|
|
||||||
class CPlayer : public IGamePlayer
|
class CPlayer : public IGamePlayer
|
||||||
{
|
{
|
||||||
friend class PlayerManager;
|
friend class PlayerManager;
|
||||||
@@ -58,24 +69,32 @@ public:
|
|||||||
public:
|
public:
|
||||||
const char *GetName();
|
const char *GetName();
|
||||||
const char *GetIPAddress();
|
const char *GetIPAddress();
|
||||||
const char *GetAuthString();
|
const char *GetAuthString(bool validated = true);
|
||||||
|
unsigned int GetSteamAccountID(bool validated = true);
|
||||||
edict_t *GetEdict();
|
edict_t *GetEdict();
|
||||||
bool IsInGame();
|
bool IsInGame();
|
||||||
bool WasCountedAsInGame();
|
bool WasCountedAsInGame();
|
||||||
bool IsConnected();
|
bool IsConnected();
|
||||||
bool IsAuthorized();
|
bool IsAuthorized();
|
||||||
bool IsFakeClient();
|
bool IsFakeClient();
|
||||||
|
bool IsSourceTV() const;
|
||||||
|
bool IsReplay() const;
|
||||||
void SetAdminId(AdminId id, bool temporary);
|
void SetAdminId(AdminId id, bool temporary);
|
||||||
AdminId GetAdminId();
|
AdminId GetAdminId();
|
||||||
void Kick(const char *str);
|
void Kick(const char *str);
|
||||||
|
bool IsInKickQueue();
|
||||||
IPlayerInfo *GetPlayerInfo();
|
IPlayerInfo *GetPlayerInfo();
|
||||||
unsigned int GetLanguageId();
|
unsigned int GetLanguageId();
|
||||||
|
void SetLanguageId(unsigned int id);
|
||||||
int GetUserId();
|
int GetUserId();
|
||||||
bool RunAdminCacheChecks();
|
bool RunAdminCacheChecks();
|
||||||
void NotifyPostAdminChecks();
|
void NotifyPostAdminChecks();
|
||||||
|
unsigned int GetSerial();
|
||||||
|
int GetIndex() const;
|
||||||
|
void PrintToConsole(const char *pMsg);
|
||||||
|
void ClearAdmin();
|
||||||
public:
|
public:
|
||||||
void DoBasicAdminChecks();
|
void DoBasicAdminChecks();
|
||||||
bool IsInKickQueue();
|
|
||||||
void MarkAsBeingKicked();
|
void MarkAsBeingKicked();
|
||||||
int GetLifeState();
|
int GetLifeState();
|
||||||
private:
|
private:
|
||||||
@@ -84,9 +103,11 @@ private:
|
|||||||
void Disconnect();
|
void Disconnect();
|
||||||
void SetName(const char *name);
|
void SetName(const char *name);
|
||||||
void DumpAdmin(bool deleting);
|
void DumpAdmin(bool deleting);
|
||||||
void Authorize(const char *auth);
|
void SetAuthString(const char *auth);
|
||||||
|
void Authorize();
|
||||||
void Authorize_Post();
|
void Authorize_Post();
|
||||||
void DoPostConnectAuthorization();
|
void DoPostConnectAuthorization();
|
||||||
|
bool IsAuthStringValidated();
|
||||||
private:
|
private:
|
||||||
bool m_IsConnected;
|
bool m_IsConnected;
|
||||||
bool m_IsInGame;
|
bool m_IsInGame;
|
||||||
@@ -105,6 +126,14 @@ private:
|
|||||||
int m_iIndex;
|
int m_iIndex;
|
||||||
unsigned int m_LangId;
|
unsigned int m_LangId;
|
||||||
int m_UserId;
|
int m_UserId;
|
||||||
|
bool m_bFakeClient;
|
||||||
|
bool m_bIsSourceTV;
|
||||||
|
bool m_bIsReplay;
|
||||||
|
serial_t m_Serial;
|
||||||
|
unsigned int m_SteamAccountID;
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
QueryCvarCookie_t m_LanguageCookie;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlayerManager :
|
class PlayerManager :
|
||||||
@@ -120,24 +149,35 @@ public: //SMGlobalClass
|
|||||||
void OnSourceModShutdown();
|
void OnSourceModShutdown();
|
||||||
void OnSourceModLevelEnd();
|
void OnSourceModLevelEnd();
|
||||||
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
|
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
|
||||||
|
void OnSourceModMaxPlayersChanged(int newvalue);
|
||||||
public:
|
public:
|
||||||
CPlayer *GetPlayerByIndex(int client) const;
|
CPlayer *GetPlayerByIndex(int client) const;
|
||||||
void RunAuthChecks();
|
void RunAuthChecks();
|
||||||
void ClearAdminId(AdminId id);
|
|
||||||
void ClearAllAdmins();
|
|
||||||
public:
|
public:
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
bool OnClientConnect(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
||||||
|
bool OnClientConnect_Post(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
||||||
|
void OnClientPutInServer(CEntityIndex index, char const *playername);
|
||||||
|
void OnClientDisconnect(CEntityIndex index, int reason);
|
||||||
|
void OnClientDisconnect_Post(CEntityIndex index, int reason);
|
||||||
|
void OnClientCommand(CEntityIndex index, const CCommand &args);
|
||||||
|
void OnClientSettingsChanged(CEntityIndex index);
|
||||||
|
//void OnClientSettingsChanged_Pre(CEntityIndex client);
|
||||||
|
#else
|
||||||
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
||||||
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
|
||||||
void OnClientPutInServer(edict_t *pEntity, char const *playername);
|
void OnClientPutInServer(edict_t *pEntity, char const *playername);
|
||||||
void OnClientDisconnect(edict_t *pEntity);
|
void OnClientDisconnect(edict_t *pEntity);
|
||||||
void OnClientDisconnect_Post(edict_t *pEntity);
|
void OnClientDisconnect_Post(edict_t *pEntity);
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
void OnClientCommand(edict_t *pEntity, const CCommand &args);
|
void OnClientCommand(edict_t *pEntity, const CCommand &args);
|
||||||
#else
|
#else
|
||||||
void OnClientCommand(edict_t *pEntity);
|
void OnClientCommand(edict_t *pEntity);
|
||||||
#endif
|
#endif
|
||||||
void OnClientSettingsChanged(edict_t *pEntity);
|
void OnClientSettingsChanged(edict_t *pEntity);
|
||||||
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
||||||
|
#endif
|
||||||
|
void OnServerHibernationUpdate(bool bHibernating);
|
||||||
public: //IPlayerManager
|
public: //IPlayerManager
|
||||||
void AddClientListener(IClientListener *listener);
|
void AddClientListener(IClientListener *listener);
|
||||||
void RemoveClientListener(IClientListener *listener);
|
void RemoveClientListener(IClientListener *listener);
|
||||||
@@ -152,6 +192,9 @@ public: //IPlayerManager
|
|||||||
void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||||
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||||
void ProcessCommandTarget(cmd_target_info_t *info);
|
void ProcessCommandTarget(cmd_target_info_t *info);
|
||||||
|
int GetClientFromSerial(unsigned int serial);
|
||||||
|
void ClearAdminId(AdminId id);
|
||||||
|
void RecheckAnyAdmins();
|
||||||
public:
|
public:
|
||||||
inline int MaxClients()
|
inline int MaxClients()
|
||||||
{
|
{
|
||||||
@@ -161,17 +204,30 @@ public:
|
|||||||
{
|
{
|
||||||
return m_PlayerCount;
|
return m_PlayerCount;
|
||||||
}
|
}
|
||||||
|
inline int ListenClient()
|
||||||
|
{
|
||||||
|
return m_ListenClient;
|
||||||
|
}
|
||||||
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
||||||
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
|
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
|
||||||
const char *GetPassInfoVar();
|
const char *GetPassInfoVar();
|
||||||
void RecheckAnyAdmins();
|
|
||||||
unsigned int GetReplyTo();
|
unsigned int GetReplyTo();
|
||||||
unsigned int SetReplyTo(unsigned int reply);
|
unsigned int SetReplyTo(unsigned int reply);
|
||||||
|
void MaxPlayersChanged(int newvalue = -1);
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
|
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
void OnServerActivate();
|
||||||
|
#else
|
||||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
||||||
|
#endif
|
||||||
|
void InvalidatePlayer(CPlayer *pPlayer);
|
||||||
private:
|
private:
|
||||||
List<IClientListener *> m_hooks;
|
List<IClientListener *> m_hooks;
|
||||||
IForward *m_clconnect;
|
IForward *m_clconnect;
|
||||||
|
IForward *m_clconnect_post;
|
||||||
IForward *m_cldisconnect;
|
IForward *m_cldisconnect;
|
||||||
IForward *m_cldisconnect_post;
|
IForward *m_cldisconnect_post;
|
||||||
IForward *m_clputinserver;
|
IForward *m_clputinserver;
|
||||||
@@ -184,12 +240,30 @@ private:
|
|||||||
int *m_UserIdLookUp;
|
int *m_UserIdLookUp;
|
||||||
int m_maxClients;
|
int m_maxClients;
|
||||||
int m_PlayerCount;
|
int m_PlayerCount;
|
||||||
|
int m_PlayersSinceActive;
|
||||||
bool m_FirstPass;
|
bool m_FirstPass;
|
||||||
unsigned int *m_AuthQueue;
|
unsigned int *m_AuthQueue;
|
||||||
String m_PassInfoVar;
|
String m_PassInfoVar;
|
||||||
bool m_QueryLang;
|
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_DOTA
|
||||||
|
void CmdMaxplayersCallback(const CCommandContext &context, const CCommand &command);
|
||||||
|
#elif SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
void CmdMaxplayersCallback(const CCommand &command);
|
||||||
|
#else
|
||||||
|
void CmdMaxplayersCallback();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void ClientConsolePrint(edict_t *e, const char *fmt, ...);
|
||||||
|
|
||||||
extern PlayerManager g_Players;
|
extern PlayerManager g_Players;
|
||||||
extern bool g_OnMapStarted;
|
extern bool g_OnMapStarted;
|
||||||
extern const unsigned int *g_NumPlayersToAuth;
|
extern const unsigned int *g_NumPlayersToAuth;
|
||||||
|
|||||||
+7
-7
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -31,10 +31,10 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "ForwardSys.h"
|
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
#include "ConVarManager.h"
|
#include "ConVarManager.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
#define TIMER_MIN_ACCURACY 0.1
|
#define TIMER_MIN_ACCURACY 0.1
|
||||||
|
|
||||||
@@ -180,9 +180,9 @@ TimerSystem::~TimerSystem()
|
|||||||
|
|
||||||
void TimerSystem::OnSourceModAllInitialized()
|
void TimerSystem::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
m_pOnGameFrame = forwardsys->CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
|
||||||
m_pOnMapTimeLeftChanged = g_Forwards.CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
|
m_pOnMapTimeLeftChanged = forwardsys->CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerSystem::OnSourceModGameInitialized()
|
void TimerSystem::OnSourceModGameInitialized()
|
||||||
@@ -198,8 +198,8 @@ void TimerSystem::OnSourceModGameInitialized()
|
|||||||
void TimerSystem::OnSourceModShutdown()
|
void TimerSystem::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
SetMapTimer(NULL);
|
SetMapTimer(NULL);
|
||||||
g_Forwards.ReleaseForward(m_pOnGameFrame);
|
forwardsys->ReleaseForward(m_pOnGameFrame);
|
||||||
g_Forwards.ReleaseForward(m_pOnMapTimeLeftChanged);
|
forwardsys->ReleaseForward(m_pOnMapTimeLeftChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerSystem::OnSourceModLevelEnd()
|
void TimerSystem::OnSourceModLevelEnd()
|
||||||
|
|||||||
+3
-3
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,11 +32,11 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
||||||
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
|
||||||
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <ITimerSystem.h>
|
#include <ITimerSystem.h>
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
|
#include "sm_globals.h"
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
@@ -78,11 +78,11 @@ public: //ITimerSystem
|
|||||||
float GetTickedTime();
|
float GetTickedTime();
|
||||||
void NotifyOfGameStart(float offset /* = 0.0f */);
|
void NotifyOfGameStart(float offset /* = 0.0f */);
|
||||||
bool GetMapTimeLeft(float *pTime);
|
bool GetMapTimeLeft(float *pTime);
|
||||||
|
IMapTimer *GetMapTimer();
|
||||||
public:
|
public:
|
||||||
void RunFrame();
|
void RunFrame();
|
||||||
void RemoveMapChangeTimers();
|
void RemoveMapChangeTimers();
|
||||||
void GameFrame(bool simulating);
|
void GameFrame(bool simulating);
|
||||||
IMapTimer *GetMapTimer();
|
|
||||||
private:
|
private:
|
||||||
List<ITimer *> m_SingleTimers;
|
List<ITimer *> m_SingleTimers;
|
||||||
List<ITimer *> m_LoopTimers;
|
List<ITimer *> m_LoopTimers;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+410
-61
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -31,15 +31,35 @@
|
|||||||
|
|
||||||
#include "UserMessages.h"
|
#include "UserMessages.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
|
#include "logic_bridge.h"
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
#include <dota_usermessage_helpers.h>
|
||||||
|
#elif SOURCE_ENGINE == SE_CSGO
|
||||||
|
#include <cstrike15_usermessage_helpers.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
UserMessages g_UserMsgs;
|
UserMessages g_UserMsgs;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
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);
|
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
||||||
|
#endif
|
||||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
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_HookCount = 0;
|
||||||
m_InExec = false;
|
m_InExec = false;
|
||||||
m_InHook = false;
|
m_InHook = false;
|
||||||
@@ -49,8 +69,6 @@ UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
|||||||
|
|
||||||
UserMessages::~UserMessages()
|
UserMessages::~UserMessages()
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_Names);
|
|
||||||
|
|
||||||
CStack<ListenerInfo *>::iterator iter;
|
CStack<ListenerInfo *>::iterator iter;
|
||||||
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
|
||||||
{
|
{
|
||||||
@@ -61,32 +79,46 @@ UserMessages::~UserMessages()
|
|||||||
|
|
||||||
void UserMessages::OnSourceModStartup(bool late)
|
void UserMessages::OnSourceModStartup(bool late)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
/* -1 means SourceMM was unable to get the user message list */
|
/* -1 means SourceMM was unable to get the user message list */
|
||||||
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserMessages::OnSourceModAllInitialized()
|
void UserMessages::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserMessages::OnSourceModAllShutdown()
|
void UserMessages::OnSourceModAllShutdown()
|
||||||
{
|
{
|
||||||
if (m_HookCount)
|
if (m_HookCount)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
#else
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
m_HookCount = 0;
|
m_HookCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int UserMessages::GetMessageIndex(const char *msg)
|
int UserMessages::GetMessageIndex(const char *msg)
|
||||||
{
|
{
|
||||||
int msgid;
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
// Can split this per engine and/or game later
|
||||||
|
return g_DotaUsermessageHelpers.GetIndex(msg);
|
||||||
|
#elif SOURCE_ENGINE == SE_CSGO
|
||||||
|
// Can split this per engine and/or game later
|
||||||
|
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
||||||
|
#else
|
||||||
|
|
||||||
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
|
int msgid;
|
||||||
|
if (!m_Names.retrieve(msg, &msgid))
|
||||||
{
|
{
|
||||||
if (m_FallbackSearch)
|
if (m_FallbackSearch)
|
||||||
{
|
{
|
||||||
@@ -98,7 +130,7 @@ int UserMessages::GetMessageIndex(const char *msg)
|
|||||||
{
|
{
|
||||||
if (strcmp(msgbuf, msg) == 0)
|
if (strcmp(msgbuf, msg) == 0)
|
||||||
{
|
{
|
||||||
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
|
m_Names.insert(msg, msgid);
|
||||||
return msgid;
|
return msgid;
|
||||||
}
|
}
|
||||||
msgid++;
|
msgid++;
|
||||||
@@ -108,16 +140,27 @@ int UserMessages::GetMessageIndex(const char *msg)
|
|||||||
msgid = g_SMAPI->FindUserMessage(msg);
|
msgid = g_SMAPI->FindUserMessage(msg);
|
||||||
|
|
||||||
if (msgid != INVALID_MESSAGE_ID)
|
if (msgid != INVALID_MESSAGE_ID)
|
||||||
{
|
m_Names.insert(msg, msgid);
|
||||||
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return msgid;
|
return msgid;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
|
||||||
{
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
const char *pszName = g_DotaUsermessageHelpers.GetName(msgid);
|
||||||
|
#elif SOURCE_ENGINE == SE_CSGO
|
||||||
|
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
||||||
|
#endif
|
||||||
|
if (!pszName)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
strncopy(buffer, pszName, maxlength);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
if (m_FallbackSearch)
|
if (m_FallbackSearch)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
@@ -133,10 +176,14 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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;
|
bf_write *buffer;
|
||||||
|
|
||||||
if (m_InExec || m_InHook)
|
if (m_InExec || m_InHook)
|
||||||
@@ -164,12 +211,89 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
|||||||
|
|
||||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
{
|
{
|
||||||
|
#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);
|
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
#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);
|
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
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 = GetMessagePrototype(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 = GetMessagePrototype(msg_id)->New();
|
||||||
|
buffer = m_FakeEngineBuffer;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MRES_OVERRIDE:
|
||||||
|
m_FakeEngineBuffer = GetMessagePrototype(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()
|
bool UserMessages::EndMessage()
|
||||||
@@ -179,12 +303,37 @@ bool UserMessages::EndMessage()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
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)
|
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||||
{
|
{
|
||||||
ENGINE_CALL(MessageEnd)();
|
ENGINE_CALL(MessageEnd)();
|
||||||
} else {
|
} else {
|
||||||
engine->MessageEnd();
|
engine->MessageEnd();
|
||||||
}
|
}
|
||||||
|
#endif // SE_CSGO || SE_DOTA
|
||||||
|
|
||||||
m_InExec = false;
|
m_InExec = false;
|
||||||
m_CurFlags = 0;
|
m_CurFlags = 0;
|
||||||
@@ -193,7 +342,60 @@ bool UserMessages::EndMessage()
|
|||||||
return true;
|
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)
|
||||||
|
{
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
#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)
|
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||||
|
{
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
|
||||||
|
#else
|
||||||
|
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
if (msg_id < 0 || msg_id >= 255)
|
||||||
{
|
{
|
||||||
@@ -212,13 +414,19 @@ bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener,
|
|||||||
pInfo->Callback = pListener;
|
pInfo->Callback = pListener;
|
||||||
pInfo->IsHooked = false;
|
pInfo->IsHooked = false;
|
||||||
pInfo->KillMe = false;
|
pInfo->KillMe = false;
|
||||||
|
pInfo->IsNew = isNew;
|
||||||
|
|
||||||
if (!m_HookCount++)
|
if (!m_HookCount++)
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
#else
|
||||||
|
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
|
||||||
|
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
|
||||||
|
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
|
||||||
|
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intercept)
|
if (intercept)
|
||||||
@@ -231,8 +439,23 @@ bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
{
|
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
return g_DotaUsermessageHelpers.GetPrototype(msg_type);
|
||||||
|
#elif SOURCE_ENGINE == SE_CSGO
|
||||||
|
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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;
|
MsgList *pList;
|
||||||
MsgIter iter;
|
MsgIter iter;
|
||||||
ListenerInfo *pInfo;
|
ListenerInfo *pInfo;
|
||||||
@@ -247,7 +470,7 @@ bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener
|
|||||||
for (iter=pList->begin(); iter!=pList->end(); iter++)
|
for (iter=pList->begin(); iter!=pList->end(); iter++)
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
if (pInfo->Callback == pListener)
|
if (pInfo->Callback == pListener && pInfo->IsNew == isNew)
|
||||||
{
|
{
|
||||||
if (pInfo->IsHooked)
|
if (pInfo->IsHooked)
|
||||||
{
|
{
|
||||||
@@ -272,14 +495,81 @@ void UserMessages::_DecRefCounter()
|
|||||||
{
|
{
|
||||||
if (--m_HookCount == 0)
|
if (--m_HookCount == 0)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
|
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
|
#else
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
|
||||||
|
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||||
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
OnStartMessage_Pre(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
|
||||||
|
#elif SOURCE_ENGINE == SE_CSGO
|
||||||
|
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_DOTA
|
||||||
|
OnStartMessage_Post(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
|
||||||
|
#elif SOURCE_ENGINE == SE_CSGO
|
||||||
|
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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 || SOURCE_ENGINE == SE_DOTA
|
||||||
|
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)
|
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
|
bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
|
||||||
bool is_hook_empty = m_msgHooks[msg_type].empty();
|
bool is_hook_empty = m_msgHooks[msg_type].empty();
|
||||||
@@ -288,7 +578,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
|||||||
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
|
||||||
{
|
{
|
||||||
m_InHook = false;
|
m_InHook = false;
|
||||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurId = msg_type;
|
m_CurId = msg_type;
|
||||||
@@ -298,42 +588,73 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
|||||||
|
|
||||||
if (!is_intercept_empty)
|
if (!is_intercept_empty)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
if (m_InterceptBuffer)
|
||||||
|
delete m_InterceptBuffer;
|
||||||
|
m_InterceptBuffer = GetMessagePrototype(msg_type)->New();
|
||||||
|
|
||||||
|
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
|
||||||
|
#else
|
||||||
m_InterceptBuffer.Reset();
|
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_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
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)
|
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (!m_InHook)
|
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 *);
|
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()
|
void UserMessages::OnMessageEnd_Post()
|
||||||
{
|
{
|
||||||
if (!m_InHook || m_BlockEndPost)
|
if (!m_InHook)
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
UM_RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgList *pList;
|
MsgList *pList;
|
||||||
MsgIter iter;
|
MsgIter iter;
|
||||||
ListenerInfo *pInfo;
|
ListenerInfo *pInfo;
|
||||||
|
|
||||||
|
m_InHook = false;
|
||||||
|
|
||||||
pList = &m_msgIntercepts[m_CurId];
|
pList = &m_msgIntercepts[m_CurId];
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
for (iter=pList->begin(); iter!=pList->end(); )
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
|
if (m_BlockEndPost && !pInfo->IsNew)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
pInfo->IsHooked = true;
|
pInfo->IsHooked = true;
|
||||||
pInfo->Callback->OnUserMessageSent(m_CurId);
|
pInfo->Callback->OnUserMessageSent(m_CurId);
|
||||||
|
if (pInfo->IsNew)
|
||||||
|
{
|
||||||
|
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
|
||||||
|
}
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
if (pInfo->KillMe)
|
||||||
{
|
{
|
||||||
@@ -347,14 +668,20 @@ void UserMessages::OnMessageEnd_Post()
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_InHook = false;
|
|
||||||
|
|
||||||
pList = &m_msgHooks[m_CurId];
|
pList = &m_msgHooks[m_CurId];
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
for (iter=pList->begin(); iter!=pList->end(); )
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
|
if (m_BlockEndPost && !pInfo->IsNew)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
pInfo->IsHooked = true;
|
pInfo->IsHooked = true;
|
||||||
pInfo->Callback->OnUserMessageSent(m_CurId);
|
pInfo->Callback->OnUserMessageSent(m_CurId);
|
||||||
|
if (pInfo->IsNew)
|
||||||
|
{
|
||||||
|
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
|
||||||
|
}
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
if (pInfo->KillMe)
|
||||||
{
|
{
|
||||||
@@ -373,7 +700,7 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
{
|
{
|
||||||
if (!m_InHook)
|
if (!m_InHook)
|
||||||
{
|
{
|
||||||
RETURN_META(MRES_IGNORED);
|
UM_RETURN_META(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgList *pList;
|
MsgList *pList;
|
||||||
@@ -389,7 +716,11 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
pInfo->IsHooked = true;
|
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);
|
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
|
||||||
|
#endif
|
||||||
|
|
||||||
intercepted = true;
|
intercepted = true;
|
||||||
|
|
||||||
@@ -435,43 +766,61 @@ void UserMessages::OnMessageEnd_Pre()
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handled)
|
if (!handled && intercepted)
|
||||||
{
|
|
||||||
goto supercede;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intercepted)
|
|
||||||
{
|
{
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
||||||
|
#else
|
||||||
bf_write *engine_bfw;
|
bf_write *engine_bfw;
|
||||||
|
#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);
|
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
|
||||||
|
#endif
|
||||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
||||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
||||||
ENGINE_CALL(MessageEnd)();
|
ENGINE_CALL(MessageEnd)();
|
||||||
|
#endif // SE_CSGO || SE_DOTA
|
||||||
}
|
}
|
||||||
|
|
||||||
pList = &m_msgHooks[m_CurId];
|
|
||||||
for (iter=pList->begin(); iter!=pList->end(); )
|
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
pInfo->IsHooked = true;
|
int size = m_OrigBuffer->ByteSize();
|
||||||
pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
|
uint8 *data = (uint8 *)stackalloc(size);
|
||||||
|
m_OrigBuffer->SerializePartialToArray(data, size);
|
||||||
|
|
||||||
if (pInfo->KillMe)
|
protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New();
|
||||||
|
pTempMsg->ParsePartialFromArray(data, size);
|
||||||
|
#else
|
||||||
|
bf_write *pTempMsg = m_OrigBuffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pList = &m_msgHooks[m_CurId];
|
||||||
|
for (iter=pList->begin(); iter!=pList->end(); )
|
||||||
{
|
{
|
||||||
iter = pList->erase(iter);
|
pInfo = (*iter);
|
||||||
m_FreeListeners.push(pInfo);
|
pInfo->IsHooked = true;
|
||||||
_DecRefCounter();
|
pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter);
|
||||||
continue;
|
|
||||||
|
if (pInfo->KillMe)
|
||||||
|
{
|
||||||
|
iter = pList->erase(iter);
|
||||||
|
m_FreeListeners.push(pInfo);
|
||||||
|
_DecRefCounter();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->IsHooked = false;
|
||||||
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
pInfo->IsHooked = false;
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
iter++;
|
delete pTempMsg;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||||
supercede:
|
supercede:
|
||||||
m_InHook = false;
|
|
||||||
m_BlockEndPost = true;
|
m_BlockEndPost = true;
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
UM_RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
|
|||||||
+70
-8
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,22 +32,44 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
||||||
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
|
||||||
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <IUserMessages.h>
|
#include <IUserMessages.h>
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "sm_trie.h"
|
#include <sm_stringhashmap.h>
|
||||||
|
#include "sm_stringutil.h"
|
||||||
#include "CellRecipientFilter.h"
|
#include "CellRecipientFilter.h"
|
||||||
|
#include "sm_globals.h"
|
||||||
|
#include <sh_list.h>
|
||||||
|
#include <sh_stack.h>
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
#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
|
#define INVALID_MESSAGE_ID -1
|
||||||
|
|
||||||
struct ListenerInfo
|
struct ListenerInfo
|
||||||
{
|
{
|
||||||
IUserMessageListener *Callback;
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
IProtobufUserMessageListener *Callback;
|
||||||
|
#else
|
||||||
|
IBitBufUserMessageListener *Callback;
|
||||||
|
#endif
|
||||||
bool IsHooked;
|
bool IsHooked;
|
||||||
bool KillMe;
|
bool KillMe;
|
||||||
|
bool IsNew;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef List<ListenerInfo *> MsgList;
|
typedef List<ListenerInfo *> MsgList;
|
||||||
@@ -69,30 +91,70 @@ public: //IUserMessages
|
|||||||
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
|
||||||
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
|
||||||
bool UnhookUserMessage(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 EndMessage();
|
||||||
|
bool HookUserMessage2(int msg_id,
|
||||||
|
IUserMessageListener *pListener,
|
||||||
|
bool intercept=false);
|
||||||
|
bool UnhookUserMessage2(int msg_id,
|
||||||
|
IUserMessageListener *pListener,
|
||||||
|
bool intercept=false);
|
||||||
|
UserMessageType GetUserMessageType() const;
|
||||||
public:
|
public:
|
||||||
|
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
|
||||||
|
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 || SOURCE_ENGINE == SE_DOTA
|
||||||
|
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
|
||||||
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type);
|
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type);
|
||||||
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type);
|
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type);
|
||||||
|
#endif
|
||||||
void OnMessageEnd_Pre();
|
void OnMessageEnd_Pre();
|
||||||
void OnMessageEnd_Post();
|
void OnMessageEnd_Post();
|
||||||
private:
|
private:
|
||||||
|
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||||
|
const protobuf::Message *GetMessagePrototype(int msg_type);
|
||||||
|
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();
|
void _DecRefCounter();
|
||||||
private:
|
private:
|
||||||
List<ListenerInfo *> m_msgHooks[255];
|
List<ListenerInfo *> m_msgHooks[255];
|
||||||
List<ListenerInfo *> m_msgIntercepts[255];
|
List<ListenerInfo *> m_msgIntercepts[255];
|
||||||
CStack<ListenerInfo *> m_FreeListeners;
|
CStack<ListenerInfo *> m_FreeListeners;
|
||||||
unsigned char m_pBase[2500];
|
|
||||||
IRecipientFilter *m_CurRecFilter;
|
IRecipientFilter *m_CurRecFilter;
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
|
unsigned char m_pBase[2500];
|
||||||
bf_write m_InterceptBuffer;
|
bf_write m_InterceptBuffer;
|
||||||
bf_write *m_OrigBuffer;
|
bf_write *m_OrigBuffer;
|
||||||
bf_read m_ReadBuffer;
|
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;
|
size_t m_HookCount;
|
||||||
bool m_InHook;
|
bool m_InHook;
|
||||||
bool m_BlockEndPost;
|
bool m_BlockEndPost;
|
||||||
|
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||||
bool m_FallbackSearch;
|
bool m_FallbackSearch;
|
||||||
|
|
||||||
Trie *m_Names;
|
StringHashMap<int> m_Names;
|
||||||
|
#endif
|
||||||
CellRecipientFilter m_CellRecFilter;
|
CellRecipientFilter m_CellRecFilter;
|
||||||
bool m_InExec;
|
bool m_InExec;
|
||||||
int m_CurFlags;
|
int m_CurFlags;
|
||||||
|
|||||||
+37
-23
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -35,9 +35,13 @@
|
|||||||
#include "concmd_cleaner.h"
|
#include "concmd_cleaner.h"
|
||||||
#include "sm_stringutil.h"
|
#include "sm_stringutil.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
|
#include "compat_wrappers.h"
|
||||||
|
|
||||||
#if defined ORANGEBOX_BUILD
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
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
|
#endif
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
@@ -50,29 +54,55 @@ struct ConCommandInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
List<ConCommandInfo *> tracked_bases;
|
List<ConCommandInfo *> tracked_bases;
|
||||||
|
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name);
|
ConCommandBase *FindConCommandBase(const char *name);
|
||||||
|
|
||||||
class ConCommandCleaner : public SMGlobalClass
|
class ConCommandCleaner : public SMGlobalClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#if defined ORANGEBOX_BUILD
|
|
||||||
void OnSourceModAllInitialized()
|
void OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
|
SH_ADD_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
|
||||||
|
SH_ADD_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
|
#else
|
||||||
|
SH_ADD_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnSourceModShutdown()
|
void OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||||
}
|
SH_REMOVE_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
|
||||||
|
SH_REMOVE_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
|
#else
|
||||||
|
SH_REMOVE_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkConCommandBase(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||||
|
while (listener)
|
||||||
|
{
|
||||||
|
listener->OnLinkConCommand(pBase);
|
||||||
|
listener = listener->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UnlinkConCommandBase(ConCommandBase *pBase)
|
void UnlinkConCommandBase(ConCommandBase *pBase)
|
||||||
{
|
{
|
||||||
ConCommandInfo *pInfo;
|
ConCommandInfo *pInfo;
|
||||||
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
||||||
|
|
||||||
|
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||||
|
while (listener)
|
||||||
|
{
|
||||||
|
listener->OnUnlinkConCommand(pBase);
|
||||||
|
listener = listener->next;
|
||||||
|
}
|
||||||
|
|
||||||
if (pBase)
|
if (pBase)
|
||||||
{
|
{
|
||||||
while (iter != tracked_bases.end())
|
while (iter != tracked_bases.end())
|
||||||
@@ -95,7 +125,7 @@ public:
|
|||||||
while (iter != tracked_bases.end())
|
while (iter != tracked_bases.end())
|
||||||
{
|
{
|
||||||
/* This is just god-awful! */
|
/* This is just god-awful! */
|
||||||
if (FindConCommandBase((*iter)->name) != (*iter)->pBase)
|
if (FindCommandBase((*iter)->name) != (*iter)->pBase)
|
||||||
{
|
{
|
||||||
pInfo = (*iter);
|
pInfo = (*iter);
|
||||||
iter = tracked_bases.erase(iter);
|
iter = tracked_bases.erase(iter);
|
||||||
@@ -143,22 +173,6 @@ public:
|
|||||||
}
|
}
|
||||||
} s_ConCmdTracker;
|
} s_ConCmdTracker;
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name)
|
|
||||||
{
|
|
||||||
const ConCommandBase *pBase = icvar->GetCommands();
|
|
||||||
|
|
||||||
while (pBase != NULL)
|
|
||||||
{
|
|
||||||
if (strcmp(pBase->GetName(), name) == 0)
|
|
||||||
{
|
|
||||||
return const_cast<ConCommandBase *>(pBase);
|
|
||||||
}
|
|
||||||
pBase = pBase->GetNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
|
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
|
||||||
{
|
{
|
||||||
s_ConCmdTracker.AddTarget(pBase, me);
|
s_ConCmdTracker.AddTarget(pBase, me);
|
||||||
|
|||||||
+23
-2
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -38,9 +38,30 @@ public:
|
|||||||
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
|
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConCommandBase *FindConCommandBase(const char *name);
|
|
||||||
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||||
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||||
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
|
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_
|
#endif //_INCLUDE_CONCMD_TRACKER_H_
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,718 @@
|
|||||||
|
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||||
|
//
|
||||||
|
// Purpose:
|
||||||
|
//
|
||||||
|
// $Workfile: $
|
||||||
|
// $Date: $
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// $NoKeywords: $
|
||||||
|
//===========================================================================//
|
||||||
|
|
||||||
|
#ifndef CONVAR_H
|
||||||
|
#define CONVAR_H
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "tier0/dbg.h"
|
||||||
|
#include "tier1/iconvar.h"
|
||||||
|
#include "tier1/utlvector.h"
|
||||||
|
#include "tier1/utlstring.h"
|
||||||
|
#include "icvar.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define FORCEINLINE_CVAR FORCEINLINE
|
||||||
|
#elif defined _LINUX || defined __APPLE__
|
||||||
|
#define FORCEINLINE_CVAR inline
|
||||||
|
#else
|
||||||
|
#error "implement me"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Forward declarations
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ConVar;
|
||||||
|
class CCommand;
|
||||||
|
class ConCommand;
|
||||||
|
class ConCommandBase;
|
||||||
|
struct characterset_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Any executable that wants to use ConVars need to implement one of
|
||||||
|
// these to hook up access to console variables.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class IConCommandBaseAccessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Flags is a combination of FCVAR flags in cvar.h.
|
||||||
|
// hOut is filled in with a handle to the variable.
|
||||||
|
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Helper method for console development
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#if defined( _X360 ) && !defined( _RETAIL )
|
||||||
|
void ConVar_PublishToVXConsole();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Called when a ConCommand needs to execute
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
typedef void ( *FnCommandCallbackV1_t )( void );
|
||||||
|
typedef void ( *FnCommandCallback_t )( const CCommand &command );
|
||||||
|
|
||||||
|
#define COMMAND_COMPLETION_MAXITEMS 64
|
||||||
|
#define COMMAND_COMPLETION_ITEM_LENGTH 64
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Interface version
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ICommandCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void CommandCallback( const CCommand &command ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ICommandCompletionCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: The base console invoked command/cvar interface
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ConCommandBase
|
||||||
|
{
|
||||||
|
friend class CCvar;
|
||||||
|
friend class ConVar;
|
||||||
|
friend class ConCommand;
|
||||||
|
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
|
||||||
|
friend void ConVar_PublishToVXConsole();
|
||||||
|
|
||||||
|
// FIXME: Remove when ConVar changes are done
|
||||||
|
friend class CDefaultCvar;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConCommandBase( void );
|
||||||
|
ConCommandBase( const char *pName, const char *pHelpString = 0,
|
||||||
|
int flags = 0 );
|
||||||
|
|
||||||
|
virtual ~ConCommandBase( void );
|
||||||
|
|
||||||
|
virtual bool IsCommand( void ) const;
|
||||||
|
|
||||||
|
// Check flag
|
||||||
|
virtual bool IsFlagSet( int flag ) const;
|
||||||
|
// Set flag
|
||||||
|
virtual void AddFlags( int flags );
|
||||||
|
// Remove flag
|
||||||
|
virtual void RemoveFlags( int flags );
|
||||||
|
// Get flags
|
||||||
|
virtual int GetFlags( void ) const;
|
||||||
|
|
||||||
|
// Return name of cvar
|
||||||
|
virtual const char *GetName( void ) const;
|
||||||
|
|
||||||
|
// Return help text for cvar
|
||||||
|
virtual const char *GetHelpText( void ) const;
|
||||||
|
|
||||||
|
// Deal with next pointer
|
||||||
|
const ConCommandBase *GetNext( void ) const;
|
||||||
|
ConCommandBase *GetNext( void );
|
||||||
|
|
||||||
|
inline void SetNext(ConCommandBase *pBase)
|
||||||
|
{
|
||||||
|
m_pNext = pBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsRegistered( void ) const;
|
||||||
|
|
||||||
|
// Returns the DLL identifier
|
||||||
|
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void Create( const char *pName, const char *pHelpString = 0,
|
||||||
|
int flags = 0 );
|
||||||
|
|
||||||
|
// Used internally by OneTimeInit to initialize/shutdown
|
||||||
|
virtual void Init();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
// Internal copy routine ( uses new operator from correct module )
|
||||||
|
char *CopyString( const char *from );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Next ConVar in chain
|
||||||
|
// Prior to register, it points to the next convar in the DLL.
|
||||||
|
// Once registered, though, m_pNext is reset to point to the next
|
||||||
|
// convar in the global list
|
||||||
|
ConCommandBase *m_pNext;
|
||||||
|
|
||||||
|
// Has the cvar been added to the global list?
|
||||||
|
bool m_bRegistered;
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
const char *m_pszName;
|
||||||
|
const char *m_pszHelpString;
|
||||||
|
|
||||||
|
// ConVar flags
|
||||||
|
int m_nFlags;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// ConVars add themselves to this list for the executable.
|
||||||
|
// Then ConVar_Register runs through all the console variables
|
||||||
|
// and registers them into a global list stored in vstdlib.dll
|
||||||
|
static ConCommandBase *s_pConCommandBases;
|
||||||
|
|
||||||
|
// ConVars in this executable use this 'global' to access values.
|
||||||
|
static IConCommandBaseAccessor *s_pAccessor;
|
||||||
|
public:
|
||||||
|
inline void SetFlags(int flags)
|
||||||
|
{
|
||||||
|
m_nFlags = flags;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Command tokenizer
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class CCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCommand();
|
||||||
|
CCommand( int nArgC, const char **ppArgV );
|
||||||
|
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
int ArgC() const;
|
||||||
|
const char **ArgV() const;
|
||||||
|
const char *ArgS() const; // All args that occur after the 0th arg, in string form
|
||||||
|
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
|
||||||
|
const char *operator[]( int nIndex ) const; // Gets at arguments
|
||||||
|
const char *Arg( int nIndex ) const; // Gets at arguments
|
||||||
|
|
||||||
|
// Helper functions to parse arguments to commands.
|
||||||
|
const char* FindArg( const char *pName ) const;
|
||||||
|
int FindArgInt( const char *pName, int nDefaultVal ) const;
|
||||||
|
|
||||||
|
static int MaxCommandLength();
|
||||||
|
static characterset_t* DefaultBreakSet();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COMMAND_MAX_ARGC = 64,
|
||||||
|
COMMAND_MAX_LENGTH = 512,
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_nArgc;
|
||||||
|
int m_nArgv0Size;
|
||||||
|
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
|
||||||
|
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
|
||||||
|
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline int CCommand::MaxCommandLength()
|
||||||
|
{
|
||||||
|
return COMMAND_MAX_LENGTH - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int CCommand::ArgC() const
|
||||||
|
{
|
||||||
|
return m_nArgc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char **CCommand::ArgV() const
|
||||||
|
{
|
||||||
|
return m_nArgc ? (const char**)m_ppArgv : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *CCommand::ArgS() const
|
||||||
|
{
|
||||||
|
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *CCommand::GetCommandString() const
|
||||||
|
{
|
||||||
|
return m_nArgc ? m_pArgSBuffer : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *CCommand::Arg( int nIndex ) const
|
||||||
|
{
|
||||||
|
// FIXME: Many command handlers appear to not be particularly careful
|
||||||
|
// about checking for valid argc range. For now, we're going to
|
||||||
|
// do the extra check and return an empty string if it's out of range
|
||||||
|
if ( nIndex < 0 || nIndex >= m_nArgc )
|
||||||
|
return "";
|
||||||
|
return m_ppArgv[nIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *CCommand::operator[]( int nIndex ) const
|
||||||
|
{
|
||||||
|
return Arg( nIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: The console invoked command
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ConCommand : public ConCommandBase
|
||||||
|
{
|
||||||
|
friend class CCvar;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef ConCommandBase BaseClass;
|
||||||
|
|
||||||
|
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
|
||||||
|
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
||||||
|
ConCommand( const char *pName, FnCommandCallback_t callback,
|
||||||
|
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
|
||||||
|
ConCommand( const char *pName, ICommandCallback *pCallback,
|
||||||
|
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
|
||||||
|
|
||||||
|
virtual ~ConCommand( void );
|
||||||
|
|
||||||
|
virtual bool IsCommand( void ) const;
|
||||||
|
|
||||||
|
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
|
||||||
|
|
||||||
|
virtual bool CanAutoComplete( void );
|
||||||
|
|
||||||
|
// Invoke the function
|
||||||
|
virtual void Dispatch( const CCommand &command );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// NOTE: To maintain backward compat, we have to be very careful:
|
||||||
|
// All public virtual methods must appear in the same order always
|
||||||
|
// since engine code will be calling into this code, which *does not match*
|
||||||
|
// in the mod code; it's using slightly different, but compatible versions
|
||||||
|
// of this class. Also: Be very careful about adding new fields to this class.
|
||||||
|
// Those fields will not exist in the version of this class that is instanced
|
||||||
|
// in mod code.
|
||||||
|
|
||||||
|
// Call this function when executing the command
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
||||||
|
FnCommandCallback_t m_fnCommandCallback;
|
||||||
|
ICommandCallback *m_pCommandCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FnCommandCompletionCallback m_fnCompletionCallback;
|
||||||
|
ICommandCompletionCallback *m_pCommandCompletionCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_bHasCompletionCallback : 1;
|
||||||
|
bool m_bUsingNewCommandCallback : 1;
|
||||||
|
bool m_bUsingCommandCallbackInterface : 1;
|
||||||
|
public:
|
||||||
|
inline FnCommandCallback_t GetCallback() const
|
||||||
|
{
|
||||||
|
return m_fnCommandCallback;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: A console variable
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ConVar : public ConCommandBase, public IConVar
|
||||||
|
{
|
||||||
|
friend class CCvar;
|
||||||
|
friend class ConVarRef;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef ConCommandBase BaseClass;
|
||||||
|
|
||||||
|
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
|
||||||
|
|
||||||
|
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||||
|
const char *pHelpString );
|
||||||
|
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||||
|
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
|
||||||
|
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||||
|
const char *pHelpString, FnChangeCallback_t callback );
|
||||||
|
ConVar( const char *pName, const char *pDefaultValue, int flags,
|
||||||
|
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
|
||||||
|
FnChangeCallback_t callback );
|
||||||
|
|
||||||
|
virtual ~ConVar( void );
|
||||||
|
|
||||||
|
virtual bool IsCommand( void ) const;
|
||||||
|
virtual bool IsFlagSet( int flag ) const;
|
||||||
|
virtual void AddFlags( int flags );
|
||||||
|
virtual int GetFlags( void ) const;
|
||||||
|
virtual const char *GetName( void ) const;
|
||||||
|
virtual const char* GetHelpText( void ) const;
|
||||||
|
virtual bool IsRegistered( void ) const;
|
||||||
|
|
||||||
|
// Install a change callback (there shouldn't already be one....)
|
||||||
|
void InstallChangeCallback( FnChangeCallback_t callback );
|
||||||
|
|
||||||
|
// Retrieve value
|
||||||
|
FORCEINLINE_CVAR float GetFloat( void ) const;
|
||||||
|
FORCEINLINE_CVAR int GetInt( void ) const;
|
||||||
|
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
|
||||||
|
FORCEINLINE_CVAR char const *GetString( void ) const;
|
||||||
|
|
||||||
|
// Used internally by OneTimeInit to initialize.
|
||||||
|
virtual void Init();
|
||||||
|
|
||||||
|
virtual const char *GetBaseName( void ) const;
|
||||||
|
virtual int GetSplitScreenPlayerSlot ( void ) const;
|
||||||
|
|
||||||
|
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
|
||||||
|
// from alloc/free across dll/exe boundaries.
|
||||||
|
|
||||||
|
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// True if it has a min/max setting
|
||||||
|
bool GetMin( float& minVal ) const;
|
||||||
|
bool GetMax( float& maxVal ) const;
|
||||||
|
const char *GetDefault( void ) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Called by CCvar when the value of a var is changing.
|
||||||
|
virtual void InternalSetValue(const char *value);
|
||||||
|
// 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 );
|
||||||
|
|
||||||
|
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
|
||||||
|
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
|
||||||
|
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// This either points to "this" or it points to the original declaration of a ConVar.
|
||||||
|
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
|
||||||
|
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
|
||||||
|
ConVar *m_pParent;
|
||||||
|
|
||||||
|
// Static data
|
||||||
|
const char *m_pszDefaultValue;
|
||||||
|
|
||||||
|
// Value
|
||||||
|
// Dynamically allocated
|
||||||
|
char *m_pszString;
|
||||||
|
int m_StringLength;
|
||||||
|
|
||||||
|
// Values
|
||||||
|
float m_fValue;
|
||||||
|
int m_nValue;
|
||||||
|
|
||||||
|
// Min/Max values
|
||||||
|
bool m_bHasMin;
|
||||||
|
float m_fMinVal;
|
||||||
|
bool m_bHasMax;
|
||||||
|
float m_fMaxVal;
|
||||||
|
|
||||||
|
// Call this function when ConVar changes
|
||||||
|
FnChangeCallback_t m_fnChangeCallback;
|
||||||
|
public:
|
||||||
|
inline FnChangeCallback_t GetCallback() const
|
||||||
|
{
|
||||||
|
return m_fnChangeCallback;
|
||||||
|
}
|
||||||
|
inline void SetMin(bool set, float min=0.0)
|
||||||
|
{
|
||||||
|
m_bHasMin = set;
|
||||||
|
m_fMinVal = min;
|
||||||
|
}
|
||||||
|
inline void SetMax(bool set, float max=0.0)
|
||||||
|
{
|
||||||
|
m_bHasMax = set;
|
||||||
|
m_fMaxVal = max;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return ConVar value as a float
|
||||||
|
// Output : float
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
|
||||||
|
{
|
||||||
|
return m_pParent->m_fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return ConVar value as an int
|
||||||
|
// Output : int
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
|
||||||
|
{
|
||||||
|
return m_pParent->m_nValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
||||||
|
// Output : const char *
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
|
||||||
|
{
|
||||||
|
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
|
||||||
|
return "FCVAR_NEVER_AS_STRING";
|
||||||
|
|
||||||
|
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Used to read/write convars that already exist (replaces the FindVar method)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ConVarRef
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConVarRef( const char *pName );
|
||||||
|
ConVarRef( const char *pName, bool bIgnoreMissing );
|
||||||
|
ConVarRef( IConVar *pConVar );
|
||||||
|
|
||||||
|
void Init( const char *pName, bool bIgnoreMissing );
|
||||||
|
bool IsValid() const;
|
||||||
|
bool IsFlagSet( int nFlags ) const;
|
||||||
|
IConVar *GetLinkedConVar();
|
||||||
|
|
||||||
|
// Get/Set value
|
||||||
|
float GetFloat( void ) const;
|
||||||
|
int GetInt( void ) const;
|
||||||
|
bool GetBool() const { return !!GetInt(); }
|
||||||
|
const char *GetString( void ) const;
|
||||||
|
|
||||||
|
void SetValue( const char *pValue );
|
||||||
|
void SetValue( float flValue );
|
||||||
|
void SetValue( int nValue );
|
||||||
|
void SetValue( bool bValue );
|
||||||
|
|
||||||
|
const char *GetName() const;
|
||||||
|
|
||||||
|
const char *GetDefault() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// High-speed method to read convar data
|
||||||
|
IConVar *m_pConVar;
|
||||||
|
ConVar *m_pConVarState;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Did we find an existing convar of that name?
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
|
||||||
|
{
|
||||||
|
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
|
||||||
|
{
|
||||||
|
return m_pConVar;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
|
||||||
|
{
|
||||||
|
return m_pConVar->GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return ConVar value as a float
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
|
||||||
|
{
|
||||||
|
return m_pConVarState->m_fValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return ConVar value as an int
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
|
||||||
|
{
|
||||||
|
return m_pConVarState->m_nValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
|
||||||
|
{
|
||||||
|
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
|
||||||
|
return m_pConVarState->m_pszString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
|
||||||
|
{
|
||||||
|
m_pConVar->SetValue( pValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
|
||||||
|
{
|
||||||
|
m_pConVar->SetValue( flValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
|
||||||
|
{
|
||||||
|
m_pConVar->SetValue( nValue );
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
|
||||||
|
{
|
||||||
|
m_pConVar->SetValue( bValue ? 1 : 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
|
||||||
|
{
|
||||||
|
return m_pConVarState->m_pszDefaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Called by the framework to register ConCommands with the ICVar
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
|
||||||
|
void ConVar_Unregister( );
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Utility methods
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ConVar_PrintFlags( const ConCommandBase *var );
|
||||||
|
void ConVar_PrintDescription( const ConCommandBase *pVar );
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Utility class to quickly allow ConCommands to call member methods
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable : 4355 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template< class T >
|
||||||
|
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
|
||||||
|
{
|
||||||
|
typedef ConCommand BaseClass;
|
||||||
|
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
|
||||||
|
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
|
||||||
|
|
||||||
|
public:
|
||||||
|
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
|
||||||
|
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
|
||||||
|
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
|
||||||
|
{
|
||||||
|
m_pOwner = pOwner;
|
||||||
|
m_Func = callback;
|
||||||
|
m_CompletionFunc = completionFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CConCommandMemberAccessor()
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetOwner( T* pOwner )
|
||||||
|
{
|
||||||
|
m_pOwner = pOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void CommandCallback( const CCommand &command )
|
||||||
|
{
|
||||||
|
Assert( m_pOwner && m_Func );
|
||||||
|
(m_pOwner->*m_Func)( command );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
|
||||||
|
{
|
||||||
|
Assert( m_pOwner && m_CompletionFunc );
|
||||||
|
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* m_pOwner;
|
||||||
|
FnMemberCommandCallback_t m_Func;
|
||||||
|
FnMemberCommandCompletionCallback_t m_CompletionFunc;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning ( default : 4355 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Utility macros to quicky generate a simple console command
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define CON_COMMAND( name, description ) \
|
||||||
|
static void name( const CCommand &args ); \
|
||||||
|
static ConCommand name##_command( #name, name, description ); \
|
||||||
|
static void name( const CCommand &args )
|
||||||
|
|
||||||
|
#define CON_COMMAND_F( name, description, flags ) \
|
||||||
|
static void name( const CCommand &args ); \
|
||||||
|
static ConCommand name##_command( #name, name, description, flags ); \
|
||||||
|
static void name( const CCommand &args )
|
||||||
|
|
||||||
|
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
|
||||||
|
static void name( const CCommand &args ); \
|
||||||
|
static ConCommand name##_command( #name, name, description, flags, completion ); \
|
||||||
|
static void name( const CCommand &args )
|
||||||
|
|
||||||
|
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
|
||||||
|
void _funcname( const CCommand &args ); \
|
||||||
|
static ConCommand name##_command( #name, _funcname, description ); \
|
||||||
|
void _funcname( const CCommand &args )
|
||||||
|
|
||||||
|
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
|
||||||
|
void _funcname( const CCommand &args ); \
|
||||||
|
static ConCommand name##_command( #name, _funcname, description, flags ); \
|
||||||
|
void _funcname( const CCommand &args )
|
||||||
|
|
||||||
|
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
|
||||||
|
void _funcname( const CCommand &args ); \
|
||||||
|
friend class CCommandMemberInitializer_##_funcname; \
|
||||||
|
class CCommandMemberInitializer_##_funcname \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
|
||||||
|
{ \
|
||||||
|
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
|
||||||
|
} \
|
||||||
|
private: \
|
||||||
|
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CONVAR_H
|
||||||
+1
-1
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define FORCEINLINE_CVAR FORCEINLINE
|
#define FORCEINLINE_CVAR FORCEINLINE
|
||||||
#elif _LINUX
|
#elif defined _LINUX || defined __APPLE__
|
||||||
#define FORCEINLINE_CVAR inline
|
#define FORCEINLINE_CVAR inline
|
||||||
#else
|
#else
|
||||||
#error "implement me"
|
#error "implement me"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+64
-5
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -30,20 +30,79 @@
|
|||||||
*/
|
*/
|
||||||
#include "frame_hooks.h"
|
#include "frame_hooks.h"
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
#include "Database.h"
|
|
||||||
#include "HalfLife2.h"
|
#include "HalfLife2.h"
|
||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "MenuStyle_Radio.h"
|
#include "MenuStyle_Radio.h"
|
||||||
#include "PlayerManager.h"
|
#include "PlayerManager.h"
|
||||||
|
#include "CoreConfig.h"
|
||||||
|
#include <sm_queue.h>
|
||||||
|
#include <IThreader.h>
|
||||||
|
#include "sourcemod.h"
|
||||||
|
|
||||||
float g_LastMenuTime = 0.0f;
|
static IMutex *frame_mutex;
|
||||||
float g_LastAuthCheck = 0.0f;
|
static Queue<FrameAction> *frame_queue;
|
||||||
|
static Queue<FrameAction> *frame_actions;
|
||||||
|
static float g_LastMenuTime = 0.0f;
|
||||||
|
static float g_LastAuthCheck = 0.0f;
|
||||||
|
bool g_PendingInternalPush = false;
|
||||||
|
|
||||||
|
class FrameActionInit : public SMGlobalClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void OnSourceModAllInitialized()
|
||||||
|
{
|
||||||
|
frame_queue = new Queue<FrameAction>();
|
||||||
|
frame_actions = new Queue<FrameAction>();
|
||||||
|
frame_mutex = g_pThreader->MakeMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnSourceModShutdown()
|
||||||
|
{
|
||||||
|
delete frame_queue;
|
||||||
|
delete frame_actions;
|
||||||
|
frame_mutex->DestroyThis();
|
||||||
|
}
|
||||||
|
} s_FrameActionInit;
|
||||||
|
|
||||||
|
void AddFrameAction(const FrameAction & action)
|
||||||
|
{
|
||||||
|
frame_mutex->Lock();
|
||||||
|
frame_queue->push(action);
|
||||||
|
frame_mutex->Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void RunFrameHooks(bool simulating)
|
void RunFrameHooks(bool simulating)
|
||||||
{
|
{
|
||||||
|
/* It's okay if this check races. */
|
||||||
|
if (frame_queue->size())
|
||||||
|
{
|
||||||
|
Queue<FrameAction> *temp;
|
||||||
|
|
||||||
|
/* Very quick lock to move queue/actions back and forth */
|
||||||
|
frame_mutex->Lock();
|
||||||
|
temp = frame_queue;
|
||||||
|
frame_queue = frame_actions;
|
||||||
|
frame_actions = temp;
|
||||||
|
frame_mutex->Unlock();
|
||||||
|
|
||||||
|
/* The server will now be adding to the other queue, so we can process events. */
|
||||||
|
while (!frame_actions->empty())
|
||||||
|
{
|
||||||
|
FrameAction &item = frame_actions->first();
|
||||||
|
frame_actions->pop();
|
||||||
|
item.action(item.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Frame based hooks */
|
/* Frame based hooks */
|
||||||
g_DBMan.RunFrame();
|
|
||||||
g_HL2.ProcessFakeCliCmdQueue();
|
g_HL2.ProcessFakeCliCmdQueue();
|
||||||
|
g_HL2.ProcessDelayedKicks();
|
||||||
|
|
||||||
|
if (g_PendingInternalPush)
|
||||||
|
{
|
||||||
|
SM_InternalCmdTrigger();
|
||||||
|
}
|
||||||
|
|
||||||
g_SourceMod.ProcessGameFrameHooks(simulating);
|
g_SourceMod.ProcessGameFrameHooks(simulating);
|
||||||
|
|
||||||
float curtime = *g_pUniversalTime;
|
float curtime = *g_pUniversalTime;
|
||||||
|
|||||||
+17
-1
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,6 +32,22 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
#ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
||||||
#define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
#define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
||||||
|
|
||||||
|
#include <ISourceMod.h>
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
struct FrameAction
|
||||||
|
{
|
||||||
|
FrameAction(FRAMEACTION a, void *d) : data(d), action(a)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void *data;
|
||||||
|
FRAMEACTION action;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern bool g_PendingInternalPush;
|
||||||
|
|
||||||
|
void AddFrameAction(const FrameAction & action);
|
||||||
void RunFrameHooks(bool simulating);
|
void RunFrameHooks(bool simulating);
|
||||||
|
|
||||||
#endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
#endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ADTFactory.h"
|
#include "ADTFactory.h"
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "ShareSys.h"
|
#include "ShareSys.h"
|
||||||
|
|
||||||
ADTFactory g_AdtFactory;
|
ADTFactory g_AdtFactory;
|
||||||
@@ -57,32 +56,30 @@ IBasicTrie *ADTFactory::CreateBasicTrie()
|
|||||||
|
|
||||||
BaseTrie::BaseTrie()
|
BaseTrie::BaseTrie()
|
||||||
{
|
{
|
||||||
m_pTrie = sm_trie_create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseTrie::~BaseTrie()
|
BaseTrie::~BaseTrie()
|
||||||
{
|
{
|
||||||
sm_trie_destroy(m_pTrie);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTrie::Insert(const char *key, void *value)
|
bool BaseTrie::Insert(const char *key, void *value)
|
||||||
{
|
{
|
||||||
return sm_trie_insert(m_pTrie, key, value);
|
return map_.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTrie::Retrieve(const char *key, void **value)
|
bool BaseTrie::Retrieve(const char *key, void **value)
|
||||||
{
|
{
|
||||||
return sm_trie_retrieve(m_pTrie, key, value);
|
return map_.retrieve(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTrie::Delete(const char *key)
|
bool BaseTrie::Delete(const char *key)
|
||||||
{
|
{
|
||||||
return sm_trie_delete(m_pTrie, key);
|
return map_.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTrie::Clear()
|
void BaseTrie::Clear()
|
||||||
{
|
{
|
||||||
sm_trie_clear(m_pTrie);
|
map_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTrie::Destroy()
|
void BaseTrie::Destroy()
|
||||||
@@ -92,5 +89,5 @@ void BaseTrie::Destroy()
|
|||||||
|
|
||||||
bool BaseTrie::Replace(const char *key, void *value)
|
bool BaseTrie::Replace(const char *key, void *value)
|
||||||
{
|
{
|
||||||
return sm_trie_replace(m_pTrie, key, value);
|
return map_.replace(key, value);
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
|
||||||
|
|
||||||
#include <IADTFactory.h>
|
#include <IADTFactory.h>
|
||||||
#include "sm_globals.h"
|
#include "common_logic.h"
|
||||||
#include "sm_trie.h"
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
virtual void Clear();
|
virtual void Clear();
|
||||||
virtual void Destroy();
|
virtual void Destroy();
|
||||||
private:
|
private:
|
||||||
Trie *m_pTrie;
|
StringHashMap<void *> map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ADTFactory :
|
class ADTFactory :
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||||
|
import os
|
||||||
|
|
||||||
|
binary = SM.Library(builder, 'sourcemod.logic')
|
||||||
|
binary.compiler.cxxincludes += [
|
||||||
|
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||||
|
os.path.join(builder.sourcePath, 'public'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
||||||
|
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||||
|
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||||
|
]
|
||||||
|
binary.compiler.defines += [
|
||||||
|
'SM_DEFAULT_THREADER',
|
||||||
|
'SM_LOGIC'
|
||||||
|
]
|
||||||
|
|
||||||
|
if builder.target_platform == 'linux':
|
||||||
|
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||||
|
elif builder.target_platform == 'mac':
|
||||||
|
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||||
|
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||||
|
|
||||||
|
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
|
||||||
|
binary.compiler.cxxflags += ['-fno-rtti']
|
||||||
|
elif binary.compiler.vendor == 'msvc':
|
||||||
|
binary.compiler.cxxflags += ['/GR-']
|
||||||
|
|
||||||
|
binary.sources += [
|
||||||
|
'common_logic.cpp',
|
||||||
|
'smn_adt_array.cpp',
|
||||||
|
'smn_sorting.cpp',
|
||||||
|
'smn_maplists.cpp',
|
||||||
|
'ADTFactory.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',
|
||||||
|
'smn_filesystem.cpp',
|
||||||
|
'stringutil.cpp',
|
||||||
|
'Translator.cpp',
|
||||||
|
'PhraseCollection.cpp',
|
||||||
|
'smn_lang.cpp',
|
||||||
|
'smn_string.cpp',
|
||||||
|
'smn_handles.cpp',
|
||||||
|
'smn_datapacks.cpp',
|
||||||
|
'smn_gameconfigs.cpp',
|
||||||
|
'smn_fakenatives.cpp',
|
||||||
|
'GameConfigs.cpp',
|
||||||
|
'sm_crc32.cpp',
|
||||||
|
'smn_profiler.cpp',
|
||||||
|
'ShareSys.cpp',
|
||||||
|
'PluginSys.cpp',
|
||||||
|
'HandleSys.cpp',
|
||||||
|
'NativeOwner.cpp',
|
||||||
|
'NativeInvoker.cpp',
|
||||||
|
'ExtensionSys.cpp',
|
||||||
|
'DebugReporter.cpp',
|
||||||
|
'Database.cpp',
|
||||||
|
'smn_database.cpp',
|
||||||
|
'ForwardSys.cpp',
|
||||||
|
'AdminCache.cpp',
|
||||||
|
'sm_trie.cpp',
|
||||||
|
'smn_console.cpp',
|
||||||
|
]
|
||||||
|
if builder.target_platform == 'windows':
|
||||||
|
binary.sources += ['thread/WinThreads.cpp']
|
||||||
|
else:
|
||||||
|
binary.sources += ['thread/PosixThreads.cpp']
|
||||||
|
|
||||||
|
SM.binaries += [builder.Add(binary)]
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,201 +1,226 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* 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
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
* Free Software Foundation.
|
* Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* 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
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
* details.
|
* details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
* 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
|
* 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
|
* "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
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
* this exception to all derivative works. AlliedModders LLC defines further
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
*
|
*
|
||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
||||||
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
||||||
|
|
||||||
#include "sm_memtable.h"
|
#include "common_logic.h"
|
||||||
#include <sm_trie.h>
|
#include <IAdminSystem.h>
|
||||||
#include <sh_list.h>
|
#include "sm_memtable.h"
|
||||||
#include <sh_string.h>
|
#include <sm_trie.h>
|
||||||
#include <IAdminSystem.h>
|
#include <sh_list.h>
|
||||||
#include "sm_globals.h"
|
#include <sh_string.h>
|
||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
using namespace SourceHook;
|
#include <sm_namehashset.h>
|
||||||
|
|
||||||
#define GRP_MAGIC_SET 0xDEADFADE
|
using namespace SourceHook;
|
||||||
#define GRP_MAGIC_UNSET 0xFACEFACE
|
|
||||||
#define USR_MAGIC_SET 0xDEADFACE
|
#define GRP_MAGIC_SET 0xDEADFADE
|
||||||
#define USR_MAGIC_UNSET 0xFADEDEAD
|
#define GRP_MAGIC_UNSET 0xFACEFACE
|
||||||
|
#define USR_MAGIC_SET 0xDEADFACE
|
||||||
struct AdminGroup
|
#define USR_MAGIC_UNSET 0xFADEDEAD
|
||||||
{
|
|
||||||
uint32_t magic; /* Magic flag, for memory validation (ugh) */
|
typedef StringHashMap<OverrideRule> OverrideMap;
|
||||||
unsigned int immunity_level; /* Immunity level */
|
|
||||||
/* Immune from target table (-1 = nonexistent)
|
struct AdminGroup
|
||||||
* [0] = number of entries
|
{
|
||||||
* [1...N] = immune targets
|
uint32_t magic; /* Magic flag, for memory validation (ugh) */
|
||||||
*/
|
unsigned int immunity_level; /* Immunity level */
|
||||||
int immune_table;
|
/* Immune from target table (-1 = nonexistent)
|
||||||
Trie *pCmdTable; /* Command override table (can be NULL) */
|
* [0] = number of entries
|
||||||
Trie *pCmdGrpTable; /* Command group override table (can be NULL) */
|
* [1...N] = immune targets
|
||||||
int next_grp; /* Next group in the chain */
|
*/
|
||||||
int prev_grp; /* Previous group in the chain */
|
int immune_table;
|
||||||
int nameidx; /* Name */
|
OverrideMap *pCmdTable; /* Command override table (can be NULL) */
|
||||||
FlagBits addflags; /* Additive flags */
|
OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */
|
||||||
};
|
int next_grp; /* Next group in the chain */
|
||||||
|
int prev_grp; /* Previous group in the chain */
|
||||||
struct AuthMethod
|
int nameidx; /* Name */
|
||||||
{
|
FlagBits addflags; /* Additive flags */
|
||||||
String name;
|
};
|
||||||
Trie *table;
|
|
||||||
};
|
struct AuthMethod
|
||||||
|
{
|
||||||
struct UserAuth
|
String name;
|
||||||
{
|
StringHashMap<AdminId> identities;
|
||||||
unsigned int index; /* Index into auth table */
|
|
||||||
int identidx; /* Index into the string table */
|
AuthMethod(const char *name)
|
||||||
};
|
: name(name)
|
||||||
|
{
|
||||||
struct AdminUser
|
}
|
||||||
{
|
|
||||||
uint32_t magic; /* Magic flag, for memory validation */
|
static inline bool matches(const char *name, const AuthMethod *method)
|
||||||
FlagBits flags; /* Flags */
|
{
|
||||||
FlagBits eflags; /* Effective flags */
|
return strcmp(name, method->name.c_str()) == 0;
|
||||||
int nameidx; /* Name index */
|
}
|
||||||
int password; /* Password index */
|
};
|
||||||
unsigned int grp_count; /* Number of groups */
|
|
||||||
unsigned int grp_size; /* Size of groups table */
|
struct UserAuth
|
||||||
int grp_table; /* Group table itself */
|
{
|
||||||
int next_user; /* Next user in the list */
|
unsigned int index; /* Index into auth table */
|
||||||
int prev_user; /* Previous user in the list */
|
int identidx; /* Index into the string table */
|
||||||
UserAuth auth; /* Auth method for this user */
|
};
|
||||||
unsigned int immunity_level; /* Immunity level */
|
|
||||||
unsigned int serialchange; /* Serial # for changes */
|
struct AdminUser
|
||||||
};
|
{
|
||||||
|
uint32_t magic; /* Magic flag, for memory validation */
|
||||||
class AdminCache :
|
FlagBits flags; /* Flags */
|
||||||
public IAdminSystem,
|
FlagBits eflags; /* Effective flags */
|
||||||
public SMGlobalClass
|
int nameidx; /* Name index */
|
||||||
{
|
int password; /* Password index */
|
||||||
public:
|
unsigned int grp_count; /* Number of groups */
|
||||||
AdminCache();
|
unsigned int grp_size; /* Size of groups table */
|
||||||
~AdminCache();
|
int grp_table; /* Group table itself */
|
||||||
public: //SMGlobalClass
|
int next_user; /* Next user in the list */
|
||||||
void OnSourceModStartup(bool late);
|
int prev_user; /* Previous user in the list */
|
||||||
void OnSourceModAllInitialized();
|
UserAuth auth; /* Auth method for this user */
|
||||||
void OnSourceModLevelChange(const char *mapName);
|
unsigned int immunity_level; /* Immunity level */
|
||||||
void OnSourceModShutdown();
|
unsigned int serialchange; /* Serial # for changes */
|
||||||
void OnSourceModPluginsLoaded();
|
};
|
||||||
public: //IAdminSystem
|
|
||||||
/** Command cache stuff */
|
class AdminCache :
|
||||||
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
|
public IAdminSystem,
|
||||||
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
|
public SMGlobalClass
|
||||||
void UnsetCommandOverride(const char *cmd, OverrideType type);
|
{
|
||||||
/** Group cache stuff */
|
public:
|
||||||
GroupId AddGroup(const char *group_name);
|
AdminCache();
|
||||||
GroupId FindGroupByName(const char *group_name);
|
~AdminCache();
|
||||||
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
|
public: //SMGlobalClass
|
||||||
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
|
void OnSourceModStartup(bool late);
|
||||||
FlagBits GetGroupAddFlags(GroupId id);
|
void OnSourceModAllInitialized();
|
||||||
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
|
void OnSourceModLevelChange(const char *mapName);
|
||||||
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
|
void OnSourceModShutdown();
|
||||||
void InvalidateGroup(GroupId id);
|
void OnSourceModPluginsLoaded();
|
||||||
void AddGroupImmunity(GroupId id, GroupId other_id);
|
public: //IAdminSystem
|
||||||
unsigned int GetGroupImmunityCount(GroupId id);
|
/** Command cache stuff */
|
||||||
GroupId GetGroupImmunity(GroupId id, unsigned int number);
|
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
|
||||||
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
|
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
|
||||||
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
|
void UnsetCommandOverride(const char *cmd, OverrideType type);
|
||||||
void DumpAdminCache(AdminCachePart part, bool rebuild);
|
/** Group cache stuff */
|
||||||
void AddAdminListener(IAdminListener *pListener);
|
GroupId AddGroup(const char *group_name);
|
||||||
void RemoveAdminListener(IAdminListener *pListener);
|
GroupId FindGroupByName(const char *group_name);
|
||||||
/** User stuff */
|
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
|
||||||
void RegisterAuthIdentType(const char *name);
|
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
|
||||||
AdminId CreateAdmin(const char *name);
|
FlagBits GetGroupAddFlags(GroupId id);
|
||||||
const char *GetAdminName(AdminId id);
|
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
|
||||||
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
|
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
|
||||||
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
|
void InvalidateGroup(GroupId id);
|
||||||
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
|
void AddGroupImmunity(GroupId id, GroupId other_id);
|
||||||
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
|
unsigned int GetGroupImmunityCount(GroupId id);
|
||||||
bool AdminInheritGroup(AdminId id, GroupId gid);
|
GroupId GetGroupImmunity(GroupId id, unsigned int number);
|
||||||
unsigned int GetAdminGroupCount(AdminId id);
|
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
|
||||||
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
|
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
|
||||||
void SetAdminPassword(AdminId id, const char *password);
|
void DumpAdminCache(AdminCachePart part, bool rebuild);
|
||||||
const char *GetAdminPassword(AdminId id);
|
void AddAdminListener(IAdminListener *pListener);
|
||||||
AdminId FindAdminByIdentity(const char *auth, const char *identity);
|
void RemoveAdminListener(IAdminListener *pListener);
|
||||||
bool InvalidateAdmin(AdminId id);
|
/** User stuff */
|
||||||
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
|
void RegisterAuthIdentType(const char *name);
|
||||||
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
|
AdminId CreateAdmin(const char *name);
|
||||||
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
|
const char *GetAdminName(AdminId id);
|
||||||
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
|
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
|
||||||
bool CheckAdminFlags(AdminId id, FlagBits bits);
|
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
|
||||||
bool CanAdminTarget(AdminId id, AdminId target);
|
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
|
||||||
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
|
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
|
||||||
bool FindFlag(const char *str, AdminFlag *pFlag);
|
bool AdminInheritGroup(AdminId id, GroupId gid);
|
||||||
bool FindFlag(char c, AdminFlag *pAdmFlag);
|
unsigned int GetAdminGroupCount(AdminId id);
|
||||||
FlagBits ReadFlagString(const char *flags, const char **end);
|
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
|
||||||
unsigned int GetAdminSerialChange(AdminId id);
|
void SetAdminPassword(AdminId id, const char *password);
|
||||||
bool CanAdminUseCommand(int client, const char *cmd);
|
const char *GetAdminPassword(AdminId id);
|
||||||
const char *GetGroupName(GroupId gid);
|
AdminId FindAdminByIdentity(const char *auth, const char *identity);
|
||||||
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
|
bool InvalidateAdmin(AdminId id);
|
||||||
unsigned int GetGroupImmunityLevel(GroupId gid);
|
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
|
||||||
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
|
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
|
||||||
unsigned int GetAdminImmunityLevel(AdminId id);
|
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
|
||||||
bool CheckAccess(int client,
|
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
|
||||||
const char *cmd,
|
bool CheckAdminFlags(AdminId id, FlagBits bits);
|
||||||
FlagBits flags,
|
bool CanAdminTarget(AdminId id, AdminId target);
|
||||||
bool override_only);
|
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
|
||||||
public:
|
bool FindFlag(const char *str, AdminFlag *pFlag);
|
||||||
bool IsValidAdmin(AdminId id);
|
bool FindFlag(char c, AdminFlag *pAdmFlag);
|
||||||
private:
|
FlagBits ReadFlagString(const char *flags, const char **end);
|
||||||
void _UnsetCommandOverride(const char *cmd);
|
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
|
||||||
void _UnsetCommandGroupOverride(const char *group);
|
unsigned int GetAdminSerialChange(AdminId id);
|
||||||
void InvalidateGroupCache();
|
bool CanAdminUseCommand(int client, const char *cmd);
|
||||||
void InvalidateAdminCache(bool unlink_admins);
|
const char *GetGroupName(GroupId gid);
|
||||||
void DumpCommandOverrideCache(OverrideType type);
|
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
|
||||||
Trie *GetMethodByIndex(unsigned int index);
|
unsigned int GetGroupImmunityLevel(GroupId gid);
|
||||||
bool GetMethodIndex(const char *name, unsigned int *_index);
|
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
|
||||||
void NameFlag(const char *str, AdminFlag flag);
|
unsigned int GetAdminImmunityLevel(AdminId id);
|
||||||
public:
|
bool CheckAccess(int client,
|
||||||
BaseStringTable *m_pStrings;
|
const char *cmd,
|
||||||
BaseMemTable *m_pMemory;
|
FlagBits flags,
|
||||||
Trie *m_pCmdOverrides;
|
bool override_only);
|
||||||
Trie *m_pCmdGrpOverrides;
|
bool FindFlagChar(AdminFlag flag, char *c);
|
||||||
int m_FirstGroup;
|
bool IsValidAdmin(AdminId id);
|
||||||
int m_LastGroup;
|
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags);
|
||||||
int m_FreeGroupList;
|
public:
|
||||||
Trie *m_pGroups;
|
void DumpCache(FILE *fp);
|
||||||
List<IAdminListener *> m_hooks;
|
AdminGroup *GetGroup(GroupId gid);
|
||||||
List<AuthMethod> m_AuthMethods;
|
AdminUser *GetUser(AdminId id);
|
||||||
Trie *m_pAuthTables;
|
const char *GetString(int idx);
|
||||||
IForward *m_pCacheFwd;
|
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
|
||||||
int m_FirstUser;
|
private:
|
||||||
int m_LastUser;
|
void _UnsetCommandOverride(const char *cmd);
|
||||||
int m_FreeUserList;
|
void _UnsetCommandGroupOverride(const char *group);
|
||||||
bool m_InvalidatingAdmins;
|
void InvalidateGroupCache();
|
||||||
bool m_destroying;
|
void InvalidateAdminCache(bool unlink_admins);
|
||||||
Trie *m_pLevelNames;
|
void DumpCommandOverrideCache(OverrideType type);
|
||||||
};
|
AuthMethod *GetMethodByIndex(unsigned int index);
|
||||||
|
bool GetMethodIndex(const char *name, unsigned int *_index);
|
||||||
extern AdminCache g_Admins;
|
const char *GetMethodName(unsigned int index);
|
||||||
|
void NameFlag(const char *str, AdminFlag flag);
|
||||||
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
public:
|
||||||
|
typedef StringHashMap<FlagBits> FlagMap;
|
||||||
|
|
||||||
|
BaseStringTable *m_pStrings;
|
||||||
|
BaseMemTable *m_pMemory;
|
||||||
|
FlagMap m_CmdOverrides;
|
||||||
|
FlagMap m_CmdGrpOverrides;
|
||||||
|
int m_FirstGroup;
|
||||||
|
int m_LastGroup;
|
||||||
|
int m_FreeGroupList;
|
||||||
|
StringHashMap<GroupId> m_Groups;
|
||||||
|
List<IAdminListener *> m_hooks;
|
||||||
|
List<AuthMethod *> m_AuthMethods;
|
||||||
|
NameHashSet<AuthMethod *> m_AuthTables;
|
||||||
|
IForward *m_pCacheFwd;
|
||||||
|
int m_FirstUser;
|
||||||
|
int m_LastUser;
|
||||||
|
int m_FreeUserList;
|
||||||
|
bool m_InvalidatingAdmins;
|
||||||
|
bool m_destroying;
|
||||||
|
StringHashMap<AdminFlag> m_LevelNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern AdminCache g_Admins;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -29,7 +29,10 @@
|
|||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <malloc.h>
|
#ifndef _INCLUDE_SOURCEMOD_CELLARRAY_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_CELLARRAY_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern HandleType_t htCellArray;
|
extern HandleType_t htCellArray;
|
||||||
@@ -40,14 +43,17 @@ public:
|
|||||||
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
|
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~CellArray()
|
~CellArray()
|
||||||
{
|
{
|
||||||
free(m_Data);
|
free(m_Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const
|
size_t size() const
|
||||||
{
|
{
|
||||||
return m_Size;
|
return m_Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t *push()
|
cell_t *push()
|
||||||
{
|
{
|
||||||
if (!GrowIfNeeded(1))
|
if (!GrowIfNeeded(1))
|
||||||
@@ -58,18 +64,22 @@ public:
|
|||||||
m_Size++;
|
m_Size++;
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t *at(size_t b) const
|
cell_t *at(size_t b) const
|
||||||
{
|
{
|
||||||
return &m_Data[b * m_BlockSize];
|
return &m_Data[b * m_BlockSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t blocksize() const
|
size_t blocksize() const
|
||||||
{
|
{
|
||||||
return m_BlockSize;
|
return m_BlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
m_Size = 0;
|
m_Size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool swap(size_t item1, size_t item2)
|
bool swap(size_t item1, size_t item2)
|
||||||
{
|
{
|
||||||
/* Make sure there is extra space available */
|
/* Make sure there is extra space available */
|
||||||
@@ -90,6 +100,7 @@ public:
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(size_t index)
|
void remove(size_t index)
|
||||||
{
|
{
|
||||||
/* If we're at the end, take the easy way out */
|
/* If we're at the end, take the easy way out */
|
||||||
@@ -107,6 +118,7 @@ public:
|
|||||||
|
|
||||||
m_Size--;
|
m_Size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t *insert_at(size_t index)
|
cell_t *insert_at(size_t index)
|
||||||
{
|
{
|
||||||
/* Make sure it'll fit */
|
/* Make sure it'll fit */
|
||||||
@@ -124,6 +136,7 @@ public:
|
|||||||
|
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool resize(size_t count)
|
bool resize(size_t count)
|
||||||
{
|
{
|
||||||
if (count <= m_Size)
|
if (count <= m_Size)
|
||||||
@@ -132,7 +145,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!GrowIfNeeded(count - m_Size))
|
if (!GrowIfNeeded(count - m_Size))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -194,3 +207,6 @@ private:
|
|||||||
size_t m_AllocSize;
|
size_t m_AllocSize;
|
||||||
size_t m_Size;
|
size_t m_Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* _INCLUDE_SOURCEMOD_CELLARRAY_H_ */
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -30,14 +30,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
|
#include "ISourceMod.h"
|
||||||
#include "HandleSys.h"
|
#include "HandleSys.h"
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "sourcemod.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "ExtensionSys.h"
|
#include "ExtensionSys.h"
|
||||||
|
#include "PluginSys.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ThreadSupport.h"
|
#include <IThreader.h>
|
||||||
|
|
||||||
#define DBPARSE_LEVEL_NONE 0
|
#define DBPARSE_LEVEL_NONE 0
|
||||||
#define DBPARSE_LEVEL_MAIN 1
|
#define DBPARSE_LEVEL_MAIN 1
|
||||||
@@ -47,10 +45,18 @@ DBManager g_DBMan;
|
|||||||
static bool s_OneTimeThreaderErrorMsg = false;
|
static bool s_OneTimeThreaderErrorMsg = false;
|
||||||
|
|
||||||
DBManager::DBManager()
|
DBManager::DBManager()
|
||||||
: m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
|
: m_Terminate(false),
|
||||||
|
m_ParseLevel(0),
|
||||||
|
m_ParseState(0),
|
||||||
|
m_pDefault(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void FrameHook(bool simulating)
|
||||||
|
{
|
||||||
|
g_DBMan.RunFrame();
|
||||||
|
}
|
||||||
|
|
||||||
void DBManager::OnSourceModAllInitialized()
|
void DBManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
HandleAccess sec;
|
HandleAccess sec;
|
||||||
@@ -64,13 +70,11 @@ void DBManager::OnSourceModAllInitialized()
|
|||||||
|
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
g_ShareSys.AddInterface(NULL, this);
|
||||||
|
|
||||||
g_SourceMod.BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
|
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
|
||||||
|
|
||||||
m_pConfigLock = g_pThreader->MakeMutex();
|
|
||||||
m_pThinkLock = g_pThreader->MakeMutex();
|
|
||||||
m_pQueueLock = g_pThreader->MakeMutex();
|
|
||||||
|
|
||||||
g_PluginSys.AddPluginsListener(this);
|
g_PluginSys.AddPluginsListener(this);
|
||||||
|
|
||||||
|
g_pSM->AddGameFrameHook(&FrameHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnSourceModLevelChange(const char *mapName)
|
void DBManager::OnSourceModLevelChange(const char *mapName)
|
||||||
@@ -82,28 +86,26 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
|
|||||||
* This way the thread's search won't be searching through a
|
* This way the thread's search won't be searching through a
|
||||||
* potentially empty/corrupt list, which would be very bad.
|
* potentially empty/corrupt list, which would be very bad.
|
||||||
*/
|
*/
|
||||||
m_pConfigLock->Lock();
|
ke::AutoLock lock(&m_ConfigLock);
|
||||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
||||||
if (err != SMCError_Custom)
|
if (err != SMCError_Custom)
|
||||||
{
|
{
|
||||||
const char *txt = textparsers->GetSMCErrorString(err);
|
const char *txt = textparsers->GetSMCErrorString(err);
|
||||||
g_Logger.LogError("[SM] Line %d: %s", states.line, txt);
|
smcore.LogError("[SM] Line %d: %s", states.line, txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_pConfigLock->Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnSourceModShutdown()
|
void DBManager::OnSourceModShutdown()
|
||||||
{
|
{
|
||||||
|
g_pSM->RemoveGameFrameHook(&FrameHook);
|
||||||
KillWorkerThread();
|
KillWorkerThread();
|
||||||
g_PluginSys.RemovePluginsListener(this);
|
g_PluginSys.RemovePluginsListener(this);
|
||||||
m_pConfigLock->DestroyThis();
|
|
||||||
m_pThinkLock->DestroyThis();
|
|
||||||
m_pQueueLock->DestroyThis();
|
|
||||||
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
||||||
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
||||||
|
ClearConfigs();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DBManager::GetInterfaceVersion()
|
unsigned int DBManager::GetInterfaceVersion()
|
||||||
@@ -133,13 +135,20 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
|
|||||||
|
|
||||||
void DBManager::ReadSMC_ParseStart()
|
void DBManager::ReadSMC_ParseStart()
|
||||||
{
|
{
|
||||||
m_confs.clear();
|
ClearConfigs();
|
||||||
m_ParseLevel = 0;
|
m_ParseLevel = 0;
|
||||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||||
m_StrTab.Reset();
|
|
||||||
m_DefDriver.clear();
|
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;
|
ConfDbInfo s_CurInfo;
|
||||||
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||||
{
|
{
|
||||||
@@ -159,7 +168,7 @@ SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *nam
|
|||||||
}
|
}
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||||
s_CurInfo = ConfDbInfo();
|
s_CurInfo = ConfDbInfo();
|
||||||
s_CurInfo.name = m_StrTab.AddString(name);
|
s_CurInfo.name = name;
|
||||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
||||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||||
m_ParseLevel++;
|
m_ParseLevel++;
|
||||||
@@ -186,16 +195,16 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
|||||||
{
|
{
|
||||||
if (strcmp(value, "default") != 0)
|
if (strcmp(value, "default") != 0)
|
||||||
{
|
{
|
||||||
s_CurInfo.driver = m_StrTab.AddString(value);
|
s_CurInfo.driver = value;
|
||||||
}
|
}
|
||||||
} else if (strcmp(key, "database") == 0) {
|
} else if (strcmp(key, "database") == 0) {
|
||||||
s_CurInfo.database = m_StrTab.AddString(value);
|
s_CurInfo.database = value;
|
||||||
} else if (strcmp(key, "host") == 0) {
|
} else if (strcmp(key, "host") == 0) {
|
||||||
s_CurInfo.host = m_StrTab.AddString(value);
|
s_CurInfo.host = value;
|
||||||
} else if (strcmp(key, "user") == 0) {
|
} else if (strcmp(key, "user") == 0) {
|
||||||
s_CurInfo.user = m_StrTab.AddString(value);
|
s_CurInfo.user = value;
|
||||||
} else if (strcmp(key, "pass") == 0) {
|
} else if (strcmp(key, "pass") == 0) {
|
||||||
s_CurInfo.pass = m_StrTab.AddString(value);
|
s_CurInfo.pass = value;
|
||||||
} else if (strcmp(key, "timeout") == 0) {
|
} else if (strcmp(key, "timeout") == 0) {
|
||||||
s_CurInfo.info.maxTimeout = atoi(value);
|
s_CurInfo.info.maxTimeout = atoi(value);
|
||||||
} else if (strcmp(key, "port") == 0) {
|
} else if (strcmp(key, "port") == 0) {
|
||||||
@@ -206,13 +215,6 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
|||||||
return SMCResult_Continue;
|
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)
|
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
{
|
{
|
||||||
if (m_ParseLevel)
|
if (m_ParseLevel)
|
||||||
@@ -223,17 +225,26 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
|
|
||||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
||||||
{
|
{
|
||||||
/* Set all of the info members to either a blank string
|
ConfDbInfo *cdb = new ConfDbInfo();
|
||||||
* or the string pointer from the string table.
|
|
||||||
*/
|
cdb->name = s_CurInfo.name;
|
||||||
ASSIGN_VAR(driver);
|
cdb->driver = s_CurInfo.driver;
|
||||||
ASSIGN_VAR(database);
|
cdb->host = s_CurInfo.host;
|
||||||
ASSIGN_VAR(host);
|
cdb->user = s_CurInfo.user;
|
||||||
ASSIGN_VAR(user);
|
cdb->pass = s_CurInfo.pass;
|
||||||
ASSIGN_VAR(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.. */
|
/* Save it.. */
|
||||||
m_confs.push_back(s_CurInfo);
|
m_confs.push_back(cdb);
|
||||||
|
|
||||||
/* Go up one level */
|
/* Go up one level */
|
||||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||||
@@ -244,7 +255,6 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
|||||||
|
|
||||||
return SMCResult_Continue;
|
return SMCResult_Continue;
|
||||||
}
|
}
|
||||||
#undef ASSIGN_VAR
|
|
||||||
|
|
||||||
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||||
{
|
{
|
||||||
@@ -261,7 +271,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
|
|||||||
*pdr = NULL;
|
*pdr = NULL;
|
||||||
}
|
}
|
||||||
*pdb = NULL;
|
*pdb = NULL;
|
||||||
UTIL_Format(error, maxlength, "Configuration \"%s\" not found", name);
|
g_pSM->Format(error, maxlength, "Configuration \"%s\" not found", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +308,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
|
|||||||
}
|
}
|
||||||
*pdb = NULL;
|
*pdb = NULL;
|
||||||
|
|
||||||
UTIL_Format(error, maxlength, "Driver \"%s\" not found", dname);
|
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -333,16 +343,22 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure NOTHING references this! */
|
/* Make sure NOTHING references this! */
|
||||||
List<ConfDbInfo>::iterator iter;
|
List<ConfDbInfo *>::iterator iter;
|
||||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||||
{
|
{
|
||||||
ConfDbInfo &db = (*iter);
|
ConfDbInfo &db = *(*iter);
|
||||||
if (db.realDriver == pDriver)
|
if (db.realDriver == pDriver)
|
||||||
{
|
{
|
||||||
db.realDriver = NULL;
|
db.realDriver = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Someone unloaded the default driver? Silly.. */
|
||||||
|
if (pDriver == m_pDefault)
|
||||||
|
{
|
||||||
|
m_pDefault = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now that the driver is gone, we have to test the think queue.
|
/* Now that the driver is gone, we have to test the think queue.
|
||||||
* Whatever happens therein is up to the db op!
|
* Whatever happens therein is up to the db op!
|
||||||
*/
|
*/
|
||||||
@@ -448,12 +464,12 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
|||||||
|
|
||||||
ConfDbInfo *DBManager::GetDatabaseConf(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++)
|
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||||
{
|
{
|
||||||
ConfDbInfo &conf = (*iter);
|
ConfDbInfo &conf = *(*iter);
|
||||||
if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
|
if (conf.name == name)
|
||||||
{
|
{
|
||||||
return &conf;
|
return &conf;
|
||||||
}
|
}
|
||||||
@@ -474,7 +490,7 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char filename[PLATFORM_MAX_PATH];
|
char filename[PLATFORM_MAX_PATH];
|
||||||
UTIL_Format(filename, sizeof(filename), "dbi.%s.ext", name);
|
g_pSM->Format(filename, sizeof(filename), "dbi.%s.ext", name);
|
||||||
|
|
||||||
IExtension *pExt = g_Extensions.LoadAutoExtension(filename);
|
IExtension *pExt = g_Extensions.LoadAutoExtension(filename);
|
||||||
if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
|
if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
|
||||||
@@ -495,12 +511,17 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
|
|||||||
|
|
||||||
void DBManager::KillWorkerThread()
|
void DBManager::KillWorkerThread()
|
||||||
{
|
{
|
||||||
if (m_pWorker)
|
if (m_Worker)
|
||||||
{
|
{
|
||||||
m_pWorker->Stop(false);
|
{
|
||||||
g_pThreader->DestroyWorker(m_pWorker);
|
ke::AutoLock lock(&m_QueueEvent);
|
||||||
m_pWorker = NULL;
|
m_Terminate = true;
|
||||||
|
m_QueueEvent.Notify();
|
||||||
|
}
|
||||||
|
m_Worker->Join();
|
||||||
|
m_Worker = NULL;
|
||||||
s_OneTimeThreaderErrorMsg = false;
|
s_OneTimeThreaderErrorMsg = false;
|
||||||
|
m_Terminate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,99 +534,106 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_pWorker)
|
if (!m_Worker)
|
||||||
{
|
{
|
||||||
m_pWorker = g_pThreader->MakeWorker(this, true);
|
m_Worker = new ke::Thread(this, "SM SQL Worker");
|
||||||
if (!m_pWorker)
|
if (!m_Worker->Succeeded())
|
||||||
{
|
{
|
||||||
if (!s_OneTimeThreaderErrorMsg)
|
if (!s_OneTimeThreaderErrorMsg)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Unable to create db threader (error unknown)");
|
smcore.LogError("[SM] Unable to create db threader (error unknown)");
|
||||||
s_OneTimeThreaderErrorMsg = true;
|
s_OneTimeThreaderErrorMsg = true;
|
||||||
}
|
}
|
||||||
return false;
|
m_Worker = NULL;
|
||||||
}
|
|
||||||
if (!m_pWorker->Start())
|
|
||||||
{
|
|
||||||
if (!s_OneTimeThreaderErrorMsg)
|
|
||||||
{
|
|
||||||
g_Logger.LogError("[SM] Unable to start db threader (error unknown)");
|
|
||||||
s_OneTimeThreaderErrorMsg = true;
|
|
||||||
}
|
|
||||||
g_pThreader->DestroyWorker(m_pWorker);
|
|
||||||
m_pWorker = NULL;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add to the queue */
|
/* Add to the queue */
|
||||||
{
|
{
|
||||||
m_pQueueLock->Lock();
|
ke::AutoLock lock(&m_QueueEvent);
|
||||||
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
|
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
|
||||||
queue.push(op);
|
queue.push(op);
|
||||||
m_pQueueLock->Unlock();
|
m_QueueEvent.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the thread */
|
|
||||||
m_pWorker->MakeThread(this);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnWorkerStart(IThreadWorker *pWorker)
|
void DBManager::Run()
|
||||||
{
|
{
|
||||||
m_drSafety.clear();
|
// Initialize DB threadsafety.
|
||||||
for (size_t i=0; i<m_drivers.size(); i++)
|
for (size_t i=0; i < m_drivers.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_drivers[i]->IsThreadSafe())
|
if (m_drivers[i]->IsThreadSafe())
|
||||||
{
|
|
||||||
m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety());
|
m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety());
|
||||||
} else {
|
else
|
||||||
m_drSafety.push_back(false);
|
m_drSafety.push_back(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnWorkerStop(IThreadWorker *pWorker)
|
// Run actual worker thread logic.
|
||||||
{
|
ThreadMain();
|
||||||
|
|
||||||
|
// Shutdown DB threadsafety.
|
||||||
for (size_t i=0; i<m_drivers.size(); i++)
|
for (size_t i=0; i<m_drivers.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_drSafety[i])
|
if (m_drSafety[i])
|
||||||
{
|
|
||||||
m_drivers[i]->ShutdownThreadSafety();
|
m_drivers[i]->ShutdownThreadSafety();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_drSafety.clear();
|
m_drSafety.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::RunThread(IThreadHandle *pThread)
|
void DBManager::ThreadMain()
|
||||||
{
|
{
|
||||||
IDBThreadOperation *op = NULL;
|
ke::AutoLock lock(&m_QueueEvent);
|
||||||
|
|
||||||
/* Get something from the queue */
|
while (true) {
|
||||||
{
|
// The lock has been acquired. Grab everything we can out of the
|
||||||
m_pQueueLock->Lock();
|
// queue. Since we want to flush the queue even if we're terminated,
|
||||||
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
|
// we process all operations we can before checking to terminate.
|
||||||
if (!queue.empty())
|
// There's no risk of starvation since the main thread blocks on us
|
||||||
|
// terminating.
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
op = queue.first();
|
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
|
||||||
|
if (queue.empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
IDBThreadOperation *op = queue.first();
|
||||||
queue.pop();
|
queue.pop();
|
||||||
|
|
||||||
|
// Unlock the queue when we run the query, so the main thread can
|
||||||
|
// keep pumping events. We re-acquire the lock to check for more
|
||||||
|
// items. It's okay if we terminate while unlocked; the main
|
||||||
|
// thread would be blocked and we'd need to flush the queue
|
||||||
|
// anyway, so after we've depleted the queue here, we'll just
|
||||||
|
// reach the terminate at the top of the loop.
|
||||||
|
{
|
||||||
|
ke::AutoUnlock unlock(&m_QueueEvent);
|
||||||
|
op->RunThreadPart();
|
||||||
|
|
||||||
|
ke::AutoLock lock(&m_ThinkLock);
|
||||||
|
m_ThinkQueue.push(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!m_Terminate)
|
||||||
|
{
|
||||||
|
ke::AutoUnlock unlock(&m_QueueEvent);
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(20);
|
||||||
|
#else
|
||||||
|
usleep(20000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_pQueueLock->Unlock();
|
|
||||||
|
if (m_Terminate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Release the lock and wait for a signal.
|
||||||
|
m_QueueEvent.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* whoa. hi. did we get something? we should have. */
|
|
||||||
if (!op)
|
|
||||||
{
|
|
||||||
/* wtf? */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
op->RunThreadPart();
|
|
||||||
|
|
||||||
m_pThinkLock->Lock();
|
|
||||||
m_ThinkQueue.push(op);
|
|
||||||
m_pThinkLock->Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::RunFrame()
|
void DBManager::RunFrame()
|
||||||
@@ -617,19 +645,16 @@ void DBManager::RunFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Dump one thing per-frame so the server stays sane. */
|
/* Dump one thing per-frame so the server stays sane. */
|
||||||
m_pThinkLock->Lock();
|
IDBThreadOperation *op;
|
||||||
IDBThreadOperation *op = m_ThinkQueue.first();
|
{
|
||||||
m_ThinkQueue.pop();
|
ke::AutoLock lock(&m_ThinkLock);
|
||||||
m_pThinkLock->Unlock();
|
op = m_ThinkQueue.first();
|
||||||
|
m_ThinkQueue.pop();
|
||||||
|
}
|
||||||
op->RunThinkPart();
|
op->RunThinkPart();
|
||||||
op->Destroy();
|
op->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::OnTerminate(IThreadHandle *pThread, bool cancel)
|
|
||||||
{
|
|
||||||
/* Do nothing */
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
|
void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
|
||||||
{
|
{
|
||||||
s_pAddBlock = pToken;
|
s_pAddBlock = pToken;
|
||||||
@@ -705,15 +730,21 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
|
|
||||||
void DBManager::LockConfig()
|
void DBManager::LockConfig()
|
||||||
{
|
{
|
||||||
m_pConfigLock->Lock();
|
m_ConfigLock.Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DBManager::UnlockConfig()
|
void DBManager::UnlockConfig()
|
||||||
{
|
{
|
||||||
m_pConfigLock->Unlock();
|
m_ConfigLock.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *DBManager::GetDefaultDriverName()
|
const char *DBManager::GetDefaultDriverName()
|
||||||
{
|
{
|
||||||
return m_DefDriver.c_str();
|
return m_DefDriver.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
|
||||||
|
{
|
||||||
|
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -33,30 +33,29 @@
|
|||||||
#define _INCLUDE_DATABASE_MANAGER_H_
|
#define _INCLUDE_DATABASE_MANAGER_H_
|
||||||
|
|
||||||
#include <IDBDriver.h>
|
#include <IDBDriver.h>
|
||||||
#include "sm_globals.h"
|
#include "common_logic.h"
|
||||||
#include <sh_vector.h>
|
#include <sh_vector.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <ITextParsers.h>
|
#include <ITextParsers.h>
|
||||||
#include "sm_memtable.h"
|
|
||||||
#include <IThreader.h>
|
#include <IThreader.h>
|
||||||
|
#include <IPluginSys.h>
|
||||||
|
#include <am-thread-utils.h>
|
||||||
#include "sm_simple_prioqueue.h"
|
#include "sm_simple_prioqueue.h"
|
||||||
#include "PluginSys.h"
|
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
struct ConfDbInfo
|
struct ConfDbInfo
|
||||||
{
|
{
|
||||||
ConfDbInfo() : name(-1), driver(-1), host(-1), user(-1), pass(-1),
|
ConfDbInfo() : realDriver(NULL)
|
||||||
database(-1), realDriver(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
int name;
|
String name;
|
||||||
int driver;
|
String driver;
|
||||||
int host;
|
String host;
|
||||||
int user;
|
String user;
|
||||||
int pass;
|
String pass;
|
||||||
int database;
|
String database;
|
||||||
IDBDriver *realDriver;
|
IDBDriver *realDriver;
|
||||||
DatabaseInfo info;
|
DatabaseInfo info;
|
||||||
};
|
};
|
||||||
@@ -66,9 +65,8 @@ class DBManager :
|
|||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IHandleTypeDispatch,
|
public IHandleTypeDispatch,
|
||||||
public ITextListener_SMC,
|
public ITextListener_SMC,
|
||||||
public IThread,
|
public IPluginsListener,
|
||||||
public IThreadWorkerCallbacks,
|
public ke::IRunnable
|
||||||
public IPluginsListener
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DBManager();
|
DBManager();
|
||||||
@@ -92,18 +90,16 @@ public: //IDBManager
|
|||||||
Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken);
|
Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken);
|
||||||
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
|
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
|
||||||
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
|
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
|
||||||
|
void AddDependency(IExtension *myself, IDBDriver *driver);
|
||||||
public: //ITextListener_SMC
|
public: //ITextListener_SMC
|
||||||
void ReadSMC_ParseStart();
|
void ReadSMC_ParseStart();
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
void ReadSMC_ParseEnd(bool halted, bool failed);
|
||||||
public: //IThread
|
public: //ke::IRunnable
|
||||||
void RunThread(IThreadHandle *pThread);
|
void Run();
|
||||||
void OnTerminate(IThreadHandle *pThread, bool cancel);
|
void ThreadMain();
|
||||||
public: //IThreadWorkerCallbacks
|
|
||||||
void OnWorkerStart(IThreadWorker *pWorker);
|
|
||||||
void OnWorkerStop(IThreadWorker *pWorker);
|
|
||||||
public: //IPluginsListener
|
public: //IPluginsListener
|
||||||
void OnPluginUnloaded(IPlugin *plugin);
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
public:
|
public:
|
||||||
@@ -120,6 +116,7 @@ public:
|
|||||||
return m_DatabaseType;
|
return m_DatabaseType;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
void ClearConfigs();
|
||||||
void KillWorkerThread();
|
void KillWorkerThread();
|
||||||
private:
|
private:
|
||||||
CVector<IDBDriver *> m_drivers;
|
CVector<IDBDriver *> m_drivers;
|
||||||
@@ -128,16 +125,16 @@ private:
|
|||||||
PrioQueue<IDBThreadOperation *> m_OpQueue;
|
PrioQueue<IDBThreadOperation *> m_OpQueue;
|
||||||
Queue<IDBThreadOperation *> m_ThinkQueue;
|
Queue<IDBThreadOperation *> m_ThinkQueue;
|
||||||
CVector<bool> m_drSafety; /* which drivers are safe? */
|
CVector<bool> m_drSafety; /* which drivers are safe? */
|
||||||
IThreadWorker *m_pWorker; /* Worker thread object */
|
ke::AutoPtr<ke::Thread> m_Worker;
|
||||||
IMutex *m_pConfigLock; /* Configuration lock */
|
ke::ConditionVariable m_QueueEvent;
|
||||||
IMutex *m_pQueueLock; /* Queue safety lock */
|
ke::Mutex m_ConfigLock;
|
||||||
IMutex *m_pThinkLock; /* Think-queue lock */
|
ke::Mutex m_ThinkLock;
|
||||||
|
bool m_Terminate;
|
||||||
|
|
||||||
List<ConfDbInfo> m_confs;
|
List<ConfDbInfo *> m_confs;
|
||||||
HandleType_t m_DriverType;
|
HandleType_t m_DriverType;
|
||||||
HandleType_t m_DatabaseType;
|
HandleType_t m_DatabaseType;
|
||||||
String m_DefDriver;
|
String m_DefDriver;
|
||||||
BaseStringTable m_StrTab;
|
|
||||||
char m_Filename[PLATFORM_MAX_PATH];
|
char m_Filename[PLATFORM_MAX_PATH];
|
||||||
unsigned int m_ParseLevel;
|
unsigned int m_ParseLevel;
|
||||||
unsigned int m_ParseState;
|
unsigned int m_ParseState;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -29,43 +29,54 @@
|
|||||||
* Version: $Id$
|
* Version: $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <IPluginSys.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include "DebugReporter.h"
|
#include "DebugReporter.h"
|
||||||
#include "Logger.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "sm_stringutil.h"
|
|
||||||
|
|
||||||
DebugReport g_DbgReporter;
|
DebugReport g_DbgReporter;
|
||||||
|
|
||||||
/* I'm really lazy. This should probably be exported to ISourcePawnEngine someday,
|
|
||||||
* but we need to make sure the JIT will deal with the version bump.
|
|
||||||
*/
|
|
||||||
extern const char *GetSourcePawnErrorMessage(int error);
|
|
||||||
|
|
||||||
void DebugReport::OnSourceModAllInitialized()
|
void DebugReport::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_pSourcePawn->SetDebugListener(this);
|
g_pSourcePawn->SetDebugListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
void DebugReport::OnDebugSpew(const char *msg, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
|
||||||
va_start(ap, message);
|
va_start(ap, msg);
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
|
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
smcore.Log("[SM] %s", buffer);
|
||||||
const char *error = GetSourcePawnErrorMessage(err);
|
}
|
||||||
|
|
||||||
|
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, message);
|
||||||
|
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];
|
||||||
|
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
|
||||||
|
|
||||||
|
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
|
||||||
|
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||||
} else {
|
} else {
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Logger.LogError("[SM] %s", buffer);
|
smcore.LogError("[SM] %s", buffer);
|
||||||
|
|
||||||
if (func_idx != -1)
|
if (func_idx != -1)
|
||||||
{
|
{
|
||||||
@@ -73,9 +84,9 @@ void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, c
|
|||||||
{
|
{
|
||||||
func_idx >>= 1;
|
func_idx >>= 1;
|
||||||
sp_public_t *function;
|
sp_public_t *function;
|
||||||
if (ctx->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
|
if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,26 +98,26 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
|||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
|
||||||
va_start(ap, message);
|
va_start(ap, message);
|
||||||
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
|
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
|
const char *plname = pluginsys->FindPluginByContext(pContext->GetContext())->GetFilename();
|
||||||
const char *error = GetSourcePawnErrorMessage(err);
|
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||||
} else {
|
} else {
|
||||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Logger.LogError("[SM] %s", buffer);
|
smcore.LogError("[SM] %s", buffer);
|
||||||
|
|
||||||
IPluginDebugInfo *pDebug;
|
IPluginDebugInfo *pDebug;
|
||||||
if ((pDebug = pContext->GetDebugInfo()) == NULL)
|
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||||
_GetPluginIndex(pContext));
|
_GetPluginIndex(pContext));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -114,21 +125,21 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
|
|||||||
const char *name;
|
const char *name;
|
||||||
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
|
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
|
||||||
} else {
|
} else {
|
||||||
g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
|
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
|
||||||
{
|
{
|
||||||
const char *lastname;
|
const char *lastname;
|
||||||
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
|
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
|
||||||
int n_err = error->GetErrorCode();
|
int n_err = error->GetErrorCode();
|
||||||
|
|
||||||
if (n_err != SP_ERROR_NATIVE)
|
if (n_err != SP_ERROR_NATIVE)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
|
smcore.LogError("[SM] Plugin encountered error %d: %s",
|
||||||
n_err,
|
n_err,
|
||||||
error->GetErrorString());
|
error->GetErrorString());
|
||||||
}
|
}
|
||||||
@@ -138,26 +149,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
|||||||
const char *custerr;
|
const char *custerr;
|
||||||
if ((custerr=error->GetCustomErrorString()) != NULL)
|
if ((custerr=error->GetCustomErrorString()) != NULL)
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
|
||||||
} else {
|
} else {
|
||||||
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error->DebugInfoAvailable())
|
if (!error->DebugInfoAvailable())
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
|
||||||
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
|
||||||
_GetPluginIndex(ctx));
|
_GetPluginIndex(ctx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallStackInfo stk_info;
|
CallStackInfo stk_info;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
|
||||||
while (error->GetTraceInfo(&stk_info))
|
while (error->GetTraceInfo(&stk_info))
|
||||||
{
|
{
|
||||||
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
|
smcore.LogError("[SM] [%d] Line %d, %s::%s()",
|
||||||
i++,
|
i++,
|
||||||
stk_info.line,
|
stk_info.line,
|
||||||
stk_info.filename,
|
stk_info.filename,
|
||||||
@@ -168,7 +179,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
|
|||||||
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
||||||
{
|
{
|
||||||
int id = 1;
|
int id = 1;
|
||||||
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
|
IPluginIterator *iter = pluginsys->GetPluginIterator();
|
||||||
|
|
||||||
for (; iter->MorePlugins(); iter->NextPlugin(), id++)
|
for (; iter->MorePlugins(); iter->NextPlugin(), id++)
|
||||||
{
|
{
|
||||||
@@ -181,6 +192,9 @@ int DebugReport::_GetPluginIndex(IPluginContext *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
iter->Release();
|
iter->Release();
|
||||||
return -1;
|
|
||||||
|
/* If we don't know which plugin this is, it's one being loaded. Fake its index for now. */
|
||||||
|
|
||||||
|
return pluginsys->GetPluginCount() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
#define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
|
#define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
|
||||||
|
|
||||||
#include "sp_vm_api.h"
|
#include "sp_vm_api.h"
|
||||||
#include "sm_globals.h"
|
#include "common_logic.h"
|
||||||
|
|
||||||
class DebugReport :
|
class DebugReport :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
@@ -43,7 +43,10 @@ public: // SMGlobalClass
|
|||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
public: // IDebugListener
|
public: // IDebugListener
|
||||||
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
|
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
|
||||||
|
void OnDebugSpew(const char *msg, ...);
|
||||||
|
public:
|
||||||
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
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, ...);
|
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
||||||
private:
|
private:
|
||||||
int _GetPluginIndex(IPluginContext *ctx);
|
int _GetPluginIndex(IPluginContext *ctx);
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -36,13 +36,13 @@
|
|||||||
#include <ILibrarySys.h>
|
#include <ILibrarySys.h>
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_string.h>
|
#include <sh_string.h>
|
||||||
#include <sm_trie_tpl.h>
|
#include "common_logic.h"
|
||||||
#include "sm_globals.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include <ISmmAPI.h>
|
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include <IRootConsoleMenu.h>
|
#include <IRootConsoleMenu.h>
|
||||||
#include "PluginSys.h"
|
#include "NativeOwner.h"
|
||||||
|
#include "ShareSys.h"
|
||||||
|
|
||||||
|
class CPlayer;
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
@@ -55,15 +55,9 @@ struct sm_extnative_t
|
|||||||
const sp_nativeinfo_t *info;
|
const sp_nativeinfo_t *info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Replacement native */
|
class CExtension :
|
||||||
struct sm_repnative_t
|
public IExtension,
|
||||||
{
|
public CNativeOwner
|
||||||
CExtension *owner;
|
|
||||||
sp_nativeinfo_t info;
|
|
||||||
SPVM_NATIVE_FUNC original;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CExtension : public IExtension
|
|
||||||
{
|
{
|
||||||
friend class CExtensionManager;
|
friend class CExtensionManager;
|
||||||
public:
|
public:
|
||||||
@@ -71,6 +65,7 @@ public:
|
|||||||
public: //IExtension
|
public: //IExtension
|
||||||
IExtensionInterface *GetAPI();
|
IExtensionInterface *GetAPI();
|
||||||
const char *GetFilename();
|
const char *GetFilename();
|
||||||
|
const char *GetPath() const;
|
||||||
IdentityToken_t *GetIdentity();
|
IdentityToken_t *GetIdentity();
|
||||||
ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
|
ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
|
||||||
bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
|
bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
|
||||||
@@ -78,17 +73,18 @@ public: //IExtension
|
|||||||
bool IsRunning(char *error, size_t maxlength);
|
bool IsRunning(char *error, size_t maxlength);
|
||||||
public:
|
public:
|
||||||
void SetError(const char *error);
|
void SetError(const char *error);
|
||||||
void AddDependency(IfaceInfo *pInfo);
|
void AddDependency(const IfaceInfo *pInfo);
|
||||||
void AddChildDependent(CExtension *pOther, SMInterface *iface);
|
void AddChildDependent(CExtension *pOther, SMInterface *iface);
|
||||||
void AddInterface(SMInterface *pInterface);
|
void AddInterface(SMInterface *pInterface);
|
||||||
void AddPlugin(IPlugin *pPlugin);
|
void AddPlugin(CPlugin *pPlugin);
|
||||||
void RemovePlugin(IPlugin *pPlugin);
|
|
||||||
void MarkAllLoaded();
|
void MarkAllLoaded();
|
||||||
void AddLibrary(const char *library);
|
void AddLibrary(const char *library);
|
||||||
public:
|
public:
|
||||||
virtual bool Load(char *error, size_t maxlength);
|
virtual bool Load(char *error, size_t maxlength);
|
||||||
virtual bool IsLoaded() =0;
|
virtual bool IsLoaded() =0;
|
||||||
virtual void Unload() =0;
|
virtual void Unload() =0;
|
||||||
|
virtual bool Reload(char *error, size_t maxlength) =0;
|
||||||
|
virtual bool IsSameFile(const char* file) =0;
|
||||||
protected:
|
protected:
|
||||||
void Initialize(const char *filename, const char *path);
|
void Initialize(const char *filename, const char *path);
|
||||||
bool PerformAPICheck(char *error, size_t maxlength);
|
bool PerformAPICheck(char *error, size_t maxlength);
|
||||||
@@ -98,15 +94,12 @@ protected:
|
|||||||
IdentityToken_t *m_pIdentToken;
|
IdentityToken_t *m_pIdentToken;
|
||||||
IExtensionInterface *m_pAPI;
|
IExtensionInterface *m_pAPI;
|
||||||
String m_File;
|
String m_File;
|
||||||
|
String m_RealFile;
|
||||||
String m_Path;
|
String m_Path;
|
||||||
String m_Error;
|
String m_Error;
|
||||||
List<IfaceInfo> m_Deps; /** Dependencies */
|
List<IfaceInfo> m_Deps; /** Dependencies */
|
||||||
List<IfaceInfo> m_ChildDeps; /** Children who might depend on us */
|
List<IfaceInfo> m_ChildDeps; /** Children who might depend on us */
|
||||||
List<SMInterface *> m_Interfaces;
|
List<SMInterface *> m_Interfaces;
|
||||||
List<IPlugin *> m_Plugins;
|
|
||||||
List<const sp_nativeinfo_t *> m_Natives;
|
|
||||||
List<WeakNative> m_WeakNatives;
|
|
||||||
List<WeakNative> m_ReplacedNatives;
|
|
||||||
List<String> m_Libraries;
|
List<String> m_Libraries;
|
||||||
unsigned int unload_code;
|
unsigned int unload_code;
|
||||||
bool m_bFullyLoaded;
|
bool m_bFullyLoaded;
|
||||||
@@ -120,9 +113,11 @@ public:
|
|||||||
bool Load(char *error, size_t maxlength);
|
bool Load(char *error, size_t maxlength);
|
||||||
bool IsLoaded();
|
bool IsLoaded();
|
||||||
void Unload();
|
void Unload();
|
||||||
|
bool Reload(char *error, size_t maxlength);
|
||||||
bool IsExternal();
|
bool IsExternal();
|
||||||
|
bool IsSameFile(const char *file);
|
||||||
private:
|
private:
|
||||||
PluginId m_PlId;
|
int m_PlId;
|
||||||
ILibrary *m_pLib;
|
ILibrary *m_pLib;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,11 +129,13 @@ public:
|
|||||||
bool Load(char *error, size_t maxlength);
|
bool Load(char *error, size_t maxlength);
|
||||||
bool IsLoaded();
|
bool IsLoaded();
|
||||||
void Unload();
|
void Unload();
|
||||||
|
bool Reload(char *error, size_t maxlength);
|
||||||
bool IsExternal();
|
bool IsExternal();
|
||||||
|
bool IsSameFile(const char *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CExtensionManager :
|
class CExtensionManager :
|
||||||
public IExtensionManager,
|
public IExtensionSys,
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IPluginsListener,
|
public IPluginsListener,
|
||||||
public IRootConsoleCommand
|
public IRootConsoleCommand
|
||||||
@@ -166,28 +163,31 @@ public: //IPluginsListener
|
|||||||
public: //IRootConsoleCommand
|
public: //IRootConsoleCommand
|
||||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||||
public:
|
public:
|
||||||
IExtension *LoadAutoExtension(const char *path);
|
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
|
||||||
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
|
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
|
||||||
void AddInterface(IExtension *pOwner, SMInterface *pInterface);
|
void AddInterface(IExtension *pOwner, SMInterface *pInterface);
|
||||||
void BindChildPlugin(IExtension *pParent, IPlugin *pPlugin);
|
void BindChildPlugin(IExtension *pParent, SMPlugin *pPlugin);
|
||||||
void AddNatives(IExtension *pOwner, const sp_nativeinfo_t *natives);
|
|
||||||
void BindAllNativesToPlugin(IPlugin *pPlugin);
|
|
||||||
void MarkAllLoaded();
|
void MarkAllLoaded();
|
||||||
void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload);
|
void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload);
|
||||||
void TryAutoload();
|
void TryAutoload();
|
||||||
void AddLibrary(IExtension *pSource, const char *library);
|
void AddLibrary(IExtension *pSource, const char *library);
|
||||||
bool LibraryExists(const char *library);
|
bool LibraryExists(const char *library);
|
||||||
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
|
||||||
|
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
|
||||||
|
const CVector<IExtension *> *ListExtensions();
|
||||||
|
void FreeExtensionList(const CVector<IExtension *> *list);
|
||||||
public:
|
public:
|
||||||
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
|
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
CNativeOwner *GetNativeOwner(IExtension *pExt)
|
||||||
|
{
|
||||||
|
CExtension *p = (CExtension *)pExt;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
CExtension *FindByOrder(unsigned int num);
|
CExtension *FindByOrder(unsigned int num);
|
||||||
private:
|
private:
|
||||||
List<CExtension *> m_Libs;
|
List<CExtension *> m_Libs;
|
||||||
List<sm_repnative_t> m_RepNativeList;
|
|
||||||
KTrie<sm_repnative_t> m_RepNatives;
|
|
||||||
KTrie<sm_extnative_t> m_ExtNatives;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CExtensionManager g_Extensions;
|
extern CExtensionManager g_Extensions;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -33,9 +33,8 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ForwardSys.h"
|
#include "ForwardSys.h"
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "DebugReporter.h"
|
#include "DebugReporter.h"
|
||||||
|
#include "common_logic.h"
|
||||||
|
|
||||||
CForwardManager g_Forwards;
|
CForwardManager g_Forwards;
|
||||||
|
|
||||||
@@ -63,8 +62,8 @@ CForwardManager::~CForwardManager()
|
|||||||
|
|
||||||
void CForwardManager::OnSourceModAllInitialized()
|
void CForwardManager::OnSourceModAllInitialized()
|
||||||
{
|
{
|
||||||
g_PluginSys.AddPluginsListener(this);
|
scripts->AddPluginsListener(this);
|
||||||
g_ShareSys.AddInterface(NULL, this);
|
sharesys->AddInterface(NULL, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
|
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
|
||||||
@@ -79,7 +78,7 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
|
|||||||
|
|
||||||
if (fwd)
|
if (fwd)
|
||||||
{
|
{
|
||||||
g_PluginSys.AddFunctionsToForward(name, fwd);
|
scripts->AddFunctionsToForward(name, fwd);
|
||||||
|
|
||||||
m_managed.push_back(fwd);
|
m_managed.push_back(fwd);
|
||||||
}
|
}
|
||||||
@@ -186,8 +185,14 @@ void CForwardManager::ReleaseForward(IForward *forward)
|
|||||||
|
|
||||||
void CForwardManager::ForwardFree(CForward *fwd)
|
void CForwardManager::ForwardFree(CForward *fwd)
|
||||||
{
|
{
|
||||||
|
if (fwd == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_FreeForwards.push(fwd);
|
m_FreeForwards.push(fwd);
|
||||||
m_managed.remove(fwd);
|
m_managed.remove(fwd);
|
||||||
|
m_unmanaged.remove(fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
CForward *CForwardManager::ForwardMake()
|
CForward *CForwardManager::ForwardMake()
|
||||||
@@ -205,7 +210,23 @@ CForward *CForwardManager::ForwardMake()
|
|||||||
|
|
||||||
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
||||||
{
|
{
|
||||||
/* No longer used */
|
if(paused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Attach any globally managed forwards */
|
||||||
|
List<CForward *>::iterator iter;
|
||||||
|
CForward *fwd;
|
||||||
|
|
||||||
|
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
||||||
|
{
|
||||||
|
fwd = (*iter);
|
||||||
|
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
||||||
|
// Only add functions, if they aren't registered yet!
|
||||||
|
if (pFunc && !fwd->IsFunctionRegistered(pFunc))
|
||||||
|
{
|
||||||
|
fwd->AddFunction(pFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
@@ -250,6 +271,7 @@ CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int nu
|
|||||||
}
|
}
|
||||||
|
|
||||||
CForward *pForward = g_Forwards.ForwardMake();
|
CForward *pForward = g_Forwards.ForwardMake();
|
||||||
|
pForward->m_IterGuard = NULL;
|
||||||
pForward->m_curparam = 0;
|
pForward->m_curparam = 0;
|
||||||
pForward->m_ExecType = et;
|
pForward->m_ExecType = et;
|
||||||
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
||||||
@@ -283,17 +305,13 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter)
|
|
||||||
{
|
|
||||||
filter->OnExecuteBegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
FuncIter iter = m_functions.begin();
|
FuncIter iter = m_functions.begin();
|
||||||
IPluginFunction *func;
|
IPluginFunction *func;
|
||||||
cell_t cur_result = 0;
|
cell_t cur_result = 0;
|
||||||
cell_t high_result = 0;
|
cell_t high_result = 0;
|
||||||
|
cell_t low_result = 0;
|
||||||
int err;
|
int err;
|
||||||
unsigned int failed=0, success=0;
|
unsigned int success=0;
|
||||||
unsigned int num_params = m_curparam;
|
unsigned int num_params = m_curparam;
|
||||||
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||||
FwdParamInfo *param;
|
FwdParamInfo *param;
|
||||||
@@ -303,20 +321,29 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
memcpy(temp_info, m_params, sizeof(m_params));
|
memcpy(temp_info, m_params, sizeof(m_params));
|
||||||
m_curparam = 0;
|
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);
|
func = (*iter);
|
||||||
|
|
||||||
|
if (filter)
|
||||||
|
filter->Preprocess(func, temp_info);
|
||||||
|
|
||||||
for (unsigned int i=0; i<num_params; i++)
|
for (unsigned int i=0; i<num_params; i++)
|
||||||
{
|
{
|
||||||
int err = SP_ERROR_PARAM;
|
int err = SP_ERROR_PARAM;
|
||||||
param = &temp_info[i];
|
param = &temp_info[i];
|
||||||
|
|
||||||
if (i >= m_numparams || m_types[i] == Param_Any)
|
if (i >= m_numparams || m_types[i] == Param_Any)
|
||||||
{
|
{
|
||||||
type = param->pushedas;
|
type = param->pushedas;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
type = m_types[i];
|
type = m_types[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
|
if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
|
||||||
{
|
{
|
||||||
/* If we're byref or we're vararg, we always push everything by ref.
|
/* If we're byref or we're vararg, we always push everything by ref.
|
||||||
@@ -325,39 +352,37 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
if (type == Param_String)
|
if (type == Param_String)
|
||||||
{
|
{
|
||||||
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
||||||
} else if (type == Param_Float || type == Param_Cell) {
|
}
|
||||||
|
else if (type == Param_Float || type == Param_Cell)
|
||||||
|
{
|
||||||
err = func->PushCellByRef(¶m->val);
|
err = func->PushCellByRef(¶m->val);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
||||||
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* If we're not byref or not vararg, our job is a bit easier. */
|
/* If we're not byref or not vararg, our job is a bit easier. */
|
||||||
assert(type == Param_Cell || type == Param_Float);
|
assert(type == Param_Cell || type == Param_Float);
|
||||||
err = func->PushCell(param->val);
|
err = func->PushCell(param->val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != SP_ERROR_NONE)
|
if (err != SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (!filter || !filter->OnErrorReport(this, func, err))
|
g_DbgReporter.GenerateError(func->GetParentContext(),
|
||||||
{
|
func->GetFunctionID(),
|
||||||
g_DbgReporter.GenerateError(func->GetParentContext(),
|
err,
|
||||||
func->GetFunctionID(),
|
"Failed to push parameter while executing forward");
|
||||||
err,
|
|
||||||
"Failed to push parameter while executing forward");
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call the function and deal with the return value. */
|
/* Call the function and deal with the return value. */
|
||||||
if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
|
if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE)
|
||||||
{
|
{
|
||||||
if (filter)
|
|
||||||
{
|
|
||||||
filter->OnErrorReport(this, func, err);
|
|
||||||
}
|
|
||||||
failed++;
|
|
||||||
} else {
|
|
||||||
success++;
|
success++;
|
||||||
switch (m_ExecType)
|
switch (m_ExecType)
|
||||||
{
|
{
|
||||||
@@ -381,14 +406,12 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_Custom:
|
case ET_LowEvent:
|
||||||
{
|
{
|
||||||
if (filter)
|
/* Check if the current result is the lowest so far (or if it's the first result) */
|
||||||
|
if (cur_result < low_result || success == 1)
|
||||||
{
|
{
|
||||||
if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
|
low_result = cur_result;
|
||||||
{
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -398,28 +421,45 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!guard.Triggered())
|
||||||
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
|
switch (m_ExecType)
|
||||||
{
|
{
|
||||||
cur_result = high_result;
|
case ET_Ignore:
|
||||||
} else if (m_ExecType == ET_Ignore) {
|
{
|
||||||
cur_result = 0;
|
cur_result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_Event:
|
||||||
|
case ET_Hook:
|
||||||
|
{
|
||||||
|
cur_result = high_result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_LowEvent:
|
||||||
|
{
|
||||||
|
cur_result = low_result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
*result = cur_result;
|
*result = cur_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter)
|
|
||||||
{
|
|
||||||
filter->OnExecuteEnd(&cur_result, success, failed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SP_ERROR_NONE;
|
return SP_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,10 +699,11 @@ bool CForward::RemoveFunction(IPluginFunction *func)
|
|||||||
lst = &m_paused;
|
lst = &m_paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
for (iter=lst->begin(); iter!=lst->end(); iter++)
|
||||||
{
|
{
|
||||||
if ((*iter) == func)
|
if ((*iter) == func)
|
||||||
{
|
{
|
||||||
|
m_IterGuard->FixIteratorChain(iter);
|
||||||
found = true;
|
found = true;
|
||||||
lst->erase(iter);
|
lst->erase(iter);
|
||||||
break;
|
break;
|
||||||
@@ -716,6 +757,28 @@ bool CForward::AddFunction(IPluginFunction *func)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CForward::IsFunctionRegistered(IPluginFunction *func)
|
||||||
|
{
|
||||||
|
FuncIter iter;
|
||||||
|
List<IPluginFunction *> *lst;
|
||||||
|
|
||||||
|
if (func->IsRunnable())
|
||||||
|
{
|
||||||
|
lst = &m_functions;
|
||||||
|
} else {
|
||||||
|
lst = &m_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
||||||
|
{
|
||||||
|
if ((*iter) == func)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const char *CForward::GetForwardName()
|
const char *CForward::GetForwardName()
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* vim: set ts=4 :
|
* vim: set ts=4 :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,31 +34,60 @@
|
|||||||
|
|
||||||
#include <IForwardSys.h>
|
#include <IForwardSys.h>
|
||||||
#include <IPluginSys.h>
|
#include <IPluginSys.h>
|
||||||
#include "sm_globals.h"
|
#include "common_logic.h"
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
#include <sh_stack.h>
|
#include <sh_stack.h>
|
||||||
#include "sourcemod.h"
|
#include "ISourceMod.h"
|
||||||
|
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
|
|
||||||
typedef List<IPluginFunction *>::iterator FuncIter;
|
typedef List<IPluginFunction *>::iterator FuncIter;
|
||||||
|
|
||||||
//:TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX
|
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
|
||||||
#define FORWARDS_NAME_MAX 64
|
#define FORWARDS_NAME_MAX 64
|
||||||
|
|
||||||
struct ByrefInfo
|
class FuncIteratorGuard
|
||||||
{
|
{
|
||||||
unsigned int cells;
|
bool triggered;
|
||||||
cell_t *orig_addr;
|
FuncIteratorGuard **pprev;
|
||||||
int flags;
|
FuncIter *iter;
|
||||||
int sz_flags;
|
FuncIteratorGuard *next;
|
||||||
};
|
public:
|
||||||
|
FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter)
|
||||||
|
: triggered(false), pprev(pprev), iter(iter), next(*pprev)
|
||||||
|
{
|
||||||
|
*pprev = this;
|
||||||
|
}
|
||||||
|
|
||||||
struct FwdParamInfo
|
~FuncIteratorGuard()
|
||||||
{
|
{
|
||||||
cell_t val;
|
*pprev = next;
|
||||||
ByrefInfo byref;
|
}
|
||||||
ParamType pushedas;
|
|
||||||
|
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
|
class CForward : public IChangeableForward
|
||||||
@@ -89,6 +118,7 @@ public:
|
|||||||
unsigned int num_params,
|
unsigned int num_params,
|
||||||
const ParamType *types,
|
const ParamType *types,
|
||||||
va_list ap);
|
va_list ap);
|
||||||
|
bool IsFunctionRegistered(IPluginFunction *func);
|
||||||
private:
|
private:
|
||||||
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
|
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
|
||||||
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
|
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
|
||||||
@@ -103,6 +133,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
mutable List<IPluginFunction *> m_functions;
|
mutable List<IPluginFunction *> m_functions;
|
||||||
mutable List<IPluginFunction *> m_paused;
|
mutable List<IPluginFunction *> m_paused;
|
||||||
|
FuncIteratorGuard *m_IterGuard;
|
||||||
|
|
||||||
/* Type and name information */
|
/* Type and name information */
|
||||||
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet:
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -32,12 +32,12 @@
|
|||||||
#ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
#ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
||||||
#define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
#define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
|
||||||
|
|
||||||
|
#include "common_logic.h"
|
||||||
#include <IGameConfigs.h>
|
#include <IGameConfigs.h>
|
||||||
#include <ITextParsers.h>
|
#include <ITextParsers.h>
|
||||||
#include <sh_list.h>
|
#include <am-refcounting.h>
|
||||||
#include "sm_trie.h"
|
#include <sm_stringhashmap.h>
|
||||||
#include "sm_globals.h"
|
#include <sm_namehashset.h>
|
||||||
#include "sm_memtable.h"
|
|
||||||
|
|
||||||
using namespace SourceMod;
|
using namespace SourceMod;
|
||||||
using namespace SourceHook;
|
using namespace SourceHook;
|
||||||
@@ -46,14 +46,18 @@ class SendProp;
|
|||||||
|
|
||||||
class CGameConfig :
|
class CGameConfig :
|
||||||
public ITextListener_SMC,
|
public ITextListener_SMC,
|
||||||
public IGameConfig
|
public IGameConfig,
|
||||||
|
public ke::Refcounted<CGameConfig>
|
||||||
{
|
{
|
||||||
friend class GameConfigManager;
|
friend class GameConfigManager;
|
||||||
public:
|
public:
|
||||||
CGameConfig(const char *file);
|
CGameConfig(const char *file, const char *engine = NULL);
|
||||||
~CGameConfig();
|
~CGameConfig();
|
||||||
public:
|
public:
|
||||||
bool Reparse(char *error, size_t maxlength);
|
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
|
public: //ITextListener_SMC
|
||||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||||
@@ -63,17 +67,19 @@ public: //IGameConfig
|
|||||||
bool GetOffset(const char *key, int *value);
|
bool GetOffset(const char *key, int *value);
|
||||||
SendProp *GetSendProp(const char *key);
|
SendProp *GetSendProp(const char *key);
|
||||||
bool GetMemSig(const char *key, void **addr);
|
bool GetMemSig(const char *key, void **addr);
|
||||||
public:
|
bool GetAddress(const char *key, void **addr);
|
||||||
void IncRefCount();
|
public: //NameHashSet
|
||||||
unsigned int DecRefCount();
|
static inline bool matches(const char *key, const CGameConfig *value)
|
||||||
|
{
|
||||||
|
return strcmp(key, value->m_File) == 0;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
BaseStringTable *m_pStrings;
|
char m_File[PLATFORM_MAX_PATH];
|
||||||
char *m_pFile;
|
char m_CurFile[PLATFORM_MAX_PATH];
|
||||||
Trie *m_pOffsets;
|
StringHashMap<int> m_Offsets;
|
||||||
Trie *m_pProps;
|
StringHashMap<SendProp *> m_Props;
|
||||||
Trie *m_pKeys;
|
StringHashMap<ke::AString> m_Keys;
|
||||||
Trie *m_pSigs;
|
StringHashMap<void *> m_Sigs;
|
||||||
unsigned int m_RefCount;
|
|
||||||
/* Parse states */
|
/* Parse states */
|
||||||
int m_ParseState;
|
int m_ParseState;
|
||||||
unsigned int m_IgnoreLevel;
|
unsigned int m_IgnoreLevel;
|
||||||
@@ -82,6 +88,35 @@ private:
|
|||||||
char m_offset[64];
|
char m_offset[64];
|
||||||
char m_Game[256];
|
char m_Game[256];
|
||||||
bool bShouldBeReadingDefault;
|
bool bShouldBeReadingDefault;
|
||||||
|
bool had_game;
|
||||||
|
bool matched_game;
|
||||||
|
bool had_engine;
|
||||||
|
bool matched_engine;
|
||||||
|
bool matched_platform;
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
StringHashMap<AddressConf> m_Addresses;
|
||||||
|
const char *m_pEngine;
|
||||||
|
const char *m_pBaseEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameConfigManager :
|
class GameConfigManager :
|
||||||
@@ -97,13 +132,20 @@ public: //IGameConfigManager
|
|||||||
IGameConfig *ReadHandle(Handle_t hndl,
|
IGameConfig *ReadHandle(Handle_t hndl,
|
||||||
IdentityToken_t *ident,
|
IdentityToken_t *ident,
|
||||||
HandleError *err);
|
HandleError *err);
|
||||||
|
void AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
|
||||||
|
void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
|
||||||
|
void AcquireLock();
|
||||||
|
void ReleaseLock();
|
||||||
public: //SMGlobalClass
|
public: //SMGlobalClass
|
||||||
void OnSourceModStartup(bool late);
|
void OnSourceModStartup(bool late);
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
void OnSourceModAllShutdown();
|
void OnSourceModAllShutdown();
|
||||||
|
public:
|
||||||
|
void RemoveCachedConfig(CGameConfig *config);
|
||||||
private:
|
private:
|
||||||
List<CGameConfig *> m_cfgs;
|
NameHashSet<CGameConfig *> m_Lookup;
|
||||||
Trie *m_pLookup;
|
public:
|
||||||
|
StringHashMap<ITextListener_SMC *> m_customHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GameConfigManager g_GameConfigs;
|
extern GameConfigManager g_GameConfigs;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -30,13 +30,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "HandleSys.h"
|
#include "HandleSys.h"
|
||||||
#include "ShareSys.h"
|
|
||||||
#include "PluginSys.h"
|
|
||||||
#include "ExtensionSys.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sm_stringutil.h"
|
#include "common_logic.h"
|
||||||
|
#include "ShareSys.h"
|
||||||
|
#include "ExtensionSys.h"
|
||||||
|
#include "PluginSys.h"
|
||||||
|
|
||||||
HandleSystem g_HandleSys;
|
HandleSystem g_HandleSys;
|
||||||
|
|
||||||
@@ -60,9 +59,6 @@ HandleSystem::HandleSystem()
|
|||||||
m_Types = new QHandleType[HANDLESYS_TYPEARRAY_SIZE];
|
m_Types = new QHandleType[HANDLESYS_TYPEARRAY_SIZE];
|
||||||
memset(m_Types, 0, sizeof(QHandleType) * HANDLESYS_TYPEARRAY_SIZE);
|
memset(m_Types, 0, sizeof(QHandleType) * HANDLESYS_TYPEARRAY_SIZE);
|
||||||
|
|
||||||
m_TypeLookup = sm_trie_create();
|
|
||||||
m_strtab = new BaseStringTable(512);
|
|
||||||
|
|
||||||
m_TypeTail = 0;
|
m_TypeTail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +66,6 @@ HandleSystem::~HandleSystem()
|
|||||||
{
|
{
|
||||||
delete [] m_Handles;
|
delete [] m_Handles;
|
||||||
delete [] m_Types;
|
delete [] m_Types;
|
||||||
sm_trie_destroy(m_TypeLookup);
|
|
||||||
delete m_strtab;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -145,12 +139,10 @@ HandleType_t HandleSystem::CreateType(const char *name,
|
|||||||
|
|
||||||
if (name && name[0] != '\0')
|
if (name && name[0] != '\0')
|
||||||
{
|
{
|
||||||
if (sm_trie_retrieve(m_TypeLookup, name, NULL))
|
if (m_TypeLookup.contains(name))
|
||||||
{
|
{
|
||||||
if (err)
|
if (err)
|
||||||
{
|
|
||||||
*err = HandleError_Parameter;
|
*err = HandleError_Parameter;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,10 +204,8 @@ HandleType_t HandleSystem::CreateType(const char *name,
|
|||||||
pType->dispatch = dispatch;
|
pType->dispatch = dispatch;
|
||||||
if (name && name[0] != '\0')
|
if (name && name[0] != '\0')
|
||||||
{
|
{
|
||||||
pType->nameIdx = m_strtab->AddString(name);
|
pType->name = new ke::AString(name);
|
||||||
sm_trie_insert(m_TypeLookup, name, (void *)pType);
|
m_TypeLookup.insert(name, pType);
|
||||||
} else {
|
|
||||||
pType->nameIdx = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pType->opened = 0;
|
pType->opened = 0;
|
||||||
@@ -243,21 +233,14 @@ HandleType_t HandleSystem::CreateType(const char *name,
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HandleSystem::FindHandleType(const char *name, HandleType_t *type)
|
bool HandleSystem::FindHandleType(const char *name, HandleType_t *aResult)
|
||||||
{
|
{
|
||||||
QHandleType *_type;
|
QHandleType *type;
|
||||||
|
if (!m_TypeLookup.retrieve(name, &type))
|
||||||
if (!sm_trie_retrieve(m_TypeLookup, name, (void **)&_type))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int offset = _type - m_Types;
|
if (aResult)
|
||||||
|
*aResult = type - m_Types;
|
||||||
if (type)
|
|
||||||
{
|
|
||||||
*type = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -493,7 +476,7 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
|
|||||||
unsigned int serial = (handle >> 16);
|
unsigned int serial = (handle >> 16);
|
||||||
unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
|
unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
|
||||||
|
|
||||||
if (index == 0 || index == 0xFFFF)
|
if (index == 0 || index > m_HandleTail || index > HANDLESYS_MAX_HANDLES)
|
||||||
{
|
{
|
||||||
return HandleError_Index;
|
return HandleError_Index;
|
||||||
}
|
}
|
||||||
@@ -579,6 +562,7 @@ HandleError HandleSystem::CloneHandle(QHandle *pHandle, unsigned int index, Hand
|
|||||||
}
|
}
|
||||||
|
|
||||||
pNewHandle->clone = index;
|
pNewHandle->clone = index;
|
||||||
|
pNewHandle->object = NULL;
|
||||||
pHandle->refcount++;
|
pHandle->refcount++;
|
||||||
|
|
||||||
*newhandle = new_handle;
|
*newhandle = new_handle;
|
||||||
@@ -620,8 +604,53 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, Iden
|
|||||||
return CloneHandle(pHandle, index, newhandle, newOwner);
|
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)
|
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];
|
QHandleType *pType = &m_Types[pHandle->type];
|
||||||
|
|
||||||
if (pHandle->clone)
|
if (pHandle->clone)
|
||||||
@@ -636,6 +665,7 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
|||||||
pMaster = &m_Handles[master];
|
pMaster = &m_Handles[master];
|
||||||
|
|
||||||
/* Release the clone now */
|
/* Release the clone now */
|
||||||
|
pHandle->is_destroying = true;
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
|
|
||||||
/* Decrement the master's reference count */
|
/* Decrement the master's reference count */
|
||||||
@@ -644,20 +674,27 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
|||||||
/* Type should be the same but do this anyway... */
|
/* Type should be the same but do this anyway... */
|
||||||
pType = &m_Types[pMaster->type];
|
pType = &m_Types[pMaster->type];
|
||||||
pMaster->is_destroying = true;
|
pMaster->is_destroying = true;
|
||||||
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
if (pMaster->object)
|
||||||
|
{
|
||||||
|
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
||||||
|
}
|
||||||
ReleasePrimHandle(master);
|
ReleasePrimHandle(master);
|
||||||
}
|
}
|
||||||
} else if (pHandle->set == HandleSet_Identity) {
|
} else if (pHandle->set == HandleSet_Identity) {
|
||||||
/* If we're an identity, skip all this stuff!
|
/* If we're an identity, skip all this stuff!
|
||||||
* NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
|
* NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
|
||||||
*/
|
*/
|
||||||
|
pHandle->is_destroying = true;
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
} else {
|
} else {
|
||||||
/* Decrement, free if necessary */
|
/* Decrement, free if necessary */
|
||||||
if (--pHandle->refcount == 0)
|
if (--pHandle->refcount == 0)
|
||||||
{
|
{
|
||||||
pHandle->is_destroying = true;
|
pHandle->is_destroying = true;
|
||||||
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
if (pHandle->object)
|
||||||
|
{
|
||||||
|
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
||||||
|
}
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
} else {
|
} else {
|
||||||
/* We must be cloned, so mark ourselves as freed */
|
/* We must be cloned, so mark ourselves as freed */
|
||||||
@@ -690,14 +727,6 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSec
|
|||||||
return HandleError_Access;
|
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);
|
return FreeHandle(pHandle, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -756,6 +785,9 @@ void HandleSystem::UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index)
|
|||||||
assert(pHandle->owner == 0);
|
assert(pHandle->owner == 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pHandle->owner = NULL;
|
||||||
|
|
||||||
/* Note that since 0 is an invalid handle, if any of these links are 0,
|
/* Note that since 0 is an invalid handle, if any of these links are 0,
|
||||||
* the data can still be set.
|
* the data can still be set.
|
||||||
*/
|
*/
|
||||||
@@ -865,10 +897,6 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
|
|||||||
m_Types[++m_FreeTypes].freeID = type;
|
m_Types[++m_FreeTypes].freeID = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invalidate the type now */
|
|
||||||
IHandleTypeDispatch *dispatch = pType->dispatch;
|
|
||||||
pType->dispatch = NULL;
|
|
||||||
|
|
||||||
/* Make sure nothing is using this type. */
|
/* Make sure nothing is using this type. */
|
||||||
if (pType->opened)
|
if (pType->opened)
|
||||||
{
|
{
|
||||||
@@ -880,29 +908,9 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pHandle->clone)
|
|
||||||
{
|
FreeHandle(pHandle, i);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pType->opened == 0)
|
if (pType->opened == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -910,6 +918,13 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Invalidate the type now */
|
||||||
|
pType->dispatch = NULL;
|
||||||
|
|
||||||
|
/* Remove it from the type cache. */
|
||||||
|
if (pType->name)
|
||||||
|
m_TypeLookup.remove(pType->name->chars());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -941,14 +956,17 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
||||||
|
smcore.LogFatal(message, ##__VA_ARGS__); \
|
||||||
|
smcore.LogError(message, ##__VA_ARGS__);
|
||||||
|
|
||||||
bool HandleSystem::TryAndFreeSomeHandles()
|
bool HandleSystem::TryAndFreeSomeHandles()
|
||||||
{
|
{
|
||||||
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
|
|
||||||
IPlugin *highest_owner = NULL;
|
IPlugin *highest_owner = NULL;
|
||||||
unsigned int highest_handle_count = 0;
|
unsigned int highest_handle_count = 0;
|
||||||
|
|
||||||
/* Search all plugins */
|
/* 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();
|
IPlugin *plugin = pl_iter->GetPlugin();
|
||||||
IdentityToken_t *identity = plugin->GetIdentity();
|
IdentityToken_t *identity = plugin->GetIdentity();
|
||||||
@@ -977,8 +995,6 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
|||||||
highest_owner = plugin;
|
highest_owner = plugin;
|
||||||
highest_handle_count = handle_count;
|
highest_handle_count = handle_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_iter->NextPlugin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (highest_owner == NULL || highest_handle_count == 0)
|
if (highest_owner == NULL || highest_handle_count == 0)
|
||||||
@@ -986,13 +1002,66 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Logger.LogFatal("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
|
HANDLE_LOG_VERY_BAD("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
|
||||||
g_Logger.LogFatal("[SM] Reloading plugin to free %d handles.", highest_handle_count);
|
HANDLE_LOG_VERY_BAD("[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] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
||||||
|
HANDLE_LOG_VERY_BAD("--------------------------------------------------------------------------");
|
||||||
|
|
||||||
highest_owner->GetContext()->n_err = SP_ERROR_MEMACCESS;
|
const IdentityToken_t *pIdentity = highest_owner->GetIdentity();
|
||||||
|
unsigned int total = 0, highest_index = 0, total_size = 0, size;
|
||||||
|
unsigned int * pCount = new unsigned int[HANDLESYS_TYPEARRAY_SIZE+1];
|
||||||
|
memset(pCount, 0, ((HANDLESYS_TYPEARRAY_SIZE + 1) * sizeof(unsigned int)));
|
||||||
|
|
||||||
return g_PluginSys.UnloadPlugin(highest_owner);
|
for (unsigned int i = 1; i <= m_HandleTail; ++i)
|
||||||
|
{
|
||||||
|
const QHandle &Handle = m_Handles[i];
|
||||||
|
if (Handle.set != HandleSet_Used || Handle.owner != pIdentity)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++pCount[Handle.type];
|
||||||
|
++total;
|
||||||
|
|
||||||
|
if (Handle.type >= highest_index)
|
||||||
|
{
|
||||||
|
highest_index = ((Handle.type) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Handle.clone != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Types[Handle.type].dispatch->GetHandleApproxSize(Handle.type, Handle.object, &size))
|
||||||
|
{
|
||||||
|
total_size += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * pTypeName = NULL;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < highest_index; ++i)
|
||||||
|
{
|
||||||
|
if (pCount[i] == 0)
|
||||||
|
{
|
||||||
|
continue; /* We may have gaps, it's fine. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_Types[i].name)
|
||||||
|
pTypeName = m_Types[i].name->chars();
|
||||||
|
else
|
||||||
|
pTypeName = "ANON";
|
||||||
|
|
||||||
|
HANDLE_LOG_VERY_BAD("Type\t%-20.20s|\tCount\t%u", pTypeName, pCount[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE_LOG_VERY_BAD("-- Approximately %d bytes of memory are in use by (%u) Handles.\n", total_size, total);
|
||||||
|
delete [] pCount;
|
||||||
|
|
||||||
|
highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
|
||||||
|
|
||||||
|
return scripts->UnloadPlugin(highest_owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleSystem::Dump(HANDLE_REPORTER rep)
|
void HandleSystem::Dump(HANDLE_REPORTER rep)
|
||||||
@@ -1017,20 +1086,20 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
|
|||||||
{
|
{
|
||||||
owner = "CORE";
|
owner = "CORE";
|
||||||
}
|
}
|
||||||
else if (pOwner == g_PluginSys.GetIdentity())
|
else if (pOwner == scripts->GetIdentity())
|
||||||
{
|
{
|
||||||
owner = "PLUGINSYS";
|
owner = "PLUGINSYS";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner);
|
IExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner);
|
||||||
if (ext)
|
if (ext)
|
||||||
{
|
{
|
||||||
owner = ext->GetFilename();
|
owner = ext->GetFilename();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CPlugin *pPlugin = g_PluginSys.GetPluginFromIdentity(pOwner);
|
SMPlugin *pPlugin = scripts->FindPluginByIdentity(pOwner);
|
||||||
if (pPlugin)
|
if (pPlugin)
|
||||||
{
|
{
|
||||||
owner = pPlugin->GetFilename();
|
owner = pPlugin->GetFilename();
|
||||||
@@ -1045,19 +1114,37 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
|
|||||||
const char *type = "ANON";
|
const char *type = "ANON";
|
||||||
QHandleType *pType = &m_Types[m_Handles[i].type];
|
QHandleType *pType = &m_Types[m_Handles[i].type];
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
if (pType->nameIdx != -1)
|
unsigned int parentIdx;
|
||||||
|
bool bresult;
|
||||||
|
if (pType->name)
|
||||||
|
type = pType->name->chars();
|
||||||
|
|
||||||
|
if ((parentIdx = m_Handles[i].clone) != 0)
|
||||||
{
|
{
|
||||||
type = m_strtab->GetString(pType->nameIdx);
|
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
|
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");
|
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
UTIL_Format(buffer, sizeof(buffer), "%d", size);
|
smcore.Format(buffer, sizeof(buffer), "%d", size);
|
||||||
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
|
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
|
||||||
total_size += size;
|
total_size += size;
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* vim: set ts=4 :
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
* SourceMod
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
* =============================================================================
|
* =============================================================================
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it under
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
@@ -34,10 +34,9 @@
|
|||||||
|
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "sm_globals.h"
|
#include <sm_namehashset.h>
|
||||||
#include "sm_trie.h"
|
#include <am-string.h>
|
||||||
#include "sourcemod.h"
|
#include "common_logic.h"
|
||||||
#include "sm_memtable.h"
|
|
||||||
|
|
||||||
#define HANDLESYS_MAX_HANDLES (1<<14)
|
#define HANDLESYS_MAX_HANDLES (1<<14)
|
||||||
#define HANDLESYS_MAX_TYPES (1<<9)
|
#define HANDLESYS_MAX_TYPES (1<<9)
|
||||||
@@ -104,7 +103,12 @@ struct QHandleType
|
|||||||
TypeAccess typeSec;
|
TypeAccess typeSec;
|
||||||
HandleAccess hndlSec;
|
HandleAccess hndlSec;
|
||||||
unsigned int opened;
|
unsigned int opened;
|
||||||
int nameIdx;
|
ke::AutoPtr<ke::AString> name;
|
||||||
|
|
||||||
|
static inline bool matches(const char *key, const QHandleType *type)
|
||||||
|
{
|
||||||
|
return type->name && type->name->compare(key) == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (HANDLE_REPORTER)(const char *str, ...);
|
typedef void (HANDLE_REPORTER)(const char *str, ...);
|
||||||
@@ -160,6 +164,9 @@ public: //IHandleSystem
|
|||||||
HandleError *err);
|
HandleError *err);
|
||||||
|
|
||||||
void Dump(HANDLE_REPORTER rep);
|
void Dump(HANDLE_REPORTER rep);
|
||||||
|
|
||||||
|
/* Bypasses security checks. */
|
||||||
|
Handle_t FastCloneHandle(Handle_t hndl);
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Decodes a handle with sanity and security checking.
|
* Decodes a handle with sanity and security checking.
|
||||||
@@ -170,6 +177,9 @@ protected:
|
|||||||
unsigned int *index,
|
unsigned int *index,
|
||||||
bool ignoreFree=false);
|
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.
|
* Creates a basic handle and sets its reference count to 1.
|
||||||
* Does not do any type or security checking.
|
* Does not do any type or security checking.
|
||||||
@@ -211,15 +221,37 @@ protected:
|
|||||||
private:
|
private:
|
||||||
QHandle *m_Handles;
|
QHandle *m_Handles;
|
||||||
QHandleType *m_Types;
|
QHandleType *m_Types;
|
||||||
Trie *m_TypeLookup;
|
NameHashSet<QHandleType *> m_TypeLookup;
|
||||||
unsigned int m_TypeTail;
|
unsigned int m_TypeTail;
|
||||||
unsigned int m_FreeTypes;
|
unsigned int m_FreeTypes;
|
||||||
unsigned int m_HandleTail;
|
unsigned int m_HandleTail;
|
||||||
unsigned int m_FreeHandles;
|
unsigned int m_FreeHandles;
|
||||||
unsigned int m_HSerial;
|
unsigned int m_HSerial;
|
||||||
BaseStringTable *m_strtab;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern HandleSystem g_HandleSys;
|
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_
|
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||||
@@ -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
|
* SourceMod
|
||||||
* Copyright (C) 2004-2007 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
|
* 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
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
* or <http://www.sourcemod.net/license.php>.
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
||||||
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
||||||
|
|
||||||
|
#include "common_logic.h"
|
||||||
#include <IMemoryUtils.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;
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
#ifdef PLATFORM_APPLE
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct DynLibInfo
|
struct DynLibInfo
|
||||||
{
|
{
|
||||||
void *baseAddress;
|
void *baseAddress;
|
||||||
size_t memorySize;
|
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 :
|
class MemoryUtils :
|
||||||
public IMemoryUtils,
|
public IMemoryUtils,
|
||||||
public SMGlobalClass
|
public SMGlobalClass
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
MemoryUtils();
|
||||||
|
~MemoryUtils();
|
||||||
public: // SMGlobalClass
|
public: // SMGlobalClass
|
||||||
void OnSourceModAllInitialized();
|
void OnSourceModAllInitialized();
|
||||||
public: // IMemoryUtils
|
public: // IMemoryUtils
|
||||||
void *FindPattern(const void *libPtr, const char *pattern, size_t len);
|
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);
|
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;
|
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
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* 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_native_h_
|
||||||
|
#define _include_sourcemod_native_h_
|
||||||
|
|
||||||
|
#include <IShareSys.h>
|
||||||
|
#include <IHandleSys.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <am-utility.h>
|
||||||
|
#include <am-refcounting.h>
|
||||||
|
#include "common_logic.h"
|
||||||
|
|
||||||
|
struct FakeNative
|
||||||
|
{
|
||||||
|
FakeNative(const char *name, IPluginFunction *fun)
|
||||||
|
: name(name),
|
||||||
|
ctx(fun->GetParentContext()),
|
||||||
|
call(fun),
|
||||||
|
gate(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~FakeNative();
|
||||||
|
|
||||||
|
ke::AString name;
|
||||||
|
IPluginContext *ctx;
|
||||||
|
IPluginFunction *call;
|
||||||
|
SPVM_NATIVE_FUNC gate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Native : public ke::Refcounted<Native>
|
||||||
|
{
|
||||||
|
Native(CNativeOwner *owner, const sp_nativeinfo_t *native)
|
||||||
|
: owner(owner),
|
||||||
|
native(native),
|
||||||
|
fake(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Native(CNativeOwner *owner, FakeNative *fake)
|
||||||
|
: owner(owner),
|
||||||
|
native(NULL),
|
||||||
|
fake(fake)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CNativeOwner *owner;
|
||||||
|
const sp_nativeinfo_t *native;
|
||||||
|
ke::AutoPtr<FakeNative> fake;
|
||||||
|
|
||||||
|
SPVM_NATIVE_FUNC func() const
|
||||||
|
{
|
||||||
|
if (native)
|
||||||
|
return native->func;
|
||||||
|
return fake->gate;
|
||||||
|
}
|
||||||
|
const char *name() const
|
||||||
|
{
|
||||||
|
if (native)
|
||||||
|
return native->name;
|
||||||
|
return fake->name.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool matches(const char *name, const ke::Ref<Native> &entry)
|
||||||
|
{
|
||||||
|
return strcmp(name, entry->name()) == 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _include_sourcemod_native_h_
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user