Compare commits
676
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4acbd45a34 | ||
|
|
c46a4e0a41 | ||
|
|
4916b99c1a | ||
|
|
012d58cc29 | ||
|
|
e7344c6b62 | ||
|
|
e41c7fddca | ||
|
|
4b1d372004 | ||
|
|
d120789a23 | ||
|
|
154be77ccb | ||
|
|
d5d620340d | ||
|
|
4c29a78f56 | ||
|
|
f05b9ef600 | ||
|
|
6a8e6837a7 | ||
|
|
d9bfdd3ae4 | ||
|
|
0c29170bba | ||
|
|
7f2765af9b | ||
|
|
51ae63bd78 | ||
|
|
f37c188b5a | ||
|
|
34ae5da0cb | ||
|
|
365dee321f | ||
|
|
aea5ad1459 | ||
|
|
2aa592ae2f | ||
|
|
fef508156b | ||
|
|
9347be33c3 | ||
|
|
52ed344653 | ||
|
|
a25b9d4b53 | ||
|
|
9e0590e12f | ||
|
|
f6b9b99abe | ||
|
|
2b5bf29dfc | ||
|
|
ee7413bbdd | ||
|
|
764d63a533 | ||
|
|
bcbff0b2e9 | ||
|
|
35b74715d8 | ||
|
|
e0639de6a0 | ||
|
|
f025fd8a05 | ||
|
|
625848b95d | ||
|
|
2de9d5f9cb | ||
|
|
ab15436a7f | ||
|
|
e507aa5025 | ||
|
|
8b205b0d5d | ||
|
|
e4e54510c8 | ||
|
|
d706023c74 | ||
|
|
8df27acc1f | ||
|
|
4c5c2eae24 | ||
|
|
bc4eecae8f | ||
|
|
218b9b1fab | ||
|
|
0750b93797 | ||
|
|
41b0e7fc53 | ||
|
|
801815b742 | ||
|
|
01a826268b | ||
|
|
55ec20b215 | ||
|
|
dc550c25e5 | ||
|
|
ad842e4665 | ||
|
|
f7398119f4 | ||
|
|
b21337c56d | ||
|
|
c1d040e153 | ||
|
|
4c3fb52c69 | ||
|
|
31c29fb33e | ||
|
|
87af9af0f6 | ||
|
|
ebb26e6144 | ||
|
|
50c15f4f78 | ||
|
|
e02bdca793 | ||
|
|
8bcbe128e7 | ||
|
|
68991bc733 | ||
|
|
d77d1de462 | ||
|
|
e1081c0a50 | ||
|
|
2b3f888712 | ||
|
|
b8e530ab7e | ||
|
|
274539cf49 | ||
|
|
6e92d0df4f | ||
|
|
1bb5f0e52b | ||
|
|
1af3446593 | ||
|
|
b70b8cf0cb | ||
|
|
8dca4bf093 | ||
|
|
a7d170bf13 | ||
|
|
f5865ee46f | ||
|
|
adac0f17c4 | ||
|
|
b8b9e4db90 | ||
|
|
5fdb4d05fa | ||
|
|
93768cfd4d | ||
|
|
8cdd3faa89 | ||
|
|
98dee0097a | ||
|
|
090cc9f818 | ||
|
|
9abbe96a7f | ||
|
|
3aeab98517 | ||
|
|
11daaac1b4 | ||
|
|
15c5ed1dd3 | ||
|
|
1bb9adc767 | ||
|
|
dd83c23cda | ||
|
|
e8a6040926 | ||
|
|
5ff8ec62e0 | ||
|
|
1f06a6951d | ||
|
|
d65f993c53 | ||
|
|
c5e37e15e6 | ||
|
|
c4473acc4e | ||
|
|
8e845b0a33 | ||
|
|
26c3193653 | ||
|
|
ee19cf4045 | ||
|
|
fca7c4f4a3 | ||
|
|
b811336c1e | ||
|
|
3fc3ab4372 | ||
|
|
6434cc7bf0 | ||
|
|
d8e3e7e11d | ||
|
|
061a958b9f | ||
|
|
294afcca2a | ||
|
|
e8834ed9cb | ||
|
|
a37e6bbb8b | ||
|
|
4d007d6b2a | ||
|
|
9527457ca0 | ||
|
|
f7d3396001 | ||
|
|
55508e0068 | ||
|
|
cc691da4d0 | ||
|
|
d05d47139d | ||
|
|
47e02e0f6c | ||
|
|
5202c1361f | ||
|
|
1d13430519 | ||
|
|
1852813741 | ||
|
|
d711c17534 | ||
|
|
717606deef | ||
|
|
5d01407ad5 | ||
|
|
41fcefad5f | ||
|
|
01f912611e | ||
|
|
f0ad0b110e | ||
|
|
fb35cf52f5 | ||
|
|
fe435ca0ab | ||
|
|
f356cb78f9 | ||
|
|
e5d1e0b319 | ||
|
|
9188e9f6a9 | ||
|
|
8e72f57333 | ||
|
|
df1e56e408 | ||
|
|
4afbf67ce1 | ||
|
|
5c1efcb4d6 | ||
|
|
f3fb84d1d0 | ||
|
|
6cae738f1c | ||
|
|
bff4fe01e3 | ||
|
|
959c571fc6 | ||
|
|
c5c8b90262 | ||
|
|
8744c1871d | ||
|
|
98a1dc7757 | ||
|
|
4064c6f1c2 | ||
|
|
04c2e47a5f | ||
|
|
2f03f53ab1 | ||
|
|
0d2819e3b5 | ||
|
|
8d16ac2295 | ||
|
|
714e71b6c3 | ||
|
|
0c16c6ebe9 | ||
|
|
1b9ce5f484 | ||
|
|
c4390478fc | ||
|
|
7d97de8a10 | ||
|
|
51bee0f420 | ||
|
|
04642a7cc0 | ||
|
|
8a0a911d43 | ||
|
|
fae6673957 | ||
|
|
63f50b1e73 | ||
|
|
f53746f720 | ||
|
|
5dd18eeaad | ||
|
|
7316b6255c | ||
|
|
eb2605f1a3 | ||
|
|
01a3a09d96 | ||
|
|
01e7fb463b | ||
|
|
f8f6f2cf6c | ||
|
|
99ae90ecc5 | ||
|
|
d64125ddd4 | ||
|
|
7fb3632fd7 | ||
|
|
49e2303a5b | ||
|
|
fe0b9f7320 | ||
|
|
b16c758f88 | ||
|
|
da729c3c08 | ||
|
|
f1bcb2ad3e | ||
|
|
9270399eb1 | ||
|
|
76e6edbad4 | ||
|
|
58ca1508bc | ||
|
|
eed1df28ec | ||
|
|
a602d7d107 | ||
|
|
9a08986fd1 | ||
|
|
5d1820853a | ||
|
|
753aced2a3 | ||
|
|
df47457321 | ||
|
|
d9e818e5d9 | ||
|
|
47c840c9b4 | ||
|
|
2bfc5d3e1e | ||
|
|
4307c57697 | ||
|
|
bff0faff52 | ||
|
|
749966ae66 | ||
|
|
9f11132fb5 | ||
|
|
2dfbd1fc1f | ||
|
|
7c659837bf | ||
|
|
7cf342a1a7 | ||
|
|
e8d6aab989 | ||
|
|
0819278465 | ||
|
|
d89c57ba79 | ||
|
|
23b10fc559 | ||
|
|
36e8e881e8 | ||
|
|
67011834df | ||
|
|
ed9f68814f | ||
|
|
79a8008280 | ||
|
|
643dce8cb1 | ||
|
|
3669b98986 | ||
|
|
e075b7b9b2 | ||
|
|
b95fda8342 | ||
|
|
5abec70579 | ||
|
|
8800d5311c | ||
|
|
3705210879 | ||
|
|
5f4befcb6a | ||
|
|
314011f118 | ||
|
|
a9b7a5dc5c | ||
|
|
9b78c68b1b | ||
|
|
328109be1f | ||
|
|
aba0f29666 | ||
|
|
bdefb58e5f | ||
|
|
7ad3a57c47 | ||
|
|
5a2f3cf433 | ||
|
|
fffc27a348 | ||
|
|
cecb7cb6a2 | ||
|
|
f5cc5eb757 | ||
|
|
689406744b | ||
|
|
603da899b7 | ||
|
|
9b4d1f6972 | ||
|
|
d56b222637 | ||
|
|
dfefda81e1 | ||
|
|
0c463b1f86 | ||
|
|
bf345eea8c | ||
|
|
5328447b74 | ||
|
|
db6881b7e3 | ||
|
|
3e96b1617a | ||
|
|
7ef8b415bb | ||
|
|
9a5d6957b9 | ||
|
|
b5a2ec7a5e | ||
|
|
373136af4e | ||
|
|
8673c11341 | ||
|
|
8c082de148 | ||
|
|
e62d47a85e | ||
|
|
2d32c587ba | ||
|
|
31e29ee94c | ||
|
|
e95e453258 | ||
|
|
48b0f61551 | ||
|
|
ef88fc21a1 | ||
|
|
558c8c9745 | ||
|
|
2f60680cfb | ||
|
|
1ffcf7a664 | ||
|
|
c00b688ab7 | ||
|
|
4169e25451 | ||
|
|
85fc65bae5 | ||
|
|
aed62d5670 | ||
|
|
01d46b8c9c | ||
|
|
f70b48276e | ||
|
|
f0070e45a0 | ||
|
|
11782cee90 | ||
|
|
24b86584a2 | ||
|
|
01b3eee1b8 | ||
|
|
2fb3f8ab0f | ||
|
|
2c7b0e04e9 | ||
|
|
9f3e9a2ff4 | ||
|
|
d9d5b65f2c | ||
|
|
90cc2d6c37 | ||
|
|
1ab5403f9f | ||
|
|
4d03a4ef60 | ||
|
|
46b714108a | ||
|
|
242e1c99e2 | ||
|
|
3d0e661cd6 | ||
|
|
d076aca9ea | ||
|
|
f824a53f21 | ||
|
|
87ca5e6e05 | ||
|
|
23af5357c0 | ||
|
|
d6b82d5dcc | ||
|
|
664da97c42 | ||
|
|
b6507b12d4 | ||
|
|
a5ab381c0a | ||
|
|
8ec5e42c7a | ||
|
|
006423dcf2 | ||
|
|
d0f4d943b6 | ||
|
|
2fd9674e09 | ||
|
|
23fca5e645 | ||
|
|
4beb7fe869 | ||
|
|
2e832f2d01 | ||
|
|
43602da743 | ||
|
|
763b73b9c5 | ||
|
|
ffb6e84b45 | ||
|
|
025f216e09 | ||
|
|
603ac75a08 | ||
|
|
1b07722848 | ||
|
|
4de8d67e27 | ||
|
|
83baabe00a | ||
|
|
3080ca1ccb | ||
|
|
c3b0f8a4d2 | ||
|
|
726ee43736 | ||
|
|
8e1f37a5d2 | ||
|
|
ce342ef6fc | ||
|
|
0a6acda737 | ||
|
|
c907c723c3 | ||
|
|
479815911d | ||
|
|
29954ec122 | ||
|
|
75455b65da | ||
|
|
5688eb55ec | ||
|
|
2e4aae95db | ||
|
|
cc43b63508 | ||
|
|
59593a2d5f | ||
|
|
e3f5d5b6cf | ||
|
|
6085125367 | ||
|
|
27805463e3 | ||
|
|
45f2b9f8ca | ||
|
|
2bd979d62e | ||
|
|
e434c43e28 | ||
|
|
02922df1cd | ||
|
|
035875f5c1 | ||
|
|
e3a3dda1d8 | ||
|
|
7187dde64d | ||
|
|
fd09d7b176 | ||
|
|
4e8fc2749b | ||
|
|
8b362700ff | ||
|
|
e926a3b94b | ||
|
|
83d1fc9abe | ||
|
|
d6a5d99e55 | ||
|
|
6322a711c2 | ||
|
|
e024871b50 | ||
|
|
b4e939e273 | ||
|
|
13743376ee | ||
|
|
69cfd36054 | ||
|
|
7d15ec4d15 | ||
|
|
b52a10f28b | ||
|
|
da7c65f0e3 | ||
|
|
a5d2945fc5 | ||
|
|
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 | ||
|
|
2c3bf7dd23 | ||
|
|
5e6417eac0 | ||
|
|
09b24e45f9 | ||
|
|
fc7f9ac6e9 | ||
|
|
7dcc7ea99c | ||
|
|
4590015ed6 | ||
|
|
79f9dc61a4 | ||
|
|
3fac7d027a | ||
|
|
10ba5809d2 | ||
|
|
792204bd06 | ||
|
|
f19cb010a0 | ||
|
|
ca3df3bd50 | ||
|
|
db43487b5a | ||
|
|
44a04e6167 | ||
|
|
9d6a9eb615 | ||
|
|
27070af1b9 | ||
|
|
32d2d4107d | ||
|
|
75ebac822d | ||
|
|
bd9fab6cf5 | ||
|
|
d75f8f11e1 | ||
|
|
47900db414 | ||
|
|
b61542242c | ||
|
|
13c1fd09c4 | ||
|
|
fddb69e49e | ||
|
|
ed51d5cf84 | ||
|
|
3d7b0db114 | ||
|
|
9e445a5adf | ||
|
|
97e25c37de | ||
|
|
16033c1307 | ||
|
|
15d64b8486 | ||
|
|
5d06aa3c8c | ||
|
|
e276223b61 | ||
|
|
6530f47b2d | ||
|
|
ffd8ff099a | ||
|
|
e194f89b25 | ||
|
|
3bfc70aa3b | ||
|
|
93a6a0f211 | ||
|
|
cef6a2e389 | ||
|
|
4f5764e4a5 | ||
|
|
21770ff10f | ||
|
|
2b97461f54 | ||
|
|
0cf5f4ae2a | ||
|
|
7b6dcfce87 | ||
|
|
f9d472847c | ||
|
|
d69d97402b | ||
|
|
643c39690f | ||
|
|
6048144310 | ||
|
|
a017e4820a | ||
|
|
c5ec369388 | ||
|
|
52826342fc | ||
|
|
29b357a2f6 | ||
|
|
747ed1e59a | ||
|
|
992c05b6aa | ||
|
|
f4a5457941 | ||
|
|
22675ba2e7 | ||
|
|
80602b011d | ||
|
|
abea8e2195 | ||
|
|
9075aecb18 | ||
|
|
6e9ac875d7 | ||
|
|
100ecb12e9 | ||
|
|
57b4701e57 | ||
|
|
fffc211989 | ||
|
|
5a0528de26 | ||
|
|
fb8f46ea45 | ||
|
|
3653f56331 | ||
|
|
e31cbbfe21 | ||
|
|
bc3491c5bd | ||
|
|
9a7c25047d | ||
|
|
7cef8b7363 | ||
|
|
e449b8384c | ||
|
|
9514c12982 | ||
|
|
489d6c5a65 | ||
|
|
ccc59ecdaf | ||
|
|
d2ce50f989 | ||
|
|
14e409adb4 | ||
|
|
4a0f639e89 | ||
|
|
32c5925652 | ||
|
|
4c91dd8621 | ||
|
|
f641aa92f5 | ||
|
|
3bdc8583e5 | ||
|
|
4e37900d93 | ||
|
|
db760dc29b | ||
|
|
f96ca17f17 | ||
|
|
50580498c4 | ||
|
|
a21e688c96 | ||
|
|
4b1deee7e1 | ||
|
|
bf5fefe84f | ||
|
|
004d450844 | ||
|
|
7705e88b57 | ||
|
|
1577fab93a | ||
|
|
181fe74b09 | ||
|
|
cdd78b2ec3 | ||
|
|
ddc42bedf5 | ||
|
|
a7a08a7d4e | ||
|
|
0a33a25a7d | ||
|
|
2c9622ea52 | ||
|
|
5564c38a2f | ||
|
|
2a853a23d7 | ||
|
|
37da98c9bb | ||
|
|
5a5172be57 | ||
|
|
88afac51f0 | ||
|
|
dd338d40f3 | ||
|
|
1cc8440900 | ||
|
|
47cf8f4233 | ||
|
|
4e88626d65 | ||
|
|
a1b91ac136 | ||
|
|
0a0fd0c64a | ||
|
|
a7c6fc12d8 | ||
|
|
48f0a49f9b | ||
|
|
b63d714a06 | ||
|
|
7bdcea5814 | ||
|
|
f418f38589 | ||
|
|
52377b509b | ||
|
|
14152bb7ba | ||
|
|
d51aaec97d | ||
|
|
ea3fe754f4 | ||
|
|
f20603ad06 | ||
|
|
bac975331d | ||
|
|
4baf847062 | ||
|
|
90a44ea6c8 | ||
|
|
fef83838f9 | ||
|
|
1422a9abe3 | ||
|
|
984a2d26f4 | ||
|
|
f85bb7e490 | ||
|
|
843ff25de4 | ||
|
|
7a38e5584c | ||
|
|
9c1e45d97c | ||
|
|
c2756c731f | ||
|
|
d6fc82f8fa | ||
|
|
2acf1b08d5 | ||
|
|
6ffd39ac77 | ||
|
|
9ae456b9d1 | ||
|
|
5bbeddc134 | ||
|
|
373fbb6ca3 | ||
|
|
43f5d71724 | ||
|
|
41b61ed36f | ||
|
|
31e30faace | ||
|
|
ff7a2c6b73 | ||
|
|
7e3f9ada31 | ||
|
|
0a956115eb |
@@ -6,6 +6,7 @@
|
||||
# Files generated by Visual Studio
|
||||
\.aps$
|
||||
\.ncb$
|
||||
\.sdf$
|
||||
\.suo$
|
||||
\.user$
|
||||
|
||||
@@ -13,3 +14,10 @@
|
||||
/CrazyDebug.*
|
||||
/Debug.*
|
||||
/Release.*
|
||||
|
||||
# Files generated by Mac OS X Finder
|
||||
(^|/)\.DS_Store$
|
||||
|
||||
# Files generated by Windows Explorer
|
||||
(^|/)[dD]esktop\.ini$
|
||||
(^|/)[tT]humbs\.db$
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
54539fa4e51f98d7841c853c1370dff6ccd3cdf2 sourcemod-1.0.0
|
||||
e6ef5ecdf8d75740ca2685a709bf321f8873bc3b sourcemod-1.1.0
|
||||
e877885fac80be71822641f7a9122cebc9812521 sourcemod-1.1.1
|
||||
b3ffa8a4511c4eadaf533fc790aa6b14f7f0c6ea sourcemod-1.1.2
|
||||
3a73bbf60f34befa9b66be03fa5974b394bb3411 sourcemod-1.2.0
|
||||
a71318396392e3c6d0ff31e069a60fbde59e0cea sourcemod-1.3.0
|
||||
3f33d01fcc28b509bed30f7be07ed215cc000538 sourcemod-1.3.1
|
||||
a3e8f7a7fdf7f012dd02ad491a2e1ccdad151687 sourcemod-1.3.2
|
||||
c5062ca8283033cf33f45da6f19e486ca10835ff sourcemod-1.3.3
|
||||
4d6afc42522c8f416dc45be7af7b145507b00630 sourcemod-1.3.4
|
||||
9de8baa40cc593d8ca5f976a3357772e804ae9e8 sourcemod-1.3.5
|
||||
8036343199caaf2812b21bb24f1fa84bf5a9e2ef sourcemod-1.3.6
|
||||
0f35d8b324ba8f6272dac3e473f056b451a13b54 sourcemod-1.3.7
|
||||
2726e2ec8c90bfc547753c5a2a160b726587ecde sourcemod-1.3.8
|
||||
2726e2ec8c90bfc547753c5a2a160b726587ecde sourcemod-1.3.8
|
||||
fa2f05c3ae003a01cc0d65df8998fcb1a936328e sourcemod-1.3.8
|
||||
fa2f05c3ae003a01cc0d65df8998fcb1a936328e sourcemod-1.3.8
|
||||
0000000000000000000000000000000000000000 sourcemod-1.3.8
|
||||
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
import sys
|
||||
from ambuild.command import SymlinkCommand
|
||||
|
||||
class SM:
|
||||
def __init__(self):
|
||||
self.compiler = Cpp.Compiler()
|
||||
|
||||
#Build SDK info
|
||||
self.sdkInfo = { }
|
||||
self.sdkInfo['ep1'] = {'sdk': 'HL2SDK', 'ext': '1.ep1', 'def': '1',
|
||||
'name': 'EPISODEONE'}
|
||||
self.sdkInfo['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3',
|
||||
'name': 'ORANGEBOX'}
|
||||
self.sdkInfo['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '4',
|
||||
'name': 'ORANGEBOXVALVE'}
|
||||
self.sdkInfo['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '5',
|
||||
'name': 'LEFT4DEAD'}
|
||||
self.sdkInfo['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '6',
|
||||
'name': 'LEFT4DEAD2'}
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
self.sdkInfo['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2',
|
||||
'name': 'DARKMESSIAH'}
|
||||
self.sdkInfo['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '7',
|
||||
'name': 'ALIENSWARM'}
|
||||
|
||||
if AMBuild.mode == 'config':
|
||||
#Detect compilers
|
||||
self.compiler.DetectAll(AMBuild)
|
||||
|
||||
#Detect variables
|
||||
envvars = { 'MMSOURCE18': 'mmsource-1.8',
|
||||
'HL2SDK': 'hl2sdk',
|
||||
'HL2SDKOB': 'hl2sdk-ob',
|
||||
'HL2SDKL4D': 'hl2sdk-l4d',
|
||||
'HL2SDKOBVALVE': 'hl2sdk-ob-valve',
|
||||
'HL2SDKL4D2': 'hl2sdk-l4d2',
|
||||
'MYSQL5': 'mysql-5.0'
|
||||
}
|
||||
|
||||
#Dark Messiah is Windows-only
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm'
|
||||
envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm'
|
||||
|
||||
#Must have a path for each envvar (file a bug if you don't like this)
|
||||
for i in envvars:
|
||||
if i in os.environ:
|
||||
path = os.environ[i]
|
||||
if not os.path.isdir(path):
|
||||
raise Exception('Path for {0} was not found: {1}'.format(i, path))
|
||||
else:
|
||||
head = os.getcwd()
|
||||
oldhead = None
|
||||
while head != None and head != oldhead:
|
||||
path = os.path.join(head, envvars[i])
|
||||
if os.path.isdir(path):
|
||||
break
|
||||
oldhead = head
|
||||
head, tail = os.path.split(head)
|
||||
if head == None or head == oldhead:
|
||||
raise Exception('Could not find a valid path for {0}'.format(i))
|
||||
AMBuild.cache.CacheVariable(i, path)
|
||||
|
||||
#Set up defines
|
||||
cxx = self.compiler.cxx
|
||||
if isinstance(cxx, Cpp.GCC):
|
||||
self.vendor = 'gcc'
|
||||
self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp')
|
||||
self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp')
|
||||
self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf')
|
||||
self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf')
|
||||
self.compiler.AddToListVar('CFLAGS', '-pipe')
|
||||
self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing')
|
||||
if cxx.majorVersion >= 4:
|
||||
self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wall')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Werror')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wno-unused')
|
||||
self.compiler.AddToListVar('CFLAGS', '-Wno-switch')
|
||||
self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse')
|
||||
self.compiler.AddToListVar('CFLAGS', '-msse')
|
||||
self.compiler.AddToListVar('CFLAGS', '-m32')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor')
|
||||
self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H')
|
||||
elif isinstance(cxx, Cpp.MSVC):
|
||||
self.vendor = 'msvc'
|
||||
if AMBuild.options.debug == '1':
|
||||
self.compiler.AddToListVar('CFLAGS', '/MTd')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt')
|
||||
else:
|
||||
self.compiler.AddToListVar('CFLAGS', '/MT')
|
||||
self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE')
|
||||
self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS')
|
||||
self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '/EHsc')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '/GR-')
|
||||
self.compiler.AddToListVar('CFLAGS', '/W3')
|
||||
self.compiler.AddToListVar('CFLAGS', '/nologo')
|
||||
self.compiler.AddToListVar('CFLAGS', '/Zi')
|
||||
self.compiler.AddToListVar('CXXFLAGS', '/TP')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib')
|
||||
|
||||
#Optimization
|
||||
if AMBuild.options.opt == '1':
|
||||
self.compiler.AddToListVar('CDEFINES', 'NDEBUG')
|
||||
if self.vendor == 'gcc':
|
||||
self.compiler.AddToListVar('CFLAGS', '-O3')
|
||||
elif self.vendor == 'msvc':
|
||||
self.compiler.AddToListVar('CFLAGS', '/Ox')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF')
|
||||
self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF')
|
||||
|
||||
#Debugging
|
||||
if AMBuild.options.debug == '1':
|
||||
self.compiler.AddToListVar('CDEFINES', 'DEBUG')
|
||||
self.compiler.AddToListVar('CDEFINES', '_DEBUG')
|
||||
if self.vendor == 'gcc':
|
||||
self.compiler.AddToListVar('CFLAGS', '-g3')
|
||||
elif self.vendor == 'msvc':
|
||||
self.compiler.AddToListVar('CFLAGS', '/Od')
|
||||
self.compiler.AddToListVar('CFLAGS', '/RTC1')
|
||||
|
||||
#Platform-specifics
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
self.compiler.AddToListVar('CDEFINES', '_LINUX')
|
||||
elif AMBuild.target['platform'] == 'windows':
|
||||
self.compiler.AddToListVar('CDEFINES', 'WIN32')
|
||||
self.compiler.AddToListVar('CDEFINES', '_WINDOWS')
|
||||
|
||||
#Finish up
|
||||
self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD')
|
||||
self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD')
|
||||
self.compiler.AddToListVar('CINCLUDES',
|
||||
os.path.join(AMBuild.outputFolder, 'includes'))
|
||||
self.compiler.ToConfig(AMBuild, 'compiler')
|
||||
AMBuild.cache.CacheVariable('vendor', self.vendor)
|
||||
self.targetMap = { }
|
||||
AMBuild.cache.CacheVariable('targetMap', self.targetMap)
|
||||
else:
|
||||
self.compiler.FromConfig(AMBuild, 'compiler')
|
||||
self.targetMap = AMBuild.cache['targetMap']
|
||||
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'public'))
|
||||
self.compiler.AddToListVar('RCINCLUDES',
|
||||
os.path.join(AMBuild.outputFolder, 'includes'))
|
||||
self.mmsPath = AMBuild.cache['MMSOURCE18']
|
||||
|
||||
def DefaultCompiler(self):
|
||||
return self.compiler.Clone()
|
||||
|
||||
def JobMatters(self, jobname):
|
||||
file = sys._getframe().f_code.co_filename
|
||||
if AMBuild.mode == 'config':
|
||||
self.targetMap[jobname] = file
|
||||
return True
|
||||
if len(AMBuild.args) == 0:
|
||||
return True
|
||||
if not jobname in AMBuild.args:
|
||||
return False
|
||||
|
||||
def DefaultExtCompiler(self, path):
|
||||
compiler = self.DefaultCompiler()
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, path, 'sdk'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'extensions'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'public', 'sourcepawn'))
|
||||
return compiler
|
||||
|
||||
def AutoVersion(self, folder, binary):
|
||||
if AMBuild.target['platform'] != 'windows':
|
||||
return
|
||||
env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']}
|
||||
binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env)
|
||||
|
||||
def PreSetupHL2Job(self, job, builder, sdk):
|
||||
info = self.sdkInfo[sdk]
|
||||
sdkPath = AMBuild.cache[info['sdk']]
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
if sdk == 'ep1':
|
||||
staticLibs = os.path.join(sdkPath, 'linux_sdk')
|
||||
else:
|
||||
staticLibs = os.path.join(sdkPath, 'lib', 'linux')
|
||||
workFolder = os.path.join(AMBuild.outputFolder, job.workFolder)
|
||||
if sdk in ['ep2v', 'l4d', 'l4d2']:
|
||||
for i in ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so']:
|
||||
link = os.path.join(workFolder, i)
|
||||
target = os.path.join(staticLibs, i)
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
job.AddCommand(SymlinkCommand(link, target))
|
||||
else:
|
||||
for i in ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so']:
|
||||
link = os.path.join(workFolder, i)
|
||||
target = os.path.join(staticLibs, i)
|
||||
try:
|
||||
os.lstat(link)
|
||||
except:
|
||||
job.AddCommand(SymlinkCommand(link, target))
|
||||
elif AMBuild.target['platform'] == 'windows':
|
||||
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
||||
if sdk == 'swarm':
|
||||
libs.append('interfaces')
|
||||
for lib in libs:
|
||||
libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib'
|
||||
builder.RebuildIfNewer(libPath)
|
||||
builder['POSTLINKFLAGS'].append(libPath)
|
||||
|
||||
def PostSetupHL2Job(self, job, builder, sdk):
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a'])
|
||||
|
||||
def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'):
|
||||
compiler = self.DefaultExtCompiler(path)
|
||||
|
||||
mms = 'core'
|
||||
if sdk == 'ep1':
|
||||
mms += oldMms
|
||||
|
||||
compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook'))
|
||||
|
||||
info = self.sdkInfo
|
||||
compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info])
|
||||
if AMBuild.target['platform'] != 'windows':
|
||||
compiler['CDEFINES'].extend(['SE_DARKMESSIAH=2', 'SE_ALIENSWARM=7'])
|
||||
|
||||
paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'],
|
||||
['public', 'tier0'], ['public', 'tier1']]
|
||||
if sdk == 'ep1' or sdk == 'darkm':
|
||||
paths.append(['public', 'dlls'])
|
||||
paths.append(['game_shared'])
|
||||
else:
|
||||
paths.append(['public', 'game', 'server'])
|
||||
paths.append(['game', 'shared'])
|
||||
paths.append(['common'])
|
||||
|
||||
info = self.sdkInfo[sdk]
|
||||
sdkPath = AMBuild.cache[info['sdk']]
|
||||
|
||||
compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def'])
|
||||
|
||||
if sdk == 'swarm' and AMBuild.target['platform'] == 'windows':
|
||||
compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32'])
|
||||
|
||||
if sdk == 'ep1':
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
staticLibs = os.path.join(sdkPath, 'linux_sdk')
|
||||
else:
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
staticLibs = os.path.join(sdkPath, 'lib', 'linux')
|
||||
|
||||
for i in paths:
|
||||
compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i))
|
||||
|
||||
if not noLink:
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['-lm']
|
||||
if sdk in ['ep2v', 'l4d', 'l4d2']:
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so']
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so']
|
||||
else:
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so']
|
||||
compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so']
|
||||
|
||||
return compiler
|
||||
|
||||
sm = SM()
|
||||
globals = {
|
||||
'SM': sm
|
||||
}
|
||||
|
||||
AMBuild.Include(os.path.join('tools', 'buildbot', 'Versioning'), globals)
|
||||
|
||||
FileList = [
|
||||
['loader', 'AMBuilder'],
|
||||
['core', 'AMBuilder'],
|
||||
['core', 'logic', 'AMBuilder'],
|
||||
['extensions', 'bintools', 'AMBuilder'],
|
||||
['extensions', 'clientprefs', 'AMBuilder'],
|
||||
['extensions', 'cstrike', 'AMBuilder'],
|
||||
['extensions', 'curl', 'AMBuilder'],
|
||||
['extensions', 'geoip', 'AMBuilder'],
|
||||
['extensions', 'mysql', 'AMBuilder'],
|
||||
['extensions', 'sdktools', 'AMBuilder'],
|
||||
['extensions', 'topmenus', 'AMBuilder'],
|
||||
['extensions', 'updater', 'AMBuilder'],
|
||||
['extensions', 'sqlite', 'AMBuilder'],
|
||||
['extensions', 'regex', 'AMBuilder'],
|
||||
['extensions', 'tf2', 'AMBuilder'],
|
||||
['sourcepawn', 'jit', 'AMBuilder'],
|
||||
['sourcepawn', 'compiler', 'AMBuilder'],
|
||||
['plugins', 'AMBuilder'],
|
||||
['tools', 'buildbot', 'PackageScript']
|
||||
]
|
||||
|
||||
for parts in FileList:
|
||||
AMBuild.Include(os.path.join(*parts), globals)
|
||||
|
||||
+354
@@ -1,5 +1,359 @@
|
||||
SourceMod Changelog
|
||||
|
||||
-----------------------------
|
||||
|
||||
SourceMod 1.3.8 [2011-06-23]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.8_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated support for various games, including Garry's Mod, Zombie Panic, and Dino D-Day.
|
||||
- Added gamedata for Eternal Silence.
|
||||
- Fixed libgcc_s.so.1 load error present on some systems (bug 4876).
|
||||
- Handle leak notices now print to error log (in addition fatal log) (bug 4929).
|
||||
- Translator now properly falls back on bad server language (bug 4861).
|
||||
- Fixed invalid client errors from bad MaxClients value when SourceTV is late-loaded (bug 4881).
|
||||
- Fixed crash on plugin unload when two commands exist with same name, different casing (bug 4698).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Updated TF2 condition defines (bug 4916).
|
||||
- Fixed var names and docs for TF2_MakeBleed native (bug 4928).
|
||||
- Removed compiler double include check (bug 4863).
|
||||
- Fixed plugin compile errors when using GetEntityClassname (bug 4798).
|
||||
|
||||
---------------------------
|
||||
|
||||
SourceMod 1.3.7 [2011-04-15]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.7_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
|
||||
- Updated support for various games, including Zombie Panic, CS ProMod, Empires, and GoldenEye: Source.
|
||||
- Added gamedata for Dino D-Day.
|
||||
- Fix precedence of voice mute flag versus specific client overrides (bug 4826).
|
||||
- Fix mistaken unhooking of voice hooks (bug 4804).
|
||||
- Fixed graphical glitches with funcommands effects in L4D1 (bug 3486).
|
||||
- Fixed bug in nominations that could cause "Unknown command" error (bug 4797).
|
||||
- Removed tv_enable hook to fix rare max client count issue (bug 4791).
|
||||
- Added missing unhooking of ClientConnect in PlayerManager (bug 4749).
|
||||
- Fixed sm_rtv printing "unknown command" (bug 4730).
|
||||
- Fixed voting crash when client console, chat, and SourceTV are enabled (bug 4676).
|
||||
- Fixed CDetour crash in TF2 extension when last plugin using forward is unloaded (bug 4713).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- SetEntProp now marks edict state as changed (bug 4855).
|
||||
- Added GetEntityClassname stock (bug 4798).
|
||||
- Fix compiler hanging when #including a directory (bug 4822).
|
||||
- Added GetEntityFlags and SetEntityFlags natives for better cross-engine compatibility. (bug 4809).
|
||||
- Fixed ClientPrefs natives not being marked optional when REQUIRE_EXTENSIONS not defined (bug 4839).
|
||||
- Changed some instances of LogMessage to LogAction (bug 4649).
|
||||
- Added some new language natives (bug 4613).
|
||||
- Fixed SetTeamScore not updating score on client (bug 2736).
|
||||
- Raised MAXPLAYERS from 64 to 65 (bug 4490).
|
||||
- Added and updated many TF2-specific defines in tf2.inc and tf2_stocks.inc.
|
||||
- Fixed TF2_GetPlayerConditionFlags no longer necessarily returning all set flags (bug 4726).
|
||||
- Fixed profiler flush not clearing, added 'report' and 'clear' (bug 4674).
|
||||
- Fixed GetPlayerDecalFile crash on L4D and L4D2 (bug 4729).
|
||||
- Fixed TF2_OnGetHoliday detour no longer firing under all circumstances (bug 4700).
|
||||
- Added TF2_IsPlayerInDuel native to TF2 extension (bug 4695).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.6 [2010-10-31]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.6_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for latest Left 4 Dead 1 (bug 4681).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Updated TF2 custom kill defines (bug 4682).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.5 [2010-10-17]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.5_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Updated support for CS:S, Garry's Mod, DoD:S, TF2, HL2DM.
|
||||
- Added support for Firearms: Source (bug 4537).
|
||||
- Added support for Fistful of Frags (bug 3883).
|
||||
- Added support for Alien Swarm (bug 4530).
|
||||
- Fixed living players hearing dead players if alltalk is disabled while deadtalk is on (bug 4533, thanks Zach Callear).
|
||||
- Fixed timeleft not getting reset on Game_Commencing in CS:S (bug 4557).
|
||||
- Fixed PlayerRunCmd being hooked when not used (bug 3990).
|
||||
- Fixed errors and missing effects caused by missing sprites on L4D2 (bug 4512).
|
||||
- Fixed 'sm plugins' public command skipping plugins in recommended listing (bug 4501).
|
||||
- Fixed corruption with large database.cfg files (bug 4286).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added TF2 object stocks (bug 4536).
|
||||
- Added TF2_MakeBleed native to TF2 ext (bug 4542).
|
||||
- Added support for logical entities in Synergy (bug 4534).
|
||||
- Updated TF2 conditions enum and defines (bug 4526).
|
||||
- Fixed potential crash with IMemUtils::FindPattern on Linux (bug 4554).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.4 [2010-07-18]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.4_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Support for latest TF update (bug 4506).
|
||||
- Support for latest L4D2 update (bug 4509).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added FindFlagChar native (bug 3776).
|
||||
- Added GetConVarDefault native (bug 4502).
|
||||
- Added forward for TF's GetHoliday function (bug 4462).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.3 [2010-06-23]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.3_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added support for CS:S on Orange Box
|
||||
- Added gamedata for Resistance and Liberation (bug 4418).
|
||||
- Updated gamedata for SourceForts, Empires, Obsidian Conflict, Zombie Master.
|
||||
- Fixed memory corruption and leaks with some voice functionality (bug 4415).
|
||||
- Fixed UI bug in sm_motd (bug 4460).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added new player condition (TFCond_CritCola, bug 4447).
|
||||
- Fixed clientprefs deleting cookies twice in rare cases (bug 4412).
|
||||
- Fixed OnClientConnected forward not firing for bots (bug 4443).
|
||||
- Fixed sm_dump_datamaps crash (bug 4424).
|
||||
- Fixed switch case comparisons failing with large numbers (bug 4457).
|
||||
- Fixed rare crash in output hooks (bug 4422).
|
||||
- Fixed bug with dynamically sized arrays being sliced (bug 4428).
|
||||
- Fixed SendConVarValue() on TF2, DOD:S, L4D, and L4D2 (bug 4273).
|
||||
- Fixed TF2 natives not being marked optional (bug 4389).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.2 [2010-05-02]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.2_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Support for recent TF, DoD, and L4D2 updates (bug 4356, bug 4361, bug 4371, bug 4374, bug 4375).
|
||||
- Fixed rare crash when replicating cvars to clients (bug 4315).
|
||||
- Lots of extra game support for Insurgency, ZPS, CSProMod, PVKII, and FortressForever (thanks
|
||||
Nicholas "psychonic" hastings).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added TF functions for stunning, conditions, regeneration, and power play (bug 4166, bug 4331).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.1 [2010-02-09]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.1_Release_Notes
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added extended support for CSProMod (bug 4255).
|
||||
- Fixed client disconnect crash on many third party games (bug 4231).
|
||||
- Improved support for Battlegrounds 2 (bug 4146).
|
||||
- Improved support for Insurgency (bug 4180).
|
||||
- Improved support for Garry's Mod (bug 4230, bug 4268).
|
||||
- Improved support for Synergy (bug 4235).
|
||||
- Updated Day of Defeat support for 20010123 update (bug 4262).
|
||||
- Fixed Webternet extension not loading on Windows 2000 (bug 4234).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Fixed compiler complaints when using |any| tag on array arguments (bug 4274).
|
||||
- Fixed GetClientCookieTime not being exported (bug 4237).
|
||||
- Fixed potential crash in entity handling code (bug 4249).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.3.0 [2010-01-15]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.3.0_Release_Notes
|
||||
|
||||
Major Features:
|
||||
* Left 4 Dead 2 support
|
||||
* Non-networked entity support
|
||||
|
||||
User Changes:
|
||||
|
||||
- Added Left 4 Dead 2 support (bug 4075).
|
||||
- Added much richer voting progress feedback (bug 1997).
|
||||
- Improved support for various third-party games (Nicholas "psychonic" Hastings).
|
||||
- Added @spec target (bug 2718).
|
||||
- Added sm_resetcvar command (bug 3636).
|
||||
- Added "motd" chat trigger (bug 2694).
|
||||
- Updated GeoIP to OCT-2009.
|
||||
- Fixed rare map vote error (bug 3905).
|
||||
- Fixed small leak in the nominations plugin (bug 4104).
|
||||
- Fixed last client being excluded from some command effects (bug 3984).
|
||||
- Fixed crashes in plugin [|un|re]loading (bug 4034, bug 4038, bug 4044, bug 4153).
|
||||
- Special target "@me" is now filtered for certain statuses properly (bug 4000).
|
||||
- Improved non-admin to admin chat (bug 3844).
|
||||
- Removed "auto.*" extension folders (bug 3949).
|
||||
|
||||
Developer Changes:
|
||||
|
||||
- Added non-networked entity support (bug 2459).
|
||||
- Added improved random number generator (bug 3831).
|
||||
- Added GetClientCookieTime native (bug 3736).
|
||||
- Added AskPluginLoad2 callback (bug 3716).
|
||||
- Added PlayerRunCmd callback (bug 3289).
|
||||
- Added PointOutsideWorld native (bug 3906).
|
||||
- Added API for "blanket" command hooks (bug 4015).
|
||||
- Added ability to test for SourceMod features (bug 4021).
|
||||
- Added ability to change broadcast status on hooked events (bug 3886).
|
||||
- OnClientCommand no longer receives unconnected clients (bug 3732).
|
||||
- Fixed various bugs in client listening API (bug 3818).
|
||||
- Fixed crash in BanClient (bug 3912).
|
||||
- Fixed various crashes in self-removing callbacks (bug 4059).
|
||||
- Fixed rare HUD text crash on TF (bug 4016).
|
||||
- Fixed OnConfigsExecuted not running on EP1 games with large configs (bug 3828).
|
||||
- Fixed entity output hooks not working (bug 3988).
|
||||
- Gamedata folder matches are now case-insensitive (bug 3913).
|
||||
- Blocked plugins from hooking "sm" command (bug 4013).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.4 [2009-10-03]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.4_Release_Notes
|
||||
|
||||
- Updated for L4D changes (bugs 4032, 4033, 4035).
|
||||
- Updated GeoLite Country database for GeoIP extension.
|
||||
- Fixed crash when block-loading more than eight plugins (bug 4034).
|
||||
- Fixed rare crash in hudtext code on TF (bug 4016).
|
||||
- Fixed crash when reloading a blocked plugin failed (bug 4038).
|
||||
- Fixed Huntsman not firing critical callback on TF (bug 3927).
|
||||
- Registering the "sm" command no longer has any effect (bug 4013).
|
||||
- Fixed translation bug in extension API (bug 4010).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.3 [2009-08-28]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.3_Release_Notes
|
||||
|
||||
- Fix extension filename lookup. (bug 3975).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.2 [2009-08-28]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.2_Release_Notes
|
||||
|
||||
- Removed auto folders. (bug 3949).
|
||||
- Added PointOutsideWorld native to sdktools. (bug 3906).
|
||||
- Added "motd" chat trigger to basetriggers. (bug 2694).
|
||||
- Added manual extension reloading command to root console menu. (bug 3934)
|
||||
- Fixed 'list' type custom menu entries overwriting admin restrictions. (bug 3783).
|
||||
- Added sm_resetcvar command to basecommands. (bug 3636).
|
||||
- Updated gamedata for DOD:S. (bug 3948).
|
||||
- Updated gamedata for TF2. (bug 3948).
|
||||
- Added new .ep2v build config for valve OB based games. (bug 3948).
|
||||
- Fixed incorrect escaping in clientprefs SQLite queries. (bug 3904)
|
||||
- Updated gamedata for Synergy. (bug 3315).
|
||||
- Upgraded to pcre-7.9 (bug 3923).
|
||||
- Switched Insurgency chat printing to SayText. (bug 3738).
|
||||
- Updated gamedata for Insurgency. (bug 3511).
|
||||
- Updated gamedata for ZM. (bug 3746).
|
||||
- Updated gamedata for Empires. (bug 3500).
|
||||
- Updated gamedata for ZPS. (bug 3877).
|
||||
- Updated gamedata for AoC. (bug 3891).
|
||||
- Fixed RemovePlayerDisguise signature for TF2. (bug 3892).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.1 [2009-05-31]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.1_Release_Notes
|
||||
|
||||
- Updated SDKTools for latest Team Fortress update.
|
||||
- Added L4D handling to GuessSDKVersion() (bug 3842).
|
||||
- Updated Zombie Panic Source offsets (bug 3632).
|
||||
- Fixed crash when clientprefs saw disconnect from 64th client (bug 3821).
|
||||
- Fixed Plugin_Handled acting like a Stop in usermsg hooks (bug 3685).
|
||||
- Fixed early tv_enable causing crashes (bug 3766).
|
||||
- Fixed unhook event crash (bug 3814).
|
||||
- Fixed compiler reading uninitialized strings while processing varargs (bug 3811).
|
||||
- Fixed compiler choosing whether to emit stradjust.pri on dynamic arrays based on uninitialized memory (bug 3810).
|
||||
- Fixed Windows L4D CreateFakeClient signature (bug 3792).
|
||||
- Fixed sm_slap for EP1 games (bug 3768).
|
||||
- Fixed casting problems in TextParsers breaking TrimString for non-ASCII characters (bug 3800).
|
||||
- Fixed OnClientConnect rejectmsg handling, improved doc (bug 3690).
|
||||
- Fixed clientprefs not loading cookies for clients on late load (bug 3735).
|
||||
- Fixed GetCommandFlags on original engine games (bug 3759).
|
||||
- Fixed compiler asserting when returning a string literal (bug 3836).
|
||||
- Fixed compiler erroring when tagging functions for string return (bug 3837).
|
||||
- Fixed compiler not handling constant chained relational operators correctly (bug 3838).
|
||||
- Fixed revote bug and inflexibilities in RedrawClientVoteMenu (bug 3834).
|
||||
- Fixed auto update URL being set too late (bug 3699).
|
||||
- Disabled nextmap in Synergy and Dystopia (bug 3687, bug 3741).
|
||||
- Removed unnecessary SSE optimizations from msvc9 project files (bug 3756).
|
||||
- Removed short-lived tag system (bug 3751).
|
||||
- Removed the alive check from sm_rename. (bug 3698).
|
||||
- Switched FortressForever to Valve menus (bug 3819).
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.2.0 [2009-03-05]
|
||||
|
||||
URL: http://wiki.alliedmods.net/SourceMod_1.2.0_Release_Notes
|
||||
|
||||
Major Features:
|
||||
* Left 4 Dead Support
|
||||
* Dark Messiah Support
|
||||
* New and Improved Updater
|
||||
|
||||
Changes:
|
||||
|
||||
- Added Left 4 Dead support (bug 3414).
|
||||
- Added Dark Messiah game support (requires Metamod:Source 1.7.1 or higher).
|
||||
- Added sm_name command (bug 2150).
|
||||
- Added extension-level dynamic hooking to bintools (bug 2616).
|
||||
- Added client validation API to replace passing userids asynchronously.
|
||||
- Added cURL extension, available to other extensions (bug 3560).
|
||||
- Added parsing of custom gamedata files (bug 3644).
|
||||
- Added case insensitivity search to ReplaceString (bug 3639, Fyren).
|
||||
- Added more detail to certain player-oriented menu titles (bug 2740, Fyren).
|
||||
- Added sv_tags API (bug 3677).
|
||||
- Greatly improved admin-sql-prefetch performance for large tables (bug 3354, FLOOR_MASTER).
|
||||
- Exposed IServer address to extensions (bug 3545).
|
||||
- New gamedata organization; files are now smaller and per-game (bug 3546).
|
||||
- Split sound functions into a new plugin, sounds.smx.
|
||||
- Fixed slap and slay on Insurgency (bug 2560).
|
||||
- Fixed blank admins being created from invalid admin file lines (bug 3431).
|
||||
- Fixed basetriggers not working on Insurgency (bug 3497).
|
||||
- Fixed client preferences missing some clients (bug 3616).
|
||||
- Improved database fallback mechanism in clientprefs (bug 3564).
|
||||
- Improved timer handling in funcommands (bug 3498).
|
||||
- Improved compile.sh to take filenames (bug 3550, jonasfietz).
|
||||
- sm_kick now shows the kick reason when available.
|
||||
- Fixed MsgPostHook (ex MsgSentNotify) callbacks not firing on intercept hook (bug 3631).
|
||||
- Note: SourceMod now adds "sourcemod" to the sv_tags cvar.
|
||||
|
||||
----------------------------
|
||||
|
||||
SourceMod 1.1.2 [2009-02-26]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents
|
||||
//any more plugins from being loaded.
|
||||
sm plugins unload_all
|
||||
sm plugins load_unlock
|
||||
sm plugins load basebans.smx
|
||||
sm plugins load basecommands.smx
|
||||
sm plugins load admin-flatfile.smx
|
||||
|
||||
@@ -80,21 +80,21 @@ sm_reserve_type 0
|
||||
sm_reserved_slots 0
|
||||
|
||||
// Specifies whether or not reserved slots will be hidden (subtracted from max
|
||||
// slot count). Valid values are 0 (visible) or 1 (hidden).
|
||||
// slot count). Valid values are 0 (Visible) or 1 (Hidden).
|
||||
// --
|
||||
// Requires: reservedslots.smx
|
||||
// Default: 0
|
||||
sm_hide_slots 0
|
||||
|
||||
// Specifies whether or not non-admins can send messages to admins using
|
||||
// say_team @<message>. Valid values are 0 (disabled) or 1 (enabled)
|
||||
// say_team @<message>. Valid values are 0 (Disabled) or 1 (Enabled)
|
||||
// --
|
||||
// Requires: basechat.smx
|
||||
// Default: 1
|
||||
sm_chat_mode 1
|
||||
|
||||
// Specifies whether or not "timeleft" will automaticly be triggered every
|
||||
// x seconds. Valid values are 0 (disabled) to 1800 seconds.
|
||||
// x seconds. Valid values are 0 (Disabled) to 1800 seconds.
|
||||
// --
|
||||
// Requires: basetriggers.smx
|
||||
// Default: 0
|
||||
@@ -107,3 +107,28 @@ sm_timeleft_interval 0
|
||||
// Requires: basetriggers.smx
|
||||
// Default: 1
|
||||
sm_trigger_show 1
|
||||
|
||||
// Specifies whether or not to display vote progress to clients in the
|
||||
// "hint" box (near the bottom of the screen in most games).
|
||||
// Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_hintbox 0
|
||||
|
||||
// Specifies whether or not to display vote progress to clients in the
|
||||
// chat area. Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_chat 0
|
||||
|
||||
// Specifies whether or not to display vote progress in the server console.
|
||||
// Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_console 0
|
||||
|
||||
// Specifies whether or not to display vote progress to clients in the
|
||||
// client console. Valid values are 0 (Disabled) or 1 (Enabled).
|
||||
// --
|
||||
// Default: 0
|
||||
sm_vote_progress_client_console 0
|
||||
|
||||
+3
-15
@@ -4,14 +4,6 @@
|
||||
*/
|
||||
"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.
|
||||
*
|
||||
@@ -105,15 +97,11 @@
|
||||
"ForceRestartAfterUpdate" "no"
|
||||
|
||||
/**
|
||||
* Sets the server to connect to for auotmatic gamedata updates.
|
||||
* URL to use for retrieving update information.
|
||||
* SSL is not yet supported.
|
||||
*/
|
||||
"AutoUpdateServer" "smupdate.alliedmods.net"
|
||||
"AutoUpdateURL" "http://update.sourcemod.net/update/"
|
||||
|
||||
/**
|
||||
* Sets the port to connect to on the AutoUpdateServer server
|
||||
*/
|
||||
"AutoUpdatePort" "6500"
|
||||
|
||||
/**
|
||||
* Whether to show debug spew.
|
||||
* Currently this will log details about the gamedata updating process.
|
||||
|
||||
Binary file not shown.
@@ -2,4 +2,3 @@
|
||||
{
|
||||
"en" "English"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet:
|
||||
import sys
|
||||
import ambuild.runner as runner
|
||||
|
||||
run = runner.Runner()
|
||||
run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
|
||||
help='Enable debugging symbols')
|
||||
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||
help='Enable optimization')
|
||||
run.Configure(sys.path[0])
|
||||
@@ -0,0 +1,90 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
|
||||
for i in SM.sdkInfo:
|
||||
sdk = SM.sdkInfo[i]
|
||||
name = 'sourcemod.' + sdk['ext']
|
||||
|
||||
compiler = SM.DefaultHL2Compiler('core', i)
|
||||
|
||||
extension = AMBuild.AddJob(name)
|
||||
binary = Cpp.LibraryBuilder(name, AMBuild, extension, compiler)
|
||||
SM.PreSetupHL2Job(extension, binary, i)
|
||||
files = [
|
||||
'AdminCache.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
'MenuStyle_Valve.cpp',
|
||||
'sm_crc32.cpp',
|
||||
'logic_bridge.cpp',
|
||||
'smn_entities.cpp',
|
||||
'sm_stringutil.cpp',
|
||||
'ADTFactory.cpp',
|
||||
'ForwardSys.cpp',
|
||||
'MenuVoting.cpp',
|
||||
'sm_memtable.cpp',
|
||||
'smn_events.cpp',
|
||||
'smn_menus.cpp',
|
||||
'sm_trie.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_hooks.cpp',
|
||||
'NativeInvoker.cpp',
|
||||
'smn_admin.cpp',
|
||||
'smn_fakenatives.cpp',
|
||||
'smn_nextmap.cpp',
|
||||
'sourcemm_api.cpp',
|
||||
'ChatTriggers.cpp',
|
||||
'GameConfigs.cpp',
|
||||
'NativeOwner.cpp',
|
||||
'smn_filesystem.cpp',
|
||||
'smn_player.cpp',
|
||||
'sourcemod.cpp',
|
||||
'concmd_cleaner.cpp',
|
||||
'HalfLife2.cpp',
|
||||
'NextMap.cpp',
|
||||
'smn_profiler.cpp',
|
||||
'ConCmdManager.cpp',
|
||||
'HandleSys.cpp',
|
||||
'PhraseCollection.cpp',
|
||||
'ConVarManager.cpp',
|
||||
'LibrarySys.cpp',
|
||||
'PlayerManager.cpp',
|
||||
'smn_banning.cpp',
|
||||
'smn_gameconfigs.cpp',
|
||||
'smn_string.cpp',
|
||||
'TimerSys.cpp',
|
||||
'CoreConfig.cpp',
|
||||
'Logger.cpp',
|
||||
'PluginInfoDatabase.cpp',
|
||||
'smn_bitbuffer.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'Translator.cpp',
|
||||
'MemoryUtils.cpp',
|
||||
'PluginSys.cpp',
|
||||
'smn_console.cpp',
|
||||
'smn_handles.cpp',
|
||||
'smn_timers.cpp',
|
||||
'UserMessages.cpp',
|
||||
'Database.cpp',
|
||||
'MenuManager.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_hudtext.cpp',
|
||||
'smn_usermsgs.cpp',
|
||||
'DebugReporter.cpp',
|
||||
'MenuStyle_Base.cpp',
|
||||
'ShareSys.cpp',
|
||||
'smn_database.cpp',
|
||||
'smn_keyvalues.cpp',
|
||||
'smn_vector.cpp',
|
||||
'EventManager.cpp',
|
||||
'MenuStyle_Radio.cpp',
|
||||
'sm_autonatives.cpp',
|
||||
'smn_datapacks.cpp',
|
||||
'smn_lang.cpp',
|
||||
'sm_srvcmds.cpp',
|
||||
'ConsoleDetours.cpp'
|
||||
]
|
||||
binary.AddSourceFiles('core', files)
|
||||
SM.PostSetupHL2Job(extension, binary, i)
|
||||
SM.AutoVersion('core', binary)
|
||||
binary.SendToJob()
|
||||
|
||||
@@ -1170,6 +1170,11 @@ bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
|
||||
|
||||
bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
|
||||
{
|
||||
if (ident[0] == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
|
||||
if (!pUser || pUser->magic != USR_MAGIC_SET)
|
||||
{
|
||||
|
||||
+8
-31
@@ -41,7 +41,7 @@
|
||||
* While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
|
||||
* can technically be compiled against any MM:S version after 1.4.2.
|
||||
*/
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
|
||||
#else
|
||||
@@ -53,7 +53,7 @@ extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate
|
||||
#elif SH_IMPL_VERSION == 3
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
#endif //SH_IMPL_VERSION
|
||||
#endif //ORANGEBOX_BUILD
|
||||
#endif //SE_ORANGEBOX
|
||||
|
||||
ChatTriggers g_ChatTriggers;
|
||||
bool g_bSupressSilentFails = false;
|
||||
@@ -118,31 +118,8 @@ void ChatTriggers::OnSourceModAllInitialized_Post()
|
||||
|
||||
void ChatTriggers::OnSourceModGameInitialized()
|
||||
{
|
||||
unsigned int total = 2;
|
||||
ConCommandBase *pCmd = icvar->GetCommands();
|
||||
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());
|
||||
}
|
||||
m_pSayCmd = FindCommand("say");
|
||||
m_pSayTeamCmd = FindCommand("say_team");
|
||||
|
||||
if (m_pSayCmd)
|
||||
{
|
||||
@@ -173,7 +150,7 @@ void ChatTriggers::OnSourceModShutdown()
|
||||
g_Forwards.ReleaseForward(m_pDidFloodBlock);
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
|
||||
{
|
||||
#else
|
||||
@@ -267,7 +244,7 @@ void ChatTriggers::OnSayCommand_Pre()
|
||||
/**
|
||||
* Test if this is actually a command!
|
||||
*/
|
||||
if (!PreProcessTrigger(engine->PEntityOfEntIndex(client), args, is_quoted))
|
||||
if (!PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
|
||||
{
|
||||
CPlayer *pPlayer;
|
||||
if (is_silent
|
||||
@@ -299,7 +276,7 @@ void ChatTriggers::OnSayCommand_Pre()
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
|
||||
#else
|
||||
void ChatTriggers::OnSayCommand_Post()
|
||||
@@ -315,7 +292,7 @@ void ChatTriggers::OnSayCommand_Post()
|
||||
/* Execute the cached command */
|
||||
int client = g_ConCmds.GetCommandClient();
|
||||
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
|
||||
serverpluginhelpers->ClientCommand(engine->PEntityOfEntIndex(client), m_ToExecute);
|
||||
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
|
||||
SetReplyTo(old);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public: //SMGlobalClass
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
private: //ConCommand
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void OnSayCommand_Pre(const CCommand &command);
|
||||
void OnSayCommand_Post(const CCommand &command);
|
||||
#else
|
||||
|
||||
+72
-70
@@ -40,7 +40,7 @@
|
||||
|
||||
ConCmdManager g_ConCmds;
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||
#else
|
||||
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||
@@ -205,7 +205,7 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
||||
delete pList;
|
||||
}
|
||||
}
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void CommandCallback(const CCommand &command)
|
||||
{
|
||||
#else
|
||||
@@ -226,49 +226,78 @@ void ConCmdManager::SetCommandClient(int client)
|
||||
m_CmdClient = client + 1;
|
||||
}
|
||||
|
||||
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
|
||||
return NULL;
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
ConCmdList::iterator ConCmdManager::FindInList(const char *cmd)
|
||||
{
|
||||
List<ConCmdInfo *>::iterator iter = m_CmdList.begin();
|
||||
|
||||
while (iter != m_CmdList.end())
|
||||
{
|
||||
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
|
||||
break;
|
||||
iter++;
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int args, ResultType type)
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
if (sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
|
||||
|
||||
if ((pInfo = FindInTrie(cmd)) == NULL)
|
||||
{
|
||||
cell_t result = type;
|
||||
cell_t tempres = result;
|
||||
List<CmdHook *>::iterator iter;
|
||||
CmdHook *pHook;
|
||||
for (iter=pInfo->conhooks.begin();
|
||||
iter!=pInfo->conhooks.end();
|
||||
iter++)
|
||||
ConCmdList::iterator item = FindInList(cmd);
|
||||
if (item == m_CmdList.end())
|
||||
return type;
|
||||
pInfo = *item;
|
||||
}
|
||||
|
||||
cell_t result = type;
|
||||
cell_t tempres = result;
|
||||
List<CmdHook *>::iterator iter;
|
||||
CmdHook *pHook;
|
||||
for (iter=pInfo->conhooks.begin();
|
||||
iter!=pInfo->conhooks.end();
|
||||
iter++)
|
||||
{
|
||||
pHook = (*iter);
|
||||
if (!pHook->pf->IsRunnable())
|
||||
{
|
||||
pHook = (*iter);
|
||||
if (!pHook->pf->IsRunnable())
|
||||
continue;
|
||||
}
|
||||
if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin))
|
||||
{
|
||||
if (result < Pl_Handled)
|
||||
{
|
||||
continue;
|
||||
result = Pl_Handled;
|
||||
}
|
||||
if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin))
|
||||
continue;
|
||||
}
|
||||
pHook->pf->PushCell(client);
|
||||
pHook->pf->PushCell(args);
|
||||
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
||||
{
|
||||
if (tempres > result)
|
||||
{
|
||||
if (result < Pl_Handled)
|
||||
{
|
||||
result = Pl_Handled;
|
||||
}
|
||||
continue;
|
||||
result = tempres;
|
||||
}
|
||||
pHook->pf->PushCell(client);
|
||||
pHook->pf->PushCell(args);
|
||||
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
||||
if (result == Pl_Stop)
|
||||
{
|
||||
if (tempres > result)
|
||||
{
|
||||
result = tempres;
|
||||
}
|
||||
if (result == Pl_Stop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
type = (ResultType)result;
|
||||
}
|
||||
|
||||
type = (ResultType)result;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -293,35 +322,20 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
|
||||
*/
|
||||
const char *cmd = g_HL2.CurrentCommandName();
|
||||
|
||||
ConCmdInfo *pInfo;
|
||||
if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
|
||||
ConCmdInfo *pInfo = FindInTrie(cmd);
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
/* Unfortunately, we now have to do a slow lookup because Valve made client commands
|
||||
* case-insensitive. We can't even use our sortedness.
|
||||
*/
|
||||
if (client == 0 && !engine->IsDedicatedServer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<ConCmdInfo *>::iterator iter;
|
||||
ConCmdList::iterator item = FindInList(cmd);
|
||||
if (item == m_CmdList.end())
|
||||
return;
|
||||
|
||||
pInfo = NULL;
|
||||
iter = m_CmdList.begin();
|
||||
while (iter != m_CmdList.end())
|
||||
{
|
||||
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pInfo = *item;
|
||||
}
|
||||
|
||||
/* This is a hack to prevent say triggers from firing on messages that were
|
||||
@@ -515,7 +529,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
|
||||
return true;
|
||||
}
|
||||
|
||||
edict_t *pEdict = engine->PEntityOfEntIndex(client);
|
||||
edict_t *pEdict = PEntityOfEntIndex(client);
|
||||
|
||||
/* If we got here, the command failed... */
|
||||
char buffer[128];
|
||||
@@ -895,25 +909,13 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
||||
ConCmdInfo *pInfo;
|
||||
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
|
||||
{
|
||||
ConCmdList::iterator item = FindInList(name);
|
||||
if (item != m_CmdList.end())
|
||||
return *item;
|
||||
|
||||
pInfo = new ConCmdInfo();
|
||||
/* Find the commandopan */
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
ConCommand *pCmd = NULL;
|
||||
while (pBase)
|
||||
{
|
||||
if (strcmp(pBase->GetName(), name) == 0)
|
||||
{
|
||||
/* Don't want to return convar with same name */
|
||||
if (!pBase->IsCommand())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pCmd = (ConCommand *)pBase;
|
||||
break;
|
||||
}
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
}
|
||||
ConCommand *pCmd = FindCommand(name);
|
||||
|
||||
if (!pCmd)
|
||||
{
|
||||
|
||||
+11
-2
@@ -92,13 +92,15 @@ struct ConCmdInfo
|
||||
bool is_admin_set; /**< Whether or not admin info is set */
|
||||
};
|
||||
|
||||
typedef List<ConCmdInfo *> ConCmdList;
|
||||
|
||||
class ConCmdManager :
|
||||
public SMGlobalClass,
|
||||
public IRootConsoleCommand,
|
||||
public IPluginsListener,
|
||||
public IConCommandTracker
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
friend void CommandCallback(const CCommand &command);
|
||||
#else
|
||||
friend void CommandCallback();
|
||||
@@ -139,6 +141,12 @@ private:
|
||||
void RemoveConCmds(List<CmdHook *> &cmdlist);
|
||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||
|
||||
// Case insensitive
|
||||
ConCmdList::iterator FindInList(const char *name);
|
||||
|
||||
// Case sensitive
|
||||
ConCmdInfo *FindInTrie(const char *name);
|
||||
public:
|
||||
inline int GetCommandClient()
|
||||
{
|
||||
@@ -151,7 +159,7 @@ public:
|
||||
private:
|
||||
Trie *m_pCmds; /* command lookup */
|
||||
Trie *m_pCmdGrps; /* command group lookup */
|
||||
List<ConCmdInfo *> m_CmdList; /* command list */
|
||||
ConCmdList m_CmdList; /* command list */
|
||||
int m_CmdClient; /* current client */
|
||||
BaseStringTable m_Strings; /* string table */
|
||||
};
|
||||
@@ -159,3 +167,4 @@ private:
|
||||
extern ConCmdManager g_ConCmds;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* 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
|
||||
@@ -28,21 +28,62 @@
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#ifndef _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
|
||||
#define _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
|
||||
|
||||
/**
|
||||
* Autogenerated by build scripts
|
||||
*/
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
class ConCommandBaseIterator
|
||||
{
|
||||
public:
|
||||
inline ConCommandBaseIterator() : iter(icvar)
|
||||
{
|
||||
iter.SetFirst();
|
||||
}
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
#define _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
inline bool IsValid()
|
||||
{
|
||||
return iter.IsValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* @file Contains SourceMod version information.
|
||||
*/
|
||||
inline void Next()
|
||||
{
|
||||
iter.Next();
|
||||
}
|
||||
|
||||
#define SM_BUILD_STRING "$BUILD_STRING$"
|
||||
#define SM_BUILD_UNIQUEID "$BUILD_ID$" SM_BUILD_STRING
|
||||
#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$" SM_BUILD_STRING
|
||||
#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,0
|
||||
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_ */
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VERSION_H_
|
||||
+77
-24
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,8 +25,6 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "ConVarManager.h"
|
||||
@@ -41,23 +39,59 @@
|
||||
|
||||
ConVarManager g_ConVarManager;
|
||||
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
|
||||
#endif
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
||||
#else
|
||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
|
||||
#endif
|
||||
|
||||
#if 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(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};
|
||||
typedef List<const ConVar *> ConVarList;
|
||||
KTrie<ConVarInfo *> convar_cache;
|
||||
|
||||
class ConVarReentrancyGuard
|
||||
{
|
||||
ConVar *cvar;
|
||||
ConVarReentrancyGuard *up;
|
||||
public:
|
||||
static ConVarReentrancyGuard *chain;
|
||||
|
||||
ConVarReentrancyGuard(ConVar *cvar)
|
||||
: cvar(cvar), up(chain)
|
||||
{
|
||||
chain = this;
|
||||
}
|
||||
|
||||
~ConVarReentrancyGuard()
|
||||
{
|
||||
assert(chain == this);
|
||||
chain = up;
|
||||
}
|
||||
|
||||
static bool IsCvarInChain(ConVar *cvar)
|
||||
{
|
||||
ConVarReentrancyGuard *guard = chain;
|
||||
while (guard != NULL)
|
||||
{
|
||||
if (guard->cvar == cvar)
|
||||
return true;
|
||||
guard = guard->up;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
|
||||
|
||||
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
|
||||
{
|
||||
}
|
||||
@@ -84,7 +118,7 @@ void ConVarManager::OnSourceModAllInitialized()
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
||||
@@ -94,6 +128,8 @@ void ConVarManager::OnSourceModAllInitialized()
|
||||
|
||||
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
||||
|
||||
g_PluginSys.AddPluginsListener(this);
|
||||
|
||||
/* Add the 'convars' option to the 'sm' console command */
|
||||
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
||||
}
|
||||
@@ -141,6 +177,7 @@ void ConVarManager::OnSourceModShutdown()
|
||||
}
|
||||
convar_cache.clear();
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
/* Unhook things */
|
||||
if (m_bIsDLLQueryHooked)
|
||||
{
|
||||
@@ -152,12 +189,15 @@ void ConVarManager::OnSourceModShutdown()
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
||||
m_bIsVSPQueryHooked = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
||||
|
||||
/* Remove the 'convars' option from the 'sm' console command */
|
||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
||||
|
||||
g_PluginSys.RemovePluginsListener(this);
|
||||
|
||||
/* Remove the 'ConVar' handle type */
|
||||
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
|
||||
}
|
||||
@@ -176,7 +216,7 @@ void ConVarManager::OnSourceModVSPReceived()
|
||||
}
|
||||
|
||||
/* For later MM:S versions, use the updated API, since it's cleaner. */
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
||||
int engine = g_SMAPI->GetSourceEngineBuild();
|
||||
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
|
||||
{
|
||||
@@ -189,8 +229,10 @@ void ConVarManager::OnSourceModVSPReceived()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
|
||||
m_bIsVSPQueryHooked = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
|
||||
@@ -246,12 +288,23 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
||||
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
ConVarList *pConVarList;
|
||||
List<ConVarQuery>::iterator iter;
|
||||
|
||||
/* If plugin has a convar list, free its memory */
|
||||
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
||||
{
|
||||
delete pConVarList;
|
||||
}
|
||||
|
||||
/* Remove convar queries for this plugin that haven't returned results yet */
|
||||
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
|
||||
{
|
||||
ConVarQuery &query = (*iter);
|
||||
if (query.pCallback->GetParentRuntime() == plugin->GetRuntime())
|
||||
{
|
||||
m_ConVarQueries.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -309,7 +362,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
|
||||
}
|
||||
|
||||
/* Display usage of subcommand */
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm cvars <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)
|
||||
@@ -359,17 +412,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 */
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
|
||||
while (pBase)
|
||||
/* Prevent creating a convar that has the same name as a console command */
|
||||
if (FindCommand(name))
|
||||
{
|
||||
if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
|
||||
{
|
||||
return BAD_HANDLE;
|
||||
}
|
||||
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
return BAD_HANDLE;
|
||||
}
|
||||
|
||||
/* Create and initialize ConVarInfo structure */
|
||||
@@ -524,7 +570,8 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
||||
}
|
||||
|
||||
/* If the forward now has 0 functions in it... */
|
||||
if (pForward->GetFunctionCount() == 0)
|
||||
if (pForward->GetFunctionCount() == 0 &&
|
||||
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
|
||||
{
|
||||
/* Free this forward */
|
||||
g_Forwards.ReleaseForward(pForward);
|
||||
@@ -535,8 +582,9 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
||||
|
||||
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 */
|
||||
if (m_bIsDLLQueryHooked)
|
||||
{
|
||||
@@ -553,6 +601,7 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
|
||||
|
||||
ConVarQuery query = {cookie, pCallback, hndl};
|
||||
m_ConVarQueries.push_back(query);
|
||||
#endif
|
||||
|
||||
return cookie;
|
||||
}
|
||||
@@ -595,7 +644,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)
|
||||
#else
|
||||
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||
@@ -623,7 +672,7 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||
i != pInfo->changeListeners.end();
|
||||
i++)
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
|
||||
#else
|
||||
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
|
||||
@@ -633,6 +682,8 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||
|
||||
if (pForward != NULL)
|
||||
{
|
||||
ConVarReentrancyGuard guard(pConVar);
|
||||
|
||||
/* Now call forwards in plugins that have hooked this */
|
||||
pForward->PushCell(pInfo->handle);
|
||||
pForward->PushString(oldValue);
|
||||
@@ -646,6 +697,7 @@ bool ConVarManager::IsQueryingSupported()
|
||||
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||
{
|
||||
IPluginFunction *pCallback = NULL;
|
||||
@@ -668,7 +720,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
|
||||
cell_t ret;
|
||||
|
||||
pCallback->PushCell(cookie);
|
||||
pCallback->PushCell(engine->IndexOfEdict(pPlayer));
|
||||
pCallback->PushCell(IndexOfEdict(pPlayer));
|
||||
pCallback->PushCell(result);
|
||||
pCallback->PushString(cvarName);
|
||||
|
||||
@@ -687,6 +739,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
|
||||
m_ConVarQueries.erase(iter);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
|
||||
{
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
#include <compat_wrappers.h>
|
||||
#include "concmd_cleaner.h"
|
||||
|
||||
#if SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
class EQueryCvarValueStatus;
|
||||
typedef int QueryCvarCookie_t;
|
||||
#endif
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
class IConVarChangeListener
|
||||
@@ -140,7 +145,7 @@ private:
|
||||
/**
|
||||
* 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);
|
||||
#else
|
||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
||||
@@ -149,8 +154,10 @@ private:
|
||||
/**
|
||||
* Callback for when StartQueryCvarValue() has finished.
|
||||
*/
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
|
||||
const char *cvarName, const char *cvarValue);
|
||||
#endif
|
||||
private:
|
||||
HandleType_t m_ConVarType;
|
||||
List<ConVarInfo *> m_ConVars;
|
||||
|
||||
@@ -0,0 +1,742 @@
|
||||
/**
|
||||
* 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 "GameConfigs.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "ConCmdManager.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "ConCommandBaseIterator.h"
|
||||
#include "ShareSys.h"
|
||||
|
||||
#if defined PLATFORM_LINUX
|
||||
# include <dlfcn.h>
|
||||
# include <sys/mman.h>
|
||||
# include <stdint.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if SH_IMPL_VERSION >= 5
|
||||
# if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||
# else
|
||||
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
||||
# endif
|
||||
#else
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHVPAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>,bool);
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
# endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
|
||||
#if SH_IMPL_VERSION >= 4
|
||||
|
||||
class GenericCommandHooker : public IConCommandLinkListener
|
||||
{
|
||||
struct HackInfo
|
||||
{
|
||||
void **vtable;
|
||||
int hook;
|
||||
unsigned int refcount;
|
||||
};
|
||||
CVector<HackInfo> vtables;
|
||||
bool enabled;
|
||||
SourceHook::MemFuncInfo dispatch;
|
||||
|
||||
inline void **GetVirtualTable(ConCommandBase *pBase)
|
||||
{
|
||||
return *reinterpret_cast<void***>(reinterpret_cast<char*>(pBase) +
|
||||
dispatch.thisptroffs +
|
||||
dispatch.vtbloffs);
|
||||
}
|
||||
|
||||
inline bool FindVtable(void **ptr, size_t& index)
|
||||
{
|
||||
for (size_t i = 0; i < vtables.size(); i++)
|
||||
{
|
||||
if (vtables[i].vtable == ptr)
|
||||
{
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MakeHookable(ConCommandBase *pBase)
|
||||
{
|
||||
if (!pBase->IsCommand())
|
||||
return;
|
||||
|
||||
ConCommand *cmd = (ConCommand*)pBase;
|
||||
void **vtable = GetVirtualTable(cmd);
|
||||
|
||||
size_t index;
|
||||
if (!FindVtable(vtable, index))
|
||||
{
|
||||
HackInfo hack;
|
||||
hack.vtable = vtable;
|
||||
hack.hook = SH_ADD_VPHOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &GenericCommandHooker::Dispatch), false);
|
||||
hack.refcount = 1;
|
||||
vtables.push_back(hack);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtables[index].refcount++;
|
||||
}
|
||||
}
|
||||
|
||||
# if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void Dispatch(const CCommand& args)
|
||||
# else
|
||||
void Dispatch()
|
||||
# endif
|
||||
{
|
||||
cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand)
|
||||
# if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
, args
|
||||
# endif
|
||||
);
|
||||
if (res >= Pl_Handled)
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
void ReparseCommandList()
|
||||
{
|
||||
for (size_t i = 0; i < vtables.size(); i++)
|
||||
vtables[i].refcount = 0;
|
||||
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
|
||||
MakeHookable(iter.Get());
|
||||
CVector<HackInfo>::iterator iter = vtables.begin();
|
||||
while (iter != vtables.end())
|
||||
{
|
||||
if ((*iter).refcount)
|
||||
{
|
||||
iter++;
|
||||
continue;
|
||||
}
|
||||
/* Damn it. This event happens AFTER the plugin has unloaded!
|
||||
* There's two options. Remove the hook now and hope SH's memory
|
||||
* protection will prevent a crash. Otherwise, we can wait until
|
||||
* the server shuts down and more likely crash then.
|
||||
*
|
||||
* This situation only arises if:
|
||||
* 1) Someone has used AddCommandFilter()
|
||||
* 2) ... on a Dark Messiah server (mm:s new api)
|
||||
* 3) ... and another MM:S plugin that uses ConCommands has unloaded.
|
||||
*
|
||||
* Even though the impact is really small, we'll wait until the
|
||||
* server shuts down, so normal operation isn't interrupted.
|
||||
*
|
||||
* See bug 4018.
|
||||
*/
|
||||
iter = vtables.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void UnhookCommand(ConCommandBase *pBase)
|
||||
{
|
||||
if (!pBase->IsCommand())
|
||||
return;
|
||||
|
||||
ConCommand *cmd = (ConCommand*)pBase;
|
||||
void **vtable = GetVirtualTable(cmd);
|
||||
|
||||
size_t index;
|
||||
if (!FindVtable(vtable, index))
|
||||
{
|
||||
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
assert(vtables[index].refcount > 0);
|
||||
vtables[index].refcount--;
|
||||
if (vtables[index].refcount == 0)
|
||||
{
|
||||
SH_REMOVE_HOOK_ID(vtables[index].hook);
|
||||
vtables.erase(vtables.iterAt(index));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
GenericCommandHooker() : enabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool Enable()
|
||||
{
|
||||
SourceHook::GetFuncInfo(&ConCommand::Dispatch, dispatch);
|
||||
|
||||
if (dispatch.thisptroffs < 0)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not determine ConCommand layout");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
|
||||
MakeHookable(iter.Get());
|
||||
|
||||
if (!vtables.size())
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find any cvars!");
|
||||
return false;
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Disable()
|
||||
{
|
||||
for (size_t i = 0; i < vtables.size(); i++)
|
||||
SH_REMOVE_HOOK_ID(vtables[i].hook);
|
||||
vtables.clear();
|
||||
}
|
||||
|
||||
virtual void OnLinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
MakeHookable(pBase);
|
||||
}
|
||||
|
||||
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
if (pBase == NULL)
|
||||
ReparseCommandList();
|
||||
else
|
||||
UnhookCommand(pBase);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* END DVP HOOK VERSION
|
||||
*/
|
||||
|
||||
#else /* SH_IMPL_VERSION >= 4 */
|
||||
|
||||
/**
|
||||
* BEGIN ENGINE DETOUR VERSION
|
||||
*/
|
||||
|
||||
# include <jit/jit_helpers.h>
|
||||
# include <jit/x86/x86_macros.h>
|
||||
|
||||
class GenericCommandHooker
|
||||
{
|
||||
struct Patch
|
||||
{
|
||||
Patch() : applied(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool applied;
|
||||
void *base;
|
||||
unsigned char search[16];
|
||||
size_t search_len;
|
||||
size_t offset;
|
||||
size_t saveat;
|
||||
int regparam;
|
||||
void *detour;
|
||||
};
|
||||
|
||||
Patch ces;
|
||||
Patch cgc;
|
||||
|
||||
public:
|
||||
static void DelayedActivation(void *inparam)
|
||||
{
|
||||
GenericCommandHooker *cdtrs = reinterpret_cast<GenericCommandHooker*>(inparam);
|
||||
/* Safe to re-enter because the frame queue is lock+swapped. */
|
||||
if ((!cdtrs->ces.applied || !cdtrs->cgc.applied) &&
|
||||
g_HL2.PeekCommandStack() != NULL)
|
||||
{
|
||||
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, cdtrs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cdtrs->ces.applied)
|
||||
cdtrs->ApplyPatch(&cdtrs->ces);
|
||||
if (!cdtrs->cgc.applied)
|
||||
cdtrs->ApplyPatch(&cdtrs->cgc);
|
||||
}
|
||||
|
||||
bool Enable()
|
||||
{
|
||||
const char *platform = NULL;
|
||||
# if defined(PLATFORM_WINDOWS)
|
||||
platform = "Windows";
|
||||
# else
|
||||
void *addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
|
||||
Dl_info info;
|
||||
if (!dladdr(addrInBase, &info))
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find engine name");
|
||||
return false;
|
||||
}
|
||||
if (strstr(info.dli_fname, "engine_i486"))
|
||||
{
|
||||
platform = "Linux_486";
|
||||
}
|
||||
else if (strstr(info.dli_fname, "engine_i686"))
|
||||
{
|
||||
platform = "Linux_686";
|
||||
}
|
||||
else if (strstr(info.dli_fname, "engine_amd"))
|
||||
{
|
||||
platform = "Linux_AMD";
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogError("Command filter could not determine engine (%s)", info.dli_fname);
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
|
||||
if (!PrepPatch("Cmd_ExecuteString", "CES", platform, &ces))
|
||||
return false;
|
||||
if (!PrepPatch("CGameClient::ExecuteString", "CGC", platform, &cgc))
|
||||
return false;
|
||||
|
||||
if (g_HL2.PeekCommandStack() != NULL)
|
||||
{
|
||||
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
ApplyPatch(&ces);
|
||||
ApplyPatch(&cgc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Disable()
|
||||
{
|
||||
UndoPatch(&ces);
|
||||
UndoPatch(&cgc);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
# if !defined PLATFORM_WINDOWS
|
||||
# define PAGE_READWRITE PROT_READ|PROT_WRITE
|
||||
# define PAGE_EXECUTE_READ PROT_READ|PROT_EXEC
|
||||
|
||||
static inline uintptr_t AddrToPage(uintptr_t address)
|
||||
{
|
||||
return (address & ~(uintptr_t(sysconf(_SC_PAGE_SIZE) - 1)));
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
void Protect(void *addr, size_t length, int prot)
|
||||
{
|
||||
# if defined PLATFORM_WINDOWS
|
||||
DWORD ignore;
|
||||
VirtualProtect(addr, length, prot, &ignore);
|
||||
# else
|
||||
uintptr_t startPage = AddrToPage(uintptr_t(addr));
|
||||
length += (uintptr_t(addr) - startPage);
|
||||
mprotect((void*)startPage, length, prot);
|
||||
# endif
|
||||
}
|
||||
|
||||
void UndoPatch(Patch *patch)
|
||||
{
|
||||
if (!patch->applied || patch->detour == NULL)
|
||||
return;
|
||||
|
||||
g_pSourcePawn->FreePageMemory(patch->detour);
|
||||
|
||||
unsigned char *source = (unsigned char *)patch->base + patch->offset;
|
||||
Protect(source, patch->search_len, PAGE_READWRITE);
|
||||
for (size_t i = 0; i < patch->search_len; i++)
|
||||
source[i] = patch->search[i];
|
||||
Protect(source, patch->search_len, PAGE_EXECUTE_READ);
|
||||
}
|
||||
|
||||
void ApplyPatch(Patch *patch)
|
||||
{
|
||||
assert(!patch->applied);
|
||||
|
||||
size_t length = 0;
|
||||
void *callback = (void*)&ConsoleDetours::Dispatch;
|
||||
|
||||
/* Bogus assignment to make compiler is doing the right thing. */
|
||||
patch->detour = callback;
|
||||
|
||||
/* Assemgle the detour. */
|
||||
JitWriter writer;
|
||||
writer.outbase = NULL;
|
||||
writer.outptr = NULL;
|
||||
do
|
||||
{
|
||||
/* Need a specific register, or value on stack? */
|
||||
if (patch->regparam != -1)
|
||||
IA32_Push_Reg(&writer, patch->regparam);
|
||||
/* Call real function. */
|
||||
IA32_Write_Jump32_Abs(&writer, IA32_Call_Imm32(&writer, 0), callback);
|
||||
/* Restore stack. */
|
||||
if (patch->regparam != -1)
|
||||
IA32_Pop_Reg(&writer, patch->regparam);
|
||||
/* Copy any saved bytes */
|
||||
if (patch->saveat)
|
||||
{
|
||||
for (size_t i = patch->saveat; i < patch->search_len; i++)
|
||||
{
|
||||
writer.write_ubyte(patch->search[i]);
|
||||
}
|
||||
}
|
||||
/* Jump back to the caller. */
|
||||
unsigned char *target = (unsigned char *)patch->base + patch->offset + patch->search_len;
|
||||
IA32_Jump_Imm32_Abs(&writer, target);
|
||||
/* Assemble, if we can. */
|
||||
if (writer.outbase == NULL)
|
||||
{
|
||||
length = writer.outptr - writer.outbase;
|
||||
patch->detour = g_pSourcePawn->AllocatePageMemory(length);
|
||||
if (patch->detour == NULL)
|
||||
{
|
||||
g_Logger.LogError("Ran out of memory!");
|
||||
return;
|
||||
}
|
||||
g_pSourcePawn->SetReadWrite(patch->detour);
|
||||
writer.outbase = (jitcode_t)patch->detour;
|
||||
writer.outptr = writer.outbase;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
g_pSourcePawn->SetReadExecute(patch->detour);
|
||||
|
||||
unsigned char *source = (unsigned char *)patch->base + patch->offset;
|
||||
Protect(source, 6, PAGE_READWRITE);
|
||||
source[0] = 0xFF;
|
||||
source[1] = 0x25;
|
||||
*(void **)&source[2] = &patch->detour;
|
||||
Protect(source, 6, PAGE_EXECUTE_READ);
|
||||
|
||||
patch->applied = true;
|
||||
}
|
||||
|
||||
bool PrepPatch(const char *signature, const char *name, const char *platform, Patch *patch)
|
||||
{
|
||||
/* Get the base address of the function. */
|
||||
if (!g_pGameConf->GetMemSig(signature, &patch->base) || patch->base == NULL)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find signature: %s", signature);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *value;
|
||||
char keyname[255];
|
||||
|
||||
/* Get the verification bytes that will be written over. */
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Patch_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find key: %s", keyname);
|
||||
return false;
|
||||
}
|
||||
patch->search_len = UTIL_DecodeHexString(patch->search, sizeof(patch->search), value);
|
||||
if (patch->search_len < 6)
|
||||
{
|
||||
g_Logger.LogError("Error decoding %s value, or not long enough", keyname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the offset into the function. */
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Offset_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
|
||||
{
|
||||
g_Logger.LogError("Command filter could not find key: %s", keyname);
|
||||
return false;
|
||||
}
|
||||
patch->offset = atoi(value);
|
||||
if (patch->offset > 20000)
|
||||
{
|
||||
g_Logger.LogError("Command filter %s value is bogus", keyname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the number of bytes to save from what was written over. */
|
||||
patch->saveat = 0;
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Save_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
|
||||
{
|
||||
patch->saveat = atoi(value);
|
||||
if (patch->saveat >= patch->search_len)
|
||||
{
|
||||
g_Logger.LogError("Command filter %s value is too large", keyname);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get register for parameter, if any. */
|
||||
patch->regparam = -1;
|
||||
UTIL_Format(keyname, sizeof(keyname), "%s_Reg_%s", name, platform);
|
||||
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
|
||||
{
|
||||
patch->regparam = atoi(value);
|
||||
}
|
||||
|
||||
/* Everything loaded from gamedata, make sure the patch will succeed. */
|
||||
unsigned char *address = (unsigned char *)patch->base + patch->offset;
|
||||
for (size_t i = 0; i < patch->search_len; i++)
|
||||
{
|
||||
if (address[i] != patch->search[i])
|
||||
{
|
||||
g_Logger.LogError("Command filter %s has changed (byte %x is not %x sub-offset %d)",
|
||||
name, address[i], patch->search[i], i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static bool dummy_hook_set = false;
|
||||
void DummyHook()
|
||||
{
|
||||
if (dummy_hook_set)
|
||||
{
|
||||
dummy_hook_set = false;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BEGIN THE ACTUALLY GENERIC CODE.
|
||||
*/
|
||||
|
||||
#define FEATURECAP_COMMANDLISTENER "command listener"
|
||||
|
||||
static GenericCommandHooker s_GenericHooker;
|
||||
ConsoleDetours g_ConsoleDetours;
|
||||
|
||||
ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
|
||||
{
|
||||
}
|
||||
|
||||
void ConsoleDetours::OnSourceModAllInitialized()
|
||||
{
|
||||
m_pForward = g_Forwards.CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
|
||||
Param_String, Param_Cell);
|
||||
g_ShareSys.AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
|
||||
}
|
||||
|
||||
void ConsoleDetours::OnSourceModShutdown()
|
||||
{
|
||||
List<Listener*>::iterator iter = m_Listeners.begin();
|
||||
while (iter != m_Listeners.end())
|
||||
{
|
||||
Listener *listener = (*iter);
|
||||
g_Forwards.ReleaseForward(listener->forward);
|
||||
delete listener;
|
||||
iter = m_Listeners.erase(iter);
|
||||
}
|
||||
|
||||
g_Forwards.ReleaseForward(m_pForward);
|
||||
s_GenericHooker.Disable();
|
||||
}
|
||||
|
||||
FeatureStatus ConsoleDetours::GetFeatureStatus(FeatureType type, const char *name)
|
||||
{
|
||||
return GetStatus();
|
||||
}
|
||||
|
||||
FeatureStatus ConsoleDetours::GetStatus()
|
||||
{
|
||||
if (status == FeatureStatus_Unknown)
|
||||
{
|
||||
status = s_GenericHooker.Enable() ? FeatureStatus_Available : FeatureStatus_Unavailable;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
|
||||
{
|
||||
if (GetStatus() != FeatureStatus_Available)
|
||||
return false;
|
||||
|
||||
if (command == NULL)
|
||||
{
|
||||
m_pForward->AddFunction(fun);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *str = UTIL_ToLowerCase(command);
|
||||
Listener *listener;
|
||||
Listener **plistener = m_CmdLookup.retrieve(str);
|
||||
if (plistener == NULL)
|
||||
{
|
||||
listener = new Listener;
|
||||
listener->forward = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
|
||||
Param_String, Param_Cell);
|
||||
m_CmdLookup.insert(str, listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
listener = *plistener;
|
||||
}
|
||||
listener->forward->AddFunction(fun);
|
||||
delete [] str;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
|
||||
{
|
||||
if (command == NULL)
|
||||
{
|
||||
return m_pForward->RemoveFunction(fun);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *str = UTIL_ToLowerCase(command);
|
||||
Listener *listener;
|
||||
Listener **plistener = m_CmdLookup.retrieve(str);
|
||||
delete [] str;
|
||||
if (plistener == NULL)
|
||||
return false;
|
||||
listener = *plistener;
|
||||
return listener->forward->RemoveFunction(fun);
|
||||
}
|
||||
}
|
||||
|
||||
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
|
||||
{
|
||||
char name[255];
|
||||
const char *realname = args.Arg(0);
|
||||
size_t len = strlen(realname);
|
||||
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_Stop)
|
||||
return result;
|
||||
|
||||
Listener **plistener = m_CmdLookup.retrieve(name);
|
||||
if (plistener == NULL)
|
||||
return result;
|
||||
Listener *listener = *plistener;
|
||||
if (listener->forward->GetFunctionCount() == 0)
|
||||
return result;
|
||||
|
||||
cell_t result2 = Pl_Continue;
|
||||
listener->forward->PushCell(client);
|
||||
listener->forward->PushString(name);
|
||||
listener->forward->PushCell(args.ArgC() - 1);
|
||||
listener->forward->Execute(&result2, NULL);
|
||||
|
||||
if (result2 > result)
|
||||
result = result2;
|
||||
|
||||
/* "sm" should not have flown through the above. */
|
||||
assert(strcmp(name, "sm") != 0 || result == Pl_Continue);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
cell_t ConsoleDetours::Dispatch(ConCommand *pBase, const CCommand& args)
|
||||
{
|
||||
#else
|
||||
cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
|
||||
{
|
||||
CCommand args;
|
||||
#endif
|
||||
g_HL2.PushCommandStack(&args);
|
||||
cell_t res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), args);
|
||||
g_HL2.PopCommandStack();
|
||||
|
||||
#if SH_IMPL_VERSION < 4
|
||||
if (res >= Pl_Handled)
|
||||
{
|
||||
/* See bug 4020 - we can't optimize this because looking at the vtable
|
||||
* is probably more expensive, since there's no SH_GET_ORIG_VFNPTR_ENTRY.
|
||||
*/
|
||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
|
||||
dummy_hook_set = true;
|
||||
pBase->Dispatch();
|
||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure the command gets invoked. See bug 4019 on making this better. */
|
||||
pBase->Dispatch();
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#ifndef _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||
#define _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "ForwardSys.h"
|
||||
#include <sm_trie_tpl.h>
|
||||
|
||||
class ConsoleDetours :
|
||||
public SMGlobalClass,
|
||||
public IFeatureProvider
|
||||
{
|
||||
friend class PlayerManager;
|
||||
friend class GenericCommandHooker;
|
||||
|
||||
struct Listener
|
||||
{
|
||||
IChangeableForward *forward;
|
||||
};
|
||||
public:
|
||||
ConsoleDetours();
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IFeatureProvider
|
||||
FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
|
||||
public:
|
||||
bool AddListener(IPluginFunction *fun, const char *command);
|
||||
bool RemoveListener(IPluginFunction *fun, const char *command);
|
||||
private:
|
||||
cell_t InternalDispatch(int client, const CCommand& args);
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
|
||||
#else
|
||||
static cell_t Dispatch(ConCommand *pBase);
|
||||
#endif
|
||||
public:
|
||||
FeatureStatus GetStatus();
|
||||
bool IsEnabled()
|
||||
{
|
||||
return status == FeatureStatus_Available;
|
||||
}
|
||||
private:
|
||||
FeatureStatus status;
|
||||
IChangeableForward *m_pForward;
|
||||
KTrie<Listener*> m_CmdLookup;
|
||||
List<Listener*> m_Listeners;
|
||||
};
|
||||
|
||||
extern ConsoleDetours g_ConsoleDetours;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_ */
|
||||
|
||||
+59
-31
@@ -34,7 +34,7 @@
|
||||
#include "sourcemod.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "sm_version.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include "sm_stringutil.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "Logger.h"
|
||||
@@ -61,30 +61,35 @@ ConVar *g_ServerCfgFile = NULL;
|
||||
|
||||
void CheckAndFinalizeConfigs();
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if 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
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
void Hook_ExecDispatchPre()
|
||||
#endif
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
#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)
|
||||
if (!g_bServerExecd && arg != NULL && strcmp(arg, g_ServerCfgFile->GetString()) == 0)
|
||||
{
|
||||
g_bGotTrigger = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void Hook_ExecDispatchPost(const CCommand &cmd)
|
||||
#else
|
||||
void Hook_ExecDispatchPost()
|
||||
@@ -100,14 +105,9 @@ void Hook_ExecDispatchPost()
|
||||
|
||||
void CheckAndFinalizeConfigs()
|
||||
{
|
||||
if ((g_bServerExecd || g_ServerCfgFile == NULL)
|
||||
&& g_bGotServerStart)
|
||||
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
g_PendingInternalPush = true;
|
||||
#else
|
||||
SM_InternalCmdTrigger();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,14 @@ void CoreConfig::OnSourceModAllInitialized()
|
||||
g_pOnAutoConfigsBuffered = g_Forwards.CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
|
||||
}
|
||||
|
||||
CoreConfig::CoreConfig() : m_Strings(512)
|
||||
{
|
||||
}
|
||||
|
||||
CoreConfig::~CoreConfig()
|
||||
{
|
||||
}
|
||||
|
||||
void CoreConfig::OnSourceModShutdown()
|
||||
{
|
||||
g_RootMenu.RemoveRootConsoleCommand("config", this);
|
||||
@@ -151,17 +159,7 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
|
||||
|
||||
if (g_ServerCfgFile != NULL)
|
||||
{
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
while (pBase != NULL)
|
||||
{
|
||||
if (pBase->IsCommand() && strcmp(pBase->GetName(), "exec") == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
}
|
||||
|
||||
g_pExecPtr = (ConCommand *)pBase;
|
||||
g_pExecPtr = FindCommand("exec");
|
||||
if (g_pExecPtr != NULL)
|
||||
{
|
||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
|
||||
@@ -216,14 +214,32 @@ void CoreConfig::Initialize()
|
||||
/* Try to get command line value of core config convar */
|
||||
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
|
||||
|
||||
/* If sm_corecfgfile not specified on command line, use default value */
|
||||
if (!corecfg)
|
||||
/* If sm_corecfgfile is on the command line, use that
|
||||
* If sm_corecfgfile isn't there, check sm_basepath on the command line and build the path off that
|
||||
* If sm_basepath isn't there, just use the default path for the cfg
|
||||
*/
|
||||
if (corecfg)
|
||||
{
|
||||
corecfg = sm_corecfgfile.GetDefault();
|
||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *basepath = icvar->GetCommandLineValue("sm_basepath");
|
||||
|
||||
/* Format path to config file */
|
||||
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 */
|
||||
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
|
||||
/* Reset cached key values */
|
||||
m_KeyValues.clear();
|
||||
m_Strings.Reset();
|
||||
|
||||
/* Parse config file */
|
||||
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
|
||||
@@ -263,9 +279,21 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
m_KeyValues.replace(option, m_Strings.AddString(value));
|
||||
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
|
||||
const char *CoreConfig::GetCoreConfigValue(const char *key)
|
||||
{
|
||||
int *pKey = m_KeyValues.retrieve(key);
|
||||
if (pKey == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return m_Strings.GetString(*pKey);
|
||||
}
|
||||
|
||||
bool SM_AreConfigsExecuted()
|
||||
{
|
||||
return g_bConfigsExecd;
|
||||
@@ -367,7 +395,7 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
|
||||
FILE *fp = fopen(file, "wt");
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SVN_FULL_VERSION);
|
||||
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SM_FULL_VERSION);
|
||||
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
|
||||
fprintf(fp, "\n\n");
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "sm_globals.h"
|
||||
#include <ITextParsers.h>
|
||||
#include <IRootConsoleMenu.h>
|
||||
#include <sm_trie_tpl.h>
|
||||
#include "sm_memtable.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
@@ -43,6 +45,9 @@ class CoreConfig :
|
||||
public ITextListener_SMC,
|
||||
public IRootConsoleCommand
|
||||
{
|
||||
public:
|
||||
CoreConfig();
|
||||
~CoreConfig();
|
||||
public: // SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
@@ -56,11 +61,15 @@ public:
|
||||
* Initializes CoreConfig by reading from core.cfg file
|
||||
*/
|
||||
void Initialize();
|
||||
const char *GetCoreConfigValue(const char *key);
|
||||
private:
|
||||
/**
|
||||
* 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);
|
||||
private:
|
||||
BaseStringTable m_Strings;
|
||||
KTrie<int> m_KeyValues;
|
||||
};
|
||||
|
||||
extern bool SM_AreConfigsExecuted();
|
||||
|
||||
+41
-32
@@ -37,7 +37,7 @@
|
||||
#include "Logger.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include <stdlib.h>
|
||||
#include "ThreadSupport.h"
|
||||
#include <IThreader.h>
|
||||
|
||||
#define DBPARSE_LEVEL_NONE 0
|
||||
#define DBPARSE_LEVEL_MAIN 1
|
||||
@@ -47,7 +47,7 @@ DBManager g_DBMan;
|
||||
static bool s_OneTimeThreaderErrorMsg = false;
|
||||
|
||||
DBManager::DBManager()
|
||||
: m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
|
||||
: m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ void DBManager::OnSourceModShutdown()
|
||||
m_pQueueLock->DestroyThis();
|
||||
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
||||
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
||||
ClearConfigs();
|
||||
}
|
||||
|
||||
unsigned int DBManager::GetInterfaceVersion()
|
||||
@@ -133,13 +134,20 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
|
||||
void DBManager::ReadSMC_ParseStart()
|
||||
{
|
||||
m_confs.clear();
|
||||
ClearConfigs();
|
||||
m_ParseLevel = 0;
|
||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||
m_StrTab.Reset();
|
||||
m_DefDriver.clear();
|
||||
}
|
||||
|
||||
void DBManager::ClearConfigs()
|
||||
{
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
delete (*iter);
|
||||
m_confs.clear();
|
||||
}
|
||||
|
||||
ConfDbInfo s_CurInfo;
|
||||
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
@@ -159,7 +167,7 @@ SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *nam
|
||||
}
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||
s_CurInfo = ConfDbInfo();
|
||||
s_CurInfo.name = m_StrTab.AddString(name);
|
||||
s_CurInfo.name = name;
|
||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||
m_ParseLevel++;
|
||||
@@ -186,16 +194,16 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
{
|
||||
if (strcmp(value, "default") != 0)
|
||||
{
|
||||
s_CurInfo.driver = m_StrTab.AddString(value);
|
||||
s_CurInfo.driver = value;
|
||||
}
|
||||
} else if (strcmp(key, "database") == 0) {
|
||||
s_CurInfo.database = m_StrTab.AddString(value);
|
||||
s_CurInfo.database = value;
|
||||
} else if (strcmp(key, "host") == 0) {
|
||||
s_CurInfo.host = m_StrTab.AddString(value);
|
||||
s_CurInfo.host = value;
|
||||
} else if (strcmp(key, "user") == 0) {
|
||||
s_CurInfo.user = m_StrTab.AddString(value);
|
||||
s_CurInfo.user = value;
|
||||
} else if (strcmp(key, "pass") == 0) {
|
||||
s_CurInfo.pass = m_StrTab.AddString(value);
|
||||
s_CurInfo.pass = value;
|
||||
} else if (strcmp(key, "timeout") == 0) {
|
||||
s_CurInfo.info.maxTimeout = atoi(value);
|
||||
} else if (strcmp(key, "port") == 0) {
|
||||
@@ -206,13 +214,6 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
#define ASSIGN_VAR(var) \
|
||||
if (s_CurInfo.var == -1) { \
|
||||
s_CurInfo.info.var = ""; \
|
||||
} else { \
|
||||
s_CurInfo.info.var = m_StrTab.GetString(s_CurInfo.var); \
|
||||
}
|
||||
|
||||
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
@@ -223,17 +224,26 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
||||
{
|
||||
/* Set all of the info members to either a blank string
|
||||
* or the string pointer from the string table.
|
||||
*/
|
||||
ASSIGN_VAR(driver);
|
||||
ASSIGN_VAR(database);
|
||||
ASSIGN_VAR(host);
|
||||
ASSIGN_VAR(user);
|
||||
ASSIGN_VAR(pass);
|
||||
ConfDbInfo *cdb = new ConfDbInfo();
|
||||
|
||||
cdb->name = s_CurInfo.name;
|
||||
cdb->driver = s_CurInfo.driver;
|
||||
cdb->host = s_CurInfo.host;
|
||||
cdb->user = s_CurInfo.user;
|
||||
cdb->pass = s_CurInfo.pass;
|
||||
cdb->database = s_CurInfo.database;
|
||||
cdb->realDriver = s_CurInfo.realDriver;
|
||||
cdb->info.maxTimeout = s_CurInfo.info.maxTimeout;
|
||||
cdb->info.port = s_CurInfo.info.port;
|
||||
|
||||
cdb->info.driver = cdb->driver.c_str();
|
||||
cdb->info.database = cdb->database.c_str();
|
||||
cdb->info.host = cdb->host.c_str();
|
||||
cdb->info.user = cdb->user.c_str();
|
||||
cdb->info.pass = cdb->pass.c_str();
|
||||
|
||||
/* Save it.. */
|
||||
m_confs.push_back(s_CurInfo);
|
||||
m_confs.push_back(cdb);
|
||||
|
||||
/* Go up one level */
|
||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||
@@ -244,7 +254,6 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
#undef ASSIGN_VAR
|
||||
|
||||
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
@@ -333,10 +342,10 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
||||
}
|
||||
|
||||
/* Make sure NOTHING references this! */
|
||||
List<ConfDbInfo>::iterator iter;
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
{
|
||||
ConfDbInfo &db = (*iter);
|
||||
ConfDbInfo &db = *(*iter);
|
||||
if (db.realDriver == pDriver)
|
||||
{
|
||||
db.realDriver = NULL;
|
||||
@@ -448,12 +457,12 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
||||
|
||||
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
|
||||
{
|
||||
List<ConfDbInfo>::iterator iter;
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
{
|
||||
ConfDbInfo &conf = (*iter);
|
||||
if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
|
||||
ConfDbInfo &conf = *(*iter);
|
||||
if (conf.name == name)
|
||||
{
|
||||
return &conf;
|
||||
}
|
||||
|
||||
+9
-10
@@ -47,16 +47,15 @@ using namespace SourceHook;
|
||||
|
||||
struct ConfDbInfo
|
||||
{
|
||||
ConfDbInfo() : name(-1), driver(-1), host(-1), user(-1), pass(-1),
|
||||
database(-1), realDriver(NULL)
|
||||
ConfDbInfo() : realDriver(NULL)
|
||||
{
|
||||
}
|
||||
int name;
|
||||
int driver;
|
||||
int host;
|
||||
int user;
|
||||
int pass;
|
||||
int database;
|
||||
String name;
|
||||
String driver;
|
||||
String host;
|
||||
String user;
|
||||
String pass;
|
||||
String database;
|
||||
IDBDriver *realDriver;
|
||||
DatabaseInfo info;
|
||||
};
|
||||
@@ -121,6 +120,7 @@ public:
|
||||
return m_DatabaseType;
|
||||
}
|
||||
private:
|
||||
void ClearConfigs();
|
||||
void KillWorkerThread();
|
||||
private:
|
||||
CVector<IDBDriver *> m_drivers;
|
||||
@@ -134,11 +134,10 @@ private:
|
||||
IMutex *m_pQueueLock; /* Queue safety lock */
|
||||
IMutex *m_pThinkLock; /* Think-queue lock */
|
||||
|
||||
List<ConfDbInfo> m_confs;
|
||||
List<ConfDbInfo *> m_confs;
|
||||
HandleType_t m_DriverType;
|
||||
HandleType_t m_DatabaseType;
|
||||
String m_DefDriver;
|
||||
BaseStringTable m_StrTab;
|
||||
char m_Filename[PLATFORM_MAX_PATH];
|
||||
unsigned int m_ParseLevel;
|
||||
unsigned int m_ParseState;
|
||||
|
||||
+39
-6
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -42,6 +42,20 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
|
||||
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
|
||||
typedef List<EventHook *> EventHookList;
|
||||
|
||||
class EventForwardFilter : public IForwardFilter
|
||||
{
|
||||
EventInfo *pEventInfo;
|
||||
public:
|
||||
EventForwardFilter(EventInfo *pEventInfo) : pEventInfo(pEventInfo)
|
||||
{
|
||||
}
|
||||
|
||||
void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
|
||||
{
|
||||
params[2].val = pEventInfo->bDontBroadcast ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
EventManager::EventManager() : m_EventType(0)
|
||||
{
|
||||
/* Create an event lookup trie */
|
||||
@@ -147,6 +161,13 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
|
||||
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
int EventManager::GetEventDebugID()
|
||||
{
|
||||
return EVENT_DEBUG_ID_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
|
||||
{
|
||||
EventHook *pHook;
|
||||
@@ -194,7 +215,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
|
||||
}
|
||||
|
||||
/* Cache the name for post hooks */
|
||||
pHook->name = strdup(name);
|
||||
pHook->name = sm_strdup(name);
|
||||
|
||||
/* Increase reference count */
|
||||
pHook->refCount++;
|
||||
@@ -300,7 +321,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
|
||||
sm_trie_delete(m_EventHooks, name);
|
||||
|
||||
/* Free the cached name */
|
||||
free(pHook->name);
|
||||
delete pHook->name;
|
||||
|
||||
/* And finally free structure memory */
|
||||
delete pHook;
|
||||
@@ -327,6 +348,7 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name,
|
||||
|
||||
pInfo->pEvent = pEvent;
|
||||
pInfo->pOwner = pContext->GetIdentity();
|
||||
pInfo->bDontBroadcast = false;
|
||||
|
||||
return pInfo;
|
||||
}
|
||||
@@ -365,6 +387,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
IChangeableForward *pForward;
|
||||
const char *name;
|
||||
cell_t res = Pl_Continue;
|
||||
bool broadcast = bDontBroadcast;
|
||||
|
||||
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
|
||||
if (!pEvent)
|
||||
@@ -390,10 +413,16 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
HandleSecurity sec(NULL, g_pCoreIdent);
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||
|
||||
info.bDontBroadcast = bDontBroadcast;
|
||||
|
||||
EventForwardFilter filter(&info);
|
||||
|
||||
pForward->PushCell(hndl);
|
||||
pForward->PushString(name);
|
||||
pForward->PushCell(bDontBroadcast);
|
||||
pForward->Execute(&res, NULL);
|
||||
pForward->Execute(&res, &filter);
|
||||
|
||||
broadcast = info.bDontBroadcast;
|
||||
|
||||
g_HandleSys.FreeHandle(hndl, &sec);
|
||||
}
|
||||
@@ -414,6 +443,9 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
m_EventStack.push(NULL);
|
||||
}
|
||||
|
||||
if (broadcast != bDontBroadcast)
|
||||
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast));
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||
}
|
||||
|
||||
@@ -441,6 +473,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
{
|
||||
if (pHook->postCopy)
|
||||
{
|
||||
info.bDontBroadcast = bDontBroadcast;
|
||||
info.pEvent = m_EventCopies.front();
|
||||
info.pOwner = NULL;
|
||||
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
|
||||
@@ -472,7 +505,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
assert(pHook->pPostHook == NULL);
|
||||
assert(pHook->pPreHook == NULL);
|
||||
sm_trie_delete(m_EventHooks, pHook->name);
|
||||
free(pHook->name);
|
||||
delete pHook->name;
|
||||
delete pHook;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -53,6 +53,7 @@ struct EventInfo
|
||||
}
|
||||
IGameEvent *pEvent;
|
||||
IdentityToken_t *pOwner;
|
||||
bool bDontBroadcast;
|
||||
};
|
||||
|
||||
struct EventHook
|
||||
@@ -104,6 +105,9 @@ public: // IPluginsListener
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
public: // IGameEventListener2
|
||||
void FireGameEvent(IGameEvent *pEvent);
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
int GetEventDebugID();
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
* Get the 'GameEvent' handle type ID.
|
||||
|
||||
+175
-35
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -49,6 +49,9 @@ void CExtension::Initialize(const char *filename, const char *path)
|
||||
m_bFullyLoaded = false;
|
||||
m_File.assign(filename);
|
||||
m_Path.assign(path);
|
||||
char real_name[PLATFORM_MAX_PATH];
|
||||
g_LibSys.GetFileFromPath(real_name, sizeof(real_name), m_Path.c_str());
|
||||
m_RealFile.assign(real_name);
|
||||
}
|
||||
|
||||
CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filename, const char *path)
|
||||
@@ -57,6 +60,26 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
|
||||
m_pAPI = pAPI;
|
||||
}
|
||||
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
#define GAMEFIX "2.l4d"
|
||||
#elif SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||
#define GAMEFIX "2.l4d2"
|
||||
#elif SOURCE_ENGINE == SE_ALIENSWARM
|
||||
#define GAMEFIX "2.swarm"
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
||||
#define GAMEFIX "2.ep2"
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
|
||||
#define GAMEFIX "2.ep2v"
|
||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
#define GAMEFIX "2.darkm"
|
||||
#else
|
||||
#define GAMEFIX "2.ep1"
|
||||
#endif //(SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2)
|
||||
#else //METAMOD_PLAPI_VERSION
|
||||
#define GAMEFIX "1.ep1"
|
||||
#endif //METAMOD_PLAPI_VERSION
|
||||
|
||||
CLocalExtension::CLocalExtension(const char *filename)
|
||||
{
|
||||
m_PlId = 0;
|
||||
@@ -64,27 +87,36 @@ CLocalExtension::CLocalExtension(const char *filename)
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
/* Zeroth, see if there is an engine specific build in the new place. */
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s." GAMEFIX "." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
if (g_LibSys.IsPathFile(path))
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* First see if there is an engine specific build! */
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined ORANGEBOX_BUILD
|
||||
"extensions/auto.2.ep2/%s",
|
||||
#else
|
||||
"extensions/auto.2.ep1/%s",
|
||||
#endif //ORANGEBOX_BUILD
|
||||
#else //METAMOD_PLAPI_VERSION
|
||||
"extensions/auto.1.ep1/%s",
|
||||
#endif //METAMOD_PLAPI_VERSION
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/auto." GAMEFIX "/%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
/* Try the "normal" version */
|
||||
if (!g_LibSys.IsPathFile(path))
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "extensions/%s", filename);
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
}
|
||||
|
||||
found:
|
||||
Initialize(filename, path);
|
||||
}
|
||||
|
||||
@@ -183,6 +215,23 @@ void CLocalExtension::Unload()
|
||||
}
|
||||
}
|
||||
|
||||
bool CRemoteExtension::Reload(char *error, size_t maxlength)
|
||||
{
|
||||
snprintf(error, maxlength, "Remote extensions do not support reloading");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CLocalExtension::Reload(char *error, size_t maxlength)
|
||||
{
|
||||
if (m_pLib == NULL) // FIXME: just load it instead?
|
||||
return false;
|
||||
|
||||
m_pAPI->OnExtensionUnload();
|
||||
Unload();
|
||||
|
||||
return Load(error, maxlength);
|
||||
}
|
||||
|
||||
bool CRemoteExtension::IsExternal()
|
||||
{
|
||||
return true;
|
||||
@@ -287,7 +336,7 @@ IExtensionInterface *CExtension::GetAPI()
|
||||
|
||||
const char *CExtension::GetFilename()
|
||||
{
|
||||
return m_File.c_str();
|
||||
return m_RealFile.c_str();
|
||||
}
|
||||
|
||||
IdentityToken_t *CExtension::GetIdentity()
|
||||
@@ -490,7 +539,7 @@ void CExtensionManager::TryAutoload()
|
||||
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
len = UTIL_Format(file, sizeof(file), "%s", lfile);
|
||||
strcpy(&file[len - 9], ".ext." PLATFORM_LIB_EXT);
|
||||
strcpy(&file[len - 9], ".ext");
|
||||
|
||||
LoadAutoExtension(file);
|
||||
|
||||
@@ -500,11 +549,14 @@ void CExtensionManager::TryAutoload()
|
||||
|
||||
IExtension *CExtensionManager::LoadAutoExtension(const char *path)
|
||||
{
|
||||
if (!strstr(path, "." PLATFORM_LIB_EXT))
|
||||
/* Remove platform extension if it's there. Compat hack. */
|
||||
const char *ext = g_LibSys.GetFileExtension(path);
|
||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
{
|
||||
char newpath[PLATFORM_MAX_PATH];
|
||||
g_LibSys.PathFormat(newpath, sizeof(newpath), "%s.%s", path, PLATFORM_LIB_EXT);
|
||||
return LoadAutoExtension(newpath);
|
||||
char path2[PLATFORM_MAX_PATH];
|
||||
UTIL_Format(path2, sizeof(path2), "%s", path);
|
||||
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||
return LoadAutoExtension(path2);
|
||||
}
|
||||
|
||||
IExtension *pAlready;
|
||||
@@ -542,24 +594,12 @@ IExtension *CExtensionManager::FindExtensionByFile(const char *file)
|
||||
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
|
||||
{
|
||||
pExt = (*iter);
|
||||
char short_file[PLATFORM_MAX_PATH];
|
||||
g_LibSys.GetFileFromPath(short_file, sizeof(short_file), pExt->GetFilename());
|
||||
if (strcmp(lookup, short_file) == 0)
|
||||
if (pExt->IsSameFile(lookup))
|
||||
{
|
||||
return pExt;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got no results, test if there was a platform extension.
|
||||
* If not, add one.
|
||||
*/
|
||||
if (!strstr(file, "." PLATFORM_LIB_EXT))
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
UTIL_Format(path, sizeof(path), "%s.%s", file, PLATFORM_LIB_EXT);
|
||||
return FindExtensionByFile(path);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -597,6 +637,16 @@ IExtension *CExtensionManager::FindExtensionByName(const char *ext)
|
||||
|
||||
IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
/* Remove platform extension if it's there. Compat hack. */
|
||||
const char *ext = g_LibSys.GetFileExtension(file);
|
||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
{
|
||||
char path2[PLATFORM_MAX_PATH];
|
||||
UTIL_Format(path2, sizeof(path2), "%s", file);
|
||||
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||
return LoadExtension(path2, error, maxlength);
|
||||
}
|
||||
|
||||
IExtension *pAlready;
|
||||
if ((pAlready=FindExtensionByFile(file)) != NULL)
|
||||
{
|
||||
@@ -905,11 +955,42 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (strcmp(cmd, "load") == 0)
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts load <file>");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *filename = command.Arg(3);
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
char error[256];
|
||||
|
||||
UTIL_Format(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
|
||||
!strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
|
||||
|
||||
if (FindExtensionByFile(path) != NULL)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s is already loaded.", path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LoadExtension(path, error, sizeof(error)))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Loaded extension %s successfully.", path);
|
||||
} else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s failed to load: %s", path, error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (strcmp(cmd, "info") == 0)
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -917,7 +998,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
unsigned int id = atoi(sId);
|
||||
if (id <= 0)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -994,7 +1075,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm unload <#> [code]");
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts unload <#> [code]");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1107,11 +1188,57 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "reload") == 0)
|
||||
{
|
||||
if (argcount < 4)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Usage: sm exts reload <#>");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *arg = command.Arg(3);
|
||||
unsigned int num = atoi(arg);
|
||||
CExtension *pExt = FindByOrder(num);
|
||||
|
||||
if (!pExt)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pExt->IsLoaded())
|
||||
{
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
char error[255];
|
||||
|
||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
||||
|
||||
if (pExt->Reload(error, sizeof(error)))
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s is now reloaded.", filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s failed to reload: %s", filename, error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_RootMenu.ConsolePrint("[SM] Extension %s is not loaded.", pExt->GetFilename());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
g_RootMenu.ConsolePrint("SourceMod Extensions Menu:");
|
||||
g_RootMenu.DrawGenericOption("info", "Extra extension information");
|
||||
g_RootMenu.DrawGenericOption("list", "List extensions");
|
||||
g_RootMenu.DrawGenericOption("load", "Load an extension");
|
||||
g_RootMenu.DrawGenericOption("reload", "Reload an extension");
|
||||
g_RootMenu.DrawGenericOption("unload", "Unload an extension");
|
||||
}
|
||||
|
||||
@@ -1206,3 +1333,16 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CLocalExtension::IsSameFile(const char *file)
|
||||
{
|
||||
/* Only care about the shortened name. */
|
||||
return strcmp(file, m_File.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool CRemoteExtension::IsSameFile(const char *file)
|
||||
{
|
||||
/* :TODO: this could be better, but no one uses this API anyway. */
|
||||
return strcmp(file, m_Path.c_str()) == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@ public:
|
||||
virtual bool Load(char *error, size_t maxlength);
|
||||
virtual bool IsLoaded() =0;
|
||||
virtual void Unload() =0;
|
||||
virtual bool Reload(char *error, size_t maxlength) =0;
|
||||
virtual bool IsSameFile(const char* file) =0;
|
||||
protected:
|
||||
void Initialize(const char *filename, const char *path);
|
||||
bool PerformAPICheck(char *error, size_t maxlength);
|
||||
@@ -92,6 +94,7 @@ protected:
|
||||
IdentityToken_t *m_pIdentToken;
|
||||
IExtensionInterface *m_pAPI;
|
||||
String m_File;
|
||||
String m_RealFile;
|
||||
String m_Path;
|
||||
String m_Error;
|
||||
List<IfaceInfo> m_Deps; /** Dependencies */
|
||||
@@ -110,7 +113,9 @@ public:
|
||||
bool Load(char *error, size_t maxlength);
|
||||
bool IsLoaded();
|
||||
void Unload();
|
||||
bool Reload(char *error, size_t maxlength);
|
||||
bool IsExternal();
|
||||
bool IsSameFile(const char *file);
|
||||
private:
|
||||
PluginId m_PlId;
|
||||
ILibrary *m_pLib;
|
||||
@@ -124,7 +129,9 @@ public:
|
||||
bool Load(char *error, size_t maxlength);
|
||||
bool IsLoaded();
|
||||
void Unload();
|
||||
bool Reload(char *error, size_t maxlength);
|
||||
bool IsExternal();
|
||||
bool IsSameFile(const char *file);
|
||||
};
|
||||
|
||||
class CExtensionManager :
|
||||
|
||||
+14
-8
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -255,6 +255,7 @@ CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int nu
|
||||
}
|
||||
|
||||
CForward *pForward = g_Forwards.ForwardMake();
|
||||
pForward->m_IterGuard = NULL;
|
||||
pForward->m_curparam = 0;
|
||||
pForward->m_ExecType = et;
|
||||
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
||||
@@ -294,7 +295,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
cell_t high_result = 0;
|
||||
cell_t low_result = 0;
|
||||
int err;
|
||||
unsigned int failed=0, success=0;
|
||||
unsigned int success=0;
|
||||
unsigned int num_params = m_curparam;
|
||||
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||
FwdParamInfo *param;
|
||||
@@ -304,10 +305,15 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
memcpy(temp_info, m_params, sizeof(m_params));
|
||||
m_curparam = 0;
|
||||
|
||||
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
||||
FuncIteratorGuard guard(&m_IterGuard, &iter);
|
||||
|
||||
while (iter != m_functions.end())
|
||||
{
|
||||
func = (*iter);
|
||||
|
||||
if (filter)
|
||||
filter->Preprocess(func, temp_info);
|
||||
|
||||
for (unsigned int i=0; i<num_params; i++)
|
||||
{
|
||||
int err = SP_ERROR_PARAM;
|
||||
@@ -359,11 +365,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
}
|
||||
|
||||
/* Call the function and deal with the return value. */
|
||||
if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
|
||||
{
|
||||
failed++;
|
||||
}
|
||||
else
|
||||
if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE)
|
||||
{
|
||||
success++;
|
||||
switch (m_ExecType)
|
||||
@@ -403,6 +405,9 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!guard.Triggered())
|
||||
iter++;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -682,6 +687,7 @@ bool CForward::RemoveFunction(IPluginFunction *func)
|
||||
{
|
||||
if ((*iter) == func)
|
||||
{
|
||||
m_IterGuard->FixIteratorChain(iter);
|
||||
found = true;
|
||||
lst->erase(iter);
|
||||
break;
|
||||
|
||||
@@ -61,6 +61,58 @@ struct FwdParamInfo
|
||||
ParamType pushedas;
|
||||
};
|
||||
|
||||
class SourceMod::IForwardFilter
|
||||
{
|
||||
public:
|
||||
virtual void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class FuncIteratorGuard
|
||||
{
|
||||
bool triggered;
|
||||
FuncIteratorGuard **pprev;
|
||||
FuncIter *iter;
|
||||
FuncIteratorGuard *next;
|
||||
public:
|
||||
FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter)
|
||||
: triggered(false), pprev(pprev), iter(iter), next(*pprev)
|
||||
{
|
||||
*pprev = this;
|
||||
}
|
||||
|
||||
~FuncIteratorGuard()
|
||||
{
|
||||
*pprev = next;
|
||||
}
|
||||
|
||||
inline bool Triggered()
|
||||
{
|
||||
bool t = triggered;
|
||||
triggered = false;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should not read from |this| before the NULL check, because FwdSys
|
||||
* can call (NULL)->FixIteratorChain().
|
||||
*/
|
||||
void FixIteratorChain(FuncIter &other)
|
||||
{
|
||||
FuncIteratorGuard *guard = this;
|
||||
while (guard != NULL)
|
||||
{
|
||||
if (*guard->iter == other)
|
||||
{
|
||||
*(guard->iter) = ++(*(guard->iter));
|
||||
guard->triggered = true;
|
||||
}
|
||||
guard = guard->next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CForward : public IChangeableForward
|
||||
{
|
||||
public: //ICallable
|
||||
@@ -103,6 +155,7 @@ protected:
|
||||
*/
|
||||
mutable List<IPluginFunction *> m_functions;
|
||||
mutable List<IPluginFunction *> m_paused;
|
||||
FuncIteratorGuard *m_IterGuard;
|
||||
|
||||
/* Type and name information */
|
||||
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
||||
|
||||
+323
-76
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,8 +25,6 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -42,7 +40,6 @@
|
||||
#include "LibrarySys.h"
|
||||
#include "HandleSys.h"
|
||||
#include "sm_crc32.h"
|
||||
#include "GameDataFetcher.h"
|
||||
|
||||
#if defined PLATFORM_LINUX
|
||||
#include <dlfcn.h>
|
||||
@@ -50,9 +47,9 @@
|
||||
|
||||
GameConfigManager g_GameConfigs;
|
||||
IGameConfig *g_pGameConf = NULL;
|
||||
char g_Game[256];
|
||||
char g_GameDesc[256] = {'!', '\0'};
|
||||
char g_GameName[256] = {'$', '\0'};
|
||||
static char g_Game[256];
|
||||
static char g_GameDesc[256] = {'!', '\0'};
|
||||
static char g_GameName[256] = {'$', '\0'};
|
||||
|
||||
#define PSTATE_NONE 0
|
||||
#define PSTATE_GAMES 1
|
||||
@@ -91,9 +88,49 @@ struct TempSigInfo
|
||||
unsigned int s_ServerBinCRC;
|
||||
bool s_ServerBinCRC_Ok = false;
|
||||
|
||||
static bool DoesGameMatch(const char *value)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
if (strcasecmp(value, g_Game) == 0 ||
|
||||
#else
|
||||
if (strcmp(value, g_Game) == 0 ||
|
||||
#endif
|
||||
strcmp(value, g_GameDesc) == 0 ||
|
||||
strcmp(value, g_GameName) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DoesEngineMatch(const char *value)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
if (strcmp(value, "original") == 0)
|
||||
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
if (strcmp(value, "darkmessiah") == 0)
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
||||
if (strcmp(value, "orangebox") == 0)
|
||||
#elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
|
||||
if (strcmp(value, "orangebox_valve") == 0)
|
||||
#elif SOURCE_ENGINE == SE_LEFT4DEAD
|
||||
if (strcmp(value, "left4dead") == 0)
|
||||
#elif SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||
if (strcmp(value, "left4dead2") == 0)
|
||||
#elif SOURCE_ENGINE == SE_ALIENSWARM
|
||||
if (strcmp(value, "alienswarm") == 0)
|
||||
#else
|
||||
#error "Unknown engine type"
|
||||
#endif
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CGameConfig::CGameConfig(const char *file)
|
||||
{
|
||||
m_pFile = sm_strdup(file);
|
||||
strncopy(m_File, file, sizeof(m_File));
|
||||
m_pOffsets = sm_trie_create();
|
||||
m_pProps = sm_trie_create();
|
||||
m_pKeys = sm_trie_create();
|
||||
@@ -111,7 +148,6 @@ CGameConfig::~CGameConfig()
|
||||
sm_trie_destroy(m_pProps);
|
||||
sm_trie_destroy(m_pKeys);
|
||||
sm_trie_destroy(m_pSigs);
|
||||
delete [] m_pFile;
|
||||
delete m_pStrings;
|
||||
}
|
||||
|
||||
@@ -137,11 +173,9 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
}
|
||||
case PSTATE_GAMES:
|
||||
{
|
||||
if ((strcmp(name, "*") == 0)
|
||||
|| (strcmp(name, "#default") == 0)
|
||||
|| (strcasecmp(name, g_Game) == 0)
|
||||
|| (strcasecmp(name, g_GameDesc) == 0)
|
||||
|| (strcasecmp(name, g_GameName) == 0))
|
||||
if (strcmp(name, "*") == 0 ||
|
||||
strcmp(name, "#default") == 0 ||
|
||||
DoesGameMatch(name))
|
||||
{
|
||||
bShouldBeReadingDefault = true;
|
||||
m_ParseState = PSTATE_GAMEDEFS;
|
||||
@@ -161,12 +195,15 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
{
|
||||
m_ParseState = PSTATE_GAMEDEFS_KEYS;
|
||||
}
|
||||
else if ((strcmp(name, "#supported") == 0)
|
||||
&& (strcmp(m_Game, "#default") == 0))
|
||||
else if ((strcmp(name, "#supported") == 0) && (strcmp(m_Game, "#default") == 0))
|
||||
{
|
||||
m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
|
||||
/* Ignore this section unless we get a game. */
|
||||
bShouldBeReadingDefault = false;
|
||||
had_game = false;
|
||||
matched_game = false;
|
||||
had_engine = false;
|
||||
matched_engine = false;
|
||||
}
|
||||
else if (strcmp(name, "Signatures") == 0)
|
||||
{
|
||||
@@ -245,7 +282,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
if (error[0] != '\0')
|
||||
{
|
||||
m_IgnoreLevel = 1;
|
||||
g_Logger.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_pFile);
|
||||
g_Logger.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||
g_Logger.LogError("[SM] %s", error);
|
||||
} else {
|
||||
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
|
||||
@@ -298,13 +335,29 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
int id = m_pStrings->AddString(value);
|
||||
sm_trie_replace(m_pKeys, key, (void *)id);
|
||||
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
|
||||
if (strcmp(key, "game") == 0
|
||||
&& (strcasecmp(value, g_Game) == 0
|
||||
|| strcasecmp(value, g_GameDesc) == 0
|
||||
|| strcasecmp(value, g_GameName) == 0)
|
||||
)
|
||||
if (strcmp(key, "game") == 0)
|
||||
{
|
||||
bShouldBeReadingDefault = true;
|
||||
had_game = true;
|
||||
if (DoesGameMatch(value))
|
||||
{
|
||||
matched_game = true;
|
||||
}
|
||||
if ((!had_engine && matched_game) || (matched_engine && matched_game))
|
||||
{
|
||||
bShouldBeReadingDefault = true;
|
||||
}
|
||||
}
|
||||
else if (strcmp(key, "engine") == 0)
|
||||
{
|
||||
had_engine = true;
|
||||
if (DoesEngineMatch(value))
|
||||
{
|
||||
matched_engine = true;
|
||||
}
|
||||
if ((!had_game && matched_engine) || (matched_game && matched_engine))
|
||||
{
|
||||
bShouldBeReadingDefault = true;
|
||||
}
|
||||
}
|
||||
} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
|
||||
if (strcmp(key, PLATFORM_NAME) == 0)
|
||||
@@ -391,7 +444,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
||||
m_Class,
|
||||
m_Prop,
|
||||
m_pFile,
|
||||
m_CurFile,
|
||||
m_Game);
|
||||
}
|
||||
}
|
||||
@@ -441,7 +494,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_pFile);
|
||||
m_CurFile);
|
||||
} else {
|
||||
#if defined PLATFORM_LINUX
|
||||
if (s_TempSig.sig[0] == '@')
|
||||
@@ -453,17 +506,21 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
||||
if (handle)
|
||||
{
|
||||
#if (SOURCE_ENGINE == SE_ORANGEBOXVALVE) || (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2)
|
||||
final_addr = g_MemUtils.ResolveSymbol(handle, &s_TempSig.sig[1]);
|
||||
#else
|
||||
final_addr = dlsym(handle, &s_TempSig.sig[1]);
|
||||
#endif
|
||||
dlclose(handle);
|
||||
} else {
|
||||
g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_pFile);
|
||||
m_File);
|
||||
}
|
||||
} else {
|
||||
g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
|
||||
s_TempSig.library,
|
||||
m_pFile);
|
||||
m_File);
|
||||
}
|
||||
}
|
||||
if (final_addr)
|
||||
@@ -472,45 +529,18 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
}
|
||||
#endif
|
||||
/* First, preprocess the signature */
|
||||
char real_sig[511];
|
||||
unsigned char real_sig[511];
|
||||
size_t real_bytes;
|
||||
size_t length;
|
||||
|
||||
real_bytes = 0;
|
||||
length = strlen(s_TempSig.sig);
|
||||
|
||||
for (size_t i=0; i<length; i++)
|
||||
{
|
||||
if (real_bytes >= sizeof(real_sig))
|
||||
{
|
||||
break;
|
||||
}
|
||||
real_sig[real_bytes++] = s_TempSig.sig[i];
|
||||
if (s_TempSig.sig[i] == '\\'
|
||||
&& s_TempSig.sig[i+1] == 'x')
|
||||
{
|
||||
if (i + 3 >= length)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Get the hex part */
|
||||
char s_byte[3];
|
||||
int r_byte;
|
||||
s_byte[0] = s_TempSig.sig[i+2];
|
||||
s_byte[1] = s_TempSig.sig[i+3];
|
||||
s_byte[2] = '\0';
|
||||
/* Read it as an integer */
|
||||
sscanf(s_byte, "%x", &r_byte);
|
||||
/* Save the value */
|
||||
real_sig[real_bytes-1] = r_byte;
|
||||
/* Adjust index */
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), s_TempSig.sig);
|
||||
|
||||
if (real_bytes >= 1)
|
||||
{
|
||||
final_addr = g_MemUtils.FindPattern(addrInBase, real_sig, real_bytes);
|
||||
final_addr = g_MemUtils.FindPattern(addrInBase, (char*)real_sig, real_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,37 +557,244 @@ skip_find:
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
bool CGameConfig::Reparse(char *error, size_t maxlength)
|
||||
{
|
||||
SMCError err;
|
||||
SMCStates state = {0, 0};
|
||||
#define MSTATE_NONE 0
|
||||
#define MSTATE_MAIN 1
|
||||
#define MSTATE_FILE 2
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s.txt", m_pFile);
|
||||
/* Backwards compatibility */
|
||||
if (!g_LibSys.PathExists(path))
|
||||
class MasterReader : public ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
virtual void ReadSMC_ParseStart()
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile);
|
||||
state = MSTATE_NONE;
|
||||
ignoreLevel = 0;
|
||||
}
|
||||
|
||||
/* Initialize parse states */
|
||||
m_IgnoreLevel = 0;
|
||||
bShouldBeReadingDefault = true;
|
||||
m_ParseState = PSTATE_NONE;
|
||||
virtual SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
if (ignoreLevel)
|
||||
{
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (state == MSTATE_NONE)
|
||||
{
|
||||
if (strcmp(name, "Game Master") == 0)
|
||||
{
|
||||
state = MSTATE_MAIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
ignoreLevel++;
|
||||
}
|
||||
}
|
||||
else if (state == MSTATE_MAIN)
|
||||
{
|
||||
strncopy(cur_file, name, sizeof(cur_file));
|
||||
had_engine = false;
|
||||
matched_engine = false;
|
||||
had_game = false;
|
||||
matched_game = false;
|
||||
state = MSTATE_FILE;
|
||||
}
|
||||
else if (state == MSTATE_FILE)
|
||||
{
|
||||
ignoreLevel++;
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
virtual SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||
{
|
||||
if (ignoreLevel || state != MSTATE_FILE)
|
||||
{
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (strcmp(key, "engine") == 0)
|
||||
{
|
||||
had_engine = true;
|
||||
if (DoesEngineMatch(value))
|
||||
{
|
||||
matched_engine = true;
|
||||
}
|
||||
}
|
||||
else if (strcmp(key, "game") == 0)
|
||||
{
|
||||
had_game = true;
|
||||
if (DoesGameMatch(value))
|
||||
{
|
||||
matched_game = true;
|
||||
}
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
virtual SMCResult ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
if (ignoreLevel)
|
||||
{
|
||||
ignoreLevel--;
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (state == MSTATE_FILE)
|
||||
{
|
||||
/* The four success conditions:
|
||||
* 1. Needed nothing.
|
||||
* 2. Needed game only.
|
||||
* 3. Needed engine only.
|
||||
* 4. Needed both engine and game.
|
||||
* Final result is minimized via k-map.
|
||||
*/
|
||||
#if 0
|
||||
if ((!had_engine && !had_game) ||
|
||||
(!had_engine && (had_game && matched_game)) ||
|
||||
(!had_game && (had_engine && matched_engine)) ||
|
||||
((had_game && had_engine) && (matched_game && matched_engine)))
|
||||
#endif
|
||||
if ((!had_engine && !had_game) ||
|
||||
(!had_engine && matched_game) ||
|
||||
(!had_game && matched_engine) ||
|
||||
(matched_engine && matched_game))
|
||||
{
|
||||
fileList->push_back(cur_file);
|
||||
}
|
||||
state = MSTATE_MAIN;
|
||||
}
|
||||
else if (state == MSTATE_MAIN)
|
||||
{
|
||||
state = MSTATE_NONE;
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
public:
|
||||
List<String> *fileList;
|
||||
unsigned int state;
|
||||
unsigned int ignoreLevel;
|
||||
char cur_file[PLATFORM_MAX_PATH];
|
||||
bool had_engine;
|
||||
bool matched_engine;
|
||||
bool had_game;
|
||||
bool matched_game;
|
||||
};
|
||||
|
||||
static MasterReader master_reader;
|
||||
|
||||
bool CGameConfig::Reparse(char *error, size_t maxlength)
|
||||
{
|
||||
/* Reset cached data */
|
||||
m_pStrings->Reset();
|
||||
sm_trie_clear(m_pOffsets);
|
||||
sm_trie_clear(m_pProps);
|
||||
sm_trie_clear(m_pKeys);
|
||||
|
||||
if ((err=textparsers->ParseSMCFile(path, this, &state, error, maxlength))
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
/* See if we can use the extended gamedata format. */
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/master.games.txt", m_File);
|
||||
if (!g_LibSys.PathExists(path))
|
||||
{
|
||||
/* Nope, use the old mechanism. */
|
||||
UTIL_Format(path, sizeof(path), "%s.txt", m_File);
|
||||
return EnterFile(path, error, maxlength);
|
||||
}
|
||||
|
||||
/* Otherwise, it's time to parse the master. */
|
||||
SMCError err;
|
||||
SMCStates state = {0, 0};
|
||||
List<String> fileList;
|
||||
master_reader.fileList = &fileList;
|
||||
|
||||
err = textparsers->ParseSMCFile(path, &master_reader, &state, error, maxlength);
|
||||
if (err != SMCError_Okay)
|
||||
{
|
||||
const char *msg = textparsers->GetSMCErrorString(err);
|
||||
|
||||
g_Logger.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
|
||||
g_Logger.LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
err,
|
||||
state.line,
|
||||
state.col,
|
||||
msg ? msg : "Unknown error");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Go through each file we found and parse it. */
|
||||
List<String>::iterator iter;
|
||||
for (iter = fileList.begin(); iter != fileList.end(); iter++)
|
||||
{
|
||||
UTIL_Format(path, sizeof(path), "%s/%s", m_File, (*iter).c_str());
|
||||
if (!EnterFile(path, error, maxlength))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the contents of the 'custom' directory */
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/custom", m_File);
|
||||
IDirectory *customDir = g_LibSys.OpenDirectory(path);
|
||||
|
||||
if (!customDir)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
while (customDir->MoreFiles())
|
||||
{
|
||||
if (!customDir->IsEntryFile())
|
||||
{
|
||||
customDir->NextEntry();
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *curFile = customDir->GetEntryName();
|
||||
|
||||
/* Only allow .txt files */
|
||||
int len = strlen(curFile);
|
||||
if (len > 4 && strcmp(&curFile[len-4], ".txt") != 0)
|
||||
{
|
||||
customDir->NextEntry();
|
||||
continue;
|
||||
}
|
||||
|
||||
UTIL_Format(path, sizeof(path), "%s/custom/%s", m_File, curFile);
|
||||
if (!EnterFile(path, error, maxlength))
|
||||
{
|
||||
g_LibSys.CloseDirectory(customDir);
|
||||
return false;
|
||||
}
|
||||
|
||||
customDir->NextEntry();
|
||||
}
|
||||
|
||||
g_LibSys.CloseDirectory(customDir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
SMCError err;
|
||||
SMCStates state = {0, 0};
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM, m_CurFile, sizeof(m_CurFile), "gamedata/%s", file);
|
||||
|
||||
/* Initialize parse states */
|
||||
m_IgnoreLevel = 0;
|
||||
bShouldBeReadingDefault = true;
|
||||
m_ParseState = PSTATE_NONE;
|
||||
|
||||
if ((err=textparsers->ParseSMCFile(m_CurFile, this, &state, error, maxlength))
|
||||
!= SMCError_Okay)
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
msg = textparsers->GetSMCErrorString(err);
|
||||
|
||||
g_Logger.LogError("[SM] Error parsing gameconfig file \"%s\":", path);
|
||||
g_Logger.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
|
||||
g_Logger.LogError("[SM] Error %d on line %d, col %d: %s",
|
||||
err,
|
||||
state.line,
|
||||
@@ -680,12 +917,14 @@ void GameConfigManager::OnSourceModAllShutdown()
|
||||
|
||||
bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength)
|
||||
{
|
||||
#if 0
|
||||
/* A crash was detected during last load - We block the gamedata loading so it hopefully won't happen again */
|
||||
if (g_blockGameDataLoad)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "GameData loaded blocked due to detected crash");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
CGameConfig *pConfig;
|
||||
|
||||
@@ -721,7 +960,7 @@ void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg)
|
||||
|
||||
if (pConfig->DecRefCount() == 0)
|
||||
{
|
||||
sm_trie_delete(m_pLookup, pConfig->m_pFile);
|
||||
sm_trie_delete(m_pLookup, pConfig->m_File);
|
||||
delete pConfig;
|
||||
}
|
||||
}
|
||||
@@ -742,12 +981,12 @@ IGameConfig *GameConfigManager::ReadHandle(Handle_t hndl, IdentityToken_t *ident
|
||||
return conf;
|
||||
}
|
||||
|
||||
void GameConfigManager::AddUserConfigHook( const char *sectionname, ITextListener_SMC *listener )
|
||||
void GameConfigManager::AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener)
|
||||
{
|
||||
m_customHandlers.insert(sectionname, listener);
|
||||
}
|
||||
|
||||
void GameConfigManager::RemoveUserConfigHook( const char *sectionname, ITextListener_SMC *listener )
|
||||
void GameConfigManager::RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener)
|
||||
{
|
||||
ITextListener_SMC **pListener = m_customHandlers.retrieve(sectionname);
|
||||
|
||||
@@ -765,3 +1004,11 @@ void GameConfigManager::RemoveUserConfigHook( const char *sectionname, ITextList
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void GameConfigManager::AcquireLock()
|
||||
{
|
||||
}
|
||||
|
||||
void GameConfigManager::ReleaseLock()
|
||||
{
|
||||
}
|
||||
|
||||
+9
-1
@@ -55,6 +55,7 @@ public:
|
||||
~CGameConfig();
|
||||
public:
|
||||
bool Reparse(char *error, size_t maxlength);
|
||||
bool EnterFile(const char *file, char *error, size_t maxlength);
|
||||
public: //ITextListener_SMC
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
@@ -69,7 +70,8 @@ public:
|
||||
unsigned int DecRefCount();
|
||||
private:
|
||||
BaseStringTable *m_pStrings;
|
||||
char *m_pFile;
|
||||
char m_File[PLATFORM_MAX_PATH];
|
||||
char m_CurFile[PLATFORM_MAX_PATH];
|
||||
Trie *m_pOffsets;
|
||||
Trie *m_pProps;
|
||||
Trie *m_pKeys;
|
||||
@@ -83,6 +85,10 @@ private:
|
||||
char m_offset[64];
|
||||
char m_Game[256];
|
||||
bool bShouldBeReadingDefault;
|
||||
bool had_game;
|
||||
bool matched_game;
|
||||
bool had_engine;
|
||||
bool matched_engine;
|
||||
|
||||
/* Custom Sections */
|
||||
unsigned int m_CustomLevel;
|
||||
@@ -104,6 +110,8 @@ public: //IGameConfigManager
|
||||
HandleError *err);
|
||||
void AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
|
||||
void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
|
||||
void AcquireLock();
|
||||
void ReleaseLock();
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllInitialized();
|
||||
|
||||
@@ -1,909 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "GameDataFetcher.h"
|
||||
#include "bitbuf.h"
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
#define closesocket close
|
||||
#define WSAGetLastError() errno
|
||||
#endif
|
||||
|
||||
#include "sh_vector.h"
|
||||
#include "sh_string.h"
|
||||
#include "sm_version.h"
|
||||
|
||||
#ifdef ORANGEBOX_BUILD
|
||||
#include "convar_sm_ob.h"
|
||||
#else
|
||||
#include "convar_sm.h"
|
||||
#endif
|
||||
|
||||
#include "sourcemm_api.h"
|
||||
#include "time.h"
|
||||
#include "TimerSys.h"
|
||||
#include "compat_wrappers.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "md5.h"
|
||||
#include "frame_hooks.h"
|
||||
|
||||
#define QUERY_MAX_LENGTH 1024
|
||||
|
||||
static BuildMD5ableBuffer g_MD5Builder;
|
||||
static FetcherThread g_FetchThread;
|
||||
|
||||
static FILE *logfile = NULL;
|
||||
|
||||
bool g_disableGameDataUpdate = false;
|
||||
|
||||
/**
|
||||
* Note on this. If we issue a reload and changelevel, my srcds.exe will emit
|
||||
* Assertion Failed: !m_bServiceStarted
|
||||
* on quit. This seems like a non-issue, because before we just terminated the
|
||||
* server anyway. If anyone notices and files a bug, we can look into it further.
|
||||
*/
|
||||
bool g_restartAfterUpdate = false;
|
||||
|
||||
static bool was_level_started = false;
|
||||
static int g_serverPort = 6500;
|
||||
static char g_serverAddress[100] = "smupdate.alliedmods.net";
|
||||
|
||||
static void _ForceRestart(void *data)
|
||||
{
|
||||
char cmd[300];
|
||||
g_Logger.LogMessage("Automatically restarting SourceMod after a successful gamedata update.");
|
||||
UTIL_Format(cmd, sizeof(cmd), "meta unload %d\n", g_PLID);
|
||||
engine->ServerCommand(cmd);
|
||||
UTIL_Format(cmd, sizeof(cmd), "changelevel \"%s\"\n", STRING(gpGlobals->mapname));
|
||||
engine->ServerCommand(cmd);
|
||||
UTIL_Format(cmd, sizeof(cmd), "echo SourceMod restarted after gamedata update.\n");
|
||||
engine->ServerCommand(cmd);
|
||||
}
|
||||
|
||||
static void ForceRestart()
|
||||
{
|
||||
FrameAction action;
|
||||
|
||||
action.action = _ForceRestart;
|
||||
action.data = NULL;
|
||||
AddFrameAction(action);
|
||||
}
|
||||
|
||||
void FetcherThread::RunThread(IThreadHandle *pHandle)
|
||||
{
|
||||
char lock_path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp");
|
||||
g_LibSys.CreateFolder(lock_path);
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp/gamedata.lock");
|
||||
|
||||
char log_path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, log_path, sizeof(log_path), "logs/gamedata");
|
||||
|
||||
g_LibSys.CreateFolder(log_path);
|
||||
|
||||
time_t t;
|
||||
GetAdjustedTime(&t);
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM,
|
||||
log_path,
|
||||
sizeof(log_path),
|
||||
"logs/gamedata/L%04d%02d%02d.log",
|
||||
curtime->tm_year + 1900,
|
||||
curtime->tm_mon + 1,
|
||||
curtime->tm_mday);
|
||||
|
||||
logfile = fopen(log_path, "at");
|
||||
|
||||
if (!logfile)
|
||||
{
|
||||
/* :( */
|
||||
return;
|
||||
}
|
||||
|
||||
//Create a blank lock file
|
||||
FILE *fp = fopen(lock_path, "w");
|
||||
if (fp)
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
char query[QUERY_MAX_LENGTH];
|
||||
|
||||
/* Check for updated gamedata files */
|
||||
int len = BuildGameDataQuery(query, QUERY_MAX_LENGTH);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
g_Logger.LogToFileOnly(logfile, "Could not build gamedata query!");
|
||||
fclose(logfile);
|
||||
unlink(lock_path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We check this late so we have the MD5 sums available. This may change in the future. */
|
||||
if (g_disableGameDataUpdate)
|
||||
{
|
||||
g_Logger.LogToFileOnly(logfile, "Skipping gamedata fetcher (DisableAutoUpdate set)");
|
||||
fclose(logfile);
|
||||
unlink(lock_path);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a new socket for this connection */
|
||||
int socketDescriptor = ConnectSocket();
|
||||
|
||||
if (socketDescriptor == INVALID_SOCKET)
|
||||
{
|
||||
fclose(logfile);
|
||||
unlink(lock_path);
|
||||
return;
|
||||
}
|
||||
|
||||
int sent = SendData(socketDescriptor, query, len);
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Sent gamedata query");
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
if (sent == 0)
|
||||
{
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Failed to send gamedata query data to remote host");
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
closesocket(socketDescriptor);
|
||||
fclose(logfile);
|
||||
unlink(lock_path);
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessGameDataQuery(socketDescriptor);
|
||||
|
||||
/* And we're done! */
|
||||
closesocket(socketDescriptor);
|
||||
fclose(logfile);
|
||||
unlink(lock_path);
|
||||
}
|
||||
|
||||
void FetcherThread::OnTerminate(IThreadHandle *pHandle, bool cancel)
|
||||
{
|
||||
g_blockGameDataLoad = false;
|
||||
|
||||
if (cancel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (wasSuccess)
|
||||
{
|
||||
HandleUpdateStatus(updateStatus, build);
|
||||
|
||||
if (needsRestart)
|
||||
{
|
||||
if (g_restartAfterUpdate)
|
||||
{
|
||||
if (was_level_started)
|
||||
{
|
||||
ForceRestart();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogMessage("Your gamedata files have been updated, please restart your server.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!g_disableGameDataUpdate)
|
||||
{
|
||||
g_Logger.LogError("An error occurred in the gamedata fetcher, see your gamedata log files for more information.");
|
||||
}
|
||||
}
|
||||
|
||||
int FetcherThread::BuildGameDataQuery(char *buffer, int maxlen)
|
||||
{
|
||||
char gamedata_path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, gamedata_path, sizeof(gamedata_path), "gamedata");
|
||||
|
||||
IDirectory *dir = g_LibSys.OpenDirectory(gamedata_path);
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bf_write Writer = bf_write("GameDataQuery", buffer, maxlen);
|
||||
|
||||
Writer.WriteByte('A'); //Generic Header char
|
||||
Writer.WriteByte('G'); //G for gamedata query, or green, like my hat.
|
||||
|
||||
short build[4] = { SVN_FILE_VERSION };
|
||||
|
||||
Writer.WriteBytes(&build[0], 8);
|
||||
|
||||
Writer.WriteByte(0); // Initialize the file counter - Index 10
|
||||
|
||||
while (dir->MoreFiles())
|
||||
{
|
||||
if (dir->IsEntryFile())
|
||||
{
|
||||
const char *name = dir->GetEntryName();
|
||||
size_t len = strlen(name);
|
||||
if (len >= 4 && strcmp(&name[len-4], ".txt") == 0)
|
||||
{
|
||||
MD5 md5;
|
||||
SMCError err;
|
||||
SMCStates states;
|
||||
unsigned char raw[16];
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
|
||||
g_LibSys.PathFormat(file, sizeof(file), "%s/%s", gamedata_path, name);
|
||||
|
||||
g_MD5Builder.checksum = &md5;
|
||||
if ((err = g_TextParser.ParseFile_SMC(file, &g_MD5Builder, &states)) == SMCError_Okay)
|
||||
{
|
||||
md5.raw_digest(raw);
|
||||
(uint8_t)buffer[10]++; //Increment the file counter
|
||||
Writer.WriteBytes(raw, 16);
|
||||
|
||||
FileData *data = new FileData();
|
||||
data->filename = new SourceHook::String(file);
|
||||
md5.hex_digest(data->checksum);
|
||||
filenames.push_back(data);
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Parsed file: %s as %s", file, data->checksum);
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
IF_DEBUG_SPEW
|
||||
const char *error = g_TextParser.GetSMCErrorString(err);
|
||||
g_Logger.LogToFileOnly(logfile, "Parsing of file %s failed: %s", file, error);
|
||||
ENDIF_DEBUG_SPEW
|
||||
}
|
||||
}
|
||||
}
|
||||
dir->NextEntry();
|
||||
}
|
||||
|
||||
return Writer.GetNumBytesWritten();
|
||||
}
|
||||
|
||||
int FetcherThread::ConnectSocket()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
WSADATA wsaData;
|
||||
WSAStartup(0x0101, &wsaData);
|
||||
#endif
|
||||
|
||||
struct protoent *ptrp;
|
||||
|
||||
if ((ptrp = getprotobyname("tcp")) == NULL)
|
||||
{
|
||||
g_Logger.LogToFileOnly(logfile, "Error: Failed to find TCP protocol");
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
int socketDescriptor = socket(AF_INET, SOCK_STREAM, ptrp->p_proto);
|
||||
|
||||
if (socketDescriptor == INVALID_SOCKET)
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
|
||||
g_Logger.LogToFileOnly(logfile, "Error: Failed to create socket: %s", error);
|
||||
closesocket(socketDescriptor);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
struct hostent *he;
|
||||
struct sockaddr_in local_addr;
|
||||
|
||||
local_addr.sin_family = AF_INET;
|
||||
local_addr.sin_port = htons((u_short)g_serverPort);
|
||||
|
||||
he = gethostbyname(g_serverAddress);
|
||||
|
||||
if (!he)
|
||||
{
|
||||
if ((local_addr.sin_addr.s_addr = inet_addr(g_serverAddress)) == INADDR_NONE)
|
||||
{
|
||||
g_Logger.LogToFileOnly(logfile, "Couldn't locate address: %s", g_serverAddress);
|
||||
closesocket(socketDescriptor);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&local_addr.sin_addr, (struct in_addr *)he->h_addr, he->h_length);
|
||||
}
|
||||
|
||||
if (connect(socketDescriptor, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0)
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
|
||||
g_Logger.LogToFileOnly(logfile, "Couldn't connect to %s: %s", g_serverAddress, error);
|
||||
closesocket(socketDescriptor);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return socketDescriptor;
|
||||
}
|
||||
|
||||
void FetcherThread::ProcessGameDataQuery(int socketDescriptor)
|
||||
{
|
||||
char buffer[50];
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Waiting for reply!");
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
//Read in the header bytes
|
||||
int returnLen = RecvData(socketDescriptor, buffer, 12);
|
||||
|
||||
|
||||
if (returnLen == 0)
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
|
||||
g_Logger.LogToFileOnly(logfile, "Did not receive reply: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Received Header!");
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
bf_read Reader = bf_read("GameDataQuery", buffer, 12);
|
||||
|
||||
if (Reader.ReadByte() != 'A' || Reader.ReadByte() != 'G')
|
||||
{
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Unknown Query Response");
|
||||
ENDIF_DEBUG_SPEW
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatus = (UpdateStatus)Reader.ReadByte();
|
||||
|
||||
build[0] = Reader.ReadShort();
|
||||
build[1] = Reader.ReadShort();
|
||||
build[2] = Reader.ReadShort();
|
||||
build[3] = Reader.ReadShort();
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile,
|
||||
"Update Status: %i - Latest %i.%i.%i.%i",
|
||||
updateStatus,
|
||||
build[0],
|
||||
build[1],
|
||||
build[2],
|
||||
build[3]);
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
int changedFiles = Reader.ReadByte();
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Files to download: %i", changedFiles);
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
for (int i=0; i<changedFiles; i++)
|
||||
{
|
||||
//Read in the file index and byte count
|
||||
returnLen = RecvData(socketDescriptor, buffer, 5);
|
||||
|
||||
if (returnLen == 0)
|
||||
{
|
||||
/* Timeout or fail? */
|
||||
return;
|
||||
}
|
||||
|
||||
Reader.StartReading(buffer, 5);
|
||||
|
||||
int index = Reader.ReadByte();
|
||||
int tempLen = Reader.ReadUBitLong(32);
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "File index %i and length %i", index, tempLen);
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
void *memPtr;
|
||||
memtable->CreateMem(tempLen+1, &memPtr);
|
||||
|
||||
//Read the contents of our file into the memtable
|
||||
returnLen = RecvData(socketDescriptor, (char *)memPtr, tempLen);
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Received %i bytes", returnLen);
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
if (returnLen == 0)
|
||||
{
|
||||
/* Timeout or fail? */
|
||||
return;
|
||||
}
|
||||
|
||||
((unsigned char *)memPtr)[tempLen] = '\0';
|
||||
|
||||
FileData *data = filenames.at(index);
|
||||
const char *filename;
|
||||
if (data != NULL)
|
||||
{
|
||||
filename = data->filename->c_str();
|
||||
|
||||
FILE *fp = fopen(filename, "w");
|
||||
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "%s", (const char *)memPtr);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Logger.LogToFileOnly(logfile, "Failed to open file \"%s\" for writing", filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = "";
|
||||
}
|
||||
|
||||
memtable->Reset();
|
||||
|
||||
g_Logger.LogToFileOnly(logfile, "Updated file: %s", filename);
|
||||
}
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "File Downloads Completed!");
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
needsRestart = false;
|
||||
|
||||
if (changedFiles > 0)
|
||||
{
|
||||
needsRestart = true;
|
||||
}
|
||||
|
||||
//Read changed file count
|
||||
returnLen = RecvData(socketDescriptor, buffer, 1);
|
||||
|
||||
if (returnLen == 0)
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
|
||||
g_Logger.LogToFileOnly(logfile, "Did not receive count reply: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
Reader.StartReading(buffer, 1);
|
||||
|
||||
changedFiles = Reader.ReadByte();
|
||||
|
||||
if (changedFiles < 1)
|
||||
{
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "No unknown files. We're all done");
|
||||
ENDIF_DEBUG_SPEW
|
||||
return;
|
||||
}
|
||||
|
||||
char *changedFileIndexes = new char[changedFiles];
|
||||
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "%i files were unknown", changedFiles);
|
||||
ENDIF_DEBUG_SPEW
|
||||
|
||||
returnLen = RecvData(socketDescriptor, changedFileIndexes, changedFiles);
|
||||
|
||||
if (returnLen == 0)
|
||||
{
|
||||
char error[255];
|
||||
g_LibSys.GetPlatformErrorEx(WSAGetLastError(), error, sizeof(error));
|
||||
g_Logger.LogToFileOnly(logfile, "Did not receive list reply: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
Reader.StartReading(changedFileIndexes, changedFiles);
|
||||
|
||||
for (int i=0; i<changedFiles; i++)
|
||||
{
|
||||
int index = Reader.ReadByte();
|
||||
char fileName[30];
|
||||
|
||||
FileData *data = filenames.at(index);
|
||||
const char* pathname;
|
||||
if (data != NULL)
|
||||
{
|
||||
pathname = data->filename->c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
pathname = "";
|
||||
}
|
||||
|
||||
g_LibSys.GetFileFromPath(fileName, sizeof(fileName), pathname);
|
||||
IF_DEBUG_SPEW
|
||||
g_Logger.LogToFileOnly(logfile, "Unknown File %i : %s", index, fileName);
|
||||
ENDIF_DEBUG_SPEW
|
||||
}
|
||||
|
||||
delete [] changedFileIndexes;
|
||||
|
||||
wasSuccess = true;
|
||||
}
|
||||
|
||||
int FetcherThread::RecvData(int socketDescriptor, char *buffer, int len)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
/* Create a 10 Second Timeout */
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int bytesReceivedTotal = 0;
|
||||
|
||||
while (bytesReceivedTotal < len)
|
||||
{
|
||||
/* Add our socket to a socket set */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(socketDescriptor, &fds);
|
||||
|
||||
/* Wait max of 10 seconds for recv to become available */
|
||||
select(socketDescriptor+1, &fds, NULL, NULL, &tv);
|
||||
|
||||
int bytesReceived = 0;
|
||||
|
||||
/* Is there a limit on how much we can receive? Some site said 1024 bytes, which will be well short of a file */
|
||||
if (FD_ISSET(socketDescriptor, &fds))
|
||||
{
|
||||
bytesReceived = recv(socketDescriptor, buffer+bytesReceivedTotal, len-bytesReceivedTotal, 0);
|
||||
}
|
||||
|
||||
if (bytesReceived == 0 || bytesReceived == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesReceivedTotal += bytesReceived;
|
||||
}
|
||||
|
||||
return bytesReceivedTotal;
|
||||
}
|
||||
|
||||
int FetcherThread::SendData(int socketDescriptor, char *buffer, int len)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int sentBytesTotal = 0;
|
||||
|
||||
while (sentBytesTotal < len)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(socketDescriptor, &fds);
|
||||
|
||||
select(socketDescriptor+1, NULL, &fds, NULL, &tv);
|
||||
|
||||
int sentBytes = 0;
|
||||
|
||||
if (FD_ISSET(socketDescriptor, &fds))
|
||||
{
|
||||
sentBytes = send(socketDescriptor, buffer+sentBytesTotal, len-sentBytesTotal, 0);
|
||||
}
|
||||
|
||||
if (sentBytes == 0 || sentBytes == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sentBytesTotal += sentBytes;
|
||||
}
|
||||
|
||||
return sentBytesTotal;
|
||||
}
|
||||
|
||||
void FetcherThread::HandleUpdateStatus(UpdateStatus status, short version[4])
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case Update_Unknown:
|
||||
case Update_Current:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case Update_NewBuild:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case Update_MinorAvailable:
|
||||
{
|
||||
g_Logger.LogMessage("SourceMod Update: A new release of SourceMod is now available from sourcemod.net");
|
||||
g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case Update_MajorAvailable:
|
||||
{
|
||||
g_Logger.LogMessage("SourceMod Update: An major release of SourceMod is now available from sourcemod.net");
|
||||
g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case Update_CriticalAvailable:
|
||||
{
|
||||
g_Logger.LogError("SourceMod Update: A critical SourceMod release is available from sourcemod.net. It is strongly recommended that you update!");
|
||||
g_Logger.LogMessage("Current Version: %i.%i.%i Available: %i.%i.%i", version[0], version[1], version[2], version[0], version[1], version[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool g_blockGameDataLoad = false;
|
||||
static IThreadHandle *fetch_thread_hndl;
|
||||
|
||||
class InitFetch : public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
void OnSourceModAllInitialized_Post()
|
||||
{
|
||||
char lock_path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_SM, lock_path, sizeof(lock_path), "data/temp/gamedata.lock");
|
||||
|
||||
if (g_LibSys.IsPathFile(lock_path) && g_LibSys.PathExists(lock_path))
|
||||
{
|
||||
g_Logger.LogError("sourcemod/data/temp/gamedata.lock file detected. This is most likely due to a crash during GameData updating - Blocking GameData loading");
|
||||
g_Logger.LogError("If this error persists delete the file manually");
|
||||
g_blockGameDataLoad = true;
|
||||
}
|
||||
|
||||
ThreadParams fetchThreadParams = ThreadParams();
|
||||
fetchThreadParams.prio = ThreadPrio_Low;
|
||||
fetch_thread_hndl = g_pThreader->MakeThread(&g_FetchThread, &fetchThreadParams);
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
fetch_thread_hndl->WaitForThread();
|
||||
fetch_thread_hndl->DestroyThis();
|
||||
}
|
||||
|
||||
void OnSourceModLevelActivated()
|
||||
{
|
||||
was_level_started = true;
|
||||
|
||||
if (g_restartAfterUpdate &&
|
||||
g_FetchThread.wasSuccess &&
|
||||
g_FetchThread.needsRestart)
|
||||
{
|
||||
ForceRestart();
|
||||
}
|
||||
}
|
||||
|
||||
void OnSourceModLevelEnd()
|
||||
{
|
||||
was_level_started = false;
|
||||
}
|
||||
|
||||
ConfigResult OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
char *error,
|
||||
size_t maxlength)
|
||||
{
|
||||
if (strcasecmp(key, "DisableAutoUpdate") == 0)
|
||||
{
|
||||
if (strcasecmp(value, "yes") == 0)
|
||||
{
|
||||
g_disableGameDataUpdate = true;
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
else if (strcasecmp(value, "no") == 0)
|
||||
{
|
||||
g_disableGameDataUpdate = false;
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
if (strcasecmp(key, "ForceRestartAfterUpdate") == 0)
|
||||
{
|
||||
if (strcasecmp(value, "yes") == 0)
|
||||
{
|
||||
g_restartAfterUpdate = true;
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
else if (strcasecmp(value, "no") == 0)
|
||||
{
|
||||
g_restartAfterUpdate = false;
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
if (strcasecmp(key, "AutoUpdateServer") == 0)
|
||||
{
|
||||
UTIL_Format(g_serverAddress, sizeof(g_serverAddress), "%s", value);
|
||||
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
|
||||
if (strcasecmp(key, "AutoUpdatePort") == 0)
|
||||
{
|
||||
int port = atoi(value);
|
||||
|
||||
if (!port)
|
||||
{
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
g_serverPort = port;
|
||||
|
||||
return ConfigResult_Accept;
|
||||
}
|
||||
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
} g_InitFetch;
|
||||
|
||||
BuildMD5ableBuffer::BuildMD5ableBuffer()
|
||||
{
|
||||
stringTable = new BaseStringTable(2048);
|
||||
}
|
||||
|
||||
BuildMD5ableBuffer::~BuildMD5ableBuffer()
|
||||
{
|
||||
delete stringTable;
|
||||
}
|
||||
|
||||
void BuildMD5ableBuffer::ReadSMC_ParseStart()
|
||||
{
|
||||
stringTable->Reset();
|
||||
}
|
||||
|
||||
SMCResult BuildMD5ableBuffer::ReadSMC_KeyValue(const SMCStates *states,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
stringTable->AddString(key);
|
||||
stringTable->AddString(value);
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult BuildMD5ableBuffer::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
stringTable->AddString(name);
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
void BuildMD5ableBuffer::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
if (halted || failed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void *data = stringTable->GetMemTable()->GetAddress(0);
|
||||
|
||||
if (data != NULL)
|
||||
{
|
||||
checksum->update((unsigned char *)data, stringTable->GetMemTable()->GetActualMemUsed());
|
||||
}
|
||||
|
||||
checksum->finalize();
|
||||
}
|
||||
|
||||
CON_COMMAND(sm_gamedata_md5, "Checks the MD5 sum for a given gamedata file")
|
||||
{
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
CCommand args;
|
||||
#endif
|
||||
|
||||
if (args.ArgC() < 2)
|
||||
{
|
||||
g_SMAPI->ConPrint("Usage: sm_gamedata_md5 <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *file = args.Arg(1);
|
||||
if (!file || file[0] == '\0')
|
||||
{
|
||||
g_SMAPI->ConPrint("Usage: sm_gamedata_md5 <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SourceHook::CVector<FileData *>::iterator iter = g_FetchThread.filenames.begin();
|
||||
|
||||
FileData *curData;
|
||||
|
||||
while (iter != g_FetchThread.filenames.end())
|
||||
{
|
||||
curData = (*iter);
|
||||
|
||||
char fileName[30];
|
||||
|
||||
g_LibSys.GetFileFromPath(fileName, sizeof(fileName), curData->filename->c_str());
|
||||
|
||||
if (strcmpi(fileName, file) == 0)
|
||||
{
|
||||
g_SMAPI->ConPrintf("MD5 Sum: %s\n", curData->checksum);
|
||||
return;
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
g_SMAPI->ConPrint("File not found!\n");
|
||||
}
|
||||
|
||||
FetcherThread::~FetcherThread()
|
||||
{
|
||||
SourceHook::CVector<FileData *>::iterator iter = filenames.begin();
|
||||
|
||||
FileData *curData;
|
||||
|
||||
while (iter != filenames.end())
|
||||
{
|
||||
curData = (*iter);
|
||||
delete curData->filename;
|
||||
delete curData;
|
||||
iter = filenames.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
FetcherThread::FetcherThread()
|
||||
{
|
||||
memtable = new BaseMemTable(4096);
|
||||
wasSuccess = false;
|
||||
needsRestart = false;
|
||||
}
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_GAMEDATAFETCHER_H_
|
||||
#define _INCLUDE_SOURCEMOD_GAMEDATAFETCHER_H_
|
||||
|
||||
#include "sourcemod.h"
|
||||
#include "TextParsers.h"
|
||||
#include "IThreader.h"
|
||||
#include "Logger.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "ThreadSupport.h"
|
||||
#include "sm_memtable.h"
|
||||
#include <sh_string.h>
|
||||
#include <sh_list.h>
|
||||
|
||||
enum UpdateStatus
|
||||
{
|
||||
Update_Unknown = 0, /* Version wasn't recognised or version querying is unsupported */
|
||||
Update_Current = 1, /* Server is running latest version */
|
||||
Update_NewBuild = 2, /* Server is on a svn release and a newer version is available */
|
||||
Update_MinorAvailable = 3, /* Server is on a release and a minor release has superceeded it */
|
||||
Update_MajorAvailable = 4, /* Server is on a release and a major release has superceeded it */
|
||||
Update_CriticalAvailable = 5, /* A critical update has been released (security fixes etc) */
|
||||
};
|
||||
|
||||
class MD5;
|
||||
|
||||
class BuildMD5ableBuffer : public ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
BuildMD5ableBuffer();
|
||||
~BuildMD5ableBuffer();
|
||||
void ReadSMC_ParseStart();
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
||||
public:
|
||||
MD5 *checksum;
|
||||
private:
|
||||
BaseStringTable *stringTable;
|
||||
};
|
||||
|
||||
struct FileData
|
||||
{
|
||||
SourceHook::String *filename;
|
||||
char checksum[33];
|
||||
};
|
||||
|
||||
class FetcherThread : public IThread
|
||||
{
|
||||
public:
|
||||
FetcherThread();
|
||||
~FetcherThread();
|
||||
public:
|
||||
void RunThread(IThreadHandle *pHandle);
|
||||
void OnTerminate(IThreadHandle *pHandle, bool cancel);
|
||||
private:
|
||||
int BuildGameDataQuery(char *buffer, int maxlen);
|
||||
void ProcessGameDataQuery(int SocketDescriptor);
|
||||
int RecvData(int socketDescriptor, char *buffer, int len);
|
||||
int SendData(int socketDescriptor, char *buffer, int len);
|
||||
int ConnectSocket();
|
||||
void HandleUpdateStatus(UpdateStatus status, short version[4]);
|
||||
public:
|
||||
SourceHook::CVector<FileData *> filenames;
|
||||
bool needsRestart;
|
||||
bool wasSuccess;
|
||||
private:
|
||||
UpdateStatus updateStatus;
|
||||
BaseMemTable *memtable;
|
||||
short build[4];
|
||||
};
|
||||
|
||||
extern bool g_blockGameDataLoad;
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_GAMEDATAFETCHER_H_
|
||||
|
||||
+374
-6
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -37,10 +37,14 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "GameConfigs.h"
|
||||
#include <compat_wrappers.h>
|
||||
#include <Logger.h>
|
||||
|
||||
CHalfLife2 g_HL2;
|
||||
ConVar *sv_lan = NULL;
|
||||
|
||||
static void *g_EntList = NULL;
|
||||
static int entInfoOffset = -1;
|
||||
|
||||
namespace SourceHook
|
||||
{
|
||||
template<>
|
||||
@@ -88,13 +92,20 @@ CHalfLife2::~CHalfLife2()
|
||||
m_Maps.clear();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
|
||||
#endif
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||
bool is_original_engine = false;
|
||||
#endif
|
||||
|
||||
void CHalfLife2::OnSourceModStartup(bool late)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
|
||||
/* The Ship currently is the only known game to use an older version of the engine */
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
||||
#else
|
||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
||||
@@ -106,27 +117,97 @@ void CHalfLife2::OnSourceModStartup(bool late)
|
||||
{
|
||||
g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CHalfLife2::OnSourceModAllInitialized()
|
||||
{
|
||||
m_MsgTextMsg = g_UserMsgs.GetMessageIndex("TextMsg");
|
||||
m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText");
|
||||
m_SayTextMsg = g_UserMsgs.GetMessageIndex("SayText");
|
||||
m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu");
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION
|
||||
void CHalfLife2::OnSourceModAllInitialized_Post()
|
||||
{
|
||||
char *addr = NULL;
|
||||
|
||||
/*
|
||||
* gEntList and/or g_pEntityList
|
||||
*
|
||||
* First try to lookup pointer directly for platforms with symbols.
|
||||
* If symbols aren't present (Windows or stripped Linux/Mac),
|
||||
* attempt find via LevelShutdown + offset
|
||||
*/
|
||||
if (g_pGameConf->GetMemSig("gEntList", (void **)&addr))
|
||||
{
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
if (!addr)
|
||||
{
|
||||
// Key exists so notify if lookup fails, but try other method.
|
||||
g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
g_EntList = reinterpret_cast<void *>(addr);
|
||||
#if !defined PLATFORM_WINDOWS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (!g_EntList)
|
||||
{
|
||||
if (!g_pGameConf->GetMemSig("LevelShutdown", (void **)&addr))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (LevelShutdown) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
g_Logger.LogError("Failed lookup of LevelShutdown - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
int offset;
|
||||
if (!g_pGameConf->GetOffset("gEntList", &offset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
||||
}
|
||||
|
||||
if (!g_EntList)
|
||||
{
|
||||
g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
|
||||
{
|
||||
g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||
bool CHalfLife2::IsOriginalEngine()
|
||||
{
|
||||
return is_original_engine;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
|
||||
{
|
||||
return engine->GetChangeAccessor( (const edict_t *)this );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool UTIL_FindInSendTable(SendTable *pTable,
|
||||
const char *name,
|
||||
@@ -296,6 +377,7 @@ typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset
|
||||
|
||||
void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
if (g_pSharedChangeInfo != NULL)
|
||||
{
|
||||
if (offset)
|
||||
@@ -308,6 +390,7 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
|
||||
}
|
||||
@@ -318,6 +401,31 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
bf_write *pBitBuf = NULL;
|
||||
cell_t players[] = {client};
|
||||
|
||||
if (dest == HUD_PRINTTALK)
|
||||
{
|
||||
const char *chat_saytext = g_pGameConf->GetKeyValue("ChatSayText");
|
||||
|
||||
/* Use SayText user message instead */
|
||||
if (chat_saytext != NULL && strcmp(chat_saytext, "yes") == 0)
|
||||
{
|
||||
char buffer[192];
|
||||
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pBitBuf->WriteByte(0);
|
||||
pBitBuf->WriteString(buffer);
|
||||
pBitBuf->WriteByte(1);
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
@@ -325,6 +433,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
|
||||
pBitBuf->WriteByte(dest);
|
||||
pBitBuf->WriteString(msg);
|
||||
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
@@ -351,6 +460,26 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||
{
|
||||
bf_write *pBitBuf = NULL;
|
||||
|
||||
if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *pre_byte = g_pGameConf->GetKeyValue("HintTextPreByte");
|
||||
if (pre_byte != NULL && strcmp(pre_byte, "yes") == 0)
|
||||
{
|
||||
pBitBuf->WriteByte(1);
|
||||
}
|
||||
pBitBuf->WriteString(msg);
|
||||
g_UserMsgs.EndMessage();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
|
||||
{
|
||||
bf_write *pBitBuf = NULL;
|
||||
@@ -437,7 +566,7 @@ bool CHalfLife2::IsLANServer()
|
||||
|
||||
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
|
||||
{
|
||||
#if defined METAMOD_PLAPI_VERSION
|
||||
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
|
||||
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
|
||||
#else
|
||||
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
|
||||
@@ -481,7 +610,7 @@ void CHalfLife2::PushCommandStack(const CCommand *cmd)
|
||||
CachedCommandInfo info;
|
||||
|
||||
info.args = cmd;
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||
strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd));
|
||||
#endif
|
||||
|
||||
@@ -505,7 +634,7 @@ void CHalfLife2::PopCommandStack()
|
||||
|
||||
const char *CHalfLife2::CurrentCommandName()
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
return m_CommandStack.front().args->Arg(0);
|
||||
#else
|
||||
return m_CommandStack.front().cmd;
|
||||
@@ -539,3 +668,242 @@ void CHalfLife2::ProcessDelayedKicks()
|
||||
player->Kick(info.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
edict_t *CHalfLife2::EdictOfIndex(int index)
|
||||
{
|
||||
return ::PEntityOfEntIndex(index);
|
||||
}
|
||||
|
||||
int CHalfLife2::IndexOfEdict(edict_t *pEnt)
|
||||
{
|
||||
return ::IndexOfEdict(pEnt);
|
||||
}
|
||||
|
||||
edict_t *CHalfLife2::GetHandleEntity(CBaseHandle &hndl)
|
||||
{
|
||||
if (!hndl.IsValid())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int index = hndl.GetEntryIndex();
|
||||
|
||||
edict_t *pStoredEdict;
|
||||
CBaseEntity *pStoredEntity;
|
||||
|
||||
if (!IndexToAThings(index, &pStoredEntity, &pStoredEdict))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pStoredEdict == NULL || pStoredEntity == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerEntity *pSE = pStoredEdict->GetIServerEntity();
|
||||
|
||||
if (pSE == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pSE->GetRefEHandle() != hndl)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pStoredEdict;
|
||||
}
|
||||
|
||||
void CHalfLife2::SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt)
|
||||
{
|
||||
IServerEntity *pEntOther = pEnt->GetIServerEntity();
|
||||
|
||||
if (pEntOther == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hndl.Set(pEntOther);
|
||||
}
|
||||
|
||||
const char *CHalfLife2::GetCurrentMap()
|
||||
{
|
||||
return STRING(gpGlobals->mapname);
|
||||
}
|
||||
|
||||
void CHalfLife2::ServerCommand(const char *buffer)
|
||||
{
|
||||
engine->ServerCommand(buffer);
|
||||
}
|
||||
|
||||
cell_t CHalfLife2::EntityToReference(CBaseEntity *pEntity)
|
||||
{
|
||||
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
|
||||
CBaseHandle hndl = pUnknown->GetRefEHandle();
|
||||
return (hndl.ToInt() | (1<<31));
|
||||
}
|
||||
|
||||
CBaseEntity *CHalfLife2::ReferenceToEntity(cell_t entRef)
|
||||
{
|
||||
CEntInfo *pInfo = NULL;
|
||||
|
||||
if (entRef & (1<<31))
|
||||
{
|
||||
/* Proper ent reference */
|
||||
int hndlValue = entRef & ~(1<<31);
|
||||
CBaseHandle hndl(hndlValue);
|
||||
|
||||
pInfo = LookupEntity(hndl.GetEntryIndex());
|
||||
if (pInfo->m_SerialNumber != hndl.GetSerialNumber())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Old style index only */
|
||||
pInfo = LookupEntity(entRef);
|
||||
}
|
||||
|
||||
if (!pInfo)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnk = static_cast<IServerUnknown *>(pInfo->m_pEntity);
|
||||
if (pUnk)
|
||||
{
|
||||
return pUnk->GetBaseEntity();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the CEntInfo pointer from g_EntList for a given entity index
|
||||
*/
|
||||
CEntInfo *CHalfLife2::LookupEntity(int entIndex)
|
||||
{
|
||||
if (!g_EntList || entInfoOffset == -1)
|
||||
{
|
||||
/* Attempt to use engine interface instead */
|
||||
static CEntInfo tempInfo;
|
||||
tempInfo.m_pNext = NULL;
|
||||
tempInfo.m_pPrev = NULL;
|
||||
|
||||
edict_t *pEdict = PEntityOfEntIndex(entIndex);
|
||||
|
||||
if (!pEdict)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnk = pEdict->GetUnknown();
|
||||
|
||||
if (!pUnk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tempInfo.m_pEntity = pUnk;
|
||||
tempInfo.m_SerialNumber = pUnk->GetRefEHandle().GetSerialNumber();
|
||||
|
||||
return &tempInfo;
|
||||
}
|
||||
|
||||
CEntInfo *pArray = (CEntInfo *)(((unsigned char *)g_EntList) + entInfoOffset);
|
||||
return &pArray[entIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
SERIAL_MASK = 0x7fff (15 bits)
|
||||
|
||||
#define MAX_EDICT_BITS 11
|
||||
#define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 1)
|
||||
m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS);
|
||||
|
||||
Top 5 bits of a handle are unused.
|
||||
Bit 31 - Our 'reference' flag indicator
|
||||
*/
|
||||
|
||||
cell_t CHalfLife2::IndexToReference(int entIndex)
|
||||
{
|
||||
CBaseEntity *pEnt = ReferenceToEntity(entIndex);
|
||||
if (!pEnt)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
return EntityToReference(pEnt);
|
||||
}
|
||||
|
||||
int CHalfLife2::ReferenceToIndex(cell_t entRef)
|
||||
{
|
||||
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
if (entRef & (1<<31))
|
||||
{
|
||||
/* Proper ent reference */
|
||||
int hndlValue = entRef & ~(1<<31);
|
||||
CBaseHandle hndl(hndlValue);
|
||||
|
||||
CEntInfo *pInfo = LookupEntity(hndl.GetEntryIndex());
|
||||
|
||||
if (pInfo->m_SerialNumber != hndl.GetSerialNumber())
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
return hndl.GetEntryIndex();
|
||||
}
|
||||
|
||||
return entRef;
|
||||
}
|
||||
|
||||
cell_t CHalfLife2::EntityToBCompatRef(CBaseEntity *pEntity)
|
||||
{
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
|
||||
CBaseHandle hndl = pUnknown->GetRefEHandle();
|
||||
|
||||
if (hndl.GetEntryIndex() >= MAX_EDICTS)
|
||||
{
|
||||
return (hndl.ToInt() | (1<<31));
|
||||
}
|
||||
else
|
||||
{
|
||||
return hndl.GetEntryIndex();
|
||||
}
|
||||
}
|
||||
|
||||
cell_t CHalfLife2::ReferenceToBCompatRef(cell_t entRef)
|
||||
{
|
||||
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
|
||||
{
|
||||
return INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
int hndlValue = entRef & ~(1<<31);
|
||||
CBaseHandle hndl(hndlValue);
|
||||
|
||||
if (hndl.GetEntryIndex() < MAX_EDICTS)
|
||||
{
|
||||
return hndl.GetEntryIndex();
|
||||
}
|
||||
|
||||
return entRef;
|
||||
}
|
||||
|
||||
void *CHalfLife2::GetGlobalEntityList()
|
||||
{
|
||||
return g_EntList;
|
||||
}
|
||||
|
||||
+31
-2
@@ -43,6 +43,7 @@
|
||||
#include <KeyValues.h>
|
||||
#include <server_class.h>
|
||||
#include <datamap.h>
|
||||
#include <ihandleentity.h>
|
||||
|
||||
class CCommand;
|
||||
|
||||
@@ -74,7 +75,7 @@ struct DelayedFakeCliCmd
|
||||
struct CachedCommandInfo
|
||||
{
|
||||
const CCommand *args;
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE <= SE_DARKMESSIAH
|
||||
char cmd[300];
|
||||
#endif
|
||||
};
|
||||
@@ -86,6 +87,15 @@ struct DelayedKickInfo
|
||||
char buffer[384];
|
||||
};
|
||||
|
||||
class CEntInfo
|
||||
{
|
||||
public:
|
||||
IHandleEntity *m_pEntity;
|
||||
int m_SerialNumber;
|
||||
CEntInfo *m_pPrev;
|
||||
CEntInfo *m_pNext;
|
||||
};
|
||||
|
||||
class CHalfLife2 :
|
||||
public SMGlobalClass,
|
||||
public IGameHelpers
|
||||
@@ -96,6 +106,7 @@ public:
|
||||
public:
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModAllInitialized_Post();
|
||||
/*void OnSourceModAllShutdown();*/
|
||||
public: //IGameHelpers
|
||||
SendProp *FindInSendTable(const char *classname, const char *offset);
|
||||
@@ -106,9 +117,24 @@ public: //IGameHelpers
|
||||
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
|
||||
bool TextMsg(int client, int dest, const char *msg);
|
||||
bool HintTextMsg(int client, const char *msg);
|
||||
bool HintTextMsg(cell_t *players, int count, const char *msg);
|
||||
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
||||
bool IsLANServer();
|
||||
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||
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();
|
||||
public:
|
||||
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
||||
void ProcessFakeCliCmdQueue();
|
||||
@@ -119,7 +145,7 @@ public:
|
||||
const char *CurrentCommandName();
|
||||
void AddDelayedKick(int client, int userid, const char *msg);
|
||||
void ProcessDelayedKicks();
|
||||
#if !defined METAMOD_PLAPI_VERSION
|
||||
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
|
||||
bool IsOriginalEngine();
|
||||
#endif
|
||||
private:
|
||||
@@ -130,6 +156,7 @@ private:
|
||||
THash<datamap_t *, DataMapTrie> m_Maps;
|
||||
int m_MsgTextMsg;
|
||||
int m_HinTextMsg;
|
||||
int m_SayTextMsg;
|
||||
int m_VGUIMenu;
|
||||
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||
@@ -139,4 +166,6 @@ private:
|
||||
|
||||
extern CHalfLife2 g_HL2;
|
||||
|
||||
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
||||
|
||||
+7
-3
@@ -950,6 +950,10 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
|
||||
return true;
|
||||
}
|
||||
|
||||
#define HANDLE_LOG_VERY_BAD(message, ...) \
|
||||
g_Logger.LogFatal(message, ##__VA_ARGS__); \
|
||||
g_Logger.LogError(message, ##__VA_ARGS__);
|
||||
|
||||
bool HandleSystem::TryAndFreeSomeHandles()
|
||||
{
|
||||
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
|
||||
@@ -995,9 +999,9 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
||||
return false;
|
||||
}
|
||||
|
||||
g_Logger.LogFatal("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
|
||||
g_Logger.LogFatal("[SM] Reloading plugin to free %d handles.", highest_handle_count);
|
||||
g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
||||
HANDLE_LOG_VERY_BAD("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
|
||||
HANDLE_LOG_VERY_BAD("[SM] Unloading plugin to free %d handles.", highest_handle_count);
|
||||
HANDLE_LOG_VERY_BAD("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
|
||||
|
||||
highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
|
||||
|
||||
|
||||
+10
-8
@@ -285,14 +285,16 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
|
||||
if (error && maxlength)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
(DWORD)code,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPSTR)error,
|
||||
maxlength,
|
||||
NULL);
|
||||
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
(DWORD)code,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPSTR)error,
|
||||
maxlength,
|
||||
NULL) == 0)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "error code %08x", code);
|
||||
}
|
||||
#elif defined PLATFORM_LINUX
|
||||
const char *ae = strerror_r(code, error, maxlength);
|
||||
if (ae != error)
|
||||
|
||||
+13
-8
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "Logger.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "TimerSys.h"
|
||||
#include "sm_version.h"
|
||||
#include <sourcemod_version.h>
|
||||
|
||||
Logger g_Logger;
|
||||
|
||||
@@ -149,7 +149,7 @@ void Logger::_NewMapFile()
|
||||
} else {
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SVN_FULL_VERSION);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SM_FULL_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
@@ -356,7 +356,7 @@ void Logger::LogMessage(const char *vafmt, ...)
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SVN_FULL_VERSION);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SM_FULL_VERSION);
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
@@ -378,6 +378,14 @@ print_error:
|
||||
}
|
||||
|
||||
void Logger::LogError(const char *vafmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogErrorEx(vafmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
@@ -408,10 +416,7 @@ void Logger::LogError(const char *vafmt, ...)
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, vafmt);
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
va_end(ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
void DisableLogging();
|
||||
void LogMessage(const char *msg, ...);
|
||||
void LogError(const char *msg, ...);
|
||||
void LogErrorEx(const char *msg, va_list ap);
|
||||
void LogFatal(const char *msg, ...);
|
||||
void LogToOpenFile(FILE *fp, const char *msg, ...);
|
||||
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
|
||||
|
||||
+68
-22
@@ -5,7 +5,10 @@ SMSDK = ..
|
||||
SRCDS_BASE = ~/srcds
|
||||
HL2SDK_ORIG = ../../hl2sdk
|
||||
HL2SDK_OB = ../../hl2sdk-ob
|
||||
MMSOURCE17 = ../../mmsource-1.7
|
||||
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve
|
||||
HL2SDK_L4D = ../../hl2sdk-l4d
|
||||
HL2SDK_L4D2 = ../../hl2sdk-l4d2
|
||||
MMSOURCE17 = ../../mmsource-central
|
||||
|
||||
#####################################
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
@@ -13,27 +16,27 @@ MMSOURCE17 = ../../mmsource-1.7
|
||||
|
||||
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
|
||||
Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
|
||||
MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
||||
MemoryUtils.cpp PlayerManager.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
|
||||
sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
|
||||
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
|
||||
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
|
||||
frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp PhraseCollection.cpp NextMap.cpp \
|
||||
NativeOwner.cpp GameDataFetcher.cpp md5.cpp
|
||||
frame_hooks.cpp concmd_cleaner.cpp PhraseCollection.cpp NextMap.cpp \
|
||||
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp
|
||||
OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
|
||||
smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
|
||||
smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp smn_maplists.cpp \
|
||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
|
||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp \
|
||||
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
|
||||
smn_filesystem.cpp smn_gameconfigs.cpp smn_halflife.cpp \
|
||||
smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp \
|
||||
smn_lang.cpp smn_player.cpp smn_string.cpp smn_timers.cpp \
|
||||
smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp \
|
||||
smn_hudtext.cpp smn_nextmap.cpp
|
||||
OBJECTS += ExtensionSys.cpp \
|
||||
ForwardSys.cpp \
|
||||
HandleSys.cpp \
|
||||
LibrarySys.cpp \
|
||||
PluginInfoDatabase.cpp \
|
||||
PluginSys.cpp \
|
||||
ShareSys.cpp
|
||||
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
|
||||
ShareSys.cpp \
|
||||
NativeInvoker.cpp
|
||||
|
||||
##############################################
|
||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||
@@ -48,8 +51,9 @@ CPP = gcc
|
||||
override ENGSET = false
|
||||
ifeq "$(ENGINE)" "original"
|
||||
HL2SDK = $(HL2SDK_ORIG)
|
||||
HL2PUB = $(HL2SDK_ORIG)/public
|
||||
HL2LIB = $(HL2SDK_ORIG)/linux_sdk
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/linux_sdk
|
||||
CFLAGS += -DSOURCE_ENGINE=1
|
||||
METAMOD = $(MMSOURCE17)/core-legacy
|
||||
INCLUDE += -I$(HL2SDK)/public/dlls
|
||||
SRCDS = $(SRCDS_BASE)
|
||||
@@ -58,18 +62,58 @@ ifeq "$(ENGINE)" "original"
|
||||
endif
|
||||
ifeq "$(ENGINE)" "orangebox"
|
||||
HL2SDK = $(HL2SDK_OB)
|
||||
HL2PUB = $(HL2SDK_OB)/public
|
||||
HL2LIB = $(HL2SDK_OB)/lib/linux
|
||||
CFLAGS += -DORANGEBOX_BUILD
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=3
|
||||
METAMOD = $(MMSOURCE17)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
SRCDS = $(SRCDS_BASE)/orangebox
|
||||
BINARY = sourcemod.2.ep2.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "orangeboxvalve"
|
||||
HL2SDK = $(HL2SDK_OB_VALVE)
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=4
|
||||
METAMOD = $(MMSOURCE17)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server -I$(HL2SDK)/common
|
||||
SRCDS = $(SRCDS_BASE)/orangebox
|
||||
BINARY = sourcemod.2.ep2v.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "left4dead"
|
||||
HL2SDK = $(HL2SDK_L4D)
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=5
|
||||
METAMOD = $(MMSOURCE17)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
SRCDS = $(SRCDS_BASE)/l4d
|
||||
BINARY = sourcemod.2.l4d.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
ifeq "$(ENGINE)" "left4dead2"
|
||||
HL2SDK = $(HL2SDK_L4D2)
|
||||
HL2PUB = $(HL2SDK)/public
|
||||
HL2LIB = $(HL2SDK)/lib/linux
|
||||
CFLAGS += -DSOURCE_ENGINE=6
|
||||
METAMOD = $(MMSOURCE17)/core
|
||||
INCLUDE += -I$(HL2SDK)/public/game/server
|
||||
SRCDS = $(SRCDS_BASE)/left4dead2
|
||||
BINARY = sourcemod.2.l4d2.so
|
||||
override ENGSET = true
|
||||
endif
|
||||
|
||||
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_ORANGEBOXVALVE=4 -DSE_LEFT4DEAD=5 -DSE_LEFT4DEAD2=6
|
||||
|
||||
ifeq "$(ENGINE)" "left4dead2"
|
||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a libvstdlib.so \
|
||||
libtier0.so -static-libgcc
|
||||
else
|
||||
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so \
|
||||
tier0_i486.so -lpthread -static-libgcc
|
||||
tier0_i486.so -static-libgcc
|
||||
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 \
|
||||
@@ -108,15 +152,19 @@ $(BIN_DIR)/%.o: %.c
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all: check
|
||||
mkdir -p $(BIN_DIR)/systems
|
||||
mkdir -p $(BIN_DIR)/thread
|
||||
mkdir -p $(BIN_DIR)
|
||||
ifeq "$(ENGINE)" "left4dead2"
|
||||
ln -sf $(SRCDS)/bin/libvstdlib.so libvstdlib.so;
|
||||
ln -sf $(SRCDS)/bin/libtier0.so libtier0.so;
|
||||
else
|
||||
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
|
||||
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
|
||||
endif
|
||||
$(MAKE) -f Makefile sourcemod
|
||||
|
||||
check:
|
||||
if [ "$(ENGSET)" = "false" ]; then \
|
||||
echo "You must supply ENGINE=orangebox or ENGINE=original"; \
|
||||
echo "You must supply ENGINE=left4dead or ENGINE=orangebox or ENGINE=original"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@@ -130,6 +178,4 @@ default: all
|
||||
|
||||
clean: check
|
||||
rm -rf $(BIN_DIR)/*.o
|
||||
rm -rf $(BIN_DIR)/systems/*.o
|
||||
rm -rf $(BIN_DIR)/thread/*.o
|
||||
rm -rf $(BIN_DIR)/$(BINARY)
|
||||
|
||||
+173
-9
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,15 +25,17 @@
|
||||
* 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>
|
||||
#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
|
||||
|
||||
MemoryUtils g_MemUtils;
|
||||
@@ -56,6 +58,17 @@ MemoryUtils::MemoryUtils()
|
||||
}
|
||||
#endif
|
||||
|
||||
MemoryUtils::~MemoryUtils()
|
||||
{
|
||||
#ifdef PLATFORM_LINUX
|
||||
for (size_t i = 0; i < m_SymTables.size(); i++)
|
||||
{
|
||||
delete m_SymTables[i];
|
||||
}
|
||||
m_SymTables.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryUtils::OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
@@ -98,6 +111,149 @@ void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t l
|
||||
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;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
{
|
||||
unsigned long baseAddr;
|
||||
@@ -201,14 +357,22 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
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)
|
||||
/* We only really care about the segment with executable code */
|
||||
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
|
||||
{
|
||||
lib.memorySize += hdr.p_memsz;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-5
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2000 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -25,8 +25,6 @@
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
|
||||
@@ -34,6 +32,12 @@
|
||||
|
||||
#include <IMemoryUtils.h>
|
||||
#include "sm_globals.h"
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <sh_vector.h>
|
||||
#include "sm_symtable.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
#endif
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
@@ -43,16 +47,34 @@ struct DynLibInfo
|
||||
size_t memorySize;
|
||||
};
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
typedef uint32_t Elf32_Addr;
|
||||
|
||||
struct LibSymbolTable
|
||||
{
|
||||
SymbolTable table;
|
||||
Elf32_Addr lib_base;
|
||||
uint32_t last_pos;
|
||||
};
|
||||
#endif
|
||||
|
||||
class MemoryUtils :
|
||||
public IMemoryUtils,
|
||||
public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
~MemoryUtils();
|
||||
public: // SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
public: // IMemoryUtils
|
||||
void *FindPattern(const void *libPtr, const char *pattern, size_t len);
|
||||
private:
|
||||
void *ResolveSymbol(void *handle, const char *symbol);
|
||||
public:
|
||||
bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
|
||||
#ifdef PLATFORM_LINUX
|
||||
private:
|
||||
CVector<LibSymbolTable *> m_SymTables;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern MemoryUtils g_MemUtils;
|
||||
|
||||
@@ -798,5 +798,11 @@ bool MenuManager::IsClientInVotePool(int client)
|
||||
|
||||
bool MenuManager::RedrawClientVoteMenu(int client)
|
||||
{
|
||||
return s_VoteHandler.RedrawToClient(client);
|
||||
return RedrawClientVoteMenu2(client, true);
|
||||
}
|
||||
|
||||
bool MenuManager::RedrawClientVoteMenu2(int client, bool revote)
|
||||
{
|
||||
return s_VoteHandler.RedrawToClient(client, revote);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
unsigned int GetRemainingVoteDelay();
|
||||
bool IsClientInVotePool(int client);
|
||||
bool RedrawClientVoteMenu(int client);
|
||||
bool RedrawClientVoteMenu2(int client, bool revote);
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
||||
|
||||
@@ -314,7 +314,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
||||
|
||||
if (sound != NULL)
|
||||
{
|
||||
edict_t *pEdict = engine->PEntityOfEntIndex(client);
|
||||
edict_t *pEdict = PEntityOfEntIndex(client);
|
||||
if (pEdict)
|
||||
{
|
||||
ICollideable *pCollideable = pEdict->GetCollideable();
|
||||
|
||||
@@ -88,7 +88,7 @@ void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
||||
return;
|
||||
}
|
||||
|
||||
int client = engine->IndexOfEdict(pEdict);
|
||||
int client = IndexOfEdict(pEdict);
|
||||
if (client < 1 || client > 256)
|
||||
{
|
||||
return;
|
||||
@@ -325,7 +325,7 @@ void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int ti
|
||||
m_pKv->SetInt("time", time ? time : 200);
|
||||
|
||||
SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
|
||||
engine->PEntityOfEntIndex(client),
|
||||
PEntityOfEntIndex(client),
|
||||
DIALOG_MENU,
|
||||
m_pKv,
|
||||
vsp_interface);
|
||||
|
||||
+217
-12
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -34,10 +34,56 @@
|
||||
#include "MenuVoting.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include <sourcemod.h>
|
||||
#include <Logger.h>
|
||||
#include <HalfLife2.h>
|
||||
#include <mathlib.h>
|
||||
#include <const.h>
|
||||
#include <Translator.h>
|
||||
|
||||
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);
|
||||
#else
|
||||
void OnVoteDelayChange(ConVar *cvar, const char *value);
|
||||
@@ -52,7 +98,7 @@ ConVar sm_vote_delay("sm_vote_delay",
|
||||
0.0,
|
||||
OnVoteDelayChange);
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
|
||||
#else
|
||||
void OnVoteDelayChange(ConVar *cvar, const char *value)
|
||||
@@ -117,7 +163,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
||||
* newly connected client is not allowed to vote.
|
||||
*/
|
||||
int item;
|
||||
if ((item = m_ClientVotes[client]) >= -1)
|
||||
if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
|
||||
{
|
||||
if (item >= 0)
|
||||
{
|
||||
@@ -125,7 +171,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
|
||||
assert(m_Votes[item] > 0);
|
||||
m_Votes[item]--;
|
||||
}
|
||||
m_ClientVotes[client] = -2;
|
||||
m_ClientVotes[client] = VOTE_NOT_VOTING;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,13 +235,13 @@ bool VoteMenuHandler::IsClientInVotePool(int client)
|
||||
return false;
|
||||
}
|
||||
|
||||
return (m_ClientVotes[client] > -2);
|
||||
return (m_ClientVotes[client] > VOTE_NOT_VOTING);
|
||||
}
|
||||
|
||||
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
||||
{
|
||||
if (!IsClientInVotePool(client)
|
||||
|| m_ClientVotes[client] == -1)
|
||||
|| m_ClientVotes[client] == VOTE_PENDING)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -205,7 +251,7 @@ bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VoteMenuHandler::RedrawToClient(int client)
|
||||
bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
|
||||
{
|
||||
unsigned int time_limit;
|
||||
|
||||
@@ -214,6 +260,20 @@ bool VoteMenuHandler::RedrawToClient(int client)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_ClientVotes[client] >= 0)
|
||||
{
|
||||
if ((m_VoteFlags & VOTEFLAG_NO_REVOTES) == VOTEFLAG_NO_REVOTES || !revotes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
assert((unsigned)m_ClientVotes[client] < m_Items);
|
||||
assert(m_Votes[m_ClientVotes[client]] > 0);
|
||||
m_Votes[m_ClientVotes[client]]--;
|
||||
m_ClientVotes[client] = VOTE_PENDING;
|
||||
m_Revoting[client] = true;
|
||||
m_NumVotes--;
|
||||
}
|
||||
|
||||
if (m_nMenuTime == MENU_TIME_FOREVER)
|
||||
{
|
||||
time_limit = m_nMenuTime;
|
||||
@@ -247,7 +307,8 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
|
||||
/* Mark all clients as not voting */
|
||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
||||
{
|
||||
m_ClientVotes[i] = -2;
|
||||
m_ClientVotes[i] = VOTE_NOT_VOTING;
|
||||
m_Revoting[i] = false;
|
||||
}
|
||||
|
||||
m_Items = menu->GetItemCount();
|
||||
@@ -291,6 +352,8 @@ void VoteMenuHandler::StartVoting()
|
||||
|
||||
m_pHandler->OnMenuVoteStart(m_pCurMenu);
|
||||
|
||||
m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
|
||||
/* By now we know how many clients were set.
|
||||
* If there are none, we should end IMMEDIATELY.
|
||||
*/
|
||||
@@ -298,6 +361,8 @@ void VoteMenuHandler::StartVoting()
|
||||
{
|
||||
EndVoting();
|
||||
}
|
||||
|
||||
m_TotalClients = m_Clients;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::DecrementPlayerCount()
|
||||
@@ -334,6 +399,11 @@ void VoteMenuHandler::EndVoting()
|
||||
g_next_vote = gpGlobals->curtime + fVoteDelay;
|
||||
}
|
||||
|
||||
if (m_displayTimer)
|
||||
{
|
||||
g_Timers.KillTimer(m_displayTimer);
|
||||
}
|
||||
|
||||
if (m_bCancelled)
|
||||
{
|
||||
/* If we were cancelled, don't bother tabulating anything.
|
||||
@@ -380,7 +450,7 @@ void VoteMenuHandler::EndVoting()
|
||||
/* Build the client list */
|
||||
for (int i=1; i<=gpGlobals->maxClients; i++)
|
||||
{
|
||||
if (m_ClientVotes[i] >= -1)
|
||||
if (m_ClientVotes[i] >= VOTE_PENDING)
|
||||
{
|
||||
client_vote[vote.num_clients].client = i;
|
||||
client_vote[vote.num_clients].item = m_ClientVotes[i];
|
||||
@@ -424,7 +494,7 @@ void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason
|
||||
|
||||
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
|
||||
{
|
||||
m_ClientVotes[client] = -1;
|
||||
m_ClientVotes[client] = VOTE_PENDING;
|
||||
m_pHandler->OnMenuDisplay(menu, client, display);
|
||||
}
|
||||
|
||||
@@ -446,6 +516,55 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
|
||||
m_ClientVotes[client] = item;
|
||||
m_Votes[item]++;
|
||||
m_NumVotes++;
|
||||
|
||||
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool())
|
||||
{
|
||||
static char buffer[1024];
|
||||
ItemDrawInfo dr;
|
||||
menu->GetItemInfo(item, &dr);
|
||||
|
||||
if (sm_vote_console.GetBool())
|
||||
{
|
||||
int target = SOURCEMOD_SERVER_LANGUAGE;
|
||||
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])
|
||||
{
|
||||
CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
|
||||
}
|
||||
else
|
||||
{
|
||||
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())
|
||||
{
|
||||
engine->ClientPrintf(pPlayer->GetEdict(), buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BuildVoteLeaders();
|
||||
DrawHintProgress();
|
||||
}
|
||||
|
||||
m_pHandler->OnMenuSelect(menu, client, item);
|
||||
@@ -468,6 +587,9 @@ void VoteMenuHandler::InternalReset()
|
||||
m_NumVotes = 0;
|
||||
m_bCancelled = false;
|
||||
m_pHandler = NULL;
|
||||
m_leaderList[0] = '\0';
|
||||
m_displayTimer = NULL;
|
||||
m_TotalClients = 0;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::CancelVoting()
|
||||
@@ -489,3 +611,86 @@ bool VoteMenuHandler::IsCancelling()
|
||||
{
|
||||
return m_bCancelled;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::DrawHintProgress()
|
||||
{
|
||||
if (!sm_vote_hintbox.GetBool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static char buffer[1024];
|
||||
|
||||
float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
|
||||
if (timeRemaining < 0)
|
||||
{
|
||||
timeRemaining = 0.0;
|
||||
}
|
||||
|
||||
int iTimeRemaining = RoundFloatToInt(timeRemaining);
|
||||
|
||||
int maxclients = g_Players.GetMaxClients();
|
||||
for (int i=1; i<=maxclients; i++)
|
||||
{
|
||||
if (g_Players.GetPlayerByIndex(i)->IsInGame())
|
||||
{
|
||||
CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count", &i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
|
||||
g_HL2.HintTextMsg(i, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoteMenuHandler::BuildVoteLeaders()
|
||||
{
|
||||
if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menu_vote_result_t vote;
|
||||
menu_vote_result_t::menu_item_vote_t item_vote[256];
|
||||
|
||||
memset(&vote, 0, sizeof(vote));
|
||||
|
||||
/* Build the item list */
|
||||
for (unsigned int i=0; i<m_Items; i++)
|
||||
{
|
||||
if (m_Votes[i] > 0)
|
||||
{
|
||||
item_vote[vote.num_items].count = m_Votes[i];
|
||||
item_vote[vote.num_items].item = i;
|
||||
vote.num_votes += m_Votes[i];
|
||||
vote.num_items++;
|
||||
}
|
||||
}
|
||||
vote.item_list = item_vote;
|
||||
assert(vote.num_votes);
|
||||
|
||||
/* Sort the item list descending */
|
||||
qsort(item_vote,
|
||||
vote.num_items,
|
||||
sizeof(menu_vote_result_t::menu_item_vote_t),
|
||||
SortVoteItems);
|
||||
|
||||
/* Take the top 3 (if applicable) and draw them */
|
||||
int len = 0;
|
||||
for (unsigned int i=0; i<vote.num_items && i<3; i++)
|
||||
{
|
||||
int curItem = vote.item_list[i].item;
|
||||
ItemDrawInfo dr;
|
||||
m_pCurMenu->GetItemInfo(curItem, &dr);
|
||||
len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
|
||||
{
|
||||
DrawHintProgress();
|
||||
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
|
||||
{
|
||||
m_displayTimer = NULL;
|
||||
}
|
||||
|
||||
+14
-2
@@ -36,6 +36,7 @@
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <sh_vector.h>
|
||||
#include "sm_globals.h"
|
||||
#include <TimerSys.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
@@ -43,7 +44,8 @@ using namespace SourceMod;
|
||||
class VoteMenuHandler :
|
||||
public IMenuHandler,
|
||||
public SMGlobalClass,
|
||||
public IClientListener
|
||||
public IClientListener,
|
||||
public ITimedEvent
|
||||
{
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
@@ -61,6 +63,9 @@ public: //IMenuHandler
|
||||
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
|
||||
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
|
||||
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
|
||||
public: //ITimedEvent
|
||||
ResultType OnTimer(ITimer *pTimer, void *pData);
|
||||
void OnTimerEnd(ITimer *pTimer, void *pData);
|
||||
public:
|
||||
bool StartVote(IBaseMenu *menu,
|
||||
unsigned int num_clients,
|
||||
@@ -74,7 +79,7 @@ public:
|
||||
unsigned int GetRemainingVoteDelay();
|
||||
bool IsClientInVotePool(int client);
|
||||
bool GetClientVoteChoice(int client, unsigned int *pItem);
|
||||
bool RedrawToClient(int client);
|
||||
bool RedrawToClient(int client, bool revote);
|
||||
private:
|
||||
void Reset(IMenuHandler *mh);
|
||||
void DecrementPlayerCount();
|
||||
@@ -85,9 +90,12 @@ private:
|
||||
unsigned int time,
|
||||
unsigned int flags);
|
||||
void StartVoting();
|
||||
void DrawHintProgress();
|
||||
void BuildVoteLeaders();
|
||||
private:
|
||||
IMenuHandler *m_pHandler;
|
||||
unsigned int m_Clients;
|
||||
unsigned int m_TotalClients;
|
||||
unsigned int m_Items;
|
||||
CVector<unsigned int> m_Votes;
|
||||
IBaseMenu *m_pCurMenu;
|
||||
@@ -99,6 +107,10 @@ private:
|
||||
float m_fStartTime;
|
||||
unsigned int m_nMenuTime;
|
||||
int m_ClientVotes[256+1];
|
||||
bool m_Revoting[256+1];
|
||||
char m_leaderList[1024];
|
||||
ITimer *m_displayTimer;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourcePawn
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "NativeInvoker.h"
|
||||
#include "ShareSys.h"
|
||||
|
||||
NativeInterface g_NInvoke;
|
||||
|
||||
NativeInvoker::NativeInvoker()
|
||||
{
|
||||
}
|
||||
|
||||
NativeInvoker::~NativeInvoker()
|
||||
{
|
||||
}
|
||||
|
||||
const char *NativeInterface::GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_NINVOKE_NAME;
|
||||
}
|
||||
|
||||
unsigned int NativeInterface::GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_NINVOKE_VERSION;
|
||||
}
|
||||
|
||||
void NativeInterface::OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, &g_NInvoke);
|
||||
}
|
||||
|
||||
IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
|
||||
{
|
||||
return g_pSourcePawn2->CreateEmptyRuntime(name, bytes);
|
||||
}
|
||||
|
||||
INativeInvoker *NativeInterface::CreateInvoker()
|
||||
{
|
||||
return new NativeInvoker();
|
||||
}
|
||||
|
||||
bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
|
||||
{
|
||||
NativeEntry *entry;
|
||||
|
||||
entry = g_ShareSys.FindNative(name);
|
||||
if (entry == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
native = NULL;
|
||||
if (entry->replacement.owner != NULL)
|
||||
{
|
||||
native = entry->replacement.func;
|
||||
}
|
||||
else if (entry->owner != NULL)
|
||||
{
|
||||
native = entry->func;
|
||||
}
|
||||
|
||||
if (native == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this->pContext = pContext;
|
||||
|
||||
m_curparam = 0;
|
||||
m_errorstate = SP_ERROR_NONE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
cell_t NativeInvoker::PushCell(cell_t cell)
|
||||
{
|
||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
|
||||
m_info[m_curparam].marked = false;
|
||||
m_params[m_curparam] = cell;
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int NativeInvoker::PushCellByRef(cell_t *cell, int flags)
|
||||
{
|
||||
return PushArray(cell, 1, flags);
|
||||
}
|
||||
|
||||
int NativeInvoker::PushFloat(float number)
|
||||
{
|
||||
cell_t val = *(cell_t *)&number;
|
||||
|
||||
return PushCell(val);
|
||||
}
|
||||
|
||||
int NativeInvoker::PushFloatByRef(float *number, int flags)
|
||||
{
|
||||
return PushCellByRef((cell_t *)number, flags);
|
||||
}
|
||||
|
||||
int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
|
||||
{
|
||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
|
||||
ParamInfo *info = &m_info[m_curparam];
|
||||
|
||||
info->flags = inarray ? copyback : 0;
|
||||
info->marked = true;
|
||||
info->size = cells;
|
||||
info->str.is_sz = false;
|
||||
info->orig_addr = inarray;
|
||||
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int NativeInvoker::PushString(const char *string)
|
||||
{
|
||||
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
|
||||
}
|
||||
|
||||
int NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
|
||||
{
|
||||
return _PushString(buffer, sz_flags, cp_flags, length);
|
||||
}
|
||||
|
||||
int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
|
||||
{
|
||||
if (m_curparam >= SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
|
||||
ParamInfo *info = &m_info[m_curparam];
|
||||
|
||||
info->marked = true;
|
||||
info->orig_addr = (cell_t *)string;
|
||||
info->flags = cp_flags;
|
||||
info->size = len;
|
||||
info->str.sz_flags = sz_flags;
|
||||
info->str.is_sz = true;
|
||||
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
void NativeInvoker::Cancel()
|
||||
{
|
||||
if (pContext == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_errorstate = SP_ERROR_NONE;
|
||||
m_curparam = 0;
|
||||
pContext = NULL;
|
||||
native = NULL;
|
||||
}
|
||||
|
||||
int NativeInvoker::SetError(int err)
|
||||
{
|
||||
m_errorstate = err;
|
||||
return err;
|
||||
}
|
||||
|
||||
int NativeInvoker::Invoke(cell_t *result)
|
||||
{
|
||||
int err = SP_ERROR_NONE;
|
||||
|
||||
if (pContext == NULL)
|
||||
{
|
||||
return SP_ERROR_INVALID_NATIVE;
|
||||
}
|
||||
|
||||
if (m_errorstate != SP_ERROR_NONE)
|
||||
{
|
||||
err = m_errorstate;
|
||||
Cancel();
|
||||
return err;
|
||||
}
|
||||
|
||||
cell_t tresult;
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
result = &tresult;
|
||||
}
|
||||
|
||||
//This is for re-entrancy!
|
||||
IPluginContext *ctx = pContext;
|
||||
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
|
||||
cell_t *temp_params = &_temp_params[1];
|
||||
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||
unsigned int numparams = m_curparam;
|
||||
unsigned int i;
|
||||
bool docopies = true;
|
||||
|
||||
if (numparams)
|
||||
{
|
||||
//Save the info locally, then reset it for re-entrant calls.
|
||||
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
|
||||
}
|
||||
m_curparam = 0;
|
||||
pContext = NULL;
|
||||
|
||||
/* Initialize 0th parameter */
|
||||
_temp_params[0] = numparams;
|
||||
|
||||
/* Browse the parameters and build arrays */
|
||||
for (i = 0; i < numparams; i++)
|
||||
{
|
||||
/* Is this marked as an array? */
|
||||
if (temp_info[i].marked)
|
||||
{
|
||||
if (!temp_info[i].str.is_sz)
|
||||
{
|
||||
/* Allocate a normal/generic array */
|
||||
if ((err = ctx->HeapAlloc(temp_info[i].size,
|
||||
&temp_info[i].local_addr,
|
||||
&temp_info[i].phys_addr))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (temp_info[i].orig_addr)
|
||||
{
|
||||
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate cells required for the string */
|
||||
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
|
||||
|
||||
/* Allocate the buffer */
|
||||
if ((err = ctx->HeapAlloc(cells,
|
||||
&temp_info[i].local_addr,
|
||||
&temp_info[i].phys_addr))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* Copy original string if necessary */
|
||||
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
|
||||
{
|
||||
/* Cut off UTF-8 properly */
|
||||
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
|
||||
{
|
||||
if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr,
|
||||
temp_info[i].size,
|
||||
(const char *)temp_info[i].orig_addr,
|
||||
NULL))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Copy a binary blob */
|
||||
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
|
||||
{
|
||||
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
|
||||
}
|
||||
/* Copy ASCII characters */
|
||||
else
|
||||
{
|
||||
if ((err = ctx->StringToLocal(temp_info[i].local_addr,
|
||||
temp_info[i].size,
|
||||
(const char *)temp_info[i].orig_addr))
|
||||
!= SP_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* End array/string calculation */
|
||||
/* Update the pushed parameter with the byref local address */
|
||||
temp_params[i] = temp_info[i].local_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just copy the value normally */
|
||||
temp_params[i] = m_params[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the call if we can */
|
||||
if (err == SP_ERROR_NONE)
|
||||
{
|
||||
*result = native(ctx, _temp_params);
|
||||
if (ctx->GetLastNativeError() != SP_ERROR_NONE)
|
||||
{
|
||||
docopies = false;
|
||||
ctx->ClearLastNativeError();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
docopies = false;
|
||||
}
|
||||
|
||||
/* i should be equal to the last valid parameter + 1 */
|
||||
while (i--)
|
||||
{
|
||||
if (!temp_info[i].marked)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
|
||||
{
|
||||
if (temp_info[i].orig_addr)
|
||||
{
|
||||
if (temp_info[i].str.is_sz)
|
||||
{
|
||||
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (temp_info[i].size == 1)
|
||||
{
|
||||
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(temp_info[i].orig_addr,
|
||||
temp_info[i].phys_addr,
|
||||
temp_info[i].size * sizeof(cell_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
||||
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include <INativeInvoker.h>
|
||||
|
||||
struct ParamInfo
|
||||
{
|
||||
int flags; /* Copy-back flags */
|
||||
bool marked; /* Whether this is marked as being used */
|
||||
cell_t local_addr; /* Local address to free */
|
||||
cell_t *phys_addr; /* Physical address of our copy */
|
||||
cell_t *orig_addr; /* Original address to copy back to */
|
||||
ucell_t size; /* Size of array in bytes */
|
||||
struct
|
||||
{
|
||||
bool is_sz; /* is a string */
|
||||
int sz_flags; /* has sz flags */
|
||||
} str;
|
||||
};
|
||||
|
||||
class NativeInvoker : public INativeInvoker
|
||||
{
|
||||
public:
|
||||
NativeInvoker();
|
||||
~NativeInvoker();
|
||||
public: /* ICallable */
|
||||
int PushCell(cell_t cell);
|
||||
int PushCellByRef(cell_t *cell, int flags=SM_PARAM_COPYBACK);
|
||||
int PushFloat(float number);
|
||||
int PushFloatByRef(float *number, int flags=SM_PARAM_COPYBACK);
|
||||
int PushArray(cell_t *inarray, unsigned int cells, int flags=0);
|
||||
int PushString(const char *string);
|
||||
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
|
||||
void Cancel();
|
||||
public: /* INativeInvoker */
|
||||
bool Start(IPluginContext *pContext, const char *name);
|
||||
int Invoke(cell_t *result);
|
||||
private:
|
||||
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
|
||||
int SetError(int err);
|
||||
private:
|
||||
IPluginContext *pContext;
|
||||
SPVM_NATIVE_FUNC native;
|
||||
cell_t m_params[SP_MAX_EXEC_PARAMS];
|
||||
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
|
||||
unsigned int m_curparam;
|
||||
int m_errorstate;
|
||||
};
|
||||
|
||||
class NativeInterface :
|
||||
public INativeInterface,
|
||||
public SMGlobalClass
|
||||
{
|
||||
public: /* SMGlobalClass */
|
||||
void OnSourceModAllInitialized();
|
||||
public: /* SMInterface */
|
||||
unsigned int GetInterfaceVersion();
|
||||
const char *GetInterfaceName();
|
||||
public: /* INativeInvoker */
|
||||
IPluginRuntime *CreateRuntime(const char *name, size_t bytes);
|
||||
INativeInvoker *CreateInvoker();
|
||||
};
|
||||
|
||||
extern NativeInterface g_NInvoke;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ */
|
||||
+26
-25
@@ -38,12 +38,22 @@
|
||||
|
||||
NextMapManager g_NextMap;
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *);
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||
#else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
|
||||
#endif
|
||||
|
||||
#if 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
|
||||
|
||||
@@ -55,30 +65,13 @@ bool g_forcedChange = false;
|
||||
|
||||
void NextMapManager::OnSourceModAllInitialized_Post()
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||
#else
|
||||
SH_ADD_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
|
||||
#endif
|
||||
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
ConCommand *pCmd = NULL;
|
||||
while (pBase)
|
||||
{
|
||||
if (strcmp(pBase->GetName(), "changelevel") == 0)
|
||||
{
|
||||
/* Don't want to return convar with same name */
|
||||
if (!pBase->IsCommand())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pCmd = (ConCommand *)pBase;
|
||||
break;
|
||||
}
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
}
|
||||
|
||||
ConCommand *pCmd = FindCommand("changelevel");
|
||||
if (pCmd != NULL)
|
||||
{
|
||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdChangeLevelCallback, false);
|
||||
@@ -88,7 +81,7 @@ void NextMapManager::OnSourceModAllInitialized_Post()
|
||||
|
||||
void NextMapManager::OnSourceModShutdown()
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
|
||||
@@ -126,7 +119,11 @@ bool NextMapManager::SetNextMap(const char *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)
|
||||
{
|
||||
@@ -146,7 +143,11 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown)
|
||||
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 )
|
||||
@@ -203,7 +204,7 @@ NextMapManager::NextMapManager()
|
||||
m_mapHistory = SourceHook::List<MapChangeData *>();
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void CmdChangeLevelCallback(const CCommand &command)
|
||||
{
|
||||
#else
|
||||
|
||||
+6
-2
@@ -58,7 +58,7 @@ struct MapChangeData
|
||||
time_t startTime;
|
||||
};
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void CmdChangeLevelCallback(const CCommand &command);
|
||||
#else
|
||||
void CmdChangeLevelCallback();
|
||||
@@ -69,7 +69,7 @@ class NextMapManager : public SMGlobalClass
|
||||
public:
|
||||
NextMapManager();
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
friend void CmdChangeLevelCallback(const CCommand &command);
|
||||
#else
|
||||
friend void CmdChangeLevelCallback();
|
||||
@@ -84,7 +84,11 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
+195
-70
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -47,13 +47,15 @@
|
||||
#include <iclient.h>
|
||||
#include "GameConfigs.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include <sourcemod_version.h>
|
||||
#include "ConsoleDetours.h"
|
||||
|
||||
PlayerManager g_Players;
|
||||
bool g_OnMapStarted = false;
|
||||
IForward *PreAdminCheck = NULL;
|
||||
IForward *PostAdminCheck = NULL;
|
||||
IForward *PostAdminFilter = NULL;
|
||||
IForward *OnClientConnected = NULL;
|
||||
|
||||
const unsigned int *g_NumPlayersToAuth = NULL;
|
||||
int lifestate_offset = -1;
|
||||
List<ICommandTargetProcessor *> target_processors;
|
||||
@@ -61,7 +63,7 @@ List<ICommandTargetProcessor *> target_processors;
|
||||
SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
|
||||
SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
|
||||
SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *);
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &);
|
||||
#else
|
||||
SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *);
|
||||
@@ -69,15 +71,23 @@ SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *)
|
||||
SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
|
||||
SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if 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
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# if SH_IMPL_VERSION >= 4
|
||||
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
# endif
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
|
||||
ConCommand *maxplayersCmd = NULL;
|
||||
|
||||
unsigned int g_PlayerSerialCount = 0;
|
||||
|
||||
class KickPlayerTimer : public ITimedEvent
|
||||
{
|
||||
public:
|
||||
@@ -132,6 +142,7 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
ParamType p2[] = {Param_Cell};
|
||||
|
||||
m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_LowEvent, 3, p1);
|
||||
m_clconnect_post = g_Forwards.CreateForward("OnClientConnected", ET_Ignore, 1, p2);
|
||||
m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
|
||||
m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
|
||||
m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
|
||||
@@ -140,7 +151,6 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
|
||||
m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
|
||||
m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
|
||||
OnClientConnected = g_Forwards.CreateForward("OnClientConnected", ET_Ignore, 1, p2);
|
||||
|
||||
PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
|
||||
PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
|
||||
@@ -149,26 +159,7 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
m_bIsListenServer = !engine->IsDedicatedServer();
|
||||
m_ListenClient = 0;
|
||||
|
||||
g_ConVarManager.AddConVarChangeListener("tv_enable", this);
|
||||
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
ConCommand *pCmd = NULL;
|
||||
while (pBase)
|
||||
{
|
||||
if (strcmp(pBase->GetName(), "maxplayers") == 0)
|
||||
{
|
||||
/* Don't want to return convar with same name */
|
||||
if (!pBase->IsCommand())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pCmd = (ConCommand *)pBase;
|
||||
break;
|
||||
}
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
}
|
||||
|
||||
ConCommand *pCmd = FindCommand("maxplayers");
|
||||
if (pCmd != NULL)
|
||||
{
|
||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdMaxplayersCallback, true);
|
||||
@@ -179,6 +170,7 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
void PlayerManager::OnSourceModShutdown()
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect_Post, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
|
||||
@@ -188,6 +180,7 @@ void PlayerManager::OnSourceModShutdown()
|
||||
|
||||
/* Release forwards */
|
||||
g_Forwards.ReleaseForward(m_clconnect);
|
||||
g_Forwards.ReleaseForward(m_clconnect_post);
|
||||
g_Forwards.ReleaseForward(m_clputinserver);
|
||||
g_Forwards.ReleaseForward(m_cldisconnect);
|
||||
g_Forwards.ReleaseForward(m_cldisconnect_post);
|
||||
@@ -196,7 +189,6 @@ void PlayerManager::OnSourceModShutdown()
|
||||
g_Forwards.ReleaseForward(m_clauth);
|
||||
g_Forwards.ReleaseForward(m_onActivate);
|
||||
g_Forwards.ReleaseForward(m_onActivate2);
|
||||
g_Forwards.ReleaseForward(OnClientConnected);
|
||||
|
||||
g_Forwards.ReleaseForward(PreAdminCheck);
|
||||
g_Forwards.ReleaseForward(PostAdminCheck);
|
||||
@@ -204,8 +196,6 @@ void PlayerManager::OnSourceModShutdown()
|
||||
|
||||
delete [] m_Players;
|
||||
|
||||
g_ConVarManager.RemoveConVarChangeListener("tv_enable", this);
|
||||
|
||||
if (maxplayersCmd != NULL)
|
||||
{
|
||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, maxplayersCmd, CmdMaxplayersCallback, true);
|
||||
@@ -245,7 +235,10 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl
|
||||
if (!m_FirstPass)
|
||||
{
|
||||
/* Initialize all players */
|
||||
m_maxClients = clientMax;
|
||||
|
||||
// clientMax will not necessarily be correct here (such as on late SourceTV enable)
|
||||
m_maxClients = gpGlobals->maxClients;
|
||||
|
||||
m_PlayerCount = 0;
|
||||
m_Players = new CPlayer[ABSOLUTE_PLAYER_LIMIT + 1];
|
||||
m_AuthQueue = new unsigned int[ABSOLUTE_PLAYER_LIMIT + 1];
|
||||
@@ -415,7 +408,7 @@ void PlayerManager::RunAuthChecks()
|
||||
|
||||
bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
|
||||
{
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
|
||||
List<IClientListener *>::iterator iter;
|
||||
@@ -433,7 +426,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
|
||||
pPlayer->Initialize(pszName, pszAddress, pEntity);
|
||||
m_clconnect->PushCell(client);
|
||||
m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8, SM_PARAM_COPYBACK);
|
||||
m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
||||
m_clconnect->PushCell(maxrejectlen);
|
||||
m_clconnect->Execute(&res);
|
||||
|
||||
@@ -459,7 +452,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
|
||||
bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
|
||||
{
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
bool orig_value = META_RESULT_ORIG_RET(bool);
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
|
||||
@@ -473,7 +466,7 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
|
||||
pListener->OnClientConnected(client);
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,8 +478,8 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
|
||||
}
|
||||
|
||||
cell_t res;
|
||||
OnClientConnected->PushCell(client);
|
||||
OnClientConnected->Execute(&res, NULL);
|
||||
m_clconnect_post->PushCell(client);
|
||||
m_clconnect_post->Execute(&res, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -499,7 +492,7 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
|
||||
void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername)
|
||||
{
|
||||
cell_t res;
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
|
||||
/* If they're not connected, they're a bot */
|
||||
@@ -527,6 +520,11 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cell_t res;
|
||||
m_clconnect_post->PushCell(client);
|
||||
m_clconnect_post->Execute(&res, NULL);
|
||||
|
||||
/* Now do authorization */
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
@@ -597,7 +595,7 @@ void PlayerManager::OnSourceModLevelEnd()
|
||||
void PlayerManager::OnClientDisconnect(edict_t *pEntity)
|
||||
{
|
||||
cell_t res;
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
|
||||
if (pPlayer->IsConnected())
|
||||
@@ -635,7 +633,7 @@ void PlayerManager::OnClientDisconnect(edict_t *pEntity)
|
||||
void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
|
||||
{
|
||||
cell_t res;
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
|
||||
m_cldisconnect_post->PushCell(client);
|
||||
m_cldisconnect_post->Execute(&res, NULL);
|
||||
@@ -649,7 +647,28 @@ void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void ClientConsolePrint(edict_t *e, const char *fmt, ...)
|
||||
{
|
||||
char buffer[512];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
size_t len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len >= sizeof(buffer) - 1)
|
||||
{
|
||||
buffer[sizeof(buffer) - 2] = '\n';
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
} else {
|
||||
buffer[len++] = '\n';
|
||||
buffer[len] = '\0';
|
||||
}
|
||||
|
||||
engine->ClientPrintf(e, buffer);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void PlayerManager::OnClientCommand(edict_t *pEntity, const CCommand &args)
|
||||
{
|
||||
#else
|
||||
@@ -657,7 +676,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
{
|
||||
CCommand args;
|
||||
#endif
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
cell_t res = Pl_Continue;
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
|
||||
@@ -666,6 +685,39 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(args.Arg(0), "sm") == 0)
|
||||
{
|
||||
if (args.ArgC() > 1 && strcmp(args.Arg(1), "plugins") == 0)
|
||||
{
|
||||
g_PluginSys.ListPluginsToClient(pPlayer, args);
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (args.ArgC() > 1 && strcmp(args.Arg(1), "credits") == 0)
|
||||
{
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod would not be possible without:");
|
||||
ClientConsolePrint(pEntity,
|
||||
" David \"BAILOPAN\" Anderson, Borja \"faluco\" Ferrer");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Scott \"DS\" Ehlert, Matt \"pRED\" Woodrow");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Michael \"ferret\" McKoy, Pavol \"PM OnoTo\" Marko");
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod is open source under the GNU General Public License.");
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod %s, by AlliedModders LLC", SM_FULL_VERSION);
|
||||
ClientConsolePrint(pEntity,
|
||||
"To see running plugins, type \"sm plugins\"");
|
||||
ClientConsolePrint(pEntity,
|
||||
"To see credits, type \"sm credits\"");
|
||||
ClientConsolePrint(pEntity,
|
||||
"Visit http://www.sourcemod.net/");
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
g_HL2.PushCommandStack(&args);
|
||||
|
||||
int argcount = args.ArgC() - 1;
|
||||
@@ -683,10 +735,27 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
}
|
||||
}
|
||||
|
||||
if (g_ConsoleDetours.IsEnabled())
|
||||
{
|
||||
cell_t res2 = g_ConsoleDetours.InternalDispatch(client, args);
|
||||
if (res2 >= Pl_Stop)
|
||||
{
|
||||
g_HL2.PopCommandStack();
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (res2 > res)
|
||||
{
|
||||
res = res2;
|
||||
}
|
||||
}
|
||||
|
||||
cell_t res2 = Pl_Continue;
|
||||
m_clcommand->PushCell(client);
|
||||
m_clcommand->PushCell(argcount);
|
||||
m_clcommand->Execute(&res2, NULL);
|
||||
if (pPlayer->IsInGame())
|
||||
{
|
||||
m_clcommand->PushCell(client);
|
||||
m_clcommand->PushCell(argcount);
|
||||
m_clcommand->Execute(&res2, NULL);
|
||||
}
|
||||
|
||||
if (res2 > res)
|
||||
{
|
||||
@@ -712,7 +781,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
{
|
||||
cell_t res;
|
||||
int client = engine->IndexOfEdict(pEntity);
|
||||
int client = IndexOfEdict(pEntity);
|
||||
CPlayer *pPlayer = &m_Players[client];
|
||||
|
||||
if (!pPlayer->IsConnected())
|
||||
@@ -720,9 +789,14 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
return;
|
||||
}
|
||||
|
||||
m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity));
|
||||
m_clinfochanged->PushCell(client);
|
||||
m_clinfochanged->Execute(&res, NULL);
|
||||
|
||||
if (pPlayer->IsFakeClient())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IPlayerInfo *info = pPlayer->GetPlayerInfo();
|
||||
const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
|
||||
const char *old_name = pPlayer->m_Name.c_str();
|
||||
@@ -840,7 +914,7 @@ void PlayerManager::RemoveClientListener(IClientListener *listener)
|
||||
|
||||
IGamePlayer *PlayerManager::GetGamePlayer(edict_t *pEdict)
|
||||
{
|
||||
int index = engine->IndexOfEdict(pEdict);
|
||||
int index = IndexOfEdict(pEdict);
|
||||
return GetGamePlayer(index);
|
||||
}
|
||||
|
||||
@@ -1106,10 +1180,18 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
|
||||
if (strcmp(info->pattern, "@me") == 0 && info->admin != 0)
|
||||
{
|
||||
info->targets[0] = info->admin;
|
||||
info->num_targets = 1;
|
||||
strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
|
||||
info->target_name_style = COMMAND_TARGETNAME_RAW;
|
||||
info->reason = FilterCommandTarget(pAdmin, pAdmin, info->flags);
|
||||
if (info->reason == COMMAND_TARGET_VALID)
|
||||
{
|
||||
info->targets[0] = info->admin;
|
||||
info->num_targets = 1;
|
||||
strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
|
||||
info->target_name_style = COMMAND_TARGETNAME_RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->num_targets = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1261,18 +1343,6 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnConVarChanged( ConVar *pConVar, const char *oldValue, float flOldValue )
|
||||
{
|
||||
if (pConVar->GetBool() && !atoi(oldValue))
|
||||
{
|
||||
MaxPlayersChanged(gpGlobals->maxClients + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxPlayersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnSourceModMaxPlayersChanged( int newvalue )
|
||||
{
|
||||
m_maxClients = newvalue;
|
||||
@@ -1280,6 +1350,11 @@ void PlayerManager::OnSourceModMaxPlayersChanged( int newvalue )
|
||||
|
||||
void PlayerManager::MaxPlayersChanged( int newvalue /*= -1*/ )
|
||||
{
|
||||
if (!m_FirstPass)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (newvalue == -1)
|
||||
{
|
||||
newvalue = gpGlobals->maxClients;
|
||||
@@ -1311,7 +1386,29 @@ void PlayerManager::MaxPlayersChanged( int newvalue /*= -1*/ )
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
int PlayerManager::GetClientFromSerial(unsigned int serial)
|
||||
{
|
||||
serial_t s;
|
||||
s.value = serial;
|
||||
|
||||
int client = s.bits.index;
|
||||
|
||||
IGamePlayer *pPlayer = GetGamePlayer(client);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (serial == pPlayer->GetSerial())
|
||||
{
|
||||
return client;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
void CmdMaxplayersCallback(const CCommand &command)
|
||||
{
|
||||
#else
|
||||
@@ -1337,6 +1434,7 @@ CPlayer::CPlayer()
|
||||
m_TempAdmin = false;
|
||||
m_Info = NULL;
|
||||
m_bAdminCheckSignalled = false;
|
||||
m_UserId = -1;
|
||||
m_bIsInKickQueue = false;
|
||||
m_LastPassword.clear();
|
||||
m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||
@@ -1349,9 +1447,12 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
m_Name.assign(name);
|
||||
m_Ip.assign(ip);
|
||||
m_pEdict = pEntity;
|
||||
m_iIndex = engine->IndexOfEdict(pEntity);
|
||||
m_iIndex = IndexOfEdict(pEntity);
|
||||
m_LangId = g_Translator.GetServerLanguage();
|
||||
|
||||
m_Serial.bits.index = m_iIndex;
|
||||
m_Serial.bits.serial = g_PlayerSerialCount++;
|
||||
|
||||
char ip2[24], *ptr;
|
||||
strncopy(ip2, ip, sizeof(ip2));
|
||||
if ((ptr = strchr(ip2, ':')) != NULL)
|
||||
@@ -1371,7 +1472,7 @@ void CPlayer::Connect()
|
||||
m_IsInGame = true;
|
||||
|
||||
const char *var = g_Players.GetPassInfoVar();
|
||||
int client = engine->IndexOfEdict(m_pEdict);
|
||||
int client = IndexOfEdict(m_pEdict);
|
||||
if (var[0] != '\0')
|
||||
{
|
||||
const char *pass = engine->GetClientConVarValue(client, var);
|
||||
@@ -1511,8 +1612,22 @@ void CPlayer::Kick(const char *str)
|
||||
{
|
||||
MarkAsBeingKicked();
|
||||
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
|
||||
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
pClient->Disconnect("%s", str);
|
||||
if (pNetChan == NULL)
|
||||
{
|
||||
/* What does this even mean? Hell if I know. */
|
||||
int userid = GetUserId();
|
||||
if (userid > 0)
|
||||
{
|
||||
char buffer[255];
|
||||
UTIL_Format(buffer, sizeof(buffer), "kickid %d %s\n", userid, str);
|
||||
engine->ServerCommand(buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
pClient->Disconnect("%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::Authorize_Post()
|
||||
@@ -1618,7 +1733,7 @@ void CPlayer::DoBasicAdminChecks()
|
||||
|
||||
/* First check the name */
|
||||
AdminId id;
|
||||
int client = engine->IndexOfEdict(m_pEdict);
|
||||
int client = IndexOfEdict(m_pEdict);
|
||||
|
||||
if ((id = g_Admins.FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID)
|
||||
{
|
||||
@@ -1654,6 +1769,11 @@ unsigned int CPlayer::GetLanguageId()
|
||||
return m_LangId;
|
||||
}
|
||||
|
||||
void CPlayer::SetLanguageId(unsigned int id)
|
||||
{
|
||||
m_LangId = id;
|
||||
}
|
||||
|
||||
int CPlayer::GetUserId()
|
||||
{
|
||||
if (m_UserId == -1)
|
||||
@@ -1715,3 +1835,8 @@ int CPlayer::GetLifeState()
|
||||
return PLAYER_LIFE_DEAD;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CPlayer::GetSerial()
|
||||
{
|
||||
return m_Serial.value;
|
||||
}
|
||||
|
||||
+21
-7
@@ -51,6 +51,16 @@ using namespace SourceHook;
|
||||
|
||||
#define MIN_API_FOR_ADMINCALLS 7
|
||||
|
||||
union serial_t
|
||||
{
|
||||
uint32_t value;
|
||||
struct
|
||||
{
|
||||
uint8_t index;
|
||||
uint32_t serial : 24;
|
||||
} bits;
|
||||
};
|
||||
|
||||
class CPlayer : public IGamePlayer
|
||||
{
|
||||
friend class PlayerManager;
|
||||
@@ -69,14 +79,16 @@ public:
|
||||
void SetAdminId(AdminId id, bool temporary);
|
||||
AdminId GetAdminId();
|
||||
void Kick(const char *str);
|
||||
bool IsInKickQueue();
|
||||
IPlayerInfo *GetPlayerInfo();
|
||||
unsigned int GetLanguageId();
|
||||
void SetLanguageId(unsigned int id);
|
||||
int GetUserId();
|
||||
bool RunAdminCacheChecks();
|
||||
void NotifyPostAdminChecks();
|
||||
unsigned int GetSerial();
|
||||
public:
|
||||
void DoBasicAdminChecks();
|
||||
bool IsInKickQueue();
|
||||
void MarkAsBeingKicked();
|
||||
int GetLifeState();
|
||||
private:
|
||||
@@ -107,12 +119,12 @@ private:
|
||||
unsigned int m_LangId;
|
||||
int m_UserId;
|
||||
bool m_bFakeClient;
|
||||
serial_t m_Serial;
|
||||
};
|
||||
|
||||
class PlayerManager :
|
||||
public SMGlobalClass,
|
||||
public IPlayerManager,
|
||||
public IConVarChangeListener
|
||||
public IPlayerManager
|
||||
{
|
||||
friend class CPlayer;
|
||||
public:
|
||||
@@ -135,7 +147,7 @@ public:
|
||||
void OnClientPutInServer(edict_t *pEntity, char const *playername);
|
||||
void OnClientDisconnect(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);
|
||||
#else
|
||||
void OnClientCommand(edict_t *pEntity);
|
||||
@@ -156,8 +168,7 @@ public: //IPlayerManager
|
||||
void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||
void ProcessCommandTarget(cmd_target_info_t *info);
|
||||
public: // IConVarChangeListener
|
||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||
int GetClientFromSerial(unsigned int serial);
|
||||
public:
|
||||
inline int MaxClients()
|
||||
{
|
||||
@@ -184,6 +195,7 @@ private:
|
||||
private:
|
||||
List<IClientListener *> m_hooks;
|
||||
IForward *m_clconnect;
|
||||
IForward *m_clconnect_post;
|
||||
IForward *m_cldisconnect;
|
||||
IForward *m_cldisconnect_post;
|
||||
IForward *m_clputinserver;
|
||||
@@ -204,12 +216,14 @@ private:
|
||||
int m_ListenClient;
|
||||
};
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if 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 bool g_OnMapStarted;
|
||||
extern const unsigned int *g_NumPlayersToAuth;
|
||||
|
||||
@@ -276,7 +276,7 @@ SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
m_infodb_size *= 2;
|
||||
}
|
||||
int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
|
||||
int newidx = memtab->CreateMem(m_infodb_size * sizeof(int), (void **)&table);
|
||||
if (m_infodb != -1)
|
||||
{
|
||||
void *oldtable = (int *)memtab->GetAddress(m_infodb);
|
||||
|
||||
+164
-44
@@ -37,7 +37,6 @@
|
||||
#include "ForwardSys.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "sourcemod.h"
|
||||
#include "TextParsers.h"
|
||||
#include "Logger.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include "sm_srvcmds.h"
|
||||
@@ -57,10 +56,11 @@ CPlugin::CPlugin(const char *file)
|
||||
|
||||
m_type = PluginType_Private;
|
||||
m_status = Plugin_Uncompiled;
|
||||
m_bSilentlyFailed = false;
|
||||
m_serial = ++MySerial;
|
||||
m_pRuntime = NULL;
|
||||
m_errormsg[256] = '\0';
|
||||
snprintf(m_filename, sizeof(m_filename), "%s", file);
|
||||
m_errormsg[sizeof(m_errormsg) - 1] = '\0';
|
||||
UTIL_Format(m_filename, sizeof(m_filename), "%s", file);
|
||||
m_handle = 0;
|
||||
m_ident = NULL;
|
||||
m_pProps = sm_trie_create();
|
||||
@@ -164,7 +164,7 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Unable to open file");
|
||||
UTIL_Format(error, maxlength, "Unable to open file");
|
||||
}
|
||||
pPlugin->m_status = Plugin_BadLoad;
|
||||
return pPlugin;
|
||||
@@ -210,7 +210,7 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, error_fmt);
|
||||
vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
|
||||
UTIL_FormatArgs(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (m_pRuntime != NULL)
|
||||
@@ -273,13 +273,13 @@ bool CPlugin::UpdateInfo()
|
||||
|
||||
base->GetPubvarAddrs(idx, &local_addr, (cell_t **)&info);
|
||||
m_FileVersion = info->version;
|
||||
if (m_FileVersion >= 3)
|
||||
if (m_FileVersion >= 4)
|
||||
{
|
||||
base->LocalToString(info->date, (char **)&pDate);
|
||||
base->LocalToString(info->time, (char **)&pTime);
|
||||
UTIL_Format(m_DateTime, sizeof(m_DateTime), "%s %s", pDate, pTime);
|
||||
}
|
||||
if (m_FileVersion > 4)
|
||||
if (m_FileVersion > 5)
|
||||
{
|
||||
base->LocalToString(info->filevers, (char **)&pFileVers);
|
||||
SetErrorState(Plugin_Failed, "Newer SourceMod required (%s or higher)", pFileVers);
|
||||
@@ -386,22 +386,27 @@ void CPlugin::Call_OnAllPluginsLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
||||
APLRes CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
||||
{
|
||||
if (m_status != Plugin_Created)
|
||||
{
|
||||
return false;
|
||||
return APLRes_Failure;
|
||||
}
|
||||
|
||||
m_status = Plugin_Loaded;
|
||||
|
||||
int err;
|
||||
cell_t result;
|
||||
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad");
|
||||
bool haveNewAPL = false;
|
||||
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad2");
|
||||
|
||||
if (!pFunction)
|
||||
if (pFunction)
|
||||
{
|
||||
return true;
|
||||
haveNewAPL = true;
|
||||
}
|
||||
else if (!(pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad")))
|
||||
{
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
pFunction->PushCell(m_handle);
|
||||
@@ -410,15 +415,21 @@ bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
|
||||
pFunction->PushCell(maxlength);
|
||||
if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE)
|
||||
{
|
||||
return false;
|
||||
return APLRes_Failure;
|
||||
}
|
||||
|
||||
if (!result || m_status != Plugin_Loaded)
|
||||
if (haveNewAPL)
|
||||
{
|
||||
return false;
|
||||
return (APLRes)result;
|
||||
}
|
||||
else if (result)
|
||||
{
|
||||
return APLRes_Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return APLRes_Failure;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *CPlugin::GetPluginStructure()
|
||||
@@ -470,6 +481,11 @@ PluginStatus CPlugin::GetStatus()
|
||||
return m_status;
|
||||
}
|
||||
|
||||
bool CPlugin::IsSilentlyFailed()
|
||||
{
|
||||
return m_bSilentlyFailed;
|
||||
}
|
||||
|
||||
bool CPlugin::IsDebugging()
|
||||
{
|
||||
if (m_pRuntime == NULL)
|
||||
@@ -480,6 +496,11 @@ bool CPlugin::IsDebugging()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPlugin::SetSilentlyFailed(bool sf)
|
||||
{
|
||||
m_bSilentlyFailed = sf;
|
||||
}
|
||||
|
||||
void CPlugin::LibraryActions(bool dropping)
|
||||
{
|
||||
List<String>::iterator iter;
|
||||
@@ -851,7 +872,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
if (localpath == NULL)
|
||||
{
|
||||
/* If no path yet, don't add a former slash */
|
||||
snprintf(new_local, sizeof(new_local), "%s", dir->GetEntryName());
|
||||
UTIL_Format(new_local, sizeof(new_local), "%s", dir->GetEntryName());
|
||||
} else {
|
||||
g_LibSys.PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName());
|
||||
}
|
||||
@@ -866,7 +887,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
char plugin[PLATFORM_MAX_PATH];
|
||||
if (localpath == NULL)
|
||||
{
|
||||
snprintf(plugin, sizeof(plugin), "%s", name);
|
||||
UTIL_Format(plugin, sizeof(plugin), "%s", name);
|
||||
} else {
|
||||
g_LibSys.PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name);
|
||||
}
|
||||
@@ -965,7 +986,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
|
||||
UTIL_Format(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
|
||||
}
|
||||
co->Abort();
|
||||
co = NULL;
|
||||
@@ -984,7 +1005,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
pPlugin->m_pRuntime = g_pSourcePawn2->LoadPlugin(co, fullpath, &err);
|
||||
if (pPlugin->m_pRuntime == NULL)
|
||||
{
|
||||
snprintf(error,
|
||||
UTIL_Format(error,
|
||||
maxlength,
|
||||
"Unable to load plugin (error %d: %s)",
|
||||
err,
|
||||
@@ -1004,20 +1025,31 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
}
|
||||
}
|
||||
|
||||
LoadRes loadFailure = LoadRes_Failure;
|
||||
/* Get the status */
|
||||
if (pPlugin->GetStatus() == Plugin_Created)
|
||||
{
|
||||
/* First native pass - add anything from Core */
|
||||
g_ShareSys.BindNativesToPlugin(pPlugin, true);
|
||||
pPlugin->InitIdentity();
|
||||
if (pPlugin->Call_AskPluginLoad(error, maxlength))
|
||||
APLRes result = pPlugin->Call_AskPluginLoad(error, maxlength);
|
||||
switch (result)
|
||||
{
|
||||
case APLRes_Success:
|
||||
/* Autoload any modules */
|
||||
LoadOrRequireExtensions(pPlugin, 1, error, maxlength);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case APLRes_Failure:
|
||||
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||
loadFailure = LoadRes_Failure;
|
||||
break;
|
||||
case APLRes_SilentFailure:
|
||||
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
|
||||
loadFailure = LoadRes_SilentFailure;
|
||||
pPlugin->SetSilentlyFailed(true);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1062,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
|
||||
*_plugin = pPlugin;
|
||||
}
|
||||
|
||||
return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : LoadRes_Failure;
|
||||
return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : loadFailure;
|
||||
}
|
||||
|
||||
IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t maxlength, bool *wasloaded)
|
||||
@@ -1053,13 +1085,16 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
|
||||
|
||||
if (res == LoadRes_NeverLoad)
|
||||
{
|
||||
if (m_LoadingLocked)
|
||||
if (error)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "There is a global plugin loading lock in effect");
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Format(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
|
||||
if (m_LoadingLocked)
|
||||
{
|
||||
UTIL_Format(error, maxlength, "There is a global plugin loading lock in effect");
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Format(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1090,12 +1125,12 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
|
||||
{
|
||||
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s", plugin, error);
|
||||
pl->SetErrorState(
|
||||
pl->GetStatus() == Plugin_BadLoad ? Plugin_BadLoad : Plugin_Failed,
|
||||
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
|
||||
"%s",
|
||||
error);
|
||||
}
|
||||
|
||||
if (res == LoadRes_Successful || res == LoadRes_Failure)
|
||||
if (res == LoadRes_Successful || res == LoadRes_Failure || res == LoadRes_SilentFailure)
|
||||
{
|
||||
AddPlugin(pl);
|
||||
}
|
||||
@@ -1189,7 +1224,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Fatal error during initializing plugin load");
|
||||
UTIL_Format(error, maxlength, "Fatal error during initializing plugin load");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1222,7 +1257,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Could not find required plugin \"%s\"", name);
|
||||
UTIL_Format(error, maxlength, "Could not find required plugin \"%s\"", name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1293,7 +1328,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
|
||||
UTIL_Format(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1361,7 +1396,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlength, "Native \"%s\" was not found", native->name);
|
||||
UTIL_Format(error, maxlength, "Native \"%s\" was not found", native->name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1951,7 +1986,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
assert(pl->GetStatus() != Plugin_Created);
|
||||
int len = 0;
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
if (pl->GetStatus() != Plugin_Running)
|
||||
if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed())
|
||||
{
|
||||
len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetStatus()));
|
||||
|
||||
@@ -1967,6 +2002,8 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
}
|
||||
if (pl->GetStatus() < Plugin_Created)
|
||||
{
|
||||
if (pl->IsSilentlyFailed())
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " Disabled:");
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
if (IS_STR_FILLED(info->version))
|
||||
{
|
||||
@@ -2015,7 +2052,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(filename) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", filename, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", filename, ext);
|
||||
|
||||
IPlugin *pl = LoadPlugin(pluginfile, false, PluginType_MapUpdated, error, sizeof(error), &wasloaded);
|
||||
|
||||
@@ -2062,7 +2099,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
@@ -2152,7 +2189,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
@@ -2273,7 +2310,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
{
|
||||
char pluginfile[256];
|
||||
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
|
||||
UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
|
||||
|
||||
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
|
||||
{
|
||||
@@ -2284,7 +2321,10 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
|
||||
|
||||
char name[PLATFORM_MAX_PATH];
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
if (pl->GetStatus() <= Plugin_Paused)
|
||||
strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
else
|
||||
strcpy(name, pl->GetFilename());
|
||||
|
||||
if (ReloadPlugin(pl))
|
||||
{
|
||||
@@ -2624,3 +2664,83 @@ void CPluginManager::SyncMaxClients(int max_clients)
|
||||
(*iter)->SyncMaxClients(max_clients);
|
||||
}
|
||||
}
|
||||
|
||||
void CPluginManager::ListPluginsToClient(CPlayer *player, const CCommand &args)
|
||||
{
|
||||
char buffer[256];
|
||||
unsigned int id = 0;
|
||||
int plnum = GetPluginCount();
|
||||
edict_t *e = player->GetEdict();
|
||||
unsigned int start = 0;
|
||||
|
||||
if (!plnum)
|
||||
{
|
||||
ClientConsolePrint(e, "[SM] No plugins found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.ArgC() > 2)
|
||||
{
|
||||
start = atoi(args.Arg(2));
|
||||
}
|
||||
|
||||
CPlugin *pl;
|
||||
SourceHook::List<CPlugin *>::iterator iter;
|
||||
SourceHook::List<CPlugin *> m_FailList;
|
||||
|
||||
for (iter = m_plugins.begin();
|
||||
iter != m_plugins.end();
|
||||
iter++)
|
||||
{
|
||||
pl = (*iter);
|
||||
|
||||
if (pl->GetStatus() != Plugin_Running)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Count valid plugins */
|
||||
id++;
|
||||
if (id < start)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id - start > 10)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
len = UTIL_Format(buffer, sizeof(buffer), " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
if (IS_STR_FILLED(info->version))
|
||||
{
|
||||
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", info->version);
|
||||
}
|
||||
if (IS_STR_FILLED(info->author))
|
||||
{
|
||||
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", info->author);
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", pl->m_filename);
|
||||
}
|
||||
ClientConsolePrint(e, "%s", buffer);
|
||||
}
|
||||
|
||||
/* See if we can get more plugins */
|
||||
while (iter != m_plugins.end())
|
||||
{
|
||||
if ((*iter)->GetStatus() == Plugin_Running)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we actually have more plugins? */
|
||||
if (iter != m_plugins.end())
|
||||
{
|
||||
ClientConsolePrint(e, "To see more, type \"sm plugins %d\"", id);
|
||||
}
|
||||
}
|
||||
|
||||
+22
-3
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -47,7 +47,11 @@
|
||||
#include "sm_trie.h"
|
||||
#include "sourcemod.h"
|
||||
#include <IRootConsoleMenu.h>
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#if SOURCE_ENGINE == SE_ALIENSWARM
|
||||
#include "convar_sm_swarm.h"
|
||||
#elif (SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2)
|
||||
#include "convar_sm_l4d.h"
|
||||
#elif (SOURCE_ENGINE == SE_ORANGEBOX) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE)
|
||||
#include "convar_sm_ob.h"
|
||||
#else
|
||||
#include "convar_sm.h"
|
||||
@@ -56,6 +60,8 @@
|
||||
#include "NativeOwner.h"
|
||||
#include "ShareSys.h"
|
||||
|
||||
class CPlayer;
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
/**
|
||||
@@ -113,9 +119,17 @@ enum LoadRes
|
||||
LoadRes_Successful,
|
||||
LoadRes_AlreadyLoaded,
|
||||
LoadRes_Failure,
|
||||
LoadRes_SilentFailure,
|
||||
LoadRes_NeverLoad
|
||||
};
|
||||
|
||||
enum APLRes
|
||||
{
|
||||
APLRes_Success,
|
||||
APLRes_Failure,
|
||||
APLRes_SilentFailure
|
||||
};
|
||||
|
||||
struct AutoConfig
|
||||
{
|
||||
String autocfg;
|
||||
@@ -142,6 +156,8 @@ public:
|
||||
const char *GetFilename();
|
||||
bool IsDebugging();
|
||||
PluginStatus GetStatus();
|
||||
bool IsSilentlyFailed();
|
||||
void SetSilentlyFailed(bool sf);
|
||||
const sm_plugininfo_t *GetPublicInfo();
|
||||
bool SetPauseState(bool paused);
|
||||
unsigned int GetSerial();
|
||||
@@ -179,7 +195,7 @@ public:
|
||||
*
|
||||
* If the error buffer is NULL, the error message is cached locally.
|
||||
*/
|
||||
bool Call_AskPluginLoad(char *error, size_t maxlength);
|
||||
APLRes Call_AskPluginLoad(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Calls the OnPluginStart function.
|
||||
@@ -243,6 +259,7 @@ private:
|
||||
PluginType m_type;
|
||||
char m_filename[PLATFORM_MAX_PATH];
|
||||
PluginStatus m_status;
|
||||
bool m_bSilentlyFailed;
|
||||
unsigned int m_serial;
|
||||
sm_plugininfo_t m_info;
|
||||
char m_errormsg[256];
|
||||
@@ -395,6 +412,8 @@ public:
|
||||
CPlugin *FindPluginByConsoleArg(const char *arg);
|
||||
|
||||
void SyncMaxClients(int max_clients);
|
||||
|
||||
void ListPluginsToClient(CPlayer *player, const CCommand &args);
|
||||
private:
|
||||
LoadRes _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t maxlength);
|
||||
|
||||
|
||||
@@ -527,3 +527,85 @@ NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name
|
||||
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name)
|
||||
{
|
||||
if (m_caps.retrieve(name) != NULL)
|
||||
return;
|
||||
|
||||
Capability cap;
|
||||
cap.ext = myself;
|
||||
cap.provider = provider;
|
||||
|
||||
m_caps.insert(name, cap);
|
||||
}
|
||||
|
||||
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name)
|
||||
{
|
||||
Capability *pCap = m_caps.retrieve(name);
|
||||
if (pCap == NULL)
|
||||
return;
|
||||
|
||||
if (pCap->ext != myself || pCap->provider != provider)
|
||||
return;
|
||||
|
||||
m_caps.remove(name);
|
||||
}
|
||||
|
||||
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature,
|
||||
const char *name)
|
||||
{
|
||||
switch (feature)
|
||||
{
|
||||
case FeatureType_Native:
|
||||
return TestNative(pRuntime, name);
|
||||
case FeatureType_Capability:
|
||||
return TestCap(name);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FeatureStatus_Unknown;
|
||||
}
|
||||
|
||||
FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (pRuntime->FindNativeByName(name, &index) == SP_ERROR_NONE)
|
||||
{
|
||||
sp_native_t *native;
|
||||
if (pRuntime->GetNativeByIndex(index, &native) == SP_ERROR_NONE)
|
||||
{
|
||||
if (native->status == SP_NATIVE_BOUND)
|
||||
return FeatureStatus_Available;
|
||||
else
|
||||
return FeatureStatus_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
NativeEntry *entry = FindNative(name);
|
||||
if (entry == NULL)
|
||||
return FeatureStatus_Unknown;
|
||||
|
||||
if ((entry->replacement.owner != NULL || entry->owner != NULL) &&
|
||||
(entry->replacement.func != NULL || entry->func != NULL))
|
||||
{
|
||||
return FeatureStatus_Available;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FeatureStatus_Unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
FeatureStatus ShareSystem::TestCap(const char *name)
|
||||
{
|
||||
Capability *cap = m_caps.retrieve(name);
|
||||
if (cap == NULL)
|
||||
return FeatureStatus_Unknown;
|
||||
|
||||
return cap->provider->GetFeatureStatus(FeatureType_Capability, name);
|
||||
}
|
||||
|
||||
+16
-2
@@ -87,7 +87,13 @@ struct NativeEntry
|
||||
FakeNative *fake;
|
||||
};
|
||||
|
||||
class ShareSystem :
|
||||
struct Capability
|
||||
{
|
||||
IExtension *ext;
|
||||
IFeatureProvider *provider;
|
||||
};
|
||||
|
||||
class ShareSystem :
|
||||
public IShareSys,
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch
|
||||
@@ -110,6 +116,10 @@ public: //IShareSys
|
||||
void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload);
|
||||
void RegisterLibrary(IExtension *myself, const char *name);
|
||||
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
||||
void AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name);
|
||||
void DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
|
||||
const char *name);
|
||||
public: //SMGlobalClass
|
||||
/* Pre-empt in case anything tries to register idents early */
|
||||
void Initialize();
|
||||
@@ -119,6 +129,9 @@ public: //IHandleTypeDispatch
|
||||
public:
|
||||
IdentityToken_t *CreateCoreIdentity();
|
||||
void RemoveInterfaces(IExtension *pExtension);
|
||||
FeatureStatus TestFeature(IPluginRuntime *pRuntime, FeatureType feature, const char *name);
|
||||
FeatureStatus TestNative(IPluginRuntime *pRuntime, const char *name);
|
||||
FeatureStatus TestCap(const char *name);
|
||||
public:
|
||||
inline IdentityToken_t *GetIdentRoot()
|
||||
{
|
||||
@@ -128,10 +141,10 @@ public:
|
||||
void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly);
|
||||
void BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry);
|
||||
NativeEntry *AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
|
||||
NativeEntry *FindNative(const char *name);
|
||||
private:
|
||||
NativeEntry *AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv);
|
||||
void ClearNativeFromCache(CNativeOwner *pOwner, const char *name);
|
||||
NativeEntry *FindNative(const char *name);
|
||||
void BindNativeToPlugin(CPlugin *pPlugin,
|
||||
sp_native_t *ntv,
|
||||
uint32_t index,
|
||||
@@ -143,6 +156,7 @@ private:
|
||||
HandleType_t m_IfaceType;
|
||||
IdentityType_t m_CoreType;
|
||||
KTrie<NativeEntry *> m_NtvCache;
|
||||
KTrie<Capability> m_caps;
|
||||
};
|
||||
|
||||
extern ShareSystem g_ShareSys;
|
||||
|
||||
+4
-2
@@ -887,8 +887,10 @@ void Translator::RebuildLanguageDatabase(const char *lang_header_file)
|
||||
strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
|
||||
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
|
||||
}
|
||||
|
||||
m_ServerLang = reinterpret_cast<unsigned int>(serverLang);
|
||||
else
|
||||
{
|
||||
m_ServerLang = reinterpret_cast<unsigned int>(serverLang);
|
||||
}
|
||||
|
||||
if (!m_Languages.size())
|
||||
{
|
||||
|
||||
+73
-14
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -34,7 +34,11 @@
|
||||
|
||||
UserMessages g_UserMsgs;
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
|
||||
#else
|
||||
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
||||
#endif
|
||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
||||
|
||||
UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
|
||||
@@ -164,9 +168,17 @@ bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigne
|
||||
|
||||
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);
|
||||
#endif
|
||||
} 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);
|
||||
#endif
|
||||
}
|
||||
|
||||
return buffer;
|
||||
@@ -193,7 +205,31 @@ bool UserMessages::EndMessage()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserMessages::HookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept)
|
||||
{
|
||||
return InternalHook(msg_id, pListener, intercept, true);
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept)
|
||||
{
|
||||
return InternalUnhook(msg_id, pListener, intercept, true);
|
||||
}
|
||||
|
||||
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
return InternalHook(msg_id, pListener, intercept, false);
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
return InternalUnhook(msg_id, pListener, intercept, false);
|
||||
}
|
||||
|
||||
bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
{
|
||||
if (msg_id < 0 || msg_id >= 255)
|
||||
{
|
||||
@@ -212,6 +248,7 @@ bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener,
|
||||
pInfo->Callback = pListener;
|
||||
pInfo->IsHooked = false;
|
||||
pInfo->KillMe = false;
|
||||
pInfo->IsNew = isNew;
|
||||
|
||||
if (!m_HookCount++)
|
||||
{
|
||||
@@ -231,8 +268,8 @@ bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
|
||||
{
|
||||
bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
|
||||
{
|
||||
MsgList *pList;
|
||||
MsgIter iter;
|
||||
ListenerInfo *pInfo;
|
||||
@@ -247,7 +284,7 @@ bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener
|
||||
for (iter=pList->begin(); iter!=pList->end(); iter++)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
if (pInfo->Callback == pListener)
|
||||
if (pInfo->Callback == pListener && pInfo->IsNew == isNew)
|
||||
{
|
||||
if (pInfo->IsHooked)
|
||||
{
|
||||
@@ -279,7 +316,11 @@ void UserMessages::_DecRefCounter()
|
||||
}
|
||||
}
|
||||
|
||||
#if 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)
|
||||
#endif
|
||||
{
|
||||
bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
|
||||
bool is_hook_empty = m_msgHooks[msg_type].empty();
|
||||
@@ -305,7 +346,11 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
||||
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
#if 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)
|
||||
#endif
|
||||
{
|
||||
if (!m_InHook)
|
||||
{
|
||||
@@ -319,7 +364,7 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
|
||||
|
||||
void UserMessages::OnMessageEnd_Post()
|
||||
{
|
||||
if (!m_InHook || m_BlockEndPost)
|
||||
if (!m_InHook)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
@@ -328,12 +373,22 @@ void UserMessages::OnMessageEnd_Post()
|
||||
MsgIter iter;
|
||||
ListenerInfo *pInfo;
|
||||
|
||||
m_InHook = false;
|
||||
|
||||
pList = &m_msgIntercepts[m_CurId];
|
||||
for (iter=pList->begin(); iter!=pList->end(); )
|
||||
{
|
||||
pInfo = (*iter);
|
||||
if (m_BlockEndPost && !pInfo->IsNew)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pInfo->IsHooked = true;
|
||||
pInfo->Callback->OnUserMessageSent(m_CurId);
|
||||
if (pInfo->IsNew)
|
||||
{
|
||||
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
|
||||
}
|
||||
|
||||
if (pInfo->KillMe)
|
||||
{
|
||||
@@ -347,14 +402,20 @@ void UserMessages::OnMessageEnd_Post()
|
||||
iter++;
|
||||
}
|
||||
|
||||
m_InHook = false;
|
||||
|
||||
pList = &m_msgHooks[m_CurId];
|
||||
for (iter=pList->begin(); iter!=pList->end(); )
|
||||
{
|
||||
pInfo = (*iter);
|
||||
if (m_BlockEndPost && !pInfo->IsNew)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pInfo->IsHooked = true;
|
||||
pInfo->Callback->OnUserMessageSent(m_CurId);
|
||||
if (pInfo->IsNew)
|
||||
{
|
||||
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
|
||||
}
|
||||
|
||||
if (pInfo->KillMe)
|
||||
{
|
||||
@@ -435,16 +496,15 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
{
|
||||
goto supercede;
|
||||
}
|
||||
|
||||
if (intercepted)
|
||||
if (!handled && intercepted)
|
||||
{
|
||||
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);
|
||||
#endif
|
||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
||||
ENGINE_CALL(MessageEnd)();
|
||||
@@ -471,7 +531,6 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
|
||||
RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
|
||||
supercede:
|
||||
m_InHook = false;
|
||||
m_BlockEndPost = true;
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
+15
-1
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -48,6 +48,7 @@ struct ListenerInfo
|
||||
IUserMessageListener *Callback;
|
||||
bool IsHooked;
|
||||
bool KillMe;
|
||||
bool IsNew;
|
||||
};
|
||||
|
||||
typedef List<ListenerInfo *> MsgList;
|
||||
@@ -71,12 +72,25 @@ public: //IUserMessages
|
||||
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);
|
||||
bool EndMessage();
|
||||
bool HookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept=false);
|
||||
bool UnhookUserMessage2(int msg_id,
|
||||
IUserMessageListener *pListener,
|
||||
bool intercept=false);
|
||||
public:
|
||||
#if 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_Post(IRecipientFilter *filter, int msg_type);
|
||||
#endif
|
||||
void OnMessageEnd_Pre();
|
||||
void OnMessageEnd_Post();
|
||||
private:
|
||||
bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
|
||||
void _DecRefCounter();
|
||||
private:
|
||||
List<ListenerInfo *> m_msgHooks[255];
|
||||
|
||||
+34
-20
@@ -35,9 +35,13 @@
|
||||
#include "concmd_cleaner.h"
|
||||
#include "sm_stringutil.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, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
#else
|
||||
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
#endif
|
||||
|
||||
using namespace SourceHook;
|
||||
@@ -50,29 +54,55 @@ struct ConCommandInfo
|
||||
};
|
||||
|
||||
List<ConCommandInfo *> tracked_bases;
|
||||
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
|
||||
|
||||
ConCommandBase *FindConCommandBase(const char *name);
|
||||
|
||||
class ConCommandCleaner : public SMGlobalClass
|
||||
{
|
||||
public:
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#else
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
|
||||
}
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#else
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LinkConCommandBase(ConCommandBase *pBase)
|
||||
{
|
||||
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||
while (listener)
|
||||
{
|
||||
listener->OnLinkConCommand(pBase);
|
||||
listener = listener->next;
|
||||
}
|
||||
}
|
||||
|
||||
void UnlinkConCommandBase(ConCommandBase *pBase)
|
||||
{
|
||||
ConCommandInfo *pInfo;
|
||||
List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
|
||||
|
||||
IConCommandLinkListener *listener = IConCommandLinkListener::head;
|
||||
while (listener)
|
||||
{
|
||||
listener->OnUnlinkConCommand(pBase);
|
||||
listener = listener->next;
|
||||
}
|
||||
|
||||
if (pBase)
|
||||
{
|
||||
while (iter != tracked_bases.end())
|
||||
@@ -95,7 +125,7 @@ public:
|
||||
while (iter != tracked_bases.end())
|
||||
{
|
||||
/* This is just god-awful! */
|
||||
if (FindConCommandBase((*iter)->name) != (*iter)->pBase)
|
||||
if (FindCommandBase((*iter)->name) != (*iter)->pBase)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
iter = tracked_bases.erase(iter);
|
||||
@@ -143,22 +173,6 @@ public:
|
||||
}
|
||||
} 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)
|
||||
{
|
||||
s_ConCmdTracker.AddTarget(pBase, me);
|
||||
|
||||
+22
-1
@@ -38,9 +38,30 @@ public:
|
||||
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 UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
|
||||
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
|
||||
|
||||
class IConCommandLinkListener
|
||||
{
|
||||
friend class ConCommandCleaner;
|
||||
|
||||
static IConCommandLinkListener *head;
|
||||
IConCommandLinkListener *next;
|
||||
public:
|
||||
IConCommandLinkListener()
|
||||
{
|
||||
next = head;
|
||||
head = this;
|
||||
}
|
||||
|
||||
virtual void OnLinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CONCMD_TRACKER_H_
|
||||
|
||||
@@ -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 _LINUX
|
||||
#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_LEFT4DEAD2
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@
|
||||
#include "PlayerManager.h"
|
||||
#include "CoreConfig.h"
|
||||
#include <sm_queue.h>
|
||||
#include "ThreadSupport.h"
|
||||
#include <IThreader.h>
|
||||
|
||||
static IMutex *frame_mutex;
|
||||
static Queue<FrameAction> *frame_queue;
|
||||
|
||||
+6
-1
@@ -32,10 +32,15 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
||||
#define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
|
||||
|
||||
typedef void (*FRAMEACTION)(void *data);
|
||||
#include <ISourceMod.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
struct FrameAction
|
||||
{
|
||||
FrameAction(FRAMEACTION a, void *d) : data(d), action(a)
|
||||
{
|
||||
}
|
||||
void *data;
|
||||
FRAMEACTION action;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
|
||||
compiler = SM.DefaultCompiler()
|
||||
base = AMBuild.sourceFolder
|
||||
compiler['CXXINCLUDES'].append(os.path.join(SM.mmsPath, 'core', 'sourcehook'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(base, 'core', 'logic'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(base, 'public'))
|
||||
compiler['CXXINCLUDES'].append(os.path.join(base, 'public', 'sourcepawn'))
|
||||
compiler['CDEFINES'].append('SM_DEFAULT_THREADER')
|
||||
compiler['CDEFINES'].append('SM_LOGIC')
|
||||
|
||||
if AMBuild.target['platform'] == 'linux':
|
||||
compiler['POSTLINKFLAGS'].append('-lpthread')
|
||||
|
||||
extension = AMBuild.AddJob('sourcemod.logic')
|
||||
binary = Cpp.LibraryBuilder('sourcemod.logic', AMBuild, extension, compiler)
|
||||
files = [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
'smn_sorting.cpp',
|
||||
'smn_maplists.cpp',
|
||||
'smn_adt_stack.cpp',
|
||||
'thread/ThreadWorker.cpp',
|
||||
'thread/BaseWorker.cpp',
|
||||
'ThreadSupport.cpp',
|
||||
'smn_float.cpp',
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'Profiler.cpp',
|
||||
'smn_functions.cpp'
|
||||
]
|
||||
if AMBuild.target['platform'] == 'windows':
|
||||
files.append('thread/WinThreads.cpp')
|
||||
else:
|
||||
files.append('thread/PosixThreads.cpp')
|
||||
binary.AddSourceFiles('core/logic', files)
|
||||
SM.AutoVersion('core/logic', binary)
|
||||
binary.SendToJob()
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CELLARRAY_H_
|
||||
#define _INCLUDE_SOURCEMOD_CELLARRAY_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -204,3 +207,6 @@ private:
|
||||
size_t m_AllocSize;
|
||||
size_t m_Size;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_CELLARRAY_H_ */
|
||||
|
||||
@@ -1,76 +1,92 @@
|
||||
# (C)2004-2008 SourceMod Development Team
|
||||
# Makefile written by David "BAILOPAN" Anderson
|
||||
|
||||
|
||||
#####################################
|
||||
### EDIT BELOW FOR OTHER PROJECTS ###
|
||||
#####################################
|
||||
|
||||
OBJECTS = smud.cpp smud_connections.cpp smud_threads.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
|
||||
|
||||
BINARY = smupdated
|
||||
|
||||
LINK += -lpthread -static-libgcc
|
||||
|
||||
INCLUDE += -I.
|
||||
|
||||
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 -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32
|
||||
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:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o)
|
||||
OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
|
||||
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
|
||||
|
||||
$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp
|
||||
$(CPP) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||
|
||||
$(BIN_DIR)/%.o: %.cpp
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
|
||||
|
||||
$(BIN_DIR)/%.o: %.c
|
||||
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
all:
|
||||
mkdir -p $(BIN_DIR)
|
||||
$(MAKE) -f Makefile sourcemod
|
||||
|
||||
sourcemod: $(OBJ_LINUX)
|
||||
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -lstdc++ -o $(BIN_DIR)/$(BINARY)
|
||||
|
||||
debug:
|
||||
$(MAKE) -f Makefile all DEBUG=true
|
||||
|
||||
default: all
|
||||
|
||||
clean:
|
||||
rm -rf $(BIN_DIR)/$(BINARY)
|
||||
# (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
|
||||
|
||||
##############################################
|
||||
### 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,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
|
||||
@@ -30,13 +30,12 @@
|
||||
*/
|
||||
|
||||
#include "Profiler.h"
|
||||
#include "PluginSys.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "Logger.h"
|
||||
#include <ISourceMod.h>
|
||||
#if defined PLATFORM_POSIX
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <IPluginSys.h>
|
||||
|
||||
ProfileEngine g_Profiler;
|
||||
IProfiler *sm_profiler = &g_Profiler;
|
||||
@@ -314,43 +313,74 @@ void ProfileEngine::Clear()
|
||||
|
||||
void ProfileEngine::OnSourceModAllInitialized()
|
||||
{
|
||||
g_RootMenu.AddRootConsoleCommand("profiler", "Profiler commands", this);
|
||||
rootmenu->AddRootConsoleCommand2("profiler", "Profiler commands", this);
|
||||
}
|
||||
|
||||
void ProfileEngine::OnSourceModShutdown()
|
||||
{
|
||||
g_RootMenu.RemoveRootConsoleCommand("profiler", this);
|
||||
rootmenu->RemoveRootConsoleCommand("profiler", this);
|
||||
}
|
||||
|
||||
void ProfileEngine::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
|
||||
void ProfileEngine::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command)
|
||||
{
|
||||
if (command.ArgC() >= 3)
|
||||
if (command->ArgC() >= 3)
|
||||
{
|
||||
if (strcmp(command.Arg(2), "flush") == 0)
|
||||
if (strcmp(command->Arg(2), "flush") == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[256];
|
||||
|
||||
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
g_RootMenu.ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateReport(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
Clear();
|
||||
|
||||
g_RootMenu.ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (strcmp(command->Arg(2), "report") == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[256];
|
||||
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
|
||||
|
||||
if ((fp = fopen(path, "wt")) == NULL)
|
||||
{
|
||||
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateReport(fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
|
||||
return;
|
||||
}
|
||||
else if (strcmp(command->Arg(2), "clear") == 0)
|
||||
{
|
||||
Clear();
|
||||
|
||||
rootmenu->ConsolePrint("Profiler statistics cleared.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_RootMenu.ConsolePrint("Profiler commands:");
|
||||
g_RootMenu.DrawGenericOption("flush", "Flushes statistics to disk and starts over");
|
||||
rootmenu->ConsolePrint("Profiler commands:");
|
||||
rootmenu->DrawGenericOption("flush", "Flushes statistics to disk and starts over");
|
||||
rootmenu->DrawGenericOption("report", "Flushes statistics to disk");
|
||||
rootmenu->DrawGenericOption("clear", "Clears statistics");
|
||||
}
|
||||
|
||||
bool ProfileEngine::GenerateReport(FILE *fp)
|
||||
@@ -387,9 +417,9 @@ void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *nam
|
||||
{
|
||||
ar = report->GetReport(i);
|
||||
|
||||
strncopy(new_name, ar->atom_name, sizeof(new_name));
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "<");
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", ">");
|
||||
smcore.strncopy(new_name, ar->atom_name, sizeof(new_name));
|
||||
smcore.ReplaceAll(new_name, sizeof(new_name), "<", "<", true);
|
||||
smcore.ReplaceAll(new_name, sizeof(new_name), ">", ">", true);
|
||||
|
||||
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
|
||||
new_name,
|
||||
@@ -438,20 +468,20 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
|
||||
|
||||
if (atom.atom_type == SP_PROF_NATIVES)
|
||||
{
|
||||
strncopy(full_name, atom.name, sizeof(full_name));
|
||||
smcore.strncopy(full_name, atom.name, sizeof(full_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
CPlugin *pl;
|
||||
IPlugin *pl;
|
||||
const char *file;
|
||||
|
||||
file = "unknown";
|
||||
if ((pl = g_PluginSys.GetPluginByCtx(atom.ctx)) != NULL)
|
||||
if ((pl = pluginsys->FindPluginByContext(atom.ctx)) != NULL)
|
||||
{
|
||||
file = pl->GetFilename();
|
||||
}
|
||||
|
||||
UTIL_Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
|
||||
smcore.Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
|
||||
}
|
||||
|
||||
atom_time = CalcAtomTime(atom);
|
||||
@@ -460,7 +490,7 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
|
||||
{
|
||||
report = new prof_atom_report_t;
|
||||
|
||||
strncopy(report->atom_name, full_name, sizeof(report->atom_name));
|
||||
smcore.strncopy(report->atom_name, full_name, sizeof(report->atom_name));
|
||||
report->max_time = atom_time;
|
||||
report->min_time = atom_time;
|
||||
report->num_calls = 1;
|
||||
@@ -38,8 +38,8 @@
|
||||
#include <sh_vector.h>
|
||||
#include <sh_stack.h>
|
||||
#include <stdio.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "common_logic.h"
|
||||
#include <IRootConsoleMenu.h>
|
||||
|
||||
using namespace SourcePawn;
|
||||
using namespace SourceHook;
|
||||
@@ -103,7 +103,7 @@ public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IRootConsoleCommand
|
||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command);
|
||||
public: //IProfiler
|
||||
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native);
|
||||
void OnNativeEnd() ;
|
||||
@@ -126,6 +126,6 @@ private:
|
||||
prof_point_t m_ProfStart;
|
||||
};
|
||||
|
||||
extern ProfileEngine g_Profiler;
|
||||
extern IProfiler *sm_profiler;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
|
||||
@@ -36,9 +36,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "TextParsers.h"
|
||||
#include "ShareSys.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "LibrarySys.h"
|
||||
#include <ILibrarySys.h>
|
||||
|
||||
TextParsers g_TextParser;
|
||||
ITextParsers *textparsers = &g_TextParser;
|
||||
@@ -48,7 +46,7 @@ static int g_ws_chartable[255] = {0};
|
||||
|
||||
bool TextParsers::IsWhitespace(const char *stream)
|
||||
{
|
||||
return g_ws_chartable[(unsigned)*stream] == 1;
|
||||
return g_ws_chartable[(unsigned char)*stream] == 1;
|
||||
}
|
||||
|
||||
TextParsers::TextParsers()
|
||||
@@ -71,7 +69,7 @@ TextParsers::TextParsers()
|
||||
|
||||
void TextParsers::OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
sharesys->AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
unsigned int TextParsers::GetUTF8CharBytes(const char *stream)
|
||||
@@ -79,45 +77,6 @@ unsigned int TextParsers::GetUTF8CharBytes(const char *stream)
|
||||
return _GetUTF8CharBytes(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Character streams
|
||||
*/
|
||||
|
||||
struct CharStream
|
||||
{
|
||||
const char *curpos;
|
||||
};
|
||||
|
||||
bool CharStreamReader(void *stream, char *buffer, size_t maxlength, unsigned int *read)
|
||||
{
|
||||
CharStream *srdr = (CharStream *)stream;
|
||||
|
||||
const char *ptr = srdr->curpos;
|
||||
for (size_t i=0; i<maxlength; i++)
|
||||
{
|
||||
if (*ptr == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
*buffer++ = *ptr++;
|
||||
}
|
||||
|
||||
*read = ptr - srdr->curpos;
|
||||
|
||||
srdr->curpos = ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SMCError TextParsers::ParseString_SMC(const char *stream,
|
||||
ITextListener_SMC *smc,
|
||||
SMCStates *states)
|
||||
{
|
||||
CharStream srdr = { stream };
|
||||
|
||||
return ParseStream_SMC(&srdr, CharStreamReader, smc, states);
|
||||
}
|
||||
|
||||
/**
|
||||
* File streams
|
||||
*/
|
||||
@@ -174,8 +133,8 @@ SMCError TextParsers::ParseSMCFile(const char *file,
|
||||
states->line = 0;
|
||||
states->col = 0;
|
||||
}
|
||||
g_LibSys.GetPlatformError(error, sizeof(error));
|
||||
UTIL_Format(buffer, maxsize, "File could not be opened: %s", error);
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
smcore.Format(buffer, maxsize, "File could not be opened: %s", error);
|
||||
return SMCError_StreamOpen;
|
||||
}
|
||||
|
||||
@@ -184,7 +143,58 @@ SMCError TextParsers::ParseSMCFile(const char *file,
|
||||
fclose(fp);
|
||||
|
||||
errstr = GetSMCErrorString(result);
|
||||
UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
smcore.Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct RawStream
|
||||
{
|
||||
const char *stream;
|
||||
size_t length;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
bool RawStreamReader(void *stream, char *buffer, size_t maxlength, unsigned int *read)
|
||||
{
|
||||
RawStream *rs = (RawStream *)stream;
|
||||
|
||||
if (rs->pos >= rs->length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t remaining = rs->length - rs->pos;
|
||||
|
||||
/* Use the smaller of the two */
|
||||
size_t copy = (remaining > maxlength) ? maxlength : remaining;
|
||||
|
||||
memcpy(buffer, &rs->stream[rs->pos], copy);
|
||||
rs->pos += copy;
|
||||
*read = copy;
|
||||
assert(rs->pos <= rs->length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SMCError TextParsers::ParseSMCStream(const char *stream,
|
||||
size_t length,
|
||||
ITextListener_SMC *smc_listener,
|
||||
SMCStates *states,
|
||||
char *buffer,
|
||||
size_t maxsize)
|
||||
{
|
||||
RawStream rs;
|
||||
SMCError result;
|
||||
|
||||
rs.stream = stream;
|
||||
rs.length = length;
|
||||
rs.pos = 0;
|
||||
|
||||
result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states);
|
||||
|
||||
const char *errstr = GetSMCErrorString(result);
|
||||
smcore.Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -496,7 +506,7 @@ SMCError TextParsers::ParseStream_SMC(void *stream,
|
||||
else
|
||||
{
|
||||
/* Check if we're whitespace or not */
|
||||
if (!g_ws_chartable[(unsigned)c])
|
||||
if (!g_ws_chartable[(unsigned char)c])
|
||||
{
|
||||
bool restage = false;
|
||||
/* Check various special tokens:
|
||||
@@ -811,7 +821,7 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
|
||||
***************************************************/
|
||||
|
||||
/* First strip beginning whitespace */
|
||||
while (*ptr != '\0' && g_ws_chartable[(unsigned)*ptr] != 0)
|
||||
while (*ptr != '\0' && g_ws_chartable[(unsigned char)*ptr] != 0)
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
@@ -864,7 +874,7 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
|
||||
/* Lastly, strip ending whitespace off */
|
||||
for (size_t i=len-1; i>=0 && i<len; i--)
|
||||
{
|
||||
if (g_ws_chartable[(unsigned)ptr[i]])
|
||||
if (g_ws_chartable[(unsigned char)ptr[i]])
|
||||
{
|
||||
ptr[i] = '\0';
|
||||
len--;
|
||||
@@ -905,7 +915,7 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
|
||||
i += _GetUTF8CharBytes(&ptr[i]) - 1;
|
||||
}
|
||||
} else {
|
||||
alnum = (isalnum(c) != 0) || (g_ini_chartable1[(unsigned)c] != 0);
|
||||
alnum = (isalnum(c) != 0) || (g_ini_chartable1[(unsigned char)c] != 0);
|
||||
}
|
||||
if (!alnum)
|
||||
{
|
||||
@@ -958,12 +968,12 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
|
||||
i += _GetUTF8CharBytes(&ptr[i]) - 1;
|
||||
}
|
||||
} else {
|
||||
alnum = (isalnum(c) != 0) || (g_ini_chartable1[(unsigned)c] != 0);
|
||||
alnum = (isalnum(c) != 0) || (g_ini_chartable1[(unsigned char)c] != 0);
|
||||
}
|
||||
|
||||
if (!alnum)
|
||||
{
|
||||
if (g_ws_chartable[(unsigned)c])
|
||||
if (g_ws_chartable[(unsigned char)c])
|
||||
{
|
||||
/* if it's a space, keep track of the first occurring space */
|
||||
if (!first_space)
|
||||
@@ -1002,7 +1012,7 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
|
||||
if (val_ptr)
|
||||
{
|
||||
/* eat up spaces! there shouldn't be any h*/
|
||||
while ((*val_ptr != '\0') && g_ws_chartable[(unsigned)*val_ptr] != 0)
|
||||
while ((*val_ptr != '\0') && g_ws_chartable[(unsigned char)*val_ptr] != 0)
|
||||
{
|
||||
val_ptr++;
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
|
||||
|
||||
#include <ITextParsers.h>
|
||||
#include "sm_globals.h"
|
||||
#include "common_logic.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
@@ -70,14 +70,18 @@ public:
|
||||
char *buffer,
|
||||
size_t maxsize);
|
||||
|
||||
SMCError ParseSMCStream(const char *stream,
|
||||
size_t length,
|
||||
ITextListener_SMC *smc_listener,
|
||||
SMCStates *states,
|
||||
char *buffer,
|
||||
size_t maxsize);
|
||||
|
||||
unsigned int GetUTF8CharBytes(const char *stream);
|
||||
|
||||
const char *GetSMCErrorString(SMCError err);
|
||||
bool IsWhitespace(const char *stream);
|
||||
private:
|
||||
SMCError ParseString_SMC(const char *stream,
|
||||
ITextListener_SMC *smc,
|
||||
SMCStates *states);
|
||||
SMCError ParseStream_SMC(void *stream,
|
||||
STREAMREADER srdr,
|
||||
ITextListener_SMC *smc,
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -28,10 +28,9 @@
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sm_platform.h>
|
||||
#include "ThreadSupport.h"
|
||||
#include "sm_globals.h"
|
||||
#include "ShareSys.h"
|
||||
#include "common_logic.h"
|
||||
|
||||
#if defined PLATFORM_POSIX
|
||||
#include "thread/PosixThreads.h"
|
||||
@@ -47,6 +46,7 @@ class RegThreadStuff : public SMGlobalClass
|
||||
public:
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
g_ShareSys.AddInterface(NULL, g_pThreader);
|
||||
sharesys->AddInterface(NULL, g_pThreader);
|
||||
}
|
||||
} s_RegThreadStuff;
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <sm_platform.h>
|
||||
#include <string.h>
|
||||
#include "common_logic.h"
|
||||
#include "ThreadSupport.h"
|
||||
#include "TextParsers.h"
|
||||
#include "Profiler.h"
|
||||
|
||||
sm_core_t smcore;
|
||||
IHandleSys *handlesys;
|
||||
IdentityToken_t *g_pCoreIdent;
|
||||
SMGlobalClass *SMGlobalClass::head = NULL;
|
||||
ISourceMod *g_pSM;
|
||||
ILibrarySys *libsys;
|
||||
ITextParsers *textparser = &g_TextParser;
|
||||
IVEngineServer *engine;
|
||||
IShareSys *sharesys;
|
||||
IRootConsole *rootmenu;
|
||||
IPluginManager *pluginsys;
|
||||
IForwardManager *forwardsys;
|
||||
|
||||
static sm_logic_t logic =
|
||||
{
|
||||
NULL,
|
||||
g_pThreader,
|
||||
sm_profiler
|
||||
};
|
||||
|
||||
static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
|
||||
{
|
||||
logic.head = SMGlobalClass::head;
|
||||
|
||||
memcpy(&smcore, core, sizeof(sm_core_t));
|
||||
memcpy(_logic, &logic, sizeof(sm_logic_t));
|
||||
|
||||
handlesys = core->handlesys;
|
||||
libsys = core->libsys;
|
||||
engine = core->engine;
|
||||
g_pCoreIdent = core->core_ident;
|
||||
g_pSM = core->sm;
|
||||
sharesys = core->sharesys;
|
||||
rootmenu = core->rootmenu;
|
||||
pluginsys = core->pluginsys;
|
||||
forwardsys = core->forwardsys;
|
||||
}
|
||||
|
||||
PLATFORM_EXTERN_C ITextParsers *get_textparsers()
|
||||
{
|
||||
return &g_TextParser;
|
||||
}
|
||||
|
||||
PLATFORM_EXTERN_C LogicInitFunction logic_load(uint32_t magic)
|
||||
{
|
||||
if (magic != SM_LOGIC_MAGIC)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return logic_init;
|
||||
}
|
||||
|
||||
void CoreNativesToAdd::OnSourceModAllInitialized()
|
||||
{
|
||||
smcore.AddNatives(m_NativeList);
|
||||
}
|
||||
|
||||
/* Overload a few things to prevent libstdc++ linking */
|
||||
#if defined __linux__ || defined __APPLE__
|
||||
extern "C" void __cxa_pure_virtual(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
@@ -29,20 +29,24 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Autogenerated by build scripts
|
||||
*/
|
||||
#ifndef _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
|
||||
#define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
#define _INCLUDE_SOURCEMOD_VERSION_H_
|
||||
#include <IHandleSys.h>
|
||||
|
||||
/**
|
||||
* @file Contains SourceMod version information.
|
||||
*/
|
||||
#include "../sm_globals.h"
|
||||
#include "intercom.h"
|
||||
|
||||
#define SM_BUILD_STRING "$BUILD_STRING$"
|
||||
#define SM_BUILD_UNIQUEID "$BUILD_ID$" SM_BUILD_STRING
|
||||
#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$" SM_BUILD_STRING
|
||||
#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,0
|
||||
extern sm_core_t smcore;
|
||||
extern IHandleSys *handlesys;
|
||||
extern ISourceMod *g_pSM;
|
||||
extern ILibrarySys *libsys;
|
||||
extern ITextParsers *textparser;
|
||||
extern IVEngineServer *engine;
|
||||
extern IShareSys *sharesys;
|
||||
extern IRootConsole *rootmenu;
|
||||
extern IPluginManager *pluginsys;
|
||||
extern IForwardManager *forwardsys;
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VERSION_H_
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <IShareSys.h>
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
|
||||
#define _INCLUDE_SOURCEMOD_INTERCOM_H_
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
/**
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 2)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
#else
|
||||
class IVEngineServer_Logic
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual bool IsMapValid(const char *map) = 0;
|
||||
};
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
class ISourceMod;
|
||||
class ILibrarySys;
|
||||
class ITextParsers;
|
||||
class IThreader;
|
||||
class IRootConsole;
|
||||
class IPluginManager;
|
||||
class IForwardManager;
|
||||
}
|
||||
|
||||
class IVEngineServer;
|
||||
class ConVar;
|
||||
|
||||
struct sm_core_t
|
||||
{
|
||||
/* Objects */
|
||||
IHandleSys *handlesys;
|
||||
IdentityToken_t *core_ident;
|
||||
ISourceMod *sm;
|
||||
ILibrarySys *libsys;
|
||||
IVEngineServer *engine;
|
||||
IShareSys *sharesys;
|
||||
IRootConsole *rootmenu;
|
||||
IPluginManager *pluginsys;
|
||||
IForwardManager *forwardsys;
|
||||
/* Functions */
|
||||
void (*AddNatives)(sp_nativeinfo_t* nlist);
|
||||
ConVar * (*FindConVar)(const char*);
|
||||
unsigned int (*strncopy)(char*, const char*, size_t);
|
||||
char * (*TrimWhitespace)(char *, size_t &);
|
||||
void (*LogError)(const char*, ...);
|
||||
const char * (*GetCvarString)(ConVar*);
|
||||
size_t (*Format)(char*, size_t, const char*, ...);
|
||||
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
|
||||
};
|
||||
|
||||
struct sm_logic_t
|
||||
{
|
||||
SMGlobalClass *head;
|
||||
IThreader *threader;
|
||||
IProfiler *profiler;
|
||||
};
|
||||
|
||||
typedef void (*LogicInitFunction)(const sm_core_t *core, sm_logic_t *logic);
|
||||
typedef LogicInitFunction (*LogicLoadFunction)(uint32_t magic);
|
||||
typedef ITextParsers *(*GetITextParsers)();
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_INTERCOM_H_ */
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logic", "logic.vcproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Executable
+323
@@ -0,0 +1,323 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="logic"
|
||||
ProjectGUID="{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
|
||||
RootNamespace="jitx86"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..;"$(MMSOURCE17)\core\sourcehook";..\..\..\public;..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_DEFAULT_THREADER"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
|
||||
LinkIncremental="2"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
FavorSizeOrSpeed="1"
|
||||
AdditionalIncludeDirectories="..;"$(MMSOURCE17)\core\sourcehook";..\..\..\public;..\..\..\public\sourcepawn"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_LOGIC;SM_DEFAULT_THREADER"
|
||||
RuntimeLibrary="0"
|
||||
EnableEnhancedInstructionSet="0"
|
||||
RuntimeTypeInfo="false"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sourcemod.logic.dll"
|
||||
LinkIncremental="1"
|
||||
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\smn_functions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_adt_trie.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Profiler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common_logic.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_adt_array.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_adt_stack.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_float.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_maplists.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_sorting.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\smn_textparse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\TextParsers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ThreadSupport.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\CellArray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\common_logic.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\intercom.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\svn_version.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\TextParsers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\ThreadSupport.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Profiler.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\svn_version.tpl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\version.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Threads"
|
||||
>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\thread\BaseWorker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\ThreadWorker.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\WinThreads.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\thread\BaseWorker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\ThreadWorker.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\thread\WinThreads.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -30,10 +30,8 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "common_logic.h"
|
||||
#include "CellArray.h"
|
||||
#include "HandleSys.h"
|
||||
|
||||
HandleType_t htCellArray;
|
||||
|
||||
@@ -44,11 +42,11 @@ class CellArrayHelpers :
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
htCellArray = g_HandleSys.CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
htCellArray = handlesys->CreateType("CellArray", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
}
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
g_HandleSys.RemoveType(htCellArray, g_pCoreIdent);
|
||||
handlesys->RemoveType(htCellArray, g_pCoreIdent);
|
||||
}
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -78,7 +76,7 @@ static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
|
||||
array->resize(params[2]);
|
||||
}
|
||||
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete array;
|
||||
@@ -93,7 +91,7 @@ static cell_t ClearArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -110,7 +108,7 @@ static cell_t ResizeArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -130,7 +128,7 @@ static cell_t GetArraySize(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -145,7 +143,7 @@ static cell_t PushArrayCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -168,7 +166,7 @@ static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -183,7 +181,7 @@ static cell_t PushArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
pContext->LocalToString(params[2], &str);
|
||||
|
||||
strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
|
||||
return (cell_t)(array->size() - 1);
|
||||
}
|
||||
@@ -194,7 +192,7 @@ static cell_t PushArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -226,7 +224,7 @@ static cell_t GetArrayCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -265,7 +263,7 @@ static cell_t GetArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -291,7 +289,7 @@ static cell_t GetArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -324,7 +322,7 @@ static cell_t SetArrayCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -363,7 +361,7 @@ static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -380,7 +378,7 @@ static cell_t SetArrayString(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
pContext->LocalToString(params[3], &str);
|
||||
|
||||
return strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
return smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
}
|
||||
|
||||
static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -389,7 +387,7 @@ static cell_t SetArrayArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -422,7 +420,7 @@ static cell_t ShiftArrayUp(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -445,7 +443,7 @@ static cell_t RemoveFromArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -468,7 +466,7 @@ static cell_t SwapArrayItems(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -496,7 +494,7 @@ static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&oldArray))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -504,7 +502,7 @@ static cell_t CloneArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
CellArray *array = oldArray->clone();
|
||||
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete array;
|
||||
@@ -519,7 +517,7 @@ static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -546,7 +544,7 @@ static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -30,10 +30,8 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "common_logic.h"
|
||||
#include "CellArray.h"
|
||||
#include "HandleSys.h"
|
||||
|
||||
HandleType_t htCellStack;
|
||||
|
||||
@@ -44,11 +42,11 @@ class CellStackHelpers :
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
htCellStack = g_HandleSys.CreateType("CellStack", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
htCellStack = handlesys->CreateType("CellStack", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
}
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
g_HandleSys.RemoveType(htCellStack, g_pCoreIdent);
|
||||
handlesys->RemoveType(htCellStack, g_pCoreIdent);
|
||||
}
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -73,7 +71,7 @@ static cell_t CreateStack(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
CellArray *array = new CellArray(params[1]);
|
||||
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(htCellStack, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellStack, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete array;
|
||||
@@ -88,7 +86,7 @@ static cell_t PushStackCell(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -111,7 +109,7 @@ static cell_t PushStackString(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -126,7 +124,7 @@ static cell_t PushStackString(IPluginContext *pContext, const cell_t *params)
|
||||
char *str;
|
||||
pContext->LocalToString(params[2], &str);
|
||||
|
||||
strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
smcore.strncopy((char *)blk, str, array->blocksize() * sizeof(cell_t));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -137,7 +135,7 @@ static cell_t PushStackArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -171,7 +169,7 @@ static cell_t PopStackCell(IPluginContext *pContext, const cell_t *params)
|
||||
cell_t *blk, *buffer;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -217,7 +215,7 @@ static cell_t PopStackString(IPluginContext *pContext, const cell_t *params)
|
||||
cell_t *blk, *pWritten;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -248,7 +246,7 @@ static cell_t PopStackArray(IPluginContext *pContext, const cell_t *params)
|
||||
CellArray *array;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -281,7 +279,7 @@ static cell_t IsStackEmpty(IPluginContext *pContext, const cell_t *params)
|
||||
CellArray *array;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -30,10 +30,8 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "HandleSys.h"
|
||||
#include "sm_trie_tpl.h"
|
||||
#include "common_logic.h"
|
||||
#include <sm_trie_tpl.h>
|
||||
|
||||
HandleType_t htCellTrie;
|
||||
|
||||
@@ -85,11 +83,11 @@ class TrieHelpers :
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
htCellTrie = g_HandleSys.CreateType("Trie", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
htCellTrie = handlesys->CreateType("Trie", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
}
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
g_HandleSys.RemoveType(htCellTrie, g_pCoreIdent);
|
||||
handlesys->RemoveType(htCellTrie, g_pCoreIdent);
|
||||
}
|
||||
public: //IHandleTypeDispatch
|
||||
static void DestroySmartTrieNode(SmartTrieNode *pNode)
|
||||
@@ -119,7 +117,7 @@ static cell_t CreateTrie(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
pTrie->mem_usage = 0;
|
||||
|
||||
if ((hndl = g_HandleSys.CreateHandle(htCellTrie, pTrie, pContext->GetIdentity(), g_pCoreIdent, NULL))
|
||||
if ((hndl = handlesys->CreateHandle(htCellTrie, pTrie, pContext->GetIdentity(), g_pCoreIdent, NULL))
|
||||
== BAD_HANDLE)
|
||||
{
|
||||
delete pTrie;
|
||||
@@ -191,7 +189,7 @@ static cell_t SetTrieValue(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -227,7 +225,7 @@ static cell_t SetTrieArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -275,7 +273,7 @@ static cell_t SetTrieString(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -317,7 +315,7 @@ static cell_t RemoveFromTrie(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -347,7 +345,7 @@ static cell_t ClearTrie(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -368,7 +366,7 @@ static cell_t GetTrieValue(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -403,7 +401,7 @@ static cell_t GetTrieArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -460,7 +458,7 @@ static cell_t GetTrieString(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -507,7 +505,7 @@ static cell_t GetTrieSize(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
hndl = params[1];
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -32,7 +32,9 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sm_globals.h"
|
||||
#include "common_logic.h"
|
||||
#include "MersenneTwister.h"
|
||||
#include <IPluginSys.h>
|
||||
|
||||
/****************************************
|
||||
* *
|
||||
@@ -285,6 +287,68 @@ static cell_t sm_FloatRound(IPluginContext *pCtx, const cell_t *params)
|
||||
}
|
||||
#endif
|
||||
|
||||
class RandomHelpers :
|
||||
public SMGlobalClass,
|
||||
public IPluginsListener
|
||||
{
|
||||
public:
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
pluginsys->AddPluginsListener(this);
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
pluginsys->RemovePluginsListener(this);
|
||||
}
|
||||
|
||||
void OnPluginDestroyed(IPlugin *plugin)
|
||||
{
|
||||
MTRand *mtrand;
|
||||
if (plugin->GetProperty("core.logic.mtrand", (void**)&mtrand, true))
|
||||
{
|
||||
delete mtrand;
|
||||
}
|
||||
}
|
||||
|
||||
MTRand *RandObjForPlugin(IPluginContext *ctx)
|
||||
{
|
||||
IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
|
||||
MTRand *mtrand;
|
||||
if (!plugin->GetProperty("core.logic.mtrand", (void**)&mtrand))
|
||||
{
|
||||
mtrand = new MTRand();
|
||||
plugin->SetProperty("core.logic.mtrand", mtrand);
|
||||
}
|
||||
return mtrand;
|
||||
}
|
||||
} s_RandHelpers;
|
||||
|
||||
static cell_t GetURandomInt(IPluginContext *ctx, const cell_t *params)
|
||||
{
|
||||
MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
|
||||
/* Note the sign bit must be stripped off because cell_t is signed,
|
||||
* and this guarantees a range of [0,max_int]
|
||||
*/
|
||||
return randobj->randInt() & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
static cell_t GetURandomFloat(IPluginContext *ctx, const cell_t *params)
|
||||
{
|
||||
MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
|
||||
return sp_ftoc((float)randobj->rand());
|
||||
}
|
||||
|
||||
static cell_t SetURandomSeed(IPluginContext *ctx, const cell_t *params)
|
||||
{
|
||||
MTRand *randobj = s_RandHelpers.RandObjForPlugin(ctx);
|
||||
cell_t *addr;
|
||||
ctx->LocalToPhysAddr(params[1], &addr);
|
||||
/* We're 32-bit only. */
|
||||
randobj->seed((MTRand::uint32*)addr, params[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(floatnatives)
|
||||
{
|
||||
{"float", sm_float},
|
||||
@@ -310,5 +374,9 @@ REGISTER_NATIVES(floatnatives)
|
||||
{"ArcCosine", sm_ArcCosine},
|
||||
{"ArcSine", sm_ArcSine},
|
||||
{"ArcTangent2", sm_ArcTangent2},
|
||||
{"GetURandomInt", GetURandomInt},
|
||||
{"GetURandomFloat", GetURandomFloat},
|
||||
{"SetURandomSeed", SetURandomSeed},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "PluginSys.h"
|
||||
#include "ForwardSys.h"
|
||||
#include "HandleSys.h"
|
||||
#include "common_logic.h"
|
||||
#include <IPluginSys.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <IForwardSys.h>
|
||||
|
||||
HandleType_t g_GlobalFwdType = 0;
|
||||
HandleType_t g_PrivateFwdType = 0;
|
||||
@@ -52,36 +52,36 @@ public:
|
||||
HandleAccess sec;
|
||||
|
||||
/* Set GlobalFwd handle access security */
|
||||
g_HandleSys.InitAccessDefaults(NULL, &sec);
|
||||
handlesys->InitAccessDefaults(NULL, &sec);
|
||||
sec.access[HandleAccess_Read] = 0;
|
||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||
|
||||
/* Create 'GlobalFwd' handle type */
|
||||
g_GlobalFwdType = g_HandleSys.CreateType("GlobalFwd", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
g_GlobalFwdType = handlesys->CreateType("GlobalFwd", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
|
||||
/* Private forwards are cloneable */
|
||||
sec.access[HandleAccess_Clone] = 0;
|
||||
|
||||
/* Create 'PrivateFwd' handle type */
|
||||
g_PrivateFwdType = g_HandleSys.CreateType("PrivateFwd", this, g_GlobalFwdType, NULL, &sec, g_pCoreIdent, NULL);
|
||||
g_PrivateFwdType = handlesys->CreateType("PrivateFwd", this, g_GlobalFwdType, NULL, &sec, g_pCoreIdent, NULL);
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
g_HandleSys.RemoveType(g_PrivateFwdType, g_pCoreIdent);
|
||||
g_HandleSys.RemoveType(g_GlobalFwdType, g_pCoreIdent);
|
||||
handlesys->RemoveType(g_PrivateFwdType, g_pCoreIdent);
|
||||
handlesys->RemoveType(g_GlobalFwdType, g_pCoreIdent);
|
||||
}
|
||||
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
IForward *pForward = static_cast<IForward *>(object);
|
||||
|
||||
g_Forwards.ReleaseForward(pForward);
|
||||
forwardsys->ReleaseForward(pForward);
|
||||
}
|
||||
|
||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
|
||||
{
|
||||
*pSize = sizeof(CForward) + (((IForward *)object)->GetFunctionCount() * 12);
|
||||
*pSize = sizeof(IForward*) + (((IForward *)object)->GetFunctionCount() * 12);
|
||||
return true;
|
||||
}
|
||||
} g_ForwardNativeHelpers;
|
||||
@@ -112,9 +112,9 @@ static cell_t sm_GetFunctionByName(IPluginContext *pContext, const cell_t *param
|
||||
|
||||
if (hndl == 0)
|
||||
{
|
||||
pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
||||
pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
} else {
|
||||
pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
|
||||
pPlugin = pluginsys->PluginFromHandle(hndl, &err);
|
||||
|
||||
if (!pPlugin)
|
||||
{
|
||||
@@ -155,9 +155,9 @@ static cell_t sm_CreateGlobalForward(IPluginContext *pContext, const cell_t *par
|
||||
forwardParams[i - 3] = static_cast<ParamType>(*addr);
|
||||
}
|
||||
|
||||
IForward *pForward = g_Forwards.CreateForward(name, static_cast<ExecType>(params[2]), count - 2, forwardParams);
|
||||
IForward *pForward = forwardsys->CreateForward(name, static_cast<ExecType>(params[2]), count - 2, forwardParams);
|
||||
|
||||
return g_HandleSys.CreateHandle(g_GlobalFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
return handlesys->CreateHandle(g_GlobalFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
}
|
||||
|
||||
static cell_t sm_CreateForward(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -177,9 +177,9 @@ static cell_t sm_CreateForward(IPluginContext *pContext, const cell_t *params)
|
||||
forwardParams[i - 2] = static_cast<ParamType>(*addr);
|
||||
}
|
||||
|
||||
IChangeableForward *pForward = g_Forwards.CreateForwardEx(NULL, static_cast<ExecType>(params[1]), count - 1, forwardParams);
|
||||
IChangeableForward *pForward = forwardsys->CreateForwardEx(NULL, static_cast<ExecType>(params[1]), count - 1, forwardParams);
|
||||
|
||||
return g_HandleSys.CreateHandle(g_PrivateFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
return handlesys->CreateHandle(g_PrivateFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
}
|
||||
|
||||
static cell_t sm_GetForwardFunctionCount(IPluginContext *pContext, const cell_t *params)
|
||||
@@ -188,7 +188,7 @@ static cell_t sm_GetForwardFunctionCount(IPluginContext *pContext, const cell_t
|
||||
HandleError err;
|
||||
IForward *pForward;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
|
||||
@@ -205,7 +205,7 @@ static cell_t sm_AddToForward(IPluginContext *pContext, const cell_t *params)
|
||||
IChangeableForward *pForward;
|
||||
IPlugin *pPlugin;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
|
||||
if ((err=handlesys->ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
|
||||
@@ -213,9 +213,9 @@ static cell_t sm_AddToForward(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (plHandle == 0)
|
||||
{
|
||||
pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
||||
pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
} else {
|
||||
pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
|
||||
pPlugin = pluginsys->PluginFromHandle(plHandle, &err);
|
||||
|
||||
if (!pPlugin)
|
||||
{
|
||||
@@ -241,7 +241,7 @@ static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *param
|
||||
IChangeableForward *pForward;
|
||||
IPlugin *pPlugin;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
|
||||
if ((err=handlesys->ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
|
||||
@@ -249,9 +249,9 @@ static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *param
|
||||
|
||||
if (plHandle == 0)
|
||||
{
|
||||
pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
||||
pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
} else {
|
||||
pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
|
||||
pPlugin = pluginsys->PluginFromHandle(plHandle, &err);
|
||||
|
||||
if (!pPlugin)
|
||||
{
|
||||
@@ -277,7 +277,7 @@ static cell_t sm_RemoveAllFromForward(IPluginContext *pContext, const cell_t *pa
|
||||
IChangeableForward *pForward;
|
||||
IPlugin *pPlugin;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
|
||||
if ((err=handlesys->ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
|
||||
@@ -285,9 +285,9 @@ static cell_t sm_RemoveAllFromForward(IPluginContext *pContext, const cell_t *pa
|
||||
|
||||
if (plHandle == 0)
|
||||
{
|
||||
pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
||||
pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
} else {
|
||||
pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
|
||||
pPlugin = pluginsys->PluginFromHandle(plHandle, &err);
|
||||
|
||||
if (!pPlugin)
|
||||
{
|
||||
@@ -310,9 +310,9 @@ static cell_t sm_CallStartFunction(IPluginContext *pContext, const cell_t *param
|
||||
|
||||
if (hndl == 0)
|
||||
{
|
||||
pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
|
||||
pPlugin = pluginsys->FindPluginByContext(pContext->GetContext());
|
||||
} else {
|
||||
pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
|
||||
pPlugin = pluginsys->PluginFromHandle(hndl, &err);
|
||||
|
||||
if (!pPlugin)
|
||||
{
|
||||
@@ -344,7 +344,7 @@ static cell_t sm_CallStartForward(IPluginContext *pContext, const cell_t *params
|
||||
|
||||
hndl = static_cast<Handle_t>(params[1]);
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
|
||||
@@ -30,17 +30,12 @@
|
||||
*/
|
||||
|
||||
#include <sh_list.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_trie_tpl.h"
|
||||
#include <sm_trie_tpl.h>
|
||||
#include "common_logic.h"
|
||||
#include "CellArray.h"
|
||||
#include "convar.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "TextParsers.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "sourcemod.h"
|
||||
#include "Logger.h"
|
||||
#include "HandleSys.h"
|
||||
#include <ILibrarySys.h>
|
||||
#include <ITextParsers.h>
|
||||
#include <ISourceMod.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
@@ -77,7 +72,7 @@ public:
|
||||
}
|
||||
void OnSourceModAllInitialized()
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_SM, m_ConfigFile, sizeof(m_ConfigFile), "configs/maplists.cfg");
|
||||
g_pSM->BuildPath(Path_SM, m_ConfigFile, sizeof(m_ConfigFile), "configs/maplists.cfg");
|
||||
}
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
@@ -94,13 +89,9 @@ public:
|
||||
pMapList->bIsCompat = true;
|
||||
pMapList->bIsPath = true;
|
||||
pMapList->last_modified_time = 0;
|
||||
strncopy(pMapList->name, name, sizeof(pMapList->name));
|
||||
smcore.strncopy(pMapList->name, name, sizeof(pMapList->name));
|
||||
pMapList->pArray = NULL;
|
||||
g_SourceMod.BuildPath(Path_Game,
|
||||
pMapList->path,
|
||||
sizeof(pMapList->path),
|
||||
"%s",
|
||||
file);
|
||||
g_pSM->BuildPath(Path_Game, pMapList->path, sizeof(pMapList->path), "%s", file);
|
||||
pMapList->serial = 0;
|
||||
m_ListLookup.insert(name, pMapList);
|
||||
m_MapLists.push_back(pMapList);
|
||||
@@ -115,11 +106,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
g_SourceMod.BuildPath(Path_Game,
|
||||
path,
|
||||
sizeof(path),
|
||||
"%s",
|
||||
file);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
/* If the path matches, don't reset the serial/time */
|
||||
if (strcmp(path, pMapList->path) == 0)
|
||||
@@ -127,7 +114,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
strncopy(pMapList->path, path, sizeof(pMapList->path));
|
||||
smcore.strncopy(pMapList->path, path, sizeof(pMapList->path));
|
||||
pMapList->bIsPath = true;
|
||||
pMapList->last_modified_time = 0;
|
||||
pMapList->serial = 0;
|
||||
@@ -139,7 +126,7 @@ public:
|
||||
time_t fileTime;
|
||||
SMCStates states = {0, 0};
|
||||
|
||||
fileFound = g_LibSys.FileTime(m_ConfigFile, FileTime_LastChange, &fileTime);
|
||||
fileFound = libsys->FileTime(m_ConfigFile, FileTime_LastChange, &fileTime);
|
||||
|
||||
/* If the file is found and hasn't changed, bail out now. */
|
||||
if (fileFound && fileTime == m_ConfigLastChanged)
|
||||
@@ -156,7 +143,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
m_pMapCycleFile = icvar->FindVar("mapcyclefile");
|
||||
m_pMapCycleFile = smcore.FindConVar("mapcyclefile");
|
||||
|
||||
/* Dump everything we know about. */
|
||||
List<maplist_info_t *> compat;
|
||||
@@ -166,12 +153,12 @@ public:
|
||||
maplist_info_t *pDefList = new maplist_info_t;
|
||||
|
||||
pDefList->bIsPath = true;
|
||||
strncopy(pDefList->name, "mapcyclefile", sizeof(pDefList->name));
|
||||
g_SourceMod.BuildPath(Path_Game,
|
||||
smcore.strncopy(pDefList->name, "mapcyclefile", sizeof(pDefList->name));
|
||||
g_pSM->BuildPath(Path_Game,
|
||||
pDefList->path,
|
||||
sizeof(pDefList->path),
|
||||
"%s",
|
||||
m_pMapCycleFile ? m_pMapCycleFile->GetString() : "mapcycle.txt");
|
||||
m_pMapCycleFile ? smcore.GetCvarString(m_pMapCycleFile) : "mapcycle.txt");
|
||||
pDefList->last_modified_time = 0;
|
||||
pDefList->pArray = NULL;
|
||||
pDefList->serial = 0;
|
||||
@@ -182,19 +169,16 @@ public:
|
||||
/* Now parse the config file even if we don't know about it.
|
||||
* This will give us a nice error message.
|
||||
*/
|
||||
if ((error = g_TextParser.ParseFile_SMC(m_ConfigFile, this, &states))
|
||||
if ((error = textparser->ParseFile_SMC(m_ConfigFile, this, &states))
|
||||
!= SMCError_Okay)
|
||||
{
|
||||
const char *errmsg = g_TextParser.GetSMCErrorString(error);
|
||||
const char *errmsg = textparser->GetSMCErrorString(error);
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
errmsg = "Unknown error";
|
||||
}
|
||||
g_Logger.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
||||
g_Logger.LogError("[SM] Error on line %d (col %d): %s",
|
||||
states.line,
|
||||
states.col,
|
||||
errmsg);
|
||||
smcore.LogError("[SM] Could not parse file \"%s\"", m_ConfigFile);
|
||||
smcore.LogError("[SM] Error on line %d (col %d): %s", states.line, states.col, errmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -249,7 +233,7 @@ public:
|
||||
m_pCurMapList = new maplist_info_t;
|
||||
|
||||
memset(m_pCurMapList, 0, sizeof(maplist_info_t));
|
||||
strncopy(m_pCurMapList->name, name, sizeof(m_pCurMapList->name));
|
||||
smcore.strncopy(m_pCurMapList->name, name, sizeof(m_pCurMapList->name));
|
||||
|
||||
m_CurState = MPS_MAPLIST;
|
||||
}
|
||||
@@ -269,7 +253,7 @@ public:
|
||||
|
||||
if (strcmp(key, "file") == 0)
|
||||
{
|
||||
g_SourceMod.BuildPath(Path_Game,
|
||||
g_pSM->BuildPath(Path_Game,
|
||||
m_pCurMapList->path,
|
||||
sizeof(m_pCurMapList->path),
|
||||
"%s",
|
||||
@@ -278,7 +262,7 @@ public:
|
||||
}
|
||||
else if (strcmp(key, "target") == 0)
|
||||
{
|
||||
strncopy(m_pCurMapList->path, value, sizeof(m_pCurMapList->path));
|
||||
smcore.strncopy(m_pCurMapList->path, value, sizeof(m_pCurMapList->path));
|
||||
m_pCurMapList->bIsPath = false;
|
||||
}
|
||||
|
||||
@@ -369,9 +353,9 @@ public:
|
||||
|
||||
pNewArray = new CellArray(64);
|
||||
free_new_array = true;
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "maps");
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "maps");
|
||||
|
||||
if ((pDir = g_LibSys.OpenDirectory(path)) != NULL)
|
||||
if ((pDir = libsys->OpenDirectory(path)) != NULL)
|
||||
{
|
||||
char *ptr;
|
||||
cell_t *blk;
|
||||
@@ -386,7 +370,7 @@ public:
|
||||
pDir->NextEntry();
|
||||
continue;
|
||||
}
|
||||
strncopy(buffer, pDir->GetEntryName(), sizeof(buffer));
|
||||
smcore.strncopy(buffer, pDir->GetEntryName(), sizeof(buffer));
|
||||
if ((ptr = strstr(buffer, ".bsp")) == NULL || ptr[4] != '\0')
|
||||
{
|
||||
pDir->NextEntry();
|
||||
@@ -403,10 +387,10 @@ public:
|
||||
pDir->NextEntry();
|
||||
continue;
|
||||
}
|
||||
strncopy((char *)blk, buffer, 255);
|
||||
smcore.strncopy((char *)blk, buffer, 255);
|
||||
pDir->NextEntry();
|
||||
}
|
||||
g_LibSys.CloseDirectory(pDir);
|
||||
libsys->CloseDirectory(pDir);
|
||||
}
|
||||
|
||||
/* Remove the array if there were no items. */
|
||||
@@ -461,7 +445,7 @@ public:
|
||||
{
|
||||
blk_dst = pUseArray->push();
|
||||
blk_src = pNewArray->at(i);
|
||||
strncopy((char *)blk_dst, (char *)blk_src, pUseArray->blocksize() * sizeof(cell_t));
|
||||
smcore.strncopy((char *)blk_dst, (char *)blk_src, pUseArray->blocksize() * sizeof(cell_t));
|
||||
}
|
||||
|
||||
/* Free resources if necessary. */
|
||||
@@ -501,20 +485,20 @@ private:
|
||||
if (m_pMapCycleFile != NULL && strcmp(name, "mapcyclefile") == 0)
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_Game,
|
||||
g_pSM->BuildPath(Path_Game,
|
||||
path,
|
||||
sizeof(path),
|
||||
"%s",
|
||||
m_pMapCycleFile ? m_pMapCycleFile->GetString() : "mapcycle.txt");
|
||||
m_pMapCycleFile ? smcore.GetCvarString(m_pMapCycleFile) : "mapcycle.txt");
|
||||
|
||||
if (strcmp(path, pMapList->path) != 0)
|
||||
{
|
||||
strncopy(pMapList->path, path, sizeof(pMapList->path));
|
||||
smcore.strncopy(pMapList->path, path, sizeof(pMapList->path));
|
||||
pMapList->last_modified_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_LibSys.FileTime(pMapList->path, FileTime_LastChange, &last_time)
|
||||
if (!libsys->FileTime(pMapList->path, FileTime_LastChange, &last_time)
|
||||
|| last_time > pMapList->last_modified_time)
|
||||
{
|
||||
/* Reparse */
|
||||
@@ -533,7 +517,7 @@ private:
|
||||
while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL)
|
||||
{
|
||||
size_t len = strlen(buffer);
|
||||
char *ptr = UTIL_TrimWhitespace(buffer, len);
|
||||
char *ptr = smcore.TrimWhitespace(buffer, len);
|
||||
if (*ptr == '\0'
|
||||
|| *ptr == ';'
|
||||
|| strncmp(ptr, "//", 2) == 0)
|
||||
@@ -546,7 +530,7 @@ private:
|
||||
}
|
||||
if ((blk = pMapList->pArray->push()) != NULL)
|
||||
{
|
||||
strncopy((char *)blk, ptr, 255);
|
||||
smcore.strncopy((char *)blk, ptr, 255);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +600,7 @@ static cell_t LoadMapList(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(hndl, htCellArray, &sec, (void **)&pArray))
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellArray, &sec, (void **)&pArray))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
@@ -635,7 +619,7 @@ static cell_t LoadMapList(IPluginContext *pContext, const cell_t *params)
|
||||
/* If the user wanted a new array, create it now. */
|
||||
if (hndl == BAD_HANDLE)
|
||||
{
|
||||
if ((hndl = g_HandleSys.CreateHandle(htCellArray, pNewArray, pContext->GetIdentity(), g_pCoreIdent, NULL))
|
||||
if ((hndl = handlesys->CreateHandle(htCellArray, pNewArray, pContext->GetIdentity(), g_pCoreIdent, NULL))
|
||||
== BAD_HANDLE)
|
||||
{
|
||||
*addr = -1;
|
||||
@@ -29,11 +29,10 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include <IHandleSys.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "HandleSys.h"
|
||||
#include <time.h>
|
||||
#include "common_logic.h"
|
||||
#include "CellArray.h"
|
||||
|
||||
/***********************************
|
||||
@@ -448,7 +447,7 @@ static cell_t sm_SortADTArray(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&cArray))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&cArray))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -535,7 +534,7 @@ static cell_t sm_SortADTArrayCustom(IPluginContext *pContext, const cell_t *para
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = g_HandleSys.ReadHandle(params[1], htCellArray, &sec, (void **)&cArray))
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellArray, &sec, (void **)&cArray))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
@@ -29,9 +29,9 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "common_logic.h"
|
||||
#include <ITextParsers.h>
|
||||
#include "HandleSys.h"
|
||||
#include <ISourceMod.h>
|
||||
|
||||
HandleType_t g_TypeSMC = 0;
|
||||
|
||||
@@ -152,16 +152,16 @@ public:
|
||||
/* These cannot be cloned, because they are locked to a specific plugin.
|
||||
* However, we let anyone read them because we don't care.
|
||||
*/
|
||||
g_HandleSys.InitAccessDefaults(NULL, &sec);
|
||||
handlesys->InitAccessDefaults(NULL, &sec);
|
||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY;
|
||||
sec.access[HandleAccess_Read] = 0;
|
||||
|
||||
g_TypeSMC = g_HandleSys.CreateType("SMCParser", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
g_TypeSMC = handlesys->CreateType("SMCParser", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
}
|
||||
|
||||
void OnSourceModShutdown()
|
||||
{
|
||||
g_HandleSys.RemoveType(g_TypeSMC, g_pCoreIdent);
|
||||
handlesys->RemoveType(g_TypeSMC, g_pCoreIdent);
|
||||
}
|
||||
|
||||
void OnHandleDestroy(HandleType_t type, void *object)
|
||||
@@ -183,7 +183,7 @@ static cell_t SMC_CreateParser(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
ParseInfo *pInfo = new ParseInfo();
|
||||
|
||||
Handle_t hndl = g_HandleSys.CreateHandle(g_TypeSMC, pInfo, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
Handle_t hndl = handlesys->CreateHandle(g_TypeSMC, pInfo, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
|
||||
/* Should never happen */
|
||||
if (!hndl)
|
||||
@@ -203,7 +203,7 @@ static cell_t SMC_SetParseStart(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
@@ -220,7 +220,7 @@ static cell_t SMC_SetParseEnd(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
@@ -237,7 +237,7 @@ static cell_t SMC_SetReaders(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
@@ -256,7 +256,7 @@ static cell_t SMC_SetRawLine(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
@@ -273,7 +273,7 @@ static cell_t SMC_ParseFile(IPluginContext *pContext, const cell_t *params)
|
||||
HandleError err;
|
||||
ParseInfo *parse;
|
||||
|
||||
if ((err=g_HandleSys.ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
if ((err=handlesys->ReadHandle(hndl, g_TypeSMC, NULL, (void **)&parse))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid SMC Parse Handle %x (error %d)", hndl, err);
|
||||
@@ -283,7 +283,7 @@ static cell_t SMC_ParseFile(IPluginContext *pContext, const cell_t *params)
|
||||
pContext->LocalToString(params[2], &file);
|
||||
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
||||
|
||||
SMCStates states;
|
||||
SMCError p_err = textparsers->ParseFile_SMC(path, parse, &states);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user